/* * PROJECT: ReactOS Universal Serial Bus Driver/Helper Library * LICENSE: GPL - See COPYING in the top level directory * FILE: drivers/usb/usbd/usbd.c * PURPOSE: Helper Library for USB * PROGRAMMERS: * Filip Navara * */ /* * Universal Serial Bus Driver/Helper Library * * Written by Filip Navara * * Notes: * This driver was obsoleted in Windows XP and most functions * became pure stubs. But some of them were retained for backward * compatibilty with existing drivers. * * Preserved functions: * * USBD_Debug_GetHeap (implemented) * USBD_Debug_RetHeap (implemented) * USBD_CalculateUsbBandwidth (implemented, tested) * USBD_CreateConfigurationRequestEx (implemented) * USBD_CreateConfigurationRequest * USBD_GetInterfaceLength (implemented) * USBD_ParseConfigurationDescriptorEx (implemented) * USBD_ParseDescriptors (implemented) * USBD_GetPdoRegistryParameters (implemented) */ #include #include #ifndef PLUGPLAY_REGKEY_DRIVER #define PLUGPLAY_REGKEY_DRIVER 2 #endif typedef struct _USBD_INTERFACE_LIST_ENTRY { PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; PUSBD_INTERFACE_INFORMATION Interface; } USBD_INTERFACE_LIST_ENTRY, *PUSBD_INTERFACE_LIST_ENTRY; NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { return STATUS_SUCCESS; } /* * @implemented */ DWORD STDCALL DllInitialize(DWORD Unknown) { return 0; } /* * @implemented */ DWORD STDCALL DllUnload(VOID) { return 0; } /* * @implemented */ PVOID STDCALL USBD_Debug_GetHeap(DWORD Unknown1, POOL_TYPE PoolType, ULONG NumberOfBytes, ULONG Tag) { return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag); } /* * @implemented */ VOID STDCALL USBD_Debug_RetHeap(PVOID Heap, DWORD Unknown2, DWORD Unknown3) { ExFreePool(Heap); } /* * @implemented */ VOID STDCALL USBD_Debug_LogEntry(PCHAR Name, ULONG_PTR Info1, ULONG_PTR Info2, ULONG_PTR Info3) { } /* * @implemented */ PVOID STDCALL USBD_AllocateDeviceName(DWORD Unknown) { return NULL; } /* * @implemented */ DWORD STDCALL USBD_CalculateUsbBandwidth( ULONG MaxPacketSize, UCHAR EndpointType, BOOLEAN LowSpeed ) { DWORD OverheadTable[] = { 0x00, /* UsbdPipeTypeControl */ 0x09, /* UsbdPipeTypeIsochronous */ 0x00, /* UsbdPipeTypeBulk */ 0x0d /* UsbdPipeTypeInterrupt */ }; DWORD Result; if (OverheadTable[EndpointType] != 0) { Result = ((MaxPacketSize + OverheadTable[EndpointType]) * 8 * 7) / 6; if (LowSpeed) return Result << 3; return Result; } return 0; } /* * @implemented */ DWORD STDCALL USBD_Dispatch(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) { return 1; } /* * @implemented */ VOID STDCALL USBD_FreeDeviceMutex(PVOID Unknown) { } /* * @implemented */ VOID STDCALL USBD_FreeDeviceName(PVOID Unknown) { } /* * @implemented */ VOID STDCALL USBD_WaitDeviceMutex(PVOID Unknown) { } /* * @implemented */ DWORD STDCALL USBD_GetSuspendPowerState(DWORD Unknown1) { return 0; } /* * @implemented */ NTSTATUS STDCALL USBD_InitializeDevice(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) { return STATUS_NOT_SUPPORTED; } /* * @implemented */ NTSTATUS STDCALL USBD_RegisterHostController(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6, DWORD Unknown7, DWORD Unknown8, DWORD Unknown9, DWORD Unknown10) { return STATUS_NOT_SUPPORTED; } /* * @implemented */ NTSTATUS STDCALL USBD_GetDeviceInformation(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) { return STATUS_NOT_SUPPORTED; } /* * @implemented */ NTSTATUS STDCALL USBD_CreateDevice(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) { return STATUS_NOT_SUPPORTED; } /* * @implemented */ NTSTATUS STDCALL USBD_RemoveDevice(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) { return STATUS_NOT_SUPPORTED; } /* * @implemented */ VOID STDCALL USBD_CompleteRequest(DWORD Unknown1, DWORD Unknown2) { } /* * @implemented */ VOID STDCALL USBD_RegisterHcFilter( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT FilterDeviceObject ) { } /* * @implemented */ VOID STDCALL USBD_SetSuspendPowerState(DWORD Unknown1, DWORD Unknown2) { } /* * @implemented */ NTSTATUS STDCALL USBD_MakePdoName(DWORD Unknown1, DWORD Unknown2) { return STATUS_NOT_SUPPORTED; } /* * @implemented */ NTSTATUS STDCALL USBD_QueryBusTime( PDEVICE_OBJECT RootHubPdo, PULONG CurrentFrame ) { return STATUS_NOT_SUPPORTED; } /* * @implemented */ VOID STDCALL USBD_GetUSBDIVersion( PUSBD_VERSION_INFORMATION Version ) { if (Version != NULL) { Version->USBDI_Version = USBDI_VERSION; Version->Supported_USB_Version = 0x100; } } /* * @implemented */ NTSTATUS STDCALL USBD_RestoreDevice(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) { return STATUS_NOT_SUPPORTED; } /* * @implemented */ VOID STDCALL USBD_RegisterHcDeviceCapabilities(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) { } /* * @implemented * FIXME: Test */ PURB STDCALL USBD_CreateConfigurationRequestEx( PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PUSBD_INTERFACE_LIST_ENTRY InterfaceList ) { PURB Urb; DWORD UrbSize; DWORD InterfaceCount; for (InterfaceCount = 0; InterfaceList[InterfaceCount].InterfaceDescriptor != NULL; ++InterfaceCount) ; /* Include the NULL entry */ ++InterfaceCount; UrbSize = sizeof(Urb->UrbSelectConfiguration) + (InterfaceCount * sizeof(PUSBD_INTERFACE_LIST_ENTRY)); Urb = ExAllocatePool(NonPagedPool, UrbSize); Urb->UrbSelectConfiguration.Hdr.Function = URB_FUNCTION_SELECT_CONFIGURATION; Urb->UrbSelectConfiguration.Hdr.Length = sizeof(Urb->UrbSelectConfiguration); Urb->UrbSelectConfiguration.ConfigurationDescriptor = ConfigurationDescriptor; memcpy((PVOID)&Urb->UrbSelectConfiguration.Interface, (PVOID)InterfaceList, InterfaceCount * sizeof(PUSBD_INTERFACE_LIST_ENTRY)); return Urb; } /* * @unimplemented */ PURB STDCALL USBD_CreateConfigurationRequest( PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PUSHORT Size ) { return NULL; } /* * @unimplemented */ ULONG STDCALL USBD_GetInterfaceLength( PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, PUCHAR BufferEnd ) { ULONG_PTR Current; PUSB_INTERFACE_DESCRIPTOR CurrentDescriptor = InterfaceDescriptor; DWORD Length = CurrentDescriptor->bLength; // USB_ENDPOINT_DESCRIPTOR_TYPE if (CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) { for (Current = (ULONG_PTR)CurrentDescriptor; Current < (ULONG_PTR)BufferEnd; Current += CurrentDescriptor->bLength) CurrentDescriptor = (PUSB_INTERFACE_DESCRIPTOR)Current; Length += CurrentDescriptor->bLength; } return Length; } /* * @implemented */ PUSB_COMMON_DESCRIPTOR STDCALL USBD_ParseDescriptors( PVOID DescriptorBuffer, ULONG TotalLength, PVOID StartPosition, LONG DescriptorType ) { PUSB_COMMON_DESCRIPTOR PComDes = StartPosition; while(PComDes) { if (PComDes >= (PUSB_COMMON_DESCRIPTOR) ((PLONG)DescriptorBuffer + TotalLength) ) break; if (PComDes->bDescriptorType == DescriptorType) return PComDes; if (PComDes->bLength == 0) break; PComDes = PComDes + PComDes->bLength; } return NULL; } /* * @implemented */ PUSB_INTERFACE_DESCRIPTOR STDCALL USBD_ParseConfigurationDescriptorEx( PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PVOID StartPosition, LONG InterfaceNumber, LONG AlternateSetting, LONG InterfaceClass, LONG InterfaceSubClass, LONG InterfaceProtocol ) { int x = 0; PUSB_INTERFACE_DESCRIPTOR UsbInterfaceDesc = StartPosition; while(UsbInterfaceDesc) { UsbInterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, UsbInterfaceDesc, USB_INTERFACE_DESCRIPTOR_TYPE); if (!UsbInterfaceDesc) break; if(InterfaceNumber != -1) { if(InterfaceNumber != UsbInterfaceDesc->bInterfaceNumber) x = 1; } if(AlternateSetting != -1) { if(AlternateSetting != UsbInterfaceDesc->bAlternateSetting) x = 1; } if(InterfaceClass != -1) { if(InterfaceClass != UsbInterfaceDesc->bInterfaceClass) x = 1; } if(InterfaceSubClass != -1) { if(InterfaceSubClass != UsbInterfaceDesc->bInterfaceSubClass) x = 1; } if(InterfaceProtocol != -1) { if(InterfaceProtocol != UsbInterfaceDesc->bInterfaceProtocol) x = 1; } if (!x) return UsbInterfaceDesc; if (UsbInterfaceDesc->bLength == 0) break; UsbInterfaceDesc = UsbInterfaceDesc + UsbInterfaceDesc->bLength; } return NULL; } /* * @implemented */ PUSB_INTERFACE_DESCRIPTOR STDCALL USBD_ParseConfigurationDescriptor( PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, UCHAR InterfaceNumber, UCHAR AlternateSetting ) { return USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)ConfigurationDescriptor, InterfaceNumber, AlternateSetting, -1, -1, -1); } /* * @implemented */ DWORD STDCALL USBD_GetPdoRegistryParameter( PDEVICE_OBJECT PhysicalDeviceObject, PVOID Parameter, ULONG ParameterLength, PWCHAR KeyName, ULONG KeyNameLength ) { NTSTATUS Status; HANDLE DevInstRegKey; Status = IoOpenDeviceRegistryKey(PhysicalDeviceObject, PLUGPLAY_REGKEY_DRIVER, STANDARD_RIGHTS_ALL, &DevInstRegKey); if (NT_SUCCESS(Status)) { PKEY_VALUE_FULL_INFORMATION FullInfo; UNICODE_STRING ValueName; ULONG Length; RtlInitUnicodeString(&ValueName, KeyName); Length = ParameterLength + KeyNameLength + sizeof(KEY_VALUE_FULL_INFORMATION); FullInfo = ExAllocatePool(PagedPool, Length); if (FullInfo) { Status = ZwQueryValueKey(DevInstRegKey, &ValueName, KeyValueFullInformation, FullInfo, Length, &Length); if (NT_SUCCESS(Status)) { RtlCopyMemory(Parameter, ((PUCHAR)FullInfo) + FullInfo->DataOffset, ParameterLength /*FullInfo->DataLength*/); } ExFreePool(FullInfo); } else Status = STATUS_NO_MEMORY; ZwClose(DevInstRegKey); } return Status; }