Ejemplo n.º 1
0
// 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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 4
0
// 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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
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;
}