From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wineusb.sys/unixlib.c | 9 +++++++++ dlls/wineusb.sys/wineusb.c | 8 -------- 2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/dlls/wineusb.sys/unixlib.c b/dlls/wineusb.sys/unixlib.c index 091d85d1ef1..cfced53d9bf 100644 --- a/dlls/wineusb.sys/unixlib.c +++ b/dlls/wineusb.sys/unixlib.c @@ -173,12 +173,19 @@ static NTSTATUS usb_main_loop(void *args)
TRACE("Starting libusb event thread.\n");
+ if ((ret = libusb_init(NULL))) + { + ERR("Failed to initialize libusb: %s\n", libusb_strerror(ret)); + return STATUS_UNSUCCESSFUL; + } + if ((ret = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, hotplug_cb, NULL, &hotplug_cb_handle))) { ERR("Failed to register callback: %s\n", libusb_strerror(ret)); + libusb_exit(NULL); return STATUS_UNSUCCESSFUL; }
@@ -188,6 +195,8 @@ static NTSTATUS usb_main_loop(void *args) ERR("Error handling events: %s\n", libusb_strerror(ret)); }
+ libusb_exit(NULL); + queue_event(&shutdown_event);
TRACE("Shutting down libusb event thread.\n"); diff --git a/dlls/wineusb.sys/wineusb.c b/dlls/wineusb.sys/wineusb.c index 49033c76213..474ee6e96a6 100644 --- a/dlls/wineusb.sys/wineusb.c +++ b/dlls/wineusb.sys/wineusb.c @@ -731,14 +731,12 @@ static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *p
static void WINAPI driver_unload(DRIVER_OBJECT *driver) { - libusb_exit(NULL); }
NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *path) { NTSTATUS status; void *instance; - int err;
TRACE("driver %p, path %s.\n", driver, debugstr_w(path->Buffer));
@@ -752,12 +750,6 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *path)
driver_obj = driver;
- if ((err = libusb_init(NULL))) - { - ERR("Failed to initialize libusb: %s\n", libusb_strerror(err)); - return STATUS_UNSUCCESSFUL; - } - driver->DriverExtension->AddDevice = driver_add_device; driver->DriverUnload = driver_unload; driver->MajorFunction[IRP_MJ_PNP] = driver_pnp;
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wineusb.sys/unixlib.c | 8 +++++++- dlls/wineusb.sys/unixlib.h | 7 ++++++- dlls/wineusb.sys/wineusb.c | 27 ++++++++++++--------------- 3 files changed, 25 insertions(+), 17 deletions(-)
diff --git a/dlls/wineusb.sys/unixlib.c b/dlls/wineusb.sys/unixlib.c index cfced53d9bf..90847bc6a7d 100644 --- a/dlls/wineusb.sys/unixlib.c +++ b/dlls/wineusb.sys/unixlib.c @@ -133,7 +133,13 @@ static void add_usb_device(libusb_device *libusb_device) pthread_mutex_unlock(&device_mutex);
usb_event.type = USB_EVENT_ADD_DEVICE; - usb_event.u.added_device = unix_device; + usb_event.u.added_device.device = unix_device; + usb_event.u.added_device.vendor = device_desc.idVendor; + usb_event.u.added_device.product = device_desc.idProduct; + usb_event.u.added_device.revision = device_desc.bcdDevice; + usb_event.u.added_device.class = device_desc.bDeviceClass; + usb_event.u.added_device.subclass = device_desc.bDeviceSubClass; + usb_event.u.added_device.protocol = device_desc.bDeviceProtocol; queue_event(&usb_event); }
diff --git a/dlls/wineusb.sys/unixlib.h b/dlls/wineusb.sys/unixlib.h index e8e2850c57a..d76818cc907 100644 --- a/dlls/wineusb.sys/unixlib.h +++ b/dlls/wineusb.sys/unixlib.h @@ -47,7 +47,12 @@ struct usb_event
union { - struct unix_device *added_device; + struct usb_add_device_event + { + struct unix_device *device; + UINT16 vendor, product, revision; + UINT8 class, subclass, protocol; + } added_device; struct unix_device *removed_device; IRP *completed_irp; } u; diff --git a/dlls/wineusb.sys/wineusb.c b/dlls/wineusb.sys/wineusb.c index 474ee6e96a6..b833dbc9824 100644 --- a/dlls/wineusb.sys/wineusb.c +++ b/dlls/wineusb.sys/wineusb.c @@ -137,12 +137,11 @@ static void add_usb_interface(struct usb_device *parent, const struct libusb_int LeaveCriticalSection(&wineusb_cs); }
-static void add_unix_device(struct unix_device *unix_device) +static void add_unix_device(const struct usb_add_device_event *event) { static const WCHAR formatW[] = {'\','D','e','v','i','c','e','\','U','S','B','P','D','O','-','%','u',0}; - libusb_device *libusb_device = libusb_get_device(unix_device->handle); + libusb_device *libusb_device = libusb_get_device(event->device->handle); struct libusb_config_descriptor *config_desc; - struct libusb_device_descriptor device_desc; static unsigned int name_index; struct usb_device *device; DEVICE_OBJECT *device_obj; @@ -151,10 +150,8 @@ static void add_unix_device(struct unix_device *unix_device) WCHAR name[26]; int ret;
- libusb_get_device_descriptor(libusb_device, &device_desc); - - TRACE("Adding new device %p, vendor %04x, product %04x.\n", unix_device, - device_desc.idVendor, device_desc.idProduct); + TRACE("Adding new device %p, vendor %04x, product %04x.\n", event->device, + event->vendor, event->product);
sprintfW(name, formatW, name_index++); RtlInitUnicodeString(&string, name); @@ -167,16 +164,16 @@ static void add_unix_device(struct unix_device *unix_device)
device = device_obj->DeviceExtension; device->device_obj = device_obj; - device->unix_device = unix_device; + device->unix_device = event->device; InitializeListHead(&device->irp_list); device->removed = FALSE;
- device->class = device_desc.bDeviceClass; - device->subclass = device_desc.bDeviceSubClass; - device->protocol = device_desc.bDeviceProtocol; - device->vendor = device_desc.idVendor; - device->product = device_desc.idProduct; - device->revision = device_desc.bcdDevice; + device->class = event->class; + device->subclass = event->subclass; + device->protocol = event->protocol; + device->vendor = event->vendor; + device->product = event->product; + device->revision = event->revision;
EnterCriticalSection(&wineusb_cs); list_add_tail(&device_list, &device->entry); @@ -279,7 +276,7 @@ static DWORD CALLBACK event_thread_proc(void *arg) switch (event.type) { case USB_EVENT_ADD_DEVICE: - add_unix_device(event.u.added_device); + add_unix_device(&event.u.added_device); break;
case USB_EVENT_REMOVE_DEVICE:
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wineusb.sys/unixlib.c | 65 ++++++++++++++++++++++++++++++ dlls/wineusb.sys/unixlib.h | 9 +---- dlls/wineusb.sys/wineusb.c | 81 +++----------------------------------- 3 files changed, 72 insertions(+), 83 deletions(-)
diff --git a/dlls/wineusb.sys/unixlib.c b/dlls/wineusb.sys/unixlib.c index 90847bc6a7d..f2356fcb06a 100644 --- a/dlls/wineusb.sys/unixlib.c +++ b/dlls/wineusb.sys/unixlib.c @@ -40,6 +40,15 @@
WINE_DEFAULT_DEBUG_CHANNEL(wineusb);
+struct unix_device +{ + struct list entry; + + libusb_device_handle *handle; + + bool interface; +}; + static libusb_hotplug_callback_handle hotplug_cb_handle;
static bool thread_shutdown; @@ -109,6 +118,7 @@ static NTSTATUS usb_get_event(void *args)
static void add_usb_device(libusb_device *libusb_device) { + struct libusb_config_descriptor *config_desc; struct libusb_device_descriptor device_desc; struct unix_device *unix_device; struct usb_event usb_event; @@ -128,6 +138,8 @@ static void add_usb_device(libusb_device *libusb_device) free(unix_device); return; } + unix_device->interface = false; + pthread_mutex_lock(&device_mutex); list_add_tail(&device_list, &unix_device->entry); pthread_mutex_unlock(&device_mutex); @@ -140,7 +152,60 @@ static void add_usb_device(libusb_device *libusb_device) usb_event.u.added_device.class = device_desc.bDeviceClass; usb_event.u.added_device.subclass = device_desc.bDeviceSubClass; usb_event.u.added_device.protocol = device_desc.bDeviceProtocol; + usb_event.u.added_device.interface = false; queue_event(&usb_event); + + if (!(ret = libusb_get_active_config_descriptor(libusb_device, &config_desc))) + { + /* Create new devices for interfaces of composite devices. + * + * On Windows this is the job of usbccgp.sys, a separate driver that + * layers on top of the base USB driver. While we could take this + * approach as well, implementing usbccgp is a lot more work, whereas + * interface support is effectively built into libusb. + * + * FIXME: usbccgp does not create separate interfaces in some cases, + * e.g. when there is an interface association descriptor available. + */ + if (config_desc->bNumInterfaces > 1) + { + uint8_t i; + + for (i = 0; i < config_desc->bNumInterfaces; ++i) + { + const struct libusb_interface *interface = &config_desc->interface[i]; + const struct libusb_interface_descriptor *iface_desc; + struct unix_device *unix_iface; + + if (interface->num_altsetting != 1) + FIXME("Interface %u has %u alternate settings; using the first one.\n", + i, interface->num_altsetting); + iface_desc = &interface->altsetting[0]; + + if (!(unix_iface = calloc(1, sizeof(*unix_iface)))) + return; + + unix_iface->handle = unix_device->handle; + unix_iface->interface = true; + pthread_mutex_lock(&device_mutex); + list_add_tail(&device_list, &unix_iface->entry); + pthread_mutex_unlock(&device_mutex); + + usb_event.u.added_device.device = unix_iface; + usb_event.u.added_device.class = iface_desc->bInterfaceClass; + usb_event.u.added_device.subclass = iface_desc->bInterfaceSubClass; + usb_event.u.added_device.protocol = iface_desc->bInterfaceProtocol; + usb_event.u.added_device.interface = true; + usb_event.u.added_device.interface_index = iface_desc->bInterfaceNumber; + queue_event(&usb_event); + } + } + libusb_free_config_descriptor(config_desc); + } + else + { + ERR("Failed to get configuration descriptor: %s\n", libusb_strerror(ret)); + } }
static void remove_usb_device(libusb_device *libusb_device) diff --git a/dlls/wineusb.sys/unixlib.h b/dlls/wineusb.sys/unixlib.h index d76818cc907..0c3319969b7 100644 --- a/dlls/wineusb.sys/unixlib.h +++ b/dlls/wineusb.sys/unixlib.h @@ -26,13 +26,6 @@ #include "ddk/wdm.h" #include "wine/unixlib.h"
-struct unix_device -{ - struct list entry; - - libusb_device_handle *handle; -}; - enum usb_event_type { USB_EVENT_ADD_DEVICE, @@ -52,6 +45,8 @@ struct usb_event struct unix_device *device; UINT16 vendor, product, revision; UINT8 class, subclass, protocol; + bool interface; + UINT8 interface_index; } added_device; struct unix_device *removed_device; IRP *completed_irp; diff --git a/dlls/wineusb.sys/wineusb.c b/dlls/wineusb.sys/wineusb.c index b833dbc9824..d432bdc5666 100644 --- a/dlls/wineusb.sys/wineusb.c +++ b/dlls/wineusb.sys/wineusb.c @@ -79,9 +79,7 @@ struct usb_device
DEVICE_OBJECT *device_obj;
- /* Points to the parent USB device if this is a USB interface; otherwise - * NULL. */ - struct usb_device *parent; + bool interface; uint8_t interface_index;
uint8_t class, subclass, protocol; @@ -106,49 +104,15 @@ static void destroy_unix_device(struct unix_device *unix_device) __wine_unix_call(unix_handle, unix_usb_destroy_device, ¶ms); }
-static void add_usb_interface(struct usb_device *parent, const struct libusb_interface_descriptor *desc) -{ - struct usb_device *device; - DEVICE_OBJECT *device_obj; - NTSTATUS status; - - if ((status = IoCreateDevice(driver_obj, sizeof(*device), NULL, - FILE_DEVICE_USB, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &device_obj))) - { - ERR("Failed to create device, status %#x.\n", status); - return; - } - - device = device_obj->DeviceExtension; - device->device_obj = device_obj; - device->parent = parent; - device->unix_device = parent->unix_device; - device->interface_index = desc->bInterfaceNumber; - device->class = desc->bInterfaceClass; - device->subclass = desc->bInterfaceSubClass; - device->protocol = desc->bInterfaceProtocol; - device->vendor = parent->vendor; - device->product = parent->product; - device->revision = parent->revision; - InitializeListHead(&device->irp_list); - - EnterCriticalSection(&wineusb_cs); - list_add_tail(&device_list, &device->entry); - LeaveCriticalSection(&wineusb_cs); -} - static void add_unix_device(const struct usb_add_device_event *event) { static const WCHAR formatW[] = {'\','D','e','v','i','c','e','\','U','S','B','P','D','O','-','%','u',0}; - libusb_device *libusb_device = libusb_get_device(event->device->handle); - struct libusb_config_descriptor *config_desc; static unsigned int name_index; struct usb_device *device; DEVICE_OBJECT *device_obj; UNICODE_STRING string; NTSTATUS status; WCHAR name[26]; - int ret;
TRACE("Adding new device %p, vendor %04x, product %04x.\n", event->device, event->vendor, event->product); @@ -179,39 +143,6 @@ static void add_unix_device(const struct usb_add_device_event *event) list_add_tail(&device_list, &device->entry); LeaveCriticalSection(&wineusb_cs);
- if (!(ret = libusb_get_active_config_descriptor(libusb_device, &config_desc))) - { - /* Create new devices for interfaces of composite devices. - * - * On Windows this is the job of usbccgp.sys, a separate driver that - * layers on top of the base USB driver. While we could take this - * approach as well, implementing usbccgp is a lot more work, whereas - * interface support is effectively built into libusb. - * - * FIXME: usbccgp does not create separate interfaces in some cases, - * e.g. when there is an interface association descriptor available. - */ - if (config_desc->bNumInterfaces > 1) - { - uint8_t i; - - for (i = 0; i < config_desc->bNumInterfaces; ++i) - { - const struct libusb_interface *interface = &config_desc->interface[i]; - - if (interface->num_altsetting != 1) - FIXME("Interface %u has %u alternate settings; using the first one.\n", - i, interface->num_altsetting); - add_usb_interface(device, &interface->altsetting[0]); - } - } - libusb_free_config_descriptor(config_desc); - } - else - { - ERR("Failed to get configuration descriptor: %s\n", libusb_strerror(ret)); - } - IoInvalidateDeviceRelations(bus_pdo, BusRelations); }
@@ -379,8 +310,7 @@ static NTSTATUS fdo_pnp(IRP *irp) LIST_FOR_EACH_ENTRY_SAFE(device, cursor, &device_list, struct usb_device, entry) { assert(!device->removed); - if (!device->parent) - destroy_unix_device(device->unix_device); + destroy_unix_device(device->unix_device); list_remove(&device->entry); IoDeleteDevice(device->device_obj); } @@ -445,7 +375,7 @@ static void get_device_id(const struct usb_device *device, struct string_buffer static const WCHAR formatW[] = {'U','S','B','\','V','I','D','_','%','0','4','X', '&','P','I','D','_','%','0','4','X',0};
- if (device->parent) + if (device->interface) append_id(buffer, interface_formatW, device->vendor, device->product, device->interface_index); else append_id(buffer, formatW, device->vendor, device->product); @@ -458,7 +388,7 @@ static void get_hardware_ids(const struct usb_device *device, struct string_buff static const WCHAR formatW[] = {'U','S','B','\','V','I','D','_','%','0','4','X', '&','P','I','D','_','%','0','4','X','&','R','E','V','_','%','0','4','X',0};
- if (device->parent) + if (device->interface) append_id(buffer, interface_formatW, device->vendor, device->product, device->revision, device->interface_index); else append_id(buffer, formatW, device->vendor, device->product, device->revision); @@ -576,8 +506,7 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp) assert(device->removed); remove_pending_irps(device);
- if (!device->parent) - destroy_unix_device(device->unix_device); + destroy_unix_device(device->unix_device);
IoDeleteDevice(device->device_obj); ret = STATUS_SUCCESS;
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wineusb.sys/Makefile.in | 2 +- dlls/wineusb.sys/wineusb.c | 52 ++++++++++++------------------------ 2 files changed, 18 insertions(+), 36 deletions(-)
diff --git a/dlls/wineusb.sys/Makefile.in b/dlls/wineusb.sys/Makefile.in index 5547200596e..66a9f56b213 100644 --- a/dlls/wineusb.sys/Makefile.in +++ b/dlls/wineusb.sys/Makefile.in @@ -5,7 +5,7 @@ IMPORTS = ntoskrnl UNIX_LIBS = $(USB_LIBS) $(PTHREAD_LIBS) UNIX_CFLAGS = $(USB_CFLAGS)
-EXTRADLLFLAGS = -Wl,--subsystem,native -mcygwin +EXTRADLLFLAGS = -Wl,--subsystem,native
C_SRCS = \ unixlib.c \ diff --git a/dlls/wineusb.sys/wineusb.c b/dlls/wineusb.sys/wineusb.c index d432bdc5666..2f918cdeeb7 100644 --- a/dlls/wineusb.sys/wineusb.c +++ b/dlls/wineusb.sys/wineusb.c @@ -21,9 +21,8 @@ #include <assert.h> #include <stdarg.h> #include <stdbool.h> +#include <stdint.h> #include <stdlib.h> -#include <pthread.h> -#include <libusb.h>
#include "ntstatus.h" #define WIN32_NO_STATUS @@ -36,7 +35,6 @@ #include "wine/asm.h" #include "wine/debug.h" #include "wine/list.h" -#include "wine/unicode.h"
#include "unixlib.h"
@@ -106,7 +104,6 @@ static void destroy_unix_device(struct unix_device *unix_device)
static void add_unix_device(const struct usb_add_device_event *event) { - static const WCHAR formatW[] = {'\','D','e','v','i','c','e','\','U','S','B','P','D','O','-','%','u',0}; static unsigned int name_index; struct usb_device *device; DEVICE_OBJECT *device_obj; @@ -117,7 +114,7 @@ static void add_unix_device(const struct usb_add_device_event *event) TRACE("Adding new device %p, vendor %04x, product %04x.\n", event->device, event->vendor, event->product);
- sprintfW(name, formatW, name_index++); + swprintf(name, ARRAY_SIZE(name), L"\Device\USBPDO-%u", name_index++); RtlInitUnicodeString(&string, name); if ((status = IoCreateDevice(driver_obj, sizeof(*device), &string, FILE_DEVICE_USB, 0, FALSE, &device_obj))) @@ -366,54 +363,39 @@ static void WINAPIV append_id(struct string_buffer *buffer, const WCHAR *format, __ms_va_end(args); }
-static const WCHAR emptyW[] = {0}; - static void get_device_id(const struct usb_device *device, struct string_buffer *buffer) { - static const WCHAR interface_formatW[] = {'U','S','B','\','V','I','D','_','%','0','4','X', - '&','P','I','D','_','%','0','4','X','&','M','I','_','%','0','2','X',0}; - static const WCHAR formatW[] = {'U','S','B','\','V','I','D','_','%','0','4','X', - '&','P','I','D','_','%','0','4','X',0}; - if (device->interface) - append_id(buffer, interface_formatW, device->vendor, device->product, device->interface_index); + append_id(buffer, L"USB\VID_%04X&PID_%04X&MI_%02X", + device->vendor, device->product, device->interface_index); else - append_id(buffer, formatW, device->vendor, device->product); + append_id(buffer, L"USB\VID_%04X&PID_%04X", device->vendor, device->product); }
static void get_hardware_ids(const struct usb_device *device, struct string_buffer *buffer) { - static const WCHAR interface_formatW[] = {'U','S','B','\','V','I','D','_','%','0','4','X', - '&','P','I','D','_','%','0','4','X','&','R','E','V','_','%','0','4','X','&','M','I','_','%','0','2','X',0}; - static const WCHAR formatW[] = {'U','S','B','\','V','I','D','_','%','0','4','X', - '&','P','I','D','_','%','0','4','X','&','R','E','V','_','%','0','4','X',0}; - if (device->interface) - append_id(buffer, interface_formatW, device->vendor, device->product, device->revision, device->interface_index); + append_id(buffer, L"USB\VID_%04X&PID_%04X&REV_%04X&MI_%02X", + device->vendor, device->product, device->revision, device->interface_index); else - append_id(buffer, formatW, device->vendor, device->product, device->revision); + append_id(buffer, L"USB\VID_%04X&PID_%04X&REV_%04X", + device->vendor, device->product, device->revision); + get_device_id(device, buffer); - append_id(buffer, emptyW); + append_id(buffer, L""); }
static void get_compatible_ids(const struct usb_device *device, struct string_buffer *buffer) { - static const WCHAR prot_format[] = {'U','S','B','\','C','l','a','s','s','_','%','0','2','x', - '&','S','u','b','C','l','a','s','s','_','%','0','2','x', - '&','P','r','o','t','_','%','0','2','x',0}; - static const WCHAR subclass_format[] = {'U','S','B','\','C','l','a','s','s','_','%','0','2','x', - '&','S','u','b','C','l','a','s','s','_','%','0','2','x',0}; - static const WCHAR class_format[] = {'U','S','B','\','C','l','a','s','s','_','%','0','2','x',0}; - - append_id(buffer, prot_format, device->class, device->subclass, device->protocol); - append_id(buffer, subclass_format, device->class, device->subclass); - append_id(buffer, class_format, device->class); - append_id(buffer, emptyW); + append_id(buffer, L"USB\Class_%02x&SubClass_%02x&Prot_%02x", + device->class, device->subclass, device->protocol); + append_id(buffer, L"USB\Class_%02x&SubClass_%02x", device->class, device->subclass); + append_id(buffer, L"USB\Class_%02x", device->class); + append_id(buffer, L""); }
static NTSTATUS query_id(struct usb_device *device, IRP *irp, BUS_QUERY_ID_TYPE type) { - static const WCHAR instance_idW[] = {'0',0}; struct string_buffer buffer = {0};
TRACE("type %#x.\n", type); @@ -425,7 +407,7 @@ static NTSTATUS query_id(struct usb_device *device, IRP *irp, BUS_QUERY_ID_TYPE break;
case BusQueryInstanceID: - append_id(&buffer, instance_idW); + append_id(&buffer, L"0"); break;
case BusQueryHardwareIDs: