NTSTATUS FDO_CloseConfiguration( IN PDEVICE_OBJECT DeviceObject) { NTSTATUS Status; PURB Urb; PFDO_DEVICE_EXTENSION FDODeviceExtension; /* Get device extension */ FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ASSERT(FDODeviceExtension->Common.IsFDO); /* Now allocate the urb */ Urb = USBD_CreateConfigurationRequestEx(FDODeviceExtension->ConfigurationDescriptor, FDODeviceExtension->InterfaceList); if (!Urb) { /* No memory */ return STATUS_INSUFFICIENT_RESOURCES; } /* Clear configuration descriptor to make it an unconfigure request */ Urb->UrbSelectConfiguration.ConfigurationDescriptor = NULL; /* Submit urb */ Status = USBCCGP_SyncUrbRequest(FDODeviceExtension->NextDeviceObject, Urb); if (!NT_SUCCESS(Status)) { /* Failed to set configuration */ DPRINT1("USBCCGP_SyncUrbRequest failed to unconfigure device\n", Status); } ExFreePool(Urb); return Status; }
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); }
PURB WINAPI USBD_CreateConfigurationRequest( PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PUSHORT Siz ) { URB *urb = NULL; USBD_INTERFACE_LIST_ENTRY *interfaceList; ULONG interfaceListSize; USB_INTERFACE_DESCRIPTOR *interfaceDesc; int i; TRACE( "(%p, %p)\n", ConfigurationDescriptor, Siz ); /* http://www.microsoft.com/whdc/archive/usbfaq.mspx * claims USBD_CreateConfigurationRequest doesn't support > 1 interface, * but is this on Windows 98 only or all versions? */ *Siz = 0; interfaceListSize = (ConfigurationDescriptor->bNumInterfaces + 1) * sizeof(USBD_INTERFACE_LIST_ENTRY); interfaceList = ExAllocatePool( NonPagedPool, interfaceListSize ); if (interfaceList) { RtlZeroMemory( interfaceList, interfaceListSize ); interfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors( ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, ConfigurationDescriptor, USB_INTERFACE_DESCRIPTOR_TYPE ); for (i = 0; i < ConfigurationDescriptor->bNumInterfaces && interfaceDesc != NULL; i++) { interfaceList[i].InterfaceDescriptor = interfaceDesc; interfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors( ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, interfaceDesc + 1, USB_INTERFACE_DESCRIPTOR_TYPE ); } urb = USBD_CreateConfigurationRequestEx( ConfigurationDescriptor, interfaceList ); if (urb) *Siz = urb->u.UrbHeader.Length; ExFreePool( interfaceList ); } 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; }
NTSTATUS set_configuration(libusb_device_t *dev, int configuration, int timeout) { NTSTATUS status = STATUS_SUCCESS; URB urb, *urb_ptr = NULL; USB_CONFIGURATION_DESCRIPTOR *configuration_descriptor = NULL; USB_INTERFACE_DESCRIPTOR *interface_descriptor = NULL; USBD_INTERFACE_LIST_ENTRY *interfaces = NULL; int i, j, interface_number, desc_size, config_index, ret; // check if this config value is already set if ((configuration > 0) && dev->config.value == configuration) { return STATUS_SUCCESS; } // check if this config index is already set if ((configuration < 0) && dev->config.value && dev->config.index == (abs(configuration)-1)) { return STATUS_SUCCESS; } memset(&urb, 0, sizeof(URB)); if (configuration == 0) { urb.UrbHeader.Function = URB_FUNCTION_SELECT_CONFIGURATION; urb.UrbHeader.Length = sizeof(struct _URB_SELECT_CONFIGURATION); status = call_usbd(dev, &urb, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout); if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb.UrbHeader.Status)) { USBERR("setting configuration %d failed: status: 0x%x, urb-status: 0x%x\n", configuration, status, urb.UrbHeader.Status); return status; } dev->config.handle = urb.UrbSelectConfiguration.ConfigurationHandle; dev->config.value = 0; clear_pipe_info(dev); return status; } if (configuration <= SET_CONFIG_ACTIVE_CONFIG) { // note: as of v1.2.4.0, the active/default configuration is // always the first configuration the device returns. (index 0) configuration=-1; } USBMSG("setting configuration %s %d timeout=%d", (configuration < 0) ? "index" : "value", (configuration < 0) ? abs(configuration) - 1 : configuration, timeout); // If configuration is negative, it is retrieved by index. // configuration_descriptor = get_config_descriptor(dev, configuration, &desc_size, &config_index); if (!configuration_descriptor) { USBERR0("getting configuration descriptor failed"); return STATUS_INVALID_PARAMETER; } // if we passed an index in we can check here to see // if the device is already configured with this value if (dev->config.value == configuration_descriptor->bConfigurationValue) { UpdateContextConfigDescriptor( dev, configuration_descriptor, desc_size, configuration_descriptor->bConfigurationValue, config_index); status = STATUS_SUCCESS; goto SetConfigurationDone; } // MEMORY ALLOCATION BEGINS interfaces = ExAllocatePool(NonPagedPool,(configuration_descriptor->bNumInterfaces + 1) * sizeof(USBD_INTERFACE_LIST_ENTRY)); if (!interfaces) { USBERR0("memory allocation failed\n"); status = STATUS_NO_MEMORY; ExFreePool(configuration_descriptor); goto SetConfigurationDone; } memset(interfaces, 0, (configuration_descriptor->bNumInterfaces + 1) * sizeof(USBD_INTERFACE_LIST_ENTRY)); interface_number = 0; for (i = 0; i < configuration_descriptor->bNumInterfaces; i++) { for (j = interface_number; j < LIBUSB_MAX_NUMBER_OF_INTERFACES; j++) { interface_descriptor = find_interface_desc(configuration_descriptor, desc_size, j, 0); if (interface_descriptor) { interface_number = ++j; break; } } if (!interface_descriptor) { USBERR("unable to find interface descriptor at index %d\n", i); status = STATUS_INVALID_PARAMETER; ExFreePool(configuration_descriptor); goto SetConfigurationDone; } else { USBMSG("found interface %d\n", interface_descriptor->bInterfaceNumber); interfaces[i].InterfaceDescriptor = interface_descriptor; } } urb_ptr = USBD_CreateConfigurationRequestEx(configuration_descriptor, interfaces); if (!urb_ptr) { USBERR0("memory allocation failed\n"); status = STATUS_NO_MEMORY; ExFreePool(configuration_descriptor); goto SetConfigurationDone; } for (i = 0; i < configuration_descriptor->bNumInterfaces; i++) { for (j = 0; j < (int)interfaces[i].Interface->NumberOfPipes; j++) { interfaces[i].Interface->Pipes[j].MaximumTransferSize = LIBUSB_MAX_READ_WRITE; } } USBDBG("#%d %s passing configuration request to target-device.", dev->id, dev->device_id); status = call_usbd(dev, urb_ptr, IOCTL_INTERNAL_USB_SUBMIT_URB, timeout); if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb_ptr->UrbHeader.Status)) { USBERR("setting configuration %d failed: status: 0x%x, urb-status: 0x%x\n", configuration, status, urb_ptr->UrbHeader.Status); if (NT_SUCCESS(status)) status = urb_ptr->UrbHeader.Status; ExFreePool(configuration_descriptor); goto SetConfigurationDone; } dev->config.handle = urb_ptr->UrbSelectConfiguration.ConfigurationHandle; clear_pipe_info(dev); for (i = 0; i < configuration_descriptor->bNumInterfaces; i++) { update_pipe_info(dev, interfaces[i].Interface); } UpdateContextConfigDescriptor(dev, configuration_descriptor, desc_size, configuration_descriptor->bConfigurationValue, config_index); SetConfigurationDone: if (interfaces) ExFreePool(interfaces); if (urb_ptr) ExFreePool(urb_ptr); 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 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 USBCCGP_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; }