Rémi Bernon : winebus.sys: Return an event from SDL bus wait on device removal.
Alexandre Julliard
julliard at winehq.org
Thu Sep 2 15:45:30 CDT 2021
Module: wine
Branch: master
Commit: 6006758ca87d7e38fb4b84bafe917e108524029f
URL: https://source.winehq.org/git/wine.git/?a=commit;h=6006758ca87d7e38fb4b84bafe917e108524029f
Author: Rémi Bernon <rbernon at codeweavers.com>
Date: Mon Aug 30 11:22:52 2021 +0200
winebus.sys: Return an event from SDL bus wait on device removal.
Instead of calling bus_unlink_hid_device or IoInvalidateDeviceRelations.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/winebus.sys/bus_sdl.c | 14 +++++---------
dlls/winebus.sys/main.c | 20 +++++++++++++++++++-
dlls/winebus.sys/unix_private.h | 6 ++++++
dlls/winebus.sys/unixlib.c | 39 +++++++++++++++++++++++++++++++++++++++
dlls/winebus.sys/unixlib.h | 12 ++++++++++++
5 files changed, 81 insertions(+), 10 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c
index 8259531779b..e8ae69633c0 100644
--- a/dlls/winebus.sys/bus_sdl.c
+++ b/dlls/winebus.sys/bus_sdl.c
@@ -64,6 +64,7 @@ static struct sdl_bus_options options;
static void *sdl_handle = NULL;
static UINT quit_event = -1;
+static struct list event_queue = LIST_INIT(event_queue);
#define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
MAKE_FUNCPTR(SDL_GetError);
@@ -730,12 +731,6 @@ static BOOL set_mapped_report_from_event(DEVICE_OBJECT *device, SDL_Event *event
return FALSE;
}
-static void try_remove_device(DEVICE_OBJECT *device)
-{
- bus_unlink_hid_device(device);
- IoInvalidateDeviceRelations(bus_pdo, BusRelations);
-}
-
static void try_add_device(unsigned int index)
{
DWORD vid = 0, pid = 0, version = 0;
@@ -821,9 +816,7 @@ static void process_device_event(SDL_Event *event)
else if (event->type == SDL_JOYDEVICEREMOVED)
{
id = ((SDL_JoyDeviceEvent *)event)->which;
- device = bus_find_hid_device(sdl_busidW, ULongToPtr(id));
- if (device) try_remove_device(device);
- else WARN("failed to find device with id %d\n", id);
+ bus_event_queue_device_removed(&event_queue, sdl_busidW, ULongToPtr(id));
}
else if (event->type >= SDL_JOYAXISMOTION && event->type <= SDL_JOYBUTTONUP)
{
@@ -980,15 +973,18 @@ failed:
NTSTATUS sdl_bus_wait(void *args)
{
+ struct bus_event *result = args;
SDL_Event event;
do
{
+ if (bus_event_queue_pop(&event_queue, result)) return STATUS_PENDING;
if (pSDL_WaitEvent(&event) != 0) process_device_event(&event);
else WARN("SDL_WaitEvent failed: %s\n", pSDL_GetError());
} while (event.type != quit_event);
TRACE("SDL main loop exiting\n");
+ bus_event_queue_destroy(&event_queue);
dlclose(sdl_handle);
sdl_handle = NULL;
return STATUS_SUCCESS;
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c
index 4c8c84ffe9b..ec5e7715488 100644
--- a/dlls/winebus.sys/main.c
+++ b/dlls/winebus.sys/main.c
@@ -654,6 +654,7 @@ struct bus_main_params
static DWORD CALLBACK bus_main_thread(void *args)
{
struct bus_main_params bus = *(struct bus_main_params *)args;
+ DEVICE_OBJECT *device;
NTSTATUS status;
TRACE("%s main loop starting\n", debugstr_w(bus.name));
@@ -663,7 +664,24 @@ static DWORD CALLBACK bus_main_thread(void *args)
bus.bus_event->type = BUS_EVENT_TYPE_NONE;
if (status) WARN("%s bus init returned status %#x\n", debugstr_w(bus.name), status);
- else while ((status = winebus_call(bus.wait_code, bus.bus_event)) == STATUS_PENDING) {}
+ else while ((status = winebus_call(bus.wait_code, bus.bus_event)) == STATUS_PENDING)
+ {
+ struct bus_event *event = bus.bus_event;
+ switch (event->type)
+ {
+ case BUS_EVENT_TYPE_NONE: break;
+ case BUS_EVENT_TYPE_DEVICE_REMOVED:
+ EnterCriticalSection(&device_list_cs);
+ if (!(device = bus_find_hid_device(event->device_removed.bus_id, event->device_removed.context)))
+ WARN("could not find removed device matching bus %s, context %p\n",
+ debugstr_w(event->device_removed.bus_id), event->device_removed.context);
+ else
+ bus_unlink_hid_device(device);
+ LeaveCriticalSection(&device_list_cs);
+ IoInvalidateDeviceRelations(bus_pdo, BusRelations);
+ break;
+ }
+ }
if (status) WARN("%s bus wait returned status %#x\n", debugstr_w(bus.name), status);
else TRACE("%s main loop exited\n", debugstr_w(bus.name));
diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h
index aff1e86263a..f3edef83cb7 100644
--- a/dlls/winebus.sys/unix_private.h
+++ b/dlls/winebus.sys/unix_private.h
@@ -27,6 +27,8 @@
#include "unixlib.h"
+#include "wine/list.h"
+
struct unix_device
{
};
@@ -43,4 +45,8 @@ extern NTSTATUS iohid_bus_init(void *) DECLSPEC_HIDDEN;
extern NTSTATUS iohid_bus_wait(void *) DECLSPEC_HIDDEN;
extern NTSTATUS iohid_bus_stop(void *) DECLSPEC_HIDDEN;
+extern void bus_event_queue_destroy(struct list *queue) DECLSPEC_HIDDEN;
+extern BOOL bus_event_queue_device_removed(struct list *queue, const WCHAR *bus_id, void *context) DECLSPEC_HIDDEN;
+extern BOOL bus_event_queue_pop(struct list *queue, struct bus_event *event) DECLSPEC_HIDDEN;
+
#endif /* __WINEBUS_UNIX_PRIVATE_H */
diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c
index c4090861675..13e2729e0c2 100644
--- a/dlls/winebus.sys/unixlib.c
+++ b/dlls/winebus.sys/unixlib.c
@@ -26,6 +26,7 @@
#include "winternl.h"
#include "wine/debug.h"
+#include "wine/list.h"
#include "wine/unixlib.h"
#include "unix_private.h"
@@ -42,3 +43,41 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
iohid_bus_wait,
iohid_bus_stop,
};
+
+void bus_event_queue_destroy(struct list *queue)
+{
+ struct bus_event *event, *next;
+
+ LIST_FOR_EACH_ENTRY_SAFE(event, next, queue, struct bus_event, entry)
+ HeapFree(GetProcessHeap(), 0, event);
+}
+
+BOOL bus_event_queue_device_removed(struct list *queue, const WCHAR *bus_id, void *context)
+{
+ ULONG size = sizeof(struct bus_event);
+ struct bus_event *event = HeapAlloc(GetProcessHeap(), 0, size);
+ if (!event) return FALSE;
+
+ event->type = BUS_EVENT_TYPE_DEVICE_REMOVED;
+ event->device_removed.bus_id = bus_id;
+ event->device_removed.context = context;
+ list_add_tail(queue, &event->entry);
+
+ return TRUE;
+}
+
+BOOL bus_event_queue_pop(struct list *queue, struct bus_event *event)
+{
+ struct list *entry = list_head(queue);
+ struct bus_event *tmp;
+
+ if (!entry) return FALSE;
+
+ tmp = LIST_ENTRY(entry, struct bus_event, entry);
+ list_remove(entry);
+
+ memcpy(event, tmp, sizeof(*event));
+ HeapFree(GetProcessHeap(), 0, tmp);
+
+ return TRUE;
+}
diff --git a/dlls/winebus.sys/unixlib.h b/dlls/winebus.sys/unixlib.h
index e6abd98601f..d9097ba9ca7 100644
--- a/dlls/winebus.sys/unixlib.h
+++ b/dlls/winebus.sys/unixlib.h
@@ -27,6 +27,7 @@
#include <ddk/wdm.h>
#include <hidusage.h>
+#include "wine/list.h"
#include "wine/unixlib.h"
struct sdl_bus_options
@@ -49,11 +50,22 @@ struct unix_device;
enum bus_event_type
{
BUS_EVENT_TYPE_NONE,
+ BUS_EVENT_TYPE_DEVICE_REMOVED,
};
struct bus_event
{
enum bus_event_type type;
+ struct list entry;
+
+ union
+ {
+ struct
+ {
+ const WCHAR *bus_id;
+ void *context;
+ } device_removed;
+ };
};
enum unix_funcs
More information about the wine-cvs
mailing list