// Get the alternate setting number of the interface. int UsbDev::GetNoOfAlternateSetting(UCHAR InterfaceNo) { PUSB_INTERFACE_DESCRIPTOR pAlternateSetting = NULL; int i; for(i=0;;i++) {// for loop i if (!m_pConfigDesc) break; pAlternateSetting = (PUSB_INTERFACE_DESCRIPTOR)USBD_ParseConfigurationDescriptorEx( m_pConfigDesc[m_UsbConfigurationNo],// Pointer to configuration descriptor m_pConfigDesc[m_UsbConfigurationNo],// Start position InterfaceNo, // Interface number i, // Alternate setting -1, // Class -1, // Subclass -1); // Protocol if(!pAlternateSetting) break; }//for loop i return (i); }
static usb_interface_descriptor_t * USBD_ParseConfigurationDescriptor(usb_config_descriptor_t *conf, uint8_t intfnum, uint8_t altset) { return USBD_ParseConfigurationDescriptorEx(conf, conf, intfnum, altset, -1, -1, -1); }
PUSB_INTERFACE_DESCRIPTOR WINAPI USBD_ParseConfigurationDescriptor( PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, UCHAR InterfaceNumber, UCHAR AlternateSetting ) { TRACE( "(%p, %u, %u)\n", ConfigurationDescriptor, InterfaceNumber, AlternateSetting ); return USBD_ParseConfigurationDescriptorEx( ConfigurationDescriptor, ConfigurationDescriptor, InterfaceNumber, AlternateSetting, -1, -1, -1 ); }
static union usbd_urb * USBD_CreateConfigurationRequest(usb_config_descriptor_t *conf, uint16_t *len) { struct usbd_interface_list_entry list[2]; union usbd_urb *urb; bzero(list, sizeof(struct usbd_interface_list_entry) * 2); list[0].uil_intfdesc = USBD_ParseConfigurationDescriptorEx(conf, conf, -1, -1, -1, -1, -1); urb = USBD_CreateConfigurationRequestEx(conf, list); if (urb == NULL) return (NULL); *len = urb->uu_selconf.usc_hdr.uuh_len; return (urb); }
NTSTATUS AllocateInterfaceDescriptorsArray( 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; }
PURB WINAPI USBD_CreateConfigurationRequestEx( PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PUSBD_INTERFACE_LIST_ENTRY InterfaceList ) { URB *urb; ULONG size = 0; USBD_INTERFACE_LIST_ENTRY *interfaceEntry; ULONG interfaceCount = 0; TRACE( "(%p, %p)\n", ConfigurationDescriptor, InterfaceList ); size = sizeof(struct _URB_SELECT_CONFIGURATION); for (interfaceEntry = InterfaceList; interfaceEntry->InterfaceDescriptor; interfaceEntry++) { ++interfaceCount; size += (interfaceEntry->InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USBD_PIPE_INFORMATION); } size += (interfaceCount - 1) * sizeof(USBD_INTERFACE_INFORMATION); urb = ExAllocatePool( NonPagedPool, size ); if (urb) { USBD_INTERFACE_INFORMATION *interfaceInfo; RtlZeroMemory( urb, size ); urb->u.UrbSelectConfiguration.Hdr.Length = size; urb->u.UrbSelectConfiguration.Hdr.Function = URB_FUNCTION_SELECT_CONFIGURATION; urb->u.UrbSelectConfiguration.ConfigurationDescriptor = ConfigurationDescriptor; interfaceInfo = &urb->u.UrbSelectConfiguration.Interface; for (interfaceEntry = InterfaceList; interfaceEntry->InterfaceDescriptor; interfaceEntry++) { int i; USB_INTERFACE_DESCRIPTOR *currentInterface; USB_ENDPOINT_DESCRIPTOR *endpointDescriptor; interfaceInfo->InterfaceNumber = interfaceEntry->InterfaceDescriptor->bInterfaceNumber; interfaceInfo->AlternateSetting = interfaceEntry->InterfaceDescriptor->bAlternateSetting; interfaceInfo->Class = interfaceEntry->InterfaceDescriptor->bInterfaceClass; interfaceInfo->SubClass = interfaceEntry->InterfaceDescriptor->bInterfaceSubClass; interfaceInfo->Protocol = interfaceEntry->InterfaceDescriptor->bInterfaceProtocol; interfaceInfo->NumberOfPipes = interfaceEntry->InterfaceDescriptor->bNumEndpoints; currentInterface = USBD_ParseConfigurationDescriptorEx( ConfigurationDescriptor, ConfigurationDescriptor, interfaceEntry->InterfaceDescriptor->bInterfaceNumber, -1, -1, -1, -1 ); endpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) USBD_ParseDescriptors( ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, currentInterface, USB_ENDPOINT_DESCRIPTOR_TYPE ); for (i = 0; i < interfaceInfo->NumberOfPipes && endpointDescriptor; i++) { interfaceInfo->Pipes[i].MaximumPacketSize = endpointDescriptor->wMaxPacketSize; interfaceInfo->Pipes[i].EndpointAddress = endpointDescriptor->bEndpointAddress; interfaceInfo->Pipes[i].Interval = endpointDescriptor->bInterval; switch (endpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) { case USB_ENDPOINT_TYPE_CONTROL: interfaceInfo->Pipes[i].PipeType = UsbdPipeTypeControl; break; case USB_ENDPOINT_TYPE_BULK: interfaceInfo->Pipes[i].PipeType = UsbdPipeTypeBulk; break; case USB_ENDPOINT_TYPE_INTERRUPT: interfaceInfo->Pipes[i].PipeType = UsbdPipeTypeInterrupt; break; case USB_ENDPOINT_TYPE_ISOCHRONOUS: interfaceInfo->Pipes[i].PipeType = UsbdPipeTypeIsochronous; break; } endpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) USBD_ParseDescriptors( ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, endpointDescriptor + 1, USB_ENDPOINT_DESCRIPTOR_TYPE ); } interfaceInfo->Length = sizeof(USBD_INTERFACE_INFORMATION) + (i - 1) * sizeof(USBD_PIPE_INFORMATION); interfaceEntry->Interface = interfaceInfo; interfaceInfo = (USBD_INTERFACE_INFORMATION*)(((char*)interfaceInfo)+interfaceInfo->Length); } } return urb; }
NTSTATUS USBHUB_ParentFDOStartDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PHUB_DEVICE_EXTENSION HubDeviceExtension; PURB Urb, ConfigurationUrb; PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; PUSBD_INTERFACE_LIST_ENTRY InterfaceList; ULONG Index; NTSTATUS Status; // get hub device extension HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; // Send the StartDevice to lower device object Status = ForwardIrpAndWait(HubDeviceExtension->LowerDeviceObject, Irp); if (!NT_SUCCESS(Status)) { // failed to start pdo DPRINT1("Failed to start the RootHub PDO\n"); return Status; } // FIXME get capabilities Urb = ExAllocatePool(NonPagedPool, sizeof(URB)); if (!Urb) { // no memory DPRINT1("No memory\n"); return STATUS_INSUFFICIENT_RESOURCES; } // lets get device descriptor UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, &HubDeviceExtension->HubDeviceDescriptor, NULL, sizeof(USB_DEVICE_DESCRIPTOR), NULL); // get hub device descriptor Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { // failed to get device descriptor of hub DPRINT1("Failed to get hub device descriptor with Status %x!\n", Status); ExFreePool(Urb); return Status; } // now get configuration descriptor UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, &HubDeviceExtension->HubConfigDescriptor, NULL, sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR), NULL); // request configuration descriptor Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { // failed to get configuration descriptor DPRINT1("Failed to get hub configuration descriptor with status %x\n", Status); ExFreePool(Urb); return Status; } // sanity checks ASSERT(HubDeviceExtension->HubConfigDescriptor.wTotalLength == sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR)); ASSERT(HubDeviceExtension->HubConfigDescriptor.bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE); ASSERT(HubDeviceExtension->HubConfigDescriptor.bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR)); ASSERT(HubDeviceExtension->HubConfigDescriptor.bNumInterfaces == 1); ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bLength == sizeof(USB_INTERFACE_DESCRIPTOR)); ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE); ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bNumEndpoints == 1); ASSERT(HubDeviceExtension->HubEndPointDescriptor.bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE); ASSERT(HubDeviceExtension->HubEndPointDescriptor.bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)); ASSERT(HubDeviceExtension->HubEndPointDescriptor.bmAttributes == USB_ENDPOINT_TYPE_INTERRUPT); ASSERT(HubDeviceExtension->HubEndPointDescriptor.bEndpointAddress == 0x81); // interrupt in // Build hub descriptor request UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_DEVICE, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, 0, USB_REQUEST_GET_DESCRIPTOR, USB_DEVICE_CLASS_RESERVED, 0, &HubDeviceExtension->HubDescriptor, NULL, sizeof(USB_HUB_DESCRIPTOR), NULL); // send request Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to get Hub Descriptor Status %x!\n", Status); ExFreePool(Urb); return STATUS_UNSUCCESSFUL; } // sanity checks ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorLength == sizeof(USB_HUB_DESCRIPTOR)); ASSERT(HubDeviceExtension->HubDescriptor.bNumberOfPorts); ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorType == 0x29); // store number of ports DPRINT1("NumberOfPorts %lu\n", HubDeviceExtension->HubDescriptor.bNumberOfPorts); HubDeviceExtension->UsbExtHubInfo.NumberOfPorts = HubDeviceExtension->HubDescriptor.bNumberOfPorts; // allocate interface list InterfaceList = ExAllocatePool(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (HubDeviceExtension->HubConfigDescriptor.bNumInterfaces + 1)); if (!InterfaceList) { // no memory DPRINT1("No memory\n"); return STATUS_INSUFFICIENT_RESOURCES; } // zero list RtlZeroMemory(InterfaceList, sizeof(USBD_INTERFACE_LIST_ENTRY) * (HubDeviceExtension->HubConfigDescriptor.bNumInterfaces + 1)); // grab all interface descriptors for(Index = 0; Index < HubDeviceExtension->HubConfigDescriptor.bNumInterfaces; Index++) { // Get the first Configuration Descriptor InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor, &HubDeviceExtension->HubConfigDescriptor, Index, 0, -1, -1, -1); // store in list InterfaceList[Index].InterfaceDescriptor = InterfaceDescriptor; } // now create configuration request ConfigurationUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor, (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList); if (ConfigurationUrb == NULL) { // failed to build urb DPRINT1("Failed to build configuration urb\n"); ExFreePool(Urb); return STATUS_INSUFFICIENT_RESOURCES; } // send request Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, ConfigurationUrb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to get Hub Descriptor Status %x!\n", Status); ExFreePool(Urb); ExFreePool(ConfigurationUrb); return STATUS_UNSUCCESSFUL; } // store configuration & pipe handle HubDeviceExtension->ConfigurationHandle = ConfigurationUrb->UrbSelectConfiguration.ConfigurationHandle; HubDeviceExtension->PipeHandle = ConfigurationUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle; DPRINT("Hub Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle); // free urb ExFreePool(ConfigurationUrb); ExFreePool(Urb); // FIXME build SCE interrupt request // FIXME create pdos return Status; }
// Set the configuration of the usb device. NTSTATUS UsbDev::SetConfiguration() { NTSTATUS ntStatus = STATUS_SUCCESS; PUSBD_INTERFACE_LIST_ENTRY pTempInterfaceList = NULL, pTempInterfaceList_First = NULL; PUSB_CONFIGURATION_DESCRIPTOR pTemp_pConfigDesc = m_pConfigDesc[m_UsbConfigurationNo]; int i,j,NoOfInterface; PUSB_INTERFACE_DESCRIPTOR pTempInterfaceDesc = NULL; PURB pUrb = NULL; //2010/8/17 03:49下午 KIRQL oldIrql; PUSBD_INTERFACE_INFORMATION interface_temp; //2010/8/16 06:17下午 NoOfInterface = pTemp_pConfigDesc->bNumInterfaces; DBGU_TRACE(">>>UsbDev::SetConfiguration ! NoOfInterface = %d\n",NoOfInterface); pTempInterfaceList_First = pTempInterfaceList = (PUSBD_INTERFACE_LIST_ENTRY) ExAllocatePoolWithTag( NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (NoOfInterface + 1), USBDEV_POOLTAG); //2010/8/23 11:51上午 m_NumberOfInterfaces = NoOfInterface; if(pTempInterfaceList) {// pTempInterfaceList != NULL RtlZeroMemory(pTempInterfaceList, sizeof(USBD_INTERFACE_LIST_ENTRY) * (NoOfInterface + 1)); for(i=0;i<NoOfInterface;i++) {// for loop i pTempInterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseConfigurationDescriptorEx( m_pConfigDesc[0], // Pointer to configuration descriptor m_pConfigDesc[0], // Start position i, // Interface number -1,//0, // Alternate setting -1, -1, -1); if(!pTempInterfaceDesc) break; pTempInterfaceList->InterfaceDescriptor = pTempInterfaceDesc; pTempInterfaceList++; }// for loop i pTempInterfaceList->InterfaceDescriptor = NULL; // Mark the end of the list //pTempInterfaceList = pTempInterfaceList_First; // Pointer to the first entry of the interface list. pUrb = USBD_CreateConfigurationRequestEx(pTemp_pConfigDesc, pTempInterfaceList_First); if(pUrb) {// pUrb != NULL for(i=0;i<NoOfInterface;i++) {// for loop i // Set to interface i, alternater 0 pTempInterfaceList_First[i].Interface->InterfaceNumber = i; pTempInterfaceList_First[i].Interface->AlternateSetting = 0; DBGU_TRACE("No of endpoints : %d\n", pTempInterfaceList_First[i].InterfaceDescriptor->bNumEndpoints); for(j=0;j<pTempInterfaceList_First[i].InterfaceDescriptor->bNumEndpoints;j++) pTempInterfaceList_First[i].Interface->Pipes[j].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; }// for loop i //2010/8/24 05:51下午 interface_temp = &pUrb->UrbSelectConfiguration.Interface; ntStatus = SendAwaitUrb(pUrb); if(!NT_SUCCESS(ntStatus)) {// ntStatus != STATUS_SUCCESS ntStatus = STATUS_IO_DEVICE_ERROR; DBGU_TRACE("Fail to configure usb device !\n"); }// ntStatus != STATUS_SUCCESS else {// ntStatus == STATUS_SUCCESS m_hConfigureation = pUrb->UrbSelectConfiguration.ConfigurationHandle; //Release memory //if(m_pInterfaceListEntry) { // m_pInterfaceListEntry != NULL for(i=0;i<m_NumberOfInterfaces;i++) if(m_pInterface[i]) { ExFreePoolWithTag(m_pInterface[i],USBDEV_POOLTAG); m_pInterface[i] = NULL; DBGU_TRACE("ExFreePoolWithTag m_pInterface[%d]\n",i); } // ExFreePoolWithTag(m_pInterfaceListEntry,USBDEV_POOLTAG); // m_pInterfaceListEntry = NULL; } // m_pInterfaceListEntry != NULL //2010/8/23 11:51上午 //m_NumberOfInterfaces = NoOfInterface; //Copy interface list //m_pInterfaceListEntry = (PUSBD_INTERFACE_LIST_ENTRY) ExAllocatePoolWithTag(NonPagedPool,(m_NumberOfInterfaces * sizeof(USBD_INTERFACE_LIST_ENTRY)), USBDEV_POOLTAG); //if(m_pInterfaceListEntry) {// m_pInterfaceListEntry != NULL for(i=0;i<m_NumberOfInterfaces;i++) {//for loop i //m_pInterfaceListEntry[i].InterfaceDescriptor = pTempInterfaceList_First[i].InterfaceDescriptor; #ifdef __VIDEO_CLASS__ // For Video Class Device if (pTempInterfaceList_First[i].Interface->InterfaceNumber==1) // UVC has 2 interfaces { //2011/5/12 02:22下午 if(BeST5R286) pTempInterfaceList_First[i].Interface->NumberOfPipes = 2; else pTempInterfaceList_First[i].Interface->NumberOfPipes = 1; pTempInterfaceList_First[i].Interface->Length = sizeof(USBD_INTERFACE_INFORMATION); } // james try M2TS. if (pTempInterfaceList_First[i].Interface->InterfaceNumber==2) { pTempInterfaceList_First[i].Interface->NumberOfPipes = 1; pTempInterfaceList_First[i].Interface->Length = sizeof(USBD_INTERFACE_INFORMATION); } #endif //2010/8/24 05:53下午 // m_pInterface[i] = (PUSBD_INTERFACE_INFORMATION) ExAllocatePoolWithTag(NonPagedPool, pTempInterfaceList_First[i].Interface->Length, USBDEV_POOLTAG); if(BeST5R286) m_pInterface[i] = (PUSBD_INTERFACE_INFORMATION) ExAllocatePoolWithTag(NonPagedPool, GET_USBD_INTERFACE_SIZE(2), USBDEV_POOLTAG); else m_pInterface[i] = (PUSBD_INTERFACE_INFORMATION) ExAllocatePoolWithTag(NonPagedPool, interface_temp->Length, USBDEV_POOLTAG); //2010/8/17 05:42下午 //KeAcquireSpinLock(&SetConfigSpinLock, &oldIrql); //2010/8/13 05:20下午 if (m_pInterface[i] && pTempInterfaceList_First[i].Interface && pTempInterfaceList_First[i].Interface->Length >0) //if (m_pInterfaceListEntry[i].Interface) { //2010/8/25 10:52上午 //DBGU_TRACE("RtlCopyMemory Interface[%d] len = %d\n",i,pTempInterfaceList_First[i].Interface->Length); //RtlCopyMemory(m_pInterface[i], pTempInterfaceList_First[i].Interface, pTempInterfaceList_First[i].Interface->Length); DBGU_TRACE("MJ RtlCopyMemory Interface[%d] len = %d\n",i,interface_temp->Length); RtlCopyMemory(m_pInterface[i], interface_temp, interface_temp->Length); m_pInterface[i]->InterfaceNumber = i; m_pInterface[i]->AlternateSetting = 0; if(i==0) m_pInterface[i]->Pipes[0].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; else { if(BeST5R286) m_pInterface[i]->NumberOfPipes = 2; else m_pInterface[i]->NumberOfPipes = 1; } } else { DBGU_TRACE("RtlCopyMemory Interface[%d] STATUS_INSUFFICIENT_RESOURCES\n",i); ntStatus = STATUS_INSUFFICIENT_RESOURCES; } //2010/8/17 03:42下午 //KeReleaseSpinLock(&SetConfigSpinLock, oldIrql); }//for loop i }// m_pInterfaceListEntry != NULL /*else {// m_pInterfaceListEntry == NULL ntStatus = STATUS_INSUFFICIENT_RESOURCES; }*/// m_pInterfaceListEntry == NULL }// ntStatus == STATUS_SUCCESS }// pUrb != NULL else {// pUrb == NULL ntStatus = STATUS_INSUFFICIENT_RESOURCES; }// pUrb == NULL }// pTempInterfaceList != NULL else {// pTempInterfaceList == NULL ntStatus = STATUS_INSUFFICIENT_RESOURCES; }// pTempInterfaceList == NULL if(pUrb) ExFreePool(pUrb); if(pTempInterfaceList_First) { ExFreePoolWithTag(pTempInterfaceList_First,USBDEV_POOLTAG); //2010/8/16 07:00下午 pTempInterfaceList_First = NULL; } return ntStatus; }
NTSTATUS USBCCGP_LegacyEnum( IN PDEVICE_OBJECT DeviceObject) { ULONG Index; PFDO_DEVICE_EXTENSION FDODeviceExtension; NTSTATUS Status = STATUS_SUCCESS; PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; // // get device extension // FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ASSERT(FDODeviceExtension->Common.IsFDO); // // sanity check // ASSERT(FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces); // // allocate function array // FDODeviceExtension->FunctionDescriptor = AllocateItem(NonPagedPool, sizeof(USBC_FUNCTION_DESCRIPTOR) * FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces); if (!FDODeviceExtension->FunctionDescriptor) { // // no memory // DPRINT1("USBCCGP_EnumWithAssociationDescriptor failed to allocate function descriptor %lu\n", FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces); return STATUS_INSUFFICIENT_RESOURCES; } // // init function descriptors // for (Index = 0; Index < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; Index++) { // get interface descriptor InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(FDODeviceExtension->ConfigurationDescriptor, FDODeviceExtension->ConfigurationDescriptor, Index, 0, -1, -1, -1); if (InterfaceDescriptor == NULL) { // // failed to find interface descriptor // DPRINT1("[USBCCGP] Failed to find interface descriptor index %lu\n", Index); ASSERT(FALSE); return STATUS_UNSUCCESSFUL; } // // init function descriptor // FDODeviceExtension->FunctionDescriptor[Index].FunctionNumber = Index; FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces = 1; FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * 1); if (!FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList) { // // no memory // return STATUS_INSUFFICIENT_RESOURCES; } // // store interface descriptor // FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList[0] = InterfaceDescriptor; // // now init the device ids // Status = USBCCG_InitIdsWithInterfaceDescriptor(FDODeviceExtension, InterfaceDescriptor, Index, &FDODeviceExtension->FunctionDescriptor[Index]); if (!NT_SUCCESS(Status)) { // // failed to init ids // DPRINT1("[USBCCGP] Failed to init ids with %lx\n", Status); return Status; } // // store function count // FDODeviceExtension->FunctionDescriptorCount++; } // // done // return Status; }
NTSTATUS StartDevice( PDEVICE_OBJECT fdo, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PARTIAL_RESOURCE_LIST translated ) { USB_CONFIGURATION_DESCRIPTOR tcd; PUSB_CONFIGURATION_DESCRIPTOR pcd; PUSB_STRING_DESCRIPTOR desc; HANDLE RecoveryHandle; PURB selurb; URB urb; NTSTATUS status; status = STATUS_SUCCESS; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; selurb = NULL; pcd = NULL; // Read our device descriptor. The only real purpose to this would be to find out how many // configurations there are so we can read their descriptors. In this simplest of examples, // there's only one configuration. KdPrint((DRIVERNAME " - Start device\n")); UsbBuildGetDescriptorRequest( &urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_DEVICE_DESCRIPTOR_TYPE, 0, LangId, &pdx->dd, NULL, sizeof(pdx->dd), NULL ); status = SendAwaitUrb( fdo, &urb ); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - Error %X trying to retrieve device descriptor\n", status)); goto cleanup; } // allocate the buffer for the descriptor; take extra space to null terminate the bString member desc = (PUSB_STRING_DESCRIPTOR)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, SPOT_TAG ); if(!desc) { KdPrint((DRIVERNAME " - Unable to allocate %X bytes for string descriptor\n", sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes)); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } pdx->devHash = desc; UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_STRING_DESCRIPTOR_TYPE, DeviceId, LangId, desc, NULL, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, NULL); status = SendAwaitUrb(fdo, &urb); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - Error %X trying to retrieve string descriptor for DeviceId\n", status)); goto cleanup; } // null terminate the buffer; we allocated one more wchar_t for the purpose desc->bString[ (desc->bLength / 2) - 1 ] = L'\0'; UpdateDeviceInformation( fdo ); // Read the descriptor of the first configuration. This requires two steps. The first step // reads the fixed-size configuration descriptor alone. The second step reads the // configuration descriptor plus all imbedded interface and endpoint descriptors. UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, LangId, &tcd, NULL, sizeof(tcd), NULL); status = SendAwaitUrb(fdo, &urb); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - Error %X trying to read configuration descriptor 1\n", status)); goto cleanup; } ULONG size = tcd.wTotalLength; pcd = (PUSB_CONFIGURATION_DESCRIPTOR) ExAllocatePoolWithTag(NonPagedPool, size, SPOT_TAG); if(!pcd) { KdPrint((DRIVERNAME " - Unable to allocate %X bytes for configuration descriptor\n", size)); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, LangId, pcd, NULL, size, NULL); status = SendAwaitUrb(fdo, &urb); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - Error %X trying to read configuration descriptor 1\n", status)); goto cleanup; } // Locate the descriptor for the one and only interface we expect to find PUSB_INTERFACE_DESCRIPTOR pid = USBD_ParseConfigurationDescriptorEx(pcd, pcd, -1, -1, -1, -1, -1); ASSERT(pid); // Create a URB to use in selecting a configuration. USBD_INTERFACE_LIST_ENTRY interfaces[2] = { {pid, NULL}, {NULL, NULL}, // fence to terminate the array }; selurb = USBD_CreateConfigurationRequestEx(pcd, interfaces); if(!selurb) { KdPrint((DRIVERNAME " - Unable to create configuration request\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } // Verify that the interface describes exactly the endpoints we expect if(pid->bNumEndpoints != 2) { KdPrint((DRIVERNAME " - %d is the wrong number of endpoints\n", pid->bNumEndpoints)); status = STATUS_DEVICE_CONFIGURATION_ERROR; goto cleanup; } PUSB_ENDPOINT_DESCRIPTOR ped = (PUSB_ENDPOINT_DESCRIPTOR) pid; ped = (PUSB_ENDPOINT_DESCRIPTOR) USBD_ParseDescriptors(pcd, tcd.wTotalLength, ped, USB_ENDPOINT_DESCRIPTOR_TYPE); if(!ped || 0 == (ped->bEndpointAddress & 0x80) || ped->bmAttributes != USB_ENDPOINT_TYPE_BULK || ped->wMaxPacketSize > 64) { KdPrint((DRIVERNAME " - Endpoint has wrong attributes\n")); status = STATUS_DEVICE_CONFIGURATION_ERROR; goto cleanup; } ++ped; if(!ped || 0 != (ped->bEndpointAddress & 0x80) || ped->bmAttributes != USB_ENDPOINT_TYPE_BULK || ped->wMaxPacketSize > 64) { KdPrint((DRIVERNAME " - Endpoint has wrong attributes\n")); status = STATUS_DEVICE_CONFIGURATION_ERROR; goto cleanup; } ++ped; PUSBD_INTERFACE_INFORMATION pii = interfaces[0].Interface; ASSERT(pii->NumberOfPipes == pid->bNumEndpoints); // Initialize the maximum transfer size for each of the endpoints. The // default would be PAGE_SIZE. The firmware itself only has a 4096-byte // ring buffer, though. We need to restrict the test applet to that many // bytes. In order to exercise the multi-segment aspect of the transfer code, // therefore, reduce the maximum transfer size to 1024 bytes. pii->Pipes[0].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; pii->Pipes[1].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; pdx->maxtransfer = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; // Submit the set-configuration request status = SendAwaitUrb(fdo, selurb); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - Error %X trying to select configuration\n", status)); goto cleanup; } // Save the configuration and pipe handles pdx->hconfig = selurb->UrbSelectConfiguration.ConfigurationHandle; pdx->hinpipe = pii->Pipes[0].PipeHandle; pdx->houtpipe = pii->Pipes[1].PipeHandle; // Transfer ownership of the configuration descriptor to the device extension pdx->pcd = pcd; pcd = NULL; // Enable the interface IoSetDeviceInterfaceState(&pdx->operationsInterfaceName, TRUE); // Enable the interface IoSetDeviceInterfaceState(&pdx->inquiriesInterfaceName, TRUE); // create recovery thread status = PsCreateSystemThread(&RecoveryHandle, 0, NULL, NULL, NULL, RecoveryThread, (PVOID)pdx); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - PsCreateSystemThread failed with error %08x\n", status)); goto cleanup; } status = ObReferenceObjectByHandle( RecoveryHandle, SYNCHRONIZE, NULL, KernelMode, (PVOID*)&pdx->RecoveryThread, NULL ); ASSERT(NT_SUCCESS(status)); ZwClose(RecoveryHandle); // Start polling status = StartPolling(pdx); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - StartPolling failed 0x%08x\n", status)); if(pdx->RecoveryThread) { // shutdown recovery thread pdx->RecoveryExit = TRUE; KeSetEvent(&pdx->RecoveryEvent, 0, FALSE); // wait for polling thread to exit KeWaitForSingleObject(pdx->RecoveryThread, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(pdx->RecoveryThread); pdx->RecoveryThread = NULL; } goto cleanup; } cleanup: if(selurb) ExFreePool(selurb); if(pcd ) ExFreePool(pcd ); // get rid of return codes like STATUS_PENDING if(NT_SUCCESS(status)) { return STATUS_SUCCESS; } return status; }
NTSTATUS NTAPI UsbhubPnpFdo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IrpSp; NTSTATUS Status = STATUS_SUCCESS; ULONG MinorFunction; ULONG_PTR Information = 0; PHUB_DEVICE_EXTENSION DeviceExtension; IrpSp = IoGetCurrentIrpStackLocation(Irp); MinorFunction = IrpSp->MinorFunction; DeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; switch (MinorFunction) { case IRP_MN_START_DEVICE: /* 0x0 */ { PURB Urb; ULONG Result = 0; PUSB_INTERFACE_DESCRIPTOR Pid; /* Theres only one descriptor on hub */ USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}}; PURB ConfigUrb = NULL; /* We differ from windows on hubpdo because we dont have usbport.sys which manages all usb device objects */ DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); /* Allocating size including the sizeof USBD_INTERFACE_LIST_ENTRY */ Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY), USB_HUB_TAG); RtlZeroMemory(Urb, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY)); /* Get the hubs PDO */ QueryRootHub(DeviceExtension->LowerDevice, IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO, &DeviceExtension->RootHubPdo, &DeviceExtension->RootHubFdo); ASSERT(DeviceExtension->RootHubPdo); ASSERT(DeviceExtension->RootHubFdo); DPRINT1("RootPdo %x, RootFdo %x\n", DeviceExtension->RootHubPdo, DeviceExtension->RootHubFdo); /* Send the START_DEVICE irp down to the PDO of RootHub */ Status = ForwardIrpAndWait(DeviceExtension->RootHubPdo, Irp); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to start the RootHub PDO\n"); ASSERT(FALSE); } /* Get the current number of hubs */ QueryRootHub(DeviceExtension->RootHubPdo,IOCTL_INTERNAL_USB_GET_HUB_COUNT, &DeviceExtension->HubCount, NULL); /* Get the Direct Call Interfaces */ Status = QueryInterface(DeviceExtension->RootHubPdo, USB_BUS_INTERFACE_HUB_GUID, sizeof(USB_BUS_INTERFACE_HUB_V5), 5, (PVOID)&DeviceExtension->HubInterface); if (!NT_SUCCESS(Status)) { DPRINT1("UsbhubM Failed to get HUB_GUID interface with status 0x%08lx\n", Status); return STATUS_UNSUCCESSFUL; } Status = QueryInterface(DeviceExtension->RootHubPdo, USB_BUS_INTERFACE_USBDI_GUID, sizeof(USB_BUS_INTERFACE_USBDI_V2), 2, (PVOID)&DeviceExtension->UsbDInterface); if (!NT_SUCCESS(Status)) { DPRINT1("UsbhubM Failed to get USBDI_GUID interface with status 0x%08lx\n", Status); return STATUS_UNSUCCESSFUL; } /* Get roothub device handle */ Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, &DeviceExtension->RootHubUsbDevice, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Usbhub: GetRootHubDeviceHandle failed with status 0x%08lx\n", Status); return Status; } Status = DeviceExtension->HubInterface.QueryDeviceInformation(DeviceExtension->RootHubPdo, DeviceExtension->RootHubUsbDevice, &DeviceExtension->DeviceInformation, sizeof(USB_DEVICE_INFORMATION_0), &Result); DPRINT("Status %x, Result %x\n", Status, Result); DPRINT("InformationLevel %x\n", DeviceExtension->DeviceInformation.InformationLevel); DPRINT("ActualLength %x\n", DeviceExtension->DeviceInformation.ActualLength); DPRINT("PortNumber %x\n", DeviceExtension->DeviceInformation.PortNumber); DPRINT("DeviceDescriptor %x\n", DeviceExtension->DeviceInformation.DeviceDescriptor); DPRINT("HubAddress %x\n", DeviceExtension->DeviceInformation.HubAddress); DPRINT("NumberofPipes %x\n", DeviceExtension->DeviceInformation.NumberOfOpenPipes); /* Get roothubs device descriptor */ UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, &DeviceExtension->HubDeviceDescriptor, NULL, sizeof(USB_DEVICE_DESCRIPTOR), NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Usbhub: Failed to get HubDeviceDescriptor!\n"); } DumpDeviceDescriptor(&DeviceExtension->HubDeviceDescriptor); /* Get roothubs configuration descriptor */ UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, &DeviceExtension->HubConfigDescriptor, NULL, sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR), NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Usbhub: Failed to get RootHub Configuration with status %x\n", Status); ASSERT(FALSE); } ASSERT(DeviceExtension->HubConfigDescriptor.wTotalLength); DumpFullConfigurationDescriptor(&DeviceExtension->HubConfigDescriptor); //DPRINT1("DeviceExtension->HubConfigDescriptor.wTotalLength %x\n", DeviceExtension->HubConfigDescriptor.wTotalLength); Status = DeviceExtension->HubInterface.GetExtendedHubInformation(DeviceExtension->RootHubPdo, DeviceExtension->RootHubPdo, &DeviceExtension->UsbExtHubInfo, sizeof(USB_EXTHUB_INFORMATION_0), &Result); if (!NT_SUCCESS(Status)) { DPRINT1("Usbhub: Failed to extended hub information. Unable to determine the number of ports!\n"); ASSERT(FALSE); } DPRINT1("DeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", DeviceExtension->UsbExtHubInfo.NumberOfPorts); UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_DEVICE, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_DEVICE_CLASS_RESERVED, 0, 0, &DeviceExtension->HubDescriptor, NULL, sizeof(USB_HUB_DESCRIPTOR), NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); DPRINT1("bDescriptorType %x\n", DeviceExtension->HubDescriptor.bDescriptorType); /* Select the configuration */ /* Get the first one */ Pid = USBD_ParseConfigurationDescriptorEx(&DeviceExtension->HubConfigDescriptor, &DeviceExtension->HubConfigDescriptor, -1, -1, -1, -1, -1); ASSERT(Pid != NULL); InterfaceList[0].InterfaceDescriptor = Pid; ConfigUrb = USBD_CreateConfigurationRequestEx(&DeviceExtension->HubConfigDescriptor, (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList); ASSERT(ConfigUrb != NULL); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, ConfigUrb, NULL); DeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle; DeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle; DPRINT1("Configuration Handle %x\n", DeviceExtension->ConfigurationHandle); ExFreePool(ConfigUrb); Status = DeviceExtension->HubInterface.Initialize20Hub(DeviceExtension->RootHubPdo, DeviceExtension->RootHubUsbDevice, 1); DPRINT1("Status %x\n", Status); { int PortLoop; USHORT PortStatusAndChange[2]; for (PortLoop=0; PortLoop< DeviceExtension->UsbExtHubInfo.NumberOfPorts; PortLoop++) { DPRINT1("Port %x\n", PortLoop); UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_REQUEST_SET_FEATURE, PORT_POWER, 1, 0, 0, 0, 0); Urb->UrbOSFeatureDescriptorRequest.MS_FeatureDescriptorIndex = PortLoop + 1; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); DPRINT1("Status %x\n", Status); UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_OUT, 0, USB_REQUEST_GET_STATUS, 0, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PortStatusAndChange), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); DPRINT1("Status %x\n", Status); DPRINT1("PortStatus = %x\n", PortStatusAndChange[0]); DPRINT1("PortChange = %x\n", PortStatusAndChange[1]); } } ExFreePool(Urb); break; } case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */ { switch (IrpSp->Parameters.QueryDeviceRelations.Type) { case BusRelations: { PDEVICE_RELATIONS DeviceRelations = NULL; DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); Status = UsbhubFdoQueryBusRelations(DeviceObject, &DeviceRelations); Information = (ULONG_PTR)DeviceRelations; break; } case RemovalRelations: { DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); return ForwardIrpAndForget(DeviceObject, Irp); } default: DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", IrpSp->Parameters.QueryDeviceRelations.Type); return ForwardIrpAndForget(DeviceObject, Irp); } break; } case IRP_MN_QUERY_BUS_INFORMATION: { DPRINT1("IRP_MN_QUERY_BUS_INFORMATION\n"); break; } case IRP_MN_QUERY_ID: { DPRINT1("IRP_MN_QUERY_ID\n"); break; } case IRP_MN_QUERY_CAPABILITIES: { DPRINT1("IRP_MN_QUERY_CAPABILITIES\n"); break; } default: { DPRINT1("Usbhub: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction); return ForwardIrpAndForget(DeviceObject, Irp); } } Irp->IoStatus.Information = Information; Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
NTSTATUS NTAPI USBCCGP_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; // // 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; } do { // // parse configuration descriptor // InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, InterfaceIndex, -1, -1, -1, -1); if (InterfaceDescriptor) { // // store in interface list // 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; }
NTSTATUS IsoUsb_SelectInterface( IN PDEVICE_OBJECT DeviceObject, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor ) /*++ Routine Description: Initializes an 82930 with (possibly) multiple interfaces; This minidriver only supports one interface (with multiple endpoints). Arguments: DeviceObject - pointer to the device object for this instance of the 82930 device. ConfigurationDescriptor - pointer to the USB configuration descriptor containing the interface and endpoint descriptors. Return Value: NT status code --*/ { PDEVICE_EXTENSION deviceExtension; NTSTATUS ntStatus; PURB urb = NULL; ULONG i; PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor = NULL; PUSBD_INTERFACE_INFORMATION Interface = NULL; USHORT siz; PUCHAR pInf; ISOUSB_KdPrint( DBGLVL_MEDIUM,("enter IsoUsb_SelectInterface\n")); deviceExtension = DeviceObject->DeviceExtension; ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_SelectInterface() called with NULL Interface\n")); // // IsoUsb driver only supports one interface, we must parse // the configuration descriptor for the interface // and remember the pipes. // urb = USBD_CreateConfigurationRequest(ConfigurationDescriptor, &siz); if (urb) { // // USBD_ParseConfigurationDescriptorEx searches a given configuration // descriptor and returns a pointer to an interface that matches the // given search criteria. We only support one interface on this device // interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, //search from start of config descriptro -1, // interface number not a criteria; we only support one interface -1, // not interested in alternate setting here either -1, // interface class not a criteria -1, // interface subclass not a criteria -1 // interface protocol not a criteria ); if ( !interfaceDescriptor ) { ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_SelectInterface() ParseConfigurationDescriptorEx() failed\n returning STATUS_INSUFFICIENT_RESOURCES\n")); ExFreePool(urb); return STATUS_INSUFFICIENT_RESOURCES; } Interface = &urb->UrbSelectConfiguration.Interface; // allocate space for an array of pipe information structs; // in this basic sample, just used to track if opened/closed deviceExtension->PipeInfo = ExAllocatePool( NonPagedPool, Interface->NumberOfPipes * sizeof ( ISOUSB_PIPEINFO ) ); if ( !deviceExtension->PipeInfo ) { return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(deviceExtension->PipeInfo, Interface->NumberOfPipes * sizeof ( ISOUSB_PIPEINFO ) ); pInf = (PUCHAR ) deviceExtension->PipeInfo; for (i=0; i< Interface->NumberOfPipes; i++) { // // Perform any pipe initialization here; // We set the max transfer size and any Pipe flags we use; USBD sets the rest // of the Interface struct members // Interface->Pipes[i].MaximumTransferSize = deviceExtension->MaximumTransferSize; ( (PISOUSB_PIPEINFO) pInf)->fPipeOpened = FALSE; pInf += sizeof ( ISOUSB_PIPEINFO ); } UsbBuildSelectConfigurationRequest(urb, (USHORT) siz, ConfigurationDescriptor); ntStatus = IsoUsb_CallUSBD(DeviceObject, urb); deviceExtension->UsbConfigurationHandle = urb->UrbSelectConfiguration.ConfigurationHandle; } else { ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_SelectInterface() USBD_CreateConfigurationRequest() failed\n returning STATUS_INSUFFICIENT_RESOURCES\n")); ntStatus = STATUS_INSUFFICIENT_RESOURCES; } if (NT_SUCCESS(ntStatus)) { // // Save the configuration handle for this device // deviceExtension->UsbConfigurationHandle = urb->UrbSelectConfiguration.ConfigurationHandle; deviceExtension->UsbInterface = ExAllocatePool(NonPagedPool, Interface->Length); if (deviceExtension->UsbInterface) { ULONG j; // // save a copy of the interface information returned // RtlCopyMemory(deviceExtension->UsbInterface, Interface, Interface->Length); // // Dump the interface to the debugger // ISOUSB_KdPrint( DBGLVL_MEDIUM,("---------\n")); ISOUSB_KdPrint( DBGLVL_MEDIUM,("NumberOfPipes 0x%x\n", deviceExtension->UsbInterface->NumberOfPipes)); ISOUSB_KdPrint( DBGLVL_MEDIUM,("Length 0x%x\n", deviceExtension->UsbInterface->Length)); ISOUSB_KdPrint( DBGLVL_MEDIUM,("Alt Setting 0x%x\n", deviceExtension->UsbInterface->AlternateSetting)); ISOUSB_KdPrint( DBGLVL_MEDIUM,("Interface Number 0x%x\n", deviceExtension->UsbInterface->InterfaceNumber)); ISOUSB_KdPrint( DBGLVL_MEDIUM,("Class, subclass, protocol 0x%x 0x%x 0x%x\n", deviceExtension->UsbInterface->Class, deviceExtension->UsbInterface->SubClass, deviceExtension->UsbInterface->Protocol)); // Dump the pipe info for (j=0; j<Interface->NumberOfPipes; j++) { PUSBD_PIPE_INFORMATION pipeInformation; pipeInformation = &deviceExtension->UsbInterface->Pipes[j]; ISOUSB_KdPrint( DBGLVL_MEDIUM,("---------\n")); ISOUSB_KdPrint( DBGLVL_MEDIUM,("PipeType 0x%x\n", pipeInformation->PipeType)); ISOUSB_KdPrint( DBGLVL_MEDIUM,("EndpointAddress 0x%x\n", pipeInformation->EndpointAddress)); ISOUSB_KdPrint( DBGLVL_MEDIUM,("MaxPacketSize 0x%x\n", pipeInformation->MaximumPacketSize)); ISOUSB_KdPrint( DBGLVL_MEDIUM,("Interval 0x%x\n", pipeInformation->Interval)); ISOUSB_KdPrint( DBGLVL_MEDIUM,("Handle 0x%x\n", pipeInformation->PipeHandle)); ISOUSB_KdPrint( DBGLVL_MEDIUM,("MaximumTransferSize 0x%x\n", pipeInformation->MaximumTransferSize)); } ISOUSB_KdPrint( DBGLVL_MEDIUM,("---------\n")); } } if (urb) { // don't call the ISOUSB_ExFreePool since the buffer was // alloced by USBD_CreateConfigurationRequest, not ISOUSB_ExAllocatePool() ExFreePool(urb); } ISOUSB_KdPrint( DBGLVL_HIGH,("exit IsoUsb_SelectInterface (%x)\n", ntStatus)); return ntStatus; }