[PATCH 4/4] wineusb.sys: Create a separate unix_device struct to wrap the libusb device handle.
Zebediah Figura
wine at gitlab.winehq.org
Fri Jul 1 00:55:04 CDT 2022
From: Zebediah Figura <zfigura at codeweavers.com>
Keep unix_device objects in a separate list.
---
dlls/wineusb.sys/Makefile.in | 2 +-
dlls/wineusb.sys/wineusb.c | 100 +++++++++++++++++++++++++++--------
2 files changed, 78 insertions(+), 24 deletions(-)
diff --git a/dlls/wineusb.sys/Makefile.in b/dlls/wineusb.sys/Makefile.in
index ee3bfffdbeb..5547200596e 100644
--- a/dlls/wineusb.sys/Makefile.in
+++ b/dlls/wineusb.sys/Makefile.in
@@ -2,7 +2,7 @@ EXTRADEFS = -DWINE_NO_LONG_TYPES
MODULE = wineusb.sys
UNIXLIB = wineusb.so
IMPORTS = ntoskrnl
-UNIX_LIBS = $(USB_LIBS)
+UNIX_LIBS = $(USB_LIBS) $(PTHREAD_LIBS)
UNIX_CFLAGS = $(USB_CFLAGS)
EXTRADLLFLAGS = -Wl,--subsystem,native -mcygwin
diff --git a/dlls/wineusb.sys/wineusb.c b/dlls/wineusb.sys/wineusb.c
index 59d8bd93fc4..cfa88616a8f 100644
--- a/dlls/wineusb.sys/wineusb.c
+++ b/dlls/wineusb.sys/wineusb.c
@@ -21,6 +21,7 @@
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
+#include <pthread.h>
#include <libusb.h>
#include "ntstatus.h"
@@ -68,8 +69,18 @@ DECLARE_CRITICAL_SECTION(wineusb_cs);
static unixlib_handle_t unix_handle;
+static pthread_mutex_t unix_device_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static struct list unix_device_list = LIST_INIT(unix_device_list);
static struct list device_list = LIST_INIT(device_list);
+struct unix_device
+{
+ struct list entry;
+
+ libusb_device_handle *handle;
+};
+
struct usb_device
{
struct list entry;
@@ -86,7 +97,7 @@ struct usb_device
uint16_t vendor, product, revision;
- libusb_device_handle *handle;
+ struct unix_device *unix_device;
LIST_ENTRY irp_list;
};
@@ -96,6 +107,15 @@ static DEVICE_OBJECT *bus_fdo, *bus_pdo;
static libusb_hotplug_callback_handle hotplug_cb_handle;
+static void destroy_unix_device(struct unix_device *unix_device)
+{
+ pthread_mutex_lock(&unix_device_mutex);
+ libusb_close(unix_device->handle);
+ list_remove(&unix_device->entry);
+ pthread_mutex_unlock(&unix_device_mutex);
+ free(unix_device);
+}
+
static void add_usb_interface(struct usb_device *parent, const struct libusb_interface_descriptor *desc)
{
struct usb_device *device;
@@ -112,7 +132,7 @@ static void add_usb_interface(struct usb_device *parent, const struct libusb_int
device = device_obj->DeviceExtension;
device->device_obj = device_obj;
device->parent = parent;
- device->handle = parent->handle;
+ device->unix_device = parent->unix_device;
device->interface_index = desc->bInterfaceNumber;
device->class = desc->bInterfaceClass;
device->subclass = desc->bInterfaceSubClass;
@@ -127,13 +147,13 @@ static void add_usb_interface(struct usb_device *parent, const struct libusb_int
LeaveCriticalSection(&wineusb_cs);
}
-static void add_usb_device(libusb_device *libusb_device)
+static void add_unix_device(struct unix_device *unix_device)
{
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);
struct libusb_config_descriptor *config_desc;
struct libusb_device_descriptor device_desc;
static unsigned int name_index;
- libusb_device_handle *handle;
struct usb_device *device;
DEVICE_OBJECT *device_obj;
UNICODE_STRING string;
@@ -143,28 +163,21 @@ static void add_usb_device(libusb_device *libusb_device)
libusb_get_device_descriptor(libusb_device, &device_desc);
- TRACE("Adding new device %p, vendor %04x, product %04x.\n", libusb_device,
+ TRACE("Adding new device %p, vendor %04x, product %04x.\n", unix_device,
device_desc.idVendor, device_desc.idProduct);
- if ((ret = libusb_open(libusb_device, &handle)))
- {
- WARN("Failed to open device: %s\n", libusb_strerror(ret));
- return;
- }
-
sprintfW(name, formatW, name_index++);
RtlInitUnicodeString(&string, name);
if ((status = IoCreateDevice(driver_obj, sizeof(*device), &string,
FILE_DEVICE_USB, 0, FALSE, &device_obj)))
{
ERR("Failed to create device, status %#x.\n", status);
- libusb_close(handle);
return;
}
device = device_obj->DeviceExtension;
device->device_obj = device_obj;
- device->handle = handle;
+ device->unix_device = unix_device;
InitializeListHead(&device->irp_list);
EnterCriticalSection(&wineusb_cs);
@@ -215,16 +228,43 @@ static void add_usb_device(libusb_device *libusb_device)
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
}
-static void remove_usb_device(libusb_device *libusb_device)
+static void add_usb_device(libusb_device *libusb_device)
+{
+ struct libusb_device_descriptor device_desc;
+ struct unix_device *unix_device;
+ int ret;
+
+ libusb_get_device_descriptor(libusb_device, &device_desc);
+
+ TRACE("Adding new device %p, vendor %04x, product %04x.\n", libusb_device,
+ device_desc.idVendor, device_desc.idProduct);
+
+ if (!(unix_device = calloc(1, sizeof(*unix_device))))
+ return;
+
+ if ((ret = libusb_open(libusb_device, &unix_device->handle)))
+ {
+ WARN("Failed to open device: %s\n", libusb_strerror(ret));
+ free(unix_device);
+ return;
+ }
+ pthread_mutex_lock(&unix_device_mutex);
+ list_add_tail(&unix_device_list, &unix_device->entry);
+ pthread_mutex_unlock(&unix_device_mutex);
+
+ add_unix_device(unix_device);
+}
+
+static void remove_unix_device(struct unix_device *unix_device)
{
struct usb_device *device;
- TRACE("Removing device %p.\n", libusb_device);
+ TRACE("Removing device %p.\n", unix_device);
EnterCriticalSection(&wineusb_cs);
LIST_FOR_EACH_ENTRY(device, &device_list, struct usb_device, entry)
{
- if (libusb_get_device(device->handle) == libusb_device)
+ if (device->unix_device == unix_device)
{
if (!device->removed)
{
@@ -239,6 +279,19 @@ static void remove_usb_device(libusb_device *libusb_device)
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
}
+static void remove_usb_device(libusb_device *libusb_device)
+{
+ struct unix_device *unix_device;
+
+ TRACE("Removing device %p.\n", libusb_device);
+
+ LIST_FOR_EACH_ENTRY(unix_device, &unix_device_list, struct unix_device, entry)
+ {
+ if (libusb_get_device(unix_device->handle) == libusb_device)
+ remove_unix_device(unix_device);
+ }
+}
+
static BOOL thread_shutdown;
static HANDLE event_thread;
@@ -361,7 +414,7 @@ static NTSTATUS fdo_pnp(IRP *irp)
{
assert(!device->removed);
if (!device->parent)
- libusb_close(device->handle);
+ destroy_unix_device(device->unix_device);
list_remove(&device->entry);
IoDeleteDevice(device->device_obj);
}
@@ -558,7 +611,7 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp)
remove_pending_irps(device);
if (!device->parent)
- libusb_close(device->handle);
+ destroy_unix_device(device->unix_device);
IoDeleteDevice(device->device_obj);
ret = STATUS_SUCCESS;
@@ -691,6 +744,7 @@ static struct pipe get_pipe(HANDLE handle)
static NTSTATUS usb_submit_urb(struct usb_device *device, IRP *irp)
{
URB *urb = IoGetCurrentIrpStackLocation(irp)->Parameters.Others.Argument1;
+ libusb_device_handle *handle = device->unix_device->handle;
struct libusb_transfer *transfer;
int ret;
@@ -727,7 +781,7 @@ static NTSTATUS usb_submit_urb(struct usb_device *device, IRP *irp)
struct _URB_PIPE_REQUEST *req = &urb->UrbPipeRequest;
struct pipe pipe = get_pipe(req->PipeHandle);
- if ((ret = libusb_clear_halt(device->handle, pipe.endpoint)) < 0)
+ if ((ret = libusb_clear_halt(handle, pipe.endpoint)) < 0)
ERR("Failed to clear halt: %s\n", libusb_strerror(ret));
return STATUS_SUCCESS;
@@ -746,12 +800,12 @@ static NTSTATUS usb_submit_urb(struct usb_device *device, IRP *irp)
if (pipe.type == UsbdPipeTypeBulk)
{
- libusb_fill_bulk_transfer(transfer, device->handle, pipe.endpoint,
+ libusb_fill_bulk_transfer(transfer, handle, pipe.endpoint,
req->TransferBuffer, req->TransferBufferLength, transfer_cb, irp, 0);
}
else if (pipe.type == UsbdPipeTypeInterrupt)
{
- libusb_fill_interrupt_transfer(transfer, device->handle, pipe.endpoint,
+ libusb_fill_interrupt_transfer(transfer, handle, pipe.endpoint,
req->TransferBuffer, req->TransferBufferLength, transfer_cb, irp, 0);
}
else
@@ -792,7 +846,7 @@ static NTSTATUS usb_submit_urb(struct usb_device *device, IRP *irp)
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
LIBUSB_REQUEST_GET_DESCRIPTOR, (req->DescriptorType << 8) | req->Index,
req->LanguageId, req->TransferBufferLength);
- libusb_fill_control_transfer(transfer, device->handle, buffer, transfer_cb, irp, 0);
+ libusb_fill_control_transfer(transfer, handle, buffer, transfer_cb, irp, 0);
transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
ret = libusb_submit_transfer(transfer);
if (ret < 0)
@@ -849,7 +903,7 @@ static NTSTATUS usb_submit_urb(struct usb_device *device, IRP *irp)
req->Value, req->Index, req->TransferBufferLength);
if (!(req->TransferFlags & USBD_TRANSFER_DIRECTION_IN))
memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, req->TransferBuffer, req->TransferBufferLength);
- libusb_fill_control_transfer(transfer, device->handle, buffer, transfer_cb, irp, 0);
+ libusb_fill_control_transfer(transfer, handle, buffer, transfer_cb, irp, 0);
transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
ret = libusb_submit_transfer(transfer);
if (ret < 0)
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/356
More information about the wine-devel
mailing list