wine  6.0.1
About: Wine is an Open Source implementation of the MS Windows API on top of X, OpenGL, and Unix. Think of Wine as a compatibility layer for running Windows programs.
  Fossies Dox: wine-6.0.1.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

wineusb.c
Go to the documentation of this file.
1 /*
2  * USB root device enumerator using libusb
3  *
4  * Copyright 2020 Zebediah Figura
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <libusb.h>
25 
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"
38 
40 
41 #if defined(__i386__) && !defined(_WIN32)
42 
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" );
49 
50 #define call_fastcall_func1(func,a) wrap_fastcall_func1(func,a)
51 
52 #else
53 
54 #define call_fastcall_func1(func,a) func(a)
55 
56 #endif
57 
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 };
64 
66 
67 static struct list device_list = LIST_INIT(device_list);
68 
69 struct usb_device
70 {
71  struct list entry;
73 
75 
77  libusb_device_handle *handle;
78 
80 };
81 
84 
85 static libusb_hotplug_callback_handle hotplug_cb_handle;
86 
87 static void add_usb_device(libusb_device *libusb_device)
88 {
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;
97  WCHAR name[20];
98  int ret;
99 
100  libusb_get_device_descriptor(libusb_device, &device_desc);
101 
102  TRACE("Adding new device %p, vendor %04x, product %04x.\n", libusb_device,
103  device_desc.idVendor, device_desc.idProduct);
104 
105  if ((ret = libusb_open(libusb_device, &handle)))
106  {
107  WARN("Failed to open device: %s\n", libusb_strerror(ret));
108  return;
109  }
110 
111  sprintfW(name, formatW, name_index++);
112  RtlInitUnicodeString(&string, name);
113  if ((status = IoCreateDevice(driver_obj, sizeof(*device), &string,
115  {
116  ERR("Failed to create device, status %#x.\n", status);
118  libusb_close(handle);
119  return;
120  }
121 
123  device->device_obj = device_obj;
124  device->libusb_device = libusb_ref_device(libusb_device);
125  device->handle = handle;
126  InitializeListHead(&device->irp_list);
127 
130  device->removed = FALSE;
132 
134 }
135 
137 {
138  struct usb_device *device;
139 
140  TRACE("Removing device %p.\n", libusb_device);
141 
144  {
145  if (device->libusb_device == libusb_device)
146  {
148  device->removed = TRUE;
149  break;
150  }
151  }
153 
155 }
156 
159 
160 static int LIBUSB_CALL hotplug_cb(libusb_context *context, libusb_device *device,
161  libusb_hotplug_event event, void *user_data)
162 {
163  if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)
165  else
167 
168  return 0;
169 }
170 
172 {
173  int ret;
174 
175  TRACE("Starting event thread.\n");
176 
177  while (!thread_shutdown)
178  {
179  if ((ret = libusb_handle_events(NULL)))
180  ERR("Error handling events: %s\n", libusb_strerror(ret));
181  }
182 
183  TRACE("Shutting down event thread.\n");
184  return 0;
185 }
186 
187 static NTSTATUS fdo_pnp(IRP *irp)
188 {
190  NTSTATUS ret;
191 
192  TRACE("irp %p, minor function %#x.\n", irp, stack->MinorFunction);
193 
194  switch (stack->MinorFunction)
195  {
197  {
198  struct usb_device *device;
200  unsigned int i = 0;
201 
202  if (stack->Parameters.QueryDeviceRelations.Type != BusRelations)
203  {
204  FIXME("Unhandled device relations type %#x.\n", stack->Parameters.QueryDeviceRelations.Type);
205  break;
206  }
207 
209 
212  {
215  break;
216  }
217 
219  {
220  devices->Objects[i++] = device->device_obj;
222  }
223 
225 
226  devices->Count = i;
229  break;
230  }
231 
232  case IRP_MN_START_DEVICE:
233  if ((ret = libusb_hotplug_register_callback(NULL,
234  LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
235  LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
236  LIBUSB_HOTPLUG_MATCH_ANY, hotplug_cb, NULL, &hotplug_cb_handle)))
237  {
238  ERR("Failed to register callback: %s\n", libusb_strerror(ret));
240  break;
241  }
243  break;
244 
247  break;
248 
250  {
251  struct usb_device *device, *cursor;
252 
253  libusb_hotplug_deregister_callback(NULL, hotplug_cb_handle);
255  libusb_interrupt_event_handler(NULL);
258 
261  {
262  libusb_unref_device(device->libusb_device);
263  libusb_close(device->handle);
265  IoDeleteDevice(device->device_obj);
266  }
268 
271  ret = IoCallDriver(bus_pdo, irp);
274  return ret;
275  }
276 
277  default:
278  FIXME("Unhandled minor function %#x.\n", stack->MinorFunction);
279  }
280 
282  return IoCallDriver(bus_pdo, irp);
283 }
284 
285 static void get_device_id(const struct usb_device *device, WCHAR *buffer)
286 {
287  static const WCHAR formatW[] = {'U','S','B','\\','V','I','D','_','%','0','4','X',
288  '&','P','I','D','_','%','0','4','X',0};
289  struct libusb_device_descriptor desc;
290 
291  libusb_get_device_descriptor(device->libusb_device, &desc);
292  sprintfW(buffer, formatW, desc.idVendor, desc.idProduct);
293 }
294 
295 static void get_hardware_ids(const struct usb_device *device, WCHAR *buffer)
296 {
297  static const WCHAR formatW[] = {'U','S','B','\\','V','I','D','_','%','0','4','X',
298  '&','P','I','D','_','%','0','4','X','&','R','E','V','_','%','0','4','X',0};
299  struct libusb_device_descriptor desc;
300 
301  libusb_get_device_descriptor(device->libusb_device, &desc);
302  buffer += sprintfW(buffer, formatW, desc.idVendor, desc.idProduct, desc.bcdDevice) + 1;
304  buffer += strlenW(buffer) + 1;
305  *buffer = 0;
306 }
307 
308 static void get_compatible_ids(const struct usb_device *device, WCHAR *buffer)
309 {
310  static const WCHAR prot_format[] = {'U','S','B','\\','C','l','a','s','s','_','%','0','2','x',
311  '&','S','u','b','C','l','a','s','s','_','%','0','2','x',
312  '&','P','r','o','t','_','%','0','2','x',0};
313  static const WCHAR subclass_format[] = {'U','S','B','\\','C','l','a','s','s','_','%','0','2','x',
314  '&','S','u','b','C','l','a','s','s','_','%','0','2','x',0};
315  static const WCHAR class_format[] = {'U','S','B','\\','C','l','a','s','s','_','%','0','2','x',0};
316 
317  struct libusb_device_descriptor device_desc;
318 
319  libusb_get_device_descriptor(device->libusb_device, &device_desc);
320 
321  buffer += sprintfW(buffer, prot_format, device_desc.bDeviceClass, device_desc.bDeviceSubClass,
322  device_desc.bDeviceProtocol) + 1;
323  buffer += sprintfW(buffer, subclass_format, device_desc.bDeviceClass, device_desc.bDeviceSubClass) + 1;
324  buffer += sprintfW(buffer, class_format, device_desc.bDeviceClass) + 1;
325  *buffer = 0;
326 }
327 
329 {
330  WCHAR *id = NULL;
331 
332  switch (type)
333  {
334  case BusQueryDeviceID:
335  if ((id = ExAllocatePool(PagedPool, 28 * sizeof(WCHAR))))
336  get_device_id(device, id);
337  break;
338 
339  case BusQueryInstanceID:
340  if ((id = ExAllocatePool(PagedPool, 2 * sizeof(WCHAR))))
341  {
342  id[0] = '0';
343  id[1] = 0;
344  }
345  break;
346 
347  case BusQueryHardwareIDs:
348  if ((id = ExAllocatePool(PagedPool, (28 + 37 + 1) * sizeof(WCHAR))))
350  break;
351 
353  if ((id = ExAllocatePool(PagedPool, (33 + 25 + 13 + 1) * sizeof(WCHAR))))
355  break;
356 
357  default:
358  FIXME("Unhandled ID query type %#x.\n", type);
359  return irp->IoStatus.Status;
360  }
361 
362  irp->IoStatus.Information = (ULONG_PTR)id;
363  return STATUS_SUCCESS;
364 }
365 
367 {
370  NTSTATUS ret = irp->IoStatus.Status;
371 
372  TRACE("device_obj %p, irp %p, minor function %#x.\n", device_obj, irp, stack->MinorFunction);
373 
374  switch (stack->MinorFunction)
375  {
376  case IRP_MN_QUERY_ID:
377  ret = query_id(device, irp, stack->Parameters.QueryId.IdType);
378  break;
379 
380  case IRP_MN_START_DEVICE:
383  ret = STATUS_SUCCESS;
384  break;
385 
387  {
388  LIST_ENTRY *entry;
389 
391  while ((entry = RemoveHeadList(&device->irp_list)) != &device->irp_list)
392  {
395  irp->IoStatus.Information = 0;
397  }
399 
400  if (device->removed)
401  {
402  libusb_unref_device(device->libusb_device);
403  libusb_close(device->handle);
404 
407  IoDeleteDevice(device->device_obj);
408  return STATUS_SUCCESS;
409  }
410 
411  ret = STATUS_SUCCESS;
412  break;
413  }
414 
415  default:
416  FIXME("Unhandled minor function %#x.\n", stack->MinorFunction);
417  }
418 
419  irp->IoStatus.Status = ret;
421  return ret;
422 }
423 
425 {
426  if (device == bus_fdo)
427  return fdo_pnp(irp);
428  return pdo_pnp(device, irp);
429 }
430 
431 static NTSTATUS usbd_status_from_libusb(enum libusb_transfer_status status)
432 {
433  switch (status)
434  {
435  case LIBUSB_TRANSFER_CANCELLED:
436  return USBD_STATUS_CANCELED;
437  case LIBUSB_TRANSFER_COMPLETED:
438  return USBD_STATUS_SUCCESS;
439  case LIBUSB_TRANSFER_NO_DEVICE:
441  case LIBUSB_TRANSFER_STALL:
443  case LIBUSB_TRANSFER_TIMED_OUT:
444  return USBD_STATUS_TIMEOUT;
445  default:
446  FIXME("Unhandled status %#x.\n", status);
447  case LIBUSB_TRANSFER_ERROR:
449  }
450 }
451 
452 static void transfer_cb(struct libusb_transfer *transfer)
453 {
454  IRP *irp = transfer->user_data;
455  URB *urb = IoGetCurrentIrpStackLocation(irp)->Parameters.Others.Argument1;
456 
457  TRACE("Completing IRP %p, status %#x.\n", irp, transfer->status);
458 
459  urb->UrbHeader.Status = usbd_status_from_libusb(transfer->status);
460 
461  if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
462  {
463  switch (urb->UrbHeader.Function)
464  {
466  urb->UrbBulkOrInterruptTransfer.TransferBufferLength = transfer->actual_length;
467  break;
468 
470  {
472  req->TransferBufferLength = transfer->actual_length;
473  memcpy(req->TransferBuffer, libusb_control_transfer_get_data(transfer), transfer->actual_length);
474  break;
475  }
476 
478  {
480  req->TransferBufferLength = transfer->actual_length;
482  memcpy(req->TransferBuffer, libusb_control_transfer_get_data(transfer), transfer->actual_length);
483  break;
484  }
485 
486  default:
487  ERR("Unexpected function %#x.\n", urb->UrbHeader.Function);
488  }
489  }
490 
494 
497 }
498 
499 static void queue_irp(struct usb_device *device, IRP *irp, struct libusb_transfer *transfer)
500 {
501  IoMarkIrpPending(irp);
502  irp->Tail.Overlay.DriverContext[0] = transfer;
504  InsertTailList(&device->irp_list, &irp->Tail.Overlay.ListEntry);
506 }
507 
508 struct pipe
509 {
510  unsigned char endpoint;
511  unsigned char type;
512 };
513 
514 static HANDLE make_pipe_handle(unsigned char endpoint, USBD_PIPE_TYPE type)
515 {
516  union
517  {
518  struct pipe pipe;
519  HANDLE handle;
520  } u;
521 
522  u.pipe.endpoint = endpoint;
523  u.pipe.type = type;
524  return u.handle;
525 }
526 
527 static struct pipe get_pipe(HANDLE handle)
528 {
529  union
530  {
531  struct pipe pipe;
532  HANDLE handle;
533  } u;
534 
535  u.handle = handle;
536  return u.pipe;
537 }
538 
540 {
541  URB *urb = IoGetCurrentIrpStackLocation(irp)->Parameters.Others.Argument1;
542  struct libusb_transfer *transfer;
543  int ret;
544 
545  TRACE("type %#x.\n", urb->UrbHeader.Function);
546 
547  switch (urb->UrbHeader.Function)
548  {
550  {
551  LIST_ENTRY *entry, *mark;
552 
553  /* The documentation states that URB_FUNCTION_ABORT_PIPE may
554  * complete before outstanding requests complete, so we don't need
555  * to wait for them. */
557  mark = &device->irp_list;
558  for (entry = mark->Flink; entry != mark; entry = entry->Flink)
559  {
560  IRP *queued_irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
561 
562  if ((ret = libusb_cancel_transfer(queued_irp->Tail.Overlay.DriverContext[0])) < 0)
563  ERR("Failed to cancel transfer: %s\n", libusb_strerror(ret));
564  }
566 
567  return STATUS_SUCCESS;
568  }
569 
571  {
572  struct _URB_PIPE_REQUEST *req = &urb->UrbPipeRequest;
573  struct pipe pipe = get_pipe(req->PipeHandle);
574 
575  if ((ret = libusb_clear_halt(device->handle, pipe.endpoint)) < 0)
576  ERR("Failed to clear halt: %s\n", libusb_strerror(ret));
577 
578  return STATUS_SUCCESS;
579  }
580 
582  {
584  struct pipe pipe = get_pipe(req->PipeHandle);
585 
586  if (req->TransferBufferMDL)
587  FIXME("Unhandled MDL output buffer.\n");
588 
589  if (!(transfer = libusb_alloc_transfer(0)))
590  return STATUS_NO_MEMORY;
591 
592  if (pipe.type == UsbdPipeTypeBulk)
593  {
594  libusb_fill_bulk_transfer(transfer, device->handle, pipe.endpoint,
595  req->TransferBuffer, req->TransferBufferLength, transfer_cb, irp, 0);
596  }
597  else if (pipe.type == UsbdPipeTypeInterrupt)
598  {
599  libusb_fill_interrupt_transfer(transfer, device->handle, pipe.endpoint,
600  req->TransferBuffer, req->TransferBufferLength, transfer_cb, irp, 0);
601  }
602  else
603  {
604  WARN("Invalid pipe type %#x.\n", pipe.type);
605  libusb_free_transfer(transfer);
607  }
608 
609  queue_irp(device, irp, transfer);
610  transfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER;
611  ret = libusb_submit_transfer(transfer);
612  if (ret < 0)
613  ERR("Failed to submit bulk transfer: %s\n", libusb_strerror(ret));
614 
615  return STATUS_PENDING;
616  }
617 
619  {
621  unsigned char *buffer;
622 
623  if (req->TransferBufferMDL)
624  FIXME("Unhandled MDL output buffer.\n");
625 
626  if (!(transfer = libusb_alloc_transfer(0)))
627  return STATUS_NO_MEMORY;
628 
629  if (!(buffer = malloc(sizeof(struct libusb_control_setup) + req->TransferBufferLength)))
630  {
631  libusb_free_transfer(transfer);
632  return STATUS_NO_MEMORY;
633  }
634 
635  queue_irp(device, irp, transfer);
636  libusb_fill_control_setup(buffer,
637  LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
638  LIBUSB_REQUEST_GET_DESCRIPTOR, (req->DescriptorType << 8) | req->Index,
639  req->LanguageId, req->TransferBufferLength);
640  libusb_fill_control_transfer(transfer, device->handle, buffer, transfer_cb, irp, 0);
641  transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
642  ret = libusb_submit_transfer(transfer);
643  if (ret < 0)
644  ERR("Failed to submit GET_DESCRIPTOR transfer: %s\n", libusb_strerror(ret));
645 
646  return STATUS_PENDING;
647  }
648 
650  {
652  ULONG i;
653 
654  /* FIXME: In theory, we'd call libusb_set_configuration() here, but
655  * the CASIO FX-9750GII (which has only one configuration) goes into
656  * an error state if it receives a SET_CONFIGURATION request. Maybe
657  * we should skip setting that if and only if the configuration is
658  * already active? */
659 
660  for (i = 0; i < req->Interface.NumberOfPipes; ++i)
661  {
663  pipe->PipeHandle = make_pipe_handle(pipe->EndpointAddress, pipe->PipeType);
664  }
665 
666  return STATUS_SUCCESS;
667  }
668 
670  {
672  uint8_t req_type = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_INTERFACE;
673  unsigned char *buffer;
674 
676  req_type |= LIBUSB_ENDPOINT_IN;
678  FIXME("Unhandled flags %#x.\n", req->TransferFlags);
679 
680  if (req->TransferBufferMDL)
681  FIXME("Unhandled MDL output buffer.\n");
682 
683  if (!(transfer = libusb_alloc_transfer(0)))
684  return STATUS_NO_MEMORY;
685 
686  if (!(buffer = malloc(sizeof(struct libusb_control_setup) + req->TransferBufferLength)))
687  {
688  libusb_free_transfer(transfer);
689  return STATUS_NO_MEMORY;
690  }
691 
692  queue_irp(device, irp, transfer);
693  libusb_fill_control_setup(buffer, req_type, req->Request,
694  req->Value, req->Index, req->TransferBufferLength);
696  memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, req->TransferBuffer, req->TransferBufferLength);
697  libusb_fill_control_transfer(transfer, device->handle, buffer, transfer_cb, irp, 0);
698  transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
699  ret = libusb_submit_transfer(transfer);
700  if (ret < 0)
701  ERR("Failed to submit vendor-specific interface transfer: %s\n", libusb_strerror(ret));
702 
703  return STATUS_PENDING;
704  }
705 
706  default:
707  FIXME("Unhandled function %#x.\n", urb->UrbHeader.Function);
708  }
709 
710  return STATUS_NOT_IMPLEMENTED;
711 }
712 
714 {
716  ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
719 
720  TRACE("device_obj %p, irp %p, code %#x.\n", device_obj, irp, code);
721 
722  switch (code)
723  {
725  status = usb_submit_urb(device, irp);
726  break;
727 
728  default:
729  FIXME("Unhandled ioctl %#x (device %#x, access %#x, function %#x, method %#x).\n",
730  code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
731  }
732 
733  if (status != STATUS_PENDING)
734  {
735  irp->IoStatus.Status = status;
737  }
738  return status;
739 }
740 
742 {
743  NTSTATUS ret;
744 
745  TRACE("driver %p, pdo %p.\n", driver, pdo);
746 
748  {
749  ERR("Failed to create FDO, status %#x.\n", ret);
750  return ret;
751  }
752 
754  bus_pdo = pdo;
755  bus_fdo->Flags &= ~~DO_DEVICE_INITIALIZING;
756 
757  return STATUS_SUCCESS;
758 }
759 
761 {
762  libusb_exit(NULL);
763 }
764 
766 {
767  int err;
768 
769  TRACE("driver %p, path %s.\n", driver, debugstr_w(path->Buffer));
770 
771  driver_obj = driver;
772 
773  if ((err = libusb_init(NULL)))
774  {
775  ERR("Failed to initialize libusb: %s\n", libusb_strerror(err));
776  return STATUS_UNSUCCESSFUL;
777  }
778 
780 
781  driver->DriverExtension->AddDevice = driver_add_device;
782  driver->DriverUnload = driver_unload;
783  driver->MajorFunction[IRP_MJ_PNP] = driver_pnp;
785 
786  return STATUS_SUCCESS;
787 }
#define __ASM_STDCALL_FUNC(name, args, code)
Definition: asm.h:91
unsigned long ULONG_PTR
Definition: basetsd.h:130
LONG NTSTATUS
Definition: bcrypt.h:40
#define WINAPI
Definition: bcrypt.h:23
enum shader_type type
Definition: type.pm:7
#define ERR(...)
Definition: cocoa_app.h:61
BOOL CloseHandle(HANDLE handle)
Definition: process.c:390
HANDLE CreateThread(SECURITY_ATTRIBUTES *sa, SIZE_T stack, LPTHREAD_START_ROUTINE start, LPVOID param, DWORD flags, LPDWORD id)
Definition: thread.c:111
void * memcpy(void *dst, const void *src, size_t n)
Definition: string.c:2580
static struct all_devices * devices
Definition: dsm_ctrl.c:48
long BOOL
Definition: dxgitype.idl:24
NTSTATUS status
Definition: except.c:81
GLuint err
Definition: glu.c:32
static DEVICE_OBJECT * device_obj
Definition: http.c:32
#define WINE_DEFAULT_DEBUG_CHANNEL(ch)
Definition: debug.h:499
static int sprintfW(WCHAR *str, const WCHAR *format,...)
Definition: unicode.h:263
static unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:56
DWORD WaitForSingleObject(HANDLE handle, DWORD timeout)
Definition: sync.c:299
static void list_remove(struct list *elem)
Definition: list.h:98
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:188
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:194
#define LIST_INIT(list)
Definition: list.h:227
static void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:92
static unsigned int list_count(const struct list *list)
Definition: list.h:145
void * malloc(size_t size)
Definition: heap.c:430
BYTE uint8_t
Definition: msvideo1.c:66
void * buffer
Definition: ntddk.h:198
void IoCompleteRequest(IRP *irp, UCHAR priority_boost)
Definition: ntoskrnl.c:1901
void ObfReferenceObject(void *obj)
Definition: ntoskrnl.c:2858
NTSTATUS IoCreateDevice(DRIVER_OBJECT *driver, ULONG ext_size, UNICODE_STRING *name, DWORD type, ULONG characteristics, BOOLEAN exclusive, DEVICE_OBJECT **ret_device)
Definition: ntoskrnl.c:1490
void IoDeleteDevice(DEVICE_OBJECT *device)
Definition: ntoskrnl.c:1561
NTSTATUS IoCallDriver(DEVICE_OBJECT *device, IRP *irp)
Definition: ntoskrnl.c:1692
PVOID ExAllocatePool(POOL_TYPE type, SIZE_T size)
Definition: ntoskrnl.c:2039
void IoDetachDevice(DEVICE_OBJECT *device)
Definition: ntoskrnl.c:1205
PDEVICE_OBJECT IoAttachDeviceToDeviceStack(DEVICE_OBJECT *source, DEVICE_OBJECT *target)
Definition: ntoskrnl.c:1213
void IoInvalidateDeviceRelations(DEVICE_OBJECT *device_object, DEVICE_RELATION_TYPE type)
Definition: pnp.c:464
PSecurityUserData *typedef PSECPKG_EXTENDED_INFORMATION *typedef ULONG
Definition: ntsecpkg.h:377
#define STATUS_PENDING
Definition: ntstatus.h:48
#define STATUS_NO_MEMORY
Definition: ntstatus.h:233
#define STATUS_UNSUCCESSFUL
Definition: ntstatus.h:211
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:212
#define STATUS_SUCCESS
Definition: ntstatus.h:30
#define STATUS_CANCELLED
Definition: ntstatus.h:498
HRESULT(* func)(HTMLDocumentNode *, DWORD, VARIANT *, VARIANT *)
Definition: olecmd.c:734
void RtlInitUnicodeString(PUNICODE_STRING target, PCWSTR source)
Definition: rtlstr.c:171
#define offsetof(s, m)
Definition: stddef.h:28
ULONG Flags
Definition: wdm.h:409
PVOID DeviceExtension
Definition: wdm.h:412
union _IO_STACK_LOCATION::@1029 Parameters
struct _IO_STACK_LOCATION::@1029::@1048 QueryId
struct _IO_STACK_LOCATION::@1029::@1042 QueryDeviceRelations
struct _IO_STACK_LOCATION::@1029::@1036 DeviceIoControl
UCHAR MinorFunction
Definition: wdm.h:970
NTSTATUS Status
Definition: winternl.h:1470
ULONG_PTR Information
Definition: winternl.h:1474
Definition: wdm.h:511
LIST_ENTRY ListEntry
Definition: wdm.h:553
PVOID DriverContext[4]
Definition: wdm.h:547
union _IRP::@1003 Tail
IO_STATUS_BLOCK IoStatus
Definition: wdm.h:522
union _IRP::@1002 Overlay
Definition: winnt.h:836
struct _LIST_ENTRY * Flink
Definition: winnt.h:837
USBD_PIPE_HANDLE PipeHandle
Definition: usb.h:253
USBD_PIPE_HANDLE PipeHandle
Definition: usb.h:215
USBD_INTERFACE_INFORMATION Interface
Definition: usb.h:210
Definition: usb.h:382
struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST UrbControlVendorClassRequest
Definition: usb.h:398
struct _URB_SELECT_CONFIGURATION UrbSelectConfiguration
Definition: usb.h:386
struct _URB_CONTROL_DESCRIPTOR_REQUEST UrbControlDescriptorRequest
Definition: usb.h:395
struct _URB_BULK_OR_INTERRUPT_TRANSFER UrbBulkOrInterruptTransfer
Definition: usb.h:393
struct _URB_PIPE_REQUEST UrbPipeRequest
Definition: usb.h:387
struct _URB_HEADER UrbHeader
Definition: usb.h:384
USBD_PIPE_INFORMATION Pipes[1]
Definition: usb.h:177
Definition: inflate.c:134
struct list entry
Definition: devinst.c:137
BOOL removed
Definition: devinst.c:138
Definition: filter.c:184
Definition: list.h:27
Definition: name.c:36
Definition: wineusb.c:509
unsigned char type
Definition: wineusb.c:511
unsigned char endpoint
Definition: wineusb.c:510
BOOL removed
Definition: wineusb.c:72
libusb_device_handle * handle
Definition: wineusb.c:77
libusb_device * libusb_device
Definition: wineusb.c:76
LIST_ENTRY irp_list
Definition: wineusb.c:79
struct list entry
Definition: wineusb.c:71
DEVICE_OBJECT * device_obj
Definition: wineusb.c:74
#define NULL
Definition: ungif.h:66
#define TRUE
Definition: ungif.h:59
#define FALSE
Definition: ungif.h:62
#define USBD_STATUS_DEVICE_GONE
Definition: usb.h:131
#define URB_FUNCTION_ABORT_PIPE
Definition: usb.h:26
#define USBD_STATUS_INVALID_PIPE_HANDLE
Definition: usb.h:115
#define USBD_STATUS_CANCELED
Definition: usb.h:133
#define USBD_STATUS_REQUEST_FAILED
Definition: usb.h:114
#define USBD_STATUS_SUCCESS
Definition: usb.h:85
enum _USBD_PIPE_TYPE USBD_PIPE_TYPE
#define USBD_TRANSFER_DIRECTION_IN
Definition: usb.h:77
#define URB_FUNCTION_SELECT_CONFIGURATION
Definition: usb.h:24
#define URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
Definition: usb.h:33
#define URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
Definition: usb.h:54
#define USBD_STATUS_TIMEOUT
Definition: usb.h:130
@ UsbdPipeTypeInterrupt
Definition: usb.h:153
@ UsbdPipeTypeBulk
Definition: usb.h:152
#define URB_FUNCTION_VENDOR_INTERFACE
Definition: usb.h:48
#define URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
Definition: usb.h:35
#define USBD_STATUS_ENDPOINT_HALTED
Definition: usb.h:109
#define IOCTL_INTERNAL_USB_SUBMIT_URB
Definition: usbioctl.h:24
#define FILE_DEVICE_USB
Definition: usbiodef.h:24
@ BusRelations
Definition: wdm.h:610
@ PagedPool
Definition: wdm.h:276
enum _BUS_QUERY_ID_TYPE BUS_QUERY_ID_TYPE
#define IO_NO_INCREMENT
Definition: wdm.h:305
#define IoGetCurrentIrpStackLocation(_Irp)
Definition: wdm.h:1586
#define IRP_MN_START_DEVICE
Definition: wdm.h:351
#define IRP_MN_QUERY_ID
Definition: wdm.h:369
#define IRP_MN_REMOVE_DEVICE
Definition: wdm.h:353
#define IRP_MN_SURPRISE_REMOVAL
Definition: wdm.h:373
#define IRP_MN_QUERY_DEVICE_RELATIONS
Definition: wdm.h:358
#define IRP_MN_QUERY_CAPABILITIES
Definition: wdm.h:360
#define IRP_MJ_PNP
Definition: wdm.h:349
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
Definition: wdm.h:337
static void IoMarkIrpPending(IRP *irp)
Definition: wdm.h:1607
@ BusQueryCompatibleIDs
Definition: wdm.h:832
@ BusQueryInstanceID
Definition: wdm.h:833
@ BusQueryDeviceID
Definition: wdm.h:830
@ BusQueryHardwareIDs
Definition: wdm.h:831
static void IoSkipCurrentIrpStackLocation(IRP *irp)
Definition: wdm.h:1588
DECLSPEC_IMPORT void WINAPI LeaveCriticalSection(CRITICAL_SECTION *lpCrit)
#define INFINITE
Definition: winbase.h:377
DECLSPEC_IMPORT void WINAPI EnterCriticalSection(CRITICAL_SECTION *lpCrit)
unsigned int DWORD
Definition: windef.h:261
#define CALLBACK
Definition: windef.h:194
static NTSTATUS fdo_pnp(IRP *irp)
Definition: wineusb.c:187
static BOOL thread_shutdown
Definition: wineusb.c:157
NTSTATUS DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *path)
Definition: wineusb.c:765
static DWORD event_thread_proc(void *arg)
Definition: wineusb.c:171
static NTSTATUS driver_internal_ioctl(DEVICE_OBJECT *device_obj, IRP *irp)
Definition: wineusb.c:713
static HANDLE make_pipe_handle(unsigned char endpoint, USBD_PIPE_TYPE type)
Definition: wineusb.c:514
static NTSTATUS usbd_status_from_libusb(enum libusb_transfer_status status)
Definition: wineusb.c:431
static struct pipe get_pipe(HANDLE handle)
Definition: wineusb.c:527
static DEVICE_OBJECT * bus_fdo
Definition: wineusb.c:83
static NTSTATUS driver_pnp(DEVICE_OBJECT *device, IRP *irp)
Definition: wineusb.c:424
static void get_compatible_ids(const struct usb_device *device, WCHAR *buffer)
Definition: wineusb.c:308
static NTSTATUS usb_submit_urb(struct usb_device *device, IRP *irp)
Definition: wineusb.c:539
static DRIVER_OBJECT * driver_obj
Definition: wineusb.c:82
static libusb_hotplug_callback_handle hotplug_cb_handle
Definition: wineusb.c:85
static void get_hardware_ids(const struct usb_device *device, WCHAR *buffer)
Definition: wineusb.c:295
static void queue_irp(struct usb_device *device, IRP *irp, struct libusb_transfer *transfer)
Definition: wineusb.c:499
static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp)
Definition: wineusb.c:366
#define DECLARE_CRITICAL_SECTION(cs)
Definition: wineusb.c:58
static void remove_usb_device(libusb_device *libusb_device)
Definition: wineusb.c:136
static void driver_unload(DRIVER_OBJECT *driver)
Definition: wineusb.c:760
#define call_fastcall_func1(func, a)
Definition: wineusb.c:54
static void add_usb_device(libusb_device *libusb_device)
Definition: wineusb.c:87
static void transfer_cb(struct libusb_transfer *transfer)
Definition: wineusb.c:452
static DEVICE_OBJECT * bus_pdo
Definition: wineusb.c:83
static NTSTATUS query_id(const struct usb_device *device, IRP *irp, BUS_QUERY_ID_TYPE type)
Definition: wineusb.c:328
static int LIBUSB_CALL hotplug_cb(libusb_context *context, libusb_device *device, libusb_hotplug_event event, void *user_data)
Definition: wineusb.c:160
static struct list device_list
Definition: wineusb.c:67
static HANDLE event_thread
Definition: wineusb.c:158
static CRITICAL_SECTION wineusb_cs
Definition: wineusb.c:65
static void get_device_id(const struct usb_device *device, WCHAR *buffer)
Definition: wineusb.c:285
static NTSTATUS driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *pdo)
Definition: wineusb.c:741
#define FILE_DEVICE_BUS_EXTENDER
Definition: winioctl.h:69
unsigned short WCHAR
Definition: winnt.h:468
#define CONTAINING_RECORD(address, type, field)
Definition: winnt.h:826
#define InsertTailList(le, e)
Definition: winternl.h:3819
#define InitializeListHead(le)
Definition: winternl.h:3817
static PLIST_ENTRY RemoveHeadList(PLIST_ENTRY le)
Definition: winternl.h:3822
#define RemoveEntryList(e)
Definition: winternl.h:3821