From 6e4873691c15bd87fda4cf6aa10d7882b1c435aa Mon Sep 17 00:00:00 2001 From: Damjan Jovanovic Date: Thu, 18 Mar 2010 21:29:01 +0200 Subject: [PATCH] usbd.sys: Add USB descriptor parsing functions. --- dlls/usbd.sys/usbd.c | 77 +++++++++++++++++++++++++++++++++++++ dlls/usbd.sys/usbd.sys.spec | 10 ++--- include/ddk/usbdlib.h | 4 ++ 3 files changed, 86 insertions(+), 5 deletions(-) diff --git a/dlls/usbd.sys/usbd.c b/dlls/usbd.sys/usbd.c index e734acdf7a0..daeb5c0131d 100644 --- a/dlls/usbd.sys/usbd.c +++ b/dlls/usbd.sys/usbd.c @@ -27,10 +27,87 @@ #include "winbase.h" #include "winternl.h" #include "ddk/wdm.h" +#include "ddk/usb.h" +#include "ddk/usbdlib.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(usbd); +PUSB_INTERFACE_DESCRIPTOR WINAPI USBD_ParseConfigurationDescriptorEx( + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, + PVOID StartPosition, LONG InterfaceNumber, + LONG AlternateSetting, LONG InterfaceClass, + LONG InterfaceSubClass, LONG InterfaceProtocol ) +{ + /* http://blogs.msdn.com/usbcoreblog/archive/2009/12/12/ + * what-is-the-right-way-to-validate-and-parse-configuration-descriptors.aspx + */ + + PUSB_INTERFACE_DESCRIPTOR interface; + + TRACE( "(%p, %p, %d, %d, %d, %d, %d)\n", ConfigurationDescriptor, + StartPosition, InterfaceNumber, AlternateSetting, + InterfaceClass, InterfaceSubClass, InterfaceProtocol ); + + interface = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors( + ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, + StartPosition, USB_INTERFACE_DESCRIPTOR_TYPE ); + while (interface != NULL) + { + if ((InterfaceNumber == -1 || interface->bInterfaceNumber == InterfaceNumber) && + (AlternateSetting == -1 || interface->bAlternateSetting == AlternateSetting) && + (InterfaceClass == -1 || interface->bInterfaceClass == InterfaceClass) && + (InterfaceSubClass == -1 || interface->bInterfaceSubClass == InterfaceSubClass) && + (InterfaceProtocol == -1 || interface->bInterfaceProtocol == InterfaceProtocol)) + { + return interface; + } + interface = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors( + ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, + interface + 1, USB_INTERFACE_DESCRIPTOR_TYPE ); + } + return NULL; +} + +PUSB_COMMON_DESCRIPTOR WINAPI USBD_ParseDescriptors( + PVOID DescriptorBuffer, + ULONG TotalLength, + PVOID StartPosition, + LONG DescriptorType ) +{ + PUSB_COMMON_DESCRIPTOR common; + + TRACE( "(%p, %u, %p, %d)\n", DescriptorBuffer, TotalLength, StartPosition, DescriptorType ); + + for (common = (PUSB_COMMON_DESCRIPTOR)DescriptorBuffer; + ((char*)common) + sizeof(USB_COMMON_DESCRIPTOR) <= ((char*)DescriptorBuffer) + TotalLength; + common = (PUSB_COMMON_DESCRIPTOR)(((char*)common) + common->bLength)) + { + if (StartPosition <= (PVOID)common && common->bDescriptorType == DescriptorType) + return common; + } + return NULL; +} + +ULONG WINAPI USBD_GetInterfaceLength( + PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, + PUCHAR BufferEnd ) +{ + PUSB_COMMON_DESCRIPTOR common; + ULONG total = InterfaceDescriptor->bLength; + + TRACE( "(%p, %p)\n", InterfaceDescriptor, BufferEnd ); + + for (common = (PUSB_COMMON_DESCRIPTOR)(InterfaceDescriptor + 1); + (((PUCHAR)common) + sizeof(USB_COMMON_DESCRIPTOR)) <= BufferEnd && + common->bDescriptorType != USB_INTERFACE_DESCRIPTOR_TYPE; + common = (PUSB_COMMON_DESCRIPTOR)(((char*)common) + common->bLength)) + { + total += common->bLength; + } + return total; +} + NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) { TRACE( "(%p, %s)\n", driver, debugstr_w(path->Buffer) ); diff --git a/dlls/usbd.sys/usbd.sys.spec b/dlls/usbd.sys/usbd.sys.spec index c8f1d687e44..47e0bdb0bc5 100644 --- a/dlls/usbd.sys/usbd.sys.spec +++ b/dlls/usbd.sys/usbd.sys.spec @@ -1,6 +1,6 @@ @ stub USBD_CreateConfigurationRequestEx -@ stub USBD_ParseConfigurationDescriptorEx -@ stub USBD_ParseDescriptors +@ stdcall USBD_ParseConfigurationDescriptorEx(ptr ptr long long long long long) +@ stdcall USBD_ParseDescriptors(ptr long ptr long) @ stub USBD_AllocateDeviceName @ stub USBD_CalculateUsbBandwidth @ stub USBD_CompleteRequest @@ -14,15 +14,15 @@ @ stub USBD_FreeDeviceMutex @ stub USBD_FreeDeviceName @ stub USBD_GetDeviceInformation -@ stub USBD_GetInterfaceLength +@ stdcall USBD_GetInterfaceLength(ptr ptr) @ stub USBD_GetPdoRegistryParameter @ stub USBD_GetSuspendPowerState @ stub USBD_GetUSBDIVersion @ stub USBD_InitializeDevice @ stub USBD_MakePdoName @ stub USBD_ParseConfigurationDescriptor -@ stub _USBD_ParseConfigurationDescriptorEx@28 -@ stub _USBD_ParseDescriptors@16 +@ stdcall _USBD_ParseConfigurationDescriptorEx@28(ptr ptr long long long long long) USBD_ParseConfigurationDescriptorEx +@ stdcall _USBD_ParseDescriptors@16(ptr long ptr long) USBD_ParseDescriptors @ stub USBD_QueryBusTime @ stub USBD_RegisterHcDeviceCapabilities @ stub USBD_RegisterHcFilter diff --git a/include/ddk/usbdlib.h b/include/ddk/usbdlib.h index c0adc46cac0..ce3cc862d10 100644 --- a/include/ddk/usbdlib.h +++ b/include/ddk/usbdlib.h @@ -25,4 +25,8 @@ typedef struct _USBD_INTERFACE_LIST_ENTRY { } USBD_INTERFACE_LIST_ENTRY; typedef struct _USBD_INTERFACE_LIST_ENTRY *PUSBD_INTERFACE_LIST_ENTRY; +PUSB_INTERFACE_DESCRIPTOR WINAPI USBD_ParseConfigurationDescriptorEx(PUSB_CONFIGURATION_DESCRIPTOR,PVOID,LONG,LONG,LONG,LONG,LONG); +ULONG WINAPI USBD_GetInterfaceLength(PUSB_INTERFACE_DESCRIPTOR,PUCHAR); +PUSB_COMMON_DESCRIPTOR WINAPI USBD_ParseDescriptors(PVOID,ULONG,PVOID,LONG); + #endif