[PATCH 1/7] winebus.sys: Pass a unix_device pointer in every bus event.

Rémi Bernon rbernon at codeweavers.com
Thu Sep 16 03:17:52 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/winebus.sys/bus_iohid.c    | 38 +++++++++++++++++++++--
 dlls/winebus.sys/bus_sdl.c      |  4 ++-
 dlls/winebus.sys/bus_udev.c     | 25 ++++++++++------
 dlls/winebus.sys/main.c         | 53 +++++----------------------------
 dlls/winebus.sys/unix_private.h |  2 +-
 dlls/winebus.sys/unixlib.c      | 17 ++++++-----
 dlls/winebus.sys/unixlib.h      |  9 +-----
 7 files changed, 75 insertions(+), 73 deletions(-)

diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c
index 8bdd7857ae6..492d5a70ddb 100644
--- a/dlls/winebus.sys/bus_iohid.c
+++ b/dlls/winebus.sys/bus_iohid.c
@@ -95,9 +95,19 @@
 WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
 #ifdef HAVE_IOHIDMANAGERCREATE
 
+static CRITICAL_SECTION iohid_cs;
+static CRITICAL_SECTION_DEBUG iohid_cs_debug =
+{
+    0, 0, &iohid_cs,
+    { &iohid_cs_debug.ProcessLocksList, &iohid_cs_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": iohid_cs") }
+};
+static CRITICAL_SECTION iohid_cs = { &iohid_cs_debug, -1, 0, 0, 0, 0 };
+
 static IOHIDManagerRef hid_manager;
 static CFRunLoopRef run_loop;
 static struct list event_queue = LIST_INIT(event_queue);
+static struct list device_list = LIST_INIT(device_list);
 
 static const WCHAR busidW[] = {'I','O','H','I','D',0};
 static struct iohid_bus_options options;
@@ -114,6 +124,16 @@ static inline struct platform_private *impl_from_unix_device(struct unix_device
     return CONTAINING_RECORD(iface, struct platform_private, unix_device);
 }
 
+static struct platform_private *find_device_from_iohid(IOHIDDeviceRef IOHIDDevice)
+{
+    struct platform_private *private;
+
+    LIST_FOR_EACH_ENTRY(private, &device_list, struct platform_private, unix_device.entry)
+        if (!private->device == IOHIDDevice) return private;
+
+    return NULL;
+}
+
 static void CFStringToWSTR(CFStringRef cstr, LPWSTR wstr, int length)
 {
     int len = min(CFStringGetLength(cstr), length-1);
@@ -170,6 +190,10 @@ static void iohid_device_stop(struct unix_device *iface)
     struct platform_private *private = impl_from_unix_device(iface);
 
     IOHIDDeviceRegisterInputReportCallback(private->device, NULL, 0, NULL, NULL);
+
+    EnterCriticalSection(&iohid_cs);
+    list_remove(&private->unix_device.entry);
+    LeaveCriticalSection(&iohid_cs);
 }
 
 static NTSTATUS iohid_device_get_report_descriptor(struct unix_device *iface, BYTE *buffer,
@@ -336,6 +360,7 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void *
     TRACE("dev %p, desc %s.\n", IOHIDDevice, debugstr_device_desc(&desc));
 
     if (!(private = unix_device_create(&iohid_device_vtbl, sizeof(struct platform_private)))) return;
+    list_add_tail(&device_list, &private->unix_device.entry);
     private->device = IOHIDDevice;
     private->buffer = NULL;
 
@@ -344,13 +369,18 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void *
 
 static void handle_RemovalCallback(void *context, IOReturn result, void *sender, IOHIDDeviceRef IOHIDDevice)
 {
+    struct platform_private *device;
+
     TRACE("OS/X IOHID Device Removed %p\n", IOHIDDevice);
     IOHIDDeviceRegisterInputReportCallback(IOHIDDevice, NULL, 0, NULL, NULL);
     /* Note: Yes, we leak the buffer. But according to research there is no
              safe way to deallocate that buffer. */
     IOHIDDeviceUnscheduleFromRunLoop(IOHIDDevice, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
     IOHIDDeviceClose(IOHIDDevice, 0);
-    bus_event_queue_device_removed(&event_queue, busidW, IOHIDDevice);
+
+    device = find_device_from_iohid(IOHIDDevice);
+    if (device) bus_event_queue_device_removed(&event_queue, &device->unix_device);
+    else WARN("failed to find device for iohid device %p\n", IOHIDDevice);
 }
 
 NTSTATUS iohid_bus_init(void *args)
@@ -377,6 +407,7 @@ NTSTATUS iohid_bus_init(void *args)
 NTSTATUS iohid_bus_wait(void *args)
 {
     struct bus_event *result = args;
+    CFRunLoopRunResult ret;
 
     /* cleanup previously returned event */
     bus_event_cleanup(result);
@@ -384,7 +415,10 @@ NTSTATUS iohid_bus_wait(void *args)
     do
     {
         if (bus_event_queue_pop(&event_queue, result)) return STATUS_PENDING;
-    } while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, TRUE) != kCFRunLoopRunStopped);
+        EnterCriticalSection(&iohid_cs);
+        ret = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, TRUE);
+        LeaveCriticalSection(&iohid_cs);
+    } while (ret != kCFRunLoopRunStopped);
 
     TRACE("IOHID main loop exiting\n");
     bus_event_queue_destroy(&event_queue);
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c
index 6a6f364edf6..d48f9507abb 100644
--- a/dlls/winebus.sys/bus_sdl.c
+++ b/dlls/winebus.sys/bus_sdl.c
@@ -799,7 +799,9 @@ static void process_device_event(SDL_Event *event)
     else if (event->type == SDL_JOYDEVICEREMOVED)
     {
         id = ((SDL_JoyDeviceEvent *)event)->which;
-        bus_event_queue_device_removed(&event_queue, sdl_busidW, ULongToPtr(id));
+        device = find_device_from_id(id);
+        if (device) bus_event_queue_device_removed(&event_queue, &device->unix_device);
+        else WARN("failed to find device with id %d\n", id);
     }
     else if (event->type >= SDL_JOYAXISMOTION && event->type <= SDL_JOYBUTTONUP)
     {
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index 23b649ff511..8cbcabf25e8 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -200,6 +200,16 @@ static struct platform_private *find_device_from_syspath(const char *path)
     return NULL;
 }
 
+static struct platform_private *find_device_from_udev(struct udev_device *dev)
+{
+    struct platform_private *device;
+
+    LIST_FOR_EACH_ENTRY(device, &device_list, struct platform_private, unix_device.entry)
+        if (device->udev_device == dev) return device;
+
+    return NULL;
+}
+
 #ifdef HAS_PROPER_INPUT_HEADER
 
 static const BYTE ABS_TO_HID_MAP[][2] = {
@@ -1062,14 +1072,6 @@ static void udev_add_device(struct udev_device *dev)
 #endif
 }
 
-static void try_remove_device(struct udev_device *dev)
-{
-    bus_event_queue_device_removed(&event_queue, hidraw_busidW, dev);
-#ifdef HAS_PROPER_INPUT_HEADER
-    bus_event_queue_device_removed(&event_queue, lnxev_busidW, dev);
-#endif
-}
-
 static void build_initial_deviceset(void)
 {
     struct udev_enumerate *enumerate;
@@ -1161,6 +1163,7 @@ error:
 
 static void process_monitor_event(struct udev_monitor *monitor)
 {
+    struct platform_private *device;
     struct udev_device *dev;
     const char *action;
 
@@ -1180,7 +1183,11 @@ static void process_monitor_event(struct udev_monitor *monitor)
     else if (strcmp(action, "add") == 0)
         udev_add_device(dev);
     else if (strcmp(action, "remove") == 0)
-        try_remove_device(dev);
+    {
+        device = find_device_from_udev(dev);
+        if (device) bus_event_queue_device_removed(&event_queue, &device->unix_device);
+        else WARN("failed to find device for udev device %p\n", dev);
+    }
     else
         WARN("Unhandled action %s\n", debugstr_a(action));
 
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c
index 162787c4e4a..a80bd8a186e 100644
--- a/dlls/winebus.sys/main.c
+++ b/dlls/winebus.sys/main.c
@@ -146,17 +146,6 @@ static void unix_device_remove(DEVICE_OBJECT *device)
     winebus_call(device_remove, ext->unix_device);
 }
 
-static int unix_device_compare(DEVICE_OBJECT *device, void *context)
-{
-    struct device_extension *ext = (struct device_extension *)device->DeviceExtension;
-    struct device_compare_params params =
-    {
-        .iface = ext->unix_device,
-        .context = context
-    };
-    return winebus_call(device_compare, &params);
-}
-
 static NTSTATUS unix_device_start(DEVICE_OBJECT *device)
 {
     struct device_extension *ext = (struct device_extension *)device->DeviceExtension;
@@ -359,29 +348,6 @@ static DEVICE_OBJECT *bus_create_hid_device(struct device_desc *desc, struct uni
     return device;
 }
 
-static DEVICE_OBJECT *bus_find_hid_device(const WCHAR *bus_id, void *platform_dev)
-{
-    struct device_extension *ext;
-    DEVICE_OBJECT *ret = NULL;
-
-    TRACE("bus_id %s, platform_dev %p\n", debugstr_w(bus_id), platform_dev);
-
-    EnterCriticalSection(&device_list_cs);
-    LIST_FOR_EACH_ENTRY(ext, &device_list, struct device_extension, entry)
-    {
-        if (strcmpW(ext->desc.busid, bus_id)) continue;
-        if (unix_device_compare(ext->device, platform_dev) == 0)
-        {
-            ret = ext->device;
-            break;
-        }
-    }
-    LeaveCriticalSection(&device_list_cs);
-
-    TRACE("returning %p\n", ret);
-    return ret;
-}
-
 static DEVICE_OBJECT *bus_find_unix_device(struct unix_device *unix_device)
 {
     struct device_extension *ext;
@@ -625,28 +591,25 @@ static DWORD CALLBACK bus_main_thread(void *args)
         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);
+            device = bus_find_unix_device(event->device);
+            if (!device) WARN("could not find device for %s bus device %p\n", debugstr_w(bus.name), event->device);
+            else bus_unlink_hid_device(device);
             LeaveCriticalSection(&device_list_cs);
             IoInvalidateDeviceRelations(bus_pdo, BusRelations);
             break;
         case BUS_EVENT_TYPE_DEVICE_CREATED:
-            device = bus_create_hid_device(&event->device_created.desc, event->device_created.device);
+            device = bus_create_hid_device(&event->device_created.desc, event->device);
             if (device) IoInvalidateDeviceRelations(bus_pdo, BusRelations);
             else
             {
-                WARN("failed to create device for %s bus device %p\n",
-                     debugstr_w(bus.name), event->device_created.device);
-                winebus_call(device_remove, event->device_created.device);
+                WARN("failed to create device for %s bus device %p\n", debugstr_w(bus.name), event->device);
+                winebus_call(device_remove, event->device);
             }
             break;
         case BUS_EVENT_TYPE_INPUT_REPORT:
             EnterCriticalSection(&device_list_cs);
-            device = bus_find_unix_device(event->input_report.device);
-            if (!device) WARN("could not find device for %s bus device %p\n", debugstr_w(bus.name), event->input_report.device);
+            device = bus_find_unix_device(event->device);
+            if (!device) WARN("could not find device for %s bus device %p\n", debugstr_w(bus.name), event->device);
             else process_hid_report(device, event->input_report.buffer, event->input_report.length);
             LeaveCriticalSection(&device_list_cs);
             break;
diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h
index 3f8d73d033a..9b2c6d81fa2 100644
--- a/dlls/winebus.sys/unix_private.h
+++ b/dlls/winebus.sys/unix_private.h
@@ -64,7 +64,7 @@ extern NTSTATUS iohid_bus_stop(void *) DECLSPEC_HIDDEN;
 
 extern void bus_event_cleanup(struct bus_event *event) 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_device_removed(struct list *queue, struct unix_device *device) DECLSPEC_HIDDEN;
 extern BOOL bus_event_queue_device_created(struct list *queue, struct unix_device *device, struct device_desc *desc) DECLSPEC_HIDDEN;
 extern BOOL bus_event_queue_input_report(struct list *queue, struct unix_device *device,
                                          BYTE *report, USHORT length) DECLSPEC_HIDDEN;
diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c
index 87cc7de3474..008fb6e77a2 100644
--- a/dlls/winebus.sys/unixlib.c
+++ b/dlls/winebus.sys/unixlib.c
@@ -343,8 +343,8 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
 
 void bus_event_cleanup(struct bus_event *event)
 {
-    if (event->type == BUS_EVENT_TYPE_INPUT_REPORT)
-        unix_device_decref(event->input_report.device);
+    if (event->type == BUS_EVENT_TYPE_NONE) return;
+    unix_device_decref(event->device);
 }
 
 void bus_event_queue_destroy(struct list *queue)
@@ -358,15 +358,16 @@ void bus_event_queue_destroy(struct list *queue)
     }
 }
 
-BOOL bus_event_queue_device_removed(struct list *queue, const WCHAR *bus_id, void *context)
+BOOL bus_event_queue_device_removed(struct list *queue, struct unix_device *device)
 {
     ULONG size = sizeof(struct bus_event);
     struct bus_event *event = HeapAlloc(GetProcessHeap(), 0, size);
     if (!event) return FALSE;
 
+    if (unix_device_incref(device) == 1) return FALSE; /* being destroyed */
+
     event->type = BUS_EVENT_TYPE_DEVICE_REMOVED;
-    event->device_removed.bus_id = bus_id;
-    event->device_removed.context = context;
+    event->device = device;
     list_add_tail(queue, &event->entry);
 
     return TRUE;
@@ -378,8 +379,10 @@ BOOL bus_event_queue_device_created(struct list *queue, struct unix_device *devi
     struct bus_event *event = HeapAlloc(GetProcessHeap(), 0, size);
     if (!event) return FALSE;
 
+    if (unix_device_incref(device) == 1) return FALSE; /* being destroyed */
+
     event->type = BUS_EVENT_TYPE_DEVICE_CREATED;
-    event->device_created.device = device;
+    event->device = device;
     event->device_created.desc = *desc;
     list_add_tail(queue, &event->entry);
 
@@ -395,7 +398,7 @@ BOOL bus_event_queue_input_report(struct list *queue, struct unix_device *device
     if (unix_device_incref(device) == 1) return FALSE; /* being destroyed */
 
     event->type = BUS_EVENT_TYPE_INPUT_REPORT;
-    event->input_report.device = device;
+    event->device = device;
     event->input_report.length = length;
     memcpy(event->input_report.buffer, report, length);
     list_add_tail(queue, &event->entry);
diff --git a/dlls/winebus.sys/unixlib.h b/dlls/winebus.sys/unixlib.h
index 61684d0c0af..cd5f64cbb51 100644
--- a/dlls/winebus.sys/unixlib.h
+++ b/dlls/winebus.sys/unixlib.h
@@ -76,23 +76,16 @@ struct bus_event
     enum bus_event_type type;
     struct list entry;
 
+    struct unix_device *device;
     union
     {
         struct
         {
-            const WCHAR *bus_id;
-            void *context;
-        } device_removed;
-
-        struct
-        {
-            struct unix_device *device;
             struct device_desc desc;
         } device_created;
 
         struct
         {
-            struct unix_device *device;
             USHORT length;
             BYTE buffer[1];
         } input_report;
-- 
2.33.0




More information about the wine-devel mailing list