Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689/* * 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 <xnavara@volny.cz> * Michael Martin <michael.martin@reactos.org> * */
/* * Universal Serial Bus Driver/Helper Library * * Written by Filip Navara <xnavara@volny.cz> * * Notes: * This driver was obsoleted in Windows XP and most functions * became pure stubs. But some of them were retained for backward * compatibility 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) */
#define _USBD_#define NDEBUG#include <ntddk.h>#include <usbdi.h>#include <usbdlib.h>#include <debug.h>#ifndef PLUGPLAY_REGKEY_DRIVER#define PLUGPLAY_REGKEY_DRIVER 2#endif
NTSTATUS NTAPIDriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath){ return STATUS_SUCCESS;}
/* * @implemented */ULONG NTAPIDllInitialize(ULONG Unknown){ return 0;}
/* * @implemented */ULONG NTAPIDllUnload(VOID){ return 0;}
/* * @implemented */PVOID NTAPIUSBD_Debug_GetHeap(ULONG Unknown1, POOL_TYPE PoolType, ULONG NumberOfBytes, ULONG Tag){ return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);}
/* * @implemented */VOID NTAPIUSBD_Debug_RetHeap(PVOID Heap, ULONG Unknown2, ULONG Unknown3){ ExFreePool(Heap);}
/* * @implemented */VOID NTAPIUSBD_Debug_LogEntry(PCHAR Name, ULONG_PTR Info1, ULONG_PTR Info2, ULONG_PTR Info3){}
/* * @implemented */PVOID NTAPIUSBD_AllocateDeviceName(ULONG Unknown){ UNIMPLEMENTED; return NULL;}
/* * @implemented */ULONG NTAPIUSBD_CalculateUsbBandwidth( ULONG MaxPacketSize, UCHAR EndpointType, BOOLEAN LowSpeed ){ ULONG OverheadTable[] = { 0x00, /* UsbdPipeTypeControl */ 0x09, /* UsbdPipeTypeIsochronous */ 0x00, /* UsbdPipeTypeBulk */ 0x0d /* UsbdPipeTypeInterrupt */ }; ULONG Result;
if (OverheadTable[EndpointType] != 0) { Result = ((MaxPacketSize + OverheadTable[EndpointType]) * 8 * 7) / 6; if (LowSpeed) return Result << 3; return Result; } return 0;}
/* * @implemented */ULONG NTAPIUSBD_Dispatch(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, ULONG Unknown4){ UNIMPLEMENTED; return 1;}
/* * @implemented */VOID NTAPIUSBD_FreeDeviceMutex(PVOID Unknown){ UNIMPLEMENTED;}
/* * @implemented */VOID NTAPIUSBD_FreeDeviceName(PVOID Unknown){ UNIMPLEMENTED;}
/* * @implemented */VOID NTAPIUSBD_WaitDeviceMutex(PVOID Unknown){ UNIMPLEMENTED;}
/* * @implemented */ULONG NTAPIUSBD_GetSuspendPowerState(ULONG Unknown1){ UNIMPLEMENTED; return 0;}
/* * @implemented */NTSTATUS NTAPIUSBD_InitializeDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, ULONG Unknown4, ULONG Unknown5, ULONG Unknown6){ UNIMPLEMENTED; return STATUS_NOT_SUPPORTED;}
/* * @implemented */NTSTATUS NTAPIUSBD_RegisterHostController(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, ULONG Unknown4, ULONG Unknown5, ULONG Unknown6, ULONG Unknown7, ULONG Unknown8, ULONG Unknown9, ULONG Unknown10){ UNIMPLEMENTED; return STATUS_NOT_SUPPORTED;}
/* * @implemented */NTSTATUS NTAPIUSBD_GetDeviceInformation(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3){ UNIMPLEMENTED; return STATUS_NOT_SUPPORTED;}
/* * @implemented */NTSTATUS NTAPIUSBD_CreateDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, ULONG Unknown4, ULONG Unknown5){ UNIMPLEMENTED; return STATUS_NOT_SUPPORTED;}
/* * @implemented */NTSTATUS NTAPIUSBD_RemoveDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3){ UNIMPLEMENTED; return STATUS_NOT_SUPPORTED;}
/* * @implemented */VOID NTAPIUSBD_CompleteRequest(ULONG Unknown1, ULONG Unknown2){ UNIMPLEMENTED;}
/* * @implemented */VOID NTAPIUSBD_RegisterHcFilter( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT FilterDeviceObject ){ UNIMPLEMENTED;}
/* * @implemented */VOID NTAPIUSBD_SetSuspendPowerState(ULONG Unknown1, ULONG Unknown2){ UNIMPLEMENTED;}
/* * @implemented */NTSTATUS NTAPIUSBD_MakePdoName(ULONG Unknown1, ULONG Unknown2){ UNIMPLEMENTED; return STATUS_NOT_SUPPORTED;}
/* * @implemented */NTSTATUS NTAPIUSBD_QueryBusTime( PDEVICE_OBJECT RootHubPdo, PULONG CurrentFrame ){ UNIMPLEMENTED; return STATUS_NOT_SUPPORTED;}
/* * @implemented */VOID NTAPIUSBD_GetUSBDIVersion( PUSBD_VERSION_INFORMATION Version ){ if (Version != NULL) { Version->USBDI_Version = USBDI_VERSION; Version->Supported_USB_Version = 0x200; }}
/* * @implemented */NTSTATUS NTAPIUSBD_RestoreDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3){ UNIMPLEMENTED; return STATUS_NOT_SUPPORTED;}
/* * @implemented */VOID NTAPIUSBD_RegisterHcDeviceCapabilities(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3){ UNIMPLEMENTED;}
/* * @implemented */PURB NTAPIUSBD_CreateConfigurationRequestEx( PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PUSBD_INTERFACE_LIST_ENTRY InterfaceList ){ PURB Urb; ULONG UrbSize = 0; ULONG InterfaceCount = 0, PipeCount = 0; ULONG InterfaceNumber, EndPointNumber; PUSBD_INTERFACE_INFORMATION InterfaceInfo;
while(InterfaceList[InterfaceCount].InterfaceDescriptor) { // pipe count PipeCount += InterfaceList[InterfaceCount].InterfaceDescriptor->bNumEndpoints;
// interface count InterfaceCount++; }
// size of urb UrbSize = GET_SELECT_CONFIGURATION_REQUEST_SIZE(InterfaceCount, PipeCount);
// allocate urb Urb = ExAllocatePool(NonPagedPool, UrbSize); if (!Urb) { // no memory return NULL; }
// zero urb RtlZeroMemory(Urb, UrbSize);
// init urb header Urb->UrbSelectConfiguration.Hdr.Function = URB_FUNCTION_SELECT_CONFIGURATION; Urb->UrbSelectConfiguration.Hdr.Length = UrbSize; Urb->UrbSelectConfiguration.ConfigurationDescriptor = ConfigurationDescriptor;
// init interface information InterfaceInfo = &Urb->UrbSelectConfiguration.Interface; for (InterfaceNumber = 0; InterfaceNumber < InterfaceCount; InterfaceNumber++) { // init interface info InterfaceList[InterfaceNumber].Interface = InterfaceInfo; InterfaceInfo->InterfaceNumber = InterfaceList[InterfaceNumber].InterfaceDescriptor->bInterfaceNumber; InterfaceInfo->AlternateSetting = InterfaceList[InterfaceNumber].InterfaceDescriptor->bAlternateSetting; InterfaceInfo->NumberOfPipes = InterfaceList[InterfaceNumber].InterfaceDescriptor->bNumEndpoints;
// store length InterfaceInfo->Length = GET_USBD_INTERFACE_SIZE(InterfaceList[InterfaceNumber].InterfaceDescriptor->bNumEndpoints);
// sanity check //C_ASSERT(FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes) == 16);
for (EndPointNumber = 0; EndPointNumber < InterfaceInfo->NumberOfPipes; EndPointNumber++) { // init max transfer size InterfaceInfo->Pipes[EndPointNumber].MaximumTransferSize = PAGE_SIZE; }
// next interface info InterfaceInfo = (PUSBD_INTERFACE_INFORMATION) ((ULONG_PTR)InterfaceInfo + InterfaceInfo->Length); }
return Urb;}
/* * @implemented */PURB NTAPIUSBD_CreateConfigurationRequest( PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PUSHORT Size ){ /* WindowsXP returns NULL */ return NULL;}
/* * @implemented */ULONG NTAPIUSBD_GetInterfaceLength( PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, PUCHAR BufferEnd ){ ULONG_PTR Current; PUSB_INTERFACE_DESCRIPTOR CurrentDescriptor = InterfaceDescriptor; ULONG Length = 0; BOOLEAN InterfaceFound = FALSE;
for (Current = (ULONG_PTR)CurrentDescriptor; Current < (ULONG_PTR)BufferEnd; Current += CurrentDescriptor->bLength) { CurrentDescriptor = (PUSB_INTERFACE_DESCRIPTOR)Current;
if ((CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) && (InterfaceFound)) break; else if (CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) InterfaceFound = TRUE;
Length += CurrentDescriptor->bLength; }
return Length;}
/* * @implemented */PUSB_COMMON_DESCRIPTOR NTAPIUSBD_ParseDescriptors( PVOID DescriptorBuffer, ULONG TotalLength, PVOID StartPosition, LONG DescriptorType ){ PUSB_COMMON_DESCRIPTOR CommonDescriptor;
/* use start position */ CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)StartPosition;
/* find next available descriptor */ while(CommonDescriptor) { if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)DescriptorBuffer + TotalLength)) { /* end reached */ DPRINT("End reached %p\n", CommonDescriptor); return NULL; }
DPRINT("CommonDescriptor Type %x Length %x\n", CommonDescriptor->bDescriptorType, CommonDescriptor->bLength);
/* is the requested one */ if (CommonDescriptor->bDescriptorType == DescriptorType) { /* it is */ return CommonDescriptor; }
if (CommonDescriptor->bLength == 0) { /* invalid usb descriptor */ return NULL; }
/* move to next descriptor */ CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength); }
/* no descriptor found */ return NULL;}
/* * @implemented */PUSB_INTERFACE_DESCRIPTOR NTAPIUSBD_ParseConfigurationDescriptorEx( PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PVOID StartPosition, LONG InterfaceNumber, LONG AlternateSetting, LONG InterfaceClass, LONG InterfaceSubClass, LONG InterfaceProtocol ){ BOOLEAN Found; PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
/* set to start position */ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)StartPosition;
DPRINT("USBD_ParseConfigurationDescriptorEx\n"); DPRINT("ConfigurationDescriptor %p Length %lu\n", ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength); DPRINT("CurrentOffset %p Offset %lu\n", StartPosition, ((ULONG_PTR)StartPosition - (ULONG_PTR)ConfigurationDescriptor));
while(InterfaceDescriptor) { /* get interface descriptor */ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, InterfaceDescriptor, USB_INTERFACE_DESCRIPTOR_TYPE); if (!InterfaceDescriptor) { /* no more descriptors available */ break; }
DPRINT("InterfaceDescriptor %p InterfaceNumber %x AlternateSetting %x Length %lu\n", InterfaceDescriptor, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, InterfaceDescriptor->bLength);
/* set found */ Found = TRUE;
/* is there an interface number provided */ if(InterfaceNumber != -1) { if(InterfaceNumber != InterfaceDescriptor->bInterfaceNumber) { /* interface number does not match */ Found = FALSE; } }
/* is there an alternate setting provided */ if(AlternateSetting != -1) { if(AlternateSetting != InterfaceDescriptor->bAlternateSetting) { /* alternate setting does not match */ Found = FALSE; } }
/* match on interface class */ if(InterfaceClass != -1) { if(InterfaceClass != InterfaceDescriptor->bInterfaceClass) { /* no match with interface class criteria */ Found = FALSE; } }
/* match on interface sub class */ if(InterfaceSubClass != -1) { if(InterfaceSubClass != InterfaceDescriptor->bInterfaceSubClass) { /* no interface sub class match */ Found = FALSE; } }
/* interface protocol criteria */ if(InterfaceProtocol != -1) { if(InterfaceProtocol != InterfaceDescriptor->bInterfaceProtocol) { /* no interface protocol match */ Found = FALSE; } }
if (Found) { /* the chosen one */ return InterfaceDescriptor; }
/* sanity check */ ASSERT(InterfaceDescriptor->bLength);
/* move to next descriptor */ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength); }
DPRINT("No Descriptor With InterfaceNumber %ld AlternateSetting %ld InterfaceClass %ld InterfaceSubClass %ld InterfaceProtocol %ld found\n", InterfaceNumber, AlternateSetting, InterfaceClass, InterfaceSubClass, InterfaceProtocol);
return NULL;}
/* * @implemented */PUSB_INTERFACE_DESCRIPTOR NTAPIUSBD_ParseConfigurationDescriptor( PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, UCHAR InterfaceNumber, UCHAR AlternateSetting ){ return USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, (PVOID)ConfigurationDescriptor, InterfaceNumber, AlternateSetting, -1, -1, -1);}
/* * @implemented */ULONG NTAPIUSBD_GetPdoRegistryParameter( PDEVICE_OBJECT PhysicalDeviceObject, PVOID Parameter, ULONG ParameterLength, PWCHAR KeyName, ULONG KeyNameLength ){ NTSTATUS Status; HANDLE DevInstRegKey;
/* Open the device key */ Status = IoOpenDeviceRegistryKey(PhysicalDeviceObject, PLUGPLAY_REGKEY_DEVICE, STANDARD_RIGHTS_ALL, &DevInstRegKey); if (NT_SUCCESS(Status)) { PKEY_VALUE_PARTIAL_INFORMATION PartialInfo; UNICODE_STRING ValueName; ULONG Length;
/* Initialize the unicode string based on caller data */ ValueName.Buffer = KeyName; ValueName.Length = ValueName.MaximumLength = KeyNameLength;
Length = ParameterLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION); PartialInfo = ExAllocatePool(PagedPool, Length); if (PartialInfo) { Status = ZwQueryValueKey(DevInstRegKey, &ValueName, KeyValuePartialInformation, PartialInfo, Length, &Length); if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) { /* The caller doesn't want all the data */ ExFreePool(PartialInfo); PartialInfo = ExAllocatePool(PagedPool, Length); if (PartialInfo) { Status = ZwQueryValueKey(DevInstRegKey, &ValueName, KeyValuePartialInformation, PartialInfo, Length, &Length); } else { Status = STATUS_NO_MEMORY; } }
if (NT_SUCCESS(Status)) { /* Compute the length to copy back */ if (ParameterLength < PartialInfo->DataLength) Length = ParameterLength; else Length = PartialInfo->DataLength;
RtlCopyMemory(Parameter, PartialInfo->Data, Length); }
if (PartialInfo) { ExFreePool(PartialInfo); } } else Status = STATUS_NO_MEMORY; ZwClose(DevInstRegKey); } return Status;}