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)
38 #ifndef PLUGPLAY_REGKEY_DRIVER
39 #define PLUGPLAY_REGKEY_DRIVER 2
41 typedef struct _USBD_INTERFACE_LIST_ENTRY
{
42 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
43 PUSBD_INTERFACE_INFORMATION Interface
;
44 } USBD_INTERFACE_LIST_ENTRY
, *PUSBD_INTERFACE_LIST_ENTRY
;
47 DriverEntry(PDRIVER_OBJECT DriverObject
,
48 PUNICODE_STRING RegistryPath
)
50 return STATUS_SUCCESS
;
57 DllInitialize(ULONG Unknown
)
75 USBD_Debug_GetHeap(ULONG Unknown1
, POOL_TYPE PoolType
, ULONG NumberOfBytes
,
78 return ExAllocatePoolWithTag(PoolType
, NumberOfBytes
, Tag
);
85 USBD_Debug_RetHeap(PVOID Heap
, ULONG Unknown2
, ULONG Unknown3
)
94 USBD_Debug_LogEntry(PCHAR Name
, ULONG_PTR Info1
, ULONG_PTR Info2
,
103 USBD_AllocateDeviceName(ULONG Unknown
)
113 USBD_CalculateUsbBandwidth(
119 ULONG OverheadTable
[] = {
120 0x00, /* UsbdPipeTypeControl */
121 0x09, /* UsbdPipeTypeIsochronous */
122 0x00, /* UsbdPipeTypeBulk */
123 0x0d /* UsbdPipeTypeInterrupt */
127 if (OverheadTable
[EndpointType
] != 0)
129 Result
= ((MaxPacketSize
+ OverheadTable
[EndpointType
]) * 8 * 7) / 6;
141 USBD_Dispatch(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
, ULONG Unknown4
)
151 USBD_FreeDeviceMutex(PVOID Unknown
)
160 USBD_FreeDeviceName(PVOID Unknown
)
169 USBD_WaitDeviceMutex(PVOID Unknown
)
178 USBD_GetSuspendPowerState(ULONG Unknown1
)
188 USBD_InitializeDevice(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
,
189 ULONG Unknown4
, ULONG Unknown5
, ULONG Unknown6
)
192 return STATUS_NOT_SUPPORTED
;
199 USBD_RegisterHostController(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
,
200 ULONG Unknown4
, ULONG Unknown5
, ULONG Unknown6
, ULONG Unknown7
,
201 ULONG Unknown8
, ULONG Unknown9
, ULONG Unknown10
)
204 return STATUS_NOT_SUPPORTED
;
211 USBD_GetDeviceInformation(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
)
214 return STATUS_NOT_SUPPORTED
;
221 USBD_CreateDevice(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
,
222 ULONG Unknown4
, ULONG Unknown5
)
225 return STATUS_NOT_SUPPORTED
;
232 USBD_RemoveDevice(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
)
235 return STATUS_NOT_SUPPORTED
;
242 USBD_CompleteRequest(ULONG Unknown1
, ULONG Unknown2
)
251 USBD_RegisterHcFilter(
252 PDEVICE_OBJECT DeviceObject
,
253 PDEVICE_OBJECT FilterDeviceObject
263 USBD_SetSuspendPowerState(ULONG Unknown1
, ULONG Unknown2
)
272 USBD_MakePdoName(ULONG Unknown1
, ULONG Unknown2
)
275 return STATUS_NOT_SUPPORTED
;
283 PDEVICE_OBJECT RootHubPdo
,
288 return STATUS_NOT_SUPPORTED
;
295 USBD_GetUSBDIVersion(
296 PUSBD_VERSION_INFORMATION Version
301 Version
->USBDI_Version
= USBDI_VERSION
;
302 Version
->Supported_USB_Version
= 0x200;
310 USBD_RestoreDevice(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
)
313 return STATUS_NOT_SUPPORTED
;
320 USBD_RegisterHcDeviceCapabilities(ULONG Unknown1
, ULONG Unknown2
,
330 USBD_CreateConfigurationRequestEx(
331 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
332 PUSBD_INTERFACE_LIST_ENTRY InterfaceList
337 ULONG InterfaceCount
;
338 ULONG InterfaceNumber
, EndPointNumber
;
339 PUSBD_INTERFACE_INFORMATION InterfaceInfo
;
341 for (InterfaceCount
= 0;
342 InterfaceList
[InterfaceCount
].InterfaceDescriptor
!= NULL
;
345 UrbSize
+= sizeof(USBD_INTERFACE_INFORMATION
);
346 UrbSize
+= (InterfaceList
[InterfaceCount
].InterfaceDescriptor
->bNumEndpoints
- 1) * sizeof(USBD_PIPE_INFORMATION
);
349 UrbSize
+= sizeof(URB
) + sizeof(USBD_INTERFACE_INFORMATION
);
351 Urb
= ExAllocatePool(NonPagedPool
, UrbSize
);
352 RtlZeroMemory(Urb
, UrbSize
);
353 Urb
->UrbSelectConfiguration
.Hdr
.Function
= URB_FUNCTION_SELECT_CONFIGURATION
;
354 Urb
->UrbSelectConfiguration
.Hdr
.Length
= sizeof(Urb
->UrbSelectConfiguration
);
355 Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
= ConfigurationDescriptor
;
357 InterfaceInfo
= &Urb
->UrbSelectConfiguration
.Interface
;
358 for (InterfaceNumber
= 0; InterfaceNumber
< InterfaceCount
; InterfaceNumber
++)
360 InterfaceList
[InterfaceNumber
].Interface
= InterfaceInfo
;
361 InterfaceInfo
->Length
= sizeof(USBD_INTERFACE_INFORMATION
) +
362 ((InterfaceList
[InterfaceNumber
].InterfaceDescriptor
->bNumEndpoints
- 1) * sizeof(USBD_PIPE_INFORMATION
));
363 InterfaceInfo
->InterfaceNumber
= InterfaceList
[InterfaceNumber
].InterfaceDescriptor
->bInterfaceNumber
;
364 InterfaceInfo
->AlternateSetting
= InterfaceList
[InterfaceNumber
].InterfaceDescriptor
->bAlternateSetting
;
365 InterfaceInfo
->NumberOfPipes
= InterfaceList
[InterfaceNumber
].InterfaceDescriptor
->bNumEndpoints
;
366 for (EndPointNumber
= 0; EndPointNumber
< InterfaceInfo
->NumberOfPipes
; EndPointNumber
++)
368 InterfaceInfo
->Pipes
[EndPointNumber
].MaximumTransferSize
= PAGE_SIZE
;
370 InterfaceInfo
= (PUSBD_INTERFACE_INFORMATION
) ((ULONG_PTR
)InterfaceInfo
+ InterfaceInfo
->Length
);
380 USBD_CreateConfigurationRequest(
381 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
385 /* WindowsXP returns NULL */
393 USBD_GetInterfaceLength(
394 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
,
399 PUSB_INTERFACE_DESCRIPTOR CurrentDescriptor
= InterfaceDescriptor
;
401 BOOLEAN InterfaceFound
= FALSE
;
403 for (Current
= (ULONG_PTR
)CurrentDescriptor
;
404 Current
< (ULONG_PTR
)BufferEnd
;
405 Current
+= CurrentDescriptor
->bLength
)
407 CurrentDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)Current
;
409 if ((CurrentDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
) && (InterfaceFound
))
411 else if (CurrentDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
)
412 InterfaceFound
= TRUE
;
414 Length
+= CurrentDescriptor
->bLength
;
423 PUSB_COMMON_DESCRIPTOR NTAPI
424 USBD_ParseDescriptors(
425 PVOID DescriptorBuffer
,
431 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
433 /* use start position */
434 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)StartPosition
;
437 /* find next available descriptor */
438 while(CommonDescriptor
)
440 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)DescriptorBuffer
+ TotalLength
))
443 DPRINT("End reached %p\n", CommonDescriptor
);
447 DPRINT("CommonDescriptor Type %x Length %x\n", CommonDescriptor
->bDescriptorType
, CommonDescriptor
->bLength
);
449 /* is the requested one */
450 if (CommonDescriptor
->bDescriptorType
== DescriptorType
)
453 return CommonDescriptor
;
457 ASSERT(CommonDescriptor
->bLength
);
459 /* move to next descriptor */
460 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
463 /* no descriptor found */
471 PUSB_INTERFACE_DESCRIPTOR NTAPI
472 USBD_ParseConfigurationDescriptorEx(
473 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
475 LONG InterfaceNumber
,
476 LONG AlternateSetting
,
478 LONG InterfaceSubClass
,
479 LONG InterfaceProtocol
483 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
485 /* set to start position */
486 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)StartPosition
;
488 DPRINT("USBD_ParseConfigurationDescriptorEx\n");
489 DPRINT("ConfigurationDescriptor %p Length %lu\n", ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
);
490 DPRINT("CurrentOffset %p Offset %lu\n", StartPosition
, ((ULONG_PTR
)StartPosition
- (ULONG_PTR
)ConfigurationDescriptor
));
492 while(InterfaceDescriptor
)
494 /* get interface descriptor */
495 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, InterfaceDescriptor
, USB_INTERFACE_DESCRIPTOR_TYPE
);
496 if (!InterfaceDescriptor
)
498 /* no more descriptors available */
502 DPRINT("InterfaceDescriptor %p InterfaceNumber %x AlternateSetting %x Length %lu\n", InterfaceDescriptor
, InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
, InterfaceDescriptor
->bLength
);
507 /* is there an interface number provided */
508 if(InterfaceNumber
!= -1)
510 if(InterfaceNumber
!= InterfaceDescriptor
->bInterfaceNumber
)
512 /* interface number does not match */
517 /* is there an alternate setting provided */
518 if(AlternateSetting
!= -1)
520 if(AlternateSetting
!= InterfaceDescriptor
->bAlternateSetting
)
522 /* alternate setting does not match */
527 /* match on interface class */
528 if(InterfaceClass
!= -1)
530 if(InterfaceClass
!= InterfaceDescriptor
->bInterfaceClass
)
532 /* no match with interface class criteria */
537 /* match on interface sub class */
538 if(InterfaceSubClass
!= -1)
540 if(InterfaceSubClass
!= InterfaceDescriptor
->bInterfaceSubClass
)
542 /* no interface sub class match */
547 /* interface protocol criteria */
548 if(InterfaceProtocol
!= -1)
550 if(InterfaceProtocol
!= InterfaceDescriptor
->bInterfaceProtocol
)
552 /* no interface protocol match */
559 /* the choosen one */
560 return InterfaceDescriptor
;
564 ASSERT(InterfaceDescriptor
->bLength
);
566 /* move to next descriptor */
567 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
);
570 DPRINT("No Descriptor With InterfaceNumber %ld AlternateSetting %ld InterfaceClass %ld InterfaceSubClass %ld InterfaceProtocol %ld found\n", InterfaceNumber
,
571 AlternateSetting
, InterfaceClass
, InterfaceSubClass
, InterfaceProtocol
);
579 PUSB_INTERFACE_DESCRIPTOR NTAPI
580 USBD_ParseConfigurationDescriptor(
581 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
582 UCHAR InterfaceNumber
,
583 UCHAR AlternateSetting
586 return USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
,
587 (PVOID
)ConfigurationDescriptor
, InterfaceNumber
, AlternateSetting
,
596 USBD_GetPdoRegistryParameter(
597 PDEVICE_OBJECT PhysicalDeviceObject
,
599 ULONG ParameterLength
,
605 HANDLE DevInstRegKey
;
607 /* Open the device key */
608 Status
= IoOpenDeviceRegistryKey(PhysicalDeviceObject
,
609 PLUGPLAY_REGKEY_DEVICE
, STANDARD_RIGHTS_ALL
, &DevInstRegKey
);
610 if (NT_SUCCESS(Status
))
612 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
613 UNICODE_STRING ValueName
;
616 /* Initialize the unicode string based on caller data */
617 ValueName
.Buffer
= KeyName
;
618 ValueName
.Length
= ValueName
.MaximumLength
= KeyNameLength
;
620 Length
= ParameterLength
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION
);
621 PartialInfo
= ExAllocatePool(PagedPool
, Length
);
624 Status
= ZwQueryValueKey(DevInstRegKey
, &ValueName
,
625 KeyValuePartialInformation
, PartialInfo
, Length
, &Length
);
626 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
628 /* The caller doesn't want all the data */
629 ExFreePool(PartialInfo
);
630 PartialInfo
= ExAllocatePool(PagedPool
, Length
);
633 Status
= ZwQueryValueKey(DevInstRegKey
, &ValueName
,
634 KeyValuePartialInformation
, PartialInfo
, Length
, &Length
);
638 Status
= STATUS_NO_MEMORY
;
642 if (NT_SUCCESS(Status
))
644 /* Compute the length to copy back */
645 if (ParameterLength
< PartialInfo
->DataLength
)
646 Length
= ParameterLength
;
648 Length
= PartialInfo
->DataLength
;
650 RtlCopyMemory(Parameter
,
657 ExFreePool(PartialInfo
);
660 Status
= STATUS_NO_MEMORY
;
661 ZwClose(DevInstRegKey
);