Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 119 +++++++++++++++++++++++++++++++++++-- dlls/dinput8/tests/hid.c | 30 ---------- 2 files changed, 113 insertions(+), 36 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 3dc0776a1ec..4ce60e67faf 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -137,6 +137,12 @@ static inline const char *debugstr_hid_caps( struct hid_caps *caps ) return "(unknown type)"; }
+struct extra_caps +{ + LONG deadzone; + LONG saturation; +}; + #define DEVICE_STATE_MAX_SIZE 1024
struct hid_joystick @@ -156,6 +162,7 @@ struct hid_joystick HIDP_LINK_COLLECTION_NODE *collection_nodes; HIDP_BUTTON_CAPS *input_button_caps; HIDP_VALUE_CAPS *input_value_caps; + struct extra_caps *input_extra_caps;
char *input_report_buf; USAGE_AND_PAGE *usages_buf; @@ -424,6 +431,7 @@ static ULONG WINAPI hid_joystick_Release( IDirectInputDevice8W *iface ) { HeapFree( GetProcessHeap(), 0, tmp.usages_buf ); HeapFree( GetProcessHeap(), 0, tmp.input_report_buf ); + HeapFree( GetProcessHeap(), 0, tmp.input_extra_caps ); HeapFree( GetProcessHeap(), 0, tmp.input_value_caps ); HeapFree( GetProcessHeap(), 0, tmp.input_button_caps ); HeapFree( GetProcessHeap(), 0, tmp.collection_nodes ); @@ -519,6 +527,34 @@ static BOOL get_property_prop_range( struct hid_joystick *impl, struct hid_caps return DIENUM_STOP; }
+static BOOL get_property_prop_deadzone( struct hid_joystick *impl, struct hid_caps *caps, + DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + struct extra_caps *extra; + DIPROPDWORD *deadzone = data; + extra = impl->input_extra_caps + (caps->value - impl->input_value_caps); + deadzone->dwData = extra->deadzone; + return DIENUM_STOP; +} + +static BOOL get_property_prop_saturation( struct hid_joystick *impl, struct hid_caps *caps, + DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + struct extra_caps *extra; + DIPROPDWORD *saturation = data; + extra = impl->input_extra_caps + (caps->value - impl->input_value_caps); + saturation->dwData = extra->saturation; + return DIENUM_STOP; +} + +static BOOL get_property_prop_granularity( struct hid_joystick *impl, struct hid_caps *caps, + DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + DIPROPDWORD *granularity = data; + granularity->dwData = 1; + return DIENUM_STOP; +} + static HRESULT WINAPI hid_joystick_GetProperty( IDirectInputDevice8W *iface, const GUID *guid, DIPROPHEADER *header ) { @@ -538,6 +574,24 @@ static HRESULT WINAPI hid_joystick_GetProperty( IDirectInputDevice8W *iface, con if (enum_objects( impl, header, DIDFT_AXIS, get_property_prop_range, header ) == DIENUM_STOP) return DI_OK; return DIERR_NOTFOUND; + case (DWORD_PTR)DIPROP_DEADZONE: + if (header->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM; + if (header->dwHow == DIPH_DEVICE) return DIERR_UNSUPPORTED; + if (enum_objects( impl, header, DIDFT_AXIS, get_property_prop_deadzone, header ) == DIENUM_STOP) + return DI_OK; + return DIERR_NOTFOUND; + case (DWORD_PTR)DIPROP_SATURATION: + if (header->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM; + if (header->dwHow == DIPH_DEVICE) return DIERR_UNSUPPORTED; + if (enum_objects( impl, header, DIDFT_AXIS, get_property_prop_saturation, header ) == DIENUM_STOP) + return DI_OK; + return DIERR_NOTFOUND; + case (DWORD_PTR)DIPROP_GRANULARITY: + if (header->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM; + if (header->dwHow == DIPH_DEVICE) return DIERR_UNSUPPORTED; + if (enum_objects( impl, header, DIDFT_AXIS, get_property_prop_granularity, header ) == DIENUM_STOP) + return DI_OK; + return DIERR_NOTFOUND; case (DWORD_PTR)DIPROP_PRODUCTNAME: { DIPROPSTRING *value = (DIPROPSTRING *)header; @@ -606,6 +660,26 @@ static BOOL set_property_prop_range( struct hid_joystick *impl, struct hid_caps return DIENUM_CONTINUE; }
+static BOOL set_property_prop_deadzone( struct hid_joystick *impl, struct hid_caps *caps, + DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + struct extra_caps *extra; + DIPROPDWORD *deadzone = data; + extra = impl->input_extra_caps + (caps->value - impl->input_value_caps); + extra->deadzone = deadzone->dwData; + return DIENUM_CONTINUE; +} + +static BOOL set_property_prop_saturation( struct hid_joystick *impl, struct hid_caps *caps, + DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + struct extra_caps *extra; + DIPROPDWORD *saturation = data; + extra = impl->input_extra_caps + (caps->value - impl->input_value_caps); + extra->saturation = saturation->dwData; + return DIENUM_CONTINUE; +} + static HRESULT WINAPI hid_joystick_SetProperty( IDirectInputDevice8W *iface, const GUID *guid, const DIPROPHEADER *header ) { @@ -627,6 +701,22 @@ static HRESULT WINAPI hid_joystick_SetProperty( IDirectInputDevice8W *iface, con enum_objects( impl, header, DIDFT_AXIS, set_property_prop_range, (void *)header ); return DI_OK; } + case (DWORD_PTR)DIPROP_DEADZONE: + { + DIPROPDWORD *value = (DIPROPDWORD *)header; + if (header->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM; + if (value->dwData > 10000) return DIERR_INVALIDPARAM; + enum_objects( impl, header, DIDFT_AXIS, set_property_prop_deadzone, (void *)header ); + return DI_OK; + } + case (DWORD_PTR)DIPROP_SATURATION: + { + DIPROPDWORD *value = (DIPROPDWORD *)header; + if (header->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM; + if (value->dwData > 10000) return DIERR_INVALIDPARAM; + enum_objects( impl, header, DIDFT_AXIS, set_property_prop_saturation, (void *)header ); + return DI_OK; + } case (DWORD_PTR)DIPROP_FFLOAD: case (DWORD_PTR)DIPROP_GRANULARITY: case (DWORD_PTR)DIPROP_VIDPID: @@ -859,7 +949,7 @@ static LONG scale_value( ULONG value, const HIDP_VALUE_CAPS *caps, LONG min, LON return min + MulDiv( tmp - caps->LogicalMin, max - min, caps->LogicalMax - caps->LogicalMin ); }
-static LONG scale_axis_value( ULONG value, const HIDP_VALUE_CAPS *caps ) +static LONG scale_axis_value( ULONG value, const HIDP_VALUE_CAPS *caps, struct extra_caps *extra ) { LONG tmp = sign_extend( value, caps ), log_ctr, log_min, log_max, phy_ctr, phy_min, phy_max; ULONG bit_max = (1 << caps->BitSize) - 1; @@ -879,14 +969,14 @@ static LONG scale_axis_value( ULONG value, const HIDP_VALUE_CAPS *caps ) tmp -= log_ctr; if (tmp <= 0) { - log_max = 0; - log_min -= log_ctr; + log_max = MulDiv( log_min - log_ctr, extra->deadzone, 10000 ); + log_min = MulDiv( log_min - log_ctr, extra->saturation, 10000 ); phy_max = phy_ctr; } else { - log_min = 0; - log_max -= log_ctr; + log_min = MulDiv( log_max - log_ctr, extra->deadzone, 10000 ); + log_max = MulDiv( log_max - log_ctr, extra->saturation, 10000 ); phy_min = phy_ctr; }
@@ -903,14 +993,16 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_caps struct parse_device_state_params *params = data; char *report_buf = impl->input_report_buf; HIDP_VALUE_CAPS *value_caps = caps->value; + struct extra_caps *extra; LONG old_value, value; NTSTATUS status;
+ extra = impl->input_extra_caps + (value_caps - impl->input_value_caps); status = HidP_GetUsageValue( HidP_Input, instance->wUsagePage, 0, instance->wUsage, &logical_value, impl->preparsed, report_buf, report_len ); if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_GetUsageValue %04x:%04x returned %#x\n", instance->wUsagePage, instance->wUsage, status ); - if (instance->dwType & DIDFT_AXIS) value = scale_axis_value( logical_value, value_caps ); + if (instance->dwType & DIDFT_AXIS) value = scale_axis_value( logical_value, value_caps, extra ); else value = scale_value( logical_value, value_caps, value_caps->PhysicalMin, value_caps->PhysicalMax );
old_value = *(LONG *)(params->old_state + instance->dwOfs); @@ -1305,9 +1397,19 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID .dwHow = DIPH_DEVICE, }, }; + DIPROPDWORD saturation = + { + .diph = + { + .dwSize = sizeof(DIPROPDWORD), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_DEVICE, + }, + }; HIDD_ATTRIBUTES attrs = {.Size = sizeof(attrs)}; HIDP_LINK_COLLECTION_NODE *nodes; struct hid_joystick *impl = NULL; + struct extra_caps *extra; DIDATAFORMAT *format = NULL; HIDP_BUTTON_CAPS *buttons; HIDP_VALUE_CAPS *values; @@ -1356,6 +1458,9 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID size = impl->caps.NumberInputValueCaps * sizeof(HIDP_VALUE_CAPS); if (!(values = HeapAlloc( GetProcessHeap(), 0, size ))) goto failed; impl->input_value_caps = values; + size = impl->caps.NumberInputValueCaps * sizeof(struct extra_caps); + if (!(extra = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size ))) goto failed; + impl->input_extra_caps = extra;
size = impl->caps.InputReportByteLength; if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size ))) goto failed; @@ -1400,6 +1505,8 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID enum_objects( impl, &range.diph, DIDFT_AXIS, set_property_prop_range, &range ); range.lMax = 36000; enum_objects( impl, &range.diph, DIDFT_POV, set_property_prop_range, &range ); + saturation.dwData = 10000; + enum_objects( impl, &range.diph, DIDFT_AXIS, set_property_prop_saturation, &saturation );
*out = &impl->base.IDirectInputDevice8W_iface; return DI_OK; diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index ec5dffe70f5..07505797eb1 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3867,16 +3867,13 @@ static void test_simple_joystick(void) todo_wine ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_AUTOCENTER returned %#x\n", hr ); hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph ); - todo_wine ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_DEADZONE returned %#x\n", hr ); hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph ); todo_wine ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_FFLOAD returned %#x\n", hr ); hr = IDirectInputDevice8_GetProperty( device, DIPROP_GRANULARITY, &prop_dword.diph ); - todo_wine ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_GRANULARITY returned %#x\n", hr ); hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph ); - todo_wine ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_SATURATION returned %#x\n", hr ); hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph ); ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_RANGE returned %#x\n", hr ); @@ -3885,21 +3882,15 @@ static void test_simple_joystick(void) prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC ); prop_dword.dwData = 0xdeadbeef; hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_DEADZONE returned %#x\n", hr ); - todo_wine ok( prop_dword.dwData == 0, "got %u expected %u\n", prop_dword.dwData, 0 ); prop_dword.dwData = 0xdeadbeef; hr = IDirectInputDevice8_GetProperty( device, DIPROP_GRANULARITY, &prop_dword.diph ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_GRANULARITY returned %#x\n", hr ); - todo_wine ok( prop_dword.dwData == 1, "got %u expected %u\n", prop_dword.dwData, 1 ); prop_dword.dwData = 0xdeadbeef; hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_SATURATION returned %#x\n", hr ); - todo_wine ok( prop_dword.dwData == 10000, "got %u expected %u\n", prop_dword.dwData, 10000 );
prop_range.diph.dwHow = DIPH_BYUSAGE; @@ -4368,67 +4359,51 @@ static void test_simple_joystick(void) prop_dword.diph.dwObj = 0; prop_dword.dwData = 10001; hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_DEADZONE returned %#x\n", hr ); hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_SATURATION returned %#x\n", hr ); prop_dword.dwData = 1000; hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_DEADZONE returned %#x\n", hr ); prop_dword.dwData = 6000; hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_SATURATION returned %#x\n", hr );
hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph ); - todo_wine ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_DEADZONE returned %#x\n", hr ); hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph ); - todo_wine ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_SATURATION returned %#x\n", hr );
prop_dword.diph.dwHow = DIPH_BYUSAGE; prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC ); prop_dword.dwData = 2000; hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_DEADZONE returned %#x\n", hr ); ok( prop_dword.dwData == 2000, "got %u expected %u\n", prop_dword.dwData, 2000 ); prop_dword.dwData = 7000; hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_SATURATION returned %#x\n", hr );
prop_dword.diph.dwHow = DIPH_BYUSAGE; prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC ); prop_dword.dwData = 0xdeadbeef; hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_DEADZONE returned %#x\n", hr ); - todo_wine ok( prop_dword.dwData == 2000, "got %u expected %u\n", prop_dword.dwData, 2000 ); prop_dword.dwData = 0xdeadbeef; hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_SATURATION returned %#x\n", hr ); - todo_wine ok( prop_dword.dwData == 7000, "got %u expected %u\n", prop_dword.dwData, 7000 );
prop_dword.diph.dwHow = DIPH_BYUSAGE; prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_Y, HID_USAGE_PAGE_GENERIC ); prop_dword.dwData = 0xdeadbeef; hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_DEADZONE returned %#x\n", hr ); - todo_wine ok( prop_dword.dwData == 1000, "got %u expected %u\n", prop_dword.dwData, 1000 ); prop_dword.dwData = 0xdeadbeef; hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_SATURATION returned %#x\n", hr ); - todo_wine ok( prop_dword.dwData == 6000, "got %u expected %u\n", prop_dword.dwData, 6000 );
for (i = 0; i < ARRAY_SIZE(injected_input); ++i) @@ -4439,9 +4414,7 @@ static void test_simple_joystick(void) if (broken( state.lX == -10750 )) win_skip( "Ignoring 32-bit rounding\n" ); else { - todo_wine_if( i == 3 || i == 4 ) check_member( state, expect_state_abs[i], "%d", lX ); - todo_wine_if( i == 3 || i == 4 ) check_member( state, expect_state_abs[i], "%d", lY ); } check_member( state, expect_state_abs[i], "%d", lZ ); @@ -4465,7 +4438,6 @@ static void test_simple_joystick(void) ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr ); winetest_push_context( "state[%d]", i ); check_member( state, expect_state_abs[i], "%d", lX ); - todo_wine check_member( state, expect_state_abs[i], "%d", lY ); check_member( state, expect_state_abs[i], "%d", lZ ); check_member( state, expect_state_abs[i], "%d", lRx ); @@ -4547,11 +4519,9 @@ static void test_simple_joystick(void) ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_CALIBRATION returned %#x\n", hr ); prop_dword.dwData = 0xdeadbeef; hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_DEADZONE returned %#x\n", hr ); prop_dword.dwData = 0xdeadbeef; hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_SATURATION returned %#x\n", hr );
for (i = 0; i < ARRAY_SIZE(injected_input); ++i)