winebus.sys: Create the SDL bus thread in main.c.
Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7a4237fd25
commit
9a78467975
|
@ -30,10 +30,12 @@ typedef int(*enum_func)(DEVICE_OBJECT *device, void *context);
|
||||||
/* Buses */
|
/* Buses */
|
||||||
NTSTATUS udev_driver_init(void) DECLSPEC_HIDDEN;
|
NTSTATUS udev_driver_init(void) DECLSPEC_HIDDEN;
|
||||||
NTSTATUS iohid_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 udev_driver_unload( void ) DECLSPEC_HIDDEN;
|
||||||
void iohid_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 */
|
/* Native device function table */
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
|
@ -63,7 +63,6 @@ static const WCHAR sdl_busidW[] = {'S','D','L','J','O','Y',0};
|
||||||
static DWORD map_controllers = 0;
|
static DWORD map_controllers = 0;
|
||||||
|
|
||||||
static void *sdl_handle = NULL;
|
static void *sdl_handle = NULL;
|
||||||
static HANDLE deviceloop_handle;
|
|
||||||
static UINT quit_event = -1;
|
static UINT quit_event = -1;
|
||||||
|
|
||||||
#define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
|
#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;
|
static const WCHAR controller_modeW[] = {'M','a','p',' ','C','o','n','t','r','o','l','l','e','r','s',0};
|
||||||
SDL_Event event;
|
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)))
|
if (!(sdl_handle = dlopen(SONAME_LIBSDL2, RTLD_NOW)))
|
||||||
{
|
{
|
||||||
WARN("could not load %s\n", SONAME_LIBSDL2);
|
WARN("could not load %s\n", SONAME_LIBSDL2);
|
||||||
return FALSE;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
#define LOAD_FUNCPTR(f) \
|
#define LOAD_FUNCPTR(f) \
|
||||||
if ((p##f = dlsym(sdl_handle, #f)) == NULL) \
|
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_JoystickGetProduct = dlsym(sdl_handle, "SDL_JoystickGetProduct");
|
||||||
pSDL_JoystickGetProductVersion = dlsym(sdl_handle, "SDL_JoystickGetProductVersion");
|
pSDL_JoystickGetProductVersion = dlsym(sdl_handle, "SDL_JoystickGetProductVersion");
|
||||||
pSDL_JoystickGetVendor = dlsym(sdl_handle, "SDL_JoystickGetVendor");
|
pSDL_JoystickGetVendor = dlsym(sdl_handle, "SDL_JoystickGetVendor");
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
failed:
|
if (pSDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) < 0)
|
||||||
dlclose(sdl_handle);
|
{
|
||||||
sdl_handle = NULL;
|
ERR("could not init SDL: %s\n", pSDL_GetError());
|
||||||
return FALSE;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS sdl_driver_init(void)
|
if ((quit_event = pSDL_RegisterEvents(1)) == -1)
|
||||||
{
|
{
|
||||||
static const WCHAR controller_modeW[] = {'M','a','p',' ','C','o','n','t','r','o','l','l','e','r','s',0};
|
ERR("error registering quit event\n");
|
||||||
static const UNICODE_STRING controller_mode = {sizeof(controller_modeW) - sizeof(WCHAR), sizeof(controller_modeW), (WCHAR*)controller_modeW};
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
HANDLE events[2];
|
pSDL_JoystickEventState(SDL_ENABLE);
|
||||||
DWORD result;
|
pSDL_GameControllerEventState(SDL_ENABLE);
|
||||||
|
|
||||||
if (!sdl_handle && !sdl_initialize()) return STATUS_UNSUCCESSFUL;
|
|
||||||
|
|
||||||
map_controllers = check_bus_option(&controller_mode, 1);
|
map_controllers = check_bus_option(&controller_mode, 1);
|
||||||
|
|
||||||
if (!(events[0] = CreateEventW(NULL, TRUE, FALSE, NULL)))
|
/* Process mappings */
|
||||||
{
|
if (pSDL_GameControllerAddMapping != NULL) sdl_load_mappings();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = WaitForMultipleObjects(2, events, FALSE, INFINITE);
|
return STATUS_SUCCESS;
|
||||||
CloseHandle(events[0]);
|
|
||||||
if (result == WAIT_OBJECT_0)
|
|
||||||
{
|
|
||||||
TRACE("Initialization successful\n");
|
|
||||||
deviceloop_handle = events[1];
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
CloseHandle(events[1]);
|
|
||||||
|
|
||||||
|
failed:
|
||||||
dlclose(sdl_handle);
|
dlclose(sdl_handle);
|
||||||
sdl_handle = NULL;
|
sdl_handle = NULL;
|
||||||
return STATUS_UNSUCCESSFUL;
|
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
|
#else
|
||||||
|
|
||||||
NTSTATUS sdl_driver_init(void)
|
NTSTATUS sdl_bus_init(void *args)
|
||||||
{
|
{
|
||||||
|
WARN("SDL support not compiled in!\n");
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
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 */
|
#endif /* SONAME_LIBSDL2 */
|
||||||
|
|
|
@ -618,6 +618,74 @@ static void keyboard_device_create(void)
|
||||||
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
|
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 NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
|
||||||
{
|
{
|
||||||
static const WCHAR SDL_enabledW[] = {'E','n','a','b','l','e',' ','S','D','L',0};
|
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();
|
mouse_device_create();
|
||||||
keyboard_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)
|
udev_driver_init();
|
||||||
{
|
iohid_driver_init();
|
||||||
irp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
udev_driver_init();
|
|
||||||
iohid_driver_init();
|
|
||||||
irp->IoStatus.Status = STATUS_SUCCESS;
|
irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
case IRP_MN_SURPRISE_REMOVAL:
|
case IRP_MN_SURPRISE_REMOVAL:
|
||||||
|
@ -652,7 +716,10 @@ static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
|
||||||
case IRP_MN_REMOVE_DEVICE:
|
case IRP_MN_REMOVE_DEVICE:
|
||||||
udev_driver_unload();
|
udev_driver_unload();
|
||||||
iohid_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;
|
irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
IoSkipCurrentIrpStackLocation(irp);
|
IoSkipCurrentIrpStackLocation(irp);
|
||||||
|
|
Loading…
Reference in New Issue