Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
Supersedes: 211939-211944
v2: Move the threads first, introduce the unixlib next. Use a new unixlib style interface directly from the start but share the entry point table directly instead of using __wine_unix_call.
dlls/winebus.sys/bus.h | 6 +- dlls/winebus.sys/bus_sdl.c | 150 +++++++++++++++---------------------- dlls/winebus.sys/main.c | 85 ++++++++++++++++++--- 3 files changed, 139 insertions(+), 102 deletions(-)
diff --git a/dlls/winebus.sys/bus.h b/dlls/winebus.sys/bus.h index 3e53b9c53f1..c5b93b769c9 100644 --- a/dlls/winebus.sys/bus.h +++ b/dlls/winebus.sys/bus.h @@ -30,10 +30,12 @@ typedef int(*enum_func)(DEVICE_OBJECT *device, void *context); /* Buses */ NTSTATUS udev_driver_init(void) DECLSPEC_HIDDEN; NTSTATUS iohid_driver_init(void) DECLSPEC_HIDDEN; -NTSTATUS sdl_driver_init(void) DECLSPEC_HIDDEN; void udev_driver_unload( void ) DECLSPEC_HIDDEN; void iohid_driver_unload( void ) DECLSPEC_HIDDEN; -void sdl_driver_unload( void ) DECLSPEC_HIDDEN; + +extern NTSTATUS sdl_bus_init(void *) DECLSPEC_HIDDEN; +extern NTSTATUS sdl_bus_wait(void *) DECLSPEC_HIDDEN; +extern NTSTATUS sdl_bus_stop(void *) DECLSPEC_HIDDEN;
/* Native device function table */ typedef struct diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 84e3ef20664..02509f1560c 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -63,7 +63,6 @@ static const WCHAR sdl_busidW[] = {'S','D','L','J','O','Y',0}; static DWORD map_controllers = 0;
static void *sdl_handle = NULL; -static HANDLE deviceloop_handle; static UINT quit_event = -1;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL @@ -889,68 +888,15 @@ static void sdl_load_mappings(void) } }
-static DWORD CALLBACK deviceloop_thread(void *args) +NTSTATUS sdl_bus_init(void *args) { - HANDLE init_done = args; - SDL_Event event; - - if (pSDL_Init(SDL_INIT_GAMECONTROLLER|SDL_INIT_HAPTIC) < 0) - { - ERR("Can't init SDL: %s\n", pSDL_GetError()); - return STATUS_UNSUCCESSFUL; - } - - pSDL_JoystickEventState(SDL_ENABLE); - pSDL_GameControllerEventState(SDL_ENABLE); - - /* Process mappings */ - if (pSDL_GameControllerAddMapping != NULL) sdl_load_mappings(); - - SetEvent(init_done); - - while (1) { - while (pSDL_WaitEvent(&event) != 0) { - if (event.type == quit_event) { - TRACE("Device thread exiting\n"); - return 0; - } - process_device_event(&event); - } - } -} - -void sdl_driver_unload( void ) -{ - SDL_Event event; - - TRACE("Unload Driver\n"); - - if (!deviceloop_handle) - return; - - quit_event = pSDL_RegisterEvents(1); - if (quit_event == -1) { - ERR("error registering quit event\n"); - return; - } - - event.type = quit_event; - if (pSDL_PushEvent(&event) != 1) { - ERR("error pushing quit event\n"); - return; - } - - WaitForSingleObject(deviceloop_handle, INFINITE); - CloseHandle(deviceloop_handle); - dlclose(sdl_handle); -} + static const WCHAR controller_modeW[] = {'M','a','p',' ','C','o','n','t','r','o','l','l','e','r','s',0}; + static const UNICODE_STRING controller_mode = {sizeof(controller_modeW) - sizeof(WCHAR), sizeof(controller_modeW), (WCHAR*)controller_modeW};
-static BOOL sdl_initialize(void) -{ if (!(sdl_handle = dlopen(SONAME_LIBSDL2, RTLD_NOW))) { WARN("could not load %s\n", SONAME_LIBSDL2); - return FALSE; + return STATUS_UNSUCCESSFUL; } #define LOAD_FUNCPTR(f) \ if ((p##f = dlsym(sdl_handle, #f)) == NULL) \ @@ -1000,63 +946,85 @@ static BOOL sdl_initialize(void) pSDL_JoystickGetProduct = dlsym(sdl_handle, "SDL_JoystickGetProduct"); pSDL_JoystickGetProductVersion = dlsym(sdl_handle, "SDL_JoystickGetProductVersion"); pSDL_JoystickGetVendor = dlsym(sdl_handle, "SDL_JoystickGetVendor"); - return TRUE; + + if (pSDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) < 0) + { + ERR("could not init SDL: %s\n", pSDL_GetError()); + goto failed; + } + + if ((quit_event = pSDL_RegisterEvents(1)) == -1) + { + ERR("error registering quit event\n"); + goto failed; + } + + pSDL_JoystickEventState(SDL_ENABLE); + pSDL_GameControllerEventState(SDL_ENABLE); + + map_controllers = check_bus_option(&controller_mode, 1); + + /* Process mappings */ + if (pSDL_GameControllerAddMapping != NULL) sdl_load_mappings(); + + return STATUS_SUCCESS;
failed: dlclose(sdl_handle); sdl_handle = NULL; - return FALSE; + return STATUS_UNSUCCESSFUL; }
-NTSTATUS sdl_driver_init(void) +NTSTATUS sdl_bus_wait(void *args) { - static const WCHAR controller_modeW[] = {'M','a','p',' ','C','o','n','t','r','o','l','l','e','r','s',0}; - static const UNICODE_STRING controller_mode = {sizeof(controller_modeW) - sizeof(WCHAR), sizeof(controller_modeW), (WCHAR*)controller_modeW}; + SDL_Event event;
- HANDLE events[2]; - DWORD result; + do + { + if (pSDL_WaitEvent(&event) != 0) process_device_event(&event); + else WARN("SDL_WaitEvent failed: %s\n", pSDL_GetError()); + } while (event.type != quit_event);
- if (!sdl_handle && !sdl_initialize()) return STATUS_UNSUCCESSFUL; + TRACE("SDL main loop exiting\n"); + dlclose(sdl_handle); + sdl_handle = NULL; + return STATUS_SUCCESS; +}
- map_controllers = check_bus_option(&controller_mode, 1); +NTSTATUS sdl_bus_stop(void *args) +{ + SDL_Event event;
- if (!(events[0] = CreateEventW(NULL, TRUE, FALSE, NULL))) - { - WARN("CreateEvent failed\n"); - return STATUS_UNSUCCESSFUL; - } - if (!(events[1] = CreateThread(NULL, 0, deviceloop_thread, events[0], 0, NULL))) - { - WARN("CreateThread failed\n"); - CloseHandle(events[0]); - return STATUS_UNSUCCESSFUL; - } + if (!sdl_handle) return STATUS_SUCCESS;
- result = WaitForMultipleObjects(2, events, FALSE, INFINITE); - CloseHandle(events[0]); - if (result == WAIT_OBJECT_0) + event.type = quit_event; + if (pSDL_PushEvent(&event) != 1) { - TRACE("Initialization successful\n"); - deviceloop_handle = events[1]; - return STATUS_SUCCESS; + ERR("error pushing quit event\n"); + return STATUS_UNSUCCESSFUL; } - CloseHandle(events[1]);
- dlclose(sdl_handle); - sdl_handle = NULL; - return STATUS_UNSUCCESSFUL; + return STATUS_SUCCESS; }
#else
-NTSTATUS sdl_driver_init(void) +NTSTATUS sdl_bus_init(void *args) { + WARN("SDL support not compiled in!\n"); return STATUS_NOT_IMPLEMENTED; }
-void sdl_driver_unload( void ) +NTSTATUS sdl_bus_wait(void *args) { - TRACE("Stub: Unload Driver\n"); + WARN("SDL support not compiled in!\n"); + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS sdl_bus_stop(void *args) +{ + WARN("SDL support not compiled in!\n"); + return STATUS_NOT_IMPLEMENTED; }
#endif /* SONAME_LIBSDL2 */ diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index e372ec6db3f..6be5e677bba 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -618,6 +618,74 @@ static void keyboard_device_create(void) IoInvalidateDeviceRelations(bus_pdo, BusRelations); }
+static DWORD bus_count; +static HANDLE bus_thread[16]; + +struct bus_main_params +{ + const WCHAR *name; + + HANDLE init_done; + NTSTATUS (*init_func)(void *args); + + NTSTATUS (*wait_func)(void *args); +}; + +static DWORD CALLBACK bus_main_thread(void *args) +{ + struct bus_main_params bus = *(struct bus_main_params *)args; + NTSTATUS status; + + TRACE("%s main loop starting\n", debugstr_w(bus.name)); + status = bus.init_func(NULL); + SetEvent(bus.init_done); + TRACE("%s main loop started\n", debugstr_w(bus.name)); + + if (status) WARN("%s bus init returned status %#x\n", debugstr_w(bus.name), status); + else status = bus.wait_func(NULL); + + 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)); + return status; +} + +static NTSTATUS bus_main_thread_start(struct bus_main_params *bus) +{ + DWORD i = bus_count++; + + if (!(bus->init_done = CreateEventW(NULL, FALSE, FALSE, NULL))) + { + ERR("failed to create %s bus init done event.\n", debugstr_w(bus->name)); + bus_count--; + return STATUS_UNSUCCESSFUL; + } + + if (!(bus_thread[i] = CreateThread(NULL, 0, bus_main_thread, bus, 0, NULL))) + { + ERR("failed to create %s bus thread.\n", debugstr_w(bus->name)); + CloseHandle(bus->init_done); + bus_count--; + return STATUS_UNSUCCESSFUL; + } + + WaitForSingleObject(bus->init_done, INFINITE); + CloseHandle(bus->init_done); + return STATUS_SUCCESS; +} + +static NTSTATUS sdl_driver_init(void) +{ + static const WCHAR bus_name[] = {'S','D','L',0}; + struct bus_main_params bus = + { + .name = bus_name, + .init_func = sdl_bus_init, + .wait_func = sdl_bus_wait, + }; + + return bus_main_thread_start(&bus); +} + 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}; @@ -634,16 +702,12 @@ static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) mouse_device_create(); keyboard_device_create();
- if (check_bus_option(&SDL_enabled, 1)) + if (!check_bus_option(&SDL_enabled, 1) || sdl_driver_init()) { - if (sdl_driver_init() == STATUS_SUCCESS) - { - irp->IoStatus.Status = STATUS_SUCCESS; - break; - } + udev_driver_init(); + iohid_driver_init(); } - udev_driver_init(); - iohid_driver_init(); + irp->IoStatus.Status = STATUS_SUCCESS; break; case IRP_MN_SURPRISE_REMOVAL: @@ -652,7 +716,10 @@ static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) case IRP_MN_REMOVE_DEVICE: udev_driver_unload(); iohid_driver_unload(); - sdl_driver_unload(); + sdl_bus_stop(NULL); + + WaitForMultipleObjects(bus_count, bus_thread, TRUE, INFINITE); + while (bus_count--) CloseHandle(bus_thread[bus_count]);
irp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(irp);