2 * PROJECT: ReactOS Universal Serial Bus Driver/Helper Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbd/usbd.c
5 * PURPOSE: Helper Library for USB
7 * Filip Navara <xnavara@volny.cz>
8 * Michael Martin <michael.martin@reactos.org>
13 * Universal Serial Bus Driver/Helper Library
15 * Written by Filip Navara <xnavara@volny.cz>
18 * This driver was obsoleted in Windows XP and most functions
19 * became pure stubs. But some of them were retained for backward
20 * compatibilty with existing drivers.
22 * Preserved functions:
24 * USBD_Debug_GetHeap (implemented)
25 * USBD_Debug_RetHeap (implemented)
26 * USBD_CalculateUsbBandwidth (implemented, tested)
27 * USBD_CreateConfigurationRequestEx (implemented)
28 * USBD_CreateConfigurationRequest
29 * USBD_GetInterfaceLength (implemented)
30 * USBD_ParseConfigurationDescriptorEx (implemented)
31 * USBD_ParseDescriptors (implemented)
32 * USBD_GetPdoRegistryParameters (implemented)
39 #ifndef PLUGPLAY_REGKEY_DRIVER
40 #define PLUGPLAY_REGKEY_DRIVER 2
42 typedef struct _USBD_INTERFACE_LIST_ENTRY
{
43 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
44 PUSBD_INTERFACE_INFORMATION Interface
;
45 } USBD_INTERFACE_LIST_ENTRY
, *PUSBD_INTERFACE_LIST_ENTRY
;
48 DriverEntry(PDRIVER_OBJECT DriverObject
,
49 PUNICODE_STRING RegistryPath
)
51 return STATUS_SUCCESS
;
58 DllInitialize(ULONG Unknown
)
76 USBD_Debug_GetHeap(ULONG Unknown1
, POOL_TYPE PoolType
, ULONG NumberOfBytes
,
79 return ExAllocatePoolWithTag(PoolType
, NumberOfBytes
, Tag
);
86 USBD_Debug_RetHeap(PVOID Heap
, ULONG Unknown2
, ULONG Unknown3
)
95 USBD_Debug_LogEntry(PCHAR Name
, ULONG_PTR Info1
, ULONG_PTR Info2
,
104 USBD_AllocateDeviceName(ULONG Unknown
)
114 USBD_CalculateUsbBandwidth(
120 ULONG OverheadTable
[] = {
121 0x00, /* UsbdPipeTypeControl */
122 0x09, /* UsbdPipeTypeIsochronous */
123 0x00, /* UsbdPipeTypeBulk */
124 0x0d /* UsbdPipeTypeInterrupt */
128 if (OverheadTable
[EndpointType
] != 0)
130 Result
= ((MaxPacketSize
+ OverheadTable
[EndpointType
]) * 8 * 7) / 6;
142 USBD_Dispatch(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
, ULONG Unknown4
)
152 USBD_FreeDeviceMutex(PVOID Unknown
)
161 USBD_FreeDeviceName(PVOID Unknown
)
170 USBD_WaitDeviceMutex(PVOID Unknown
)
179 USBD_GetSuspendPowerState(ULONG Unknown1
)
189 USBD_InitializeDevice(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
,
190 ULONG Unknown4
, ULONG Unknown5
, ULONG Unknown6
)
193 return STATUS_NOT_SUPPORTED
;
200 USBD_RegisterHostController(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
,
201 ULONG Unknown4
, ULONG Unknown5
, ULONG Unknown6
, ULONG Unknown7
,
202 ULONG Unknown8
, ULONG Unknown9
, ULONG Unknown10
)
205 return STATUS_NOT_SUPPORTED
;
212 USBD_GetDeviceInformation(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
)
215 return STATUS_NOT_SUPPORTED
;
222 USBD_CreateDevice(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
,
223 ULONG Unknown4
, ULONG Unknown5
)
226 return STATUS_NOT_SUPPORTED
;
233 USBD_RemoveDevice(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
)
236 return STATUS_NOT_SUPPORTED
;
243 USBD_CompleteRequest(ULONG Unknown1
, ULONG Unknown2
)
252 USBD_RegisterHcFilter(
253 PDEVICE_OBJECT DeviceObject
,
254 PDEVICE_OBJECT FilterDeviceObject
264 USBD_SetSuspendPowerState(ULONG Unknown1
, ULONG Unknown2
)
273 USBD_MakePdoName(ULONG Unknown1
, ULONG Unknown2
)
276 return STATUS_NOT_SUPPORTED
;
284 PDEVICE_OBJECT RootHubPdo
,
289 return STATUS_NOT_SUPPORTED
;
296 USBD_GetUSBDIVersion(
297 PUSBD_VERSION_INFORMATION Version
302 Version
->USBDI_Version
= USBDI_VERSION
;
303 Version
->Supported_USB_Version
= 0x200;
311 USBD_RestoreDevice(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
)
314 return STATUS_NOT_SUPPORTED
;
321 USBD_RegisterHcDeviceCapabilities(ULONG Unknown1
, ULONG Unknown2
,
331 USBD_CreateConfigurationRequestEx(
332 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
333 PUSBD_INTERFACE_LIST_ENTRY InterfaceList
338 ULONG InterfaceCount
;
339 ULONG InterfaceNumber
, EndPointNumber
;
340 PUSBD_INTERFACE_INFORMATION InterfaceInfo
;
342 for (InterfaceCount
= 0;
343 InterfaceList
[InterfaceCount
].InterfaceDescriptor
!= NULL
;
346 UrbSize
+= sizeof(USBD_INTERFACE_INFORMATION
);
347 UrbSize
+= (InterfaceList
[InterfaceCount
].InterfaceDescriptor
->bNumEndpoints
- 1) * sizeof(USBD_PIPE_INFORMATION
);
350 UrbSize
+= sizeof(URB
) + sizeof(USBD_INTERFACE_INFORMATION
);
352 Urb
= ExAllocatePool(NonPagedPool
, UrbSize
);
353 RtlZeroMemory(Urb
, UrbSize
);
354 Urb
->UrbSelectConfiguration
.Hdr
.Function
= URB_FUNCTION_SELECT_CONFIGURATION
;
355 Urb
->UrbSelectConfiguration
.Hdr
.Length
= sizeof(Urb
->UrbSelectConfiguration
);
356 Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
= ConfigurationDescriptor
;
358 InterfaceInfo
= &Urb
->UrbSelectConfiguration
.Interface
;
359 for (InterfaceNumber
= 0; InterfaceNumber
< InterfaceCount
; InterfaceNumber
++)
361 InterfaceList
[InterfaceNumber
].Interface
= InterfaceInfo
;
362 InterfaceInfo
->Length
= sizeof(USBD_INTERFACE_INFORMATION
) +
363 ((InterfaceList
[InterfaceNumber
].InterfaceDescriptor
->bNumEndpoints
- 1) * sizeof(USBD_PIPE_INFORMATION
));
364 InterfaceInfo
->InterfaceNumber
= InterfaceList
[InterfaceNumber
].InterfaceDescriptor
->bInterfaceNumber
;
365 InterfaceInfo
->AlternateSetting
= InterfaceList
[InterfaceNumber
].InterfaceDescriptor
->bAlternateSetting
;
366 InterfaceInfo
->NumberOfPipes
= InterfaceList
[InterfaceNumber
].InterfaceDescriptor
->bNumEndpoints
;
367 for (EndPointNumber
= 0; EndPointNumber
< InterfaceInfo
->NumberOfPipes
; EndPointNumber
++)
369 InterfaceInfo
->Pipes
[EndPointNumber
].MaximumTransferSize
= PAGE_SIZE
;
371 InterfaceInfo
= (PUSBD_INTERFACE_INFORMATION
) ((ULONG_PTR
)InterfaceInfo
+ InterfaceInfo
->Length
);
381 USBD_CreateConfigurationRequest(
382 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
386 /* WindowsXP returns NULL */
394 USBD_GetInterfaceLength(
395 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
,
400 PUSB_INTERFACE_DESCRIPTOR CurrentDescriptor
= InterfaceDescriptor
;
402 BOOLEAN InterfaceFound
= FALSE
;
404 for (Current
= (ULONG_PTR
)CurrentDescriptor
;
405 Current
< (ULONG_PTR
)BufferEnd
;
406 Current
+= CurrentDescriptor
->bLength
)
408 CurrentDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)Current
;
410 if ((CurrentDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
) && (InterfaceFound
))
412 else if (CurrentDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
)
413 InterfaceFound
= TRUE
;
415 Length
+= CurrentDescriptor
->bLength
;
424 PUSB_COMMON_DESCRIPTOR NTAPI
425 USBD_ParseDescriptors(
426 PVOID DescriptorBuffer
,
432 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
434 /* use start position */
435 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)StartPosition
;
438 /* find next available descriptor */
439 while(CommonDescriptor
)
441 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)DescriptorBuffer
+ TotalLength
))
444 DPRINT("End reached %p\n", CommonDescriptor
);
448 DPRINT("CommonDescriptor Type %x Length %x\n", CommonDescriptor
->bDescriptorType
, CommonDescriptor
->bLength
);
450 /* is the requested one */
451 if (CommonDescriptor
->bDescriptorType
== DescriptorType
)
454 return CommonDescriptor
;
458 ASSERT(CommonDescriptor
->bLength
);
460 /* move to next descriptor */
461 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
464 /* no descriptor found */
472 PUSB_INTERFACE_DESCRIPTOR NTAPI
473 USBD_ParseConfigurationDescriptorEx(
474 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
476 LONG InterfaceNumber
,
477 LONG AlternateSetting
,
479 LONG InterfaceSubClass
,
480 LONG InterfaceProtocol
484 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
486 /* set to start position */
487 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)StartPosition
;
489 DPRINT("USBD_ParseConfigurationDescriptorEx\n");
490 DPRINT("ConfigurationDescriptor %p Length %lu\n", ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
);
491 DPRINT("CurrentOffset %p Offset %lu\n", StartPosition
, ((ULONG_PTR
)StartPosition
- (ULONG_PTR
)ConfigurationDescriptor
));
493 while(InterfaceDescriptor
)
495 /* get interface descriptor */
496 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, InterfaceDescriptor
, USB_INTERFACE_DESCRIPTOR_TYPE
);
497 if (!InterfaceDescriptor
)
499 /* no more descriptors available */
503 DPRINT("InterfaceDescriptor %p InterfaceNumber %x AlternateSetting %x Length %lu\n", InterfaceDescriptor
, InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
, InterfaceDescriptor
->bLength
);
508 /* is there an interface number provided */
509 if(InterfaceNumber
!= -1)
511 if(InterfaceNumber
!= InterfaceDescriptor
->bInterfaceNumber
)
513 /* interface number does not match */
518 /* is there an alternate setting provided */
519 if(AlternateSetting
!= -1)
521 if(AlternateSetting
!= InterfaceDescriptor
->bAlternateSetting
)
523 /* alternate setting does not match */
528 /* match on interface class */
529 if(InterfaceClass
!= -1)
531 if(InterfaceClass
!= InterfaceDescriptor
->bInterfaceClass
)
533 /* no match with interface class criteria */
538 /* match on interface sub class */
539 if(InterfaceSubClass
!= -1)
541 if(InterfaceSubClass
!= InterfaceDescriptor
->bInterfaceSubClass
)
543 /* no interface sub class match */
548 /* interface protocol criteria */
549 if(InterfaceProtocol
!= -1)
551 if(InterfaceProtocol
!= InterfaceDescriptor
->bInterfaceProtocol
)
553 /* no interface protocol match */
560 /* the choosen one */
561 return InterfaceDescriptor
;
565 ASSERT(InterfaceDescriptor
->bLength
);
567 /* move to next descriptor */
568 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
);
571 DPRINT("No Descriptor With InterfaceNumber %ld AlternateSetting %ld InterfaceClass %ld InterfaceSubClass %ld InterfaceProtocol %ld found\n", InterfaceNumber
,
572 AlternateSetting
, InterfaceClass
, InterfaceSubClass
, InterfaceProtocol
);
580 PUSB_INTERFACE_DESCRIPTOR NTAPI
581 USBD_ParseConfigurationDescriptor(
582 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
583 UCHAR InterfaceNumber
,
584 UCHAR AlternateSetting
587 return USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
,
588 (PVOID
)ConfigurationDescriptor
, InterfaceNumber
, AlternateSetting
,
597 USBD_GetPdoRegistryParameter(
598 PDEVICE_OBJECT PhysicalDeviceObject
,
600 ULONG ParameterLength
,
606 HANDLE DevInstRegKey
;
608 /* Open the device key */
609 Status
= IoOpenDeviceRegistryKey(PhysicalDeviceObject
,
610 PLUGPLAY_REGKEY_DEVICE
, STANDARD_RIGHTS_ALL
, &DevInstRegKey
);
611 if (NT_SUCCESS(Status
))
613 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
614 UNICODE_STRING ValueName
;
617 /* Initialize the unicode string based on caller data */
618 ValueName
.Buffer
= KeyName
;
619 ValueName
.Length
= ValueName
.MaximumLength
= KeyNameLength
;
621 Length
= ParameterLength
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION
);
622 PartialInfo
= ExAllocatePool(PagedPool
, Length
);
625 Status
= ZwQueryValueKey(DevInstRegKey
, &ValueName
,
626 KeyValuePartialInformation
, PartialInfo
, Length
, &Length
);
627 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
629 /* The caller doesn't want all the data */
630 ExFreePool(PartialInfo
);
631 PartialInfo
= ExAllocatePool(PagedPool
, Length
);
634 Status
= ZwQueryValueKey(DevInstRegKey
, &ValueName
,
635 KeyValuePartialInformation
, PartialInfo
, Length
, &Length
);
639 Status
= STATUS_NO_MEMORY
;
643 if (NT_SUCCESS(Status
))
645 /* Compute the length to copy back */
646 if (ParameterLength
< PartialInfo
->DataLength
)
647 Length
= ParameterLength
;
649 Length
= PartialInfo
->DataLength
;
651 RtlCopyMemory(Parameter
,
658 ExFreePool(PartialInfo
);
661 Status
= STATUS_NO_MEMORY
;
662 ZwClose(DevInstRegKey
);