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
27 #define WIN32_NO_STATUS
33 #include "ddk/usbioctl.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,
47 "xchgl (%esp),%ecx\n\t"
50 #define call_fastcall_func1(func,a) wrap_fastcall_func1(func,a)
54 #define call_fastcall_func1(func,a) func(a)
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
);
74 DEVICE_OBJECT
*device_obj
;
76 /* Points to the parent USB device if this is a USB interface; otherwise
78 struct usb_device
*parent
;
79 uint8_t interface_index
;
81 uint8_t class, subclass
, protocol
;
83 libusb_device
*libusb_device
;
84 libusb_device_handle
*handle
;
89 static DRIVER_OBJECT
*driver_obj
;
90 static DEVICE_OBJECT
*bus_fdo
, *bus_pdo
;
92 static libusb_hotplug_callback_handle hotplug_cb_handle
;
94 static void add_usb_interface(struct usb_device
*parent
, const struct libusb_interface_descriptor
*desc
)
96 struct usb_device
*device
;
97 DEVICE_OBJECT
*device_obj
;
100 if ((status
= IoCreateDevice(driver_obj
, sizeof(*device
), NULL
,
101 FILE_DEVICE_USB
, FILE_AUTOGENERATED_DEVICE_NAME
, FALSE
, &device_obj
)))
103 ERR("Failed to create device, status %#x.\n", status
);
107 device
= device_obj
->DeviceExtension
;
108 device
->device_obj
= device_obj
;
109 device
->parent
= parent
;
110 device
->handle
= parent
->handle
;
111 device
->libusb_device
= parent
->libusb_device
;
112 device
->interface_index
= desc
->bInterfaceNumber
;
113 device
->class = desc
->bInterfaceClass
;
114 device
->subclass
= desc
->bInterfaceSubClass
;
115 device
->protocol
= desc
->bInterfaceProtocol
;
116 InitializeListHead(&device
->irp_list
);
118 EnterCriticalSection(&wineusb_cs
);
119 list_add_tail(&device_list
, &device
->entry
);
120 LeaveCriticalSection(&wineusb_cs
);
123 static void add_usb_device(libusb_device
*libusb_device
)
125 static const WCHAR formatW
[] = {'\\','D','e','v','i','c','e','\\','U','S','B','P','D','O','-','%','u',0};
126 struct libusb_config_descriptor
*config_desc
;
127 struct libusb_device_descriptor device_desc
;
128 static unsigned int name_index
;
129 libusb_device_handle
*handle
;
130 struct usb_device
*device
;
131 DEVICE_OBJECT
*device_obj
;
132 UNICODE_STRING string
;
137 libusb_get_device_descriptor(libusb_device
, &device_desc
);
139 TRACE("Adding new device %p, vendor %04x, product %04x.\n", libusb_device
,
140 device_desc
.idVendor
, device_desc
.idProduct
);
142 if ((ret
= libusb_open(libusb_device
, &handle
)))
144 WARN("Failed to open device: %s\n", libusb_strerror(ret
));
148 sprintfW(name
, formatW
, name_index
++);
149 RtlInitUnicodeString(&string
, name
);
150 if ((status
= IoCreateDevice(driver_obj
, sizeof(*device
), &string
,
151 FILE_DEVICE_USB
, 0, FALSE
, &device_obj
)))
153 ERR("Failed to create device, status %#x.\n", status
);
154 libusb_close(handle
);
158 device
= device_obj
->DeviceExtension
;
159 device
->device_obj
= device_obj
;
160 device
->libusb_device
= libusb_ref_device(libusb_device
);
161 device
->handle
= handle
;
162 InitializeListHead(&device
->irp_list
);
164 EnterCriticalSection(&wineusb_cs
);
165 list_add_tail(&device_list
, &device
->entry
);
166 device
->removed
= FALSE
;
167 LeaveCriticalSection(&wineusb_cs
);
169 device
->class = device_desc
.bDeviceClass
;
170 device
->subclass
= device_desc
.bDeviceSubClass
;
171 device
->protocol
= device_desc
.bDeviceProtocol
;
173 if (!(ret
= libusb_get_active_config_descriptor(libusb_device
, &config_desc
)))
175 /* Create new devices for interfaces of composite devices.
177 * On Windows this is the job of usbccgp.sys, a separate driver that
178 * layers on top of the base USB driver. While we could take this
179 * approach as well, implementing usbccgp is a lot more work, whereas
180 * interface support is effectively built into libusb.
182 * FIXME: usbccgp does not create separate interfaces in some cases,
183 * e.g. when there is an interface association descriptor available.
185 if (config_desc
->bNumInterfaces
> 1)
189 for (i
= 0; i
< config_desc
->bNumInterfaces
; ++i
)
191 const struct libusb_interface
*interface
= &config_desc
->interface
[i
];
193 if (interface
->num_altsetting
!= 1)
194 FIXME("Interface %u has %u alternate settings; using the first one.\n",
195 i
, interface
->num_altsetting
);
196 add_usb_interface(device
, &interface
->altsetting
[0]);
199 libusb_free_config_descriptor(config_desc
);
203 ERR("Failed to get configuration descriptor: %s\n", libusb_strerror(ret
));
206 IoInvalidateDeviceRelations(bus_pdo
, BusRelations
);
209 static void remove_usb_device(libusb_device
*libusb_device
)
211 struct usb_device
*device
;
213 TRACE("Removing device %p.\n", libusb_device
);
215 EnterCriticalSection(&wineusb_cs
);
216 LIST_FOR_EACH_ENTRY(device
, &device_list
, struct usb_device
, entry
)
218 if (device
->libusb_device
== libusb_device
)
220 if (!device
->removed
)
222 device
->removed
= TRUE
;
223 list_remove(&device
->entry
);
228 LeaveCriticalSection(&wineusb_cs
);
230 IoInvalidateDeviceRelations(bus_pdo
, BusRelations
);
233 static BOOL thread_shutdown
;
234 static HANDLE event_thread
;
236 static int LIBUSB_CALL
hotplug_cb(libusb_context
*context
, libusb_device
*device
,
237 libusb_hotplug_event event
, void *user_data
)
239 if (event
== LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED
)
240 add_usb_device(device
);
242 remove_usb_device(device
);
247 static DWORD CALLBACK
event_thread_proc(void *arg
)
251 TRACE("Starting event thread.\n");
253 while (!thread_shutdown
)
255 if ((ret
= libusb_handle_events(NULL
)))
256 ERR("Error handling events: %s\n", libusb_strerror(ret
));
259 TRACE("Shutting down event thread.\n");
263 static NTSTATUS
fdo_pnp(IRP
*irp
)
265 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
268 TRACE("irp %p, minor function %#x.\n", irp
, stack
->MinorFunction
);
270 switch (stack
->MinorFunction
)
272 case IRP_MN_QUERY_DEVICE_RELATIONS
:
274 struct usb_device
*device
;
275 DEVICE_RELATIONS
*devices
;
278 if (stack
->Parameters
.QueryDeviceRelations
.Type
!= BusRelations
)
280 FIXME("Unhandled device relations type %#x.\n", stack
->Parameters
.QueryDeviceRelations
.Type
);
284 EnterCriticalSection(&wineusb_cs
);
286 if (!(devices
= ExAllocatePool(PagedPool
,
287 offsetof(DEVICE_RELATIONS
, Objects
[list_count(&device_list
)]))))
289 LeaveCriticalSection(&wineusb_cs
);
290 irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
294 LIST_FOR_EACH_ENTRY(device
, &device_list
, struct usb_device
, entry
)
296 devices
->Objects
[i
++] = device
->device_obj
;
297 call_fastcall_func1(ObfReferenceObject
, device
->device_obj
);
300 LeaveCriticalSection(&wineusb_cs
);
303 irp
->IoStatus
.Information
= (ULONG_PTR
)devices
;
304 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
308 case IRP_MN_START_DEVICE
:
309 if ((ret
= libusb_hotplug_register_callback(NULL
,
310 LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED
| LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT
,
311 LIBUSB_HOTPLUG_ENUMERATE
, LIBUSB_HOTPLUG_MATCH_ANY
, LIBUSB_HOTPLUG_MATCH_ANY
,
312 LIBUSB_HOTPLUG_MATCH_ANY
, hotplug_cb
, NULL
, &hotplug_cb_handle
)))
314 ERR("Failed to register callback: %s\n", libusb_strerror(ret
));
315 irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
318 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
321 case IRP_MN_SURPRISE_REMOVAL
:
322 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
325 case IRP_MN_REMOVE_DEVICE
:
327 struct usb_device
*device
, *cursor
;
329 libusb_hotplug_deregister_callback(NULL
, hotplug_cb_handle
);
330 thread_shutdown
= TRUE
;
331 libusb_interrupt_event_handler(NULL
);
332 WaitForSingleObject(event_thread
, INFINITE
);
333 CloseHandle(event_thread
);
335 EnterCriticalSection(&wineusb_cs
);
336 /* Normally we unlink all devices either:
338 * - as a result of hot-unplug, which unlinks the device, and causes
339 * a subsequent IRP_MN_REMOVE_DEVICE which will free it;
341 * - if the parent is deleted (at shutdown time), in which case
342 * ntoskrnl will send us IRP_MN_SURPRISE_REMOVAL and
343 * IRP_MN_REMOVE_DEVICE unprompted.
345 * But we can get devices hotplugged between when shutdown starts
346 * and now, in which case they'll be stuck in this list and never
349 * FIXME: This is still broken, though. If a device is hotplugged
350 * and then removed, it'll be unlinked and never freed. */
351 LIST_FOR_EACH_ENTRY_SAFE(device
, cursor
, &device_list
, struct usb_device
, entry
)
353 assert(!device
->removed
);
356 libusb_unref_device(device
->libusb_device
);
357 libusb_close(device
->handle
);
359 list_remove(&device
->entry
);
360 IoDeleteDevice(device
->device_obj
);
362 LeaveCriticalSection(&wineusb_cs
);
364 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
365 IoSkipCurrentIrpStackLocation(irp
);
366 ret
= IoCallDriver(bus_pdo
, irp
);
367 IoDetachDevice(bus_pdo
);
368 IoDeleteDevice(bus_fdo
);
373 FIXME("Unhandled minor function %#x.\n", stack
->MinorFunction
);
376 IoSkipCurrentIrpStackLocation(irp
);
377 return IoCallDriver(bus_pdo
, irp
);
386 static void WINAPIV
append_id(struct string_buffer
*buffer
, const WCHAR
*format
, ...)
392 __ms_va_start(args
, format
);
394 len
= _vsnwprintf(NULL
, 0, format
, args
) + 1;
395 if (!(string
= ExAllocatePool(PagedPool
, (buffer
->len
+ len
) * sizeof(WCHAR
))))
398 ExFreePool(buffer
->string
);
399 buffer
->string
= NULL
;
404 memcpy(string
, buffer
->string
, buffer
->len
* sizeof(WCHAR
));
405 ExFreePool(buffer
->string
);
407 _vsnwprintf(string
+ buffer
->len
, len
, format
, args
);
408 buffer
->string
= string
;
414 static const WCHAR emptyW
[] = {0};
416 static void get_device_id(const struct usb_device
*device
, struct string_buffer
*buffer
)
418 static const WCHAR interface_formatW
[] = {'U','S','B','\\','V','I','D','_','%','0','4','X',
419 '&','P','I','D','_','%','0','4','X','&','M','I','_','%','0','2','X',0};
420 static const WCHAR formatW
[] = {'U','S','B','\\','V','I','D','_','%','0','4','X',
421 '&','P','I','D','_','%','0','4','X',0};
422 struct libusb_device_descriptor desc
;
424 libusb_get_device_descriptor(device
->libusb_device
, &desc
);
426 append_id(buffer
, interface_formatW
, desc
.idVendor
, desc
.idProduct
, device
->interface_index
);
428 append_id(buffer
, formatW
, desc
.idVendor
, desc
.idProduct
);
431 static void get_hardware_ids(const struct usb_device
*device
, struct string_buffer
*buffer
)
433 static const WCHAR interface_formatW
[] = {'U','S','B','\\','V','I','D','_','%','0','4','X',
434 '&','P','I','D','_','%','0','4','X','&','R','E','V','_','%','0','4','X','&','M','I','_','%','0','2','X',0};
435 static const WCHAR formatW
[] = {'U','S','B','\\','V','I','D','_','%','0','4','X',
436 '&','P','I','D','_','%','0','4','X','&','R','E','V','_','%','0','4','X',0};
437 struct libusb_device_descriptor desc
;
439 libusb_get_device_descriptor(device
->libusb_device
, &desc
);
442 append_id(buffer
, interface_formatW
, desc
.idVendor
, desc
.idProduct
, desc
.bcdDevice
, device
->interface_index
);
444 append_id(buffer
, formatW
, desc
.idVendor
, desc
.idProduct
, desc
.bcdDevice
);
445 get_device_id(device
, buffer
);
446 append_id(buffer
, emptyW
);
449 static void get_compatible_ids(const struct usb_device
*device
, struct string_buffer
*buffer
)
451 static const WCHAR prot_format
[] = {'U','S','B','\\','C','l','a','s','s','_','%','0','2','x',
452 '&','S','u','b','C','l','a','s','s','_','%','0','2','x',
453 '&','P','r','o','t','_','%','0','2','x',0};
454 static const WCHAR subclass_format
[] = {'U','S','B','\\','C','l','a','s','s','_','%','0','2','x',
455 '&','S','u','b','C','l','a','s','s','_','%','0','2','x',0};
456 static const WCHAR class_format
[] = {'U','S','B','\\','C','l','a','s','s','_','%','0','2','x',0};
458 append_id(buffer
, prot_format
, device
->class, device
->subclass
, device
->protocol
);
459 append_id(buffer
, subclass_format
, device
->class, device
->subclass
);
460 append_id(buffer
, class_format
, device
->class);
461 append_id(buffer
, emptyW
);
464 static NTSTATUS
query_id(struct usb_device
*device
, IRP
*irp
, BUS_QUERY_ID_TYPE type
)
466 static const WCHAR instance_idW
[] = {'0',0};
467 struct string_buffer buffer
= {0};
469 TRACE("type %#x.\n", type
);
473 case BusQueryDeviceID
:
474 get_device_id(device
, &buffer
);
477 case BusQueryInstanceID
:
478 append_id(&buffer
, instance_idW
);
481 case BusQueryHardwareIDs
:
482 get_hardware_ids(device
, &buffer
);
485 case BusQueryCompatibleIDs
:
486 get_compatible_ids(device
, &buffer
);
490 FIXME("Unhandled ID query type %#x.\n", type
);
491 return irp
->IoStatus
.Status
;
495 return STATUS_NO_MEMORY
;
497 irp
->IoStatus
.Information
= (ULONG_PTR
)buffer
.string
;
498 return STATUS_SUCCESS
;
501 static void remove_pending_irps(struct usb_device
*device
)
506 while ((entry
= RemoveHeadList(&device
->irp_list
)) != &device
->irp_list
)
508 irp
= CONTAINING_RECORD(entry
, IRP
, Tail
.Overlay
.ListEntry
);
509 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
510 irp
->IoStatus
.Information
= 0;
511 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
515 static NTSTATUS
pdo_pnp(DEVICE_OBJECT
*device_obj
, IRP
*irp
)
517 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
518 struct usb_device
*device
= device_obj
->DeviceExtension
;
519 NTSTATUS ret
= irp
->IoStatus
.Status
;
521 TRACE("device_obj %p, irp %p, minor function %#x.\n", device_obj
, irp
, stack
->MinorFunction
);
523 switch (stack
->MinorFunction
)
525 case IRP_MN_QUERY_ID
:
526 ret
= query_id(device
, irp
, stack
->Parameters
.QueryId
.IdType
);
529 case IRP_MN_QUERY_CAPABILITIES
:
531 DEVICE_CAPABILITIES
*caps
= stack
->Parameters
.DeviceCapabilities
.Capabilities
;
533 caps
->RawDeviceOK
= 1;
535 ret
= STATUS_SUCCESS
;
539 case IRP_MN_START_DEVICE
:
540 ret
= STATUS_SUCCESS
;
543 case IRP_MN_SURPRISE_REMOVAL
:
544 EnterCriticalSection(&wineusb_cs
);
545 remove_pending_irps(device
);
546 if (!device
->removed
)
548 device
->removed
= TRUE
;
549 list_remove(&device
->entry
);
551 LeaveCriticalSection(&wineusb_cs
);
552 ret
= STATUS_SUCCESS
;
555 case IRP_MN_REMOVE_DEVICE
:
556 assert(device
->removed
);
557 remove_pending_irps(device
);
561 libusb_unref_device(device
->libusb_device
);
562 libusb_close(device
->handle
);
565 IoDeleteDevice(device
->device_obj
);
566 ret
= STATUS_SUCCESS
;
570 FIXME("Unhandled minor function %#x.\n", stack
->MinorFunction
);
573 irp
->IoStatus
.Status
= ret
;
574 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
578 static NTSTATUS WINAPI
driver_pnp(DEVICE_OBJECT
*device
, IRP
*irp
)
580 if (device
== bus_fdo
)
582 return pdo_pnp(device
, irp
);
585 static NTSTATUS
usbd_status_from_libusb(enum libusb_transfer_status status
)
589 case LIBUSB_TRANSFER_CANCELLED
:
590 return USBD_STATUS_CANCELED
;
591 case LIBUSB_TRANSFER_COMPLETED
:
592 return USBD_STATUS_SUCCESS
;
593 case LIBUSB_TRANSFER_NO_DEVICE
:
594 return USBD_STATUS_DEVICE_GONE
;
595 case LIBUSB_TRANSFER_STALL
:
596 return USBD_STATUS_ENDPOINT_HALTED
;
597 case LIBUSB_TRANSFER_TIMED_OUT
:
598 return USBD_STATUS_TIMEOUT
;
600 FIXME("Unhandled status %#x.\n", status
);
601 case LIBUSB_TRANSFER_ERROR
:
602 return USBD_STATUS_REQUEST_FAILED
;
606 static void LIBUSB_CALL
transfer_cb(struct libusb_transfer
*transfer
)
608 IRP
*irp
= transfer
->user_data
;
609 URB
*urb
= IoGetCurrentIrpStackLocation(irp
)->Parameters
.Others
.Argument1
;
611 TRACE("Completing IRP %p, status %#x.\n", irp
, transfer
->status
);
613 urb
->UrbHeader
.Status
= usbd_status_from_libusb(transfer
->status
);
615 if (transfer
->status
== LIBUSB_TRANSFER_COMPLETED
)
617 switch (urb
->UrbHeader
.Function
)
619 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
620 urb
->UrbBulkOrInterruptTransfer
.TransferBufferLength
= transfer
->actual_length
;
623 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
625 struct _URB_CONTROL_DESCRIPTOR_REQUEST
*req
= &urb
->UrbControlDescriptorRequest
;
626 req
->TransferBufferLength
= transfer
->actual_length
;
627 memcpy(req
->TransferBuffer
, libusb_control_transfer_get_data(transfer
), transfer
->actual_length
);
631 case URB_FUNCTION_VENDOR_INTERFACE
:
633 struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
*req
= &urb
->UrbControlVendorClassRequest
;
634 req
->TransferBufferLength
= transfer
->actual_length
;
635 if (req
->TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
636 memcpy(req
->TransferBuffer
, libusb_control_transfer_get_data(transfer
), transfer
->actual_length
);
641 ERR("Unexpected function %#x.\n", urb
->UrbHeader
.Function
);
645 EnterCriticalSection(&wineusb_cs
);
646 RemoveEntryList(&irp
->Tail
.Overlay
.ListEntry
);
647 LeaveCriticalSection(&wineusb_cs
);
649 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
650 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
653 static void queue_irp(struct usb_device
*device
, IRP
*irp
, struct libusb_transfer
*transfer
)
655 IoMarkIrpPending(irp
);
656 irp
->Tail
.Overlay
.DriverContext
[0] = transfer
;
657 EnterCriticalSection(&wineusb_cs
);
658 InsertTailList(&device
->irp_list
, &irp
->Tail
.Overlay
.ListEntry
);
659 LeaveCriticalSection(&wineusb_cs
);
664 unsigned char endpoint
;
668 static HANDLE
make_pipe_handle(unsigned char endpoint
, USBD_PIPE_TYPE type
)
676 u
.pipe
.endpoint
= endpoint
;
681 static struct pipe
get_pipe(HANDLE handle
)
693 static NTSTATUS
usb_submit_urb(struct usb_device
*device
, IRP
*irp
)
695 URB
*urb
= IoGetCurrentIrpStackLocation(irp
)->Parameters
.Others
.Argument1
;
696 struct libusb_transfer
*transfer
;
699 TRACE("type %#x.\n", urb
->UrbHeader
.Function
);
701 switch (urb
->UrbHeader
.Function
)
703 case URB_FUNCTION_ABORT_PIPE
:
705 LIST_ENTRY
*entry
, *mark
;
707 /* The documentation states that URB_FUNCTION_ABORT_PIPE may
708 * complete before outstanding requests complete, so we don't need
709 * to wait for them. */
710 EnterCriticalSection(&wineusb_cs
);
711 mark
= &device
->irp_list
;
712 for (entry
= mark
->Flink
; entry
!= mark
; entry
= entry
->Flink
)
714 IRP
*queued_irp
= CONTAINING_RECORD(entry
, IRP
, Tail
.Overlay
.ListEntry
);
716 if ((ret
= libusb_cancel_transfer(queued_irp
->Tail
.Overlay
.DriverContext
[0])) < 0)
717 ERR("Failed to cancel transfer: %s\n", libusb_strerror(ret
));
719 LeaveCriticalSection(&wineusb_cs
);
721 return STATUS_SUCCESS
;
724 case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
:
726 struct _URB_PIPE_REQUEST
*req
= &urb
->UrbPipeRequest
;
727 struct pipe pipe
= get_pipe(req
->PipeHandle
);
729 if ((ret
= libusb_clear_halt(device
->handle
, pipe
.endpoint
)) < 0)
730 ERR("Failed to clear halt: %s\n", libusb_strerror(ret
));
732 return STATUS_SUCCESS
;
735 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
:
737 struct _URB_BULK_OR_INTERRUPT_TRANSFER
*req
= &urb
->UrbBulkOrInterruptTransfer
;
738 struct pipe pipe
= get_pipe(req
->PipeHandle
);
740 if (req
->TransferBufferMDL
)
741 FIXME("Unhandled MDL output buffer.\n");
743 if (!(transfer
= libusb_alloc_transfer(0)))
744 return STATUS_NO_MEMORY
;
746 if (pipe
.type
== UsbdPipeTypeBulk
)
748 libusb_fill_bulk_transfer(transfer
, device
->handle
, pipe
.endpoint
,
749 req
->TransferBuffer
, req
->TransferBufferLength
, transfer_cb
, irp
, 0);
751 else if (pipe
.type
== UsbdPipeTypeInterrupt
)
753 libusb_fill_interrupt_transfer(transfer
, device
->handle
, pipe
.endpoint
,
754 req
->TransferBuffer
, req
->TransferBufferLength
, transfer_cb
, irp
, 0);
758 WARN("Invalid pipe type %#x.\n", pipe
.type
);
759 libusb_free_transfer(transfer
);
760 return USBD_STATUS_INVALID_PIPE_HANDLE
;
763 queue_irp(device
, irp
, transfer
);
764 transfer
->flags
= LIBUSB_TRANSFER_FREE_TRANSFER
;
765 ret
= libusb_submit_transfer(transfer
);
767 ERR("Failed to submit bulk transfer: %s\n", libusb_strerror(ret
));
769 return STATUS_PENDING
;
772 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
:
774 struct _URB_CONTROL_DESCRIPTOR_REQUEST
*req
= &urb
->UrbControlDescriptorRequest
;
775 unsigned char *buffer
;
777 if (req
->TransferBufferMDL
)
778 FIXME("Unhandled MDL output buffer.\n");
780 if (!(transfer
= libusb_alloc_transfer(0)))
781 return STATUS_NO_MEMORY
;
783 if (!(buffer
= malloc(sizeof(struct libusb_control_setup
) + req
->TransferBufferLength
)))
785 libusb_free_transfer(transfer
);
786 return STATUS_NO_MEMORY
;
789 queue_irp(device
, irp
, transfer
);
790 libusb_fill_control_setup(buffer
,
791 LIBUSB_ENDPOINT_IN
| LIBUSB_REQUEST_TYPE_STANDARD
| LIBUSB_RECIPIENT_DEVICE
,
792 LIBUSB_REQUEST_GET_DESCRIPTOR
, (req
->DescriptorType
<< 8) | req
->Index
,
793 req
->LanguageId
, req
->TransferBufferLength
);
794 libusb_fill_control_transfer(transfer
, device
->handle
, buffer
, transfer_cb
, irp
, 0);
795 transfer
->flags
= LIBUSB_TRANSFER_FREE_BUFFER
| LIBUSB_TRANSFER_FREE_TRANSFER
;
796 ret
= libusb_submit_transfer(transfer
);
798 ERR("Failed to submit GET_DESCRIPTOR transfer: %s\n", libusb_strerror(ret
));
800 return STATUS_PENDING
;
803 case URB_FUNCTION_SELECT_CONFIGURATION
:
805 struct _URB_SELECT_CONFIGURATION
*req
= &urb
->UrbSelectConfiguration
;
808 /* FIXME: In theory, we'd call libusb_set_configuration() here, but
809 * the CASIO FX-9750GII (which has only one configuration) goes into
810 * an error state if it receives a SET_CONFIGURATION request. Maybe
811 * we should skip setting that if and only if the configuration is
814 for (i
= 0; i
< req
->Interface
.NumberOfPipes
; ++i
)
816 USBD_PIPE_INFORMATION
*pipe
= &req
->Interface
.Pipes
[i
];
817 pipe
->PipeHandle
= make_pipe_handle(pipe
->EndpointAddress
, pipe
->PipeType
);
820 return STATUS_SUCCESS
;
823 case URB_FUNCTION_VENDOR_INTERFACE
:
825 struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
*req
= &urb
->UrbControlVendorClassRequest
;
826 uint8_t req_type
= LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_INTERFACE
;
827 unsigned char *buffer
;
829 if (req
->TransferFlags
& USBD_TRANSFER_DIRECTION_IN
)
830 req_type
|= LIBUSB_ENDPOINT_IN
;
831 if (req
->TransferFlags
& ~USBD_TRANSFER_DIRECTION_IN
)
832 FIXME("Unhandled flags %#x.\n", req
->TransferFlags
);
834 if (req
->TransferBufferMDL
)
835 FIXME("Unhandled MDL output buffer.\n");
837 if (!(transfer
= libusb_alloc_transfer(0)))
838 return STATUS_NO_MEMORY
;
840 if (!(buffer
= malloc(sizeof(struct libusb_control_setup
) + req
->TransferBufferLength
)))
842 libusb_free_transfer(transfer
);
843 return STATUS_NO_MEMORY
;
846 queue_irp(device
, irp
, transfer
);
847 libusb_fill_control_setup(buffer
, req_type
, req
->Request
,
848 req
->Value
, req
->Index
, req
->TransferBufferLength
);
849 if (!(req
->TransferFlags
& USBD_TRANSFER_DIRECTION_IN
))
850 memcpy(buffer
+ LIBUSB_CONTROL_SETUP_SIZE
, req
->TransferBuffer
, req
->TransferBufferLength
);
851 libusb_fill_control_transfer(transfer
, device
->handle
, buffer
, transfer_cb
, irp
, 0);
852 transfer
->flags
= LIBUSB_TRANSFER_FREE_BUFFER
| LIBUSB_TRANSFER_FREE_TRANSFER
;
853 ret
= libusb_submit_transfer(transfer
);
855 ERR("Failed to submit vendor-specific interface transfer: %s\n", libusb_strerror(ret
));
857 return STATUS_PENDING
;
861 FIXME("Unhandled function %#x.\n", urb
->UrbHeader
.Function
);
864 return STATUS_NOT_IMPLEMENTED
;
867 static NTSTATUS WINAPI
driver_internal_ioctl(DEVICE_OBJECT
*device_obj
, IRP
*irp
)
869 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
870 ULONG code
= stack
->Parameters
.DeviceIoControl
.IoControlCode
;
871 struct usb_device
*device
= device_obj
->DeviceExtension
;
872 NTSTATUS status
= STATUS_NOT_IMPLEMENTED
;
875 TRACE("device_obj %p, irp %p, code %#x.\n", device_obj
, irp
, code
);
877 EnterCriticalSection(&wineusb_cs
);
878 removed
= device
->removed
;
879 LeaveCriticalSection(&wineusb_cs
);
883 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
884 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
885 return STATUS_DELETE_PENDING
;
890 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
891 status
= usb_submit_urb(device
, irp
);
895 FIXME("Unhandled ioctl %#x (device %#x, access %#x, function %#x, method %#x).\n",
896 code
, code
>> 16, (code
>> 14) & 3, (code
>> 2) & 0xfff, code
& 3);
899 if (status
!= STATUS_PENDING
)
901 irp
->IoStatus
.Status
= status
;
902 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
907 static NTSTATUS WINAPI
driver_add_device(DRIVER_OBJECT
*driver
, DEVICE_OBJECT
*pdo
)
911 TRACE("driver %p, pdo %p.\n", driver
, pdo
);
913 if ((ret
= IoCreateDevice(driver
, 0, NULL
, FILE_DEVICE_BUS_EXTENDER
, 0, FALSE
, &bus_fdo
)))
915 ERR("Failed to create FDO, status %#x.\n", ret
);
919 IoAttachDeviceToDeviceStack(bus_fdo
, pdo
);
921 bus_fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
923 return STATUS_SUCCESS
;
926 static void WINAPI
driver_unload(DRIVER_OBJECT
*driver
)
931 NTSTATUS WINAPI
DriverEntry(DRIVER_OBJECT
*driver
, UNICODE_STRING
*path
)
935 TRACE("driver %p, path %s.\n", driver
, debugstr_w(path
->Buffer
));
939 if ((err
= libusb_init(NULL
)))
941 ERR("Failed to initialize libusb: %s\n", libusb_strerror(err
));
942 return STATUS_UNSUCCESSFUL
;
945 event_thread
= CreateThread(NULL
, 0, event_thread_proc
, NULL
, 0, NULL
);
947 driver
->DriverExtension
->AddDevice
= driver_add_device
;
948 driver
->DriverUnload
= driver_unload
;
949 driver
->MajorFunction
[IRP_MJ_PNP
] = driver_pnp
;
950 driver
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = driver_internal_ioctl
;
952 return STATUS_SUCCESS
;