Signed-off-by: Rémi Bernon <rbernon(a)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);
--
2.33.0