dinput: Use heuristics to guess if a device is a gamepad or a joystick.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47123 Signed-off-by: Andrew Eikum <aeikum@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9cbfd2c9c5
commit
ae84957916
|
@ -81,7 +81,7 @@ extern void _copy_diactionformatWtoA(LPDIACTIONFORMATA, LPDIACTIONFORMATW) DECLS
|
|||
extern HRESULT _configure_devices(IDirectInput8W *iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) DECLSPEC_HIDDEN;
|
||||
|
||||
extern WCHAR* get_mapping_path(const WCHAR *device, const WCHAR *username) DECLSPEC_HIDDEN;
|
||||
extern DWORD get_device_type(DWORD version) DECLSPEC_HIDDEN;
|
||||
extern DWORD get_device_type(DWORD version, BOOL is_joystick) DECLSPEC_HIDDEN;
|
||||
|
||||
#define IS_DIPROP(x) (((ULONG_PTR)(x) >> 16) == 0)
|
||||
|
||||
|
|
|
@ -76,8 +76,12 @@ DWORD typeFromGUID(REFGUID guid)
|
|||
}
|
||||
}
|
||||
|
||||
DWORD get_device_type(DWORD version)
|
||||
DWORD get_device_type(DWORD version, BOOL is_joystick)
|
||||
{
|
||||
if (is_joystick)
|
||||
return version >= 0x0800 ? DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8) :
|
||||
DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
|
||||
|
||||
return version >= 0x0800 ? DI8DEVTYPE_GAMEPAD | (DI8DEVTYPEJOYSTICK_STANDARD << 8) :
|
||||
DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_GAMEPAD << 8);
|
||||
}
|
||||
|
|
|
@ -84,6 +84,8 @@ struct JoyDev
|
|||
int *dev_axes_map;
|
||||
|
||||
WORD vendor_id, product_id, bus_type;
|
||||
|
||||
BOOL is_joystick;
|
||||
};
|
||||
|
||||
typedef struct JoystickImpl JoystickImpl;
|
||||
|
@ -177,6 +179,7 @@ static INT find_joystick_devices(void)
|
|||
int fd;
|
||||
struct JoyDev joydev, *new_joydevs;
|
||||
BYTE axes_map[ABS_MAX + 1];
|
||||
SHORT btn_map[KEY_MAX - BTN_MISC + 1];
|
||||
|
||||
snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_NEW, i);
|
||||
if ((fd = open(joydev.device, O_RDONLY)) == -1)
|
||||
|
@ -220,6 +223,42 @@ static INT find_joystick_devices(void)
|
|||
joydev.button_count = 2;
|
||||
#endif
|
||||
|
||||
joydev.is_joystick = FALSE;
|
||||
if (ioctl(fd, JSIOCGBTNMAP, btn_map) < 0)
|
||||
{
|
||||
WARN("ioctl(%s,JSIOCGBTNMAP) failed: %s\n", joydev.device, strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
INT j;
|
||||
/* in lieu of properly reporting HID usage, detect presence of
|
||||
* "joystick buttons" and report those devices as joysticks instead of
|
||||
* gamepads */
|
||||
for (j = 0; !joydev.is_joystick && j < joydev.button_count; j++)
|
||||
{
|
||||
switch (btn_map[j])
|
||||
{
|
||||
case BTN_TRIGGER:
|
||||
case BTN_THUMB:
|
||||
case BTN_THUMB2:
|
||||
case BTN_TOP:
|
||||
case BTN_TOP2:
|
||||
case BTN_PINKIE:
|
||||
case BTN_BASE:
|
||||
case BTN_BASE2:
|
||||
case BTN_BASE3:
|
||||
case BTN_BASE4:
|
||||
case BTN_BASE5:
|
||||
case BTN_BASE6:
|
||||
case BTN_DEAD:
|
||||
joydev.is_joystick = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ioctl(fd, JSIOCGAXMAP, axes_map) < 0)
|
||||
{
|
||||
WARN("ioctl(%s,JSIOCGAXMAP) failed: %s\n", joydev.device, strerror(errno));
|
||||
|
@ -322,7 +361,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
|
|||
lpddi->guidInstance = DInput_Wine_Joystick_GUID;
|
||||
lpddi->guidInstance.Data3 = id;
|
||||
lpddi->guidProduct = joystick_devices[id].guid_product;
|
||||
lpddi->dwDevType = get_device_type(version);
|
||||
lpddi->dwDevType = get_device_type(version, joystick_devices[id].is_joystick);
|
||||
|
||||
/* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */
|
||||
if (joystick_devices[id].bus_type == BUS_USB &&
|
||||
|
@ -330,7 +369,10 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
|
|||
{
|
||||
lpddi->dwDevType |= DIDEVTYPE_HID;
|
||||
lpddi->wUsagePage = 0x01; /* Desktop */
|
||||
lpddi->wUsage = 0x05; /* Game Pad */
|
||||
if (joystick_devices[id].is_joystick)
|
||||
lpddi->wUsage = 0x04; /* Joystick */
|
||||
else
|
||||
lpddi->wUsage = 0x05; /* Game Pad */
|
||||
}
|
||||
|
||||
MultiByteToWideChar(CP_ACP, 0, joystick_devices[id].name, -1, lpddi->tszInstanceName, MAX_PATH);
|
||||
|
|
|
@ -100,7 +100,7 @@ struct JoyDev {
|
|||
GUID guid;
|
||||
GUID guid_product;
|
||||
|
||||
BOOL has_ff;
|
||||
BOOL has_ff, is_joystick;
|
||||
int num_effects;
|
||||
|
||||
/* data returned by EVIOCGBIT for caps, EV_ABS, EV_KEY, and EV_FF */
|
||||
|
@ -243,6 +243,24 @@ static void find_joydevs(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* in lieu of properly reporting HID usage, detect presence of
|
||||
* "joystick buttons" and report those devices as joysticks instead of
|
||||
* gamepads */
|
||||
joydev.is_joystick =
|
||||
test_bit(joydev.keybits, BTN_TRIGGER) ||
|
||||
test_bit(joydev.keybits, BTN_THUMB) ||
|
||||
test_bit(joydev.keybits, BTN_THUMB2) ||
|
||||
test_bit(joydev.keybits, BTN_TOP) ||
|
||||
test_bit(joydev.keybits, BTN_TOP2) ||
|
||||
test_bit(joydev.keybits, BTN_PINKIE) ||
|
||||
test_bit(joydev.keybits, BTN_BASE) ||
|
||||
test_bit(joydev.keybits, BTN_BASE2) ||
|
||||
test_bit(joydev.keybits, BTN_BASE3) ||
|
||||
test_bit(joydev.keybits, BTN_BASE4) ||
|
||||
test_bit(joydev.keybits, BTN_BASE5) ||
|
||||
test_bit(joydev.keybits, BTN_BASE6) ||
|
||||
test_bit(joydev.keybits, BTN_DEAD);
|
||||
|
||||
if (!(joydev.device = HeapAlloc(GetProcessHeap(), 0, strlen(buf) + 1)))
|
||||
{
|
||||
close(fd);
|
||||
|
@ -350,7 +368,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
|
|||
lpddi->guidInstance = joydevs[id].guid;
|
||||
lpddi->guidProduct = joydevs[id].guid_product;
|
||||
lpddi->guidFFDriver = GUID_NULL;
|
||||
lpddi->dwDevType = get_device_type(version);
|
||||
lpddi->dwDevType = get_device_type(version, joydevs[id].is_joystick);
|
||||
|
||||
/* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */
|
||||
if (joydevs[id].bus_type == BUS_USB &&
|
||||
|
@ -358,7 +376,10 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
|
|||
{
|
||||
lpddi->dwDevType |= DIDEVTYPE_HID;
|
||||
lpddi->wUsagePage = 0x01; /* Desktop */
|
||||
lpddi->wUsage = 0x05; /* Game Pad */
|
||||
if (joydevs[id].is_joystick)
|
||||
lpddi->wUsage = 0x04; /* Joystick */
|
||||
else
|
||||
lpddi->wUsage = 0x05; /* Game Pad */
|
||||
}
|
||||
|
||||
MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszInstanceName, MAX_PATH);
|
||||
|
|
|
@ -945,6 +945,7 @@ static DWORD make_vid_pid(IOHIDDeviceRef device)
|
|||
static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
|
||||
{
|
||||
IOHIDDeviceRef device;
|
||||
BOOL is_joystick;
|
||||
|
||||
TRACE("dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType, dwFlags, version, id);
|
||||
|
||||
|
@ -962,15 +963,19 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
|||
if(get_ff(device, NULL) != S_OK)
|
||||
return S_FALSE;
|
||||
}
|
||||
is_joystick = get_device_property_long(device, CFSTR(kIOHIDDeviceUsageKey)) == kHIDUsage_GD_Joystick;
|
||||
/* Return joystick */
|
||||
lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
|
||||
lpddi->guidInstance.Data3 = id;
|
||||
lpddi->guidProduct = DInput_Wine_OsX_Joystick_GUID;
|
||||
lpddi->guidProduct.Data1 = make_vid_pid(device);
|
||||
lpddi->dwDevType = get_device_type(version);
|
||||
lpddi->dwDevType = get_device_type(version, is_joystick);
|
||||
lpddi->dwDevType |= DIDEVTYPE_HID;
|
||||
lpddi->wUsagePage = 0x01; /* Desktop */
|
||||
lpddi->wUsage = 0x05; /* Game Pad */
|
||||
if (is_joystick)
|
||||
lpddi->wUsage = 0x04; /* Joystick */
|
||||
else
|
||||
lpddi->wUsage = 0x05; /* Game Pad */
|
||||
sprintf(lpddi->tszInstanceName, "Joystick %d", id);
|
||||
|
||||
/* get the device name */
|
||||
|
@ -988,6 +993,7 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
|||
char name[MAX_PATH];
|
||||
char friendly[32];
|
||||
IOHIDDeviceRef device;
|
||||
BOOL is_joystick;
|
||||
|
||||
TRACE("dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType, dwFlags, version, id);
|
||||
|
||||
|
@ -1005,14 +1011,22 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
|||
if(get_ff(device, NULL) != S_OK)
|
||||
return S_FALSE;
|
||||
}
|
||||
is_joystick = get_device_property_long(device, CFSTR(kIOHIDDeviceUsageKey)) == kHIDUsage_GD_Joystick;
|
||||
/* Return joystick */
|
||||
lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
|
||||
lpddi->guidInstance.Data3 = id;
|
||||
lpddi->guidProduct = DInput_Wine_OsX_Joystick_GUID;
|
||||
lpddi->guidProduct.Data1 = make_vid_pid(device);
|
||||
lpddi->dwDevType = get_device_type(version);
|
||||
lpddi->dwDevType = get_device_type(version, is_joystick);
|
||||
lpddi->dwDevType |= DIDEVTYPE_HID;
|
||||
lpddi->wUsagePage = 0x01; /* Desktop */
|
||||
if (is_joystick)
|
||||
lpddi->wUsage = 0x04; /* Joystick */
|
||||
else
|
||||
lpddi->wUsage = 0x05; /* Game Pad */
|
||||
sprintf(friendly, "Joystick %d", id);
|
||||
MultiByteToWideChar(CP_ACP, 0, friendly, -1, lpddi->tszInstanceName, MAX_PATH);
|
||||
|
||||
/* get the device name */
|
||||
get_osx_device_name(id, name, MAX_PATH);
|
||||
|
||||
|
|
Loading…
Reference in New Issue