[PATCH 1/3] xinput1_3: Create a new background update thread.
Rémi Bernon
rbernon at codeweavers.com
Fri Aug 6 04:05:56 CDT 2021
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/xinput1_3/hid.c | 49 ++++++++++++++++++++++++++++++++-
dlls/xinput1_3/xinput_main.c | 2 +-
dlls/xinput1_3/xinput_private.h | 2 +-
3 files changed, 50 insertions(+), 3 deletions(-)
diff --git a/dlls/xinput1_3/hid.c b/dlls/xinput1_3/hid.c
index 00907b54bed..176e18fd95c 100644
--- a/dlls/xinput1_3/hid.c
+++ b/dlls/xinput1_3/hid.c
@@ -70,6 +70,8 @@ struct hid_platform_private {
};
static DWORD last_check = 0;
+static HANDLE stop_event;
+static HANDLE done_event;
static BOOL find_opened_device(SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail, int *free_slot)
{
@@ -85,6 +87,40 @@ static BOOL find_opened_device(SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail, int *f
return FALSE;
}
+static DWORD WINAPI hid_update_thread_proc(void *param)
+{
+ HANDLE events[1];
+ DWORD count, ret;
+
+ do
+ {
+ count = 0;
+ events[count++] = stop_event;
+ }
+ while ((ret = WaitForMultipleObjectsEx( count, events, FALSE, INFINITE, TRUE )) < count - 1);
+
+ if (ret != count - 1) ERR("update thread exited unexpectedly, ret %u\n", ret);
+ SetEvent(done_event);
+ return ret;
+}
+
+static BOOL WINAPI start_update_thread( INIT_ONCE *once, void *param, void **context )
+{
+ HANDLE thread;
+
+ stop_event = CreateEventA(NULL, FALSE, FALSE, NULL);
+ if (!stop_event) ERR("failed to create stop event, error %u\n", GetLastError());
+
+ done_event = CreateEventA(NULL, FALSE, FALSE, NULL);
+ if (!done_event) ERR("failed to create stop event, error %u\n", GetLastError());
+
+ thread = CreateThread(NULL, 0, hid_update_thread_proc, NULL, 0, NULL);
+ if (!thread) ERR("failed to create update thread, error %u\n", GetLastError());
+ CloseHandle(thread);
+
+ return TRUE;
+}
+
static void MarkUsage(struct hid_platform_private *private, WORD usage, LONG min, LONG max, USHORT bits)
{
struct axis_info info = {min, max-min, bits};
@@ -223,6 +259,8 @@ failed:
void HID_find_gamepads(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;
@@ -235,6 +273,8 @@ void HID_find_gamepads(void)
DWORD idx;
int i;
+ InitOnceExecuteOnce(&init_once, start_update_thread, NULL, NULL);
+
idx = GetTickCount();
if ((idx - last_check) < 2000)
return;
@@ -317,9 +357,16 @@ static void remove_gamepad(xinput_controller *device)
LeaveCriticalSection(&device->crit);
}
-void HID_destroy_gamepads(void)
+void HID_stop_update_thread(void)
{
int i;
+
+ SetEvent(stop_event);
+ WaitForSingleObject(done_event, INFINITE);
+
+ CloseHandle(stop_event);
+ CloseHandle(done_event);
+
for (i = 0; i < XUSER_MAX_COUNT; i++)
remove_gamepad(&controllers[i]);
}
diff --git a/dlls/xinput1_3/xinput_main.c b/dlls/xinput1_3/xinput_main.c
index 2d9f54c83f2..547247dc76e 100644
--- a/dlls/xinput1_3/xinput_main.c
+++ b/dlls/xinput1_3/xinput_main.c
@@ -104,7 +104,7 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
break;
case DLL_PROCESS_DETACH:
if (reserved) break;
- HID_destroy_gamepads();
+ HID_stop_update_thread();
break;
}
return TRUE;
diff --git a/dlls/xinput1_3/xinput_private.h b/dlls/xinput1_3/xinput_private.h
index 2bf16c0ffce..79c3023c543 100644
--- a/dlls/xinput1_3/xinput_private.h
+++ b/dlls/xinput1_3/xinput_private.h
@@ -31,7 +31,7 @@ extern CRITICAL_SECTION xinput_crit;
extern xinput_controller controllers[XUSER_MAX_COUNT];
void HID_find_gamepads(void) DECLSPEC_HIDDEN;
-void HID_destroy_gamepads(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;
void HID_enable(xinput_controller* device, BOOL enable) DECLSPEC_HIDDEN;
--
2.32.0
More information about the wine-devel
mailing list