Jump to content

Idea: Unified Peripheral Profiler, need devs :)


RvEYoda

Recommended Posts

Been away from the forum for a while but I read up on things every now and then. Some of you might know me, but most probably don't.

 

Long story short: I got an idea for a new hotas/keyboard/*anything* programming/profiler tool/utility. (wow thats a lot of slashes!).

 

We all sit with tons of different sim gear like throttle, stick, pedals (wheels anyone? ;)) and the list goes on. Some of these things come with decent programming/profiling tools, but seriously, none are really that powerful, and worst is that in almost every setup there are different tools for each hardware, they get non-backwards-compatible upgrades (for the profiles). On top of that the hardware don't play too well together. For example

 

1. Can my new game really support N number of devices?

2. Can my new game let different hardware act as modifiers for each other etc?.

 

Now why can't normal profiler software support basic gestures like "double-clicking" or acting on different time-dependant conditions?

 

MAYBE some do, maybe some obscure ones for parts of your hardware.

 

----------------

 

Ok so if you actually have read all the above without getting tired or bored, what is the point of this post?

 

Let's say we make a new software (or more correctly named some kind of utility programming library), compatible with ALL directx devices (keyboard, mice, joysticks, wheels etc).

 

How to do this? It is likely simpler than one would expect. My idea (that I need advice on and hopefully more devs) is this:

 

1. ask DirectX (DirectInput) what *real* devices are present

2. create a single *virtual* device for sending back commands

3. ask directinput to notify our program on any changes in the *real* devices we want to check.

4. act on arbitrary changes as if they were just normal program events.

5. send desired commands on *virtual* device

 

Creating a hotas cougar profile in c++...lovely :). (Or maybe C#, I normally prefer Java but for low level global controller access then... maybe later we can wrap it in JNI)

 

Example of multiple devices acting together:

 

if (x52.throttle.slider(1).accelleration()< a && hCougar.stick.button(5).isDown()) // 
  airbrakesOut();

or as a callback if preferred

void onChange(Event& e) {
  globalState.update(e);
  Interface * interface = e->getDevice()->getInterface();
  MappingList * activeMappings = mappings.getMappings(interface);   
  if (activeMappings->length()>0)
    respond(globalState, MappingList);
}

 

 

I estimate such a program would be really short, maybe a few hundred lines (tops) for the actual framework. Then if anyone nice wants to add a GUI (boring... ) and profile file reader/writer that would be cool as well.

 

 

 

----------

 

END RANT

 

Suggestions?

Want to help?

Post!


Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Link to comment
Share on other sites

This is an interesting concept! I'm not quite sure what you are proposing here. Would this be replacing cougar control panel/foxy for the couger, TARGET for the warthog, SST software for saitek, logitech software for keyboard, mouse, etc. and combine it all in one program with tabs for the different kinds of directx input devices? Seems like more than a few hundred lines of work to replace all that software functionality.

 

In any case, you know I don't have a high level of programming knowledge, but I'd be happy to help out however I can with testing and problem solving.

Link to comment
Share on other sites

This is an interesting concept! I'm not quite sure what you are proposing here. Would this be replacing cougar control panel/foxy for the couger, TARGET for the warthog, SST software for saitek, logitech software for keyboard, mouse, etc. and combine it all in one program with tabs for the different kinds of directx input devices?

 

You would not need any other profiling software, not even necessarily programming different devices in different tabs - all the devices can be programmed in the same code (and you can for example use a button on an x52 as a modifier for a functionality on your CH pedals etc). It would be a direct programming approach instead of wrapping it in a semi-programmable profiler application. You would get access to each of the devices' *states* and could write simple conditional statements as if you were doing very basic programming.

 

 

Seems like more than a few hundred lines of work to replace all that software functionality.

In any case, you know I don't have a high level of programming knowledge, but I'd be happy to help out however I can with testing and problem solving.

 

The thing is that you don't need to replace or rewrite any of the functionality. You only need to Give access to

1. Read current state

2. Input virtual keystrokes ( that your game reads)

 

These two things are what I mean will be only a few hundred lines (in fact it might even be below 100 lines of code, much shorter than my previous projects).

What would require more work would be simplifications of profiles and GUIs, that could be a lot more code.

  • Like 1

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Link to comment
Share on other sites

Hi Yoda, quite an interesting proposition that you have here :). Unfortunately though, at the moment I don't know as to whether I would be able to give you a hand with this. As I'm still planning to add more features to EFFSSI among other reasons. Will let you know though when I'm able to give you some help with this :).

Link to comment
Share on other sites

  • 2 weeks later...

Looking at it more closer now, I have solved part 1 but am still working on part 2, which is turning out to be quite difficult...

 

1. So detecting multiple controller input and creating conditions on when to react on each turns out to be fairly simple

 

2. But actually inputing something back is more difficult than I expected. :/. What I would like to do is to create three virtual inputs: virtual mouse input, virtual keyboard input and virtual joystick input. The first two are not too hard as windows has decent methods for doing this, however creating a virtual joystick seems to be harder than I expect. It seems like u actually have to make windows believe that you have connected a new hardware HID/usb device and then have that device give input.

 

If anyone has some programming suggestions on how to create a virtual joystick for emulated input, then that would solve the last problem. So far I have not found anything for it but I'm still looking.

 

update: This guy here has done part 2 http://ppjoy.blogspot.com/, but the code is not open source and from what I can tell there is no plan to make it so. Also what is worse is that creating a virtual joystick device means you must create a device driver, which for windows 7 in turn has to be (unless you specifically boot windows 7 into test mode) digitally signed......and for that you must pay microsoft a yearly fee :P.

 

 

So it looks like my first go with this software will only allow:

1. Read and conditionalize events from all directinput devices (by using directinput http://msdn.microsoft.com/en-us/library/ee418273(v=vs.85).aspx)

2. Input virtual mouse and keyboard events (by using windows functions SendInput http://msdn.microsoft.com/en-us/library/ms646310(v=vs.85).aspx)

(2b. Later, I wish to also be able to create virtual joystick input, see text above to see why it's not possible to make atm.)

 

 

Google found a neat demonstration on how to use the SendInput function in a forum post :)

(http://stackoverflow.com/questions/3726812/how-to-send-unicode-keys-with-c-keybd-event)

 
KEYBDINPUT kb={0};
INPUT Input={0};

// down
kb.wScan = 0x00c5;
kb.dwFlags = KEYEVENTF_UNICODE;
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
::SendInput(1,&Input,sizeof(Input));

// up
kb.wScan = 0x00c5;
kb.dwFlags = KEYEVENTF_UNICODE|KEYEVENTF_KEYUP;
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
::SendInput(1,&Input,sizeof(Input));


Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Link to comment
Share on other sites

 

update: This guy here has done part 2 http://ppjoy.blogspot.com/, but the code is not open source and from what I can tell there is no plan to make it so. Also what is worse is that creating a virtual joystick device means you must create a device driver, which for windows 7 in turn has to be (unless you specifically boot windows 7 into test mode) digitally signed......and for that you must pay microsoft a yearly fee :P.

 

This was the first thing i was thinking about when i started to read your thread, that you need a driver. And that cannot be achieved without signing it in Win7, especially x64. So there is testmode.

This is the point where you cannot address all users.

I twiddled around with PPJoy several times, and yes it is working in test mode, but i dont have a good feeling using it that way. And it isn't a plug-and-play stuff anyway.

Link to comment
Share on other sites

This was the first thing i was thinking about when i started to read your thread, that you need a driver. And that cannot be achieved without signing it in Win7, especially x64. So there is testmode.

This is the point where you cannot address all users.

I twiddled around with PPJoy several times, and yes it is working in test mode, but i dont have a good feeling using it that way. And it isn't a plug-and-play stuff anyway.

 

Yeah, same, I think it is too much work for most people.

However if the program I/we make initially supports only virtual mouse and keyboard emulation, we can then later expand it to also a virtual joystick for those running test mode.

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Link to comment
Share on other sites

Began coding the stuff, but I've run into a strange problem.

 

I've tried as best as I can to follow the directinput guides out there, here is what I have so far:

 

#include "stdafx.h"
#include "conio.h"
#include "iostream"
#include "dinput.h"
#include "vector"

using std::vector;
using std::cout;
using std::wcout;
using std::endl;

typedef LPDIRECTINPUT8 DinputInterface;
typedef LPCDIDEVICEINSTANCE InputDeviceID;
typedef LPDIRECTINPUTDEVICE8 InputDevice;

BOOL CALLBACK addDevice(InputDeviceID device, LPVOID pvRef);
vector<InputDeviceID> deviceIDs = vector<InputDeviceID>();
vector<InputDevice> devices = vector<InputDevice>();
HWND thisWindow;

int _tmain(int argc, _TCHAR* argv[])
{

// Check our app's window
thisWindow = GetActiveWindow();

// The DirectInput interface
DinputInterface dinputInterface; 
const HRESULT res1 = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&dinputInterface, NULL);
if (FAILED(res1)) {
	cout << endl << "Creation of dx interface failed";
	_getch();
	return 0;
}

// Get the DirectInput deviceIDs
const HRESULT res2 = dinputInterface->EnumDevices(DI8DEVCLASS_GAMECTRL, addDevice, NULL, DIEDFL_ATTACHEDONLY);	
if (!FAILED(res2)) {

	// Create a device for each deviceID
	for each(InputDeviceID id in deviceIDs) {
		InputDevice dev = NULL;
		const HRESULT resDev = dinputInterface->CreateDevice(id->guidInstance, &dev, NULL);
		 
		if (!FAILED(resDev)) {
			/*dev->SetDataFormat(&c_dfDIJoystick);
			dev->SetCooperativeLevel(thisWindow, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
			dev->Acquire();
			dev->Poll();
			DIJOYSTATE curState;
			dev->GetDeviceState(sizeof(DIJOYSTATE), &curState);
			cout << endl << curState.lZ;
			devices.push_back(dev);*/
		} else if(DIERR_DEVICENOTREG == resDev) {
			cout << endl << "Failed to create device";
		}
	}	

	// Release all memory and references
	for each (InputDevice dev in devices) {
		dev->Release();
	}
	devices.clear();

} else {
	cout << endl << "Creating Device IDs failed";
}

deviceIDs.clear();
dinputInterface->Release();

// Wait for test window to close
_getch();
return 0;

}


BOOL CALLBACK addDevice(InputDeviceID id, LPVOID pvRef) {

deviceIDs.push_back(id);	

GUID instanceGuid = id->guidInstance;
GUID productGuid = id->guidProduct;

wcout << endl << "_GUID DATA_";
wcout << endl << "iguid.d1: " << instanceGuid.Data1 << endl << "iguid.d2: " << instanceGuid.Data2 << endl << "iguid.d3: " << instanceGuid.Data3 << endl << "iguid.d4: " << instanceGuid.Data4;
wcout << endl << "pguid.d1: " << productGuid.Data1  << endl << "pguid.d2: " << productGuid.Data2 << endl << "pguid.d3: " << productGuid.Data3 << endl << "pguid.d4: " << productGuid.Data4;

wcout << endl << "_DEVICE DATA_";
wcout << endl << "devtype: " << id->dwDevType << endl << "prodname: " << id->tszProductName << endl << "instancename: " << id->tszInstanceName;

wcout << endl;
return DIENUM_CONTINUE;
}

 

It fails on "dinputInterface->CreateDevice(...." and I have no idea why. It says DIERR_DEVICENOTREG, or "Device not Registered", but I have absolutely no idea what that means, if a device is registered or not :P. The devices are all connected and working fine.

 

The program outputs:

 



_GUID DATA_
iguid.d1: 2519117328
iguid.d2: 63399
iguid.d3: 4574
iguid.d4: 001FF864
pguid.d1: 67109967
pguid.d2: 0
pguid.d3: 0
pguid.d4: 001FF84C
_DEVICE DATA_
devtype: 66068
prodname: Thrustmaster HOTAS Cougar
instancename: Thrustmaster HOTAS Cougar

_GUID DATA_
iguid.d1: 3723248736
iguid.d2: 25704
iguid.d3: 4576
iguid.d4: 001FF864
pguid.d1: 3008431183
pguid.d2: 0
pguid.d3: 0
pguid.d4: 001FF84C
_DEVICE DATA_
devtype: 66076
prodname: F16 MFD 1
instancename: F16 MFD 1

_GUID DATA_
iguid.d1: 3723248736
iguid.d2: 25704
iguid.d3: 4576
iguid.d4: 001FF864
pguid.d1: 3008496719
pguid.d2: 0
pguid.d3: 0
pguid.d4: 001FF84C
_DEVICE DATA_
devtype: 66076
prodname: F16 MFD 2
instancename: F16 MFD 2

_GUID DATA_
iguid.d1: 3833754032
iguid.d2: 48150
iguid.d3: 4574
iguid.d4: 001FF864
pguid.d1: 123471523
pguid.d2: 0
pguid.d3: 0
pguid.d4: 001FF84C
_DEVICE DATA_
devtype: 66328
prodname: Saitek X52 Flight Control System
instancename: Saitek X52 Flight Control System

Failed to create device
Failed to create device
Failed to create device
Failed to create device

 

Update: AHA. Apparently MS has decided that you can only run CreateDevice inside the callback given at the enumerate-call (else u get the error above). Either that or I miss something else.

What my guess is that the call to enumerate is blocking, and then some "CreateDevice"-allowed DX thread actually runs the callback instead of the main thread, and only it has the permissions

to create a device......regardless....problem solved.


Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Link to comment
Share on other sites

Success :)

 

I can now read any axis and any button of any device

Sample output:


_GUID DATA_
iguid.d1: 2519117328
iguid.d2: 63399
iguid.d3: 4574
iguid.d4: 0033F6F4
pguid.d1: 67109967
pguid.d2: 0
pguid.d3: 0
pguid.d4: 0033F704
_DEVICE DATA_
devtype: 66068
prodname: Thrustmaster HOTAS Cougar
instancename: Thrustmaster HOTAS Cougar

_GUID DATA_
iguid.d1: 3723248736
iguid.d2: 25704
iguid.d3: 4576
iguid.d4: 0033F6F4
pguid.d1: 3008431183
pguid.d2: 0
pguid.d3: 0
pguid.d4: 0033F704
_DEVICE DATA_
devtype: 66076
prodname: F16 MFD 1
instancename: F16 MFD 1

_GUID DATA_
iguid.d1: 3723248736
iguid.d2: 25704
iguid.d3: 4576
iguid.d4: 0033F6F4
pguid.d1: 3008496719
pguid.d2: 0
pguid.d3: 0
pguid.d4: 0033F704
_DEVICE DATA_
devtype: 66076
prodname: F16 MFD 2
instancename: F16 MFD 2

_GUID DATA_
iguid.d1: 3833754032
iguid.d2: 48150
iguid.d3: 4574
iguid.d4: 0033F6F4
pguid.d1: 123471523
pguid.d2: 0
pguid.d3: 0
pguid.d4: 0033F704
_DEVICE DATA_
devtype: 66328
prodname: Saitek X52 Flight Control System
instancename: Saitek X52 Flight Control System

Pressing button nr: 22
Pressing button nr: 22
Pressing button nr: 22
Pressing button nr: 20
Pressing button nr: 20
Pressing button nr: 20
Pressing button nr: 19
Pressing button nr: 29
Pressing button nr: 29
Pressing button nr: 29
Pressing button nr: 29
Pressing button nr: 29
Pressing button nr: 29
Pressing button nr: 6
Pressing button nr: 6
Pressing button nr: 6
Pressing button nr: 6

 

 

Test code below.

Going to start working on buffered reading later or tomorrow:

 


#include "stdafx.h"
#include "conio.h"
#include "iostream"
#include "dinput.h"
#include "vector"

using std::vector;
using std::cout;
using std::wcout;
using std::endl;

typedef LPDIRECTINPUT8 DinputInterface;
typedef LPCDIDEVICEINSTANCE InputDeviceID;
typedef LPDIRECTINPUTDEVICE8 InputDevice;

const size_t bufferSize_numItems = 20;
HWND thisWindow;
DinputInterface dinputInterface; 
BOOL CALLBACK addDevice(InputDeviceID device, LPVOID pvRef);
vector<InputDevice> devices = vector<InputDevice>();

int _tmain(int argc, _TCHAR* argv[])
{

// Check our app's window
thisWindow = GetActiveWindow();

// The DirectInput interface
const HRESULT res1 = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&dinputInterface, NULL);
if (FAILED(res1)) {
	cout << endl << "Creation of dx interface failed";
	_getch();
	return 0;
}

// Get the DirectInput deviceIDs
const HRESULT res2 = dinputInterface->EnumDevices(DI8DEVCLASS_GAMECTRL, addDevice, NULL, DIEDFL_ATTACHEDONLY);	
if (SUCCEEDED(res2)) {

	// Create a device for each deviceID
	for (size_t i = 0; i < devices.size(); i++) {
		InputDevice dev = devices[i];
		while (i==3) {
			dev->Poll();
			DIJOYSTATE curState;
			dev->GetDeviceState(sizeof(DIJOYSTATE), &curState);
		/*	cout << endl << curState.lX;
			cout << endl << curState.lY;
			cout << endl << curState.lZ;
			cout << endl << curState.lRx;
			cout << endl << curState.lRz;*/
		//	cout << endl << curState.lRy;
			if (curState.rgbButtons[21]) {
				break;
			}
			for (size_t i = 0; i < 32; i++) {
				if (curState.rgbButtons[i]) {
					cout << endl << "Pressing button nr: " << i;
				}
			}
			Sleep(1);
		}
	}	

	// Release all memory and references
	for (size_t i = 0; i < devices.size(); i++) {
		devices[i]->Release();
	}
	devices.clear();
} else {
	cout << endl << "Creating Device IDs failed";
}
dinputInterface->Release();

_getch();
return 0;

}


BOOL CALLBACK addDevice(InputDeviceID id, LPVOID pvRef) {

InputDevice dev = NULL;
const HRESULT resDev = dinputInterface->CreateDevice(id->guidInstance, &dev, NULL);
devices.push_back(dev);

if(SUCCEEDED(resDev)) {
	wcout << endl << "_GUID DATA_";
	wcout << endl << "iguid.d1: " << id->guidInstance.Data1 << endl << "iguid.d2: " << id->guidInstance.Data2 << endl << "iguid.d3: " << id->guidInstance.Data3 << endl << "iguid.d4: " << id->guidInstance.Data4;
	wcout << endl << "pguid.d1: " << id->guidProduct.Data1  << endl << "pguid.d2: " << id->guidProduct.Data2 << endl << "pguid.d3: " << id->guidProduct.Data3 << endl << "pguid.d4: " << id->guidProduct.Data4;	
	wcout << endl << "_DEVICE DATA_";
	wcout << endl << "devtype: " << id->dwDevType << endl << "prodname: " << id->tszProductName << endl << "instancename: " << id->tszInstanceName;	
	wcout << endl;

	DIPROPDWORD dipdw;
	dipdw.diph.dwSize = sizeof(DIPROPDWORD); 
	dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
	dipdw.diph.dwObj = 0; 
	dipdw.diph.dwHow = DIPH_DEVICE; 
	dipdw.dwData = bufferSize_numItems;
	
	dev->SetCooperativeLevel(thisWindow, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
	dev->SetDataFormat(&c_dfDIJoystick);
	dev->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph);		
	
	dev->Acquire();

} else {
	cout << endl << "Failed to create device";
} 

return DIENUM_CONTINUE;
}


Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Link to comment
Share on other sites

Hi Yoda. Another amazing project from you, as always.

 

There is a Java library that amalgamates Joysticks, keyboards etc. On Windows it uses DirectInput

 

http://java.net/projects/jinput/ (think this might be the old site)

 

Forums about jinput:

http://www.java-gaming.org/index.php?board=27.0

 

This library used to be rubbish (would throw NullPointerException on start) but a few months ago I tried it again and it worked with my Cougar. I don't think it would work fully with a Warthog as the Warthog has more buttons than DirectInput could enumerate (although this may have changed) - which I think is why LockOn couldn't see some of the buttons last time I tried setting them in-game (perhaps I'm wrong here, it was a while since I tried).

Link to comment
Share on other sites

Yeah the issue seems to be that most devices don't necessarily report all their buttons ans DirectInput buttons (as you say cause DirectInput only supports 32 buttons and 8 axii per device!)

For example my X52 throttle (which I use together with an fssb r2 cougar stick) reports some buttons as a mouse by default etc. But I should be able to get around that :)

 

I think I would prefer coding the "reading part" on my own, but if jinput has good facilities for inputing stuff back that would be nice, but I am already able to emulate keyboard buttons freely, so the question is only if jinput can create a virtual joystick device and emulate input from it.. One of the problems with Jinput when I used it last time is that it does not detect global input for all devices (only joysticks), so for example the input coming from the saitek mouse (that is part on the x52 throttle) would not be registered when the UPP is minimized if I used Jinput.

 

Update: New OO test code running which basically allows me to map any arbitrary C++ function to a key event.

 



#include "stdafx.h"
#include "DID_headers.h"

using namespace Yoda_DID;

const size_t bufferSize_numItems = 20;
DinputInterface dinputInterface; 

vector<DID_Joystick> joysticks = vector<DID_Joystick>();
vector<DID_Mouse> mice = vector<DID_Mouse>();
vector<DID_Other> others = vector<DID_Other>();
	
BOOL CALLBACK enumJoystickCallback(InputDeviceID, LPVOID);
BOOL CALLBACK enumMouseCallback(InputDeviceID, LPVOID);
BOOL CALLBACK enumOtherCallback(InputDeviceID, LPVOID);
void releaseAllDevices();

void testBtn1P() {
cout << endl << "PR btn 1";
}

void testBtn1H() {
cout << endl << "HL btn 1";
}

void testBtn1R() {
cout << endl << "RL btn 1";
}

int _tmain(int argc, _TCHAR* argv[])
{

// The DirectInput interface
DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&dinputInterface, NULL);

// Create the DirectInput devices
dinputInterface->EnumDevices(DI8DEVCLASS_GAMECTRL, enumJoystickCallback, NULL, DIEDFL_ATTACHEDONLY);	

// Test some input
joysticks[1].button(0).assignCallback_onKeyDown(&testBtn1P); // test callback to be displayed when button is first pressed down
joysticks[1].button(0).assignCallback_onKeyHeld(&testBtn1H); // test callback to be displayed while button is held down (maybe someone needs this? )
joysticks[1].button(0).assignCallback_onKeyReleased(&testBtn1R); // test callback to be displayed when button is released

bool toRun = true;
while (toRun) {
	for (size_t i = 0; i < joysticks.size(); i++) {
		DID_Joystick& dev = joysticks[i];
		dev.updateState();
		if (dev.button(20).isPressed() && dev.button(23).isPressed()) {
			toRun = false;
		}
	}
	Sleep(1);
}

releaseAllDevices();
dinputInterface->Release();
_getch();
return 0;

}

void releaseAllDevices() {
for (size_t i = 0; i < joysticks.size(); i++) {
	joysticks[i].release();
}
for (size_t i = 0; i < mice.size(); i++) {
	mice[i].release();
}
for (size_t i = 0; i < others.size(); i++) {
	others[i].release();
}
}

BOOL CALLBACK enumJoystickCallback(InputDeviceID id, LPVOID pvRef) {
joysticks.push_back(DID_Joystick(dinputInterface, id, bufferSize_numItems));
return DIENUM_CONTINUE;
}
BOOL CALLBACK enumMouseCallback(InputDeviceID id, LPVOID pvRef) {
mice.push_back(DID_Mouse(dinputInterface, id, bufferSize_numItems));
return DIENUM_CONTINUE;
}
BOOL CALLBACK enumOtherCallback(InputDeviceID id, LPVOID pvRef) {
others.push_back(DID_Other(dinputInterface, id, bufferSize_numItems));
return DIENUM_CONTINUE;
}

 

and the output is


_GUID DATA_
iguid.d1: 2519117328
iguid.d2: 63399
iguid.d3: 4574
iguid.d4: 0017F390
pguid.d1: 67109967
pguid.d2: 0
pguid.d3: 0
pguid.d4: 0017F3A0
_DEVICE DATA_
devtype: 66068
prodname: Thrustmaster HOTAS Cougar
instancename: Thrustmaster HOTAS Cougar

_GUID DATA_
iguid.d1: 3723248736
iguid.d2: 25704
iguid.d3: 4576
iguid.d4: 0017F390
pguid.d1: 3008431183
pguid.d2: 0
pguid.d3: 0
pguid.d4: 0017F3A0
_DEVICE DATA_
devtype: 66076
prodname: F16 MFD 1
instancename: F16 MFD 1

_GUID DATA_
iguid.d1: 3723248736
iguid.d2: 25704
iguid.d3: 4576
iguid.d4: 0017F390
pguid.d1: 3008496719
pguid.d2: 0
pguid.d3: 0
pguid.d4: 0017F3A0
_DEVICE DATA_
devtype: 66076
prodname: F16 MFD 2
instancename: F16 MFD 2

_GUID DATA_
iguid.d1: 3833754032
iguid.d2: 48150
iguid.d3: 4574
iguid.d4: 0017F390
pguid.d1: 123471523
pguid.d2: 0
pguid.d3: 0
pguid.d4: 0017F3A0
_DEVICE DATA_
devtype: 66328
prodname: Saitek X52 Flight Control System
instancename: Saitek X52 Flight Control System

PR btn 1
HL btn 1
HL btn 1
HL btn 1
HL btn 1
HL btn 1
HL btn 1
HL btn 1
RL btn 1


Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Link to comment
Share on other sites

I've run into a problem..

 

Hotas cougar: can map everything fine

Thrustmaster mfds: all fine

 

Saitek X52 (i use the throttle): All axii except mouse ok, all buttons except mouse ok, all povs ok. It seems as Saitek has written som nasty driver here. As soon as any application creates a DirectInput device of the X52, then the saitek "magic mouse" is activated, and the buttons that control it are no longer readable as DirectInput buttons.

 

So as soon as you start your own software or the saitek panel, BLING! Mouse activated.

The worse problem is that the saitek magic mouse doesnt register as a directx device!

Even if I uninstall the saitek profiling software, and there is no more magic mouse.....the buttons still dont show as dx input :(

 

This means, effectively, that I cannot read it. Well I can read it through the global mouse input but that is pointless. :(

 

 

-------

 

 

Update: There might be an evil way of getting raw data from the device and going from there...Investigating http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.reference.diobjectdataformat(v=VS.85).aspx :D

 

Update 2: Through looking at the device's raw data sent I've been able to ask DirectInput to send me data from mouse controller on the x52 without having to use it as mouse :P.

Now I just need to read those extra buttons... Getting close!

 

Basically just need to define a custom data format for devices (like x52 but not cougar or TM mfds) that behave evil.

 

Update 3: Now able to read all x52 states EXCEPT the mouse buttons (even though the mouse and profiling software is uninstalled). The cursor stick itself I can read, but not the buttons... hmm

They do not send any dx information EXCEPT if the x52 control panel is opened, then they suddenly become DirectInput compatible buttons.....hm....evil drivers...


Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Link to comment
Share on other sites

Good luck! I have messed around with Inputs on windows years ago. I hope it has gotten better, but it used to be very easy to get 90% working and very hard to get 100% working. In the end I just used GlovePIE and PPJoy, though I understand that PPJoy will not work on the newer Windows. However, GlovePIE does a lot of what you are trying to do already (reampping inputs as other inputs) and allows use of some pretty unique input devices - TrackIR, VR Gloves, Wiimotes.

 

http://glovepie.org/glovepie.php

 

...


Edited by pakfront
Link to comment
Share on other sites

Solved the last piece of the puzzle. I can now read x52, cougar, mfds 100% :).

Going back to work on the implementation now. It is not meant to be a scripting software,

more like a static c++ and/or java library so that you can write conditions in low level programming language

 

Basically what I've had to do is to dynamically generate the device data formats during program runtime, given what directinput reports on the device capabilities, (cause some, for example the x52 hotas have buttons that exceed the standard DirectInput data formats). I'm in the process of testing the new formats, basically dynamically generated structs at runtime (and with dyn generated I mean different amount of members and types), so working for filling in bytes here and there :P

 

Update: So basically everything works now. Input, profiles, output. games detect my mappings just fine.

 

There is just one total gamebreaker.......

I'm unable to block the DX input to games. I can receive it myself, i can generate the keystrokes I want, but the games also receive the original DX input.

This is a problem since some games does not allow me to unmap for example POV hats (damn u f4AF), while in lockon/dcs this isnt a problem.

 

So unless someone knows a way how to block selective directinput information going to other applications, then I'm putting this project on hold for the moment.

(Like it said everything is working, it's just that I cannot get the apps to get "double information")

 

This is what my game profile looked like :P. At least I can use it to map my thrustmaster MFDs I guess XD





////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
/////  Thrustmaster MFDs
//////////////////////////////////////////////////

// Special buttons which do not have modifiers
int L_mfd_btn[3*20] = {
0,		0,			0,
1,		VK_ADD,		0,
2,		0,			0,
3,		0,			0,
4,		0,			0,
5,		VK_HOME,	1,
6,		0,			0,
7,		0,			0,
8,		0,			0,
9,		0,			0,
10,		0,			0,
11,		VK_F6,		0,
12,		VK_F7,		0,
13,		0,			0,
14,		0,			0,
15,		VK_F8,		0,
16,		VK_MULTIPLY,0,
17,		VK_DIVIDE,	1,
18,		0,			0,
19,		VK_PRIOR,	1
};
int R_mfd_btn[3*20] = {
0,		0,			0,
1,		VK_END,		1,
2,		0,			0,
3,		0,			0,
4,		0,			0,
5,		0,			0,
6,		0,			0,
7,		0,			0,
8,		0,			0,
9,		0,			0,
10,		0,			0,
11,		0,			0,
12,		0,			0,
13,		0,			0,
14,		0,			0,
15,		0,			0,
16,		0,			0,
17,		0,			0,
18,		0,			0,
19,		0,			0
};

void tapAfMfd(int mod1, int mod2, int bNum) {
if (bNum<10) {
	tripleTap(mod1, mod2, number(oneToTenKeys(bNum)));
} else if (bNum>=10 && bNum<20) {
	tripleTap(mod1, mod2, numpad(oneToTenKeys(bNum-10)));
}
}

void stdTapLeftMfd(int bNum) {
tapAfMfd(VK_LCONTROL, VK_LMENU, bNum);
}

void stdTapRightMfd(int bNum) {
tapAfMfd(VK_LSHIFT, VK_LMENU, bNum);
}

// Mapping Thrustmaster left mfd
void tapLeftMfdButton(int bNum) {
if (isSimpleMapped(bNum, 3, L_mfd_btn)) {
	keyTap(getMapping(bNum, 3, L_mfd_btn), isExtended(bNum, 3, L_mfd_btn));
} else {
	stdTapLeftMfd(bNum);
};
}

// Mapping Thrustmaster right mfd
void tapRightMfdButton(int bNum) {
if (isSimpleMapped(bNum, 3, R_mfd_btn)) {
	keyTap(getMapping(bNum, 3, R_mfd_btn), isExtended(bNum, 3, R_mfd_btn));
} else {
	stdTapRightMfd(bNum);
}
}

void assignMfds() {	
for (size_t i=0; i < mfd1->getNumButtons(); i++)
	mfd1->getButton(i).assignCallback_onKeyDown(&tapLeftMfdButton);
for (size_t i=0; i < mfd2->getNumButtons(); i++)
	mfd2->getButton(i).assignCallback_onKeyDown(&tapRightMfdButton);
}




////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
/////  HOTAS COUGAR
//////////////////////////////////////////////////


// Simple mappings: buttonNumber, vkey, extended state
const int simpleCougarMappings[3*18] = {
0,	VK_DELETE,	1, // first detent
1,	VK_SPACE,	0, // pickle
2,	0,			0, // round pinky
3,	0,			0, // paddle
4,	0,			0, // nws
5,	VK_INSERT,	1, // second detent
6,	0,			0, // tms u
7,	0,			0, // tms r
8,	0,			0, // tms d
9,	0,			0, // tms l
10,	0,			0, // dms u
11,	0,			0, // dms r
12,	0,			0, // dms d
13,	0,			0, // dms l
14,	0,			0, // cms fwd
15,	0,			0, // cms up/right
16,	0,			0, // cms back
17,	0,			0  // cms down left
};
const int simplePov[3*8] = {
0,		0,					0,
1,		0,					0,
2,		VkKeyScanA('l'),	0,
3,		0,					0,
4,		VK_ADD,				0,
5,		0,					0,
6,		VkKeyScanA('n'),	0,
7,		0,					0
};

void simpleCougarmappings(int bNum) {
if (isSimpleMapped(bNum, 3, simpleCougarMappings)) {
	int key = getMapping(bNum, 3, simpleCougarMappings);
	bool isEx = isExtended(bNum, 3, simpleCougarMappings);
	if (cougar->getButton(bNum).isPressed()) {
		keyDown(key, isEx);
	} else {
		keyUp(key, isEx);
	}
}
}



void cougarPovChange(int dirIndex) {

if (dirIndex == 0) {
	if(cougar->getButton(2).isPressed()) {
		tapRightMfdButton(1);
	} else {
		tapLeftMfdButton(16);
	}
} else{
	keyTap(getMapping(dirIndex, 3, simplePov), isExtended(dirIndex, 3, simplePov));
}
cout << endl << "Pov changed";
}

void assignCougar() {	
for (size_t i=0; i < cougar->getNumButtons(); i++) {
	if (isSimpleMapped(i, 3, simpleCougarMappings)) {
		cougar->getButton(i).assignCallback_onKeyDown(&simpleCougarmappings);
		cougar->getButton(i).assignCallback_onKeyReleased(&simpleCougarmappings);
	} else {
		cougar->getButton(i).assignCallback_onKeyDown(&keyIdentifier);
	}
}

cougar->getPov(0).getPovButton(0).assignCallback_onKeyDown(&cougarPovChange);
cougar->getPov(0).getPovButton(2).assignCallback_onKeyDown(&cougarPovChange);
cougar->getPov(0).getPovButton(4).assignCallback_onKeyDown(&cougarPovChange);
cougar->getPov(0).getPovButton(6).assignCallback_onKeyDown(&cougarPovChange);

}



////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
/////  General
//////////////////////////////////////////////////


void assign() {
assignMfds();
assignCougar();
}

 

 

Update: Working F4Af profile, going to make a Fc2 profile later :P. 2xTM mfds, Hotas cougar and saitek x52 throttle now profiled with single software ^^

:: the profile (v1) -> http://gigurra.se/ProfilerTest.txt

 

.


Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...