⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 umss.c

📁 微软提供的USB Mass Storage驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    //
    ntStatus = ioStatus.Status;

    RETURN(ntStatus, UMSS_CallUSBD);
}


NTSTATUS
UMSS_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 device.

Return Value:

    NT status code

--*/
{
    PDEVICE_EXTENSION deviceExtension;
    NTSTATUS ntStatus;
    PURB urb;
    ULONG siz;

    ENTER(UMSS_ConfigureDevice);

    deviceExtension = DeviceObject->DeviceExtension;

    UMSS_ASSERT( deviceExtension->UsbConfigurationDescriptor == NULL );

    urb = UMSS_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) + 512;  

    // We will break out of this 'retry loop' when UsbBuildGetDescriptorRequest()
    // has a big enough deviceExtension->UsbConfigurationDescriptor buffer not to truncate
    while( 1 )
    {
        deviceExtension->UsbConfigurationDescriptor = UMSS_ExAllocatePool(NonPagedPool, siz);

        if ( !deviceExtension->UsbConfigurationDescriptor )
        {
            UMSS_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 = UMSS_CallUSBD(DeviceObject, urb);

        UMSS_KdPrint( DBGLVL_HIGH,("UMSS_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;
            UMSS_ExFreePool(deviceExtension->UsbConfigurationDescriptor);
            deviceExtension->UsbConfigurationDescriptor = NULL;
        }
        else
        {
            break;  // we got it on the first try
        }

    } // end, while (retry loop )

    UMSS_ExFreePool(urb);
    UMSS_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 = UMSS_SelectInterface(
                   DeviceObject,
                   deviceExtension->UsbConfigurationDescriptor
                   );


    RETURN(ntStatus, UMSS_ConfigureDevice);
} 


NTSTATUS
UMSS_SelectInterface(
    IN PDEVICE_OBJECT DeviceObject,
    IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
    )
/*++
Routine Description:

    Initializes an device with (possibly) multiple interfaces;
    This minidriver only supports one interface (with multiple endpoints).

Arguments:

    DeviceObject - pointer to the device object for this instance of the 
                   device.
    ConfigurationDescriptor - pointer to the USB configuration
                   descriptor containing the interface and endpoint
                   descriptors.

Return Value:

    NT status code

--*/

{
    PDEVICE_EXTENSION deviceExtension;
    NTSTATUS ntStatus;
    PURB urb = NULL;
    ULONG i;
    USHORT siz;
    PUSBD_INTERFACE_LIST_ENTRY interfaceList = NULL;
    PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor = NULL;
    PUSBD_INTERFACE_INFORMATION Interface = NULL;

    ENTER(UMSS_SelectInterface);

    deviceExtension = DeviceObject->DeviceExtension;


    UMSS_KdPrint( DBGLVL_HIGH,("UMSS_SelectInterface() called with NULL Interface\n"));

    interfaceList = UMSS_ExAllocatePool(
                        PagedPool,
                        sizeof(USBD_INTERFACE_LIST_ENTRY) * 2);

    if (!interfaceList)
    {
        RETURN(STATUS_INSUFFICIENT_RESOURCES, UMSS_SelectInterface);
    }

    interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
                                  ConfigurationDescriptor,
                                  ConfigurationDescriptor, //search from start of config  descriptro
                                  -1,   // interface number not a criteria; we only support one interface
                                  -1,   // not interested in alternate setting here either
                                  -1,   // interface class not a criteria
                                  -1,   // interface subclass not a criteria
                                  -1    // interface protocol not a criteria
                                  );

    if ( !interfaceDescriptor )
    {
        UMSS_KdPrint( DBGLVL_HIGH,("UMSS_SelectInterface() ParseConfigurationDescriptorEx() failed\n  returning STATUS_INSUFFICIENT_RESOURCES\n"));
        UMSS_ExFreePool(interfaceList);
        RETURN(STATUS_INSUFFICIENT_RESOURCES, UMSS_SelectInterface);
    }

    interfaceList[0].InterfaceDescriptor = interfaceDescriptor;
    interfaceList[1].InterfaceDescriptor = NULL;

    urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor, interfaceList);

    UMSS_ExFreePool(interfaceList);

    if (urb)
    {
	Interface = &urb->UrbSelectConfiguration.Interface;

        for (i=0; i< Interface->NumberOfPipes; i++)
        {
	    //
	    // perform any pipe initialization here
	    //
	    Interface->Pipes[i].MaximumTransferSize = deviceExtension->MaximumTransferSize;
	    Interface->Pipes[i].PipeFlags = 0;
	}

        siz = GET_SELECT_CONFIGURATION_REQUEST_SIZE(1, Interface->NumberOfPipes);

	UsbBuildSelectConfigurationRequest(
            urb,
            siz,
            ConfigurationDescriptor);

        ntStatus = UMSS_CallUSBD(DeviceObject, urb);
    }
    else
    {
        UMSS_KdPrint( DBGLVL_HIGH,("UMSS_SelectInterface() USBD_CreateConfigurationRequest() failed\n  returning STATUS_INSUFFICIENT_RESOURCES\n"));

        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }

    if (NT_SUCCESS(ntStatus))
    {
        //
	// Save the configuration handle for this device
	//
	deviceExtension->UsbConfigurationHandle =
	    urb->UrbSelectConfiguration.ConfigurationHandle;
        
        deviceExtension->UsbInterface = UMSS_ExAllocatePool(
                                            NonPagedPool,
                                            Interface->Length
                                            );

        if (deviceExtension->UsbInterface)
        {
            // save a copy of the interface information returned
            RtlCopyMemory(deviceExtension->UsbInterface, Interface, Interface->Length);

            Interface = deviceExtension->UsbInterface;
        }
        else
        {
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        }
    }

    if (NT_SUCCESS(ntStatus))
    {
        // Per Q200977, we must re-select the interface to get the correct
        // max transfer size if this is a composite device

        siz = GET_SELECT_INTERFACE_REQUEST_SIZE (Interface->NumberOfPipes);

        RtlZeroMemory(urb, siz);

        urb->UrbSelectInterface.Hdr.Length = siz;
        urb->UrbSelectInterface.Hdr.Function = URB_FUNCTION_SELECT_INTERFACE;
        urb->UrbSelectInterface.ConfigurationHandle = deviceExtension->UsbConfigurationHandle;

        for (i=0; i< Interface->NumberOfPipes; i++)
        {
	    Interface->Pipes[i].MaximumTransferSize = deviceExtension->MaximumTransferSize;
	}

        RtlCopyMemory(
            &urb->UrbSelectInterface.Interface,
            Interface,
            Interface->Length);

        ntStatus = UMSS_CallUSBD(DeviceObject, urb);
    }

    if (NT_SUCCESS(ntStatus))
    {
        ULONG j;

        // save a copy of the interface information returned (again)
        RtlCopyMemory(
            deviceExtension->UsbInterface,
            &urb->UrbSelectInterface.Interface,
            urb->UrbSelectInterface.Interface.Length);

        //
        // Dump the interface to the debugger
        //
        UMSS_KdPrint( 1,("---------\n"));
        UMSS_KdPrint( 1,("NumberOfPipes 0x%x\n", deviceExtension->UsbInterface->NumberOfPipes));
        UMSS_KdPrint( 1,("Length 0x%x\n", deviceExtension->UsbInterface->Length));
        UMSS_KdPrint( 1,("Alt Setting 0x%x\n", deviceExtension->UsbInterface->AlternateSetting));
        UMSS_KdPrint( 1,("Interface Number 0x%x\n", deviceExtension->UsbInterface->InterfaceNumber));
        UMSS_KdPrint( 1,("Class, subclass, protocol 0x%x 0x%x 0x%x\n",
            deviceExtension->UsbInterface->Class,
            deviceExtension->UsbInterface->SubClass,
            deviceExtension->UsbInterface->Protocol));

        // Dump the pipe info
        for (j=0; j<Interface->NumberOfPipes; j++)
        {
            PUSBD_PIPE_INFORMATION pipeInformation;
            pipeInformation = &deviceExtension->UsbInterface->Pipes[j];

            UMSS_KdPrint( 1,("---------\n"));
            UMSS_KdPrint( 1,("PipeType 0x%x\n", pipeInformation->PipeType));
            UMSS_KdPrint( 1,("EndpointAddress 0x%x\n", pipeInformation->EndpointAddress));
            UMSS_KdPrint( 1,("MaxPacketSize 0x%x\n", pipeInformation->MaximumPacketSize));
            UMSS_KdPrint( 1,("Interval 0x%x\n", pipeInformation->Interval));
            UMSS_KdPrint( 1,("Handle 0x%x\n", pipeInformation->PipeHandle));
            UMSS_KdPrint( 1,("MaximumTransferSize 0x%x\n", pipeInformation->MaximumTransferSize));

            switch (pipeInformation->PipeType)
            {
                 case UsbdPipeTypeBulk:
                     if (USBD_PIPE_DIRECTION_IN(pipeInformation))
                     {
                         UMSS_KdPrint( 1,("DataInPipe 0x%x\n", j));
                         deviceExtension->DataInPipe = j;
                     }
                     else
                     {
                         UMSS_KdPrint( 1,("DataOutPipe 0x%x\n", j));
                         deviceExtension->DataOutPipe = j;
                     }
                     break;
			

                 case UsbdPipeTypeInterrupt:
                     UMSS_KdPrint( 1,("StatusPipe 0x%x\n", j));
                     deviceExtension->StatusPipe = j;
                     break;


                 default:
                     UMSS_KdPrint( 1,("Unknown pipe 0x%x\n", j));
                     break;
            }
        }

        UMSS_KdPrint( DBGLVL_MEDIUM,("---------\n"));


        // Figure out the protocol this storage device uses
        deviceExtension->DeviceProtocol = PROTOCOL_UNDEFINED;

        if (!UMSS_GetDeviceProtocolFromRegistry(DeviceObject))
        {
            if (!UMSS_GetDeviceProtocolFromDescriptor(DeviceObject))
            {
                // Can't determine device protocol
                ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
            }
        }
    }


    if (PROTOCOL_BULKONLY == deviceExtension->DeviceProtocol)
    {
        // Query device for max LUN number
        deviceExtension->MaxLun = UMSS_BulkOnlyGetMaxLun(deviceExtension);
    }
    else
    {
        // CBI protocol doesn't implement LUNs, so set to 0
        deviceExtension->MaxLun = 0;
    }

    if (urb)
    {
        // don't call the UMSS_ExFreePool since the buffer was 
        //  alloced by USBD_CreateConfigurationRequest, not UMSS_ExAllocatePool()
        ExFreePool(urb);
    }

    RETURN(ntStatus, UMSS_SelectInterface);
}



NTSTATUS
UMSS_ResetPipe(
    IN PDEVICE_OBJECT DeviceObject,
    USBD_PIPE_HANDLE PipeHandle
    )
/*++
Routine Description:

    Reset a given USB pipe.

    NOTES:

    This will reset the host to Data0 and should also reset the device to Data0 

Arguments:

    Ptrs to our FDO and a USBD_PIPE_INFORMATION struct

Return Value:

    NT status code

--*/

{
    NTSTATUS ntStatus;
    PURB urb;
    PDEVICE_EXTENSION deviceExtension;

    deviceExtension = DeviceObject->DeviceExtension;

    ENTER(UMSS_ResetPipe);

    UMSS_KdPrint( DBGLVL_DEFAULT,("UMSS_ResetPipe() Reset Pipe %x\n", PipeHandle));

    urb = UMSS_ExAllocatePool(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));

    if (urb)
    {
	urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
	urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
        urb->UrbPipeRequest.PipeHandle = PipeHandle;

        ntStatus = UMSS_CallUSBD(DeviceObject, urb);

        UMSS_ExFreePool(urb);

    }
    else
    {
	ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }

    if (!(NT_SUCCESS(ntStatus)))
    {

#if DBG
        if ( gpDbg )
            gpDbg->PipeErrorCount++;
#endif
        UMSS_KdPrint( DBGLVL_DEFAULT,("UMSS_ResetPipe() FAILED, ntStatus =0x%x\n", ntStatus ));

    }
    else
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -