[PATCH 3/6] winebus.sys: Use the unixlib interface for the UDEV bus thread.

Rémi Bernon rbernon at codeweavers.com
Thu Aug 19 02:10:01 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/winebus.sys/bus.h          |   3 -
 dlls/winebus.sys/bus_udev.c     | 158 ++++++++++++++------------------
 dlls/winebus.sys/main.c         |  46 +++++++++-
 dlls/winebus.sys/unix_private.h |   4 +
 dlls/winebus.sys/unixlib.c      |   3 +
 dlls/winebus.sys/unixlib.h      |  10 ++
 6 files changed, 128 insertions(+), 96 deletions(-)

diff --git a/dlls/winebus.sys/bus.h b/dlls/winebus.sys/bus.h
index 2c2d26a1525..4618dea1396 100644
--- a/dlls/winebus.sys/bus.h
+++ b/dlls/winebus.sys/bus.h
@@ -28,9 +28,7 @@
 typedef int(*enum_func)(DEVICE_OBJECT *device, void *context);
 
 /* Buses */
-NTSTATUS udev_driver_init(void) DECLSPEC_HIDDEN;
 NTSTATUS iohid_driver_init(void) DECLSPEC_HIDDEN;
-void udev_driver_unload( void ) DECLSPEC_HIDDEN;
 void iohid_driver_unload( void ) DECLSPEC_HIDDEN;
 
 /* Native device function table */
@@ -58,7 +56,6 @@ void process_hid_report(DEVICE_OBJECT *device, BYTE *report, DWORD length) DECLS
 DEVICE_OBJECT *bus_enumerate_hid_devices(const WCHAR *bus_id, enum_func function, void *context) DECLSPEC_HIDDEN;
 
 /* General Bus Functions */
-DWORD check_bus_option(const UNICODE_STRING *option, DWORD default_value) DECLSPEC_HIDDEN;
 BOOL is_xbox_gamepad(WORD vid, WORD pid) DECLSPEC_HIDDEN;
 
 extern HANDLE driver_key DECLSPEC_HIDDEN;
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index 77a242a6087..51d846b3bed 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -80,6 +80,7 @@
 #endif
 
 #include "bus.h"
+#include "unix_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
 
@@ -87,11 +88,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
 
 WINE_DECLARE_DEBUG_CHANNEL(hid_report);
 
+static struct udev_bus_options options;
+
 static struct udev *udev_context = NULL;
-static DWORD disable_hidraw = 0;
-static DWORD disable_input = 0;
-static HANDLE deviceloop_handle;
+static struct udev_monitor *udev_monitor;
 static int deviceloop_control[2];
+static int udev_monitor_fd;
 
 static const WCHAR hidraw_busidW[] = {'H','I','D','R','A','W',0};
 static const WCHAR lnxev_busidW[] = {'L','N','X','E','V',0};
@@ -1179,11 +1181,11 @@ static void build_initial_deviceset(void)
         return;
     }
 
-    if (!disable_hidraw)
+    if (!options.disable_hidraw)
         if (udev_enumerate_add_match_subsystem(enumerate, "hidraw") < 0)
             WARN("Failed to add subsystem 'hidraw' to enumeration\n");
 #ifdef HAS_PROPER_INPUT_HEADER
-    if (!disable_input)
+    if (!options.disable_input)
     {
         if (udev_enumerate_add_match_subsystem(enumerate, "input") < 0)
             WARN("Failed to add subsystem 'input' to enumeration\n");
@@ -1210,7 +1212,7 @@ static void build_initial_deviceset(void)
     udev_enumerate_unref(enumerate);
 }
 
-static struct udev_monitor *create_monitor(struct pollfd *pfd)
+static struct udev_monitor *create_monitor(int *fd)
 {
     struct udev_monitor *monitor;
     int systems = 0;
@@ -1222,7 +1224,7 @@ static struct udev_monitor *create_monitor(struct pollfd *pfd)
         return NULL;
     }
 
-    if (!disable_hidraw)
+    if (!options.disable_hidraw)
     {
         if (udev_monitor_filter_add_match_subsystem_devtype(monitor, "hidraw", NULL) < 0)
             WARN("Failed to add 'hidraw' subsystem to monitor\n");
@@ -1230,7 +1232,7 @@ static struct udev_monitor *create_monitor(struct pollfd *pfd)
             systems++;
     }
 #ifdef HAS_PROPER_INPUT_HEADER
-    if (!disable_input)
+    if (!options.disable_input)
     {
         if (udev_monitor_filter_add_match_subsystem_devtype(monitor, "input", NULL) < 0)
             WARN("Failed to add 'input' subsystem to monitor\n");
@@ -1247,11 +1249,8 @@ static struct udev_monitor *create_monitor(struct pollfd *pfd)
     if (udev_monitor_enable_receiving(monitor) < 0)
         goto error;
 
-    if ((pfd->fd = udev_monitor_get_fd(monitor)) >= 0)
-    {
-        pfd->events = POLLIN;
+    if ((*fd = udev_monitor_get_fd(monitor)) >= 0)
         return monitor;
-    }
 
 error:
     WARN("Failed to start monitoring\n");
@@ -1287,118 +1286,95 @@ static void process_monitor_event(struct udev_monitor *monitor)
     udev_device_unref(dev);
 }
 
-static DWORD CALLBACK deviceloop_thread(void *args)
-{
-    struct udev_monitor *monitor;
-    HANDLE init_done = args;
-    struct pollfd pfd[2];
-
-    pfd[1].fd = deviceloop_control[0];
-    pfd[1].events = POLLIN;
-    pfd[1].revents = 0;
-
-    monitor = create_monitor(&pfd[0]);
-    build_initial_deviceset();
-    SetEvent(init_done);
-
-    while (monitor)
-    {
-        if (poll(pfd, 2, -1) <= 0) continue;
-        if (pfd[1].revents) break;
-        process_monitor_event(monitor);
-    }
-
-    TRACE("Monitor thread exiting\n");
-    if (monitor)
-        udev_monitor_unref(monitor);
-    return 0;
-}
-
-void udev_driver_unload( void )
+NTSTATUS WINAPI udev_bus_stop(void)
 {
-    TRACE("Unload Driver\n");
-
-    if (!deviceloop_handle)
-        return;
+    if (!udev_context) return STATUS_SUCCESS;
 
     write(deviceloop_control[1], "q", 1);
-    WaitForSingleObject(deviceloop_handle, INFINITE);
-    close(deviceloop_control[0]);
-    close(deviceloop_control[1]);
-    CloseHandle(deviceloop_handle);
+    return STATUS_SUCCESS;
 }
 
-NTSTATUS udev_driver_init(void)
+NTSTATUS WINAPI udev_bus_init(void *args)
 {
-    HANDLE events[2];
-    DWORD result;
-    static const WCHAR hidraw_disabledW[] = {'D','i','s','a','b','l','e','H','i','d','r','a','w',0};
-    static const UNICODE_STRING hidraw_disabled = {sizeof(hidraw_disabledW) - sizeof(WCHAR), sizeof(hidraw_disabledW), (WCHAR*)hidraw_disabledW};
-    static const WCHAR input_disabledW[] = {'D','i','s','a','b','l','e','I','n','p','u','t',0};
-    static const UNICODE_STRING input_disabled = {sizeof(input_disabledW) - sizeof(WCHAR), sizeof(input_disabledW), (WCHAR*)input_disabledW};
+    TRACE("args %p\n", args);
+
+    options = *(struct udev_bus_options *)args;
 
     if (pipe(deviceloop_control) != 0)
     {
-        ERR("Control pipe creation failed\n");
+        ERR("control pipe creation failed\n");
         return STATUS_UNSUCCESSFUL;
     }
 
     if (!(udev_context = udev_new()))
     {
-        ERR("Can't create udev object\n");
-        goto error;
+        ERR("udev object creation failed\n");
+        close(deviceloop_control[0]);
+        close(deviceloop_control[1]);
+        return STATUS_UNSUCCESSFUL;
     }
 
-    disable_hidraw = check_bus_option(&hidraw_disabled, 0);
-    if (disable_hidraw)
-        TRACE("UDEV hidraw devices disabled in registry\n");
-
-#ifdef HAS_PROPER_INPUT_HEADER
-    disable_input = check_bus_option(&input_disabled, 0);
-    if (disable_input)
-        TRACE("UDEV input devices disabled in registry\n");
-#endif
-
-    if (!(events[0] = CreateEventW(NULL, TRUE, FALSE, NULL)))
-        goto error;
-    if (!(events[1] = CreateThread(NULL, 0, deviceloop_thread, events[0], 0, NULL)))
+    if (!(udev_monitor = create_monitor(&udev_monitor_fd)))
     {
-        CloseHandle(events[0]);
-        goto error;
+        ERR("udev monitor creation failed\n");
+        close(deviceloop_control[0]);
+        close(deviceloop_control[1]);
+        udev_unref(udev_context);
+        udev_context = NULL;
+        return STATUS_UNSUCCESSFUL;
     }
 
-    result = WaitForMultipleObjects(2, events, FALSE, INFINITE);
-    CloseHandle(events[0]);
-    if (result == WAIT_OBJECT_0)
+    build_initial_deviceset();
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS WINAPI udev_bus_wait(void)
+{
+    struct pollfd pfd[2];
+
+    pfd[0].fd = udev_monitor_fd;
+    pfd[0].events = POLLIN;
+    pfd[0].revents = 0;
+    pfd[1].fd = deviceloop_control[0];
+    pfd[1].events = POLLIN;
+    pfd[1].revents = 0;
+
+    while (1)
     {
-        deviceloop_handle = events[1];
-        TRACE("Initialization successful\n");
-        return STATUS_SUCCESS;
+        if (poll(pfd, 2, -1) <= 0) continue;
+        if (pfd[1].revents) break;
+        process_monitor_event(udev_monitor);
     }
-    CloseHandle(events[1]);
 
-error:
-    ERR("Failed to initialize udev device thread\n");
+    TRACE("UDEV main loop exiting\n");
+    udev_monitor_unref(udev_monitor);
+
+    udev_unref(udev_context);
+    udev_context = NULL;
+
     close(deviceloop_control[0]);
     close(deviceloop_control[1]);
-    if (udev_context)
-    {
-        udev_unref(udev_context);
-        udev_context = NULL;
-    }
-    return STATUS_UNSUCCESSFUL;
+    return STATUS_SUCCESS;
 }
 
 #else
 
-NTSTATUS udev_driver_init(void)
+NTSTATUS WINAPI udev_bus_init(void *args)
+{
+    WARN("UDEV support not compiled in!\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS WINAPI udev_bus_wait(void)
 {
+    WARN("UDEV support not compiled in!\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
-void udev_driver_unload( void )
+NTSTATUS WINAPI udev_bus_stop(void)
 {
-    TRACE("Stub: Unload Driver\n");
+    WARN("UDEV support not compiled in!\n");
+    return STATUS_NOT_IMPLEMENTED;
 }
 
 #endif /* HAVE_UDEV */
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c
index a4b236cecb7..36a281bec9d 100644
--- a/dlls/winebus.sys/main.c
+++ b/dlls/winebus.sys/main.c
@@ -408,7 +408,7 @@ static NTSTATUS build_device_relations(DEVICE_RELATIONS **devices)
     return STATUS_SUCCESS;
 }
 
-DWORD check_bus_option(const UNICODE_STRING *option, DWORD default_value)
+static DWORD check_bus_option(const UNICODE_STRING *option, DWORD default_value)
 {
     char buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[sizeof(DWORD)])];
     KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
@@ -705,6 +705,48 @@ static NTSTATUS sdl_driver_init(void)
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS udev_driver_init(void)
+{
+    static const WCHAR udev_bus_name[] = {'U','D','E','V',0};
+    static const WCHAR hidraw_disabledW[] = {'D','i','s','a','b','l','e','H','i','d','r','a','w',0};
+    static const UNICODE_STRING hidraw_disabled = {sizeof(hidraw_disabledW) - sizeof(WCHAR), sizeof(hidraw_disabledW), (WCHAR*)hidraw_disabledW};
+    static const WCHAR input_disabledW[] = {'D','i','s','a','b','l','e','I','n','p','u','t',0};
+    static const UNICODE_STRING input_disabled = {sizeof(input_disabledW) - sizeof(WCHAR), sizeof(input_disabledW), (WCHAR*)input_disabledW};
+    struct udev_bus_options udev_params;
+    struct bus_main_params params =
+    {
+        .name = udev_bus_name,
+        .bus_init = unix_funcs->udev_bus_init,
+        .bus_wait = unix_funcs->udev_bus_wait,
+        .bus_params = &udev_params,
+    };
+    DWORD i = bus_count++;
+
+    if (!(params.init = CreateEventW(NULL, FALSE, FALSE, NULL)))
+    {
+        ERR("failed to create UDEV bus event.\n");
+        bus_count--;
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    udev_params.disable_hidraw = check_bus_option(&hidraw_disabled, 0);
+    if (udev_params.disable_hidraw) TRACE("UDEV hidraw devices disabled in registry\n");
+    udev_params.disable_input = check_bus_option(&input_disabled, 0);
+    if (udev_params.disable_input) TRACE("UDEV input devices disabled in registry\n");
+
+    if (!(bus_thread[i] = CreateThread(NULL, 0, bus_main_thread, &params, 0, NULL)))
+    {
+        ERR("failed to create UDEV bus thread.\n");
+        CloseHandle(params.init);
+        bus_count--;
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    WaitForSingleObject(params.init, INFINITE);
+    CloseHandle(params.init);
+    return STATUS_SUCCESS;
+}
+
 static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
 {
     static const WCHAR SDL_enabledW[] = {'E','n','a','b','l','e',' ','S','D','L',0};
@@ -733,8 +775,8 @@ static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
         irp->IoStatus.Status = STATUS_SUCCESS;
         break;
     case IRP_MN_REMOVE_DEVICE:
-        udev_driver_unload();
         iohid_driver_unload();
+        unix_funcs->udev_bus_stop();
         unix_funcs->sdl_bus_stop();
 
         WaitForMultipleObjects(bus_count, bus_thread, TRUE, INFINITE);
diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h
index 7ac882a03b2..8fb280ac7cd 100644
--- a/dlls/winebus.sys/unix_private.h
+++ b/dlls/winebus.sys/unix_private.h
@@ -31,4 +31,8 @@ extern NTSTATUS WINAPI sdl_bus_init(void *args) DECLSPEC_HIDDEN;
 extern NTSTATUS WINAPI sdl_bus_wait(void) DECLSPEC_HIDDEN;
 extern NTSTATUS WINAPI sdl_bus_stop(void) DECLSPEC_HIDDEN;
 
+extern NTSTATUS WINAPI udev_bus_init(void *args) DECLSPEC_HIDDEN;
+extern NTSTATUS WINAPI udev_bus_wait(void) DECLSPEC_HIDDEN;
+extern NTSTATUS WINAPI udev_bus_stop(void) DECLSPEC_HIDDEN;
+
 #endif /* __WINEBUS_UNIX_PRIVATE_H */
diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c
index 832a20372d6..cbd29ceecd1 100644
--- a/dlls/winebus.sys/unixlib.c
+++ b/dlls/winebus.sys/unixlib.c
@@ -36,6 +36,9 @@ static const struct unix_funcs unix_funcs =
     sdl_bus_init,
     sdl_bus_wait,
     sdl_bus_stop,
+    udev_bus_init,
+    udev_bus_wait,
+    udev_bus_stop,
 };
 
 NTSTATUS CDECL __wine_init_unix_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
diff --git a/dlls/winebus.sys/unixlib.h b/dlls/winebus.sys/unixlib.h
index a5cd57867e4..cd1bce096c7 100644
--- a/dlls/winebus.sys/unixlib.h
+++ b/dlls/winebus.sys/unixlib.h
@@ -32,11 +32,21 @@ struct sdl_bus_options
     BOOL map_controllers;
 };
 
+struct udev_bus_options
+{
+    BOOL disable_hidraw;
+    BOOL disable_input;
+};
+
 struct unix_funcs
 {
     NTSTATUS (WINAPI *sdl_bus_init)(void *);
     NTSTATUS (WINAPI *sdl_bus_wait)(void);
     NTSTATUS (WINAPI *sdl_bus_stop)(void);
+
+    NTSTATUS (WINAPI *udev_bus_init)(void *);
+    NTSTATUS (WINAPI *udev_bus_wait)(void);
+    NTSTATUS (WINAPI *udev_bus_stop)(void);
 };
 
 #endif /* __WINEBUS_UNIXLIB_H */
-- 
2.32.0




More information about the wine-devel mailing list