From: "Rémi Bernon" Subject: [PATCH 2/2] dinput: Add support for more HID axes usages. Message-Id: <20211015111741.3172055-2-rbernon@codeweavers.com> Date: Fri, 15 Oct 2021 13:17:41 +0200 In-Reply-To: <20211015111741.3172055-1-rbernon@codeweavers.com> References: <20211015111741.3172055-1-rbernon@codeweavers.com> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=40658 Signed-off-by: Rémi Bernon --- dlls/dinput/joystick_hid.c | 33 +++++++- dlls/dinput8/tests/hid.c | 157 +++++++++++++++++++++++-------------- 2 files changed, 128 insertions(+), 62 deletions(-) diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 91b07f47cd8..03005964c67 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -229,6 +229,16 @@ static const GUID *object_usage_to_guid( USAGE usage_page, USAGE usage ) switch (usage_page) { case HID_USAGE_PAGE_BUTTON: return &GUID_Button; + case HID_USAGE_PAGE_SIMULATION: + switch (usage) + { + case HID_USAGE_SIMULATION_STEERING: return &GUID_XAxis; + case HID_USAGE_SIMULATION_ACCELERATOR: return &GUID_YAxis; + case HID_USAGE_SIMULATION_BRAKE: return &GUID_RzAxis; + case HID_USAGE_SIMULATION_RUDDER: return &GUID_RzAxis; + case HID_USAGE_SIMULATION_THROTTLE: return &GUID_Slider; + } + break; case HID_USAGE_PAGE_GENERIC: switch (usage) { @@ -378,7 +388,7 @@ static void check_pid_effect_axis_caps( struct hid_joystick *impl, DIDEVICEOBJEC static void set_axis_type( DIDEVICEOBJECTINSTANCEW *instance, BOOL *seen, DWORD i, DWORD *count ) { if (!seen[i]) instance->dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( i ); - else instance->dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 6 + *count++ ); + else instance->dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 6 + (*count)++ ); seen[i] = TRUE; } @@ -439,18 +449,37 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, set_axis_type( &instance, seen_axis, j - HID_USAGE_GENERIC_X, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; break; + case MAKELONG(HID_USAGE_SIMULATION_STEERING, HID_USAGE_PAGE_SIMULATION): + set_axis_type( &instance, seen_axis, 0, &axis ); + instance.dwFlags = DIDOI_ASPECTPOSITION; + break; + case MAKELONG(HID_USAGE_SIMULATION_ACCELERATOR, HID_USAGE_PAGE_SIMULATION): + set_axis_type( &instance, seen_axis, 1, &axis ); + instance.dwFlags = DIDOI_ASPECTPOSITION; + break; case MAKELONG(HID_USAGE_GENERIC_WHEEL, HID_USAGE_PAGE_GENERIC): + case MAKELONG(HID_USAGE_SIMULATION_THROTTLE, HID_USAGE_PAGE_SIMULATION): set_axis_type( &instance, seen_axis, 2, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; break; + case MAKELONG(HID_USAGE_SIMULATION_RUDDER, HID_USAGE_PAGE_SIMULATION): + case MAKELONG(HID_USAGE_SIMULATION_BRAKE, HID_USAGE_PAGE_SIMULATION): + set_axis_type( &instance, seen_axis, 5, &axis ); + instance.dwFlags = DIDOI_ASPECTPOSITION; + break; case MAKELONG(HID_USAGE_GENERIC_HATSWITCH, HID_USAGE_PAGE_GENERIC): instance.dwType = DIDFT_POV | DIDFT_MAKEINSTANCE( pov++ ); instance.dwFlags = 0; break; - default: + case MAKELONG(HID_USAGE_GENERIC_SLIDER, HID_USAGE_PAGE_GENERIC): + case MAKELONG(HID_USAGE_GENERIC_DIAL, HID_USAGE_PAGE_GENERIC): instance.dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 6 + axis++ ); instance.dwFlags = DIDOI_ASPECTPOSITION; break; + default: + instance.dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 6 + axis++ ); + instance.dwFlags = 0; + break; } instance.wUsagePage = caps->usage_page; instance.wUsage = j; diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index d42d3119785..8fda1289843 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3451,12 +3451,15 @@ static void test_simple_joystick(void) USAGE(4, (0xff01u<<16)|(0x1234)), USAGE(1, HID_USAGE_GENERIC_X), USAGE(1, HID_USAGE_GENERIC_Y), + USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_RUDDER), + USAGE(4, (HID_USAGE_PAGE_DIGITIZER<<16)|HID_USAGE_DIGITIZER_TIP_PRESSURE), + USAGE(4, (HID_USAGE_PAGE_CONSUMER<<16)|HID_USAGE_CONSUMER_VOLUME), LOGICAL_MINIMUM(1, 0xe7), LOGICAL_MAXIMUM(1, 0x38), PHYSICAL_MINIMUM(1, 0xe7), PHYSICAL_MAXIMUM(1, 0x38), REPORT_SIZE(1, 8), - REPORT_COUNT(1, 4), + REPORT_COUNT(1, 7), INPUT(1, Data|Var|Abs), USAGE(1, HID_USAGE_GENERIC_HATSWITCH), @@ -3486,14 +3489,14 @@ static void test_simple_joystick(void) static const HIDP_CAPS hid_caps = { - .InputReportByteLength = 6, + .InputReportByteLength = 9, }; static const DIDEVCAPS expect_caps = { .dwSize = sizeof(DIDEVCAPS), .dwFlags = DIDC_ATTACHED | DIDC_EMULATED, .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK, - .dwAxes = 3, + .dwAxes = 6, .dwPOVs = 1, .dwButtons = 2, }; @@ -3501,27 +3504,27 @@ static void test_simple_joystick(void) { { .code = IOCTL_HID_READ_REPORT, - .report_buf = {1,0x10,0x10,0x10,0x10,0}, + .report_buf = {1,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0}, }, { .code = IOCTL_HID_READ_REPORT, - .report_buf = {1,0x10,0x10,0x38,0x38,0xf8}, + .report_buf = {1,0x10,0x10,0x38,0x38,0x10,0x10,0x10,0xf8}, }, { .code = IOCTL_HID_READ_REPORT, - .report_buf = {1,0x10,0x10,0x01,0x01,0x00}, + .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x00}, }, { .code = IOCTL_HID_READ_REPORT, - .report_buf = {1,0x10,0x10,0x01,0x01,0x00}, + .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x00}, }, { .code = IOCTL_HID_READ_REPORT, - .report_buf = {1,0x10,0x10,0x80,0x80,0xff}, + .report_buf = {1,0x10,0x10,0x80,0x80,0x10,0x10,0x10,0xff}, }, { .code = IOCTL_HID_READ_REPORT, - .report_buf = {1,0x10,0x10,0x10,0xee,0x54}, + .report_buf = {1,0x10,0x10,0x10,0xee,0x10,0x10,0x10,0x54}, }, }; static const struct DIJOYSTATE2 expect_state[] = @@ -3586,9 +3589,43 @@ static void test_simple_joystick(void) }; const DIDEVICEOBJECTINSTANCEW expect_objects[] = { + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_Unknown, + .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(6), + .tszName = L"Volume", + .wCollectionNumber = 1, + .wUsagePage = HID_USAGE_PAGE_CONSUMER, + .wUsage = HID_USAGE_CONSUMER_VOLUME, + .wReportId = 1, + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_Unknown, + .dwOfs = 0x4, + .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(7), + .tszName = L"Tip Pressure", + .wCollectionNumber = 1, + .wUsagePage = HID_USAGE_PAGE_DIGITIZER, + .wUsage = HID_USAGE_DIGITIZER_TIP_PRESSURE, + .wReportId = 1, + }, + { + .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), + .guidType = GUID_RzAxis, + .dwOfs = 0x8, + .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(5), + .dwFlags = DIDOI_ASPECTPOSITION, + .tszName = L"Rudder", + .wCollectionNumber = 1, + .wUsagePage = HID_USAGE_PAGE_SIMULATION, + .wUsage = HID_USAGE_SIMULATION_RUDDER, + .wReportId = 1, + }, { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_YAxis, + .dwOfs = 0xc, .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(1), .dwFlags = DIDOI_ASPECTPOSITION, .tszName = L"Y Axis", @@ -3600,7 +3637,7 @@ static void test_simple_joystick(void) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_XAxis, - .dwOfs = 0x4, + .dwOfs = 0x10, .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(0), .dwFlags = DIDOI_ASPECTPOSITION, .tszName = L"X Axis", @@ -3612,7 +3649,7 @@ static void test_simple_joystick(void) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_ZAxis, - .dwOfs = 0xc, + .dwOfs = 0x18, .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(2), .dwFlags = DIDOI_ASPECTPOSITION, .tszName = L"Wheel", @@ -3624,7 +3661,7 @@ static void test_simple_joystick(void) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_POV, - .dwOfs = 0x10, + .dwOfs = 0x1c, .dwType = DIDFT_POV|DIDFT_MAKEINSTANCE(0), .tszName = L"Hat Switch", .wCollectionNumber = 1, @@ -3635,7 +3672,7 @@ static void test_simple_joystick(void) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Button, - .dwOfs = 0x14, + .dwOfs = 0x20, .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(0), .tszName = L"Button 0", .wCollectionNumber = 1, @@ -3646,7 +3683,7 @@ static void test_simple_joystick(void) { .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW), .guidType = GUID_Button, - .dwOfs = 0x15, + .dwOfs = 0x21, .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(1), .tszName = L"Button 1", .wCollectionNumber = 1, @@ -4024,7 +4061,7 @@ static void test_simple_joystick(void) res = 0; hr = IDirectInputDevice8_EnumObjects( device, check_object_count, &res, DIDFT_AXIS | DIDFT_PSHBUTTON ); ok( hr == DI_OK, "EnumObjects returned %#x\n", hr ); - ok( res == 5, "got %u expected %u\n", res, 5 ); + ok( res == 8, "got %u expected %u\n", res, 8 ); hr = IDirectInputDevice8_EnumObjects( device, check_objects, &check_objects_params, DIDFT_ALL ); ok( hr == DI_OK, "EnumObjects returned %#x\n", hr ); ok( check_objects_params.index >= check_objects_params.expect_count, "missing %u objects\n", @@ -4045,21 +4082,21 @@ static void test_simple_joystick(void) hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYUSAGE ); ok( hr == DI_OK, "GetObjectInfo returned: %#x\n", hr ); - check_member( objinst, expect_objects[1], "%u", dwSize ); - check_member_guid( objinst, expect_objects[1], guidType ); - check_member( objinst, expect_objects[1], "%#x", dwOfs ); - check_member( objinst, expect_objects[1], "%#x", dwType ); - check_member( objinst, expect_objects[1], "%#x", dwFlags ); - if (!localized) todo_wine check_member_wstr( objinst, expect_objects[1], tszName ); - check_member( objinst, expect_objects[1], "%u", dwFFMaxForce ); - check_member( objinst, expect_objects[1], "%u", dwFFForceResolution ); - check_member( objinst, expect_objects[1], "%u", wCollectionNumber ); - check_member( objinst, expect_objects[1], "%u", wDesignatorIndex ); - check_member( objinst, expect_objects[1], "%#04x", wUsagePage ); - check_member( objinst, expect_objects[1], "%#04x", wUsage ); - check_member( objinst, expect_objects[1], "%#04x", dwDimension ); - check_member( objinst, expect_objects[1], "%#04x", wExponent ); - check_member( objinst, expect_objects[1], "%u", wReportId ); + check_member( objinst, expect_objects[4], "%u", dwSize ); + check_member_guid( objinst, expect_objects[4], guidType ); + check_member( objinst, expect_objects[4], "%#x", dwOfs ); + check_member( objinst, expect_objects[4], "%#x", dwType ); + check_member( objinst, expect_objects[4], "%#x", dwFlags ); + if (!localized) todo_wine check_member_wstr( objinst, expect_objects[4], tszName ); + check_member( objinst, expect_objects[4], "%u", dwFFMaxForce ); + check_member( objinst, expect_objects[4], "%u", dwFFForceResolution ); + check_member( objinst, expect_objects[4], "%u", wCollectionNumber ); + check_member( objinst, expect_objects[4], "%u", wDesignatorIndex ); + check_member( objinst, expect_objects[4], "%#04x", wUsagePage ); + check_member( objinst, expect_objects[4], "%#04x", wUsage ); + check_member( objinst, expect_objects[4], "%#04x", dwDimension ); + check_member( objinst, expect_objects[4], "%#04x", wExponent ); + check_member( objinst, expect_objects[4], "%u", wReportId ); hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0x14, DIPH_BYOFFSET ); ok( hr == DIERR_NOTFOUND, "GetObjectInfo returned: %#x\n", hr ); @@ -4072,21 +4109,21 @@ static void test_simple_joystick(void) hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYID ); ok( hr == DI_OK, "GetObjectInfo returned: %#x\n", hr ); - check_member( objinst, expect_objects[5], "%u", dwSize ); - check_member_guid( objinst, expect_objects[5], guidType ); - check_member( objinst, expect_objects[5], "%#x", dwOfs ); - check_member( objinst, expect_objects[5], "%#x", dwType ); - check_member( objinst, expect_objects[5], "%#x", dwFlags ); - if (!localized) todo_wine check_member_wstr( objinst, expect_objects[5], tszName ); - check_member( objinst, expect_objects[5], "%u", dwFFMaxForce ); - check_member( objinst, expect_objects[5], "%u", dwFFForceResolution ); - check_member( objinst, expect_objects[5], "%u", wCollectionNumber ); - check_member( objinst, expect_objects[5], "%u", wDesignatorIndex ); - check_member( objinst, expect_objects[5], "%#04x", wUsagePage ); - check_member( objinst, expect_objects[5], "%#04x", wUsage ); - check_member( objinst, expect_objects[5], "%#04x", dwDimension ); - check_member( objinst, expect_objects[5], "%#04x", wExponent ); - check_member( objinst, expect_objects[5], "%u", wReportId ); + check_member( objinst, expect_objects[8], "%u", dwSize ); + check_member_guid( objinst, expect_objects[8], guidType ); + check_member( objinst, expect_objects[8], "%#x", dwOfs ); + check_member( objinst, expect_objects[8], "%#x", dwType ); + check_member( objinst, expect_objects[8], "%#x", dwFlags ); + if (!localized) todo_wine check_member_wstr( objinst, expect_objects[8], tszName ); + check_member( objinst, expect_objects[8], "%u", dwFFMaxForce ); + check_member( objinst, expect_objects[8], "%u", dwFFForceResolution ); + check_member( objinst, expect_objects[8], "%u", wCollectionNumber ); + check_member( objinst, expect_objects[8], "%u", wDesignatorIndex ); + check_member( objinst, expect_objects[8], "%#04x", wUsagePage ); + check_member( objinst, expect_objects[8], "%#04x", wUsage ); + check_member( objinst, expect_objects[8], "%#04x", dwDimension ); + check_member( objinst, expect_objects[8], "%#04x", wExponent ); + check_member( objinst, expect_objects[8], "%u", wReportId ); hr = IDirectInputDevice8_EnumEffects( device, NULL, NULL, DIEFT_ALL ); ok( hr == DIERR_INVALIDPARAM, "EnumEffects returned %#x\n", hr ); @@ -4130,21 +4167,21 @@ static void test_simple_joystick(void) hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, DIJOFS_Y, DIPH_BYOFFSET ); ok( hr == DI_OK, "GetObjectInfo returned: %#x\n", hr ); - check_member( objinst, expect_objects[0], "%u", dwSize ); - check_member_guid( objinst, expect_objects[0], guidType ); - check_member( objinst, expect_objects[0], "%#x", dwOfs ); - check_member( objinst, expect_objects[0], "%#x", dwType ); - check_member( objinst, expect_objects[0], "%#x", dwFlags ); - if (!localized) todo_wine check_member_wstr( objinst, expect_objects[0], tszName ); - check_member( objinst, expect_objects[0], "%u", dwFFMaxForce ); - check_member( objinst, expect_objects[0], "%u", dwFFForceResolution ); - check_member( objinst, expect_objects[0], "%u", wCollectionNumber ); - check_member( objinst, expect_objects[0], "%u", wDesignatorIndex ); - check_member( objinst, expect_objects[0], "%#04x", wUsagePage ); - check_member( objinst, expect_objects[0], "%#04x", wUsage ); - check_member( objinst, expect_objects[0], "%#04x", dwDimension ); - check_member( objinst, expect_objects[0], "%#04x", wExponent ); - check_member( objinst, expect_objects[0], "%u", wReportId ); + check_member( objinst, expect_objects[3], "%u", dwSize ); + check_member_guid( objinst, expect_objects[3], guidType ); + check_member( objinst, expect_objects[3], "%#x", dwOfs ); + check_member( objinst, expect_objects[3], "%#x", dwType ); + check_member( objinst, expect_objects[3], "%#x", dwFlags ); + if (!localized) todo_wine check_member_wstr( objinst, expect_objects[3], tszName ); + check_member( objinst, expect_objects[3], "%u", dwFFMaxForce ); + check_member( objinst, expect_objects[3], "%u", dwFFForceResolution ); + check_member( objinst, expect_objects[3], "%u", wCollectionNumber ); + check_member( objinst, expect_objects[3], "%u", wDesignatorIndex ); + check_member( objinst, expect_objects[3], "%#04x", wUsagePage ); + check_member( objinst, expect_objects[3], "%#04x", wUsage ); + check_member( objinst, expect_objects[3], "%#04x", dwDimension ); + check_member( objinst, expect_objects[3], "%#04x", wExponent ); + check_member( objinst, expect_objects[3], "%u", wReportId ); hr = IDirectInputDevice8_SetEventNotification( device, (HANDLE)0xdeadbeef ); todo_wine -- 2.33.0