dinput axis mapping patch
Robert Reif
reif at earthlink.net
Fri Sep 3 21:16:53 CDT 2004
This patch allows you map a linux joystick axis to a dinput axis or POV.
I had to change the initialization sequence a bit to get the needed data
at the right time.
Add a [dinput] section to your config file and provide a line with the
following information:
"your device name" = "X,Y,Z,Rx,Ry,Rz,Slider1,Slider2,POV1,POV2,POV3,POV4"
where "your device name" is what you get from /bin/jstest and
the axes list are the axes supported by your joystick.
for example, her is a part of my config file:
[dinput]
"Logitech Logitech Extreme 3D Pro" = "X,Y,Rz,Slider1,POV1,POV2"
where my joystick has 6 axes.
The code is not 100% yet. It has a problem with the slider on
my joy stick. I am about to be hit by the second hurricane in
three weeks so I don't know when I will be able to finish
debugging it.
-------------- next part --------------
Index: dlls/dinput/joystick_linux.c
===================================================================
RCS file: /home/wine/wine/dlls/dinput/joystick_linux.c,v
retrieving revision 1.10
diff -u -r1.10 joystick_linux.c
--- dlls/dinput/joystick_linux.c 3 Sep 2004 18:55:01 -0000 1.10
+++ dlls/dinput/joystick_linux.c 4 Sep 2004 01:57:47 -0000
@@ -19,6 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/*
+ * To Do:
+ * support more than one device
+ * dead zone
+ */
+
#include "config.h"
#include "wine/port.h"
@@ -56,6 +62,7 @@
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
+#include "winreg.h"
#include "dinput.h"
#include "dinput_private.h"
@@ -65,6 +72,7 @@
/* Wine joystick driver object instances */
#define WINE_JOYSTICK_AXIS_BASE 0
+#define WINE_JOYSTICK_POV_BASE 4
#define WINE_JOYSTICK_BUTTON_BASE 8
typedef struct {
@@ -98,6 +106,11 @@
int queue_head, queue_tail, queue_len;
BOOL acquired;
char *name;
+ DIDEVCAPS devcaps;
+ LONG deadzone;
+ int *axis_map;
+ int axes;
+ int buttons;
};
static GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
@@ -107,6 +120,29 @@
{0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
};
+static void _dump_DIDEVCAPS(LPDIDEVCAPS lpDIDevCaps)
+{
+ TRACE("dwSize: %ld\n", lpDIDevCaps->dwSize);
+ TRACE("dwFlags: %08lx\n",lpDIDevCaps->dwFlags);
+ TRACE("dwDevType: %08lx %s\n", lpDIDevCaps->dwDevType,
+ lpDIDevCaps->dwDevType == DIDEVTYPE_DEVICE ? "DIDEVTYPE_DEVICE" :
+ lpDIDevCaps->dwDevType == DIDEVTYPE_DEVICE ? "DIDEVTYPE_DEVICE" :
+ lpDIDevCaps->dwDevType == DIDEVTYPE_MOUSE ? "DIDEVTYPE_MOUSE" :
+ lpDIDevCaps->dwDevType == DIDEVTYPE_KEYBOARD ? "DIDEVTYPE_KEYBOARD" :
+ lpDIDevCaps->dwDevType == DIDEVTYPE_JOYSTICK ? "DIDEVTYPE_JOYSTICK" :
+ lpDIDevCaps->dwDevType == DIDEVTYPE_HID ? "DIDEVTYPE_HID" : "UNKNOWN");
+ TRACE("dwAxes: %ld\n",lpDIDevCaps->dwAxes);
+ TRACE("dwButtons: %ld\n",lpDIDevCaps->dwButtons);
+ TRACE("dwPOVs: %ld\n",lpDIDevCaps->dwPOVs);
+ if (lpDIDevCaps->dwSize > sizeof(DIDEVCAPS_DX3)) {
+ TRACE("dwFFSamplePeriod: %ld\n",lpDIDevCaps->dwFFSamplePeriod);
+ TRACE("dwFFMinTimeResolution: %ld\n",lpDIDevCaps->dwFFMinTimeResolution);
+ TRACE("dwFirmwareRevision: %ld\n",lpDIDevCaps->dwFirmwareRevision);
+ TRACE("dwHardwareRevision: %ld\n",lpDIDevCaps->dwHardwareRevision);
+ TRACE("dwFFDriverVersion: %ld\n",lpDIDevCaps->dwFFDriverVersion);
+ }
+}
+
static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, int version)
{
int fd = -1;
@@ -133,8 +169,8 @@
lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
strcpy(lpddi->tszInstanceName, "Joystick");
#if defined(JSIOCGNAME)
- if (ioctl(fd,JSIOCGNAME(sizeof(lpddi->tszProductName)),lpddi->tszProductName) < 0) {
- WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", JOYDEV, strerror(errno));
+ if (ioctl(fd,JSIOCGNAME(sizeof(lpddi->tszProductName)),lpddi->tszProductName) < 0) {
+ WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", JOYDEV, strerror(errno));
strcpy(lpddi->tszProductName, "Wine Joystick");
}
#else
@@ -162,7 +198,7 @@
if ((dwDevType==0) || (GET_DIDEVICE_TYPE(dwDevType)==DIDEVTYPE_JOYSTICK)) {
/* check whether we have a joystick */
- if ((fd = open(JOYDEV,O_RDONLY) < 0)) {
+ if ((fd = open(JOYDEV,O_RDONLY)) < 0) {
WARN("open(%s,O_RDONLY) failed: %s\n", JOYDEV, strerror(errno));
return FALSE;
}
@@ -176,8 +212,8 @@
MultiByteToWideChar(CP_ACP, 0, "Joystick", -1, lpddi->tszInstanceName, MAX_PATH);
#if defined(JSIOCGNAME)
- if (ioctl(fd,JSIOCGNAME(sizeof(name)),name) < 0) {
- WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", JOYDEV, strerror(errno));
+ if (ioctl(fd,JSIOCGNAME(sizeof(name)),name) < 0) {
+ WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", JOYDEV, strerror(errno));
strcpy(name, "Wine Joystick");
}
#else
@@ -193,23 +229,215 @@
return FALSE;
}
-static JoystickImpl *alloc_device(REFGUID rguid, LPVOID jvt, IDirectInputImpl *dinput)
+/*
+ * Get a config key from either the app-specific or the default config
+ */
+
+inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
+ char *buffer, DWORD size )
+{
+ if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, buffer, &size ))
+ return 0;
+
+ return RegQueryValueExA( defkey, name, 0, NULL, buffer, &size );
+}
+
+/*
+ * Setup the dinput options.
+ */
+
+static HRESULT setup_dinput_options(JoystickImpl * device)
+{
+ char buffer[MAX_PATH+1];
+ HKEY hkey, appkey = 0;
+ DWORD len;
+
+ buffer[MAX_PATH]='\0';
+
+ if (RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\dinput", 0, NULL,
+ REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL )) {
+ ERR("Cannot create config registry key\n" );
+ ExitProcess(1);
+ }
+
+ len = GetModuleFileNameA( 0, buffer, MAX_PATH );
+ if (len && len < MAX_PATH) {
+ HKEY tmpkey;
+
+ if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\AppDefaults", &tmpkey )) {
+ char appname[MAX_PATH+16];
+ char *p = strrchr( buffer, '\\' );
+ if (p!=NULL) {
+ appname[MAX_PATH]='\0';
+ strncpy(appname,p+1,MAX_PATH);
+ strcat(appname,"\\dinput");
+ TRACE("appname = [%s] \n",appname);
+ if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
+ RegCloseKey( tmpkey );
+ }
+ }
+ }
+
+ /* get options */
+
+ if (!get_config_key( hkey, appkey, "DefaultDeadZone", buffer, MAX_PATH )) {
+ device->deadzone = atoi(buffer);
+ TRACE("setting default deadzone to: \"%s\" %ld\n", buffer, device->deadzone);
+ }
+
+ if (!get_config_key( hkey, appkey, device->name, buffer, MAX_PATH )) {
+ int tokens = 0;
+ int axis = 0;
+ int pov = 0;
+ char *delim = ",";
+ char * ptr;
+ ERR("\"%s\" = \"%s\"\n", device->name, buffer);
+
+ device->axis_map = HeapAlloc(GetProcessHeap(), 0, device->axes * sizeof(int));
+ if (device->axis_map == 0)
+ return DIERR_OUTOFMEMORY;
+
+ if ((ptr = strtok(buffer, delim)) != NULL) {
+ do {
+ if (strcmp(ptr, "X") == 0) {
+ device->axis_map[tokens] = 0;
+ axis++;
+ } else if (strcmp(ptr, "Y") == 0) {
+ device->axis_map[tokens] = 1;
+ axis++;
+ } else if (strcmp(ptr, "Z") == 0) {
+ device->axis_map[tokens] = 2;
+ axis++;
+ } else if (strcmp(ptr, "Rx") == 0) {
+ device->axis_map[tokens] = 3;
+ axis++;
+ } else if (strcmp(ptr, "Ry") == 0) {
+ device->axis_map[tokens] = 4;
+ axis++;
+ } else if (strcmp(ptr, "Rz") == 0) {
+ device->axis_map[tokens] = 5;
+ axis++;
+ } else if (strcmp(ptr, "Slider1") == 0) {
+ device->axis_map[tokens] = 6;
+ axis++;
+ } else if (strcmp(ptr, "Slider2") == 0) {
+ device->axis_map[tokens] = 7;
+ axis++;
+ } else if (strcmp(ptr, "POV1") == 0) {
+ device->axis_map[tokens] = 8;
+ pov++;
+ } else if (strcmp(ptr, "POV2") == 0) {
+ device->axis_map[tokens] = 9;
+ pov++;
+ } else if (strcmp(ptr, "POV3") == 0) {
+ device->axis_map[tokens] = 10;
+ pov++;
+ } else if (strcmp(ptr, "POV4") == 0) {
+ device->axis_map[tokens] = 11;
+ pov++;
+ } else {
+ ERR("invalid joystick axis type: %s\n", ptr);
+ device->axis_map[tokens] = tokens;
+ axis++;
+ }
+
+ tokens++;
+ } while ((ptr = strtok(NULL, delim)) != NULL);
+
+ if (tokens != device->devcaps.dwAxes) {
+ ERR("no all joystick axes mapped: %d axes(%d,%d), %d arguments\n", device->axes, axis, pov,tokens);
+ while (tokens < device->axes) {
+ device->axis_map[tokens] = tokens;
+ tokens++;
+ }
+ }
+ }
+
+ device->devcaps.dwAxes = axis;
+ device->devcaps.dwPOVs = pov;
+ }
+
+ if (appkey)
+ RegCloseKey( appkey );
+
+ RegCloseKey( hkey );
+
+ return DI_OK;
+}
+
+static HRESULT alloc_device(REFGUID rguid, LPVOID jvt, IDirectInputImpl *dinput, LPDIRECTINPUTDEVICEA* pdev)
{
DWORD i;
JoystickImpl* newDevice;
+ char name[MAX_PATH];
+ HRESULT hr;
newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickImpl));
- if (newDevice == 0)
- return 0;
+ if (newDevice == 0) {
+ WARN("out of memory\n");
+ *pdev = 0;
+ return DIERR_OUTOFMEMORY;
+ }
+
+ if ((newDevice->joyfd = open(JOYDEV,O_RDONLY)) < 0) {
+ WARN("open(%s,O_RDONLY) failed: %s\n", JOYDEV, strerror(errno));
+ HeapFree(GetProcessHeap(), 0, newDevice);
+ return DIERR_DEVICENOTREG;
+ }
+
+ /* get the device name */
+#if defined(JSIOCGNAME)
+ if (ioctl(newDevice->joyfd,JSIOCGNAME(MAX_PATH),name) < 0) {
+ WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", JOYDEV, strerror(errno));
+ strcpy(name, "Wine Joystick");
+ }
+#else
+ strcpy(name, "Wine Joystick");
+#endif
+
+ /* copy the device name */
+ newDevice->name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
+ strcpy(newDevice->name, name);
+
+#ifdef JSIOCGAXES
+ if (ioctl(newDevice->joyfd,JSIOCGAXES,&newDevice->axes) < 0) {
+ WARN("ioctl(%s,JSIOCGAXES) failed: %s, defauting to 2\n", JOYDEV, strerror(errno));
+ newDevice->axes = 2;
+ }
+#endif
+#ifdef JSIOCGBUTTONS
+ if (ioctl(newDevice->joyfd,JSIOCGBUTTONS,&newDevice->buttons) < 0) {
+ WARN("ioctl(%s,JSIOCGBUTTONS) failed: %s, defauting to 2\n", JOYDEV, strerror(errno));
+ newDevice->buttons = 2;
+ }
+#endif
newDevice->lpVtbl = jvt;
newDevice->ref = 1;
- newDevice->joyfd = -1;
newDevice->dinput = dinput;
newDevice->acquired = FALSE;
- newDevice->name = NULL;
+ newDevice->deadzone = 0;
CopyMemory(&(newDevice->guid),rguid,sizeof(*rguid));
+ /* setup_dinput_options may change these */
+ newDevice->devcaps.dwAxes = newDevice->axes;
+ newDevice->devcaps.dwButtons = newDevice->buttons;
+ newDevice->devcaps.dwPOVs = 0;
+
+ /* do any user specified configuration */
+ hr = setup_dinput_options(newDevice);
+ if (hr != DI_OK)
+ goto FAILED1;
+
+ if (newDevice->axis_map == 0) {
+ newDevice->axis_map = HeapAlloc(GetProcessHeap(), 0, newDevice->axes * sizeof(int));
+ if (newDevice->axis_map == 0)
+ goto FAILED;
+
+ for (i = 0; i < newDevice->axes; i++)
+ newDevice->axis_map[i] = i;
+ }
+
/* wine uses DIJOYSTATE2 as it's internal format so copy
* the already defined format c_dfDIJoystick2 */
newDevice->user_df = HeapAlloc(GetProcessHeap(),0,c_dfDIJoystick2.dwSize);
@@ -234,7 +462,7 @@
for (i = 0; i < c_dfDIJoystick2.dwNumObjs; i++) {
newDevice->props[i].lMin = 0;
newDevice->props[i].lMax = 0xffff;
- newDevice->props[i].lDeadZone = 1000;
+ newDevice->props[i].lDeadZone = newDevice->deadzone;
newDevice->props[i].lSaturation = 0;
}
@@ -248,12 +476,33 @@
IDirectInputDevice_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->dinput);
- if (TRACE_ON(dinput))
+ newDevice->devcaps.dwSize = sizeof(newDevice->devcaps);
+ newDevice->devcaps.dwFlags = DIDC_ATTACHED;
+ newDevice->devcaps.dwDevType = DIDEVTYPE_JOYSTICK;
+ newDevice->devcaps.dwFFSamplePeriod = 0;
+ newDevice->devcaps.dwFFMinTimeResolution = 0;
+ newDevice->devcaps.dwFirmwareRevision = 0;
+ newDevice->devcaps.dwHardwareRevision = 0;
+ newDevice->devcaps.dwFFDriverVersion = 0;
+
+ if (TRACE_ON(dinput)) {
_dump_DIDATAFORMAT(newDevice->user_df);
+ for (i = 0; i < (newDevice->axes); i++)
+ TRACE("axis_map[%ld] = %d\n", i, newDevice->axis_map[i]);
+ _dump_DIDEVCAPS(&newDevice->devcaps);
+ }
- return newDevice;
+ *pdev = (LPDIRECTINPUTDEVICEA)newDevice;
+
+ return DI_OK;
FAILED:
+ hr = DIERR_OUTOFMEMORY;
+FAILED1:
+ if (newDevice->axis_map)
+ HeapFree(GetProcessHeap(),0,newDevice->axis_map);
+ if (newDevice->name)
+ HeapFree(GetProcessHeap(),0,newDevice->name);
if (newDevice->props)
HeapFree(GetProcessHeap(),0,newDevice->props);
if (newDevice->user_df->rgodf)
@@ -262,7 +511,9 @@
HeapFree(GetProcessHeap(),0,newDevice->user_df);
if (newDevice)
HeapFree(GetProcessHeap(),0,newDevice);
- return 0;
+ *pdev = 0;
+
+ return hr;
}
static HRESULT joydev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
@@ -274,14 +525,7 @@
IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
- *pdev=(IDirectInputDeviceA*) alloc_device(rguid, &JoystickAvt, dinput);
- if (*pdev == 0) {
- WARN("out of memory\n");
- return DIERR_OUTOFMEMORY;
- }
-
- TRACE("Creating a Joystick device (%p)\n", *pdev);
- return DI_OK;
+ return alloc_device(rguid, &JoystickAvt, dinput, pdev);
} else {
WARN("no interface\n");
*pdev = 0;
@@ -303,14 +547,7 @@
IsEqualGUID(&IID_IDirectInputDevice2W,riid) ||
IsEqualGUID(&IID_IDirectInputDevice7W,riid) ||
IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
- *pdev = (IDirectInputDeviceW*) alloc_device(rguid, &JoystickWvt, dinput);
- if (*pdev == 0) {
- WARN("out of memory\n");
- return DIERR_OUTOFMEMORY;
- }
-
- TRACE("Creating a Joystick device (%p)\n", *pdev);
- return DI_OK;
+ return alloc_device(rguid, &JoystickWvt, dinput, (LPDIRECTINPUTDEVICEA *)pdev);
} else {
WARN("no interface\n");
*pdev = 0;
@@ -349,6 +586,10 @@
if (This->name)
HeapFree(GetProcessHeap(),0,This->name);
+ /* Free the axis map */
+ if (This->axis_map)
+ HeapFree(GetProcessHeap(),0,This->axis_map);
+
/* Free the data queue */
if (This->data_queue != NULL)
HeapFree(GetProcessHeap(),0,This->data_queue);
@@ -564,14 +805,16 @@
This->js.rgbButtons[jse.number] = value;
GEN_EVENT(offset,value,jse.time,(This->dinput->evsequence)++);
} else if (jse.type & JS_EVENT_AXIS) {
- if (jse.number < 8) {
- int offset = This->offsets[jse.number];
+ int number = This->axis_map[jse.number];
+ if (number < 12) {
+ int offset = This->offsets[number];
int index = offset_to_object(This, offset);
LONG value = map_axis(This, jse.value, index);
/* FIXME do deadzone and saturation here */
- switch (jse.number) {
+ TRACE("changing axis %d => %d\n", jse.number, number);
+ switch (number) {
case 0:
This->js.lX = value;
break;
@@ -596,11 +839,23 @@
case 7:
This->js.rglSlider[1] = value;
break;
+ case 8:
+ This->js.rgdwPOV[0] = value;
+ break;
+ case 9:
+ This->js.rgdwPOV[1] = value;
+ break;
+ case 10:
+ This->js.rgdwPOV[2] = value;
+ break;
+ case 11:
+ This->js.rgdwPOV[3] = value;
+ break;
}
GEN_EVENT(offset,value,jse.time,(This->dinput->evsequence)++);
- } else
- WARN("axis %d not supported\n", jse.number);
+ } else
+ WARN("axis %d not supported\n", number);
}
}
}
@@ -663,19 +918,26 @@
} else if (ph->dwHow == DIPH_BYID) {
int axis = 0;
int button = 0;
+ int pov = 0;
for (i = 0; i < This->user_df->dwNumObjs; i++) {
DWORD type = 0;
if (DIDFT_GETTYPE(This->user_df->rgodf[i].dwType) & DIDFT_AXIS) {
axis++;
type = DIDFT_GETTYPE(This->user_df->rgodf[i].dwType) |
DIDFT_MAKEINSTANCE(axis << WINE_JOYSTICK_AXIS_BASE);
- TRACE("type = 0x%08lx\n", type);
+ TRACE("axis type = 0x%08lx\n", type);
+ }
+ if (DIDFT_GETTYPE(This->user_df->rgodf[i].dwType) & DIDFT_POV) {
+ pov++;
+ type = DIDFT_GETTYPE(This->user_df->rgodf[i].dwType) |
+ DIDFT_MAKEINSTANCE(axis << WINE_JOYSTICK_POV_BASE);
+ TRACE("POV type = 0x%08lx\n", type);
}
if (DIDFT_GETTYPE(This->user_df->rgodf[i].dwType) & DIDFT_BUTTON) {
button++;
type = DIDFT_GETTYPE(This->user_df->rgodf[i].dwType) |
DIDFT_MAKEINSTANCE(button << WINE_JOYSTICK_BUTTON_BASE);
- TRACE("type = 0x%08lx\n", type);
+ TRACE("button type = 0x%08lx\n", type);
}
if (type == ph->dwObj) {
return i;
@@ -761,63 +1023,24 @@
return DI_OK;
}
-static void _dump_DIDEVCAPS(LPDIDEVCAPS lpDIDevCaps)
-{
- TRACE("dwSize: %ld\n", lpDIDevCaps->dwSize);
- TRACE("dwFlags: %08lx\n",lpDIDevCaps->dwFlags);
- TRACE("dwDevType: %08lx %s\n", lpDIDevCaps->dwDevType,
- lpDIDevCaps->dwDevType == DIDEVTYPE_DEVICE ? "DIDEVTYPE_DEVICE" :
- lpDIDevCaps->dwDevType == DIDEVTYPE_DEVICE ? "DIDEVTYPE_DEVICE" :
- lpDIDevCaps->dwDevType == DIDEVTYPE_MOUSE ? "DIDEVTYPE_MOUSE" :
- lpDIDevCaps->dwDevType == DIDEVTYPE_KEYBOARD ? "DIDEVTYPE_KEYBOARD" :
- lpDIDevCaps->dwDevType == DIDEVTYPE_JOYSTICK ? "DIDEVTYPE_JOYSTICK" :
- lpDIDevCaps->dwDevType == DIDEVTYPE_HID ? "DIDEVTYPE_HID" : "UNKNOWN");
- TRACE("dwAxes: %ld\n",lpDIDevCaps->dwAxes);
- TRACE("dwButtons: %ld\n",lpDIDevCaps->dwButtons);
- TRACE("dwPOVs: %ld\n",lpDIDevCaps->dwPOVs);
- if (lpDIDevCaps->dwSize > sizeof(DIDEVCAPS_DX3)) {
- TRACE("dwFFSamplePeriod: %ld\n",lpDIDevCaps->dwFFSamplePeriod);
- TRACE("dwFFMinTimeResolution: %ld\n",lpDIDevCaps->dwFFMinTimeResolution);
- TRACE("dwFirmwareRevision: %ld\n",lpDIDevCaps->dwFirmwareRevision);
- TRACE("dwHardwareRevision: %ld\n",lpDIDevCaps->dwHardwareRevision);
- TRACE("dwFFDriverVersion: %ld\n",lpDIDevCaps->dwFFDriverVersion);
- }
-}
-
static HRESULT WINAPI JoystickAImpl_GetCapabilities(
LPDIRECTINPUTDEVICE8A iface,
LPDIDEVCAPS lpDIDevCaps)
{
ICOM_THIS(JoystickImpl,iface);
- BYTE axes,buttons;
- int xfd = This->joyfd;
+ int size;
TRACE("%p->(%p)\n",iface,lpDIDevCaps);
- if (xfd==-1)
- xfd = open(JOYDEV,O_RDONLY);
- lpDIDevCaps->dwFlags = DIDC_ATTACHED;
- lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK;
-#ifdef JSIOCGAXES
- if (-1==ioctl(xfd,JSIOCGAXES,&axes))
- axes = 2;
- lpDIDevCaps->dwAxes = axes;
-#endif
-#ifdef JSIOCGBUTTONS
- if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
- buttons = 2;
- lpDIDevCaps->dwButtons = buttons;
-#endif
- if (xfd!=This->joyfd)
- close(xfd);
- if (lpDIDevCaps->dwSize > sizeof(DIDEVCAPS_DX3)) {
- lpDIDevCaps->dwFFSamplePeriod = 0;
- lpDIDevCaps->dwFFMinTimeResolution = 0;
- lpDIDevCaps->dwFirmwareRevision = 0;
- lpDIDevCaps->dwHardwareRevision = 0;
- lpDIDevCaps->dwFFDriverVersion = 0;
+ if (lpDIDevCaps == NULL) {
+ WARN("invalid parameter: lpDIDevCaps = NULL\n");
+ return DIERR_INVALIDPARAM;
}
+ size = lpDIDevCaps->dwSize;
+ CopyMemory(lpDIDevCaps, &This->devcaps, size);
+ lpDIDevCaps->dwSize = size;
+
if (TRACE_ON(dinput))
_dump_DIDEVCAPS(lpDIDevCaps);
@@ -850,7 +1073,7 @@
{
ICOM_THIS(JoystickImpl,iface);
DIDEVICEOBJECTINSTANCEA ddoi;
- int xfd = This->joyfd;
+ BYTE i;
TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags);
if (TRACE_ON(dinput)) {
@@ -862,30 +1085,13 @@
/* Only the fields till dwFFMaxForce are relevant */
ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
-#if defined(JSIOCGNAME)
- if (!This->name) {
- char name[64];
- if (-1==ioctl(xfd,JSIOCGNAME(sizeof(name)),name)) {
- This->name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
- strcpy(This->name, name);
- strcpy(ddoi.tszName, This->name);
- }
- } else
- strcpy(ddoi.tszName, This->name);
-#endif
-
/* For the joystick, do as is done in the GetCapabilities function */
if ((dwFlags == DIDFT_ALL) ||
- (dwFlags & DIDFT_AXIS)) {
- BYTE axes, i;
-
-#ifdef JSIOCGAXES
- if (-1==ioctl(xfd,JSIOCGAXES,&axes))
- axes = 2;
-#endif
+ (dwFlags & DIDFT_AXIS) ||
+ (dwFlags & DIDFT_POV)) {
- for (i = 0; i < axes; i++) {
- switch (i) {
+ for (i = 0; i < This->axes; i++) {
+ switch (This->axis_map[i]) {
case 0:
ddoi.guidType = GUID_XAxis;
ddoi.dwOfs = DIJOFS_X;
@@ -918,12 +1124,33 @@
ddoi.guidType = GUID_Slider;
ddoi.dwOfs = DIJOFS_SLIDER(1);
break;
+ case 8:
+ ddoi.guidType = GUID_POV;
+ ddoi.dwOfs = DIJOFS_POV(0);
+ break;
+ case 9:
+ ddoi.guidType = GUID_POV;
+ ddoi.dwOfs = DIJOFS_POV(1);
+ break;
+ case 10:
+ ddoi.guidType = GUID_POV;
+ ddoi.dwOfs = DIJOFS_POV(2);
+ break;
+ case 11:
+ ddoi.guidType = GUID_POV;
+ ddoi.dwOfs = DIJOFS_POV(3);
+ break;
default:
ddoi.guidType = GUID_Unknown;
ddoi.dwOfs = DIJOFS_Z + (i - 2) * sizeof(LONG);
}
- ddoi.dwType = DIDFT_MAKEINSTANCE((i + 1) << WINE_JOYSTICK_AXIS_BASE) | DIDFT_AXIS;
- sprintf(ddoi.tszName, "%d-Axis", i);
+ if (This->axis_map[i] < 8) {
+ ddoi.dwType = DIDFT_MAKEINSTANCE((i + 1) << WINE_JOYSTICK_AXIS_BASE) | DIDFT_AXIS;
+ sprintf(ddoi.tszName, "%d-Axis", i);
+ } else {
+ ddoi.dwType = DIDFT_MAKEINSTANCE((i + 1) << WINE_JOYSTICK_POV_BASE) | DIDFT_POV;
+ sprintf(ddoi.tszName, "%d-POV", i);
+ }
_dump_OBJECTINSTANCEA(&ddoi);
if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
}
@@ -931,17 +1158,11 @@
if ((dwFlags == DIDFT_ALL) ||
(dwFlags & DIDFT_BUTTON)) {
- BYTE buttons, i;
-
-#ifdef JSIOCGBUTTONS
- if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
- buttons = 2;
-#endif
/* The DInput SDK says that GUID_Button is only for mouse buttons but well... */
ddoi.guidType = GUID_Button;
- for (i = 0; i < buttons; i++) {
+ for (i = 0; i < This->buttons; i++) {
ddoi.dwOfs = DIJOFS_BUTTON(i);
ddoi.dwType = DIDFT_MAKEINSTANCE((i + 1) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_BUTTON;
sprintf(ddoi.tszName, "%d-Button", i);
@@ -949,9 +1170,6 @@
if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
}
}
-
- if (xfd!=This->joyfd)
- close(xfd);
return DI_OK;
}
More information about the wine-patches
mailing list