Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559/* * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface * LICENSE: GPL - See COPYING in the top level directory * FILE: drivers/usb/usbccgp/descriptor.c * PURPOSE: USB device driver. * PROGRAMMERS: * Michael Martin (michael.martin@reactos.org) * Johannes Anderwald (johannes.anderwald@reactos.org) * Cameron Gutman */
#include "usbccgp.h"
#define NDEBUG#include <debug.h>
NTSTATUSNTAPIUSBCCGP_GetDescriptor( IN PDEVICE_OBJECT DeviceObject, IN UCHAR DescriptorType, IN ULONG DescriptorLength, IN UCHAR DescriptorIndex, IN LANGID LanguageId, OUT PVOID *OutDescriptor){ PURB Urb; NTSTATUS Status; PVOID Descriptor;
// // sanity checks // ASSERT(DeviceObject); ASSERT(OutDescriptor); ASSERT(DescriptorLength);
// // first allocate descriptor buffer // Descriptor = AllocateItem(NonPagedPool, DescriptorLength); if (!Descriptor) { // // no memory // return STATUS_INSUFFICIENT_RESOURCES; }
// // allocate urb // Urb = (PURB) AllocateItem(NonPagedPool, sizeof(URB)); if (!Urb) { // // no memory // FreeItem(Descriptor); return STATUS_INSUFFICIENT_RESOURCES; }
// // initialize urb // UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), DescriptorType, DescriptorIndex, LanguageId, Descriptor, NULL, DescriptorLength, NULL);
// // submit urb // Status = USBCCGP_SyncUrbRequest(DeviceObject, Urb);
// // free urb // FreeItem(Urb);
if (NT_SUCCESS(Status)) { // // store result // *OutDescriptor = Descriptor; }
// // done // return Status;}
NTSTATUSNTAPIUSBCCGP_GetStringDescriptor( IN PDEVICE_OBJECT DeviceObject, IN ULONG DescriptorLength, IN UCHAR DescriptorIndex, IN LANGID LanguageId, OUT PVOID *OutDescriptor){ NTSTATUS Status; PUSB_STRING_DESCRIPTOR StringDescriptor; ULONG Size; PVOID Buffer;
// retrieve descriptor Status = USBCCGP_GetDescriptor(DeviceObject, USB_STRING_DESCRIPTOR_TYPE, DescriptorLength, DescriptorIndex, LanguageId, OutDescriptor); if (!NT_SUCCESS(Status)) { // failed return Status; }
// get descriptor structure StringDescriptor = (PUSB_STRING_DESCRIPTOR)*OutDescriptor;
// sanity check ASSERT(StringDescriptor->bLength < DescriptorLength - 2);
if (StringDescriptor->bLength == 2) { // invalid descriptor FreeItem(StringDescriptor); return STATUS_DEVICE_DATA_ERROR; }
// calculate size Size = StringDescriptor->bLength + sizeof(WCHAR);
// allocate buffer Buffer = AllocateItem(NonPagedPool, Size); if (!Buffer) { // no memory FreeItem(StringDescriptor); return STATUS_INSUFFICIENT_RESOURCES; }
// copy result RtlCopyMemory(Buffer, StringDescriptor->bString, Size - FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString));
// free buffer FreeItem(StringDescriptor);
// store result *OutDescriptor = (PVOID)Buffer; return STATUS_SUCCESS;}
NTSTATUSUSBCCGP_GetDescriptors( IN PDEVICE_OBJECT DeviceObject){ NTSTATUS Status; PFDO_DEVICE_EXTENSION DeviceExtension; USHORT DescriptorLength;
// // get device extension // DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
// // first get device descriptor // Status = USBCCGP_GetDescriptor(DeviceExtension->NextDeviceObject, USB_DEVICE_DESCRIPTOR_TYPE, sizeof(USB_DEVICE_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->DeviceDescriptor); if (!NT_SUCCESS(Status)) { // // failed to get device descriptor // DeviceExtension->DeviceDescriptor = NULL; return Status; }
// // now get basic configuration descriptor // Status = USBCCGP_GetDescriptor(DeviceExtension->NextDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, sizeof(USB_CONFIGURATION_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor); if (!NT_SUCCESS(Status)) { // // failed to get configuration descriptor // FreeItem(DeviceExtension->DeviceDescriptor); DeviceExtension->DeviceDescriptor = NULL; return Status; }
// // backup length // DescriptorLength = DeviceExtension->ConfigurationDescriptor->wTotalLength;
// // release basic descriptor // FreeItem(DeviceExtension->ConfigurationDescriptor); DeviceExtension->ConfigurationDescriptor = NULL;
// // allocate full descriptor // Status = USBCCGP_GetDescriptor(DeviceExtension->NextDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, DescriptorLength, 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor); if (!NT_SUCCESS(Status)) { // // failed to get configuration descriptor // FreeItem(DeviceExtension->DeviceDescriptor); DeviceExtension->DeviceDescriptor = NULL; return Status; } return Status;}
NTSTATUSAllocateInterfaceDescriptorsArray( IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, OUT PUSB_INTERFACE_DESCRIPTOR **OutArray){ PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; ULONG Count = 0; PUSB_INTERFACE_DESCRIPTOR *Array;
// // allocate array // Array = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * ConfigurationDescriptor->bNumInterfaces); if (!Array) return STATUS_INSUFFICIENT_RESOURCES;
// // enumerate all interfaces // Count = 0; do { // // find next descriptor // InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, Count, 0, -1, -1, -1); if (!InterfaceDescriptor) break;
// // store descriptor // Array[Count] = InterfaceDescriptor; Count++;
}while(TRUE);
// // store result // *OutArray = Array;
// // done // return STATUS_SUCCESS;}
VOIDDumpFullConfigurationDescriptor( IN PFDO_DEVICE_EXTENSION FDODeviceExtension, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor){ PUSB_COMMON_DESCRIPTOR Descriptor;
Descriptor = (PUSB_COMMON_DESCRIPTOR)ConfigurationDescriptor;
DbgPrint("Bogus ConfigurationDescriptor Found\n"); DbgPrint("InterfaceCount %x\n", ConfigurationDescriptor->bNumInterfaces);
do { if (((ULONG_PTR)Descriptor) >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength)) break;
DbgPrint("Descriptor Type %x Length %lu Offset %lu\n", Descriptor->bDescriptorType, Descriptor->bLength, ((ULONG_PTR)Descriptor - (ULONG_PTR)ConfigurationDescriptor));
// check for invalid descriptors if (!Descriptor->bLength) { DbgPrint("Bogus Descriptor!!!\n"); break; }
// advance to next descriptor Descriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)Descriptor + Descriptor->bLength);
}while(TRUE);
}
NTSTATUSNTAPIUSBCCGP_ScanConfigurationDescriptor( IN OUT PFDO_DEVICE_EXTENSION FDODeviceExtension, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor){ PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; ULONG InterfaceIndex = 0; ULONG DescriptorCount;
// // sanity checks // ASSERT(ConfigurationDescriptor); ASSERT(ConfigurationDescriptor->bNumInterfaces);
// // count all interface descriptors // DescriptorCount = ConfigurationDescriptor->bNumInterfaces; if (DescriptorCount == 0) { DPRINT1("[USBCCGP] DescriptorCount is zero\n"); return STATUS_INVALID_PARAMETER; }
// // allocate array holding the interface descriptors // FDODeviceExtension->InterfaceList = AllocateItem(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (DescriptorCount + 1)); if (!FDODeviceExtension->InterfaceList) { // // no memory // return STATUS_INSUFFICIENT_RESOURCES; }
// // reset interface list count // FDODeviceExtension->InterfaceListCount = 0;
do { // // parse configuration descriptor // InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, InterfaceIndex, -1, -1, -1, -1); if (InterfaceDescriptor) { // // store in interface list // ASSERT(FDODeviceExtension->InterfaceListCount < DescriptorCount); FDODeviceExtension->InterfaceList[FDODeviceExtension->InterfaceListCount].InterfaceDescriptor = InterfaceDescriptor; FDODeviceExtension->InterfaceListCount++; } else { DumpConfigurationDescriptor(ConfigurationDescriptor); DumpFullConfigurationDescriptor(FDODeviceExtension, ConfigurationDescriptor);
// // see issue // CORE-6574 Test 3 (USB Web Cam) // if (FDODeviceExtension->DeviceDescriptor && FDODeviceExtension->DeviceDescriptor->idVendor == 0x0458 && FDODeviceExtension->DeviceDescriptor->idProduct == 0x705f) ASSERT(FALSE); }
// // move to next interface // InterfaceIndex++;
}while(InterfaceIndex < DescriptorCount);
// // sanity check // ASSERT(FDODeviceExtension->InterfaceListCount);
// // done // return STATUS_SUCCESS;}
VOIDDumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor){ DbgPrint("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor); DbgPrint("bLength %x\n", ConfigurationDescriptor->bLength); DbgPrint("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType); DbgPrint("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength); DbgPrint("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces); DbgPrint("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue); DbgPrint("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration); DbgPrint("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes); DbgPrint("MaxPower %x\n", ConfigurationDescriptor->MaxPower);}
NTSTATUSUSBCCGP_SelectInterface( IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension, IN ULONG InterfaceIndex){ NTSTATUS Status; PURB Urb;
// // allocate urb // Urb = AllocateItem(NonPagedPool, GET_SELECT_INTERFACE_REQUEST_SIZE(DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bNumEndpoints)); if (!Urb) { // // no memory // return STATUS_INSUFFICIENT_RESOURCES; }
// // now prepare interface urb // UsbBuildSelectInterfaceRequest(Urb, GET_SELECT_INTERFACE_REQUEST_SIZE(DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bNumEndpoints), DeviceExtension->ConfigurationHandle, DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bInterfaceNumber, DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bAlternateSetting);
// // now select the interface // Status = USBCCGP_SyncUrbRequest(DeviceExtension->NextDeviceObject, Urb);
// // did it succeed // if (NT_SUCCESS(Status)) { // // update configuration info // ASSERT(Urb->UrbSelectInterface.Interface.Length == DeviceExtension->InterfaceList[InterfaceIndex].Interface->Length); RtlCopyMemory(DeviceExtension->InterfaceList[InterfaceIndex].Interface, &Urb->UrbSelectInterface.Interface, Urb->UrbSelectInterface.Interface.Length); }
// // free urb // FreeItem(Urb);
// // done // return Status;}
NTSTATUSUSBCCGP_SelectConfiguration( IN PDEVICE_OBJECT DeviceObject, IN PFDO_DEVICE_EXTENSION DeviceExtension){ PUSBD_INTERFACE_INFORMATION InterfaceInformation; NTSTATUS Status; PURB Urb; ULONG Index;
// // now scan configuration descriptors // Status = USBCCGP_ScanConfigurationDescriptor(DeviceExtension, DeviceExtension->ConfigurationDescriptor); if (!NT_SUCCESS(Status)) { // // failed to scan // return Status; }
// // now allocate the urb // Urb = USBD_CreateConfigurationRequestEx(DeviceExtension->ConfigurationDescriptor, DeviceExtension->InterfaceList); if (!Urb) { // // no memory // return STATUS_INSUFFICIENT_RESOURCES; }
// // submit urb // Status = USBCCGP_SyncUrbRequest(DeviceExtension->NextDeviceObject, Urb); if (!NT_SUCCESS(Status)) { // // failed to set configuration // DPRINT1("USBCCGP_SyncUrbRequest failed to set interface %x\n", Status); ExFreePool(Urb); return Status; }
// // get interface information // InterfaceInformation = &Urb->UrbSelectConfiguration.Interface; for(Index = 0; Index < DeviceExtension->InterfaceListCount; Index++) { // // allocate buffer to store interface information // DeviceExtension->InterfaceList[Index].Interface = AllocateItem(NonPagedPool, InterfaceInformation->Length); if (!DeviceExtension->InterfaceList[Index].Interface) { // // no memory // return STATUS_INSUFFICIENT_RESOURCES; }
// // copy interface information // RtlCopyMemory(DeviceExtension->InterfaceList[Index].Interface, InterfaceInformation, InterfaceInformation->Length);
// // move to next interface // InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + InterfaceInformation->Length); }
// // store pipe handle // DeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
// // free interface list & urb // ExFreePool(Urb);
// // done // return Status;}