Signed-off-by: Rémi Bernon rbernon@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, ¶ms, 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 */