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 * compatibility 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)
41 #ifndef PLUGPLAY_REGKEY_DRIVER
42 #define PLUGPLAY_REGKEY_DRIVER 2
46 DriverEntry(PDRIVER_OBJECT DriverObject
,
47 PUNICODE_STRING RegistryPath
)
49 return STATUS_SUCCESS
;
56 DllInitialize(ULONG Unknown
)
74 USBD_Debug_GetHeap(ULONG Unknown1
, POOL_TYPE PoolType
, ULONG NumberOfBytes
,
77 return ExAllocatePoolWithTag(PoolType
, NumberOfBytes
, Tag
);
84 USBD_Debug_RetHeap(PVOID Heap
, ULONG Unknown2
, ULONG Unknown3
)
93 USBD_Debug_LogEntry(PCHAR Name
, ULONG_PTR Info1
, ULONG_PTR Info2
,
102 USBD_AllocateDeviceName(ULONG Unknown
)
112 USBD_CalculateUsbBandwidth(
118 ULONG OverheadTable
[] = {
119 0x00, /* UsbdPipeTypeControl */
120 0x09, /* UsbdPipeTypeIsochronous */
121 0x00, /* UsbdPipeTypeBulk */
122 0x0d /* UsbdPipeTypeInterrupt */
126 if (OverheadTable
[EndpointType
] != 0)
128 Result
= ((MaxPacketSize
+ OverheadTable
[EndpointType
]) * 8 * 7) / 6;
140 USBD_Dispatch(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
, ULONG Unknown4
)
150 USBD_FreeDeviceMutex(PVOID Unknown
)
159 USBD_FreeDeviceName(PVOID Unknown
)
168 USBD_WaitDeviceMutex(PVOID Unknown
)
177 USBD_GetSuspendPowerState(ULONG Unknown1
)
187 USBD_InitializeDevice(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
,
188 ULONG Unknown4
, ULONG Unknown5
, ULONG Unknown6
)
191 return STATUS_NOT_SUPPORTED
;
198 USBD_RegisterHostController(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
,
199 ULONG Unknown4
, ULONG Unknown5
, ULONG Unknown6
, ULONG Unknown7
,
200 ULONG Unknown8
, ULONG Unknown9
, ULONG Unknown10
)
203 return STATUS_NOT_SUPPORTED
;
210 USBD_GetDeviceInformation(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
)
213 return STATUS_NOT_SUPPORTED
;
220 USBD_CreateDevice(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
,
221 ULONG Unknown4
, ULONG Unknown5
)
224 return STATUS_NOT_SUPPORTED
;
231 USBD_RemoveDevice(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
)
234 return STATUS_NOT_SUPPORTED
;
241 USBD_CompleteRequest(ULONG Unknown1
, ULONG Unknown2
)
250 USBD_RegisterHcFilter(
251 PDEVICE_OBJECT DeviceObject
,
252 PDEVICE_OBJECT FilterDeviceObject
262 USBD_SetSuspendPowerState(ULONG Unknown1
, ULONG Unknown2
)
271 USBD_MakePdoName(ULONG Unknown1
, ULONG Unknown2
)
274 return STATUS_NOT_SUPPORTED
;
282 PDEVICE_OBJECT RootHubPdo
,
287 return STATUS_NOT_SUPPORTED
;
294 USBD_GetUSBDIVersion(
295 PUSBD_VERSION_INFORMATION Version
300 Version
->USBDI_Version
= USBDI_VERSION
;
301 Version
->Supported_USB_Version
= 0x200;
309 USBD_RestoreDevice(ULONG Unknown1
, ULONG Unknown2
, ULONG Unknown3
)
312 return STATUS_NOT_SUPPORTED
;
319 USBD_RegisterHcDeviceCapabilities(ULONG Unknown1
, ULONG Unknown2
,
329 USBD_CreateConfigurationRequestEx(
330 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
331 PUSBD_INTERFACE_LIST_ENTRY InterfaceList
336 ULONG InterfaceCount
= 0, PipeCount
= 0;
337 ULONG InterfaceNumber
, EndPointNumber
;
338 PUSBD_INTERFACE_INFORMATION InterfaceInfo
;
340 while(InterfaceList
[InterfaceCount
].InterfaceDescriptor
)
343 PipeCount
+= InterfaceList
[InterfaceCount
].InterfaceDescriptor
->bNumEndpoints
;
350 UrbSize
= GET_SELECT_CONFIGURATION_REQUEST_SIZE(InterfaceCount
, PipeCount
);
353 Urb
= ExAllocatePool(NonPagedPool
, UrbSize
);
361 RtlZeroMemory(Urb
, UrbSize
);
364 Urb
->UrbSelectConfiguration
.Hdr
.Function
= URB_FUNCTION_SELECT_CONFIGURATION
;
365 Urb
->UrbSelectConfiguration
.Hdr
.Length
= UrbSize
;
366 Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
= ConfigurationDescriptor
;
368 // init interface information
369 InterfaceInfo
= &Urb
->UrbSelectConfiguration
.Interface
;
370 for (InterfaceNumber
= 0; InterfaceNumber
< InterfaceCount
; InterfaceNumber
++)
372 // init interface info
373 InterfaceList
[InterfaceNumber
].Interface
= InterfaceInfo
;
374 InterfaceInfo
->InterfaceNumber
= InterfaceList
[InterfaceNumber
].InterfaceDescriptor
->bInterfaceNumber
;
375 InterfaceInfo
->AlternateSetting
= InterfaceList
[InterfaceNumber
].InterfaceDescriptor
->bAlternateSetting
;
376 InterfaceInfo
->NumberOfPipes
= InterfaceList
[InterfaceNumber
].InterfaceDescriptor
->bNumEndpoints
;
379 InterfaceInfo
->Length
= GET_USBD_INTERFACE_SIZE(InterfaceList
[InterfaceNumber
].InterfaceDescriptor
->bNumEndpoints
);
382 //C_ASSERT(FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes) == 16);
384 for (EndPointNumber
= 0; EndPointNumber
< InterfaceInfo
->NumberOfPipes
; EndPointNumber
++)
386 // init max transfer size
387 InterfaceInfo
->Pipes
[EndPointNumber
].MaximumTransferSize
= PAGE_SIZE
;
390 // next interface info
391 InterfaceInfo
= (PUSBD_INTERFACE_INFORMATION
) ((ULONG_PTR
)InterfaceInfo
+ InterfaceInfo
->Length
);
401 USBD_CreateConfigurationRequest(
402 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
406 /* WindowsXP returns NULL */
414 USBD_GetInterfaceLength(
415 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
,
420 PUSB_INTERFACE_DESCRIPTOR CurrentDescriptor
= InterfaceDescriptor
;
422 BOOLEAN InterfaceFound
= FALSE
;
424 for (Current
= (ULONG_PTR
)CurrentDescriptor
;
425 Current
< (ULONG_PTR
)BufferEnd
;
426 Current
+= CurrentDescriptor
->bLength
)
428 CurrentDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)Current
;
430 if ((CurrentDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
) && (InterfaceFound
))
432 else if (CurrentDescriptor
->bDescriptorType
== USB_INTERFACE_DESCRIPTOR_TYPE
)
433 InterfaceFound
= TRUE
;
435 Length
+= CurrentDescriptor
->bLength
;
444 PUSB_COMMON_DESCRIPTOR NTAPI
445 USBD_ParseDescriptors(
446 PVOID DescriptorBuffer
,
452 PUSB_COMMON_DESCRIPTOR CommonDescriptor
;
454 /* use start position */
455 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)StartPosition
;
458 /* find next available descriptor */
459 while(CommonDescriptor
)
461 if ((ULONG_PTR
)CommonDescriptor
>= ((ULONG_PTR
)DescriptorBuffer
+ TotalLength
))
464 DPRINT("End reached %p\n", CommonDescriptor
);
468 DPRINT("CommonDescriptor Type %x Length %x\n", CommonDescriptor
->bDescriptorType
, CommonDescriptor
->bLength
);
470 /* is the requested one */
471 if (CommonDescriptor
->bDescriptorType
== DescriptorType
)
474 return CommonDescriptor
;
477 if (CommonDescriptor
->bLength
== 0)
479 /* invalid usb descriptor */
483 /* move to next descriptor */
484 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
487 /* no descriptor found */
495 PUSB_INTERFACE_DESCRIPTOR NTAPI
496 USBD_ParseConfigurationDescriptorEx(
497 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
499 LONG InterfaceNumber
,
500 LONG AlternateSetting
,
502 LONG InterfaceSubClass
,
503 LONG InterfaceProtocol
507 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
509 /* set to start position */
510 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)StartPosition
;
512 DPRINT("USBD_ParseConfigurationDescriptorEx\n");
513 DPRINT("ConfigurationDescriptor %p Length %lu\n", ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
);
514 DPRINT("CurrentOffset %p Offset %lu\n", StartPosition
, ((ULONG_PTR
)StartPosition
- (ULONG_PTR
)ConfigurationDescriptor
));
516 while(InterfaceDescriptor
)
518 /* get interface descriptor */
519 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, InterfaceDescriptor
, USB_INTERFACE_DESCRIPTOR_TYPE
);
520 if (!InterfaceDescriptor
)
522 /* no more descriptors available */
526 DPRINT("InterfaceDescriptor %p InterfaceNumber %x AlternateSetting %x Length %lu\n", InterfaceDescriptor
, InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
, InterfaceDescriptor
->bLength
);
531 /* is there an interface number provided */
532 if(InterfaceNumber
!= -1)
534 if(InterfaceNumber
!= InterfaceDescriptor
->bInterfaceNumber
)
536 /* interface number does not match */
541 /* is there an alternate setting provided */
542 if(AlternateSetting
!= -1)
544 if(AlternateSetting
!= InterfaceDescriptor
->bAlternateSetting
)
546 /* alternate setting does not match */
551 /* match on interface class */
552 if(InterfaceClass
!= -1)
554 if(InterfaceClass
!= InterfaceDescriptor
->bInterfaceClass
)
556 /* no match with interface class criteria */
561 /* match on interface sub class */
562 if(InterfaceSubClass
!= -1)
564 if(InterfaceSubClass
!= InterfaceDescriptor
->bInterfaceSubClass
)
566 /* no interface sub class match */
571 /* interface protocol criteria */
572 if(InterfaceProtocol
!= -1)
574 if(InterfaceProtocol
!= InterfaceDescriptor
->bInterfaceProtocol
)
576 /* no interface protocol match */
583 /* the choosen one */
584 return InterfaceDescriptor
;
588 ASSERT(InterfaceDescriptor
->bLength
);
590 /* move to next descriptor */
591 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
);
594 DPRINT("No Descriptor With InterfaceNumber %ld AlternateSetting %ld InterfaceClass %ld InterfaceSubClass %ld InterfaceProtocol %ld found\n", InterfaceNumber
,
595 AlternateSetting
, InterfaceClass
, InterfaceSubClass
, InterfaceProtocol
);
603 PUSB_INTERFACE_DESCRIPTOR NTAPI
604 USBD_ParseConfigurationDescriptor(
605 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
606 UCHAR InterfaceNumber
,
607 UCHAR AlternateSetting
610 return USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
,
611 (PVOID
)ConfigurationDescriptor
, InterfaceNumber
, AlternateSetting
,
620 USBD_GetPdoRegistryParameter(
621 PDEVICE_OBJECT PhysicalDeviceObject
,
623 ULONG ParameterLength
,
629 HANDLE DevInstRegKey
;
631 /* Open the device key */
632 Status
= IoOpenDeviceRegistryKey(PhysicalDeviceObject
,
633 PLUGPLAY_REGKEY_DEVICE
, STANDARD_RIGHTS_ALL
, &DevInstRegKey
);
634 if (NT_SUCCESS(Status
))
636 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
637 UNICODE_STRING ValueName
;
640 /* Initialize the unicode string based on caller data */
641 ValueName
.Buffer
= KeyName
;
642 ValueName
.Length
= ValueName
.MaximumLength
= KeyNameLength
;
644 Length
= ParameterLength
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION
);
645 PartialInfo
= ExAllocatePool(PagedPool
, Length
);
648 Status
= ZwQueryValueKey(DevInstRegKey
, &ValueName
,
649 KeyValuePartialInformation
, PartialInfo
, Length
, &Length
);
650 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
652 /* The caller doesn't want all the data */
653 ExFreePool(PartialInfo
);
654 PartialInfo
= ExAllocatePool(PagedPool
, Length
);
657 Status
= ZwQueryValueKey(DevInstRegKey
, &ValueName
,
658 KeyValuePartialInformation
, PartialInfo
, Length
, &Length
);
662 Status
= STATUS_NO_MEMORY
;
666 if (NT_SUCCESS(Status
))
668 /* Compute the length to copy back */
669 if (ParameterLength
< PartialInfo
->DataLength
)
670 Length
= ParameterLength
;
672 Length
= PartialInfo
->DataLength
;
674 RtlCopyMemory(Parameter
,
681 ExFreePool(PartialInfo
);
684 Status
= STATUS_NO_MEMORY
;
685 ZwClose(DevInstRegKey
);