[PATCH 2/3] dinput: Rewrite and simplify user data format object matching.

Rémi Bernon rbernon at codeweavers.com
Fri Oct 29 02:40:40 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/dinput/device.c         | 282 +++++++----------------------------
 dlls/dinput/device_private.h |   8 -
 dlls/dinput8/tests/hid.c     |   5 -
 3 files changed, 56 insertions(+), 239 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index ed9bdee98ea..1eed223f51c 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -107,138 +107,6 @@ static void _dump_cooperativelevel_DI(DWORD dwFlags) {
     }
 }
 
-static void _dump_ObjectDataFormat_flags(DWORD dwFlags) {
-    unsigned int   i;
-    static const struct {
-        DWORD       mask;
-        const char  *name;
-    } flags[] = {
-#define FE(x) { x, #x}
-        FE(DIDOI_FFACTUATOR),
-        FE(DIDOI_FFEFFECTTRIGGER),
-        FE(DIDOI_POLLED),
-        FE(DIDOI_GUIDISUSAGE)
-#undef FE
-    };
-
-    if (!dwFlags) return;
-
-    TRACE("Flags:");
-
-    /* First the flags */
-    for (i = 0; i < ARRAY_SIZE(flags); i++) {
-        if (flags[i].mask & dwFlags)
-        TRACE(" %s",flags[i].name);
-    }
-
-    /* Now specific values */
-#define FE(x) case x: TRACE(" "#x); break
-    switch (dwFlags & DIDOI_ASPECTMASK) {
-        FE(DIDOI_ASPECTACCEL);
-        FE(DIDOI_ASPECTFORCE);
-        FE(DIDOI_ASPECTPOSITION);
-        FE(DIDOI_ASPECTVELOCITY);
-    }
-#undef FE
-
-}
-
-static void _dump_EnumObjects_flags(DWORD dwFlags) {
-    if (TRACE_ON(dinput)) {
-	unsigned int   i;
-	DWORD type, instance;
-	static const struct {
-	    DWORD       mask;
-	    const char  *name;
-	} flags[] = {
-#define FE(x) { x, #x}
-	    FE(DIDFT_RELAXIS),
-	    FE(DIDFT_ABSAXIS),
-	    FE(DIDFT_PSHBUTTON),
-	    FE(DIDFT_TGLBUTTON),
-	    FE(DIDFT_POV),
-	    FE(DIDFT_COLLECTION),
-	    FE(DIDFT_NODATA),	    
-	    FE(DIDFT_FFACTUATOR),
-	    FE(DIDFT_FFEFFECTTRIGGER),
-	    FE(DIDFT_OUTPUT),
-	    FE(DIDFT_VENDORDEFINED),
-	    FE(DIDFT_ALIAS),
-	    FE(DIDFT_OPTIONAL)
-#undef FE
-	};
-	type = (dwFlags & 0xFF0000FF);
-	instance = ((dwFlags >> 8) & 0xFFFF);
-	TRACE("Type:");
-	if (type == DIDFT_ALL) {
-	    TRACE(" DIDFT_ALL");
-	} else {
-	    for (i = 0; i < ARRAY_SIZE(flags); i++) {
-		if (flags[i].mask & type) {
-		    type &= ~flags[i].mask;
-		    TRACE(" %s",flags[i].name);
-		}
-	    }
-	    if (type) {
-                TRACE(" (unhandled: %08x)", type);
-	    }
-	}
-	TRACE(" / Instance: ");
-	if (instance == ((DIDFT_ANYINSTANCE >> 8) & 0xFFFF)) {
-	    TRACE("DIDFT_ANYINSTANCE");
-	} else {
-            TRACE("%3d", instance);
-	}
-    }
-}
-
-/* This function is a helper to convert a GUID into any possible DInput GUID out there */
-static const char *_dump_dinput_GUID( const GUID *guid )
-{
-    unsigned int i;
-    static const struct {
-	const GUID *guid;
-	const char *name;
-    } guids[] = {
-#define FE(x) { &x, #x}
-	FE(GUID_XAxis),
-	FE(GUID_YAxis),
-	FE(GUID_ZAxis),
-	FE(GUID_RxAxis),
-	FE(GUID_RyAxis),
-	FE(GUID_RzAxis),
-	FE(GUID_Slider),
-	FE(GUID_Button),
-	FE(GUID_Key),
-	FE(GUID_POV),
-	FE(GUID_Unknown),
-	FE(GUID_SysMouse),
-	FE(GUID_SysKeyboard),
-	FE(GUID_Joystick),
-	FE(GUID_ConstantForce),
-	FE(GUID_RampForce),
-	FE(GUID_Square),
-	FE(GUID_Sine),
-	FE(GUID_Triangle),
-	FE(GUID_SawtoothUp),
-	FE(GUID_SawtoothDown),
-	FE(GUID_Spring),
-	FE(GUID_Damper),
-	FE(GUID_Inertia),
-	FE(GUID_Friction),
-	FE(GUID_CustomForce)
-#undef FE
-    };
-    if (guid == NULL)
-	return "null GUID";
-    for (i = 0; i < ARRAY_SIZE(guids); i++) {
-	if (IsEqualGUID(guids[i].guid, guid)) {
-	    return guids[i].name;
-	}
-    }
-    return debugstr_guid(guid);
-}
-
 /******************************************************************************
  * Get the default and the app-specific config keys.
  */
@@ -370,116 +238,78 @@ LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD
     return NULL;
 }
 
-static HRESULT dinput_device_init_user_format( struct dinput_device *impl, const DIDATAFORMAT *asked_format )
+static BOOL match_device_object( DIDATAFORMAT *device_format, DIDATAFORMAT *user_format,
+                                 const DIDATAFORMAT *format, const DIOBJECTDATAFORMAT *match_obj )
 {
+    DWORD i, device_instance, instance = DIDFT_GETINSTANCE( match_obj->dwType );
     DIOBJECTDATAFORMAT *device_obj, *user_obj;
-    DataFormat *format = &impl->data_format;
-    DIDATAFORMAT *user_format = NULL;
-    unsigned int i, j;
-    int *done;
 
-    if (!format->wine_df) return DIERR_INVALIDPARAM;
-    done = calloc( asked_format->dwNumObjs, sizeof(int) );
-    if (!done) goto failed;
-
-    if (!(user_format = malloc( sizeof(DIDATAFORMAT) ))) goto failed;
-    *user_format = *format->wine_df;
-    user_format->dwFlags = asked_format->dwFlags;
-    user_format->dwDataSize = asked_format->dwDataSize;
-    user_format->dwNumObjs += asked_format->dwNumObjs;
-    if (!(user_format->rgodf = calloc( user_format->dwNumObjs, sizeof(DIOBJECTDATAFORMAT) ))) goto failed;
-
-    TRACE("Creating DataTransform :\n");
-    
-    for (i = 0; i < format->wine_df->dwNumObjs; i++)
+    for (i = 0; i < device_format->dwNumObjs; i++)
     {
-        device_obj = format->wine_df->rgodf + i;
         user_obj = user_format->rgodf + i;
+        device_obj = device_format->rgodf + i;
+        device_instance = DIDFT_GETINSTANCE( device_obj->dwType );
 
-        for (j = 0; j < asked_format->dwNumObjs; j++)
+        if (!(user_obj->dwType & DIDFT_OPTIONAL)) continue; /* already matched */
+        if (match_obj->pguid && device_obj->pguid && !IsEqualGUID( device_obj->pguid, match_obj->pguid )) continue;
+        if (instance != DIDFT_GETINSTANCE( DIDFT_ANYINSTANCE ) && instance != device_instance) continue;
+        if (!(DIDFT_GETTYPE( match_obj->dwType ) & DIDFT_GETTYPE( device_obj->dwType ))) continue;
+
+        TRACE( "match %s with device %s\n", debugstr_diobjectdataformat( match_obj ),
+               debugstr_diobjectdataformat( device_obj ) );
+
+        *user_obj = *device_obj;
+        user_obj->dwOfs = match_obj->dwOfs;
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+static HRESULT dinput_device_init_user_format( struct dinput_device *impl, const DIDATAFORMAT *format )
+{
+    DIDATAFORMAT *user_format, *device_format = impl->data_format.wine_df;
+    DIOBJECTDATAFORMAT *user_obj, *match_obj;
+    DWORD i;
+
+    if (!device_format) return DIERR_INVALIDPARAM;
+    if (!(user_format = malloc( sizeof(DIDATAFORMAT) ))) return DIERR_OUTOFMEMORY;
+    *user_format = *device_format;
+    user_format->dwFlags = format->dwFlags;
+    user_format->dwDataSize = format->dwDataSize;
+    user_format->dwNumObjs += format->dwNumObjs;
+    if (!(user_format->rgodf = calloc( user_format->dwNumObjs, sizeof(DIOBJECTDATAFORMAT) )))
+    {
+        free( user_format );
+        return DIERR_OUTOFMEMORY;
+    }
+
+    user_obj = user_format->rgodf + user_format->dwNumObjs;
+    while (user_obj-- > user_format->rgodf) user_obj->dwType |= DIDFT_OPTIONAL;
+
+    for (i = 0; i < format->dwNumObjs; ++i)
+    {
+        match_obj = format->rgodf + i;
+
+        if (!match_device_object( device_format, user_format, format, match_obj ))
         {
-            if (done[j] == 1) continue;
-
-            if (/* Check if the application either requests any GUID and if not, it if matches
-		 * the GUID of the Wine object.
-		 */
-		((asked_format->rgodf[j].pguid == NULL) ||
-		 (format->wine_df->rgodf[i].pguid == NULL) ||
-		 (IsEqualGUID(format->wine_df->rgodf[i].pguid, asked_format->rgodf[j].pguid)))
-		&&
-		(/* Then check if it accepts any instance id, and if not, if it matches Wine's
-		  * instance id.
-		  */
-		 ((asked_format->rgodf[j].dwType & DIDFT_INSTANCEMASK) == DIDFT_ANYINSTANCE) ||
-		 (DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType) == 0x00FF) || /* This is mentioned in no DX docs, but it works fine - tested on WinXP */
-		 (DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType) == DIDFT_GETINSTANCE(format->wine_df->rgodf[i].dwType)))
-		&&
-		( /* Then if the asked type matches the one Wine provides */
-                 DIDFT_GETTYPE(asked_format->rgodf[j].dwType) & format->wine_df->rgodf[i].dwType))
-            {
-		done[j] = 1;
-		
-		TRACE("Matching :\n");
-		TRACE("   - Asked (%d) :\n", j);
-		TRACE("       * GUID: %s ('%s')\n",
-		      debugstr_guid(asked_format->rgodf[j].pguid),
-		      _dump_dinput_GUID(asked_format->rgodf[j].pguid));
-                TRACE("       * Offset: %3d\n", asked_format->rgodf[j].dwOfs);
-                TRACE("       * dwType: 0x%08x\n", asked_format->rgodf[j].dwType);
-		TRACE("         "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
-                TRACE("       * dwFlags: 0x%08x\n", asked_format->rgodf[j].dwFlags);
-		TRACE("         "); _dump_ObjectDataFormat_flags(asked_format->rgodf[j].dwFlags); TRACE("\n");
-		
-		TRACE("   - Wine  (%d) :\n", i);
-		TRACE("       * GUID: %s ('%s')\n",
-                      debugstr_guid(format->wine_df->rgodf[i].pguid),
-                      _dump_dinput_GUID(format->wine_df->rgodf[i].pguid));
-                TRACE("       * Offset: %3d\n", format->wine_df->rgodf[i].dwOfs);
-                TRACE("       * dwType: 0x%08x\n", format->wine_df->rgodf[i].dwType);
-                TRACE("         "); _dump_EnumObjects_flags(format->wine_df->rgodf[i].dwType); TRACE("\n");
-                TRACE("       * dwFlags: 0x%08x\n", format->wine_df->rgodf[i].dwFlags);
-                TRACE("         "); _dump_ObjectDataFormat_flags(format->wine_df->rgodf[i].dwFlags); TRACE("\n");
-
-                *user_obj = *device_obj;
-                user_obj->dwOfs = asked_format->rgodf[j].dwOfs;
-                break;
-            }
+            WARN( "object %s not found\n", debugstr_diobjectdataformat( match_obj ) );
+            if (!(match_obj->dwType & DIDFT_OPTIONAL)) goto failed;
+            user_obj = user_format->rgodf + device_format->dwNumObjs + i;
+            *user_obj = *match_obj;
         }
     }
 
-    TRACE("Setting to default value :\n");
-    for (j = 0; j < asked_format->dwNumObjs; j++) {
-        user_obj = user_format->rgodf + format->wine_df->dwNumObjs + j;
-
-        if (done[j] == 0) {
-	    TRACE("   - Asked (%d) :\n", j);
-	    TRACE("       * GUID: %s ('%s')\n",
-		  debugstr_guid(asked_format->rgodf[j].pguid),
-		  _dump_dinput_GUID(asked_format->rgodf[j].pguid));
-            TRACE("       * Offset: %3d\n", asked_format->rgodf[j].dwOfs);
-            TRACE("       * dwType: 0x%08x\n", asked_format->rgodf[j].dwType);
-	    TRACE("         "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
-            TRACE("       * dwFlags: 0x%08x\n", asked_format->rgodf[j].dwFlags);
-	    TRACE("         "); _dump_ObjectDataFormat_flags(asked_format->rgodf[j].dwFlags); TRACE("\n");
-
-            if (!(asked_format->rgodf[j].dwType & DIDFT_POV))
-                continue; /* fill_DataFormat memsets the buffer to 0 */
-
-            *user_obj = asked_format->rgodf[j];
-        }
-    }
-    
-    free( done );
+    user_obj = user_format->rgodf + user_format->dwNumObjs;
+    while (user_obj-- > user_format->rgodf) user_obj->dwType &= ~DIDFT_OPTIONAL;
 
     impl->user_format = user_format;
     return DI_OK;
 
 failed:
-    free( done );
-    if (user_format) free( user_format->rgodf );
+    free( user_format->rgodf );
     free( user_format );
-
-    return DIERR_OUTOFMEMORY;
+    return DIERR_INVALIDPARAM;
 }
 
 static int id_to_offset( struct dinput_device *impl, int id )
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 3f07a3a0f8a..190e2c16ffe 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -28,14 +28,6 @@
 #include "wine/list.h"
 #include "dinput_private.h"
 
-typedef struct
-{
-    int size;
-    int offset_in;
-    int offset_out;
-    int value;
-} DataTransform;
-
 typedef struct
 {
     LPDIDATAFORMAT              wine_df;     /* wine internal data format */
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
index dab6ea4478e..c6d01b8bee7 100644
--- a/dlls/dinput8/tests/hid.c
+++ b/dlls/dinput8/tests/hid.c
@@ -4475,26 +4475,21 @@ static void test_simple_joystick(void)
     objdataformat[3].dwType = 0xff|DIDFT_ANYINSTANCE;
     objdataformat[3].dwFlags = 0;
     hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
-    todo_wine
     ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
     objdataformat[1].dwType = DIDFT_AXIS|DIDFT_MAKEINSTANCE( 12 );
     hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
-    todo_wine
     ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
     objdataformat[1].dwType = DIDFT_AXIS|DIDFT_MAKEINSTANCE( 0xff );
     hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
-    todo_wine
     ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
     objdataformat[1].dwType = DIDFT_AXIS|DIDFT_MAKEINSTANCE( 1 );
     hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
     ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
     objdataformat[1].pguid = &GUID_RzAxis;
     hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
-    todo_wine
     ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
     objdataformat[1].pguid = &GUID_Unknown;
     hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
-    todo_wine
     ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
     objdataformat[1].pguid = &GUID_YAxis;
     hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
-- 
2.33.0




More information about the wine-devel mailing list