Below we present the steps required to open the virtual joystick control device, send input to it and finally close the control device.
HANDLE h;
h= CreateFile("\\\\.\\PPJoyIOCTL1",GENERIC_WRITE,FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
#pragma pack(push,1) /* All fields in structure must be byte aligned. */ typedef struct { unsigned long Signature; /* Signature to identify packet to PPJoy IOCTL */ char NumAnalog; /* Num of analog values we pass */ long Analog[NUM_ANALOG]; /* Analog input values */ char NumDigital; /* Number of digital values we pass */ char Digital[NUM_DIGITAL]; /* Digital input values */ } JOYSTICK_STATE; #pragma pack(pop)
The Signature field should be set to the constant JOYSTICK_STATE_V1 (defined in ppjioctl.h). NumAnalog and NumDigital should be set to the size of axis and button arrays respectively. PPJoy currently supports up to 63 analog and 128 digital values. Extra values in the arrays will be ignored. By default the first 8 analog values will be reported as axes and the first 16 digital values as buttons. Undefined analog values will be centred; undefined digital values will be off/not pressed.
NOTE: The fields in the structure must be byte aligned with no padding between the fields.
PPJOY_AXIS_MIN and PPJOY_AXIS_MAX represents the minimum and maximum values for an analog value. For digital values 1 means pressed and 0 is not pressed.
The sequence of axes are as follows:
PPJoy does not current support changing the number of axes or buttons reported; however extra axes or button can be mapped to "nothing".
A memory dump of the structure with two analog and four digital values looks like this:
43 41 54 53 Header 02 Two analog values to follow xx xx xx xx Analog value 1 (defaults to X Axis) xx xx xx xx Analog value 2 (defaults to Y Axis) 04 Four digital values to follow xx Digital value 1 (defaults to Button 1) xx Digital value 2 (defaults to Button 2) xx Digital value 3 (defaults to Button 3) xx Digital value 4 (defaults to Button 4)After setting the axis and button values in the structure it is passed to PPJoy using DeviceIoControl() with an IOCTL code of IOCTL_PPORTJOY_SET_STATE (defined in ppjioctl.h). This code snippet illustrates:
JOYSTICK_STATE JoyState; DWORD RetSize; DWORD rc; /* Initialise JoyState structure here... */ if (!DeviceIoControl(h,IOCTL_PPORTJOY_SET_STATE,&JoyState,sizeof(JoyState),NULL,0,&RetSize,NULL)) { rc= GetLastError(); /* ... */ }It is important to check the return code for the DeviceIOControl() funcion. If the control device is still open when the underlying joystick device is deleted the PPortJoy.sys driver cannot unload. In this case GetLastError() will return 2. When you get this error code close the handle to the control device and retry opening the control device.
Get IOCTLSample sample application (Microsoft Visual C++ 6.0).