Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 83 ++++++++++++++------------------------ 1 file changed, 31 insertions(+), 52 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 30e63c16cb8..6eb1a98c13b 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -136,10 +136,11 @@ static inline const char *debugstr_hid_caps( struct hid_caps *caps ) return "(unknown type)"; }
+#define DEVICE_STATE_MAX_SIZE 1024 + struct hid_joystick { IDirectInputDeviceImpl base; - DIJOYSTATE2 state;
HANDLE device; OVERLAPPED read_ovl; @@ -160,6 +161,7 @@ struct hid_joystick ULONG usages_count;
BYTE device_state_report_id; + BYTE device_state[DEVICE_STATE_MAX_SIZE]; };
static inline struct hid_joystick *impl_from_IDirectInputDevice8W( IDirectInputDevice8W *iface ) @@ -660,7 +662,7 @@ static HRESULT WINAPI hid_joystick_GetDeviceState( IDirectInputDevice8W *iface,
EnterCriticalSection( &impl->base.crit ); if (!impl->base.acquired) hr = DIERR_NOTACQUIRED; - else fill_DataFormat( ptr, len, &impl->state, &impl->base.data_format ); + else fill_DataFormat( ptr, len, impl->device_state, &impl->base.data_format ); LeaveCriticalSection( &impl->base.crit );
return hr; @@ -796,7 +798,8 @@ static const IDirectInputDevice8WVtbl hid_joystick_vtbl =
struct parse_device_state_params { - DIJOYSTATE2 old_state; + BYTE old_state[DEVICE_STATE_MAX_SIZE]; + BYTE buttons[128]; DWORD time; DWORD seq; }; @@ -806,12 +809,18 @@ static BOOL check_device_state_button( struct hid_joystick *impl, struct hid_cap { IDirectInputDevice8W *iface = &impl->base.IDirectInputDevice8W_iface; struct parse_device_state_params *params = data; - DWORD i = DIDFT_GETINSTANCE( instance->dwType ); + BYTE old_value, value;
if (!(instance->dwType & DIDFT_BUTTON)) FIXME( "unexpected object type %#x, expected DIDFT_BUTTON\n", instance->dwType ); - else if (params->old_state.rgbButtons[i] != impl->state.rgbButtons[i]) - queue_event( iface, instance->dwType, impl->state.rgbButtons[i], params->time, params->seq ); + else + { + value = params->buttons[instance->wUsage - 1]; + old_value = params->old_state[instance->dwOfs]; + impl->device_state[instance->dwOfs] = value; + if (old_value != value) + queue_event( iface, instance->dwType, value, params->time, params->seq ); + }
return DIENUM_CONTINUE; } @@ -842,8 +851,8 @@ 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; + LONG old_value, value; NTSTATUS status; - LONG value;
if (!(instance->dwType & (DIDFT_POV | DIDFT_AXIS))) FIXME( "unexpected object type %#x, expected DIDFT_POV | DIDFT_AXIS\n", instance->dwType ); @@ -855,47 +864,10 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_caps instance->wUsagePage, instance->wUsage, status ); value = scale_value( logical_value, value_caps, value_caps->PhysicalMin, value_caps->PhysicalMax );
- switch (instance->dwOfs) - { - case DIJOFS_X: - if (impl->state.lX == value) break; - impl->state.lX = value; - queue_event( iface, instance->dwType, value, params->time, params->seq ); - break; - case DIJOFS_Y: - if (impl->state.lY == value) break; - impl->state.lY = value; - queue_event( iface, instance->dwType, value, params->time, params->seq ); - break; - case DIJOFS_Z: - if (impl->state.lZ == value) break; - impl->state.lZ = value; - queue_event( iface, instance->dwType, value, params->time, params->seq ); - break; - case DIJOFS_RX: - if (impl->state.lRx == value) break; - impl->state.lRx = value; + old_value = *(LONG *)(params->old_state + instance->dwOfs); + *(LONG *)(impl->device_state + instance->dwOfs) = value; + if (old_value != value) queue_event( iface, instance->dwType, value, params->time, params->seq ); - break; - case DIJOFS_RY: - if (impl->state.lRy == value) break; - impl->state.lRy = value; - queue_event( iface, instance->dwType, value, params->time, params->seq ); - break; - case DIJOFS_RZ: - if (impl->state.lRz == value) break; - impl->state.lRz = value; - queue_event( iface, instance->dwType, value, params->time, params->seq ); - break; - case DIJOFS_POV( 0 ): - if (impl->state.rgdwPOV[0] == value) break; - impl->state.rgdwPOV[0] = value; - queue_event( iface, instance->dwType, value, params->time, params->seq ); - break; - default: - FIXME( "unimplemented offset %#x.\n", instance->dwOfs ); - break; - } }
return DIENUM_CONTINUE; @@ -911,6 +883,7 @@ static HRESULT hid_joystick_read_state( IDirectInputDevice8W *iface ) }; struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); ULONG i, count, report_len = impl->caps.InputReportByteLength; + DIDATAFORMAT *format = impl->base.data_format.wine_df; struct parse_device_state_params params = {0}; char *report_buf = impl->input_report_buf; USAGE_AND_PAGE *usages; @@ -944,11 +917,11 @@ static HRESULT hid_joystick_read_state( IDirectInputDevice8W *iface )
if (report_buf[0] == impl->device_state_report_id) { - params.old_state = impl->state; params.time = GetCurrentTime(); params.seq = impl->base.dinput->evsequence++; + memcpy( params.old_state, impl->device_state, format->dwDataSize ); + memset( impl->device_state, 0, format->dwDataSize );
- memset( impl->state.rgbButtons, 0, sizeof(impl->state.rgbButtons) ); while (count--) { usages = impl->usages_buf + count; @@ -957,12 +930,12 @@ static HRESULT hid_joystick_read_state( IDirectInputDevice8W *iface ) else if (usages->Usage >= 128) FIXME( "ignoring extraneous button %d.\n", usages->Usage ); else - impl->state.rgbButtons[usages->Usage - 1] = 0x80; + params.buttons[usages->Usage - 1] = 0x80; }
enum_value_objects( impl, &filter, DIDFT_ALL, read_device_state_value, ¶ms ); enum_button_objects( impl, &filter, DIDFT_ALL, check_device_state_button, ¶ms ); - if (memcmp( ¶ms.old_state, &impl->state, sizeof(impl->state) ) && impl->base.hEvent) + if (impl->base.hEvent && memcmp( ¶ms.old_state, impl->device_state, format->dwDataSize )) SetEvent( impl->base.hEvent ); }
@@ -1231,6 +1204,7 @@ static BOOL init_objects( struct hid_joystick *impl, struct hid_caps *caps, DIDATAFORMAT *format = impl->base.data_format.wine_df;
format->dwNumObjs++; + format->dwDataSize = max( format->dwDataSize, instance->dwOfs + sizeof(LONG) ); if (instance->dwType & DIDFT_BUTTON) impl->dev_caps.dwButtons++; if (instance->dwType & DIDFT_AXIS) impl->dev_caps.dwAxes++; if (instance->dwType & DIDFT_POV) impl->dev_caps.dwPOVs++; @@ -1360,12 +1334,17 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID enum_button_objects( impl, &filter, DIDFT_ALL, init_objects, NULL );
format = impl->base.data_format.wine_df; + if (format->dwDataSize > DEVICE_STATE_MAX_SIZE) + { + FIXME( "unable to create device, state is too large\n" ); + goto failed; + } + size = format->dwNumObjs * sizeof(*format->rgodf); if (!(format->rgodf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size ))) goto failed; format->dwSize = sizeof(*format); format->dwObjSize = sizeof(*format->rgodf); format->dwFlags = DIDF_ABSAXIS; - format->dwDataSize = sizeof(impl->state);
index = 0; enum_value_objects( impl, &filter, DIDFT_ALL, init_data_format, &index );
Instead of using individual helpers.
The force-feedback EnumObjects test shows that we should enumerate the output objects in their original order in the HID report descriptor, not depending on their button/value nature.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 128 +++++++++++++++---------------------- dlls/dinput8/tests/hid.c | 1 - 2 files changed, 51 insertions(+), 78 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 6eb1a98c13b..06537e9fd25 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -231,13 +231,13 @@ static void set_axis_type( DIDEVICEOBJECTINSTANCEW *instance, BOOL *seen, DWORD seen[i] = TRUE; }
-static BOOL enum_value_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, - DWORD flags, enum_object_callback callback, void *data ) +static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, DWORD flags, + enum_object_callback callback, void *data ) { DIDEVICEOBJECTINSTANCEW instance = {.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW)}; - struct hid_caps caps = {.type = VALUE_CAPS}; + DWORD collection = 0, axis = 0, button = 0, pov = 0, i, j; BOOL ret, seen_axis[6] = {0}; - DWORD axis = 0, pov = 0, i; + struct hid_caps caps = {0};
for (i = 0; i < impl->caps.NumberInputValueCaps; ++i) { @@ -328,17 +328,6 @@ static BOOL enum_value_objects( struct hid_joystick *impl, const DIPROPHEADER *f } }
- return DIENUM_CONTINUE; -} - -static BOOL enum_button_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, - DWORD flags, enum_object_callback callback, void *data ) -{ - DIDEVICEOBJECTINSTANCEW instance = {.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW)}; - struct hid_caps caps = {.type = BUTTON_CAPS}; - DWORD button = 0, i, j; - BOOL ret; - for (i = 0; i < impl->caps.NumberInputButtonCaps; ++i) { caps.button = impl->input_button_caps + i; @@ -384,17 +373,6 @@ static BOOL enum_button_objects( struct hid_joystick *impl, const DIPROPHEADER * } }
- return DIENUM_CONTINUE; -} - -static BOOL enum_collections_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, DWORD flags, - enum_object_callback callback, void *data ) -{ - DIDEVICEOBJECTINSTANCEW instance = {.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW)}; - struct hid_caps caps = {.type = LINK_COLLECTION_NODE}; - DWORD collection = 0, i; - BOOL ret; - for (i = 0; i < impl->caps.NumberLinkCollectionNodes; ++i) { caps.node = impl->collection_nodes + i; @@ -489,14 +467,31 @@ static HRESULT WINAPI hid_joystick_EnumObjects( IDirectInputDevice8W *iface, LPD TRACE( "iface %p, callback %p, context %p, flags %#x.\n", iface, callback, context, flags );
if (!callback) return DIERR_INVALIDPARAM; + if (flags & ~(DIDFT_AXIS | DIDFT_AXIS | DIDFT_BUTTON | DIDFT_NODATA | DIDFT_COLLECTION)) + return DIERR_INVALIDPARAM;
- ret = enum_value_objects( impl, &filter, flags, enum_objects_callback, ¶ms ); - if (ret != DIENUM_CONTINUE) return S_OK; - ret = enum_button_objects( impl, &filter, flags, enum_objects_callback, ¶ms ); - if (ret != DIENUM_CONTINUE) return S_OK; - enum_collections_objects( impl, &filter, flags, enum_objects_callback, ¶ms ); + if (flags == DIDFT_ALL || (flags & DIDFT_AXIS)) + { + ret = enum_objects( impl, &filter, DIDFT_AXIS, enum_objects_callback, ¶ms ); + if (ret != DIENUM_CONTINUE) return DI_OK; + } + if (flags == DIDFT_ALL || (flags & DIDFT_POV)) + { + ret = enum_objects( impl, &filter, DIDFT_POV, enum_objects_callback, ¶ms ); + if (ret != DIENUM_CONTINUE) return DI_OK; + } + if (flags == DIDFT_ALL || (flags & DIDFT_BUTTON)) + { + ret = enum_objects( impl, &filter, DIDFT_BUTTON, enum_objects_callback, ¶ms ); + if (ret != DIENUM_CONTINUE) return DI_OK; + } + if (flags == DIDFT_ALL || (flags & (DIDFT_NODATA | DIDFT_COLLECTION))) + { + ret = enum_objects( impl, &filter, DIDFT_NODATA, enum_objects_callback, ¶ms ); + if (ret != DIENUM_CONTINUE) return DI_OK; + }
- return S_OK; + return DI_OK; }
static BOOL get_property_prop_range( struct hid_joystick *impl, struct hid_caps *caps, @@ -524,7 +519,7 @@ static HRESULT WINAPI hid_joystick_GetProperty( IDirectInputDevice8W *iface, con { case (DWORD_PTR)DIPROP_RANGE: if (header->dwSize != sizeof(DIPROPRANGE)) return DIERR_INVALIDPARAM; - enum_value_objects( impl, header, DIDFT_AXIS, get_property_prop_range, header ); + enum_objects( impl, header, DIDFT_AXIS, get_property_prop_range, header ); return DI_OK; case (DWORD_PTR)DIPROP_PRODUCTNAME: { @@ -597,7 +592,7 @@ static HRESULT WINAPI hid_joystick_SetProperty( IDirectInputDevice8W *iface, con { case (DWORD_PTR)DIPROP_RANGE: if (header->dwSize != sizeof(DIPROPRANGE)) return DIERR_INVALIDPARAM; - enum_value_objects( impl, header, DIDFT_AXIS, set_property_prop_range, (void *)header ); + enum_objects( impl, header, DIDFT_AXIS, set_property_prop_range, (void *)header ); return DI_OK; case (DWORD_PTR)DIPROP_FFLOAD: case (DWORD_PTR)DIPROP_GRANULARITY: @@ -687,7 +682,6 @@ static HRESULT WINAPI hid_joystick_GetObjectInfo( IDirectInputDevice8W *iface, D .dwHow = how, .dwObj = obj }; - BOOL ret;
TRACE( "iface %p, instance %p, obj %#x, how %#x.\n", iface, instance, obj, how );
@@ -696,12 +690,7 @@ static HRESULT WINAPI hid_joystick_GetObjectInfo( IDirectInputDevice8W *iface, D instance->dwSize != sizeof(DIDEVICEOBJECTINSTANCEW)) return DIERR_INVALIDPARAM;
- ret = enum_value_objects( impl, &filter, DIDFT_ALL, get_object_info, instance ); - if (ret != DIENUM_CONTINUE) return S_OK; - ret = enum_button_objects( impl, &filter, DIDFT_ALL, get_object_info, instance ); - if (ret != DIENUM_CONTINUE) return S_OK; - enum_collections_objects( impl, &filter, DIDFT_ALL, get_object_info, instance ); - + enum_objects( impl, &filter, DIDFT_ALL, get_object_info, instance ); return S_OK; }
@@ -811,16 +800,11 @@ static BOOL check_device_state_button( struct hid_joystick *impl, struct hid_cap struct parse_device_state_params *params = data; BYTE old_value, value;
- if (!(instance->dwType & DIDFT_BUTTON)) - FIXME( "unexpected object type %#x, expected DIDFT_BUTTON\n", instance->dwType ); - else - { - value = params->buttons[instance->wUsage - 1]; - old_value = params->old_state[instance->dwOfs]; - impl->device_state[instance->dwOfs] = value; - if (old_value != value) - queue_event( iface, instance->dwType, value, params->time, params->seq ); - } + value = params->buttons[instance->wUsage - 1]; + old_value = params->old_state[instance->dwOfs]; + impl->device_state[instance->dwOfs] = value; + if (old_value != value) + queue_event( iface, instance->dwType, value, params->time, params->seq );
return DIENUM_CONTINUE; } @@ -854,21 +838,16 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_caps LONG old_value, value; NTSTATUS status;
- if (!(instance->dwType & (DIDFT_POV | DIDFT_AXIS))) - FIXME( "unexpected object type %#x, expected DIDFT_POV | DIDFT_AXIS\n", instance->dwType ); - else - { - 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 ); - value = scale_value( logical_value, value_caps, value_caps->PhysicalMin, value_caps->PhysicalMax ); - - old_value = *(LONG *)(params->old_state + instance->dwOfs); - *(LONG *)(impl->device_state + instance->dwOfs) = value; - if (old_value != value) - queue_event( iface, instance->dwType, value, params->time, params->seq ); - } + 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 ); + value = scale_value( logical_value, value_caps, value_caps->PhysicalMin, value_caps->PhysicalMax ); + + old_value = *(LONG *)(params->old_state + instance->dwOfs); + *(LONG *)(impl->device_state + instance->dwOfs) = value; + if (old_value != value) + queue_event( iface, instance->dwType, value, params->time, params->seq );
return DIENUM_CONTINUE; } @@ -933,8 +912,8 @@ static HRESULT hid_joystick_read_state( IDirectInputDevice8W *iface ) params.buttons[usages->Usage - 1] = 0x80; }
- enum_value_objects( impl, &filter, DIDFT_ALL, read_device_state_value, ¶ms ); - enum_button_objects( impl, &filter, DIDFT_ALL, check_device_state_button, ¶ms ); + enum_objects( impl, &filter, DIDFT_AXIS | DIDFT_POV, read_device_state_value, ¶ms ); + enum_objects( impl, &filter, DIDFT_BUTTON, check_device_state_button, ¶ms ); if (impl->base.hEvent && memcmp( ¶ms.old_state, impl->device_state, format->dwDataSize )) SetEvent( impl->base.hEvent ); } @@ -1328,10 +1307,7 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID &impl->caps.NumberInputValueCaps, impl->preparsed ); if (status != HIDP_STATUS_SUCCESS && status != HIDP_STATUS_USAGE_NOT_FOUND) goto failed;
- /* enumerate collections first, so we can find report collections */ - enum_collections_objects( impl, &filter, DIDFT_ALL, init_objects, NULL ); - enum_value_objects( impl, &filter, DIDFT_ALL, init_objects, NULL ); - enum_button_objects( impl, &filter, DIDFT_ALL, init_objects, NULL ); + enum_objects( impl, &filter, DIDFT_ALL, init_objects, NULL );
format = impl->base.data_format.wine_df; if (format->dwDataSize > DEVICE_STATE_MAX_SIZE) @@ -1347,16 +1323,14 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID format->dwFlags = DIDF_ABSAXIS;
index = 0; - enum_value_objects( impl, &filter, DIDFT_ALL, init_data_format, &index ); - enum_button_objects( impl, &filter, DIDFT_ALL, init_data_format, &index ); - enum_collections_objects( impl, &filter, DIDFT_ALL, init_data_format, &index ); + enum_objects( impl, &filter, DIDFT_ALL, init_data_format, &index );
_dump_DIDATAFORMAT( impl->base.data_format.wine_df );
range.lMax = 65535; - enum_value_objects( impl, &range.diph, DIDFT_AXIS, set_property_prop_range, &range ); + enum_objects( impl, &range.diph, DIDFT_AXIS, set_property_prop_range, &range ); range.lMax = 36000; - enum_value_objects( impl, &range.diph, DIDFT_POV, set_property_prop_range, &range ); + enum_objects( impl, &range.diph, DIDFT_POV, set_property_prop_range, &range );
*out = &impl->base.IDirectInputDevice8W_iface; return DI_OK; diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 14198f2d876..d73d4dabfff 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3943,7 +3943,6 @@ static void test_simple_joystick(void) hr = IDirectInputDevice8_EnumObjects( device, NULL, NULL, DIDFT_ALL ); ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_EnumObjects returned %#x\n", hr ); hr = IDirectInputDevice8_EnumObjects( device, check_object_count, &res, 0x20 ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_EnumObjects returned %#x\n", hr ); res = 0; hr = IDirectInputDevice8_EnumObjects( device, check_object_count, &res, DIDFT_AXIS | DIDFT_PSHBUTTON );
When no object matched the enumeration or when DIPH_DEVICE is used.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 7 +++++-- dlls/dinput8/tests/hid.c | 4 ---- 2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 06537e9fd25..3535e533029 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -682,6 +682,7 @@ static HRESULT WINAPI hid_joystick_GetObjectInfo( IDirectInputDevice8W *iface, D .dwHow = how, .dwObj = obj }; + BOOL ret;
TRACE( "iface %p, instance %p, obj %#x, how %#x.\n", iface, instance, obj, how );
@@ -689,9 +690,11 @@ static HRESULT WINAPI hid_joystick_GetObjectInfo( IDirectInputDevice8W *iface, D if (instance->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3W) && instance->dwSize != sizeof(DIDEVICEOBJECTINSTANCEW)) return DIERR_INVALIDPARAM; + if (how == DIPH_DEVICE) return DIERR_INVALIDPARAM;
- enum_objects( impl, &filter, DIDFT_ALL, get_object_info, instance ); - return S_OK; + ret = enum_objects( impl, &filter, DIDFT_ALL, get_object_info, instance ); + if (ret != DIENUM_CONTINUE) return DI_OK; + return DIERR_NOTFOUND; }
static HRESULT WINAPI hid_joystick_GetDeviceInfo( IDirectInputDevice8W *iface, DIDEVICEINSTANCEW *instance ) diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index d73d4dabfff..c7f5b82c187 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3959,12 +3959,10 @@ static void test_simple_joystick(void) ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetObjectInfo returned: %#x\n", hr ); objinst.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW); hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0, DIPH_DEVICE ); - todo_wine ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetObjectInfo returned: %#x\n", hr );
res = MAKELONG( HID_USAGE_GENERIC_Z, HID_USAGE_PAGE_GENERIC ); hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYUSAGE ); - todo_wine ok( hr == DIERR_NOTFOUND, "IDirectInputDevice8_GetObjectInfo returned: %#x\n", hr ); res = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC ); hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYUSAGE ); @@ -3988,14 +3986,12 @@ static void test_simple_joystick(void) check_member( objinst, expect_objects[1], "%u", wReportId );
hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0x14, DIPH_BYOFFSET ); - todo_wine ok( hr == DIERR_NOTFOUND, "IDirectInputDevice8_GetObjectInfo returned: %#x\n", hr ); hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0, DIPH_BYOFFSET ); todo_wine ok( hr == DIERR_NOTFOUND, "IDirectInputDevice8_GetObjectInfo returned: %#x\n", hr ); res = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 3 ); hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYID ); - todo_wine ok( hr == DIERR_NOTFOUND, "IDirectInputDevice8_GetObjectInfo returned: %#x\n", hr ); res = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 1 ); hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYID );
Instead of hardcoded DIJOYSTATE2 offsets.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 36 ++++++++++++++++++++++++------------ dlls/dinput8/tests/hid.c | 1 - 2 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 3535e533029..28539776c36 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -231,14 +231,26 @@ static void set_axis_type( DIDEVICEOBJECTINSTANCEW *instance, BOOL *seen, DWORD seen[i] = TRUE; }
-static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, DWORD flags, +static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, DWORD flags, enum_object_callback callback, void *data ) { DIDEVICEOBJECTINSTANCEW instance = {.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW)}; DWORD collection = 0, axis = 0, button = 0, pov = 0, i, j; + DIDATAFORMAT *format = impl->base.data_format.wine_df; + int *offsets = impl->base.data_format.offsets; + DIPROPHEADER filter = *header; BOOL ret, seen_axis[6] = {0}; struct hid_caps caps = {0};
+ if (filter.dwHow == DIPH_BYOFFSET) + { + if (!offsets) return DIENUM_CONTINUE; + for (i = 0; i < format->dwNumObjs; ++i) + if (offsets[i] == filter.dwObj) break; + if (i == format->dwNumObjs) return DIENUM_CONTINUE; + filter.dwObj = format->rgodf[i].dwOfs; + } + for (i = 0; i < impl->caps.NumberInputValueCaps; ++i) { caps.value = impl->input_value_caps + i; @@ -267,14 +279,14 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, instance.dwOfs = DIJOFS_X; set_axis_type( &instance, seen_axis, 0, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; - ret = enum_object( impl, filter, flags, callback, &caps, &instance, data ); + ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; case HID_USAGE_GENERIC_Y: instance.dwOfs = DIJOFS_Y; set_axis_type( &instance, seen_axis, 1, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; - ret = enum_object( impl, filter, flags, callback, &caps, &instance, data ); + ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; case HID_USAGE_GENERIC_Z: @@ -282,28 +294,28 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, instance.dwOfs = DIJOFS_Z; set_axis_type( &instance, seen_axis, 2, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; - ret = enum_object( impl, filter, flags, callback, &caps, &instance, data ); + ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; case HID_USAGE_GENERIC_RX: instance.dwOfs = DIJOFS_RX; set_axis_type( &instance, seen_axis, 3, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; - ret = enum_object( impl, filter, flags, callback, &caps, &instance, data ); + ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; case HID_USAGE_GENERIC_RY: instance.dwOfs = DIJOFS_RY; set_axis_type( &instance, seen_axis, 4, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; - ret = enum_object( impl, filter, flags, callback, &caps, &instance, data ); + ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; case HID_USAGE_GENERIC_RZ: instance.dwOfs = DIJOFS_RZ; set_axis_type( &instance, seen_axis, 5, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; - ret = enum_object( impl, filter, flags, callback, &caps, &instance, data ); + ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; case HID_USAGE_GENERIC_DIAL: @@ -311,14 +323,14 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, instance.dwOfs = DIJOFS_SLIDER( 0 ); instance.dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 6 + axis++ ); instance.dwFlags = DIDOI_ASPECTPOSITION; - ret = enum_object( impl, filter, flags, callback, &caps, &instance, data ); + ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; case HID_USAGE_GENERIC_HATSWITCH: instance.dwOfs = DIJOFS_POV( 0 ); instance.dwType = DIDFT_POV | DIDFT_MAKEINSTANCE( pov++ ); instance.dwFlags = 0; - ret = enum_object( impl, filter, flags, callback, &caps, &instance, data ); + ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; default: @@ -352,7 +364,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, instance.guidType = *object_usage_to_guid( instance.wUsagePage, instance.wUsage ); instance.wReportId = caps.button->ReportID; instance.wCollectionNumber = caps.button->LinkCollection; - ret = enum_object( impl, filter, flags, callback, &caps, &instance, data ); + ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; } } @@ -368,7 +380,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, instance.guidType = *object_usage_to_guid( instance.wUsagePage, instance.wUsage ); instance.wReportId = caps.button->ReportID; instance.wCollectionNumber = caps.button->LinkCollection; - ret = enum_object( impl, filter, flags, callback, &caps, &instance, data ); + ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; } } @@ -391,7 +403,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, instance.guidType = *object_usage_to_guid( instance.wUsagePage, instance.wUsage ); instance.wReportId = 0; instance.wCollectionNumber = caps.node->Parent; - ret = enum_object( impl, filter, flags, callback, &caps, &instance, data ); + ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; } } diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index c7f5b82c187..5031c4429af 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3988,7 +3988,6 @@ static void test_simple_joystick(void) hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0x14, DIPH_BYOFFSET ); ok( hr == DIERR_NOTFOUND, "IDirectInputDevice8_GetObjectInfo returned: %#x\n", hr ); hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0, DIPH_BYOFFSET ); - todo_wine ok( hr == DIERR_NOTFOUND, "IDirectInputDevice8_GetObjectInfo returned: %#x\n", hr ); res = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 3 ); hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYID );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=98814
Your paranoid android.
=== w8 (32 bit report) ===
dinput8: hid.c:578: Test failed: unexpected error 1058
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 24 +++++++++++++----------- dlls/dinput8/tests/hid.c | 13 +------------ 2 files changed, 14 insertions(+), 23 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 28539776c36..460bd848836 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -235,7 +235,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, enum_object_callback callback, void *data ) { DIDEVICEOBJECTINSTANCEW instance = {.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW)}; - DWORD collection = 0, axis = 0, button = 0, pov = 0, i, j; + DWORD collection = 0, axis = 0, button = 0, pov = 0, value_ofs = 0, button_ofs = 0, i, j; DIDATAFORMAT *format = impl->base.data_format.wine_df; int *offsets = impl->base.data_format.offsets; DIPROPHEADER filter = *header; @@ -251,6 +251,10 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, filter.dwObj = format->rgodf[i].dwOfs; }
+ button_ofs += impl->caps.NumberInputValueCaps * sizeof(LONG); + button_ofs += impl->caps.NumberOutputValueCaps * sizeof(LONG); + button_ofs += impl->caps.NumberFeatureValueCaps * sizeof(LONG); + for (i = 0; i < impl->caps.NumberInputValueCaps; ++i) { caps.value = impl->input_value_caps + i; @@ -267,6 +271,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, TRACE( "Ignoring input value %s, usage page not implemented.\n", debugstr_hid_caps( &caps ) ); else { + instance.dwOfs = value_ofs; instance.wUsagePage = caps.value->UsagePage; instance.wUsage = caps.value->NotRange.Usage; instance.guidType = *object_usage_to_guid( instance.wUsagePage, instance.wUsage ); @@ -276,14 +281,12 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, switch (instance.wUsage) { case HID_USAGE_GENERIC_X: - instance.dwOfs = DIJOFS_X; set_axis_type( &instance, seen_axis, 0, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; case HID_USAGE_GENERIC_Y: - instance.dwOfs = DIJOFS_Y; set_axis_type( &instance, seen_axis, 1, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); @@ -291,28 +294,24 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, break; case HID_USAGE_GENERIC_Z: case HID_USAGE_GENERIC_WHEEL: - instance.dwOfs = DIJOFS_Z; set_axis_type( &instance, seen_axis, 2, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; case HID_USAGE_GENERIC_RX: - instance.dwOfs = DIJOFS_RX; set_axis_type( &instance, seen_axis, 3, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; case HID_USAGE_GENERIC_RY: - instance.dwOfs = DIJOFS_RY; set_axis_type( &instance, seen_axis, 4, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; case HID_USAGE_GENERIC_RZ: - instance.dwOfs = DIJOFS_RZ; set_axis_type( &instance, seen_axis, 5, &axis ); instance.dwFlags = DIDOI_ASPECTPOSITION; ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); @@ -320,14 +319,12 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, break; case HID_USAGE_GENERIC_DIAL: case HID_USAGE_GENERIC_SLIDER: - instance.dwOfs = DIJOFS_SLIDER( 0 ); instance.dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 6 + axis++ ); instance.dwFlags = DIDOI_ASPECTPOSITION; ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; break; case HID_USAGE_GENERIC_HATSWITCH: - instance.dwOfs = DIJOFS_POV( 0 ); instance.dwType = DIDFT_POV | DIDFT_MAKEINSTANCE( pov++ ); instance.dwFlags = 0; ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); @@ -338,6 +335,8 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, break; } } + + value_ofs += sizeof(LONG); }
for (i = 0; i < impl->caps.NumberInputButtonCaps; ++i) @@ -356,7 +355,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, FIXME( "Ignoring input button %s, too many buttons.\n", debugstr_hid_caps( &caps ) ); else for (j = caps.button->Range.UsageMin; j <= caps.button->Range.UsageMax; ++j) { - instance.dwOfs = DIJOFS_BUTTON( j - 1 ); + instance.dwOfs = button_ofs + (j - caps.button->Range.UsageMin); instance.dwType = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( button++ ); instance.dwFlags = 0; instance.wUsagePage = caps.button->UsagePage; @@ -372,7 +371,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, FIXME( "Ignoring input button %s, too many buttons.\n", debugstr_hid_caps( &caps ) ); else { - instance.dwOfs = DIJOFS_BUTTON( caps.button->NotRange.Usage - 1 ); + instance.dwOfs = button_ofs; instance.dwType = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( button++ ); instance.dwFlags = 0; instance.wUsagePage = caps.button->UsagePage; @@ -383,6 +382,9 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, ret = enum_object( impl, &filter, flags, callback, &caps, &instance, data ); if (ret != DIENUM_CONTINUE) return ret; } + + if (caps.button->IsRange) button_ofs += caps.button->Range.UsageMax - caps.button->Range.UsageMin; + button_ofs++; }
for (i = 0; i < impl->caps.NumberLinkCollectionNodes; ++i) diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 5031c4429af..25e7511353f 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3579,15 +3579,7 @@ static void test_simple_joystick(void) .wUsage = HID_USAGE_GENERIC_JOYSTICK, }, }; - const struct check_objects_todos objects_todos[ARRAY_SIZE(expect_objects)] = - { - {.ofs = TRUE}, - {.ofs = TRUE}, - {.ofs = TRUE}, - {.ofs = TRUE}, - {.ofs = TRUE}, - {.ofs = TRUE}, - }; + const struct check_objects_todos objects_todos[ARRAY_SIZE(expect_objects)] = {};
struct check_objects_params check_objects_params = { @@ -3970,7 +3962,6 @@ static void test_simple_joystick(void)
check_member( objinst, expect_objects[1], "%u", dwSize ); check_member_guid( objinst, expect_objects[1], guidType ); - todo_wine check_member( objinst, expect_objects[1], "%#x", dwOfs ); check_member( objinst, expect_objects[1], "%#x", dwType ); check_member( objinst, expect_objects[1], "%#x", dwFlags ); @@ -3998,7 +3989,6 @@ static void test_simple_joystick(void)
check_member( objinst, expect_objects[5], "%u", dwSize ); check_member_guid( objinst, expect_objects[5], guidType ); - todo_wine check_member( objinst, expect_objects[5], "%#x", dwOfs ); check_member( objinst, expect_objects[5], "%#x", dwType ); check_member( objinst, expect_objects[5], "%#x", dwFlags ); @@ -4031,7 +4021,6 @@ static void test_simple_joystick(void)
check_member( objinst, expect_objects[0], "%u", dwSize ); check_member_guid( objinst, expect_objects[0], guidType ); - todo_wine check_member( objinst, expect_objects[0], "%#x", dwOfs ); check_member( objinst, expect_objects[0], "%#x", dwType ); check_member( objinst, expect_objects[0], "%#x", dwFlags );