From aa485d63fdf50a3ddda56859556701a5df563fe2 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Wed, 1 Feb 2012 16:59:13 +0000 Subject: [PATCH] [USBD] - In 2012 a long protected natural resource for bugs was shutdown due to popular usb device support demand - Fix length check in USBD_ParseDescriptors. (PLONG)Descriptor + TotalLength is not the length of the configuration descriptor but twice the configuration descriptor - Reset found variable in the loop. This fixes finding of interfaces which are not the first one in the configuration descriptor - Again moving to next usb descriptor was broken. UsbDeviceDescriptor = UsbDeviceDescriptor + UsbDeviceDescriptor->bLength does not move to the next but to next XX descriprors specified by bLength - Introduced in rev 17382 (14/08/2005) svn path=/branches/usb-bringup-trunk/; revision=55370 --- drivers/usb/usbd/usbd.c | 131 +++++++++++++++++++++++++++++++--------- 1 file changed, 103 insertions(+), 28 deletions(-) diff --git a/drivers/usb/usbd/usbd.c b/drivers/usb/usbd/usbd.c index a62ed93565d..4cdbb31d228 100644 --- a/drivers/usb/usbd/usbd.c +++ b/drivers/usb/usbd/usbd.c @@ -32,9 +32,9 @@ * USBD_GetPdoRegistryParameters (implemented) */ -#include +#include #include - +#include #ifndef PLUGPLAY_REGKEY_DRIVER #define PLUGPLAY_REGKEY_DRIVER 2 #endif @@ -324,8 +324,8 @@ USBD_CreateConfigurationRequestEx( InterfaceList[InterfaceCount].InterfaceDescriptor != NULL; InterfaceCount++) { - UrbSize += FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes); - UrbSize += (InterfaceList[InterfaceCount].InterfaceDescriptor->bNumEndpoints) * sizeof(USBD_PIPE_INFORMATION); + UrbSize += sizeof(USBD_INTERFACE_INFORMATION); + UrbSize += (InterfaceList[InterfaceCount].InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USBD_PIPE_INFORMATION); } UrbSize += sizeof(URB) + sizeof(USBD_INTERFACE_INFORMATION); @@ -410,16 +410,39 @@ USBD_ParseDescriptors( LONG DescriptorType ) { - PUSB_COMMON_DESCRIPTOR PComDes = StartPosition; + PUSB_COMMON_DESCRIPTOR CommonDescriptor; - while(PComDes) + /* use start position */ + CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)StartPosition; + + + /* find next available descriptor */ + while(CommonDescriptor) { - if (PComDes >= (PUSB_COMMON_DESCRIPTOR) - ((PLONG)DescriptorBuffer + TotalLength) ) break; - if (PComDes->bDescriptorType == DescriptorType) return PComDes; - if (PComDes->bLength == 0) break; - PComDes = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)PComDes + PComDes->bLength); + if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)DescriptorBuffer + TotalLength)) + { + /* end reached */ + DPRINT1("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; + } + + /* sanity check */ + ASSERT(CommonDescriptor->bLength); + + /* move to next descriptor */ + CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength); } + + /* no descriptor found */ return NULL; } @@ -438,45 +461,97 @@ USBD_ParseConfigurationDescriptorEx( LONG InterfaceProtocol ) { - int x = 0; - PUSB_INTERFACE_DESCRIPTOR UsbInterfaceDesc = StartPosition; + BOOLEAN Found; + PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; - while(UsbInterfaceDesc) + /* 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) { - UsbInterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) - USBD_ParseDescriptors(ConfigurationDescriptor, - ConfigurationDescriptor->wTotalLength, - UsbInterfaceDesc, - USB_INTERFACE_DESCRIPTOR_TYPE); + /* get interface descriptor */ + InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, InterfaceDescriptor, USB_INTERFACE_DESCRIPTOR_TYPE); + if (!InterfaceDescriptor) + { + /* no more descriptors available */ + break; + } - if (!UsbInterfaceDesc) 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 != UsbInterfaceDesc->bInterfaceNumber) x = 1; + if(InterfaceNumber != InterfaceDescriptor->bInterfaceNumber) + { + /* interface number does not match */ + Found = FALSE; + } } + + /* is there an alternate setting provided */ if(AlternateSetting != -1) { - if(AlternateSetting != UsbInterfaceDesc->bAlternateSetting) x = 1; + if(AlternateSetting != InterfaceDescriptor->bAlternateSetting) + { + /* alternate setting does not match */ + Found = FALSE; + } } + + /* match on interface class */ if(InterfaceClass != -1) { - if(InterfaceClass != UsbInterfaceDesc->bInterfaceClass) x = 1; + if(InterfaceClass != InterfaceDescriptor->bInterfaceClass) + { + /* no match with interface class criteria */ + Found = FALSE; + } } + + /* match on interface sub class */ if(InterfaceSubClass != -1) { - if(InterfaceSubClass != UsbInterfaceDesc->bInterfaceSubClass) x = 1; + if(InterfaceSubClass != InterfaceDescriptor->bInterfaceSubClass) + { + /* no interface sub class match */ + Found = FALSE; + } } + + /* interface protocol criteria */ if(InterfaceProtocol != -1) { - if(InterfaceProtocol != UsbInterfaceDesc->bInterfaceProtocol) x = 1; + if(InterfaceProtocol != InterfaceDescriptor->bInterfaceProtocol) + { + /* no interface protocol match */ + Found = FALSE; + } } - if (!x) return UsbInterfaceDesc; + if (Found) + { + /* the choosen one */ + return InterfaceDescriptor; + } - if (UsbInterfaceDesc->bLength == 0) break; - UsbInterfaceDesc = UsbInterfaceDesc + UsbInterfaceDesc->bLength; + /* 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; }