Allocated on the caller side.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/main.c | 13 ++++++++++++- dlls/winebus.sys/unixlib.h | 10 ++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index e9c85deb846..973931fe517 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -632,6 +632,7 @@ struct bus_main_params HANDLE init_done; unsigned int init_code; unsigned int wait_code; + struct bus_event *bus_event; };
static DWORD CALLBACK bus_main_thread(void *args) @@ -644,11 +645,13 @@ static DWORD CALLBACK bus_main_thread(void *args) SetEvent(bus.init_done); TRACE("%s main loop started\n", debugstr_w(bus.name));
+ bus.bus_event->type = BUS_EVENT_TYPE_NONE; if (status) WARN("%s bus init returned status %#x\n", debugstr_w(bus.name), status); - else status = winebus_call(bus.wait_code, NULL); + else while ((status = winebus_call(bus.wait_code, bus.bus_event)) == STATUS_PENDING) {}
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)); + HeapFree(GetProcessHeap(), 0, bus.bus_event); return status; }
@@ -663,6 +666,14 @@ static NTSTATUS bus_main_thread_start(struct bus_main_params *bus) return STATUS_UNSUCCESSFUL; }
+ if (!(bus->bus_event = HeapAlloc(GetProcessHeap(), 0, sizeof(struct bus_event)))) + { + ERR("failed to allocate %s bus event.\n", debugstr_w(bus->name)); + CloseHandle(bus->init_done); + 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)); diff --git a/dlls/winebus.sys/unixlib.h b/dlls/winebus.sys/unixlib.h index c0de991d20a..e6abd98601f 100644 --- a/dlls/winebus.sys/unixlib.h +++ b/dlls/winebus.sys/unixlib.h @@ -46,6 +46,16 @@ struct iohid_bus_options
struct unix_device;
+enum bus_event_type +{ + BUS_EVENT_TYPE_NONE, +}; + +struct bus_event +{ + enum bus_event_type type; +}; + enum unix_funcs { sdl_init,
Instead of calling bus_unlink_hid_device or IoInvalidateDeviceRelations.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 14 +++++------- dlls/winebus.sys/main.c | 20 ++++++++++++++++- dlls/winebus.sys/unix_private.h | 6 +++++ dlls/winebus.sys/unixlib.c | 39 +++++++++++++++++++++++++++++++++ dlls/winebus.sys/unixlib.h | 12 ++++++++++ 5 files changed, 81 insertions(+), 10 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 61d1240e05d..cdc20b09b54 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -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; @@ -824,9 +819,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) { @@ -983,15 +976,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; diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 973931fe517..781a4101f10 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -638,6 +638,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)); @@ -647,7 +648,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)); diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index aff1e86263a..f3edef83cb7 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -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 */ diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c index c4090861675..13e2729e0c2 100644 --- a/dlls/winebus.sys/unixlib.c +++ b/dlls/winebus.sys/unixlib.c @@ -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; +} diff --git a/dlls/winebus.sys/unixlib.h b/dlls/winebus.sys/unixlib.h index e6abd98601f..d9097ba9ca7 100644 --- a/dlls/winebus.sys/unixlib.h +++ b/dlls/winebus.sys/unixlib.h @@ -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
Instead of calling bus_unlink_hid_device or IoInvalidateDeviceRelations.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_udev.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index bd70a66f2cd..9aa01b48304 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -92,6 +92,7 @@ static struct udev *udev_context = NULL; static struct udev_monitor *udev_monitor; static int deviceloop_control[2]; static int udev_monitor_fd; +static struct list event_queue = LIST_INIT(event_queue);
static const WCHAR hidraw_busidW[] = {'H','I','D','R','A','W',0}; static const WCHAR lnxev_busidW[] = {'L','N','X','E','V',0}; @@ -1173,16 +1174,10 @@ static void try_add_device(struct udev_device *dev)
static void try_remove_device(struct udev_device *dev) { - DEVICE_OBJECT *device = NULL; - - device = bus_find_hid_device(hidraw_busidW, dev); + bus_event_queue_device_removed(&event_queue, hidraw_busidW, dev); #ifdef HAS_PROPER_INPUT_HEADER - if (device == NULL) device = bus_find_hid_device(lnxev_busidW, dev); + bus_event_queue_device_removed(&event_queue, lnxev_busidW, dev); #endif - if (!device) return; - - bus_unlink_hid_device(device); - IoInvalidateDeviceRelations(bus_pdo, BusRelations); }
static void build_initial_deviceset(void) @@ -1339,6 +1334,7 @@ error:
NTSTATUS udev_bus_wait(void *args) { + struct bus_event *result = args; struct pollfd pfd[2];
pfd[0].fd = udev_monitor_fd; @@ -1350,12 +1346,14 @@ NTSTATUS udev_bus_wait(void *args)
while (1) { + if (bus_event_queue_pop(&event_queue, result)) return STATUS_PENDING; if (poll(pfd, 2, -1) <= 0) continue; if (pfd[1].revents) break; process_monitor_event(udev_monitor); }
TRACE("UDEV main loop exiting\n"); + bus_event_queue_destroy(&event_queue); udev_monitor_unref(udev_monitor); udev_unref(udev_context); udev_context = NULL;
Instead of calling bus_unlink_hid_device or IoInvalidateDeviceRelations.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus.h | 1 - dlls/winebus.sys/bus_iohid.c | 17 +++++++++-------- dlls/winebus.sys/main.c | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/dlls/winebus.sys/bus.h b/dlls/winebus.sys/bus.h index 803ffaad132..6d9090d8603 100644 --- a/dlls/winebus.sys/bus.h +++ b/dlls/winebus.sys/bus.h @@ -47,7 +47,6 @@ DEVICE_OBJECT *bus_create_hid_device(const WCHAR *busidW, WORD vid, WORD pid, WO DWORD version, DWORD uid, const WCHAR *serialW, BOOL is_gamepad, const platform_vtbl *vtbl, struct unix_device *unix_device) DECLSPEC_HIDDEN; DEVICE_OBJECT *bus_find_hid_device(const WCHAR *bus_id, void *platform_dev) DECLSPEC_HIDDEN; -void bus_unlink_hid_device(DEVICE_OBJECT *device) DECLSPEC_HIDDEN; void process_hid_report(DEVICE_OBJECT *device, BYTE *report, DWORD length) DECLSPEC_HIDDEN; DEVICE_OBJECT *bus_enumerate_hid_devices(const WCHAR *bus_id, enum_func function, void *context) DECLSPEC_HIDDEN;
diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c index eb5eddd60fa..5002d5fb5b7 100644 --- a/dlls/winebus.sys/bus_iohid.c +++ b/dlls/winebus.sys/bus_iohid.c @@ -97,6 +97,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
static IOHIDManagerRef hid_manager; static CFRunLoopRef run_loop; +static struct list event_queue = LIST_INIT(event_queue);
static const WCHAR busidW[] = {'I','O','H','I','D',0}; static struct iohid_bus_options options; @@ -380,19 +381,13 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void *
static void handle_RemovalCallback(void *context, IOReturn result, void *sender, IOHIDDeviceRef IOHIDDevice) { - DEVICE_OBJECT *device; TRACE("OS/X IOHID Device Removed %p\n", IOHIDDevice); IOHIDDeviceRegisterInputReportCallback(IOHIDDevice, NULL, 0, NULL, NULL); /* Note: Yes, we leak the buffer. But according to research there is no safe way to deallocate that buffer. */ IOHIDDeviceUnscheduleFromRunLoop(IOHIDDevice, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); IOHIDDeviceClose(IOHIDDevice, 0); - device = bus_find_hid_device(busidW, IOHIDDevice); - if (device) - { - bus_unlink_hid_device(device); - IoInvalidateDeviceRelations(bus_pdo, BusRelations); - } + bus_event_queue_device_removed(&event_queue, busidW, IOHIDDevice); }
NTSTATUS iohid_bus_init(void *args) @@ -418,9 +413,15 @@ NTSTATUS iohid_bus_init(void *args)
NTSTATUS iohid_bus_wait(void *args) { - CFRunLoopRun(); + struct bus_event *result = args; + + do + { + if (bus_event_queue_pop(&event_queue, result)) return STATUS_PENDING; + } while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, TRUE) != kCFRunLoopRunStopped);
TRACE("IOHID main loop exiting\n"); + bus_event_queue_destroy(&event_queue); IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, NULL, NULL); IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, NULL, NULL); CFRelease(hid_manager); diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 781a4101f10..20efa3cfb17 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -358,7 +358,7 @@ DEVICE_OBJECT *bus_enumerate_hid_devices(const WCHAR *bus_id, enum_func function return ret; }
-void bus_unlink_hid_device(DEVICE_OBJECT *device) +static void bus_unlink_hid_device(DEVICE_OBJECT *device) { struct device_extension *ext = (struct device_extension *)device->DeviceExtension;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus.h | 24 +---- dlls/winebus.sys/hid.c | 4 +- dlls/winebus.sys/main.c | 152 ++--------------------------- dlls/winebus.sys/unix_private.h | 20 ++++ dlls/winebus.sys/unixlib.c | 167 ++++++++++++++++++++++++++++++++ dlls/winebus.sys/unixlib.h | 7 ++ 6 files changed, 208 insertions(+), 166 deletions(-)
diff --git a/dlls/winebus.sys/bus.h b/dlls/winebus.sys/bus.h index 6d9090d8603..8f36959d4e1 100644 --- a/dlls/winebus.sys/bus.h +++ b/dlls/winebus.sys/bus.h @@ -25,6 +25,8 @@ #include <ddk/hidclass.h> #include <hidusage.h>
+#include "unixlib.h" + typedef int(*enum_func)(DEVICE_OBJECT *device, void *context);
/* Native device function table */ @@ -56,23 +58,5 @@ BOOL is_xbox_gamepad(WORD vid, WORD pid) DECLSPEC_HIDDEN; extern HANDLE driver_key DECLSPEC_HIDDEN; extern DEVICE_OBJECT *bus_pdo DECLSPEC_HIDDEN;
-struct hid_descriptor -{ - BYTE *data; - SIZE_T size; - SIZE_T max_size; -}; - -extern BOOL hid_descriptor_append(struct hid_descriptor *desc, const BYTE *buffer, SIZE_T size) DECLSPEC_HIDDEN; -extern BOOL hid_descriptor_begin(struct hid_descriptor *desc, USAGE usage_page, USAGE usage) DECLSPEC_HIDDEN; -extern BOOL hid_descriptor_end(struct hid_descriptor *desc) DECLSPEC_HIDDEN; -extern void hid_descriptor_free(struct hid_descriptor *desc) DECLSPEC_HIDDEN; - -extern BOOL hid_descriptor_add_buttons(struct hid_descriptor *desc, USAGE usage_page, - USAGE usage_min, USAGE usage_max) DECLSPEC_HIDDEN; -extern BOOL hid_descriptor_add_padding(struct hid_descriptor *desc, BYTE bitcount) DECLSPEC_HIDDEN; -extern BOOL hid_descriptor_add_hatswitch(struct hid_descriptor *desc, INT count) DECLSPEC_HIDDEN; -extern BOOL hid_descriptor_add_axes(struct hid_descriptor *desc, BYTE count, USAGE usage_page, - const USAGE *usages, BOOL rel, INT size, LONG min, LONG max) DECLSPEC_HIDDEN; - -extern BOOL hid_descriptor_add_haptics(struct hid_descriptor *desc) DECLSPEC_HIDDEN; +extern const platform_vtbl mouse_vtbl DECLSPEC_HIDDEN; +extern const platform_vtbl keyboard_vtbl DECLSPEC_HIDDEN; diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 1a245031d4d..e4623fab664 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -27,9 +27,9 @@ #include "hidusage.h" #include "ddk/wdm.h"
-#include "bus.h" +#include "unix_private.h"
-BOOL hid_descriptor_append(struct hid_descriptor *desc, const BYTE *buffer, SIZE_T size) +static BOOL hid_descriptor_append(struct hid_descriptor *desc, const BYTE *buffer, SIZE_T size) { BYTE *tmp = desc->data;
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 20efa3cfb17..a1062bb822d 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -95,9 +95,7 @@ static const struct product_desc XBOX_CONTROLLERS[] = { static DRIVER_OBJECT *driver_obj;
static DEVICE_OBJECT *mouse_obj; -static struct hid_descriptor mouse_desc; static DEVICE_OBJECT *keyboard_obj; -static struct hid_descriptor keyboard_desc;
/* The root-enumerated device stack. */ DEVICE_OBJECT *bus_pdo; @@ -467,157 +465,23 @@ static NTSTATUS handle_IRP_MN_QUERY_ID(DEVICE_OBJECT *device, IRP *irp) return status; }
-static void mouse_free_device(DEVICE_OBJECT *device) -{ -} - -static NTSTATUS mouse_start_device(DEVICE_OBJECT *device) -{ - if (!hid_descriptor_begin(&mouse_desc, HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE)) - return STATUS_NO_MEMORY; - if (!hid_descriptor_add_buttons(&mouse_desc, HID_USAGE_PAGE_BUTTON, 1, 3)) - return STATUS_NO_MEMORY; - if (!hid_descriptor_end(&mouse_desc)) - return STATUS_NO_MEMORY; - - return STATUS_SUCCESS; -} - -static NTSTATUS mouse_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *ret_length) -{ - TRACE("buffer %p, length %u.\n", buffer, length); - - *ret_length = mouse_desc.size; - if (length < mouse_desc.size) return STATUS_BUFFER_TOO_SMALL; - - memcpy(buffer, mouse_desc.data, mouse_desc.size); - return STATUS_SUCCESS; -} - -static NTSTATUS mouse_get_string(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length) -{ - static const WCHAR nameW[] = {'W','i','n','e',' ','H','I','D',' ','m','o','u','s','e',0}; - if (index != HID_STRING_ID_IPRODUCT) - return STATUS_NOT_IMPLEMENTED; - if (length < ARRAY_SIZE(nameW)) - return STATUS_BUFFER_TOO_SMALL; - strcpyW(buffer, nameW); - return STATUS_SUCCESS; -} - -static void mouse_set_output_report(DEVICE_OBJECT *device, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) -{ - FIXME("id %u, stub!\n", packet->reportId); - io->Information = 0; - io->Status = STATUS_NOT_IMPLEMENTED; -} - -static void mouse_get_feature_report(DEVICE_OBJECT *device, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) -{ - FIXME("id %u, stub!\n", packet->reportId); - io->Information = 0; - io->Status = STATUS_NOT_IMPLEMENTED; -} - -static void mouse_set_feature_report(DEVICE_OBJECT *device, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) -{ - FIXME("id %u, stub!\n", packet->reportId); - io->Information = 0; - io->Status = STATUS_NOT_IMPLEMENTED; -} - -static const platform_vtbl mouse_vtbl = -{ - .free_device = mouse_free_device, - .start_device = mouse_start_device, - .get_reportdescriptor = mouse_get_reportdescriptor, - .get_string = mouse_get_string, - .set_output_report = mouse_set_output_report, - .get_feature_report = mouse_get_feature_report, - .set_feature_report = mouse_set_feature_report, -}; - static void mouse_device_create(void) { static const WCHAR busidW[] = {'W','I','N','E','M','O','U','S','E',0}; - mouse_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE, &mouse_vtbl, 0); - IoInvalidateDeviceRelations(bus_pdo, BusRelations); -} - -static void keyboard_free_device(DEVICE_OBJECT *device) -{ -} - -static NTSTATUS keyboard_start_device(DEVICE_OBJECT *device) -{ - if (!hid_descriptor_begin(&keyboard_desc, HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD)) - return STATUS_NO_MEMORY; - if (!hid_descriptor_add_buttons(&keyboard_desc, HID_USAGE_PAGE_KEYBOARD, 0, 101)) - return STATUS_NO_MEMORY; - if (!hid_descriptor_end(&keyboard_desc)) - return STATUS_NO_MEMORY; - - return STATUS_SUCCESS; -} - -static NTSTATUS keyboard_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *ret_length) -{ - TRACE("buffer %p, length %u.\n", buffer, length); - - *ret_length = keyboard_desc.size; - if (length < keyboard_desc.size) return STATUS_BUFFER_TOO_SMALL; - - memcpy(buffer, keyboard_desc.data, keyboard_desc.size); - return STATUS_SUCCESS; -} - -static NTSTATUS keyboard_get_string(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length) -{ - static const WCHAR nameW[] = {'W','i','n','e',' ','H','I','D',' ','k','e','y','b','o','a','r','d',0}; - if (index != HID_STRING_ID_IPRODUCT) - return STATUS_NOT_IMPLEMENTED; - if (length < ARRAY_SIZE(nameW)) - return STATUS_BUFFER_TOO_SMALL; - strcpyW(buffer, nameW); - return STATUS_SUCCESS; -} - -static void keyboard_set_output_report(DEVICE_OBJECT *device, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) -{ - FIXME("id %u, stub!\n", packet->reportId); - io->Information = 0; - io->Status = STATUS_NOT_IMPLEMENTED; -} - -static void keyboard_get_feature_report(DEVICE_OBJECT *device, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) -{ - FIXME("id %u, stub!\n", packet->reportId); - io->Information = 0; - io->Status = STATUS_NOT_IMPLEMENTED; -} + struct device_create_params params = {0};
-static void keyboard_set_feature_report(DEVICE_OBJECT *device, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) -{ - FIXME("id %u, stub!\n", packet->reportId); - io->Information = 0; - io->Status = STATUS_NOT_IMPLEMENTED; + if (winebus_call(mouse_create, ¶ms)) return; + mouse_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE, &mouse_vtbl, params.device); + IoInvalidateDeviceRelations(bus_pdo, BusRelations); }
-static const platform_vtbl keyboard_vtbl = -{ - .free_device = keyboard_free_device, - .start_device = keyboard_start_device, - .get_reportdescriptor = keyboard_get_reportdescriptor, - .get_string = keyboard_get_string, - .set_output_report = keyboard_set_output_report, - .get_feature_report = keyboard_get_feature_report, - .set_feature_report = keyboard_set_feature_report, -}; - static void keyboard_device_create(void) { static const WCHAR busidW[] = {'W','I','N','E','K','E','Y','B','O','A','R','D',0}; - keyboard_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE, &keyboard_vtbl, 0); + struct device_create_params params = {0}; + + if (winebus_call(keyboard_create, ¶ms)) return; + keyboard_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE, &keyboard_vtbl, params.device); IoInvalidateDeviceRelations(bus_pdo, BusRelations); }
diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index f3edef83cb7..56194503090 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -49,4 +49,24 @@ 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;
+struct hid_descriptor +{ + BYTE *data; + SIZE_T size; + SIZE_T max_size; +}; + +extern BOOL hid_descriptor_begin(struct hid_descriptor *desc, USAGE usage_page, USAGE usage) DECLSPEC_HIDDEN; +extern BOOL hid_descriptor_end(struct hid_descriptor *desc) DECLSPEC_HIDDEN; +extern void hid_descriptor_free(struct hid_descriptor *desc) DECLSPEC_HIDDEN; + +extern BOOL hid_descriptor_add_buttons(struct hid_descriptor *desc, USAGE usage_page, + USAGE usage_min, USAGE usage_max) DECLSPEC_HIDDEN; +extern BOOL hid_descriptor_add_padding(struct hid_descriptor *desc, BYTE bitcount) DECLSPEC_HIDDEN; +extern BOOL hid_descriptor_add_hatswitch(struct hid_descriptor *desc, INT count) DECLSPEC_HIDDEN; +extern BOOL hid_descriptor_add_axes(struct hid_descriptor *desc, BYTE count, USAGE usage_page, + const USAGE *usages, BOOL rel, INT size, LONG min, LONG max) DECLSPEC_HIDDEN; + +extern BOOL hid_descriptor_add_haptics(struct hid_descriptor *desc) DECLSPEC_HIDDEN; + #endif /* __WINEBUS_UNIX_PRIVATE_H */ diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c index 13e2729e0c2..fdfdcc52dcb 100644 --- a/dlls/winebus.sys/unixlib.c +++ b/dlls/winebus.sys/unixlib.c @@ -24,13 +24,178 @@ #include "windef.h" #include "winbase.h" #include "winternl.h" +#include "ddk/hidtypes.h"
#include "wine/debug.h" #include "wine/list.h" #include "wine/unixlib.h"
+#include "bus.h" #include "unix_private.h"
+WINE_DEFAULT_DEBUG_CHANNEL(plugplay); + +static struct hid_descriptor mouse_desc; +static struct hid_descriptor keyboard_desc; + +static void mouse_free_device(DEVICE_OBJECT *device) +{ +} + +static NTSTATUS mouse_start_device(DEVICE_OBJECT *device) +{ + if (!hid_descriptor_begin(&mouse_desc, HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE)) + return STATUS_NO_MEMORY; + if (!hid_descriptor_add_buttons(&mouse_desc, HID_USAGE_PAGE_BUTTON, 1, 3)) + return STATUS_NO_MEMORY; + if (!hid_descriptor_end(&mouse_desc)) + return STATUS_NO_MEMORY; + + return STATUS_SUCCESS; +} + +static NTSTATUS mouse_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *ret_length) +{ + TRACE("buffer %p, length %u.\n", buffer, length); + + *ret_length = mouse_desc.size; + if (length < mouse_desc.size) return STATUS_BUFFER_TOO_SMALL; + + memcpy(buffer, mouse_desc.data, mouse_desc.size); + return STATUS_SUCCESS; +} + +static NTSTATUS mouse_get_string(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length) +{ + static const WCHAR nameW[] = {'W','i','n','e',' ','H','I','D',' ','m','o','u','s','e',0}; + if (index != HID_STRING_ID_IPRODUCT) + return STATUS_NOT_IMPLEMENTED; + if (length < ARRAY_SIZE(nameW)) + return STATUS_BUFFER_TOO_SMALL; + lstrcpyW(buffer, nameW); + return STATUS_SUCCESS; +} + +static void mouse_set_output_report(DEVICE_OBJECT *device, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) +{ + FIXME("id %u, stub!\n", packet->reportId); + io->Information = 0; + io->Status = STATUS_NOT_IMPLEMENTED; +} + +static void mouse_get_feature_report(DEVICE_OBJECT *device, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) +{ + FIXME("id %u, stub!\n", packet->reportId); + io->Information = 0; + io->Status = STATUS_NOT_IMPLEMENTED; +} + +static void mouse_set_feature_report(DEVICE_OBJECT *device, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) +{ + FIXME("id %u, stub!\n", packet->reportId); + io->Information = 0; + io->Status = STATUS_NOT_IMPLEMENTED; +} + +const platform_vtbl mouse_vtbl = +{ + .free_device = mouse_free_device, + .start_device = mouse_start_device, + .get_reportdescriptor = mouse_get_reportdescriptor, + .get_string = mouse_get_string, + .set_output_report = mouse_set_output_report, + .get_feature_report = mouse_get_feature_report, + .set_feature_report = mouse_set_feature_report, +}; + +static struct unix_device mouse_device; + +static NTSTATUS mouse_device_create(void *args) +{ + struct device_create_params *params = args; + params->device = &mouse_device; + return STATUS_SUCCESS; +} + +static void keyboard_free_device(DEVICE_OBJECT *device) +{ +} + +static NTSTATUS keyboard_start_device(DEVICE_OBJECT *device) +{ + if (!hid_descriptor_begin(&keyboard_desc, HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_KEYBOARD)) + return STATUS_NO_MEMORY; + if (!hid_descriptor_add_buttons(&keyboard_desc, HID_USAGE_PAGE_KEYBOARD, 0, 101)) + return STATUS_NO_MEMORY; + if (!hid_descriptor_end(&keyboard_desc)) + return STATUS_NO_MEMORY; + + return STATUS_SUCCESS; +} + +static NTSTATUS keyboard_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer, DWORD length, DWORD *ret_length) +{ + TRACE("buffer %p, length %u.\n", buffer, length); + + *ret_length = keyboard_desc.size; + if (length < keyboard_desc.size) return STATUS_BUFFER_TOO_SMALL; + + memcpy(buffer, keyboard_desc.data, keyboard_desc.size); + return STATUS_SUCCESS; +} + +static NTSTATUS keyboard_get_string(DEVICE_OBJECT *device, DWORD index, WCHAR *buffer, DWORD length) +{ + static const WCHAR nameW[] = {'W','i','n','e',' ','H','I','D',' ','k','e','y','b','o','a','r','d',0}; + if (index != HID_STRING_ID_IPRODUCT) + return STATUS_NOT_IMPLEMENTED; + if (length < ARRAY_SIZE(nameW)) + return STATUS_BUFFER_TOO_SMALL; + lstrcpyW(buffer, nameW); + return STATUS_SUCCESS; +} + +static void keyboard_set_output_report(DEVICE_OBJECT *device, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) +{ + FIXME("id %u, stub!\n", packet->reportId); + io->Information = 0; + io->Status = STATUS_NOT_IMPLEMENTED; +} + +static void keyboard_get_feature_report(DEVICE_OBJECT *device, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) +{ + FIXME("id %u, stub!\n", packet->reportId); + io->Information = 0; + io->Status = STATUS_NOT_IMPLEMENTED; +} + +static void keyboard_set_feature_report(DEVICE_OBJECT *device, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io) +{ + FIXME("id %u, stub!\n", packet->reportId); + io->Information = 0; + io->Status = STATUS_NOT_IMPLEMENTED; +} + +const platform_vtbl keyboard_vtbl = +{ + .free_device = keyboard_free_device, + .start_device = keyboard_start_device, + .get_reportdescriptor = keyboard_get_reportdescriptor, + .get_string = keyboard_get_string, + .set_output_report = keyboard_set_output_report, + .get_feature_report = keyboard_get_feature_report, + .set_feature_report = keyboard_set_feature_report, +}; + +static struct unix_device keyboard_device; + +static NTSTATUS keyboard_device_create(void *args) +{ + struct device_create_params *params = args; + params->device = &keyboard_device; + return STATUS_SUCCESS; +} + const unixlib_entry_t __wine_unix_call_funcs[] = { sdl_bus_init, @@ -42,6 +207,8 @@ const unixlib_entry_t __wine_unix_call_funcs[] = iohid_bus_init, iohid_bus_wait, iohid_bus_stop, + mouse_device_create, + keyboard_device_create, };
void bus_event_queue_destroy(struct list *queue) diff --git a/dlls/winebus.sys/unixlib.h b/dlls/winebus.sys/unixlib.h index d9097ba9ca7..d70dedecb2c 100644 --- a/dlls/winebus.sys/unixlib.h +++ b/dlls/winebus.sys/unixlib.h @@ -68,6 +68,11 @@ struct bus_event }; };
+struct device_create_params +{ + struct unix_device *device; +}; + enum unix_funcs { sdl_init, @@ -79,6 +84,8 @@ enum unix_funcs iohid_init, iohid_wait, iohid_stop, + mouse_create, + keyboard_create, };
extern const unixlib_entry_t __wine_unix_call_funcs[] DECLSPEC_HIDDEN;