dllhost: Add ISurrogate stub implementation.
[wine.git] / dlls / wineusb.sys / wineusb.c
blobcca0257bb0298ba80940dc9ac240bc6cf45c809d
1 /*
2 * USB root device enumerator using libusb
4 * Copyright 2020 Zebediah Figura
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <libusb.h>
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "windef.h"
29 #include "winioctl.h"
30 #include "winternl.h"
31 #include "ddk/wdm.h"
32 #include "ddk/usb.h"
33 #include "ddk/usbioctl.h"
34 #include "wine/asm.h"
35 #include "wine/debug.h"
36 #include "wine/list.h"
37 #include "wine/unicode.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(wineusb);
41 #ifdef __ASM_USE_FASTCALL_WRAPPER
43 extern void * WINAPI wrap_fastcall_func1( void *func, const void *a );
44 __ASM_STDCALL_FUNC( wrap_fastcall_func1, 8,
45 "popl %ecx\n\t"
46 "popl %eax\n\t"
47 "xchgl (%esp),%ecx\n\t"
48 "jmp *%eax" );
50 #define call_fastcall_func1(func,a) wrap_fastcall_func1(func,a)
52 #else
54 #define call_fastcall_func1(func,a) func(a)
56 #endif
58 #define DECLARE_CRITICAL_SECTION(cs) \
59 static CRITICAL_SECTION cs; \
60 static CRITICAL_SECTION_DEBUG cs##_debug = \
61 { 0, 0, &cs, { &cs##_debug.ProcessLocksList, &cs##_debug.ProcessLocksList }, \
62 0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \
63 static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 };
65 DECLARE_CRITICAL_SECTION(wineusb_cs);
67 static struct list device_list = LIST_INIT(device_list);
69 struct usb_device
71 struct list entry;
72 BOOL removed;
74 DEVICE_OBJECT *device_obj;
76 libusb_device *libusb_device;
77 libusb_device_handle *handle;
79 LIST_ENTRY irp_list;
82 static DRIVER_OBJECT *driver_obj;
83 static DEVICE_OBJECT *bus_fdo, *bus_pdo;
85 static libusb_hotplug_callback_handle hotplug_cb_handle;
87 static void add_usb_device(libusb_device *libusb_device)
89 static const WCHAR formatW[] = {'\\','D','e','v','i','c','e','\\','U','S','B','P','D','O','-','%','u',0};
90 struct libusb_device_descriptor device_desc;
91 static unsigned int name_index;
92 libusb_device_handle *handle;
93 struct usb_device *device;
94 DEVICE_OBJECT *device_obj;
95 UNICODE_STRING string;
96 NTSTATUS status;
97 WCHAR name[26];
98 int ret;
100 libusb_get_device_descriptor(libusb_device, &device_desc);
102 TRACE("Adding new device %p, vendor %04x, product %04x.\n", libusb_device,
103 device_desc.idVendor, device_desc.idProduct);
105 if ((ret = libusb_open(libusb_device, &handle)))
107 WARN("Failed to open device: %s\n", libusb_strerror(ret));
108 return;
111 sprintfW(name, formatW, name_index++);
112 RtlInitUnicodeString(&string, name);
113 if ((status = IoCreateDevice(driver_obj, sizeof(*device), &string,
114 FILE_DEVICE_USB, 0, FALSE, &device_obj)))
116 ERR("Failed to create device, status %#x.\n", status);
117 LeaveCriticalSection(&wineusb_cs);
118 libusb_close(handle);
119 return;
122 device = device_obj->DeviceExtension;
123 device->device_obj = device_obj;
124 device->libusb_device = libusb_ref_device(libusb_device);
125 device->handle = handle;
126 InitializeListHead(&device->irp_list);
128 EnterCriticalSection(&wineusb_cs);
129 list_add_tail(&device_list, &device->entry);
130 device->removed = FALSE;
131 LeaveCriticalSection(&wineusb_cs);
133 IoInvalidateDeviceRelations(bus_pdo, BusRelations);
136 static void remove_usb_device(libusb_device *libusb_device)
138 struct usb_device *device;
140 TRACE("Removing device %p.\n", libusb_device);
142 EnterCriticalSection(&wineusb_cs);
143 LIST_FOR_EACH_ENTRY(device, &device_list, struct usb_device, entry)
145 if (device->libusb_device == libusb_device)
147 if (!device->removed)
149 device->removed = TRUE;
150 list_remove(&device->entry);
152 break;
155 LeaveCriticalSection(&wineusb_cs);
157 IoInvalidateDeviceRelations(bus_pdo, BusRelations);
160 static BOOL thread_shutdown;
161 static HANDLE event_thread;
163 static int LIBUSB_CALL hotplug_cb(libusb_context *context, libusb_device *device,
164 libusb_hotplug_event event, void *user_data)
166 if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)
167 add_usb_device(device);
168 else
169 remove_usb_device(device);
171 return 0;
174 static DWORD CALLBACK event_thread_proc(void *arg)
176 int ret;
178 TRACE("Starting event thread.\n");
180 while (!thread_shutdown)
182 if ((ret = libusb_handle_events(NULL)))
183 ERR("Error handling events: %s\n", libusb_strerror(ret));
186 TRACE("Shutting down event thread.\n");
187 return 0;
190 static NTSTATUS fdo_pnp(IRP *irp)
192 IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
193 NTSTATUS ret;
195 TRACE("irp %p, minor function %#x.\n", irp, stack->MinorFunction);
197 switch (stack->MinorFunction)
199 case IRP_MN_QUERY_DEVICE_RELATIONS:
201 struct usb_device *device;
202 DEVICE_RELATIONS *devices;
203 unsigned int i = 0;
205 if (stack->Parameters.QueryDeviceRelations.Type != BusRelations)
207 FIXME("Unhandled device relations type %#x.\n", stack->Parameters.QueryDeviceRelations.Type);
208 break;
211 EnterCriticalSection(&wineusb_cs);
213 if (!(devices = ExAllocatePool(PagedPool,
214 offsetof(DEVICE_RELATIONS, Objects[list_count(&device_list)]))))
216 LeaveCriticalSection(&wineusb_cs);
217 irp->IoStatus.Status = STATUS_NO_MEMORY;
218 break;
221 LIST_FOR_EACH_ENTRY(device, &device_list, struct usb_device, entry)
223 devices->Objects[i++] = device->device_obj;
224 call_fastcall_func1(ObfReferenceObject, device->device_obj);
227 LeaveCriticalSection(&wineusb_cs);
229 devices->Count = i;
230 irp->IoStatus.Information = (ULONG_PTR)devices;
231 irp->IoStatus.Status = STATUS_SUCCESS;
232 break;
235 case IRP_MN_START_DEVICE:
236 if ((ret = libusb_hotplug_register_callback(NULL,
237 LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
238 LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
239 LIBUSB_HOTPLUG_MATCH_ANY, hotplug_cb, NULL, &hotplug_cb_handle)))
241 ERR("Failed to register callback: %s\n", libusb_strerror(ret));
242 irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
243 break;
245 irp->IoStatus.Status = STATUS_SUCCESS;
246 break;
248 case IRP_MN_SURPRISE_REMOVAL:
249 irp->IoStatus.Status = STATUS_SUCCESS;
250 break;
252 case IRP_MN_REMOVE_DEVICE:
254 struct usb_device *device, *cursor;
256 libusb_hotplug_deregister_callback(NULL, hotplug_cb_handle);
257 thread_shutdown = TRUE;
258 libusb_interrupt_event_handler(NULL);
259 WaitForSingleObject(event_thread, INFINITE);
260 CloseHandle(event_thread);
262 EnterCriticalSection(&wineusb_cs);
263 /* Normally we unlink all devices either:
265 * - as a result of hot-unplug, which unlinks the device, and causes
266 * a subsequent IRP_MN_REMOVE_DEVICE which will free it;
268 * - if the parent is deleted (at shutdown time), in which case
269 * ntoskrnl will send us IRP_MN_SURPRISE_REMOVAL and
270 * IRP_MN_REMOVE_DEVICE unprompted.
272 * But we can get devices hotplugged between when shutdown starts
273 * and now, in which case they'll be stuck in this list and never
274 * freed.
276 * FIXME: This is still broken, though. If a device is hotplugged
277 * and then removed, it'll be unlinked and never freed. */
278 LIST_FOR_EACH_ENTRY_SAFE(device, cursor, &device_list, struct usb_device, entry)
280 assert(!device->removed);
281 libusb_unref_device(device->libusb_device);
282 libusb_close(device->handle);
283 list_remove(&device->entry);
284 IoDeleteDevice(device->device_obj);
286 LeaveCriticalSection(&wineusb_cs);
288 irp->IoStatus.Status = STATUS_SUCCESS;
289 IoSkipCurrentIrpStackLocation(irp);
290 ret = IoCallDriver(bus_pdo, irp);
291 IoDetachDevice(bus_pdo);
292 IoDeleteDevice(bus_fdo);
293 return ret;
296 default:
297 FIXME("Unhandled minor function %#x.\n", stack->MinorFunction);
300 IoSkipCurrentIrpStackLocation(irp);
301 return IoCallDriver(bus_pdo, irp);
304 static void get_device_id(const struct usb_device *device, WCHAR *buffer)
306 static const WCHAR formatW[] = {'U','S','B','\\','V','I','D','_','%','0','4','X',
307 '&','P','I','D','_','%','0','4','X',0};
308 struct libusb_device_descriptor desc;
310 libusb_get_device_descriptor(device->libusb_device, &desc);
311 sprintfW(buffer, formatW, desc.idVendor, desc.idProduct);
314 static void get_hardware_ids(const struct usb_device *device, WCHAR *buffer)
316 static const WCHAR formatW[] = {'U','S','B','\\','V','I','D','_','%','0','4','X',
317 '&','P','I','D','_','%','0','4','X','&','R','E','V','_','%','0','4','X',0};
318 struct libusb_device_descriptor desc;
320 libusb_get_device_descriptor(device->libusb_device, &desc);
321 buffer += sprintfW(buffer, formatW, desc.idVendor, desc.idProduct, desc.bcdDevice) + 1;
322 get_device_id(device, buffer);
323 buffer += strlenW(buffer) + 1;
324 *buffer = 0;
327 static void get_compatible_ids(const struct usb_device *device, WCHAR *buffer)
329 static const WCHAR prot_format[] = {'U','S','B','\\','C','l','a','s','s','_','%','0','2','x',
330 '&','S','u','b','C','l','a','s','s','_','%','0','2','x',
331 '&','P','r','o','t','_','%','0','2','x',0};
332 static const WCHAR subclass_format[] = {'U','S','B','\\','C','l','a','s','s','_','%','0','2','x',
333 '&','S','u','b','C','l','a','s','s','_','%','0','2','x',0};
334 static const WCHAR class_format[] = {'U','S','B','\\','C','l','a','s','s','_','%','0','2','x',0};
336 struct libusb_device_descriptor device_desc;
338 libusb_get_device_descriptor(device->libusb_device, &device_desc);
340 buffer += sprintfW(buffer, prot_format, device_desc.bDeviceClass, device_desc.bDeviceSubClass,
341 device_desc.bDeviceProtocol) + 1;
342 buffer += sprintfW(buffer, subclass_format, device_desc.bDeviceClass, device_desc.bDeviceSubClass) + 1;
343 buffer += sprintfW(buffer, class_format, device_desc.bDeviceClass) + 1;
344 *buffer = 0;
347 static NTSTATUS query_id(const struct usb_device *device, IRP *irp, BUS_QUERY_ID_TYPE type)
349 WCHAR *id = NULL;
351 switch (type)
353 case BusQueryDeviceID:
354 if ((id = ExAllocatePool(PagedPool, 28 * sizeof(WCHAR))))
355 get_device_id(device, id);
356 break;
358 case BusQueryInstanceID:
359 if ((id = ExAllocatePool(PagedPool, 2 * sizeof(WCHAR))))
361 id[0] = '0';
362 id[1] = 0;
364 break;
366 case BusQueryHardwareIDs:
367 if ((id = ExAllocatePool(PagedPool, (28 + 37 + 1) * sizeof(WCHAR))))
368 get_hardware_ids(device, id);
369 break;
371 case BusQueryCompatibleIDs:
372 if ((id = ExAllocatePool(PagedPool, (33 + 25 + 13 + 1) * sizeof(WCHAR))))
373 get_compatible_ids(device, id);
374 break;
376 default:
377 FIXME("Unhandled ID query type %#x.\n", type);
378 return irp->IoStatus.Status;
381 irp->IoStatus.Information = (ULONG_PTR)id;
382 return STATUS_SUCCESS;
385 static void remove_pending_irps(struct usb_device *device)
387 LIST_ENTRY *entry;
388 IRP *irp;
390 while ((entry = RemoveHeadList(&device->irp_list)) != &device->irp_list)
392 irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
393 irp->IoStatus.Status = STATUS_DELETE_PENDING;
394 irp->IoStatus.Information = 0;
395 IoCompleteRequest(irp, IO_NO_INCREMENT);
399 static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp)
401 IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
402 struct usb_device *device = device_obj->DeviceExtension;
403 NTSTATUS ret = irp->IoStatus.Status;
405 TRACE("device_obj %p, irp %p, minor function %#x.\n", device_obj, irp, stack->MinorFunction);
407 switch (stack->MinorFunction)
409 case IRP_MN_QUERY_ID:
410 ret = query_id(device, irp, stack->Parameters.QueryId.IdType);
411 break;
413 case IRP_MN_QUERY_CAPABILITIES:
415 DEVICE_CAPABILITIES *caps = stack->Parameters.DeviceCapabilities.Capabilities;
417 caps->RawDeviceOK = 1;
419 ret = STATUS_SUCCESS;
420 break;
423 case IRP_MN_START_DEVICE:
424 ret = STATUS_SUCCESS;
425 break;
427 case IRP_MN_SURPRISE_REMOVAL:
428 EnterCriticalSection(&wineusb_cs);
429 remove_pending_irps(device);
430 if (!device->removed)
432 device->removed = TRUE;
433 list_remove(&device->entry);
435 LeaveCriticalSection(&wineusb_cs);
436 ret = STATUS_SUCCESS;
437 break;
439 case IRP_MN_REMOVE_DEVICE:
440 assert(device->removed);
441 remove_pending_irps(device);
443 libusb_unref_device(device->libusb_device);
444 libusb_close(device->handle);
446 IoDeleteDevice(device->device_obj);
447 ret = STATUS_SUCCESS;
448 break;
450 default:
451 FIXME("Unhandled minor function %#x.\n", stack->MinorFunction);
454 irp->IoStatus.Status = ret;
455 IoCompleteRequest(irp, IO_NO_INCREMENT);
456 return ret;
459 static NTSTATUS WINAPI driver_pnp(DEVICE_OBJECT *device, IRP *irp)
461 if (device == bus_fdo)
462 return fdo_pnp(irp);
463 return pdo_pnp(device, irp);
466 static NTSTATUS usbd_status_from_libusb(enum libusb_transfer_status status)
468 switch (status)
470 case LIBUSB_TRANSFER_CANCELLED:
471 return USBD_STATUS_CANCELED;
472 case LIBUSB_TRANSFER_COMPLETED:
473 return USBD_STATUS_SUCCESS;
474 case LIBUSB_TRANSFER_NO_DEVICE:
475 return USBD_STATUS_DEVICE_GONE;
476 case LIBUSB_TRANSFER_STALL:
477 return USBD_STATUS_ENDPOINT_HALTED;
478 case LIBUSB_TRANSFER_TIMED_OUT:
479 return USBD_STATUS_TIMEOUT;
480 default:
481 FIXME("Unhandled status %#x.\n", status);
482 case LIBUSB_TRANSFER_ERROR:
483 return USBD_STATUS_REQUEST_FAILED;
487 static void transfer_cb(struct libusb_transfer *transfer)
489 IRP *irp = transfer->user_data;
490 URB *urb = IoGetCurrentIrpStackLocation(irp)->Parameters.Others.Argument1;
492 TRACE("Completing IRP %p, status %#x.\n", irp, transfer->status);
494 urb->UrbHeader.Status = usbd_status_from_libusb(transfer->status);
496 if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
498 switch (urb->UrbHeader.Function)
500 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
501 urb->UrbBulkOrInterruptTransfer.TransferBufferLength = transfer->actual_length;
502 break;
504 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
506 struct _URB_CONTROL_DESCRIPTOR_REQUEST *req = &urb->UrbControlDescriptorRequest;
507 req->TransferBufferLength = transfer->actual_length;
508 memcpy(req->TransferBuffer, libusb_control_transfer_get_data(transfer), transfer->actual_length);
509 break;
512 case URB_FUNCTION_VENDOR_INTERFACE:
514 struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *req = &urb->UrbControlVendorClassRequest;
515 req->TransferBufferLength = transfer->actual_length;
516 if (req->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
517 memcpy(req->TransferBuffer, libusb_control_transfer_get_data(transfer), transfer->actual_length);
518 break;
521 default:
522 ERR("Unexpected function %#x.\n", urb->UrbHeader.Function);
526 EnterCriticalSection(&wineusb_cs);
527 RemoveEntryList(&irp->Tail.Overlay.ListEntry);
528 LeaveCriticalSection(&wineusb_cs);
530 irp->IoStatus.Status = STATUS_SUCCESS;
531 IoCompleteRequest(irp, IO_NO_INCREMENT);
534 static void queue_irp(struct usb_device *device, IRP *irp, struct libusb_transfer *transfer)
536 IoMarkIrpPending(irp);
537 irp->Tail.Overlay.DriverContext[0] = transfer;
538 EnterCriticalSection(&wineusb_cs);
539 InsertTailList(&device->irp_list, &irp->Tail.Overlay.ListEntry);
540 LeaveCriticalSection(&wineusb_cs);
543 struct pipe
545 unsigned char endpoint;
546 unsigned char type;
549 static HANDLE make_pipe_handle(unsigned char endpoint, USBD_PIPE_TYPE type)
551 union
553 struct pipe pipe;
554 HANDLE handle;
555 } u;
557 u.pipe.endpoint = endpoint;
558 u.pipe.type = type;
559 return u.handle;
562 static struct pipe get_pipe(HANDLE handle)
564 union
566 struct pipe pipe;
567 HANDLE handle;
568 } u;
570 u.handle = handle;
571 return u.pipe;
574 static NTSTATUS usb_submit_urb(struct usb_device *device, IRP *irp)
576 URB *urb = IoGetCurrentIrpStackLocation(irp)->Parameters.Others.Argument1;
577 struct libusb_transfer *transfer;
578 int ret;
580 TRACE("type %#x.\n", urb->UrbHeader.Function);
582 switch (urb->UrbHeader.Function)
584 case URB_FUNCTION_ABORT_PIPE:
586 LIST_ENTRY *entry, *mark;
588 /* The documentation states that URB_FUNCTION_ABORT_PIPE may
589 * complete before outstanding requests complete, so we don't need
590 * to wait for them. */
591 EnterCriticalSection(&wineusb_cs);
592 mark = &device->irp_list;
593 for (entry = mark->Flink; entry != mark; entry = entry->Flink)
595 IRP *queued_irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
597 if ((ret = libusb_cancel_transfer(queued_irp->Tail.Overlay.DriverContext[0])) < 0)
598 ERR("Failed to cancel transfer: %s\n", libusb_strerror(ret));
600 LeaveCriticalSection(&wineusb_cs);
602 return STATUS_SUCCESS;
605 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
607 struct _URB_PIPE_REQUEST *req = &urb->UrbPipeRequest;
608 struct pipe pipe = get_pipe(req->PipeHandle);
610 if ((ret = libusb_clear_halt(device->handle, pipe.endpoint)) < 0)
611 ERR("Failed to clear halt: %s\n", libusb_strerror(ret));
613 return STATUS_SUCCESS;
616 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
618 struct _URB_BULK_OR_INTERRUPT_TRANSFER *req = &urb->UrbBulkOrInterruptTransfer;
619 struct pipe pipe = get_pipe(req->PipeHandle);
621 if (req->TransferBufferMDL)
622 FIXME("Unhandled MDL output buffer.\n");
624 if (!(transfer = libusb_alloc_transfer(0)))
625 return STATUS_NO_MEMORY;
627 if (pipe.type == UsbdPipeTypeBulk)
629 libusb_fill_bulk_transfer(transfer, device->handle, pipe.endpoint,
630 req->TransferBuffer, req->TransferBufferLength, transfer_cb, irp, 0);
632 else if (pipe.type == UsbdPipeTypeInterrupt)
634 libusb_fill_interrupt_transfer(transfer, device->handle, pipe.endpoint,
635 req->TransferBuffer, req->TransferBufferLength, transfer_cb, irp, 0);
637 else
639 WARN("Invalid pipe type %#x.\n", pipe.type);
640 libusb_free_transfer(transfer);
641 return USBD_STATUS_INVALID_PIPE_HANDLE;
644 queue_irp(device, irp, transfer);
645 transfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER;
646 ret = libusb_submit_transfer(transfer);
647 if (ret < 0)
648 ERR("Failed to submit bulk transfer: %s\n", libusb_strerror(ret));
650 return STATUS_PENDING;
653 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
655 struct _URB_CONTROL_DESCRIPTOR_REQUEST *req = &urb->UrbControlDescriptorRequest;
656 unsigned char *buffer;
658 if (req->TransferBufferMDL)
659 FIXME("Unhandled MDL output buffer.\n");
661 if (!(transfer = libusb_alloc_transfer(0)))
662 return STATUS_NO_MEMORY;
664 if (!(buffer = malloc(sizeof(struct libusb_control_setup) + req->TransferBufferLength)))
666 libusb_free_transfer(transfer);
667 return STATUS_NO_MEMORY;
670 queue_irp(device, irp, transfer);
671 libusb_fill_control_setup(buffer,
672 LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
673 LIBUSB_REQUEST_GET_DESCRIPTOR, (req->DescriptorType << 8) | req->Index,
674 req->LanguageId, req->TransferBufferLength);
675 libusb_fill_control_transfer(transfer, device->handle, buffer, transfer_cb, irp, 0);
676 transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
677 ret = libusb_submit_transfer(transfer);
678 if (ret < 0)
679 ERR("Failed to submit GET_DESCRIPTOR transfer: %s\n", libusb_strerror(ret));
681 return STATUS_PENDING;
684 case URB_FUNCTION_SELECT_CONFIGURATION:
686 struct _URB_SELECT_CONFIGURATION *req = &urb->UrbSelectConfiguration;
687 ULONG i;
689 /* FIXME: In theory, we'd call libusb_set_configuration() here, but
690 * the CASIO FX-9750GII (which has only one configuration) goes into
691 * an error state if it receives a SET_CONFIGURATION request. Maybe
692 * we should skip setting that if and only if the configuration is
693 * already active? */
695 for (i = 0; i < req->Interface.NumberOfPipes; ++i)
697 USBD_PIPE_INFORMATION *pipe = &req->Interface.Pipes[i];
698 pipe->PipeHandle = make_pipe_handle(pipe->EndpointAddress, pipe->PipeType);
701 return STATUS_SUCCESS;
704 case URB_FUNCTION_VENDOR_INTERFACE:
706 struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST *req = &urb->UrbControlVendorClassRequest;
707 uint8_t req_type = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_INTERFACE;
708 unsigned char *buffer;
710 if (req->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
711 req_type |= LIBUSB_ENDPOINT_IN;
712 if (req->TransferFlags & ~USBD_TRANSFER_DIRECTION_IN)
713 FIXME("Unhandled flags %#x.\n", req->TransferFlags);
715 if (req->TransferBufferMDL)
716 FIXME("Unhandled MDL output buffer.\n");
718 if (!(transfer = libusb_alloc_transfer(0)))
719 return STATUS_NO_MEMORY;
721 if (!(buffer = malloc(sizeof(struct libusb_control_setup) + req->TransferBufferLength)))
723 libusb_free_transfer(transfer);
724 return STATUS_NO_MEMORY;
727 queue_irp(device, irp, transfer);
728 libusb_fill_control_setup(buffer, req_type, req->Request,
729 req->Value, req->Index, req->TransferBufferLength);
730 if (!(req->TransferFlags & USBD_TRANSFER_DIRECTION_IN))
731 memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, req->TransferBuffer, req->TransferBufferLength);
732 libusb_fill_control_transfer(transfer, device->handle, buffer, transfer_cb, irp, 0);
733 transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
734 ret = libusb_submit_transfer(transfer);
735 if (ret < 0)
736 ERR("Failed to submit vendor-specific interface transfer: %s\n", libusb_strerror(ret));
738 return STATUS_PENDING;
741 default:
742 FIXME("Unhandled function %#x.\n", urb->UrbHeader.Function);
745 return STATUS_NOT_IMPLEMENTED;
748 static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device_obj, IRP *irp)
750 IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
751 ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
752 struct usb_device *device = device_obj->DeviceExtension;
753 NTSTATUS status = STATUS_NOT_IMPLEMENTED;
754 BOOL removed;
756 TRACE("device_obj %p, irp %p, code %#x.\n", device_obj, irp, code);
758 EnterCriticalSection(&wineusb_cs);
759 removed = device->removed;
760 LeaveCriticalSection(&wineusb_cs);
762 if (removed)
764 irp->IoStatus.Status = STATUS_DELETE_PENDING;
765 IoCompleteRequest(irp, IO_NO_INCREMENT);
766 return STATUS_DELETE_PENDING;
769 switch (code)
771 case IOCTL_INTERNAL_USB_SUBMIT_URB:
772 status = usb_submit_urb(device, irp);
773 break;
775 default:
776 FIXME("Unhandled ioctl %#x (device %#x, access %#x, function %#x, method %#x).\n",
777 code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
780 if (status != STATUS_PENDING)
782 irp->IoStatus.Status = status;
783 IoCompleteRequest(irp, IO_NO_INCREMENT);
785 return status;
788 static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *pdo)
790 NTSTATUS ret;
792 TRACE("driver %p, pdo %p.\n", driver, pdo);
794 if ((ret = IoCreateDevice(driver, 0, NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &bus_fdo)))
796 ERR("Failed to create FDO, status %#x.\n", ret);
797 return ret;
800 IoAttachDeviceToDeviceStack(bus_fdo, pdo);
801 bus_pdo = pdo;
802 bus_fdo->Flags &= ~DO_DEVICE_INITIALIZING;
804 return STATUS_SUCCESS;
807 static void WINAPI driver_unload(DRIVER_OBJECT *driver)
809 libusb_exit(NULL);
812 NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *path)
814 int err;
816 TRACE("driver %p, path %s.\n", driver, debugstr_w(path->Buffer));
818 driver_obj = driver;
820 if ((err = libusb_init(NULL)))
822 ERR("Failed to initialize libusb: %s\n", libusb_strerror(err));
823 return STATUS_UNSUCCESSFUL;
826 event_thread = CreateThread(NULL, 0, event_thread_proc, NULL, 0, NULL);
828 driver->DriverExtension->AddDevice = driver_add_device;
829 driver->DriverUnload = driver_unload;
830 driver->MajorFunction[IRP_MJ_PNP] = driver_pnp;
831 driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = driver_internal_ioctl;
833 return STATUS_SUCCESS;