[PATCH 1/4] xinput1_3: Introduce new find_opened_device helper.

Rémi Bernon rbernon at codeweavers.com
Thu Aug 5 10:12:06 CDT 2021


To look for already opened device, or available device index.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---

This is a bit of refactoring prior to some more patches to make XInput
device enumeration and report reading asynchronous.

Currently every call to XInputGetState does an ioctl, which introduces a
very high load on wineserver and windevice (with multiple round trips to
satisfy the ioctl).

I intend to optimize this by using a thread queueing asynchronous reads
to get the HID reports, and update the state in background, as well as
refreshing the device list. XInputGetState would then only be about
acquiring the critical section and copying the state.

 dlls/xinput1_3/hid.c | 39 +++++++++++++++++++--------------------
 1 file changed, 19 insertions(+), 20 deletions(-)

diff --git a/dlls/xinput1_3/hid.c b/dlls/xinput1_3/hid.c
index 0f4dec44ee3..e7a77813c71 100644
--- a/dlls/xinput1_3/hid.c
+++ b/dlls/xinput1_3/hid.c
@@ -71,6 +71,20 @@ struct hid_platform_private {
 
 static DWORD last_check = 0;
 
+static BOOL find_opened_device(xinput_controller *devices, SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail, int *free_slot)
+{
+    struct hid_platform_private *private;
+    int i;
+
+    *free_slot = XUSER_MAX_COUNT;
+    for (i = XUSER_MAX_COUNT; i > 0; i--)
+    {
+        if (!(private = devices[i - 1].platform_private)) *free_slot = i - 1;
+        else if (!wcscmp(detail->DevicePath, private->device_path)) return TRUE;
+    }
+    return FALSE;
+}
+
 static void MarkUsage(struct hid_platform_private *private, WORD usage, LONG min, LONG max, USHORT bits)
 {
     struct axis_info info = {min, max-min, bits};
@@ -219,7 +233,7 @@ void HID_find_gamepads(xinput_controller *devices)
     HIDP_CAPS caps;
     NTSTATUS status;
     DWORD idx;
-    int i, open_device_idx;
+    int i;
 
     idx = GetTickCount();
     if ((idx - last_check) < 2000)
@@ -255,24 +269,9 @@ void HID_find_gamepads(xinput_controller *devices)
         if (!wcsstr(data->DevicePath, L"IG_"))
             continue;
 
-        open_device_idx = -1;
-        for (i = 0; i < XUSER_MAX_COUNT; i++)
-        {
-            struct hid_platform_private *private = devices[i].platform_private;
-            if (devices[i].platform_private)
-            {
-                if (!wcscmp(data->DevicePath, private->device_path))
-                    break;
-            }
-            else if(open_device_idx < 0)
-                open_device_idx = i;
-        }
-        if (i != XUSER_MAX_COUNT)
-            /* this device is already opened */
-            continue;
-        if (open_device_idx < 0)
-            /* no open device slots */
-            break;
+        if (find_opened_device(devices, data, &i)) continue; /* already opened */
+        if (i == XUSER_MAX_COUNT) break; /* no more slots */
+
         device = CreateFileW(data->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
         if (device == INVALID_HANDLE_VALUE)
             continue;
@@ -286,7 +285,7 @@ void HID_find_gamepads(xinput_controller *devices)
             WARN("ignoring HID device, unsupported usage page %04x\n", caps.UsagePage);
         else if (caps.Usage != HID_USAGE_GENERIC_GAMEPAD && caps.Usage != HID_USAGE_GENERIC_JOYSTICK && caps.Usage != HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER)
             WARN("ignoring HID device, unsupported usage %04x:%04x\n", caps.UsagePage, caps.Usage);
-        else if (!init_controller(&devices[open_device_idx], ppd, &caps, device, data->DevicePath))
+        else if (!init_controller(&devices[i], ppd, &caps, device, data->DevicePath))
             WARN("ignoring HID device, failed to initialize\n");
         else
             goto done;
-- 
2.32.0




More information about the wine-devel mailing list