[PATCH 2/3] xinput1_3: Update the controller list in the update thread.
Rémi Bernon
rbernon at codeweavers.com
Fri Aug 6 04:05:57 CDT 2021
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/xinput1_3/hid.c | 144 +++++++++++++++-----------------
dlls/xinput1_3/xinput_main.c | 8 +-
dlls/xinput1_3/xinput_private.h | 2 +-
3 files changed, 73 insertions(+), 81 deletions(-)
diff --git a/dlls/xinput1_3/hid.c b/dlls/xinput1_3/hid.c
index 176e18fd95c..6aacf0ac9cd 100644
--- a/dlls/xinput1_3/hid.c
+++ b/dlls/xinput1_3/hid.c
@@ -69,7 +69,6 @@ struct hid_platform_private {
struct axis_info lx, ly, ltrigger, rx, ry, rtrigger;
};
-static DWORD last_check = 0;
static HANDLE stop_event;
static HANDLE done_event;
@@ -87,17 +86,80 @@ static BOOL find_opened_device(SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail, int *f
return FALSE;
}
+static BOOL init_controller(xinput_controller *controller, PHIDP_PREPARSED_DATA ppd,
+ HIDP_CAPS *caps, HANDLE device, WCHAR *device_path);
+
+static void update_controller_list(void)
+{
+ char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR)];
+ SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)buffer;
+ SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
+ PHIDP_PREPARSED_DATA preparsed;
+ NTSTATUS status;
+ HIDP_CAPS caps;
+ HANDLE device;
+ HDEVINFO set;
+ DWORD idx;
+ GUID guid;
+ int i;
+
+ HidD_GetHidGuid(&guid);
+
+ set = SetupDiGetClassDevsW(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
+ detail->cbSize = sizeof(*detail);
+
+ idx = 0;
+ while (SetupDiEnumDeviceInterfaces(set, NULL, &guid, idx++, &iface))
+ {
+ if (!SetupDiGetDeviceInterfaceDetailW(set, &iface, detail, sizeof(buffer), NULL, NULL))
+ continue;
+
+ if (!wcsstr(detail->DevicePath, L"IG_")) continue;
+
+ if (find_opened_device(detail, &i)) continue; /* already opened */
+ if (i == XUSER_MAX_COUNT) break; /* no more slots */
+
+ device = CreateFileW(detail->DevicePath, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
+ if (device == INVALID_HANDLE_VALUE) continue;
+
+ preparsed = NULL;
+ if (!HidD_GetPreparsedData(device, &preparsed))
+ WARN("ignoring HID device, HidD_GetPreparsedData failed with error %u\n", GetLastError());
+ else if ((status = HidP_GetCaps(preparsed, &caps)) != HIDP_STATUS_SUCCESS)
+ WARN("ignoring HID device, HidP_GetCaps returned %#x\n", status);
+ else if (caps.UsagePage != HID_USAGE_PAGE_GENERIC)
+ 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(&controllers[i], preparsed, &caps, device, detail->DevicePath))
+ WARN("ignoring HID device, failed to initialize\n");
+ else
+ continue;
+
+ CloseHandle(device);
+ HidD_FreePreparsedData(preparsed);
+ }
+
+ SetupDiDestroyDeviceInfoList(set);
+}
+
static DWORD WINAPI hid_update_thread_proc(void *param)
{
HANDLE events[1];
- DWORD count, ret;
+ DWORD count, ret = WAIT_TIMEOUT;
do
{
+ EnterCriticalSection(&xinput_crit);
+ if (ret == WAIT_TIMEOUT) update_controller_list();
+
count = 0;
events[count++] = stop_event;
+ LeaveCriticalSection(&xinput_crit);
}
- while ((ret = WaitForMultipleObjectsEx( count, events, FALSE, INFINITE, TRUE )) < count - 1);
+ while ((ret = WaitForMultipleObjectsEx( count, events, FALSE, 2000, TRUE )) < count - 1 || ret == WAIT_TIMEOUT);
if (ret != count - 1) ERR("update thread exited unexpectedly, ret %u\n", ret);
SetEvent(done_event);
@@ -245,7 +307,9 @@ static BOOL init_controller(xinput_controller *controller, PHIDP_PREPARSED_DATA
memset(&controller->state, 0, sizeof(controller->state));
memset(&controller->vibration, 0, sizeof(controller->vibration));
+ EnterCriticalSection(&controller->crit);
controller->platform_private = private;
+ LeaveCriticalSection(&controller->crit);
return TRUE;
failed:
@@ -257,82 +321,10 @@ failed:
return FALSE;
}
-void HID_find_gamepads(void)
+void HID_start_update_thread(void)
{
static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
-
- char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR)];
- SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)buffer;
- HDEVINFO device_info_set;
- GUID hid_guid;
- SP_DEVICE_INTERFACE_DATA interface_data;
- PHIDP_PREPARSED_DATA ppd;
- HANDLE device;
- HIDP_CAPS caps;
- NTSTATUS status;
- DWORD idx;
- int i;
-
InitOnceExecuteOnce(&init_once, start_update_thread, NULL, NULL);
-
- idx = GetTickCount();
- if ((idx - last_check) < 2000)
- return;
-
- EnterCriticalSection(&xinput_crit);
-
- if ((idx - last_check) < 2000)
- {
- LeaveCriticalSection(&xinput_crit);
- return;
- }
- last_check = idx;
-
- HidD_GetHidGuid(&hid_guid);
-
- device_info_set = SetupDiGetClassDevsW(&hid_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
- detail->cbSize = sizeof(*detail);
-
- ZeroMemory(&interface_data, sizeof(interface_data));
- interface_data.cbSize = sizeof(interface_data);
-
- idx = 0;
- while (SetupDiEnumDeviceInterfaces(device_info_set, NULL, &hid_guid, idx++,
- &interface_data))
- {
- if (!SetupDiGetDeviceInterfaceDetailW(device_info_set, &interface_data, detail, sizeof(buffer), NULL, NULL))
- continue;
-
- if (!wcsstr(detail->DevicePath, L"IG_"))
- continue;
-
- if (find_opened_device(detail, &i)) continue; /* already opened */
- if (i == XUSER_MAX_COUNT) break; /* no more slots */
-
- device = CreateFileW(detail->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
- if (device == INVALID_HANDLE_VALUE)
- continue;
-
- ppd = NULL;
- if (!HidD_GetPreparsedData(device, &ppd))
- WARN("ignoring HID device, HidD_GetPreparsedData failed with error %u\n", GetLastError());
- else if ((status = HidP_GetCaps(ppd, &caps)) != HIDP_STATUS_SUCCESS)
- WARN("ignoring HID device, HidP_GetCaps returned %#x\n", status);
- else if (caps.UsagePage != HID_USAGE_PAGE_GENERIC)
- 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(&controllers[i], ppd, &caps, device, detail->DevicePath))
- WARN("ignoring HID device, failed to initialize\n");
- else
- continue;
-
- CloseHandle(device);
- HidD_FreePreparsedData(ppd);
- }
-
- SetupDiDestroyDeviceInfoList(device_info_set);
- LeaveCriticalSection(&xinput_crit);
}
static void remove_gamepad(xinput_controller *device)
diff --git a/dlls/xinput1_3/xinput_main.c b/dlls/xinput1_3/xinput_main.c
index 547247dc76e..56a5802fc6a 100644
--- a/dlls/xinput1_3/xinput_main.c
+++ b/dlls/xinput1_3/xinput_main.c
@@ -120,7 +120,7 @@ void WINAPI DECLSPEC_HOTPATCH XInputEnable(BOOL enable)
to the controllers. Setting to true will send the last vibration
value (sent to XInputSetState) to the controller and allow messages to
be sent */
- HID_find_gamepads();
+ HID_start_update_thread();
for (index = 0; index < XUSER_MAX_COUNT; index ++)
{
@@ -136,7 +136,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH XInputSetState(DWORD index, XINPUT_VIBRATION* vib
TRACE("(index %u, vibration %p)\n", index, vibration);
- HID_find_gamepads();
+ HID_start_update_thread();
if (index >= XUSER_MAX_COUNT)
return ERROR_BAD_ARGUMENTS;
@@ -157,7 +157,7 @@ static DWORD xinput_get_state(DWORD index, XINPUT_STATE *state)
if (!state)
return ERROR_BAD_ARGUMENTS;
- HID_find_gamepads();
+ HID_start_update_thread();
if (index >= XUSER_MAX_COUNT)
return ERROR_BAD_ARGUMENTS;
@@ -421,7 +421,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH XInputGetCapabilities(DWORD index, DWORD flags, X
{
TRACE("(index %u, flags 0x%x, capabilities %p)\n", index, flags, capabilities);
- HID_find_gamepads();
+ HID_start_update_thread();
if (index >= XUSER_MAX_COUNT)
return ERROR_BAD_ARGUMENTS;
diff --git a/dlls/xinput1_3/xinput_private.h b/dlls/xinput1_3/xinput_private.h
index 79c3023c543..b2bd8a1ed57 100644
--- a/dlls/xinput1_3/xinput_private.h
+++ b/dlls/xinput1_3/xinput_private.h
@@ -30,7 +30,7 @@ typedef struct _xinput_controller
extern CRITICAL_SECTION xinput_crit;
extern xinput_controller controllers[XUSER_MAX_COUNT];
-void HID_find_gamepads(void) DECLSPEC_HIDDEN;
+void HID_start_update_thread(void) DECLSPEC_HIDDEN;
void HID_stop_update_thread(void) DECLSPEC_HIDDEN;
void HID_update_state(xinput_controller* device, XINPUT_STATE *state) DECLSPEC_HIDDEN;
DWORD HID_set_state(xinput_controller* device, XINPUT_VIBRATION* state) DECLSPEC_HIDDEN;
--
2.32.0
More information about the wine-devel
mailing list