Rémi Bernon : dinput: Use a custom HID joystick state instead of DIJOYSTATE2.
Alexandre Julliard
julliard at winehq.org
Mon Sep 27 15:21:43 CDT 2021
Module: wine
Branch: master
Commit: d682b3a9d3253f935ee53cca3c2005c1b5b6c9ca
URL: https://source.winehq.org/git/wine.git/?a=commit;h=d682b3a9d3253f935ee53cca3c2005c1b5b6c9ca
Author: Rémi Bernon <rbernon at codeweavers.com>
Date: Mon Sep 27 09:43:03 2021 +0200
dinput: Use a custom HID joystick state instead of DIJOYSTATE2.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/dinput/joystick_hid.c | 85 +++++++++++++++++-----------------------------
1 file changed, 32 insertions(+), 53 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index 30e63c16cb8..7fe2e5f246c 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,7 +883,8 @@ static HRESULT hid_joystick_read_state( IDirectInputDevice8W *iface )
};
struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
ULONG i, count, report_len = impl->caps.InputReportByteLength;
- struct parse_device_state_params params = {0};
+ 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;
NTSTATUS status;
@@ -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 );
More information about the wine-cvs
mailing list