To initialize the device data format by enumerating its objects.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/device.c | 93 ++++++++++++++++++++++++++++++++++++ dlls/dinput/device_private.h | 6 +++ dlls/dinput/joystick_hid.c | 89 +++++----------------------------- 3 files changed, 112 insertions(+), 76 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index e2d2e551d02..03c10c7360f 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -35,6 +35,7 @@ #include "winerror.h" #include "dinput.h" #include "dinputd.h" +#include "hidusage.h"
#include "initguid.h" #include "device_private.h" @@ -1821,3 +1822,95 @@ HRESULT direct_input_device_alloc( SIZE_T size, const IDirectInputDevice8WVtbl * *out = This; return DI_OK; } + +static const GUID *object_instance_guid( const DIDEVICEOBJECTINSTANCEW *instance ) +{ + switch (instance->wUsagePage) + { + case HID_USAGE_PAGE_BUTTON: return &GUID_Button; + case HID_USAGE_PAGE_GENERIC: + switch (instance->wUsage) + { + case HID_USAGE_GENERIC_X: return &GUID_XAxis; + case HID_USAGE_GENERIC_Y: return &GUID_YAxis; + case HID_USAGE_GENERIC_Z: return &GUID_ZAxis; + case HID_USAGE_GENERIC_WHEEL: return &GUID_ZAxis; + case HID_USAGE_GENERIC_RX: return &GUID_RxAxis; + case HID_USAGE_GENERIC_RY: return &GUID_RyAxis; + case HID_USAGE_GENERIC_RZ: return &GUID_RzAxis; + case HID_USAGE_GENERIC_SLIDER: return &GUID_Slider; + case HID_USAGE_GENERIC_HATSWITCH: return &GUID_POV; + } + break; + } + + if (IsEqualGUID( &instance->guidType, &GUID_XAxis )) return &GUID_XAxis; + if (IsEqualGUID( &instance->guidType, &GUID_YAxis )) return &GUID_YAxis; + if (IsEqualGUID( &instance->guidType, &GUID_ZAxis )) return &GUID_ZAxis; + if (IsEqualGUID( &instance->guidType, &GUID_RxAxis )) return &GUID_RxAxis; + if (IsEqualGUID( &instance->guidType, &GUID_RyAxis )) return &GUID_RyAxis; + if (IsEqualGUID( &instance->guidType, &GUID_RzAxis )) return &GUID_RzAxis; + if (IsEqualGUID( &instance->guidType, &GUID_Slider )) return &GUID_Slider; + if (IsEqualGUID( &instance->guidType, &GUID_Button )) return &GUID_Button; + if (IsEqualGUID( &instance->guidType, &GUID_Key )) return &GUID_Key; + if (IsEqualGUID( &instance->guidType, &GUID_POV )) return &GUID_POV; + + return &GUID_Unknown; +} + +static BOOL CALLBACK enum_objects_init( const DIDEVICEOBJECTINSTANCEW *instance, void *data ) +{ + IDirectInputDeviceImpl *impl = impl_from_IDirectInputDevice8W( data ); + DIDATAFORMAT *format = impl->data_format.wine_df; + DIOBJECTDATAFORMAT *obj_format; + + if (!format->rgodf) + { + format->dwDataSize = max( format->dwDataSize, instance->dwOfs + sizeof(LONG) ); + if (instance->dwType & DIDFT_BUTTON) impl->caps.dwButtons++; + if (instance->dwType & DIDFT_AXIS) impl->caps.dwAxes++; + if (instance->dwType & DIDFT_POV) impl->caps.dwPOVs++; + if (instance->dwType & (DIDFT_BUTTON|DIDFT_AXIS|DIDFT_POV)) + { + if (!impl->device_state_report_id) + impl->device_state_report_id = instance->wReportId; + else if (impl->device_state_report_id != instance->wReportId) + FIXME( "multiple device state reports found!\n" ); + } + } + else + { + obj_format = format->rgodf + format->dwNumObjs; + obj_format->pguid = object_instance_guid( instance ); + obj_format->dwOfs = instance->dwOfs; + obj_format->dwType = instance->dwType; + obj_format->dwFlags = instance->dwFlags; + } + + format->dwNumObjs++; + return DIENUM_CONTINUE; +} + +HRESULT direct_input_device_init( IDirectInputDevice8W *iface ) +{ + IDirectInputDeviceImpl *impl = impl_from_IDirectInputDevice8W( iface ); + DIDATAFORMAT *format = impl->data_format.wine_df; + ULONG size; + + IDirectInputDevice8_EnumObjects( iface, enum_objects_init, iface, DIDFT_ALL ); + if (format->dwDataSize > DEVICE_STATE_MAX_SIZE) + { + FIXME( "unable to create device, state is too large\n" ); + return DIERR_OUTOFMEMORY; + } + + size = format->dwNumObjs * sizeof(*format->rgodf); + if (!(format->rgodf = calloc( 1, size ))) return DIERR_OUTOFMEMORY; + format->dwSize = sizeof(*format); + format->dwObjSize = sizeof(*format->rgodf); + format->dwFlags = DIDF_ABSAXIS; + format->dwNumObjs = 0; + IDirectInputDevice8_EnumObjects( iface, enum_objects_init, iface, DIDFT_ALL ); + + return DI_OK; +} diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 7ae040744cb..43629abdb15 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -62,6 +62,8 @@ struct dinput_device_vtbl HRESULT (*unacquire)(IDirectInputDevice8W *); };
+#define DEVICE_STATE_MAX_SIZE 1024 + /* Device implementation */ typedef struct IDirectInputDeviceImpl IDirectInputDeviceImpl; struct IDirectInputDeviceImpl @@ -99,10 +101,14 @@ struct IDirectInputDeviceImpl /* internal device callbacks */ HANDLE read_event; const struct dinput_device_vtbl *vtbl; + + BYTE device_state_report_id; + BYTE device_state[DEVICE_STATE_MAX_SIZE]; };
extern HRESULT direct_input_device_alloc( SIZE_T size, const IDirectInputDevice8WVtbl *vtbl, const struct dinput_device_vtbl *internal_vtbl, const GUID *guid, IDirectInputImpl *dinput, void **out ) DECLSPEC_HIDDEN; +extern HRESULT direct_input_device_init( IDirectInputDevice8W *iface ); extern const IDirectInputDevice8AVtbl dinput_device_a_vtbl DECLSPEC_HIDDEN;
extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN; diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 03005964c67..b6eeb772fcf 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -150,8 +150,6 @@ struct pid_set_ramp_force struct hid_value_caps *end_caps; };
-#define DEVICE_STATE_MAX_SIZE 1024 - struct hid_joystick { IDirectInputDeviceImpl base; @@ -172,9 +170,6 @@ struct hid_joystick USAGE_AND_PAGE *usages_buf; ULONG usages_count;
- BYTE device_state_report_id; - BYTE device_state[DEVICE_STATE_MAX_SIZE]; - BYTE effect_inuse[255]; struct list effect_list; struct pid_control_report pid_device_control; @@ -856,13 +851,13 @@ static BOOL set_property_prop_range( struct hid_joystick *impl, struct hid_value { if (!caps->physical_min) tmp = caps->physical_max / 2; else tmp = round( (caps->physical_min + caps->physical_max) / 2.0 ); - *(LONG *)(impl->device_state + instance->dwOfs) = tmp; + *(LONG *)(impl->base.device_state + instance->dwOfs) = tmp; } else if (instance->dwType & DIDFT_POV) { tmp = caps->logical_max - caps->logical_min; if (tmp > 0) caps->physical_max -= value->lMax / (tmp + 1); - *(LONG *)(impl->device_state + instance->dwOfs) = -1; + *(LONG *)(impl->base.device_state + instance->dwOfs) = -1; } return DIENUM_CONTINUE; } @@ -1009,7 +1004,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->device_state, &impl->base.data_format ); + else fill_DataFormat( ptr, len, impl->base.device_state, &impl->base.data_format ); LeaveCriticalSection( &impl->base.crit );
return hr; @@ -1445,11 +1440,11 @@ static BOOL check_device_state_button( struct hid_joystick *impl, struct hid_val struct parse_device_state_params *params = data; BYTE old_value, value;
- if (instance->wReportId != impl->device_state_report_id) return DIENUM_CONTINUE; + if (instance->wReportId != impl->base.device_state_report_id) return DIENUM_CONTINUE;
value = params->buttons[instance->wUsage - 1]; old_value = params->old_state[instance->dwOfs]; - impl->device_state[instance->dwOfs] = value; + impl->base.device_state[instance->dwOfs] = value; if (old_value != value) queue_event( iface, instance->dwType, value, params->time, params->seq );
@@ -1518,7 +1513,7 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_value LONG old_value, value; NTSTATUS status;
- if (instance->wReportId != impl->device_state_report_id) return DIENUM_CONTINUE; + if (instance->wReportId != impl->base.device_state_report_id) return DIENUM_CONTINUE;
extra = impl->input_extra_caps + (caps - HID_INPUT_VALUE_CAPS( preparsed )); status = HidP_GetUsageValue( HidP_Input, instance->wUsagePage, 0, instance->wUsage, @@ -1529,7 +1524,7 @@ static BOOL read_device_state_value( struct hid_joystick *impl, struct hid_value else value = scale_value( logical_value, caps, caps->physical_min, caps->physical_max );
old_value = *(LONG *)(params->old_state + instance->dwOfs); - *(LONG *)(impl->device_state + instance->dwOfs) = value; + *(LONG *)(impl->base.device_state + instance->dwOfs) = value; if (old_value != value) queue_event( iface, instance->dwType, value, params->time, params->seq );
@@ -1579,12 +1574,12 @@ static HRESULT hid_joystick_internal_read( IDirectInputDevice8W *iface ) impl->preparsed, report_buf, report_len ); if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_GetUsagesEx returned %#x\n", status );
- if (report_buf[0] == impl->device_state_report_id) + if (report_buf[0] == impl->base.device_state_report_id) { 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 ); + memcpy( params.old_state, impl->base.device_state, format->dwDataSize ); + memset( impl->base.device_state, 0, format->dwDataSize );
while (count--) { @@ -1599,7 +1594,7 @@ static HRESULT hid_joystick_internal_read( IDirectInputDevice8W *iface )
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 )) + if (impl->base.hEvent && memcmp( ¶ms.old_state, impl->base.device_state, format->dwDataSize )) SetEvent( impl->base.hEvent ); }
@@ -1884,47 +1879,6 @@ static HRESULT hid_joystick_enum_device( DWORD type, DWORD flags, DIDEVICEINSTAN return DI_OK; }
-static BOOL init_objects( struct hid_joystick *impl, struct hid_value_caps *caps, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) -{ - 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->base.caps.dwButtons++; - if (instance->dwType & DIDFT_AXIS) impl->base.caps.dwAxes++; - if (instance->dwType & DIDFT_POV) impl->base.caps.dwPOVs++; - - if (instance->dwType & (DIDFT_BUTTON|DIDFT_AXIS|DIDFT_POV) && - (instance->wUsagePage == HID_USAGE_PAGE_GENERIC || - instance->wUsagePage == HID_USAGE_PAGE_BUTTON)) - { - if (!impl->device_state_report_id) - impl->device_state_report_id = instance->wReportId; - else if (impl->device_state_report_id != instance->wReportId) - FIXME( "multiple device state reports found!\n" ); - } - - return DIENUM_CONTINUE; -} - -static BOOL init_data_format( struct hid_joystick *impl, struct hid_value_caps *caps, - DIDEVICEOBJECTINSTANCEW *instance, void *data ) -{ - DIDATAFORMAT *format = impl->base.data_format.wine_df; - DIOBJECTDATAFORMAT *obj_format; - DWORD *index = data; - - obj_format = format->rgodf + *index; - obj_format->pguid = object_usage_to_guid( instance->wUsagePage, instance->wUsage ); - obj_format->dwOfs = instance->dwOfs; - obj_format->dwType = instance->dwType; - obj_format->dwFlags = instance->dwFlags; - (*index)++; - - return DIENUM_CONTINUE; -} - static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps *caps, DIDEVICEOBJECTINSTANCEW *instance, void *data ) { @@ -2203,11 +2157,10 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID struct hid_preparsed_data *preparsed; struct hid_joystick *impl = NULL; struct extra_caps *extra; - DIDATAFORMAT *format = NULL; USAGE_AND_PAGE *usages; - DWORD size, index; char *buffer; HRESULT hr; + DWORD size;
TRACE( "dinput %p, guid %s, out %p\n", dinput, debugstr_guid( guid ), out );
@@ -2255,7 +2208,6 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID if (!(usages = malloc( size ))) goto failed; impl->usages_buf = usages;
- enum_objects( impl, &filter, DIDFT_ALL, init_objects, NULL ); enum_objects( impl, &filter, DIDFT_COLLECTION, init_pid_reports, NULL ); enum_objects( impl, &filter, DIDFT_NODATA, init_pid_caps, NULL );
@@ -2296,23 +2248,8 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID impl->base.caps.dwFFDriverVersion = 1; }
- format = impl->base.data_format.wine_df; - if (format->dwDataSize > DEVICE_STATE_MAX_SIZE) - { - FIXME( "unable to create device, state is too large\n" ); + if (FAILED(hr = direct_input_device_init( &impl->base.IDirectInputDevice8W_iface ))) goto failed; - } - - size = format->dwNumObjs * sizeof(*format->rgodf); - if (!(format->rgodf = calloc( 1, size ))) goto failed; - format->dwSize = sizeof(*format); - format->dwObjSize = sizeof(*format->rgodf); - format->dwFlags = DIDF_ABSAXIS; - - index = 0; - enum_objects( impl, &filter, DIDFT_ALL, init_data_format, &index ); - - _dump_DIDATAFORMAT( impl->base.data_format.wine_df );
range.lMax = 65535; enum_objects( impl, &range.diph, DIDFT_AXIS, set_property_prop_range, &range );