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; + 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}; - 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 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; -failed: - dlclose(sdl_handle); - sdl_handle = NULL; - return FALSE; -} + if (pSDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) < 0) + { + ERR("could not init SDL: %s\n", pSDL_GetError()); + goto failed; + } -NTSTATUS sdl_driver_init(void) -{ - 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}; + if ((quit_event = pSDL_RegisterEvents(1)) == -1) + { + ERR("error registering quit event\n"); + goto failed; + } - HANDLE events[2]; - DWORD result; - - if (!sdl_handle && !sdl_initialize()) return STATUS_UNSUCCESSFUL; + pSDL_JoystickEventState(SDL_ENABLE); + pSDL_GameControllerEventState(SDL_ENABLE); map_controllers = check_bus_option(&controller_mode, 1); - 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; - } + /* Process mappings */ + if (pSDL_GameControllerAddMapping != NULL) sdl_load_mappings(); - result = WaitForMultipleObjects(2, events, FALSE, INFINITE); - CloseHandle(events[0]); - if (result == WAIT_OBJECT_0) - { - TRACE("Initialization successful\n"); - deviceloop_handle = events[1]; - return STATUS_SUCCESS; - } - CloseHandle(events[1]); + return STATUS_SUCCESS; +failed: dlclose(sdl_handle); sdl_handle = NULL; return STATUS_UNSUCCESSFUL; } +NTSTATUS sdl_bus_wait(void *args) +{ + SDL_Event event; + + do + { + 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"); + dlclose(sdl_handle); + sdl_handle = NULL; + return STATUS_SUCCESS; +} + +NTSTATUS sdl_bus_stop(void *args) +{ + SDL_Event event; + + if (!sdl_handle) return STATUS_SUCCESS; + + event.type = quit_event; + if (pSDL_PushEvent(&event) != 1) + { + ERR("error pushing quit event\n"); + 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);