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 libusb_device
*libusb_device
;
77 libusb_device_handle
*handle
;
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
;
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
));
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
);
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
);
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
);
169 remove_usb_device(device
);
174 static DWORD CALLBACK
event_thread_proc(void *arg
)
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");
190 static NTSTATUS
fdo_pnp(IRP
*irp
)
192 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
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
;
205 if (stack
->Parameters
.QueryDeviceRelations
.Type
!= BusRelations
)
207 FIXME("Unhandled device relations type %#x.\n", stack
->Parameters
.QueryDeviceRelations
.Type
);
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
;
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
);
230 irp
->IoStatus
.Information
= (ULONG_PTR
)devices
;
231 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
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
;
245 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
248 case IRP_MN_SURPRISE_REMOVAL
:
249 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
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
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
);
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;
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;
347 static NTSTATUS
query_id(const struct usb_device
*device
, IRP
*irp
, BUS_QUERY_ID_TYPE type
)
353 case BusQueryDeviceID
:
354 if ((id
= ExAllocatePool(PagedPool
, 28 * sizeof(WCHAR
))))
355 get_device_id(device
, id
);
358 case BusQueryInstanceID
:
359 if ((id
= ExAllocatePool(PagedPool
, 2 * sizeof(WCHAR
))))
366 case BusQueryHardwareIDs
:
367 if ((id
= ExAllocatePool(PagedPool
, (28 + 37 + 1) * sizeof(WCHAR
))))
368 get_hardware_ids(device
, id
);
371 case BusQueryCompatibleIDs
:
372 if ((id
= ExAllocatePool(PagedPool
, (33 + 25 + 13 + 1) * sizeof(WCHAR
))))
373 get_compatible_ids(device
, id
);
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
)
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
);
413 case IRP_MN_QUERY_CAPABILITIES
:
415 DEVICE_CAPABILITIES
*caps
= stack
->Parameters
.DeviceCapabilities
.Capabilities
;
417 caps
->RawDeviceOK
= 1;
419 ret
= STATUS_SUCCESS
;
423 case IRP_MN_START_DEVICE
:
424 ret
= STATUS_SUCCESS
;
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
;
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
;
451 FIXME("Unhandled minor function %#x.\n", stack
->MinorFunction
);
454 irp
->IoStatus
.Status
= ret
;
455 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
459 static NTSTATUS WINAPI
driver_pnp(DEVICE_OBJECT
*device
, IRP
*irp
)
461 if (device
== bus_fdo
)
463 return pdo_pnp(device
, irp
);
466 static NTSTATUS
usbd_status_from_libusb(enum libusb_transfer_status 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
;
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
;
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
);
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
);
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
);
545 unsigned char endpoint
;
549 static HANDLE
make_pipe_handle(unsigned char endpoint
, USBD_PIPE_TYPE type
)
557 u
.pipe
.endpoint
= endpoint
;
562 static struct pipe
get_pipe(HANDLE handle
)
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
;
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);
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
);
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
);
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
;
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
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
);
736 ERR("Failed to submit vendor-specific interface transfer: %s\n", libusb_strerror(ret
));
738 return STATUS_PENDING
;
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
;
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
);
764 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
765 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
766 return STATUS_DELETE_PENDING
;
771 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
772 status
= usb_submit_urb(device
, irp
);
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
);
788 static NTSTATUS WINAPI
driver_add_device(DRIVER_OBJECT
*driver
, DEVICE_OBJECT
*pdo
)
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
);
800 IoAttachDeviceToDeviceStack(bus_fdo
, pdo
);
802 bus_fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
804 return STATUS_SUCCESS
;
807 static void WINAPI
driver_unload(DRIVER_OBJECT
*driver
)
812 NTSTATUS WINAPI
DriverEntry(DRIVER_OBJECT
*driver
, UNICODE_STRING
*path
)
816 TRACE("driver %p, path %s.\n", driver
, debugstr_w(path
->Buffer
));
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
;