winebus.sys: Return an event from SDL bus wait on device removal.

Instead of calling bus_unlink_hid_device or IoInvalidateDeviceRelations.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2021-08-30 11:22:52 +02:00 committed by Alexandre Julliard
parent f6d567d3e3
commit 6006758ca8
5 changed files with 81 additions and 10 deletions

View file

@ -64,6 +64,7 @@ static struct sdl_bus_options options;
static void *sdl_handle = NULL;
static UINT quit_event = -1;
static struct list event_queue = LIST_INIT(event_queue);
#define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
MAKE_FUNCPTR(SDL_GetError);
@ -730,12 +731,6 @@ static BOOL set_mapped_report_from_event(DEVICE_OBJECT *device, SDL_Event *event
return FALSE;
}
static void try_remove_device(DEVICE_OBJECT *device)
{
bus_unlink_hid_device(device);
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
}
static void try_add_device(unsigned int index)
{
DWORD vid = 0, pid = 0, version = 0;
@ -821,9 +816,7 @@ static void process_device_event(SDL_Event *event)
else if (event->type == SDL_JOYDEVICEREMOVED)
{
id = ((SDL_JoyDeviceEvent *)event)->which;
device = bus_find_hid_device(sdl_busidW, ULongToPtr(id));
if (device) try_remove_device(device);
else WARN("failed to find device with id %d\n", id);
bus_event_queue_device_removed(&event_queue, sdl_busidW, ULongToPtr(id));
}
else if (event->type >= SDL_JOYAXISMOTION && event->type <= SDL_JOYBUTTONUP)
{
@ -980,15 +973,18 @@ failed:
NTSTATUS sdl_bus_wait(void *args)
{
struct bus_event *result = args;
SDL_Event event;
do
{
if (bus_event_queue_pop(&event_queue, result)) return STATUS_PENDING;
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");
bus_event_queue_destroy(&event_queue);
dlclose(sdl_handle);
sdl_handle = NULL;
return STATUS_SUCCESS;

View file

@ -654,6 +654,7 @@ struct bus_main_params
static DWORD CALLBACK bus_main_thread(void *args)
{
struct bus_main_params bus = *(struct bus_main_params *)args;
DEVICE_OBJECT *device;
NTSTATUS status;
TRACE("%s main loop starting\n", debugstr_w(bus.name));
@ -663,7 +664,24 @@ static DWORD CALLBACK bus_main_thread(void *args)
bus.bus_event->type = BUS_EVENT_TYPE_NONE;
if (status) WARN("%s bus init returned status %#x\n", debugstr_w(bus.name), status);
else while ((status = winebus_call(bus.wait_code, bus.bus_event)) == STATUS_PENDING) {}
else while ((status = winebus_call(bus.wait_code, bus.bus_event)) == STATUS_PENDING)
{
struct bus_event *event = bus.bus_event;
switch (event->type)
{
case BUS_EVENT_TYPE_NONE: break;
case BUS_EVENT_TYPE_DEVICE_REMOVED:
EnterCriticalSection(&device_list_cs);
if (!(device = bus_find_hid_device(event->device_removed.bus_id, event->device_removed.context)))
WARN("could not find removed device matching bus %s, context %p\n",
debugstr_w(event->device_removed.bus_id), event->device_removed.context);
else
bus_unlink_hid_device(device);
LeaveCriticalSection(&device_list_cs);
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
break;
}
}
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));

View file

@ -27,6 +27,8 @@
#include "unixlib.h"
#include "wine/list.h"
struct unix_device
{
};
@ -43,4 +45,8 @@ extern NTSTATUS iohid_bus_init(void *) DECLSPEC_HIDDEN;
extern NTSTATUS iohid_bus_wait(void *) DECLSPEC_HIDDEN;
extern NTSTATUS iohid_bus_stop(void *) DECLSPEC_HIDDEN;
extern void bus_event_queue_destroy(struct list *queue) DECLSPEC_HIDDEN;
extern BOOL bus_event_queue_device_removed(struct list *queue, const WCHAR *bus_id, void *context) DECLSPEC_HIDDEN;
extern BOOL bus_event_queue_pop(struct list *queue, struct bus_event *event) DECLSPEC_HIDDEN;
#endif /* __WINEBUS_UNIX_PRIVATE_H */

View file

@ -26,6 +26,7 @@
#include "winternl.h"
#include "wine/debug.h"
#include "wine/list.h"
#include "wine/unixlib.h"
#include "unix_private.h"
@ -42,3 +43,41 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
iohid_bus_wait,
iohid_bus_stop,
};
void bus_event_queue_destroy(struct list *queue)
{
struct bus_event *event, *next;
LIST_FOR_EACH_ENTRY_SAFE(event, next, queue, struct bus_event, entry)
HeapFree(GetProcessHeap(), 0, event);
}
BOOL bus_event_queue_device_removed(struct list *queue, const WCHAR *bus_id, void *context)
{
ULONG size = sizeof(struct bus_event);
struct bus_event *event = HeapAlloc(GetProcessHeap(), 0, size);
if (!event) return FALSE;
event->type = BUS_EVENT_TYPE_DEVICE_REMOVED;
event->device_removed.bus_id = bus_id;
event->device_removed.context = context;
list_add_tail(queue, &event->entry);
return TRUE;
}
BOOL bus_event_queue_pop(struct list *queue, struct bus_event *event)
{
struct list *entry = list_head(queue);
struct bus_event *tmp;
if (!entry) return FALSE;
tmp = LIST_ENTRY(entry, struct bus_event, entry);
list_remove(entry);
memcpy(event, tmp, sizeof(*event));
HeapFree(GetProcessHeap(), 0, tmp);
return TRUE;
}

View file

@ -27,6 +27,7 @@
#include <ddk/wdm.h>
#include <hidusage.h>
#include "wine/list.h"
#include "wine/unixlib.h"
struct sdl_bus_options
@ -49,11 +50,22 @@ struct unix_device;
enum bus_event_type
{
BUS_EVENT_TYPE_NONE,
BUS_EVENT_TYPE_DEVICE_REMOVED,
};
struct bus_event
{
enum bus_event_type type;
struct list entry;
union
{
struct
{
const WCHAR *bus_id;
void *context;
} device_removed;
};
};
enum unix_funcs