// Get Usb Configuration Descriptor NTSTATUS UsbDev::GetConfigurationDescriptor() { NTSTATUS ntStatus = STATUS_SUCCESS; PURB pUrb; ULONG siz; UCHAR index; PUSB_CONFIGURATION_DESCRIPTOR pTemp_pConfigDesc = NULL; DBGU_TRACE(">>>UsbDev::GetConfigurationDescriptor !\n"); pUrb = (PURB) ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), USBDEV_POOLTAG); if(pUrb) {//pUrb != NULL RtlZeroMemory(pUrb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); for(index=0;index<m_DevDesc.bNumConfigurations;index++) {//travel all configurations siz = 64; get_config_descriptor_retry: if(pTemp_pConfigDesc) ExFreePoolWithTag(pTemp_pConfigDesc,USBDEV_POOLTAG); if ((pTemp_pConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR) ExAllocatePoolWithTag(NonPagedPool, siz, USBDEV_POOLTAG))) {//pTemp_pConfigDesc != NULL RtlZeroMemory(pTemp_pConfigDesc,siz); UsbBuildGetDescriptorRequest( pUrb, (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), USB_CONFIGURATION_DESCRIPTOR_TYPE, index, 0, pTemp_pConfigDesc, NULL, siz, NULL); ntStatus = SendAwaitUrb(pUrb); if(!NT_SUCCESS(ntStatus)) {//ntStatus != STATUS_SUCCESS DBGU_TRACE("ERR: Fail to get configuration descriptor !!\n"); ExFreePoolWithTag(pTemp_pConfigDesc,USBDEV_POOLTAG); ntStatus = STATUS_INSUFFICIENT_RESOURCES; break; }//ntStatus != STATUS_SUCCESS if ((pUrb->UrbControlDescriptorRequest.TransferBufferLength>0) && \ (pTemp_pConfigDesc->wTotalLength>siz)) { siz = pTemp_pConfigDesc->wTotalLength; goto get_config_descriptor_retry; } m_pConfigDesc[index] = pTemp_pConfigDesc; pTemp_pConfigDesc = NULL; // Print configuration descriptor DBGU_TRACE(" Configuration Descriptor: %x\n",index); DBGU_TRACE(" -------------------------\n"); DBGU_TRACE(" bLength %x\n",m_pConfigDesc[index]->bLength); DBGU_TRACE(" bDescriptorType %x\n",m_pConfigDesc[index]->bDescriptorType); DBGU_TRACE(" wTotalLength %x\n",m_pConfigDesc[index]->wTotalLength); DBGU_TRACE(" bNumInterfaces %x\n",m_pConfigDesc[index]->bNumInterfaces); DBGU_TRACE(" bConfigurationValue %x\n",m_pConfigDesc[index]->bConfigurationValue); DBGU_TRACE(" iConfiguration %x\n",m_pConfigDesc[index]->iConfiguration); DBGU_TRACE(" MaxPower %x\n",m_pConfigDesc[index]->MaxPower); DBGU_TRACE(" -------------------------\n"); }//pTemp_pConfigDesc != NULL else {//pTemp_pConfigDesc == NULL DBGU_TRACE("ERR: Fail to allocate memory for m_pConfigDesc !!\n"); ntStatus = STATUS_INSUFFICIENT_RESOURCES; break; }//pTemp_pConfigDesc == NULL }//travel all configurations }//pUrb != NULL else {//pUrb == NULL DBGU_TRACE("ERR: Fail to allocate memory for pUrb !!\n"); ntStatus = STATUS_INSUFFICIENT_RESOURCES; }//pUrb == NULL if(pUrb) ExFreePoolWithTag(pUrb,USBDEV_POOLTAG); return ntStatus; }
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 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; }
// Get Usb Device Descriptor NTSTATUS UsbDev::GetDeviceDescriptor() { NTSTATUS ntStatus; PURB pUrb; DBGU_TRACE(">>>UsbDev::GetDeviceDescriptor !\n"); pUrb = (PURB) ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), USBDEV_POOLTAG); if (pUrb) {//pUrb != NULL RtlZeroMemory((void *) pUrb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); UsbBuildGetDescriptorRequest( pUrb, (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, &m_DevDesc, NULL, sizeof(USB_DEVICE_DESCRIPTOR), NULL); ntStatus = SendAwaitUrb(pUrb); ExFreePoolWithTag(pUrb,USBDEV_POOLTAG); #if DBG if (NT_SUCCESS(ntStatus)) { //Print the infomation of device descriptor DBGU_TRACE(" Device Descriptor:\n"); DBGU_TRACE(" -------------------------\n"); DBGU_TRACE(" bLength %x\n", m_DevDesc.bLength); DBGU_TRACE(" bDescriptorType 0x%x\n", m_DevDesc.bDescriptorType); DBGU_TRACE(" bcdUSB 0x%x\n", m_DevDesc.bcdUSB); DBGU_TRACE(" bDeviceClass 0x%x\n", m_DevDesc.bDeviceClass); DBGU_TRACE(" bDeviceSubClass 0x%x\n", m_DevDesc.bDeviceSubClass); DBGU_TRACE(" bDeviceProtocol 0x%x\n", m_DevDesc.bDeviceProtocol); DBGU_TRACE(" bMaxPacketSize0 0x%x\n", m_DevDesc.bMaxPacketSize0); DBGU_TRACE(" idVendor 0x%x\n", m_DevDesc.idVendor); DBGU_TRACE(" idProduct 0x%x\n", m_DevDesc.idProduct); DBGU_TRACE(" bcdDevice 0x%x\n", m_DevDesc.bcdDevice); DBGU_TRACE(" iManufacturer 0x%x\n", m_DevDesc.iManufacturer); DBGU_TRACE(" iProduct 0x%x\n", m_DevDesc.iProduct); DBGU_TRACE(" iSerialNumber 0x%x\n", m_DevDesc.iSerialNumber); DBGU_TRACE(" bNumConfigurations 0x%x\n", m_DevDesc.bNumConfigurations); DBGU_TRACE(" -------------------------\n"); } else { DBGU_TRACE("ERR: Cannot get device descriptor !!\n"); } #endif }//pUrb != NULL else {//pUrb == NULL DBGU_TRACE("ERR: Fail to allocate memory for pUrb !!\n"); ntStatus = STATUS_INSUFFICIENT_RESOURCES; }//pUrb == NULL return ntStatus; }
NTSTATUS UpdateDeviceInformation( PDEVICE_OBJECT fdo ) { PUSB_STRING_DESCRIPTOR desc; UNICODE_STRING dummy; URB urb; int id; NTSTATUS status; KdPrint((DRIVERNAME " - UpdateDeviceInformation\n")); status = STATUS_SUCCESS; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; // initialize buffers pdx->manufacturer.Buffer = NULL; pdx->product .Buffer = NULL; pdx->serialNumber.Buffer = NULL; pdx->displayName .Buffer = NULL; desc = NULL; // allocate buffers for all strings pdx->manufacturer.Buffer = (WCHAR*)ExAllocatePoolWithTag(NonPagedPool, StringDescriptorBytes, SPOT_TAG ); pdx->product .Buffer = (WCHAR*)ExAllocatePoolWithTag(NonPagedPool, StringDescriptorBytes, SPOT_TAG ); pdx->serialNumber.Buffer = (WCHAR*)ExAllocatePoolWithTag(NonPagedPool, StringDescriptorBytes, SPOT_TAG ); pdx->displayName .Buffer = (WCHAR*)ExAllocatePoolWithTag(NonPagedPool, StringDescriptorBytes, SPOT_TAG ); if( (pdx->manufacturer.Buffer == NULL) || (pdx->product .Buffer == NULL) || (pdx->serialNumber.Buffer == NULL) || (pdx->displayName .Buffer == NULL) ) { KdPrint((DRIVERNAME " - Unable to allocate memory for device info\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } pdx->manufacturer.Length = 0; pdx->manufacturer.MaximumLength = StringDescriptorBytes; pdx->product .Length = 0; pdx->product .MaximumLength = StringDescriptorBytes; pdx->serialNumber.Length = 0; pdx->serialNumber.MaximumLength = StringDescriptorBytes; pdx->displayName .Length = 0; pdx->displayName .MaximumLength = StringDescriptorBytes; // allocate buffer for device string descriptor requests 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; } if(0 != pdx->dd.iManufacturer) { // Manufacturer UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_STRING_DESCRIPTOR_TYPE, pdx->dd.iManufacturer, LangId, desc, NULL, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, NULL); status = SendAwaitUrb(fdo, &urb); if(NT_SUCCESS(status)) { desc->bString[ (desc->bLength / 2) - 1 ] = L'\0'; RtlInitUnicodeString( &dummy , desc->bString ); RtlCopyUnicodeString( &pdx->manufacturer, &dummy ); } else { RtlInitUnicodeString( &dummy , EmptyString ); RtlCopyUnicodeString( &pdx->manufacturer, &dummy ); KdPrint(( DRIVERNAME " - could not retrieve manufacturer %08x\n", status )); } } if(0 != pdx->dd.iProduct) { // Product UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_STRING_DESCRIPTOR_TYPE, pdx->dd.iProduct, LangId, desc, NULL, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, NULL); status = SendAwaitUrb(fdo, &urb); if(NT_SUCCESS(status)) { desc->bString[ (desc->bLength / 2) - 1 ] = L'\0'; RtlInitUnicodeString( &dummy , desc->bString ); RtlCopyUnicodeString( &pdx->product, &dummy ); } else { RtlInitUnicodeString( &dummy , EmptyString ); RtlCopyUnicodeString( &pdx->product, &dummy ); KdPrint(( DRIVERNAME " - could not retrieve product %08x\n", status )); } } if(0 != pdx->dd.iSerialNumber) { // Serial Number UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_STRING_DESCRIPTOR_TYPE, pdx->dd.iSerialNumber, LangId, desc, NULL, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, NULL); status = SendAwaitUrb(fdo, &urb); if(NT_SUCCESS(status)) { desc->bString[ (desc->bLength / 2) - 1 ] = L'\0'; RtlInitUnicodeString( &dummy , desc->bString ); RtlCopyUnicodeString( &pdx->serialNumber, &dummy ); } else { RtlInitUnicodeString( &dummy , EmptyString ); RtlCopyUnicodeString( &pdx->serialNumber, &dummy ); KdPrint(( DRIVERNAME " - could not retrieve serial number %08x\n", status )); } } // DisplayName UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_STRING_DESCRIPTOR_TYPE, DisplayNameId, LangId, desc, NULL, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, NULL); status = SendAwaitUrb(fdo, &urb); if(NT_SUCCESS(status)) { desc->bString[ (desc->bLength / 2) - 1 ] = L'\0'; RtlInitUnicodeString( &dummy , desc->bString ); RtlCopyUnicodeString( &pdx->displayName, &dummy ); } else { RtlInitUnicodeString( &dummy , EmptyString ); RtlCopyUnicodeString( &pdx->displayName, &dummy ); KdPrint(( DRIVERNAME " - could not retrieve display name %08x\n", status )); } cleanup: if(desc) ExFreePool( desc ); if(!NT_SUCCESS(status)) { if(pdx->manufacturer.Buffer) ExFreePool( pdx->manufacturer.Buffer ); if(pdx->product .Buffer) ExFreePool( pdx->product .Buffer ); if(pdx->serialNumber.Buffer) ExFreePool( pdx->serialNumber.Buffer ); if(pdx->displayName .Buffer) ExFreePool( pdx->displayName .Buffer ); pdx->manufacturer.Buffer = NULL; pdx->product .Buffer = NULL; pdx->serialNumber.Buffer = NULL; pdx->displayName .Buffer = NULL; } return status; }
NTSTATUS NTAPI USBSTOR_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 = USBSTOR_SyncUrbRequest(DeviceObject, Urb); // // free urb // FreeItem(Urb); if (NT_SUCCESS(Status)) { // // store result // *OutDescriptor = Descriptor; } // // done // 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; }
VOID NTAPI WorkerThread(IN PVOID Context) { PHUB_DEVICE_EXTENSION DeviceExtension; PDEVICE_OBJECT DeviceObject, Pdo; PHUB_CHILDDEVICE_EXTENSION PdoExtension; PURB Urb = NULL; PORTSTATUSANDCHANGE PortStatusAndChange; int PortLoop, DeviceCount; NTSTATUS Status; USB_DEVICE_DESCRIPTOR DevDesc; USB_CONFIGURATION_DESCRIPTOR ConfigDesc; ULONG DevDescSize, ConfigDescSize; PUSB_STRING_DESCRIPTOR StringDesc; USB_STRING_DESCRIPTOR LanguageIdDescriptor; PWORKITEMDATA WorkItemData = (PWORKITEMDATA)Context; DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context; DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; /* Determine where in the children array to store this device info */ for (DeviceCount = 0; DeviceCount < USB_MAXCHILDREN; DeviceCount++) { if (DeviceExtension->UsbChildren[DeviceCount] == NULL) { break; } } Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); if (!Urb) { DPRINT1("Failed to allocate memory for URB!\n"); ASSERT(FALSE); } RtlZeroMemory(Urb, sizeof(URB)); for (PortLoop = 0; PortLoop < DeviceExtension->UsbExtHubInfo.NumberOfPorts; PortLoop++) { /* Get the port 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); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to get PortStatus!\n"); goto CleanUp; } DPRINT("Notification Port %x:\n", PortLoop + 1); DPRINT("Status %x\n", PortStatusAndChange.Status); DPRINT("Change %x\n", PortStatusAndChange.Change); if (PortStatusAndChange.Change == USB_PORT_STATUS_RESET) { /* Clear the Reset */ UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_REQUEST_CLEAR_FEATURE, C_PORT_RESET, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Clear the Port Reset with Status %x!\n", Status); goto CleanUp; } 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); DPRINT("Status %x\n", PortStatusAndChange.Status); DPRINT("Change %x\n", PortStatusAndChange.Change); /* Create the UsbDevice */ Status = DeviceExtension->HubInterface.CreateUsbDevice(DeviceExtension->RootHubPdo, (PVOID)&DeviceExtension->UsbChildren[DeviceCount], DeviceExtension->RootHubUsbDevice, PortStatusAndChange.Status, PortLoop + 1); DPRINT1("CreateUsbDevice Status %x\n", Status); Status = DeviceExtension->HubInterface.InitializeUsbDevice(DeviceExtension->RootHubPdo, DeviceExtension->UsbChildren[DeviceCount]); DPRINT1("InitializeUsbDevice Status %x\n", Status); DevDescSize = sizeof(USB_DEVICE_DESCRIPTOR); ConfigDescSize = sizeof(USB_CONFIGURATION_DESCRIPTOR); Status = DeviceExtension->HubInterface.GetUsbDescriptors(DeviceExtension->RootHubPdo, DeviceExtension->UsbChildren[DeviceCount], (PUCHAR)&DevDesc, &DevDescSize, (PUCHAR)&ConfigDesc, &ConfigDescSize); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Get Usb Deccriptors %x!\n", Status); } DumpDeviceDescriptor(&DevDesc); Status = IoCreateDevice(DeviceObject->DriverObject, sizeof(HUB_CHILDDEVICE_EXTENSION), NULL, FILE_DEVICE_CONTROLLER, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &DeviceExtension->Children[DeviceCount]); if (!NT_SUCCESS(Status)) { DPRINT1("UsbHub; IoCreateDevice failed with status %x\n",Status); goto CleanUp; } Pdo = DeviceExtension->Children[DeviceCount]; DPRINT1("Created New Device with %x\n", Pdo); Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; PdoExtension = Pdo->DeviceExtension; RtlZeroMemory(PdoExtension, sizeof(HUB_CHILDDEVICE_EXTENSION)); PdoExtension->DeviceId = ExAllocatePoolWithTag(NonPagedPool, 32 * sizeof(WCHAR), USB_HUB_TAG); RtlZeroMemory(PdoExtension->DeviceId, 32 * sizeof(WCHAR)); swprintf(PdoExtension->DeviceId, L"USB\\Vid_%04x&Pid_%04x", DevDesc.idVendor, DevDesc.idProduct); /* Get the LANGids */ RtlZeroMemory(&LanguageIdDescriptor, sizeof(USB_STRING_DESCRIPTOR)); UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_STRING_DESCRIPTOR_TYPE, 0, 0, &LanguageIdDescriptor, NULL, sizeof(USB_STRING_DESCRIPTOR), NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount]; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); /* Get the length of the SerialNumber */ StringDesc = ExAllocatePoolWithTag(PagedPool, 64, USB_HUB_TAG); RtlZeroMemory(StringDesc, 64); StringDesc->bLength = 0; StringDesc->bDescriptorType = 0; UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_STRING_DESCRIPTOR_TYPE, DevDesc.iSerialNumber, LanguageIdDescriptor.bString[0], StringDesc, NULL, 64, NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount]; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); PdoExtension->InstanceId = ExAllocatePoolWithTag(NonPagedPool, (StringDesc->bLength + 1) * sizeof(WCHAR), USB_HUB_TAG); DPRINT1("PdoExtension->InstanceId %x\n",PdoExtension->InstanceId); RtlZeroMemory(PdoExtension->InstanceId, (StringDesc->bLength + 1) * sizeof(WCHAR)); RtlCopyMemory(PdoExtension->InstanceId, &StringDesc->bString[0], StringDesc->bLength); DPRINT1("------>SerialNumber %S\n", PdoExtension->InstanceId); RtlZeroMemory(StringDesc, 64); StringDesc->bLength = 0; StringDesc->bDescriptorType = 0; UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_STRING_DESCRIPTOR_TYPE, DevDesc.iProduct, LanguageIdDescriptor.bString[0], StringDesc, NULL, 64, NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount]; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); PdoExtension->TextDescription = ExAllocatePoolWithTag(NonPagedPool, (StringDesc->bLength + 1) * sizeof(WCHAR), USB_HUB_TAG); RtlZeroMemory(PdoExtension->TextDescription, (StringDesc->bLength + 1) * sizeof(WCHAR)); RtlCopyMemory(PdoExtension->TextDescription, &StringDesc->bString[0], StringDesc->bLength); ExFreePool(StringDesc); DPRINT1("------>TextDescription %S\n", PdoExtension->TextDescription); PdoExtension->IsFDO = FALSE; PdoExtension->Parent = DeviceObject; Pdo->Flags &= ~DO_DEVICE_INITIALIZING; ExFreePool(WorkItemData); ExFreePool(Urb); IoInvalidateDeviceRelations(DeviceExtension->RootHubPdo, BusRelations); return; } /* Is a device connected to this port */ if (PortStatusAndChange.Change == USB_PORT_STATUS_CONNECT) { /* Clear the Connect from ProtChange */ UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_REQUEST_CLEAR_FEATURE, C_PORT_CONNECTION, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Clear the Port Connect!\n"); goto CleanUp; } /* Send the miniport controller a SCE request so when the port resets we can be informed */ WaitForUsbDeviceArrivalNotification(DeviceObject); UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_REQUEST_SET_FEATURE, PORT_RESET, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Reset the port!\n"); goto CleanUp; } /* At this point the miniport will complete another SCE to inform of Reset completed */ } } CleanUp: ExFreePool(WorkItemData); ExFreePool(Urb); }
NTSTATUS IsoUsb_ConfigureDevice( IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: Initializes a given instance of the device on the USB and selects and saves the configuration. Arguments: DeviceObject - pointer to the physical device object for this instance of the 82930 device. Return Value: NT status code --*/ { PDEVICE_EXTENSION deviceExtension; NTSTATUS ntStatus; PURB urb; ULONG siz; ISOUSB_KdPrint( DBGLVL_HIGH,("enter IsoUsb_ConfigureDevice\n")); deviceExtension = DeviceObject->DeviceExtension; ISOUSB_ASSERT( deviceExtension->UsbConfigurationDescriptor == NULL ); urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); if ( !urb ) return STATUS_INSUFFICIENT_RESOURCES; // When USB_CONFIGURATION_DESCRIPTOR_TYPE is specified for DescriptorType // in a call to UsbBuildGetDescriptorRequest(), // all interface, endpoint, class-specific, and vendor-specific descriptors // for the configuration also are retrieved. // The caller must allocate a buffer large enough to hold all of this // information or the data is truncated without error. // Therefore the 'siz' set below is just a 'good guess', and we may have to retry siz = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 128; // We will break out of this 'retry loop' when UsbBuildGetDescriptorRequest() // has a big enough deviceExtension->UsbConfigurationDescriptor buffer not to truncate while( 1 ) { deviceExtension->UsbConfigurationDescriptor = ExAllocatePool(NonPagedPool, siz); if ( !deviceExtension->UsbConfigurationDescriptor ) { ExFreePool(urb); return STATUS_INSUFFICIENT_RESOURCES; } UsbBuildGetDescriptorRequest(urb, (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, deviceExtension->UsbConfigurationDescriptor, NULL, siz, NULL); ntStatus = IsoUsb_CallUSBD(DeviceObject, urb); ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_CallUSBD() Configuration Descriptor = %x, len %x\n", deviceExtension->UsbConfigurationDescriptor, urb->UrbControlDescriptorRequest.TransferBufferLength)); // // if we got some data see if it was enough. // NOTE: we may get an error in URB because of buffer overrun if (urb->UrbControlDescriptorRequest.TransferBufferLength>0 && deviceExtension->UsbConfigurationDescriptor->wTotalLength > siz) { siz = deviceExtension->UsbConfigurationDescriptor->wTotalLength; ExFreePool(deviceExtension->UsbConfigurationDescriptor); deviceExtension->UsbConfigurationDescriptor = NULL; } else { break; // we got it on the first try } } // end, while (retry loop ) ExFreePool(urb); ISOUSB_ASSERT( deviceExtension->UsbConfigurationDescriptor ); // // We have the configuration descriptor for the configuration we want. // Now we issue the select configuration command to get // the pipes associated with this configuration. // ntStatus = IsoUsb_SelectInterface(DeviceObject, deviceExtension->UsbConfigurationDescriptor); ISOUSB_KdPrint( DBGLVL_HIGH,("exit IsoUsb_ConfigureDevice (%x)\n", ntStatus)); return ntStatus; }