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)
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
;
478 ASSERT(CommonDescriptor
->bLength
);
480 /* move to next descriptor */
481 CommonDescriptor
= (PUSB_COMMON_DESCRIPTOR
)((ULONG_PTR
)CommonDescriptor
+ CommonDescriptor
->bLength
);
484 /* no descriptor found */
492 PUSB_INTERFACE_DESCRIPTOR NTAPI
493 USBD_ParseConfigurationDescriptorEx(
494 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
496 LONG InterfaceNumber
,
497 LONG AlternateSetting
,
499 LONG InterfaceSubClass
,
500 LONG InterfaceProtocol
504 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor
;
506 /* set to start position */
507 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)StartPosition
;
509 DPRINT("USBD_ParseConfigurationDescriptorEx\n");
510 DPRINT("ConfigurationDescriptor %p Length %lu\n", ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
);
511 DPRINT("CurrentOffset %p Offset %lu\n", StartPosition
, ((ULONG_PTR
)StartPosition
- (ULONG_PTR
)ConfigurationDescriptor
));
513 while(InterfaceDescriptor
)
515 /* get interface descriptor */
516 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
) USBD_ParseDescriptors(ConfigurationDescriptor
, ConfigurationDescriptor
->wTotalLength
, InterfaceDescriptor
, USB_INTERFACE_DESCRIPTOR_TYPE
);
517 if (!InterfaceDescriptor
)
519 /* no more descriptors available */
523 DPRINT("InterfaceDescriptor %p InterfaceNumber %x AlternateSetting %x Length %lu\n", InterfaceDescriptor
, InterfaceDescriptor
->bInterfaceNumber
, InterfaceDescriptor
->bAlternateSetting
, InterfaceDescriptor
->bLength
);
528 /* is there an interface number provided */
529 if(InterfaceNumber
!= -1)
531 if(InterfaceNumber
!= InterfaceDescriptor
->bInterfaceNumber
)
533 /* interface number does not match */
538 /* is there an alternate setting provided */
539 if(AlternateSetting
!= -1)
541 if(AlternateSetting
!= InterfaceDescriptor
->bAlternateSetting
)
543 /* alternate setting does not match */
548 /* match on interface class */
549 if(InterfaceClass
!= -1)
551 if(InterfaceClass
!= InterfaceDescriptor
->bInterfaceClass
)
553 /* no match with interface class criteria */
558 /* match on interface sub class */
559 if(InterfaceSubClass
!= -1)
561 if(InterfaceSubClass
!= InterfaceDescriptor
->bInterfaceSubClass
)
563 /* no interface sub class match */
568 /* interface protocol criteria */
569 if(InterfaceProtocol
!= -1)
571 if(InterfaceProtocol
!= InterfaceDescriptor
->bInterfaceProtocol
)
573 /* no interface protocol match */
580 /* the choosen one */
581 return InterfaceDescriptor
;
585 ASSERT(InterfaceDescriptor
->bLength
);
587 /* move to next descriptor */
588 InterfaceDescriptor
= (PUSB_INTERFACE_DESCRIPTOR
)((ULONG_PTR
)InterfaceDescriptor
+ InterfaceDescriptor
->bLength
);
591 DPRINT("No Descriptor With InterfaceNumber %ld AlternateSetting %ld InterfaceClass %ld InterfaceSubClass %ld InterfaceProtocol %ld found\n", InterfaceNumber
,
592 AlternateSetting
, InterfaceClass
, InterfaceSubClass
, InterfaceProtocol
);
600 PUSB_INTERFACE_DESCRIPTOR NTAPI
601 USBD_ParseConfigurationDescriptor(
602 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
,
603 UCHAR InterfaceNumber
,
604 UCHAR AlternateSetting
607 return USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor
,
608 (PVOID
)ConfigurationDescriptor
, InterfaceNumber
, AlternateSetting
,
617 USBD_GetPdoRegistryParameter(
618 PDEVICE_OBJECT PhysicalDeviceObject
,
620 ULONG ParameterLength
,
626 HANDLE DevInstRegKey
;
628 /* Open the device key */
629 Status
= IoOpenDeviceRegistryKey(PhysicalDeviceObject
,
630 PLUGPLAY_REGKEY_DEVICE
, STANDARD_RIGHTS_ALL
, &DevInstRegKey
);
631 if (NT_SUCCESS(Status
))
633 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
634 UNICODE_STRING ValueName
;
637 /* Initialize the unicode string based on caller data */
638 ValueName
.Buffer
= KeyName
;
639 ValueName
.Length
= ValueName
.MaximumLength
= KeyNameLength
;
641 Length
= ParameterLength
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION
);
642 PartialInfo
= ExAllocatePool(PagedPool
, Length
);
645 Status
= ZwQueryValueKey(DevInstRegKey
, &ValueName
,
646 KeyValuePartialInformation
, PartialInfo
, Length
, &Length
);
647 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
649 /* The caller doesn't want all the data */
650 ExFreePool(PartialInfo
);
651 PartialInfo
= ExAllocatePool(PagedPool
, Length
);
654 Status
= ZwQueryValueKey(DevInstRegKey
, &ValueName
,
655 KeyValuePartialInformation
, PartialInfo
, Length
, &Length
);
659 Status
= STATUS_NO_MEMORY
;
663 if (NT_SUCCESS(Status
))
665 /* Compute the length to copy back */
666 if (ParameterLength
< PartialInfo
->DataLength
)
667 Length
= ParameterLength
;
669 Length
= PartialInfo
->DataLength
;
671 RtlCopyMemory(Parameter
,
678 ExFreePool(PartialInfo
);
681 Status
= STATUS_NO_MEMORY
;
682 ZwClose(DevInstRegKey
);