UsbStorage驱动开发

前段时间发现有网友在开发驱动的过程中遇到问题,所以今天我整理了一下我在写驱动中的一点心得。希望大家指导!

    win2k的UsbStorage不需要驱动程序就能运行,但是如果我们的设备有特殊功能,像前几天有网友问的那种要显示自已的标号的。那么UsbStor.sys就不能满足我们的需求。当然如果要实现自己的功能,我们也只需要UsbStor.sys的基础上修改就行了!
    USB磁盘驱动程序是一个BUS DRIVER,它的主要入口如下:
    NTSTATUS
DriverEntry(
            IN PDRIVER_OBJECT DriverObject,
            IN PUNICODE_STRING pRegistryPath
            )
{
#if    DBG
    DbgPrint("Enter UsbStore DriverEntry!/n");
#endif     
    DriverObject->DriverExtension->AddDevice = UsbStore_AddDevice;
    DriverObject->DriverUnload = UsbStore_Unload;
    DriverObject->DriverStartIo = UsbStore_StartIo;

    DriverObject->MajorFunction[IRP_MJ_CREATE] =  
    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = UsbStore_CreateClose;
    DriverObject->MajorFunction[IRP_MJ_READ]   =
    DriverObject->MajorFunction[IRP_MJ_WRITE]  = UsbStore_ReadWrite;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = UsbStore_DeviceIoControl;
    DriverObject->MajorFunction[IRP_MJ_SCSI]   = UsbStore_Scsi;
    DriverObject->MajorFunction[IRP_MJ_PNP]    = UsbStore_Pnp;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = UsbStore_SystemControl;
    DriverObject->MajorFunction[IRP_MJ_POWER]  = UsbStore_Power;
     
    return STATUS_SUCCESS;
}
USB STORAGE DRIVER对设备的主要操作MajorFunction是IRP_MJ_SCSI,而不是IRP_MJ_READ 以及IRP_MJ_WRITE 。
USB STORAGE DRIVER的上层程序是CLASS DRIVER。CLASS DRIVER对上层的USB磁盘的读写等操作转换成IRP_MJ_SCSI,USB STORAGE DRIVER根据USB CBI规范和BULK ONLY规范将上层DRIVER传送来的IRP_MJ_SCSI的SRB(SCSI_REQUEST_BLOCK)的相关部分传递给设备。
UsbStore_AddDevice的功能是建立USB STORAGE DRIVER的FDO。
NTSTATUS
UsbStore_AddDevice(
                   IN PDRIVER_OBJECT DriverObject,
                   IN PDEVICE_OBJECT PhysicalDeviceObject
                   )
{
    NTSTATUS status;
    PUSB_DEVICE_EXTENSION pUsb_DeviceExtension;
    PDEVICE_OBJECT USbStore_FileDeviceObject = NULL;
    KEVENT Event;
#if    DBG
    DbgPrint("Enter AddDevice Dispatch!/n");
#endif
     
    status = IoCreateDevice(
                   DriverObject,
                   sizeof(USB_DEVICE_EXTENSION),
                   NULL,
                   FILE_DEVICE_BUS_EXTENDER,
                   FILE_AUTOGENERATED_DEVICE_NAME ,
                   FALSE,
                   &USbStore_FileDeviceObject
                   );
    if(!NT_SUCCESS(status))
    {
#if DBG
        DbgPrint("IoCreateDevice Failed!/n");
#endif
        return status;
    }

    pUsb_DeviceExtension = (PUSB_DEVICE_EXTENSION)USbStore_FileDeviceObject->DeviceExtension;
    RtlZeroMemory(pUsb_DeviceExtension,sizeof(USB_DEVICE_EXTENSION));
     
    pUsb_DeviceExtension->DeviceType = USBSTORE_FDO;
    pUsb_DeviceExtension->UsbFileDeviceObject = USbStore_FileDeviceObject;
    pUsb_DeviceExtension->UsbPhysicalDeviceObject = PhysicalDeviceObject;
     
    pUsb_DeviceExtension->SystemPowerState = PowerSystemWorking;
    pUsb_DeviceExtension->CurrentPowerState = PowerDeviceD0;

    pUsb_DeviceExtension->UsbStore_TopOfStackDeviceObject =  
                            IoAttachDeviceToDeviceStack(
                                                        USbStore_FileDeviceObject,
                                                        PhysicalDeviceObject
                                                        );
    KeInitializeEvent(
                      &Event,
                      SynchronizationEvent,
                      FALSE
                      );
    pUsb_DeviceExtension->Usb_Event = Event;

    UsbStore_GetDriverFlags(USbStore_FileDeviceObject);
     
    USbStore_FileDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
    USbStore_FileDeviceObject->Flags |= DO_DIRECT_IO;
    USbStore_FileDeviceObject->Flags |= DO_POWER_PAGABLE;

    return STATUS_SUCCESS;
}

//UsbStore_GetDriverFlags
NTSTATUS
UsbStore_GetDriverFlags(
                        IN PDEVICE_OBJECT UsbFdo
                        )
{
    PUSB_DEVICE_EXTENSION pUsb_DeviceExtension;
    NTSTATUS status;
    HANDLE RegHandle;
    RTL_QUERY_REGISTRY_TABLE RegTable;

    ULONG Value = 0;
    RtlZeroMemory(&RegTable,sizeof(RTL_QUERY_REGISTRY_TABLE));
    pUsb_DeviceExtension = UsbFdo->DeviceExtension;
    status = IoOpenDeviceRegistryKey(
                                     pUsb_DeviceExtension->UsbPhysicalDeviceObject,
                                     PLUGPLAY_REGKEY_DRIVER,
                                     STANDARD_RIGHTS_ALL,
                                     &RegHandle
                                     );
    if(NT_SUCCESS(status))
    {
        RegTable.Flags = RTL_QUERY_REGISTRY_DIRECT;
        RegTable.Name = L"DriverFlags";
        RegTable.EntryContext = &Value;
        RegTable.DefaultType = REG_DWORD;
        RegTable.DefaultData = &Value;
        RegTable.DefaultLength = sizeof(ULONG);

        status = RtlQueryRegistryValues(
                                        RTL_REGISTRY_HANDLE,
                                        RegHandle,
                                        &RegTable,
                                        NULL,
                                        NULL
                                        );
        if(!NT_SUCCESS(status))
        {
#if DBG
            DbgPrint("RtlQueryRegistryValues Failed!/n");
#endif
            return status;
        }
        ZwClose(RegHandle);  
    }

    if(Value>=4)
        Value =0;
    pUsb_DeviceExtension->DriverFlags = Value;     
     
    return status;
}
在这段代码中,
status = IoCreateDevice(
                   DriverObject,
                   sizeof(USB_DEVICE_EXTENSION),
                   NULL,
                   FILE_DEVICE_BUS_EXTENDER,
                   FILE_AUTOGENERATED_DEVICE_NAME ,
                   FALSE,
                   &USbStore_FileDeviceObject
                   );
负责建立一个USB STORAGE DRIVER的FDO,请各位注意,设备的类型(DEVICE TYPE)是FILE_DEVICE_BUS_EXTENDER。
取注册表的一段代码,主要负责是取出DRIVER FLAGS,它用于标记设备是满足CBI规范还是BULK ONLY规范。

UsbStore_ReadWrite这一函数不做任何实际有用的读写操作。

 

NTSTATUS UsbStore_ReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )

{

#if DBG

DbgPrint("Enter ReadWrite Dispatch!/n");

#endif

Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;

 Irp->IoStatus.Information = 0;

IoCompleteRequest(Irp,IO_NO_INCREMENT);

return STATUS_INVALID_PARAMETER;

}

 

UsbStore_Scsi将上层DRIVER的IRP_MJ_SCSI的请求排队,

 

NTSTATUS UsbStore_Scsi(IN PDEVICE_OBJECT UsbStorePdo, IN PIRP Irp)

{

PUSBSTORE_DEVICE_EXTENSION pUsbStoreDeviceExtension = UsbStorePdo->DeviceExtension;

PIO_STACK_LOCATION irpStackLocation = IoGetCurrentIrpStackLocation(Irp);

PSCSI_REQUEST_BLOCK Srb = irpStackLocation->Parameters.Scsi.Srb;

NTSTATUS status;

KIRQL Irql;

 if(pUsbStoreDeviceExtension->DeviceType == USBSTORE_PDO)

{

 if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI)

{

if(Srb->DataTransferLength <=0x10000)

{

Srb->SrbStatus = SRB_STATUS_PENDING;

IoMarkIrpPending(Irp);

IoStartPacket(UsbStorePdo, Irp, &Srb->QueueSortKey, (PDRIVER_CANCEL)UsbStore_CancelRoutine);

status = STATUS_PENDING;

}

else

{

status = STATUS_INVALID_PARAMETER;

}

}

else if(Srb->Function == SRB_FUNCTION_CLAIM_DEVICE)

{

KeAcquireSpinLock(&pUsbStoreDeviceExtension->SpinLock, &Irql);

if(pUsbStoreDeviceExtension->DeviceFlags&0x01)

{

status = STATUS_END_OF_FILE;

Srb->SrbStatus = SRB_STATUS_BUSY;

}

else

{

pUsbStoreDeviceExtension->DeviceFlags|=0x01;

Srb->DataBuffer = UsbStorePdo;

Srb->SrbStatus = SRB_STATUS_SUCCESS;

}

 

KeReleaseSpinLock(&pUsbStoreDeviceExtension->SpinLock, Irql);

}

else if(Srb->Function == SRB_FUNCTION_RELEASE_DEVICE)

{

KeAcquireSpinLock(&pUsbStoreDeviceExtension->SpinLock,&Irql);

pUsbStoreDeviceExtension->DeviceFlags &= 0xFFFFFFFE;

KeReleaseSpinLock(&pUsbStoreDeviceExtension->SpinLock, Irql);

Srb->SrbStatus = SRB_STATUS_SUCCESS;

status = STATUS_SUCCESS;

}

else if(Srb->Function == SRB_FUNCTION_FLUSH)

{

Srb->SrbStatus = SRB_STATUS_SUCCESS;

status = STATUS_SUCCESS;

}

else

{

status = STATUS_NOT_SUPPORTED;

}

}

else

{

status = STATUS_NOT_SUPPORTED;

}

if(status != STATUS_PENDING)

{

Irp->IoStatus.Status = STATUS_SUCCESS;

IoCompleteRequest(Irp, IO_NO_INCREMENT);

}

return status;

}

 

而UsbStore_StartIo函数将排队的IRP通过CBI规范或者BULK ONLY规范发送给设备

VOID UsbStore_StartIo( IN PDEVICE_OBJECT UsbStorePdo, IN PIRP Irp )

{

ULONG TempFlags;

PSCSI_REQUEST_BLOCK Srb;

UCHAR DeviceErrorFlags ;

ULONG NeedSenseRequestFlags;

PUSBSTORE_DEVICE_EXTENSION pUsbStoreDeviceExtension = UsbStorePdo->DeviceExtension;

PIO_STACK_LOCATION irpStackLocation;

KIRQL Irql;

 irpStackLocation = IoGetCurrentIrpStackLocation(Irp);

 if(irpStackLocation->MajorFunction == IRP_MJ_POWER)

{

Irp->IoStatus.Status = STATUS_SUCCESS;

PoStartNextPowerIrp(Irp);

IoCompleteRequest(Irp,IO_NO_INCREMENT);

return;

}

else

{

IoAcquireCancelSpinLock(&Irql);

InterlockedExchange((PULONG)&Irp->CancelRoutine,0);

if(Irp->Cancel != 0)

{

KeAcquireSpinLockAtDpcLevel(&pUsbStoreDeviceExtension->SpinLock);

pUsbStoreDeviceExtension->DeviceFlags = pUsbStoreDeviceExtension->DeviceFlags>>3; pUsbStoreDeviceExtension->DeviceFlags = ~pUsbStoreDeviceExtension->DeviceFlags;

pUsbStoreDeviceExtension->DeviceFlags = pUsbStoreDeviceExtension->DeviceFlags&1;

TempFlags = pUsbStoreDeviceExtension->DeviceFlags;

KeReleaseSpinLockFromDpcLevel(&pUsbStoreDeviceExtension->SpinLock);

IoReleaseCancelSpinLock(Irql); Irp->IoStatus.Status = STATUS_CANCELLED;

Irp->IoStatus.Information = 0;

IoCompleteRequest(Irp,IO_NO_INCREMENT);

if(TempFlags==0)

return;

else

IoStartNextPacket(UsbStorePdo, TRUE);

return;

}

else

{

IoReleaseCancelSpinLock(Irql);

DeviceErrorFlags = 0;

NeedSenseRequestFlags = 0;

Srb = irpStackLocation->Parameters.Scsi.Srb;

pUsbStoreDeviceExtension->Srb = Srb;

KeAcquireSpinLockAtDpcLevel(&pUsbStoreDeviceExtension->SpinLock);

if(pUsbStoreDeviceExtension->DeviceFlags&DEVICE_ERROR)

{

DeviceErrorFlags = 1;

}

else

{

pUsbStoreDeviceExtension->SrbTimeOutValue = Srb->TimeOutValue;

if(pUsbStoreDeviceExtension->DeviceFlags&NEED_SENSEREQUEST)

{

NeedSenseRequestFlags = 1;

pUsbStoreDeviceExtension->DeviceFlags&=~NEED_SENSEREQUEST;

}

}

KeReleaseSpinLockFromDpcLevel(&pUsbStoreDeviceExtension->SpinLock);

if(DeviceErrorFlags ==0)

{

UsbStore_FormatSrb(UsbStorePdo,Irp,Srb,1);

if(pUsbStoreDeviceExtension->DriverFlags==1)

{

UsbStore_BulkOnly(UsbStorePdo,Irp);

return;

}

else

{

if(NeedSenseRequestFlags == 0||Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)

{

UsbStore_CBI(UsbStorePdo, Irp);

return;

}

else

{

UsbStore_CBIGetRequestSense(UsbStorePdo,Irp,1);

return;

}

}

}

else

{

Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;

IoCompleteRequest(Irp, IO_NO_INCREMENT);

IoStartNextPacket(UsbStorePdo, TRUE);

return;

}

}

}

}

 

UsbStore_DeviceIoControl函数负责处理IRP_MJ_DEVICE_CONTROL,其中IOCONTROLCODE主要有IOCTL_SCSI_PASS_THROUGH,IOCTL_SCSI_PASS_THROUGH_DIRECT,IOCTL_STORAGE_QUERY_PROPERTY。限于篇幅,就不将此函数的代码列下。 UsbStore_Pnp函数负责处理IRP_MJ_PNP,USB STORAGE DRIVER的FDO IRP_MJ_PNP的IRP_MN_START_DEVICE负责建立USB连接,建立USB STORAGE DRIVER的PDO。USB STORAGE DRIVER FDO 的IRP_MN_REMOVE_DEVICE负责清除设备资源及USB连接。 USB STORAGE DRIVER PDO的IRP_MN_QUERY_DEVICE_TEXT 和IRP_MN_QUERY_ID是BUS DRIVER的PNP所必须处理的。

 

NTSTATUS
UsbStore_Pnp(
             IN PDEVICE_OBJECT DeviceObject,
             IN PIRP Irp
             )
{
    NTSTATUS status = STATUS_SUCCESS;
    PUSB_DEVICE_EXTENSION pUsbDeviceExtension;
    PIO_STACK_LOCATION irpStackLocation;

    irpStackLocation = IoGetCurrentIrpStackLocation(Irp);
    pUsbDeviceExtension = DeviceObject->DeviceExtension;
     
    if(pUsbDeviceExtension->DeviceType == USBSTORE_FDO)
    {
        switch(irpStackLocation->MinorFunction)
        {
        case IRP_MN_STOP_DEVICE:
            status = UsbStore_UsbFdoStopDevice(DeviceObject,Irp);
            break;
        case IRP_MN_START_DEVICE:
            status = UsbStore_UsbFdoStartDevice(DeviceObject,Irp);
            break;
        case IRP_MN_QUERY_REMOVE_DEVICE:
        case IRP_MN_QUERY_STOP_DEVICE:
            status = UsbStore_UsbFdoQueryRemoveDevice(DeviceObject,Irp);
            break;
        case IRP_MN_REMOVE_DEVICE:
            status = UsbStore_UsbFdoRemoveDevice(DeviceObject,Irp);
            break;
        case IRP_MN_CANCEL_REMOVE_DEVICE:
        case IRP_MN_CANCEL_STOP_DEVICE:
            status = UsbStore_UsbFdoCancelRemoveDevice(DeviceObject,Irp);
            break;
        case IRP_MN_QUERY_DEVICE_RELATIONS:
            status = UsbStore_UsbFdoQueryDeviceRelations(DeviceObject,Irp);
            break;
        case IRP_MN_SURPRISE_REMOVAL:
            Irp->IoStatus.Status = STATUS_SUCCESS;
        default:
            IoSkipCurrentIrpStackLocation(Irp);
            status = IoCallDriver(pUsbDeviceExtension->UsbStore_TopOfStackDeviceObject,Irp);
            return status;
        }
    }
    else
    {
        switch(irpStackLocation->MinorFunction)
        {
        case IRP_MN_QUERY_CAPABILITIES:
            status = UsbStore_StorePdoQueryCapabilities(DeviceObject,Irp);
            return status;
        case IRP_MN_START_DEVICE:
            status = UsbStore_StorePdoStartDevice(DeviceObject,Irp);
            return status;
        case IRP_MN_REMOVE_DEVICE:
            status = UsbStore_StoreRemoveDevice(DeviceObject,Irp);
            return status;
        case IRP_MN_QUERY_DEVICE_RELATIONS:
            status = UsbStore_StoreQueryDeviceRelations(DeviceObject,Irp);
            return status;
        case IRP_MN_QUERY_DEVICE_TEXT:
            status = UsbStore_StoreQueryDeviceText(DeviceObject,Irp);
            return status;
        case IRP_MN_QUERY_ID:
            status = UsbStore_StoreQueryID(DeviceObject,Irp);
            return status;
        default:
            Irp->IoStatus.Status = STATUS_SUCCESS;
            IoCompleteRequest(Irp,IO_NO_INCREMENT);
            return status;
        }
    }
    return status;
}
本文以BULK ONLY为例来说明USB STORAGE DRIVER的传输过程。
VOID                    
UsbStore_BulkOnly(IN PDEVICE_OBJECT UsbStorePdo,  
                  IN PIRP Irp)
{
    PUSBSTORE_DEVICE_EXTENSION pUsbStoreDeviceExtension = UsbStorePdo->DeviceExtension;
    PUSB_DEVICE_EXTENSION pUsbDeviceExtension = pUsbStoreDeviceExtension->pUsbDeviceExtension;
    PIO_STACK_LOCATION nextirpst,irpst,irpStackLocation = IoGetCurrentIrpStackLocation(Irp);
    PSCSI_REQUEST_BLOCK Srb = irpStackLocation->Parameters.Scsi.Srb;
    PUCHAR pCdb = &Srb->Cdb[0];
    PBULKONLY_CBW pBulkOnly_Cbw = &pUsbStoreDeviceExtension->BulkOnly_Cbw;
    pUsbStoreDeviceExtension->ResaetpipeTimes = 0;
    pBulkOnly_Cbw->dCbwSignature = BULKONLY_CBWSIG;
    pBulkOnly_Cbw->dCbwTag = (ULONG_PTR)Irp;
    pBulkOnly_Cbw->dCbwDataTransferLength = Srb->DataTransferLength;
    pBulkOnly_Cbw->bmCbwFlags = ((UCHAR)Srb->SrbFlags&0xC0)<<1;
    pBulkOnly_Cbw->bCbwLun = 0;
    pBulkOnly_Cbw->bCbwCBLength = Srb->CdbLength;
    RtlCopyMemory(pBulkOnly_Cbw->CbwCDB,pCdb,sizeof(CDB));
    UsbStore_TransferData(UsbStorePdo,Irp,pUsbDeviceExtension->pBulkOutPipeInfo->PipeHandle,0,0x1F,pBulkOnly_Cbw,NULL,(PIO_COMPLETION_ROUTINE)UsbStore_BulkOnlySendCbwCompleteRoutine,0);
    return;
}
根据BULK ONLY规范定义了一个结构:
typedef struct _BULKONLY_CBW{
    ULONG dCbwSignature;
    ULONG_PTR dCbwTag;
    ULONG dCbwDataTransferLength;
    UCHAR bmCbwFlags;
    UCHAR bCbwLun :4;
    UCHAR Reserved0:4;
    UCHAR bCbwCBLength:5;
    UCHAR Reserved1:3;
    UCHAR CbwCDB[16];
}BULKONLY_CBW, *PBULKONLY_CBW;
注意:这个结构的长度在BULKONLY规范里是0X1F,而不是SIZEOF(BULKONLY_CBW),此值传递给UsbStore_TransferData
UsbStore_TransferData负责USB数据传输
VOID
UsbStore_TransferData(
                      IN PDEVICE_OBJECT UsbStorePdo,
                      IN PIRP Irp,
                      IN USBD_PIPE_HANDLE PipeHandle,
                      IN ULONG TransferFlags,
                      IN ULONG DataTransferBufferLength,
                      IN PVOID DataTransferBuffer,
                      IN PMDL DataTransferBufferMDL,
                      IN PIO_COMPLETION_ROUTINE CompleteRoutine,
                      IN PVOID Context
                      )
{
    PUSBSTORE_DEVICE_EXTENSION pUsbStoreDeviceExtension = UsbStorePdo->DeviceExtension;
    PUSB_DEVICE_EXTENSION pUsbDeviceExtension = pUsbStoreDeviceExtension->pUsbDeviceExtension;
    PURB purb = &pUsbStoreDeviceExtension->CurrentUrb;
    PIO_STACK_LOCATION irpStackLocation = IoGetNextIrpStackLocation(Irp);
    KIRQL Irql;
    RtlZeroMemory(purb,sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
    UsbBuildInterruptOrBulkTransferRequest(
                                           purb,
                                           sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
                                           PipeHandle,
                                           DataTransferBuffer,
                                           DataTransferBufferMDL,
                                           DataTransferBufferLength,
                                           TransferFlags,
                                           NULL  
                                           );
    irpStackLocation->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    irpStackLocation->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
    irpStackLocation->Parameters.Others.Argument1 = purb;
    IoSetCompletionRoutine(Irp, CompleteRoutine, Context, TRUE, TRUE, TRUE);
    KeAcquireSpinLock(&pUsbStoreDeviceExtension->SpinLock, &Irql);
    pUsbStoreDeviceExtension->DeviceFlags |= TRANSFER_FINISHED;
    pUsbStoreDeviceExtension->CurrentIrp = Irp;
    KeReleaseSpinLock(&pUsbStoreDeviceExtension->SpinLock, Irql);
    IoCallDriver(pUsbDeviceExtension->UsbStore_TopOfStackDeviceObject, Irp);
}

你可能感兴趣的:(UsbStorage驱动开发)