Windows系统-----USB 设备驱动

本文详细介绍了USB通信的基本原理及开发流程,包括USB总线结构、四种传输模式、USB请求包构建过程及其处理机制。此外,还介绍了如何通过创建USB请求块(URB)与USB设备进行交互。

总线协议:

对于每一台PC来说,都有一个或多个称为Host控制器的设备,该Host控制器和一个根Hub作为一个整体。每个hub可以级联多级的hub。


Host控制器:
就是一个PCI设备,挂载在PCI总线上。
Host可能有多种驱动,分别为1.0 2.0 3.0 分别对用usb协议的1.0 2.0 3.0 


USB Hub:
每个Host控制器都会自带一个Hub,称为根hub,


USB设备:
插在USB总线上工作的设备。hub也算是一种特殊的USB设备。


USB通信流程:
USB的连接模式是Host和Device的连接模式。所有的请求必须是Host向Device发出。
在USB的通信中,可以看成是一个分层的协议,即最底层usb总线接口层、USB设备层、功能通信层。


USB四种传输模式


USB驱动向USB控制器驱动请求的每次传输被称为一个事务。事务分为四种类型:Bulk(大量传输模式)、Control(控制传输模式)、Interrupt(中断传输模式)、Isochronous(同步传输模式)。


Bulk(大量传输模式):
(a)Host端发出一个BULK的令牌请求,IN代表从DEVICE到HOST的请求,OUT则反之。
(b)数据传送阶段,用DATA0和DATA1令牌携带着数据交替传送。这两个是重复数据,确保数据不会丢失。 (c)握手信号,IN时,握手信号有Host端发出,OUT时,反之。信号可以是ACK,或NAK表示传送失败,STALL表示主机不可预知的错误。
Control(控制传输模式):
控制传输是负责向USB设置一些信息,传送这种事务的管道被称为控制管道。每个USB设备中都必须拥有控制管道。
控制传输也分为令牌请求、数据传输、握手三个阶段。
Interrupt(中断传输模式):
类似于PCI的中断机制,数据量很小,一般通知Host某个事件的来临,例如USB鼠标的移动、点击。
同样为为令牌请求、数据传输、握手三个阶段。
Isochronous(同步传输模式):
保证传输的同步性。例如USB摄像头中传输视频数据,每秒会有固定的传输量。
但是与BULK不同,它允许有一定的误码率。
分为令牌请求和数据传输两个阶段。


令牌请求阶段:
通过8字节传输请求:8字节中主要是设置0字节(请求类型)和1字节(请求类别)。
其他字节根据请求类别的不同而改变。

请求类别为:
#define USB_REQUEST_GET_STATUS                    0x00
#define USB_REQUEST_CLEAR_FEATURE                 0x01

#define USB_REQUEST_SET_FEATURE                   0x03

#define USB_REQUEST_SET_ADDRESS                   0x05
#define USB_REQUEST_GET_DESCRIPTOR                0x06
#define USB_REQUEST_SET_DESCRIPTOR                0x07
#define USB_REQUEST_GET_CONFIGURATION             0x08
#define USB_REQUEST_SET_CONFIGURATION             0x09
#define USB_REQUEST_GET_INTERFACE                 0x0A
#define USB_REQUEST_SET_INTERFACE                 0x0B
#define USB_REQUEST_SYNC_FRAME                    0x0C

令牌请求类别:
(a)设备描述符
请求类别为USB_REQUEST_GET_DESCRIPTOR时,可以请求查询设备描述或者管道描述,具体由请求类型决定。请求device描述如下:
typedef struct _USB_DEVICE_DESCRIPTOR { 
 UCHAR  bLength ;
 UCHAR  bDescriptorType ;
 USHORT  bcdUSB ;
 UCHAR  bDeviceClass ;
 UCHAR  bDeviceSubClass ;
 UCHAR  bDeviceProtocol ;
 UCHAR  bMaxPacketSize0 ;
 USHORT  idVendor ;
 USHORT  idProduct ;
 USHORT  bcdDevice ;
 UCHAR  iManufacturer ;
 UCHAR  iProduct ;
 UCHAR  iSerialNumber ;
 UCHAR  bNumConfigurations ;
} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR ;


(b)配置描述符
每个设备都有一个或多个配置描述符,描述了设备能实行的各种配置方式。
typedef struct _USB_CONFIGURATION_DESCRIPTOR { 
 UCHAR  bLength ;
 UCHAR  bDescriptorType ;
 USHORT  wTotalLength ;
 UCHAR  bNumInterfaces ;
 UCHAR  bConfigurationValue;
 UCHAR  iConfiguration ;
 UCHAR  bmAttributes ;
 UCHAR  MaxPower ;
} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR ;

(c)接口描述符
每个配置有一个或多个接口描述符,描述了设备提供功能的接口。
typedef struct _USB_INTERFACE_DESCRIPTOR { 
 UCHAR  bLength ;
 UCHAR  bDescriptorType ;
 UCHAR  bInterfaceNumber ;
 UCHAR  bAlternateSetting ;
 UCHAR  bNumEndpoints ;
 UCHAR  bInterfaceClass ;
 UCHAR  bInterfaceSubClass ;
 UCHAR  bInterfaceProtocol ;
 UCHAR  iInterface ;
} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR ;
(d)断点描述符
接口可以没有或有多个端点描述符,描述了处理事务的端点。
typedef struct _USB_ENDPOINT_DESCRIPTOR { 
 UCHAR  bLength ;
 UCHAR  bDescriptorType ;
 UCHAR  bEndpointAddress ;
 UCHAR  bmAttributes ;
 USHORT  wMaxPacketSize ;
 UCHAR  bInterval ;
} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR ;




开发实例:
(1)需要开发的事情只是要完成FDO的功能,需要指定何种管道,发送何种数据即可。
(2)当FDO想向某个管道发送读写请求时,首先构造URB(USB请求块)发给USB总线驱动。
总线驱动解释URB ,然后转化为请求,发给USB Host或者Usb Hub。
(3)构造URB
USB驱动在与USB设备通信的时候,都是通过创建URB来完成。URB中填充需要对USB的请求。然后将URB作为一个参数传递给底层的USB总线驱动。
在功能驱动中,所有与USB的通信,都需要用这个函数创建URB,并通过IRP发送给底层USB总线驱动。
VOID 
 UsbBuildGetDescriptorRequest(
IN OUT PURB  Urb,
IN USHORT  Length,
IN UCHAR  DescriptorType,
IN UCHAR  Index,
IN USHORT  LanguageId,
IN PVOID  TransferBuffer  OPTIONAL,
IN PMDL  TransferBufferMDL  OPTIONAL,
IN ULONG  TransferBufferLength,
IN PURB  Link  OPTIONAL
);
(4)发送USB请求包
URB创建完成以后,需要与一个IRP关联,这就需要用IoBuildDeviceIoControlRequest 创建一个IO控制码的IRP,然后将URB作为IRP的参数,用IoCallDriver将URB发送到底层总线驱动上。
由于上层驱动无法得知底层驱动是同步还是异步的,因此需要判断返回值为PENDING时,使用内核事件等待完成。
代码略。
(5)USB设备初始化
首先入口函数与其他WDM驱动程序无异。
usb设备的热插拔:
完善支持即插即用,IRP_MN_START_DEVICE当驱动加载运行USB设备时,即插即用管理器将此IRP发送给设备驱动。
usb驱动程序可以获取USB的类别描述符,例如设备、配置、接口、端点。
IRP_MN_EJECT
IRP_MN_SURPRISE_REMOVE
IRP_MN_STOP_DEVICE,即插即用管理器发送此IRP后,驱动程序应尽快结束当前的IRP,并将其逐个取消。
(6)USB设备读写
(a)处理IRP_MJ_READ 和OIRP_MJ_WRITE
(b)使用UsbBuildInterruptOrBulkTransferRequest在bulk pipe或者interrupt pipe格式化一个发送或接收的URB。
(c)保存数据,设置完成例程
(d)IoCallDriver将IRP给下层驱动,派遣函数返回status_pending

(f)完成例程内根据获取的数据,处理是返回status_success或者多次调用底层驱动程序。



注:这里的记录并非是usb设备的过滤驱动,而是讲解如何在usb驱动总线相连,实现一个usb设备。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值