USB驱动开发——基于windows的WDM模型

USB驱动开发——基于windows的WDM模型

 

译自 Programming the Microsoft Windows Driver Model / Walter Oney -- 2nd ed,第12章,第2节——Working with the Bus Driver,加入了个人一些理解,希望对大家编写USB设备驱动有一定帮助,欢迎指正。

和其他设备驱动不同,USB设备驱动不直接与底层硬件进行通信,而是先建立一个称为USB请求块(USB request blocks,URB)的数据结构,把它发送给父级驱动,父级驱动根据URB中的信息对底层硬件进行相应操作,这里父级驱动通常就是指USB总线驱动。发送URB可以使用主功能码为IRP_MJ_INTERNAL_DEVICE_CONTROL的IRP来实现,也可以直接调用父级驱动提供的接口调用函数来实现。

1. 初始化请求
URB时一种预先定义的数据结构,包含许多域(field)。为了建立一个URB,首先要开辟一个存储空间来存储这个URB,然后运行初始化程序向这个空间来填充一些数据,即设置URB的各个域,例如,若令设备能够对一个IRP_MN_START_DEVICE请求做出相应,那么首先需要做的一个工作就是读取设备描述符,可能需要使用类似下面的一段代码:
USB_DEVICE_DESCRIPTOR dd;
URB urb;
UsbBuildGetDescriptorRequest(&urb, 
sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST),
USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, &dd, NULL,
sizeof(dd), NULL);

这里声明了一个名为urb的URB类型的局部变量,用它来存储要构建的URB。URB这种数据结构是在USBDI.H中进行定义的,USBDI.H可以在DDK开发软件安装目录下找到。URB是一种共用体结构,里面又定义了一些子结构体,每个结构体用于存放特定的USB请求。URB具体定义如下:

typedef struct _URB {
    union {
            struct _URB_HEADER                           UrbHeader;
            struct _URB_SELECT_INTERFACE                 UrbSelectInterface;
            struct _URB_SELECT_CONFIGURATION             UrbSelectConfiguration;
            struct _URB_PIPE_REQUEST                     UrbPipeRequest;
            struct _URB_FRAME_LENGTH_CONTROL             UrbFrameLengthControl;
            struct _URB_GET_FRAME_LENGTH                 UrbGetFrameLength;
            struct _URB_SET_FRAME_LENGTH                 UrbSetFrameLength;
            struct _URB_GET_CURRENT_FRAME_NUMBER         UrbGetCurrentFrameNumber;
            struct _URB_CONTROL_TRANSFER                 UrbControlTransfer;
            struct _URB_BULK_OR_INTERRUPT_TRANSFER       UrbBulkOrInterruptTransfer;
            struct _URB_ISOCH_TRANSFER                   UrbIsochronousTransfer;

            // for standard control transfers on the default pipe
            struct _URB_CONTROL_DESCRIPTOR_REQUEST       UrbControlDescriptorRequest;
            struct _URB_CONTROL_GET_STATUS_REQUEST       UrbControlGetStatusRequest;
            struct _URB_CONTROL_FEATURE_REQUEST          UrbControlFeatureRequest;
            struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST UrbControlVendorClassRequest;
            struct _URB_CONTROL_GET_INTERFACE_REQUEST    UrbControlGetInterfaceRequest;
            struct _URB_CONTROL_GET_CONFIGURATION_REQUEST      UrbControlGetConfigurationRequest;
    };
} URB, *PURB;

这里类似于 _URB_**** 的代码也是在USBDI.H预先定义的某种结构体类型,例如: _URB_CONTROL_GET_STATUS_REQUEST在USBDI.H中定义如下:

struct _URB_CONTROL_DESCRIPTOR_REQUEST {
#ifdef OSR21_COMPAT
    struct _URB_HEADER;     
#else
    struct _URB_HEADER Hdr;                 // function code indicates get or set.
#endif    
    PVOID Reserved;
    ULONG Reserved0;
    ULONG TransferBufferLength;
    PVOID TransferBuffer;
    PMDL TransferBufferMDL;             // *optional*
    struct _URB *UrbLink;               // *optional* link to next urb request
                                        // if this is a chain of commands
    struct _URB_HCD_AREA hca;               // fields for HCD use
    USHORT Reserved1;
    UCHAR Index;
    UCHAR DescriptorType;
    USHORT LanguageId;
    USHORT Reserved2;
};

初始化URB可以通过类似于UsbBuildGetDescriptorRequest这样的函数来完成,以下给出一个表来说明:

USB驱动开发——基于windows的WDM模型 (1) - 胡胡 - 雪晴的博客

这些函数是在另一个头文件USBDLIB.H中定义的,在DDK安装目录下查找即可,对于表中的函数都可以在DDK的说明文档里找到,利用这些函数就可以实现对URB的初始化。这里以UsbBuildGetDescriptorRequest为例,说明一个函数具体功能,有些参数我也不能完全讲清其含义,把英文直接贴在上面了。

VOID 
  UsbBuildGetDescriptorRequest(
    IN OUT PURB  Urb,  // 指向一个要初始化的URB首地址
    IN USHORT  Length, // 确定URB的长度
    IN UCHAR  DescriptorType, // 确定描述符类型
    IN UCHAR  Index,   // Specifies the device-defined index of the descriptor that is to be retrieved 
    IN USHORT  LanguageId, // Specifies the language ID of the descriptor to be retrieved when USB_STRING_DESCRIPTOR_TYPE is set in DescriptorType. This parameter must be zero for any other value in DescriptorType. 
    IN PVOID  TransferBuffer  OPTIONAL, // 读回的描述符后所存放的地址
    IN PMDL  TransferBufferMDL  OPTIONAL, // Pointer to a resident buffer to receive the descriptor data or is NULL if an MDL is supplied in TransferBufferMDL. 
    IN ULONG  TransferBufferLength, // Specifies the length of the buffer specified in TransferBuffer or described in TransferBufferMDL.
    IN PURB  Link  OPTIONAL // 必需为NULL
    );
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值