[PATCH v2 2/6] dinput: Introduce new direct_input_device_init helper.

Rémi Bernon rbernon at codeweavers.com
Mon Oct 18 03:21:52 CDT 2021


To initialize the device data format by enumerating its objects.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/dinput/device.c         | 73 +++++++++++++++++++++++++++++
 dlls/dinput/device_private.h |  6 +++
 dlls/dinput/joystick_hid.c   | 89 ++++++------------------------------
 3 files changed, 92 insertions(+), 76 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index e2d2e551d02..d23bb8ea975 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,75 @@ HRESULT direct_input_device_alloc( SIZE_T size, const IDirectInputDevice8WVtbl *
     *out = This;
     return DI_OK;
 }
+
+static const GUID *object_instance_guid( const DIDEVICEOBJECTINSTANCEW *instance )
+{
+    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, &params );
             enum_objects( impl, &filter, DIDFT_BUTTON, check_device_state_button, &params );
-            if (impl->base.hEvent && memcmp( &params.old_state, impl->device_state, format->dwDataSize ))
+            if (impl->base.hEvent && memcmp( &params.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 );
-- 
2.33.0




More information about the wine-devel mailing list