搜档网
当前位置:搜档网 › USB驱动开发

USB驱动开发

USB驱动开发
USB驱动开发

第17章USB设备驱动

USB设备驱动和PCI设备驱动是PC中最主要的两种设备驱动程序。与PCI协议相比,USB协议更复杂,涉及面较多。本章将介绍USB设备驱动开发。首先介绍USB协议,使读者对USB协议有个整体认识。然后介绍USB设备在WDM中的开发框架。由于操作系统的USB总线驱动程序提供了丰富的功能调用,因此开发USB驱动开发变得相对简单,只需要调用USB总线驱动接口。

17.1 USB总线协议

USB总线协议比PCI协议复杂的多,涉及USB物理层协议,又涉及USB传输层协议等。对于USB驱动程序开发者来说,不需要对USB协议的每个细节都很清楚。本节概要地介绍USB总线协议,并对驱动开发者需要了解的地方进行详细介绍。

17.1.1 USB设备简介

USB即通用串行总线(Universal Serial Bus),是一种支持即插即用的新型串行接口。也有人称之为“菊链(daisy-chaining)”,是因为在一条“线缆”上有链接127 个设备的能力。USB要比标准串行口快得多,其数据传输率可达每秒4Mb~12Mb(而老式的串行口最多是每秒115Kb)。除了具有较高的传输率外,它还能给外围设备提供支持。

需要注意的是,这不是一种新的总线标准,而是计算机系统连接外围设备(如键盘、鼠标、打印机等)的输入/输出接口标准。到现在为止,计算机系统连接外围设备的接口还没有统一的标准,例如,键盘的插口是圆的、连接打印机要用9针或25针的并行接口、鼠标则要用9针或25针的串行接口。USB能把这些不同的接口统一起来,仅用一个4针插头作为标准插头,如图17-1所示。通过这个标准插头,采用菊花链形式可以把所有的外设连接起来,并且不会损失带宽。USB正在取代当前PC上的串口和并口。

第17章 USB 设备驱动

4

31

图17-1 USB 的四条传输线

以USB 方式连接设备时,所有的外设都在机箱外连接,连接外设不必再打开机箱;允许外设热插拔,而不必关闭主机电源。USB 采用“级联”方式,即每个USB 设备用一个USB 插头连接到另一个外设的USB 插座上,而其本身又提供一个USB 插座供下一个USB 外设连接用。通过这种类似菊花链式的连接,一个USB 控制器可以连接多达127个外设,而每个外设间距离(线缆长度)可达5米。USB 能智能识别USB 链上外围设备的插入或拆卸。

它可使多个设备在一个端口上运行,速度也比现在的串行口或并行口快得多,而且其总的连线在理论上说可以无限延长。对PC 来说,以上这些都是一些难得的优点,因为不再需要PS/2端口、MIDI 端口等各种不同的端口了,还可以随时随地在各种设备上任意插拔。可以在一个端口上运行鼠标、控制手柄、键盘以及其他输入装置(例如数码相机),而且,也不必重新启动系统去做这些工作。现在USB 设备正在快速增多,且由于操作系统已内置支持USB 的功能,因而用户现在就可以方便地使用。显然,USB 为PC 的外设扩充提供了一个很好的解决方案。

目前USB 技术的发展,已经允许用户在不使用网卡、HUB 的情况下,直接通过USB 技术将几台计算机连接起来组成小型局域网,用户只需要给各台计算机起个名字就可以开始工作。这种网络具备Ethernet 网络的各种优点,同时少了Ethernet 网络的许多限制。假设一位用户上班时使用笔记本电脑,回家时使用PC 机,为实现数据传输,他可以通过采用USB 技术的接口将两部电脑连接起来交换资源,其数据传输速度可达12Mbps ,这是传统串行口无法比拟的。而且用户在组网的时候根本无须考虑DIP 、IRQ 等问题。此类技术除支持兼容Ethernet 的软硬件外,也支持标准的网络通信协议,包括IPX/SPX 、NetBEUI 和TCP/IP ,这为通过USB 技术组成的小局域网连接至大型网络或Internet 提供了条件。 17.1.2 USB 连接拓扑结构

USB 设备的连接如图17-2所示,对于每个PC 来说,都有一个或者多个称为Host 控制器的设备,该Host 控制器和一个根Hub 作为一个整体。这个根Hub 下可以接多级的Hub ,每个子Hub 又可以接子Hub 。每个USB 作为一个节点接在不同级别的Hub 上。

(1)USB Host 控制器:每个PC 的主板上都会有多个Host 控制器,这个Host 控制器其实就是一个PCI 设备,挂载在PCI 总线上。Host 控制器的驱动由微软公司提供,如图17-3所示,这是笔者PC 中的Host 控制器及USB Hub 的驱动。值得注意的是,这里Host 分别有两种驱动,一种是1.0,另一种是2.0,分别对应着USB 协议1.0和USB

Windows 驱动开发技术详解

432 议2.0。

第17章 USB 设备驱动

4

33

图17-2 USB 连接拓扑结构

(2)USB Hub :每个USB Host 控制器都会自带一个USB Hub ,被称为根(Root)Hub 。这个根Hub 可以接子(Sub)Hub ,每个Hub 上挂载USB 设备。一般PC 有8个USB 口,通过外接USB Hub ,可以插更多的USB 设备。当USB 设备插入到USB Hub 或从上面拔出时,都会发出电信号通知系统。这样可以枚举USB 设备,例如当被插入的时候,系统就会创建一个USB 物理总线,并询问用户安装设备驱动。如图17-4所示为一个典型的USB Hub 的示意图。

图17-3 USB Host 和USB Hub 驱动 图17-4 USB Hub 示意图 (3)USB 设备:USB 设备就是插在USB 总线上工作的设备,广义地讲USB Hub 也算是USB 设备。每个根USB Hub 下可以直接或间接地连接127个设备,并且彼此不会干扰。对于用户来说,可以看成是USB 设备和USB 控制器直接相连,之间通信需要满足USB 的通信协议。

有的USB 设备功能单一,直接挂载在USB Hub 上。而有的USB 设备功能复杂,

会将

Windows 驱动开发技术详解

434 多个USB 功能连在一起,成为一个复合设备,它甚至可以自己内部带一个Hub ,这个Hub 下接多个USB 子设备,其和多个子设备作为一个整体当做一个USB 设备,如图17-5所示。

以上是USB 的物理拓扑结构,但对于用户来说,可以略去USB Hub 的概念,或者说USB Hub 的概念对于用户可以看成是透明的。用户只需要将USB 设备理解成一个USB Host 连接多个逻辑设备。可能逻辑设备1和逻辑设备2是集中在第一个物理设备里,例如有的手机连接计算机后,系统会当做多个USB 设备加载。因此,作为用户需要用如图17-6所示的逻辑拓扑结构理解USB 拓扑结构。

图17-5 符合设备 图17-6 USB 逻辑拓扑结构 但对于具体USB 设备来说,每个USB 设备的传输绝对不会影响其他USB 设备的传输。例如,在有USB 设备传输的时候,其他USB 设备的带宽不会被占用。对于USB 设备来说,每个USB 设备是直接连接到USB Host 控制器上的。因此,应该用如图17-7所示的视角考虑USB 设备的通信。

图17-7 用户对USB 设备的观察

17.1.3 USB 通信的流程

USB 的连接模式是Host 和Devcie

的连接模式,它不同于早期的串口和并口,所有的

第17章 USB 设备驱动

4

35

请求必须是Host 向Device 发出,这就使Host 端设计相对复杂,而Device 端设计相对简单。Host 端会在主板的南桥设计好,而Device 的厂商众多,厂商只需要遵循USB 协议,重点精力可以放在设备的研发上,而与PC 的通信不用过多考虑。

在USB 的通信中,可以看成是一个分层的协议。分为三个层次,即最底层USB 总线接口层、USB 设备层、功能通信层,如图17-8所示。

图17-8 USB 协议

以USB 摄像头设备为例,视频播放软件想通过USB 总线得到USB 摄像头捕捉的视频数据,这就相当于在功能层上。Clinet SW 是视频播放软件,Function 是USB 摄像头。而这些数据的读取需要USB 设备层提供的服务,在这一层上,主要是USB 设备的驱动调度Host 控制器向USB 摄像头发出读请求。每个USB 设备会有多个管道,使用哪个管道,传输的大小都需要指定。这个层次的USB System SW 就是USB 摄像头的驱动程序。而在USB 设备一端一般会有小单片机或者处理芯片负责响应这种读请求,而这一层的传输又依赖于USB 总线接口层的服务。在这一层,完全是USB 的物理协议,包括如何分成更小的包(packages )传输,如何保证每次包传输不丢失数据等。

对于USB 设备驱动程序员,主要是工作在USB 设备层,向“上”对应用程序提供读写等接口,向“下”将读取某个管道的请求发往USB Host 控制器驱动程序,它实现了最底层的传输请求。

对于每个USB 设备,都有一个或者多个的接口(Interface ),每个Interface 都有多个端点(Endpoints ),每个端点通过管道(Pipes )和USB Host 控制器连接。每个USB 设备都会有一个特殊的端点,即Endpoint0,它负责传输设备的描述信息,同时也负责传输PC 与设备之间的控制信息,如图17-9所示。

Windows 驱动开发技术详解

436

图17-9 USB 管道与端点

17.1.4 USB 四种传输模式

当USB 插入USB 总线时,USB 控制器会自动为该USB 设备分配一个数字来标示这个设备。另外,在设备的每个端点都有一个数字来表明这个端点。

USB 设备驱动向USB 控制器驱动请求的每次传输被称为一个事务(Transaction ),事务有四种类型,分别是Bulk Transaction 、Control Transaction 、Interrupt Transaction 和Isochronous Transaction 。每次事务都会分解成若干个数据包在USB 总线上传输。每次传输必须历经两个或三个部分,第一部分是USB 控制器向USB 设备发出命令,第二部分是USB 控制器和USB 设备之间传递读写请求,其方向主要看第一部分的命令是读还是写,第二部分有时候可以没有。第三部分是握手信号。以下针对这四种传输,分别进行讲解。

1.Bulk 传输事务

顾名思义,改种事务传输主要是大块的数据,传送这种事务的管道叫做Bulk 管道。这种事务传输的时候分为三部分,如图17-10所示。第一部分是Host 端发出一个Bulk 的令牌请求,如果令牌是IN 请求则是从Device 到Host 的请求,如果是OUT 令牌,则是从Host 到Device 端的请求。

第二部分是传送数据的阶段,根据先前请求的令牌的类型,数据传输有可能是IN 方向,也有可能是OUT 方向。传输数据的时候用DATA0和DATA1令牌携带着数据交替传送。

第三部分是握手信号。如果数据是IN 方向,握手信号应该是Host 端发出,如果是OUT 方向,握手信号应该是Device 端发出。握手信号可以为ACK ,表示正常响应,也可以是NAK 表示没有正确传送。STALL 表示出现主机不可预知的错误。

在第二部分,即传输数据包的时候,数据传送由DATA0和DATA1数据包交替发送。数据传输格式DATA1和DATA0,这两个是重复数据,确保在1数据丢失时0可以补上,不至于数据丢失。如图17-11所示。

第17章 USB 设备驱动

4

37

图17-10 Bulk 传输

图17-11 Bulk 传输时的令牌

2.控制传输事务

控制传输是负责向USB 设置一些控制信息,传送这种事务的管道是控制管道。在每个USB 设备中都会有控制管道,也就是说控制管道在USB 设备中是必须的。控制传输也分为三个阶段,即令牌阶段、数据传送阶段、握手阶段,如图17-12所示。

图17-12 控制传输事务

Windows 驱动开发技术详解

438 3.中断传输事务

在USB 设备中,有种处理机制类似于PCI 中断的机制,这就是中断事务。中断事务的数据量很小,一般用于通知Host 某个事件的来临,例如USB 鼠标,鼠标移动或者鼠标单击等操作都会通过中断管道来向Host 传送事件。在中断事务中,也分为三个阶段,即令牌阶段、数据传输阶段、握手阶段,如图17-13所示。

图17-13 中断传输事务

4.同步传输事务

USB 设备中还有一种事务叫同步传输事务,这种事务能保证传输的同步性。例如,在USB 摄像头中传输视频数据的时候会采用这种事务,这种事务能保证每秒有固定的传输量,但与Bulk 传输不同,它允许有一定的误码率,这样符合视频会议等传输的需求,因为视频会议首先要保证实时性,在一定条件下,允许有一定的误码率。同步传输事务有只有两个阶段,即令牌阶段、数据阶段,因为不关心数据的正确性,故没有握手阶段,如图17-14所示。

图17-14 同步传输事务

第17章 USB 设备驱动

4

39

17.2 Windows 下的USB 驱动

在Windows 上开发USB 驱动相对来说比较简单,主要是因为微软已经提供了完备的USB 总线驱动,程序员编写的设备驱动只需调用总线驱动即可。在Windows 上还有一些工具软件可以帮助开发者查看USB 的各类信息,包括设备描述符、配置描述符等。当然,这些描述符在驱动中也会用到。本节将介绍这些工具软件,并介绍这些描述符。 17.2.1 观察USB 设备的工具

在学习编写USB 驱动之前,有几个USB 查看工具需要向读者介绍一下,通过用这些工具能方便地学习USB 协议。

首先需要介绍的就是DDK 中提供的工具,该工具叫usbview ,位于DDK 的子目录src\wdm\usb\usbview 下,需要用DDK 编译环境进行编译。如图17-15所示为usbview 的界面,在笔者的计算机里插入了一个USB 移动硬盘,在这个软件中已经清楚地列举除了该USB 设备的各个信息,如图设备描述符、管道描述符等。

图17-15 USBView

另一个有用的工具是BusHound ,如图17-16所示。BusHound 用于监视USB 设备的传输数据,它 的实现原理是在USB 设备驱动之上加载一层过滤驱动程序,将IRP 进行拦截,因此可以观察到所有USB 数据的传输。使用该软件时需要指明监视哪种USB 设备,如图17-16所示,在需要监视的设备上打钩。笔者这里监视的是一个USB 移动硬盘。另外,在下面会列出该设备的基本信息,如管道0是控制管道,管道1是输出管道,管道2

是输入

Windows 驱动开发技术详解

440 管道。

第17章 USB 设备驱动

4

41

图17-16 BusHound

该软件将USB 的传输完全进行监视,包括每个USB 的各个管道中的传输情况,都一一进行记录,非常有利于调试驱动。如图17-17所示,Device 一栏中标识是何种设备,例如27.2意味着第27号设备的第2号管道。Phase 一栏标识传输是输入还是输出。在Data 一栏中记录着一次传输的具体内容。

图17-17 BusHound 监视数据传输

Windows 驱动开发技术详解

442 17.2.2 USB 设备请求

USB 的请求是通过控制管道传输的,请求是8个字节,按照如表17-1所示的排列发送:

表17-1

其中,bRequest 代表不同的USB 请求,它们分别是以下的几种请求,定义在DDK 的usb100.h 文件中:

#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

17.2.3 设备描述符

在控制管道发起USB 设备请求,其中很常见的请求是USB_REQUEST_GET_ DESCRIPTOR ,即请求USB 设备回答设备或者管道描述符。在请求描述符时,

第17章 USB 设备驱动

4

43

bmRequestType 可以指定是针对设备还是针对管道的。

当请求设备描述符后,设备会回答主机该设备的设备描述符,设备描述符是一种固定的数据结构,它定义在DDK 中的usb100.h 文件中。 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;

bLength :设备描述符的bLength 域应等于18。

bDescriptorType :bDescriptorType 域应等于1,以指出该结构是一个设备描述符。 bcdUSB :bcdUSB 域包含该描述符遵循的USB 规范的版本号(以BCD 编码)。现在,设备可以使用值0x0100或0x0110来指出它所遵循的是1.0版本还是1.1版本的USB 规范。

bDeviceClass :指出设备类型。

bDeviceSubClass :指出设备子类型。

bDeviceProtocol :指出设备类型所使用的协议。

bMaxPacketSize0:设备描述符的bMaxPacketSize0域,给出了默认控制端点(端点0)上的数据包容量的最大值。

idVendor :厂商代码。

idProduct :厂商专用的产品标识。

bcdDevice :bcdDevice 指出设备的发行版本号(0x0100对应版本1.0)。

iManufacturer 、iProduct 、iSerialNumber :iManufacturer 、iProduct 和iSerialNumber 域指向一个串描述符,该串描述符用人类可读的语言描述设备生产厂商、产品和序列号。这些串是可选的,0值代表没有描述串。如果在设备上放入了序列号串,Microsoft 建议应使每个物理设备的序列号唯一。

bNumConfigurations :bNumConfigurations 指出该设备能实现多少种配置。Microsoft 的驱动程序仅工作于设备的第一种配置(1号配置)。

如图17-18所示为笔者用BusHound 截获的USB 移动硬盘的请求设备描述符,前面已经介绍过,在控制管道中,传输分为三个阶段。第一阶段是令牌阶段,这里Host 向设备发送“80 06 00 01 00 00 12 00”8个字节,可以参见表17-1中的解释。第二阶段是数据传

Windows 驱动开发技术详解

444 输阶段,方向是由设备传给主机,这个例子中设备给主机传递了18(0x12)个字节,这18个字节对应着USB_DEVICE_DESCRIPTOR 数据结构。第三阶段是握手阶段,在BusHound 软件中没有体现出来。

图17-18 用BusHound 抓取设备描述符

17.2.4 配置描述符

每个设备有一个或多个配置描述符,它们描述了设备能实行的各种配置方式。DDK 中定义的配置描述符结构如下: 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;

bLength :bLength 应该为9。

bDescriptorType :bDescriptorType 应该为2,即是一个9字节长的配置描述符。 wTotalLength :wTotalLength 域为该配置描述符长度加上该配置内所有接口和端点描述符长度的总和。通常,主机在发出一个GET_DESCRIPTOR 请求并正确接收到9字节长的配置描述符后,就会再发出一个GET_DESCRIPTOR 请求并指定这个总长度。第二个请求把这个大联合描述符传输回来。

bNumInterfaces :指出该配置有多少个接口。

bConfigurationValue :bConfigurationValue 域是该配置的索引值。

iConfiguration :iConfiguration 域是一个可选的串描述符索引,指向描述该配置的Unicode 字符串。此值为0表明该配置没有串描述符。

bmAttributes :bmAttributes 字节包含描述该配置中设备电源和其他特性的位掩码。 MaxPower :MaxPower 域中指出要从USB 总线上获取的最大电流量。

如图17-19所示为笔者用BusHound

截获的USB 移动硬盘的请求配置描述符。其中第一行是Host 向Device 发送

Token 令牌,而第二行是Device 向Host 返回的数据。

图17-19 用BusHound 抓取设配置描述符

第17章 USB 设备驱动

4

45

17.2.5 接口描述符

每个配置有一个或多个接口描述符,它们描述了设备提供功能的接口。 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;

bLength :bLength 应该为9。

bDescriptorType :bDescriptorType 域应为4。

bInterfaceNumber :bInterfaceNumber 是索引值。

bAlternateSetting :bAlternateSetting 是索引值。用在SET_INTERFACE 控制事务中以指定要激活的接口。

bNumEndpoints :bNumEndpoints 域指出该接口有多少个端点,不包括端点0,端点0被认为总是存在的,并且是接口的一部分。

bInterfaceClass :bInterfaceClass 为接口类。

bInterfaceSubClass :bInterfaceSubClass 为子接口类。

bInterfaceProtocol :bInterfaceProtocol 为协议。

iInterface :iInterface 是一个串描述符的索引,0表示该接口无描述串。

如图17-20所示为笔者用BusHound 截获的USB 移动硬盘的请求配置描述符和接口描述符。其中第一行是Host 向Device 发送

Token 令牌,而第二行是Device 向Host 返回的数据。可以看出图中有一个配置描述符,后面紧接着一个接口描述符(“09 04 00 00 02 00 06 50 05”),后面还有两个接口描述符(下一节介绍)。

图17-20 用BusHound 抓取接口描述符

17.2.6 端点描述符

接口可以没有或有多个端点描述符,它们描述了处理事务的端点。DDK 中定义的端点描述符结构如下:

typedef struct _USB_ENDPOINT_DESCRIPTOR {

UCHAR bLength;

UCHAR bDescriptorType;

UCHAR bEndpointAddress;

Windows 驱动开发技术详解

446 UCHAR bmAttributes;

USHORT wMaxPacketSize;

UCHAR bInterval;

} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR;

bLength :bLength 应为7。

bDescriptorType :bDescriptorType 应该为5。

bEndpointAddress :bEndpointAddress 域编码端点的方向性和端点号。

bmAttributes :bmAttributes 的低两位指出端点的类型。0代表控制端点,1代表等时端点,2代表批量端点,3代表中断端点。

wMaxPacketSize :wMaxPacketSize 值指出该端点在一个事务中能传输的最大数据量。 bInterval :中断端点和等时端点描述符还有一个用于指定循检间隔时间的bInterval 域。 17.3 USB 驱动开发实例

本节具体介绍如何进行USB 驱动的开发,本节采用的源码来源自DDK 的源程序,其位置在DDK 子目录的src\wdm\usb\bulkusb 目录下。该示例很全面地支持了即插即用IRP 的处理,也很全面地支持了电源管理,同时很好地支持了USB 设备的bulk 读写。如果从头开发USB 驱动,往往很难达到USB 驱动的稳定性,所以强烈建议读者在此驱动修改的基础上进行USB 驱动开发。

17.3.1 功能驱动与物理总线驱动

DDK 已经为USB 驱动开发人员提供了功能强大的USB 物理总线驱动(PDO ),程序员需要做的事情是完成功能驱动(FDO )的开发。驱动开发人员不需要了解USB 如何将请求转化成数据包等细节,程序员只需要指定何种管道,发送何种数据即可。

当功能驱动想向某个管道发出读写请求时,首先构造请求发给USB 总线驱动。这种请求是标准的USB 请求,被称为URB (USB Request Block ),即USB 请求块。这种URB 被发送到USB 物理总线驱动以后,被USB 总线驱动所解释,进而转化成请求发往USB HOST 驱动或者USB HUB 驱动,如图17-21所示。

功功功功

图17-21 总线驱动与功能驱动的关系

第17章 USB 设备驱动

4

47

可以看出,USB 总线驱动完成了大部分工作,并留给USB 功能驱动标准的接口,即URB 请求。USB 驱动开发人员只需要根据不同的USB 设备的设计要求,在相应的管道中发起URB 请求即可。

17.3.2 构造USB 请求包

USB 驱动在与USB 设备通信的时候,如在控制管道中获取设备描述符、配置描述符、端点描述符,或者在Bulk 管道中获取大量数据,都是通过创建USB 请求包(URB )来完成的。URB 中填充需要对USB 的请求,然后将URB 作为IRP 的一个参数传递给底层的USB 总线驱动。在USB 总线驱动中,能够解释不同URB ,并将其转化为USB 总线上的相应数据包。

DDK 提供了构造URB 的内核函数UsbBuildGetDescriptorRequest ,其声明如下: 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

);

Urb :用来输出的URB 结构的指针。

Length :用来描述该URB 结构的大小。

DescriptorType :描述该URB 的类型。它可以是USB_DEVICE_DESCRIPTOR_TYPE 、USB_CONFIGURATION_DESCRIPTOR_TYPE 和USB_STRING_DESCRIPTOR_ TYPE 。

Index :用来描述设备描述符的索引。

LanguageId :用来描述语言ID 。

TransferBuffer :如果用缓冲区读取设备,TransferBuffer 是缓冲区内存的指针。 TransferBufferMDL :如果用直接读取内存时,TransferBufferMDL 是直接读取内存时MDL 的指针。

TransferBufferLength :对于该URB 所操作内存的大小。

在功能驱动中,所有与USB 的通信,都需要用这个函数创建URB ,并通过IRP 发送到底层USB 总线驱动,以下是一个最基本的示例。

#001 UsbBuildGetDescriptorRequest(

#002 urb,

#003 (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), #004 USB_DEVICE_DESCRIPTOR_TYPE,

#005 0,

Windows 驱动开发技术详解

448 #006 0,

#007 deviceDescriptor,

#008 NULL,

#009 siz,

#010 NULL);

17.3.3 发送USB 请求包

功能驱动将URB 包构造完毕后,就可以发送到底层总线驱动上了。URB 包要和一个IRP 相关联起来,这就需要用IoBuildDeviceIoControlRequest 创建一个IO 控制码的IRP ,然后将URB 作为IRP 的参数,用IoCallDriver 将URB 发送到底层总线驱动上。由于上层驱动无法知道底层驱动是同步还是异步完成的,因此需要做一个判断。if 语句判断当异步完成IRP 时,用事件等待总线驱动完成这个IRP 。 #001 //

该函数实现对发送URB 到USB 物理总线驱动

#002 NTSTATUS

#003 CallUSBD(

#004 IN PDEVICE_OBJECT DeviceObject,

#005 IN PURB Urb

#006 )

#007 {

#008 PIRP irp;

#009 KEVENT event;

#010 NTSTATUS ntStatus;

#011 IO_STATUS_BLOCK ioStatus;

#012 PIO_STACK_LOCATION nextStack;

#013 PDEVICE_EXTENSION deviceExtension;

#014

#015 //首先是变量初始化

#016 irp = NULL;

#017 deviceExtension = DeviceObject->DeviceExtension;

#018 //初始化事件

#019 KeInitializeEvent(&event, NotificationEvent, FALSE);

#020 //创建IO 控制码相关的IRP

#021 irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, #022 deviceExtension->TopOfStackDeviceObject, #023 NULL,

#024 0,

#025 NULL,

#026 0,

#027 TRUE,

#028 &event,

#029 &ioStatus);

#030

#031 if(!irp) {

#032 //如果IRP 创建失败则返回

#033 BulkUsb_DbgPrint(1, ("IoBuildDeviceIoControlRequest failed\n")); #034 return STATUS_INSUFFICIENT_RESOURCES;

#035 }

#036 //得到下一层设备栈

#037 nextStack = IoGetNextIrpStackLocation(irp);

#038 ASSERT(nextStack != NULL);

#039 nextStack->Parameters.Others.Argument1 = Urb;

第17章 USB 设备驱动

4

49 #040 BulkUsb_DbgPrint(3, ("CallUSBD::"));

#041 BulkUsb_IoIncrement(deviceExtension);

#042 //通过IoCallDriver 将IRP 发送到底层驱动

#043 ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp); #044 //如果IRP 是异步完成时,等待其结束

#045 if(ntStatus == STATUS_PENDING) {

#046 //等待IRP 结束

#047 KeWaitForSingleObject(&event,

#048 Executive,

#049 KernelMode,

#050 FALSE,

#051 NULL);

#052 ntStatus = ioStatus.Status;

#053 }

#054 //调用结束

#055 BulkUsb_DbgPrint(3, ("CallUSBD::"));

#056 BulkUsb_IoDecrement(deviceExtension);

#057 return ntStatus;

#058 }

此段代码可以在配套光盘中本章的sys 目录下找到。

17.3.4 USB 设备初始化

USB 驱动的初始化和一般驱动类似,首先是进入入口函数DriverEntry ,在DriverEntry 函数中,分别指定各个IRP 的派遣函数地址、指定AddDevice 例程函数地址、指定Unload 例程函数地址等。

在AddDevice 例程中,创建功能设备对象,然后将该对象挂载在总线设备对象之上,从而形成设备栈。另外为设备创建一个设备链接,便于应用程序可以找到这个设备。也可以根据具体需要,从注册表中读取一些必要的设置。

17.3.5 USB 设备的插拔

由于

USB 设备驱动是基于WDM 框架的,因此需要对即插即用消息进行处理。BulkUSB 程序对即插即用IRP 的支持非常完善,具体可以参照其代码,这里简单提一下其对插拔的处理。

插拔设备会设计4个即插即用IRP ,包括IRP_MN_START_DEVICE 、IRP_MN_STOP_ DEVICE 、IRP_MN_EJECT 和IRP_MN_SURPRISE_REMOV AL 。其中,IRP_MN_START_ DEVICE 消息是当驱动争取加载并运行时,操作系统的即插即用管理器会将这个IRP 发往设备驱动。因此,当获得这个IRP 后,USB 驱动需要获得USB 设备类别描述符,如设备描述符、配置描述符、接口描述符、端点描述符等。并通过这些描述符,从中获取有用信息,记录在设备扩展中。

IRP_MN_STOP_DEVICE 是设备关闭前,即插即用管理器发的IRP 。USB 驱动获得这个IRP 时,应该尽快结束当前执行的IRP ,并将其逐个取消掉。另外,在设备扩展中还应该

usb驱动程序教程

编写Windows https://www.sodocs.net/doc/5518662486.html,的usb驱动程序教程 Windows https://www.sodocs.net/doc/5518662486.html, 是微软推出的功能强大的嵌入式操作系统,国内采用此操作系统的厂商已经很多了,本文就以windows https://www.sodocs.net/doc/5518662486.html,为例,简单介绍一下如何开发windows https://www.sodocs.net/doc/5518662486.html, 下的USB驱动程序。 Windows https://www.sodocs.net/doc/5518662486.html, 的USB系统软件分为两层: USB Client设备驱动程序和底层的Windows CE实现的函数层。USB设备驱动程序主要负责利用系统提供的底层接口配置设备,和设备进行通讯。底层的函数提本身又由两部分组成,通用串行总线驱动程序(USBD)模块和较低的主控制器驱动程序(HCD)模块。HCD负责最最底层的处理,USBD模块实现较高的USBD函数接口。USB设备驱动主要利用 USBD接口函数和他们的外围设备打交道。 USB设备驱动程序主要和USBD打交道,所以我们必须详细的了解USBD提供的函数。 主要的传输函数有: abourttransfer issuecontroltransfer closetransfer issuein te rruptransfer getisochresult issueisochtransfer gettransferstatus istransfercomplete issuebulktransfer issuevendortransfer 主要的用于打开和关闭usbd和usb设备之间的通信通道的函数有: abortpipetransfers closepipe isdefaultpipehalted ispipehalted openpipe resetdefaultpipe resetpipe 相应的打包函数接口有: getframelength getframenumber releaseframelengthcontrol setframelength takeframelengthcontrol 取得设置设备配置函数: clearfeature setdescriptor getdescriptor setfeature

未能成功安装设备驱动程序MTPUSB设备安装失败的解决办法

未能成功安装设备驱动程序M T P U S B设备安装失败的解决办法 文件编码(GHTU-UITID-GGBKT-POIU-WUUI-8968)

M T P U S B设备安装失败未能成功安装设备驱动程序 终极解决方法 环境介绍:电脑系统win7(32位)已安装摩托罗拉手机驱动版本(其他版本应该也行,不行的话去摩托罗拉官网下载最新驱动) 手机型号:摩托罗拉defy mb525(系统) 备注:其他电脑操作系统和不同型号手机可参考此方法,找到相应设置项即可。 问题简介: 1.当我们把手机连接至电脑,把模式调制成“摩托罗拉手机门户”时,出现下列情况 2.过一会之后便会弹出提示说:未能成功安装设备驱动程序

3.单击查看详情便弹出窗口如下图所示: 4.此时桌面右下角图标出现黄色三角号,如图所示: 5.于是我们就开始不淡定了,怎么看怎么别扭、抓狂、按耐不住。下面介绍问题解决方案 解决方法: 1.我的电脑——右键单击——管理——设别管理器,之后会看到如图所示:在便携设备下有黄色三角号提示,即是我们纠结的MTP USB设备安装不成功的展示。

MIUI手机操作系统为例,其他手机操作系统需将USB绑定服务开启即可)。选择设置——系统——共享手机网络——USB绑定,将该选项设置为“开”,这是你会发现如图所示变化,在设备管理器面板中没有了便携设备选项及黄色三角号提醒,如图所示:(但桌面右下角的黄色三角警示还在)

3.在完成以上步骤后,用手机打开WIFI并登录无线WLAN,手机打开网页检验连接是否正常,若正常则如下图所示,黄色三角号警示消失,问题解决;若以上步骤没有解决问题,请先连接WIFI并登录WLAN之后,再按步骤操作。 4.完成以上步骤并解决问题后,选择电脑桌面网络——右键单击——属性,如下图所示:此时不仅手机能上网,而且电脑也能正常连接网络,正常上网。(我的体验是连接数据不稳定,时不时的要手机重新登陆WIFI,才有数据传输,可能是高校WLAN的问题,在家网速快的可以尝试一下) 5.通过这个问题的解决,我才知道原来MTP USB设备安装失败,未能成 功安装设备驱动程序的原因是我们手机里面没有启用该设备服务。今天 才知道MTP USB设备是与手机里的共享手机网络中“USB绑定”服务相关 联的,是电脑用来使用手机WIFI网络连接进行上网的工具。

字符设备驱动开发实验

字符设备驱动实验 实验步骤: 1、将设备驱动程序使用马克file文件编译 生成模块firstdev.ko 2、将模块加载到系统中insmod firstdev.ko 3、手动创建设备节点 mknod /dev/first c 122 0 4、使用gcc语句编译firsttest.c生成可执行 文件 5、运行可执行文件firsttest,返回驱动程序 中的打印输出语句。 查看设备号:cat /proc/devices 卸载驱动:rmmod firstdev 删除设备节点:rm /dev/first 显示printk语句,(打开一个新的终端)while true do sudo dmesg -c sleep 1 done

源码分析 设备驱动程序firstdev.c #include #include #include #include #include #include //#include static int first_dev_open(struct inode *inode, struct file *file) { //int i; printk("this is a test!\n"); return 0; }

static struct file_operations first_dev_fops ={ .owner = THIS_MODULE, .open = first_dev_open, }; static int __init first_dev_init(void) { int ret; ret = register_chrdev(122,"/dev/first",&first_dev_fo ps); printk("Hello Modules\n"); if(ret<0) { printk("can't register major number\n"); return ret; }

USB设备驱动程序设计

USB设备驱动程序设计 引言 USB 总线是1995 年微软、IBM 等公司推出的一种新型通信标准总线, 特点是速度快、价格低、独立供电、支持热插拔等,其版本从早期的1.0、1.1 已经发展到目前的2.0 版本,2.0 版本的最高数据传输速度达到480Mbit/s,能 满足包括视频在内的多种高速外部设备的数据传输要求,由于其众多的优点,USB 总线越来越多的被应用到计算机与外设的接口中,芯片厂家也提供了多种USB 接口芯片供设计者使用,为了开发出功能强大的USB 设备,设计者往往 需要自己开发USB 设备驱动程序,驱动程序开发一直是Windows 开发中较难 的一个方面,但是通过使用专门的驱动程序开发包能减小开发的难度,提高工 作效率,本文使用Compuware Numega 公司的DriverStudio3.2 开发包,开发了基于NXP 公司USB2.0 控制芯片ISP1581 的USB 设备驱动程序。 USB 设备驱动程序的模型 USB 设备驱动程序是一种典型的WDM(Windows Driver Model)驱动程序,其程序模型如图1 所示。用户应用程序工作在Windows 操作系统的用户模式层,它不能直接访问USB 设备,当需要访问时,通过调用操作系统的 API(Application programming interface)函数生成I/O 请求信息包(IRP),IRP 被传输到工作于内核模式层的设备驱动程序,并通过驱动程序完成与UBS 外设通 信。设备驱动程序包括两层:函数驱动程序层和总线驱动程序层,函数驱动程 序一方面通过IRP 及API 函数与应用程序通信,另一方面调用相应的总线驱动 程序,总线驱动程序完成和外设硬件通信。USB 总线驱动程序已经由操作系统 提供,驱动程序开发的重点是函数驱动程序。 USB 设备驱动程序的设计

USB WDM 设备驱动程序

USB WDM 设备驱动程序DriverStudio 引言 随着微机技术水平的日益提高,传统的计算接口已经不能满足当前计算机高速发展的需求,计算机业界迫切需要新的通用型、高速总线接口。通用外设接口标准USB应运而生。USB,全称为通用串行总线(Universal Serial Bus),它是Compaq、IBM等PC大厂商联合开发的一种新型的、基于令牌的、高速的串行总线标准。开发者要设计USB设备接口,就必须首先了解USB协议,在此基础上有针对性的开发USB设备驱动程序。 USB简介 在众多的PC机总线中,USB以其突出的优点独树一帜:①使用方便。支持热拔插,不涉及中断请求(IRQ)冲突等问题,能真正做到“即插即用”。②传输速率高。目前的USB 2.0协议速度高达480Mbps 。③易于扩展。通过使用Hub扩展可连接多达127个外设。④使用灵活。USB共有4种传输模式:控制(control)、同步(Synchronization)、中断(interrupt)、批量(bulk),以适应不同设备的需要。⑤独立供电。正由于上述优点,开发USB接口的设备已成为一种发展趋势。 一个完整的USB系统包括主机系统和USB设备。所有的传输事务都是由主机发起的。一个主机系统又可以分为以下几个层次结构,如图1所示:

图1 USB 互连通信模型 USB总线接口包括USB主控制器和根集线器,其中USB主控制器负责处理主机与设备之间电气和协议层的互连,根集线器提供USB设备连接点。USB系统使用USB主控制器来管理主机和USB设备之间的数据传输,另外它也负责管理USB资源,如带宽等。应用软件不能直接访问USB设备硬件,而通过USB系统和USB总线接口与USB设备进行交互。 USB设备包含一些向主机软件提供一系列USB设备的特征和能力的信息的设备描述符,用来配置设备和定位USB设备驱动程序。这些信息确保了主机以正确的方式访问设备。通常,一个设备有一个或多个配置(Configuration)来控制其行为。配置是接口(Interface)的集合,接口指出软件应该如何访问硬件。接口又是端点(endpoint)的集合,每一个与USB交换数据的硬件就为端点,它是作为通信管道的一个终点。图1显示了一个多层次结构的通信模型,它表明了端点和管道所扮演的角色。 WDM驱动程序和USB驱动程序的分层结构 设备驱动程序实际上是指一系列控制硬件设备的函数,是操作系统中控制和连接硬件的关键模块。它提供连接到计算机的硬件设备的软件接口。

一个简单字符设备驱动实例

如何编写Linux设备驱动程序 Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的区别。在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是支持函数少,只能依赖kernel中的函数,有些常用的操作要自己来编写,而且调试也不方便。本文是在编写一块多媒体卡编制的驱动程序后的总结,获得了一些经验,愿与Linux fans共享,有不当之处,请予指正。 以下的一些文字主要来源于khg,johnsonm的Write linux device driver,Brennan's Guide to Inline Assembly,The Linux A-Z,还有清华BBS上的有关device driver的一些资料. 这些资料有的已经过时,有的还有一些错误,我依据自己的试验结果进行了修正. 一、Linux device driver 的概念 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能: 1)对设备初始化和释放; 2)把数据从内核传送到硬件和从硬件读取数据; 3)读取应用程序传送给设备文件的数据和回送应用程序请求的数据; 4)检测和处理设备出现的错误。 在Linux操作系统下有两类主要的设备文件类型,一种是字符设备,另一种是块设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待. 已经提到,用户进程是通过设备文件来与实际的硬件打交道。每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备。另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。设备文件的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序. 最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度。也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作。如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就是漫长的fsck。 二、实例剖析 我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理.把下面的C代码输入机器,你就会获得一个真正的设备

安装USB驱动过程中可能遇到的问题及解决方案

安装USB 驱动过程中可能遇到的问题及解决方案 概述: 本文列举了在安装USB 驱动程序过程中可能遇到的常见问题,并提供了常用的解 决方案。对于其他特殊的情况,如:驱动安装之后出现打印乱码等现象,将在相 关的技术文档中予以进一步的说明。 本文包括: 1. 故障现象: 在打印时遇到:打印到DOT4_00x 端口错误。 故障分析: 1 ).USB 端口没有被正确地识别。USB 电缆不符合规范,长度太长,或者加装 延长线,转接线,共享器等附加设备; 2 ).端口选择不正确; 3 ). 打印机驱动程序未正确安装;如果安装了不匹配的驱动也会出现端口错误。 比如:lj1010 打印机安装了同系列1015 的PCL5e 驱动; 4)). 系统和USB Host Controller 的影响; 5 ).端口供电不足。 解决方案: 1 ).正确连接USB 线,保证USB 电缆长度应小于 2 米,通讯质量较好;取 消延长线和共享器等附加设备; 2 ).检查打印机驱动属性中的端口选项,如果存在多个DOT4 端口, 则首选数 目较高的端口;查看是否有USB 端口,选择USB 端口打印测试; 3 ).取消双向支持;

4 ).完全卸载当前驱动,然后重新启动或热拔插USB 电缆,若系统自动找到新硬件,取消,在device manager 里发现usb printing support 后,再利用“添加打印机向导”添加打印机,安装与打印机语言相匹配的驱动程序,此时,应该选择USB-00X 端口;若系统无法检测到新硬件,要检查系统是否正确识别USB 芯片组,步骤如下: 在Windows 2000/XP 中(Windows 9x/Me 的操作步骤基本类似) ,依次点击“开始→设置→控制面板→系统→硬件→设备管理器”,找到并双击“通用串行总线控制器”。其中应当至少列出两类条目,一类是USB 控制器,另一个是USB Root Hub。如果PC 主板支持USB 2.0 ,并正常安装了驱动程序,一般会在此处显示USB 2.0 Root Hub 。 如果Windows 无法识别出USB 控制器,或在“其他设备”中出现“ USB 控制器”,那么说明主板芯片组的驱动程序或USB 2.0 的驱动程序没有安装成功。建议到芯片组官方网站下载最新的驱动程序,并确认Windows 能正确识别; 5 ).建议将打印机安装到其他计算机上测试; 6 ).保证USB 接口获得足够的电力。USB 设备包含从计算机通过USB 电缆驱动USB 通讯的电源。计算机在100mA 的低电力级别下可以检测到设备,但是需要500mA 才能维持大功率USB 设备的高速通讯(movable disk) 。当打印机得不到充分的电流供应时,也可能造成DOT4 无法正确的设定。建议将打印机直接插在屋内的电源插孔上,而非插在延长线上与其他的电器共用电流,同时尽量使用HP 所附的电源线而非其他可能不合格的电源线,或者为计算机添加有源的USB 集线器。 2. 故障现象: 1 ) . 激光打印机在运行光盘安装驱动程序,插入USB 电缆后或者在出现的新硬件向导下安装打印机时会发生这个错误“ 无法安装这个硬件,在安装LaserJet 1020 时出现了一个问题。安装该设备是发生了一个错误:这个设备的驱动程序丢失了一个必需的项,这可能是由于inf 是为Windows 95 或更新版本而写的。联系您的硬件供应商。”; 2 ).设备控制器的USB 主控制器中出现黄色叹号。 故障分析: 当用打印机驱动光盘的Windows 98 第二版的USB 打印支持驱动程序,而不是使用系统自带的USB 打印支持驱动程序时会发生这种错误。Windows 98 USB 打印驱动程序与更高版本的Windows 操作系统不兼容。

USB编程电缆驱动程序安装说明

USB编程电缆驱动程序安装说明 概述 USB编程电缆是通过将电脑的USB接口模拟成传统的串行口(通常为COM3),从而使用现有的编程软件或通信软件,通过编程电缆与PLC等设备的传统接口进行通信。 功能 ●支持的操作系统Windows2000/Windows XP ●完全兼容USB V1.1和USB CDC V1.1规范 ●USB总线供电(非隔离电缆)、或USB总线供电与PLC的编程口同时供 电(隔离型电缆) ●波特率:300bps~1Mbps自动适应 ●每台PC只支持一根USB编程电缆 系统要求 请在使用USB编程电缆之前确认你的电脑是IBM PC兼容型并具备以下最低系统要求: ●Intel兼容586DX4-100MHz中央处理器或更高 ●一个标准的USB接口(4-pin A型插座) ●运行操作系统为Windows2000或Windows XP 驱动程序的安装 驱动程序的安装非常简单,只需按提示进行即可,以Windows XP为例,按以下步骤进行: 1、打开将要连接USB编程电缆的电脑电源,并确认电脑的USB口已经启 动并正常工作。 2、将USB编程电缆插入电脑的USB接口,Windows将检测到设备并运行 添加新硬件向导帮助你设置新设备,插入驱动程序光盘并单击下一步继 续。 如果Windows没有提示找到新硬件,那么在设备管理器的硬件列表中, 展开“通用串行总线控制器”,选择带问号的USB设备,单击鼠标右键 并运行更新驱动程序。

3、Windows将检测到安装信息,显示“FOURSTAR USB Composite Device ” 设备,并出现如下没有通过Windows徽标测试的信息框,单击“仍然继续”。

USB HID 设备驱动程序设计

USB HID 设备驱动程序设计 引自:https://www.sodocs.net/doc/5518662486.html,/hudaweikevin/archive/2009/11/02/4756394.aspx 摘要:USB(Universal Serial Bus)即“通用串行总线”是一种应用在计算机领域的新型接口技术。它的出现大大简化了PC机和外围设备的连接过程,使PC机接口的扩展变得更加容易。USB作为近年来计算机和嵌入式领域中的热点,推动了计算机外设的飞速发展。本文介绍了适用于PC的嵌入式操作系统的USB HID设备驱动的设计,并给出了具体的实现方法。关键词:USB HID设备PC 嵌入式驱动程序 从USB 1.1到USB2.0再到目前的USB OTG(On-The-Go),USB在不断自我完善,并走向成熟。USB具有高速度、低成本、低功耗、即插即用和使用维护方便等优点,不仅成为了PC主板上的标准接口,而且成为了所有PC外部设备如键盘、鼠标、显示器、打印机、数码相机等与PC相连的标准协议之一,迅速占领了计算机中、低速外部设备的市场。 USB(Universal Serial Bus)即“通用串行总线”是一种应用在计算机领域的新型接口技术。USB的拓扑结构中居于核心地位的是Host(也称为主机)。任何一次USB的数据传输都必须由主机来发起和控制,所有的USB外设都只能和主机建立连接,任何两个外设之间或是两个主机之间无法直接通信。而目前,大量的扮演主机角色的是个人电脑PC。 随着USB应用领域的逐渐扩大,对于USB的期望也越来越高。我们希望USB能应用在各种计算机领域中,希望能通过PDA等移动设备直接和USB外设通信,使得USB能应用在没有PC的领域中。 而我们目前所使用的USB移动设备,大多数都是USB的外设,比如USB的移动硬盘、USB 接口的数码相机等。所有这些设备都只能在PC上使用,只能通过PC来进行相互的文件和数据交换。 本驱动程序是为完善我们自行设计的嵌入式操作系统,使得它具备能识别USB HID设备的功能而开发的。所使用的编程语言为C语言,并下载到目标机上,通过测试验证可以识别USB HID设备,如USB键盘,USB鼠标等。本文探讨的即是PC上实现USB HID设备驱动的方法。 ⒈HID 设备驱动简介 为简化USB设备的开发过程,USB提出了设备类的概念。HID设备类,即人机接口设备。典型的HID设备如键盘、鼠标。 所有设备类都必须支持标准USB描述符和标准USB设备请求。如果有必要,设备类还可以自行定义其专用的描述符和设备请求,这分别被称为设备类定义描述符和设备类定义请求。另外,一个完整的设备类还将指明其接口和端点的使用方法,如如接口所包含端点的个数、端点的最大数据包长度等。 HID设备既可以是低速设备也可以是全速设备,其典型的数据传输类型为中断IN传输,即它适用于主机接收USB设备发来的小量到中等量的数据。HID具有以下的功能特点:1)适用于传输少量或中量的数据;2)传输的数据具有突发性;3)传输的最大速率有限制;4)无固定

【IT专家】Linux设备驱动开发详解

本文由我司收集整编,推荐下载,如有疑问,请与我司联系 Linux设备驱动开发详解 2010/05/09 0 typedef void (*lpFunction) ();//定义一个无参数,无返回类型的函数指针类型 ?//定义一个函数指针,指向cpu启动后所执行的第一条指令的位置 ?lpFunction lpReset = (lpFunction)0xF000FFF0; ?lpReset();//调用函数 ?MMU停供虚拟地址和物理地址的映射、内存访问权限保护和Cache缓存控制等硬件支持。操作系统内核借助MMU,可以让用户感觉到好像程序可以使用非常大的内存空间,从而使得编程人员在写程序时不用考虑计算机的物理内存的实际容量?如图,当ARM要访问存储器时,MMU先查找TLB中的虚拟地址表。如果ARM 的结构支持分开的数据TLB(DTLB)和指令TLB(ITLB),则除去指令使用的ITLB外,其他的都是用DTLB ? ?若TLB中没有虚拟地址的入口,则转换表遍历硬件从存放于主存储器中的转换表中获取地址转换信息和访问权限(即执行TTW),同时将这些信息放入TLB,它或者被放在一个没有使用的入口或者替换一个已经存在的入口。之后,在TLB条目中控制信息的控制下,当访问权限允许时,对真实物理地址的访问将在Cache或者在内存中发生 ?用户空间0-3GB,内核空间3-4GB,用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址。用户进程只能通过系统调用等方式才能访问到内核空间 ?每个进程的用户空间都是完全独立、互不相干的,用户进程各自有不同的页表。而内核空间是由内核负责映射,它并不会跟着进程改变,是固定的。内核空间地址有自己对应的叶表,内核的虚拟空间独立于其他程序 ?Linux中的1GB内核地址空间又被划分为内存映射区,虚拟内存分配区、高端页面映射区、专用页面映射区和系统保留映射区

未能成功安装设备驱动程序MTPUSB设备安装失败的解决办法

M T P U S B设备安装失败未能成功安装设备驱动程序 终极解决方法 环境介绍:电脑系统win7(32位)已安装摩托罗拉手机驱动版本(其他版本应该也行,不行的话去摩托罗拉官网下载最新驱动) 手机型号 备注:其他电脑操作系统和不同型号手机可参考此方法,找到相应设置项即可。 问题简介: 1.当我们把手机连接至电脑,把模式调制成“摩托罗拉手机门户”时,出现下列情况 2.过一会之后便会弹出提示说:未能成功安装设备驱动程序 3.单击查看详情便弹出窗口如下图所示: 4.此时桌面右下角图标出现黄色三角号,如图所示: 5.于是我们就开始不淡定了,怎么看怎么别扭、抓狂、按耐不住。下面介绍问题解决方案 解决方法: 1.我的电脑——右键单击——管理——设别管理器,之后会看到如图所示:在便携设备下有黄色三角号提示,即是我们纠结的MTP USB设备安装不成功的展示。 2.对手机进行设置(这是关键步骤),(备注:以MIUI手机操作系统为例,其他手机操作系统需将USB 绑定服务开启即可)。选择设置——系统——共享手机网络——USB绑定,将该选项设置为“开”,这是你会发现如图所示变化,在设备管理器面板中没有了便携设备选项及黄色三角号提醒,如图所示:(但桌面右下角的黄色三角警示还在) 3.在完成以上步骤后,用手机打开WIFI并登录无线WLAN,手机打开网页检验连接是否正常,若正常则如下图所示,黄色三角号警示消失,问题解决;若以上步骤没有解决问题,请先连接WIFI并登录WLAN之后,再按步骤操作。 4.完成以上步骤并解决问题后,选择电脑桌面网络——右键单击——属性,如下图所示:此时不仅手机能上网,而且电脑也能正常连接网络,正常上网。(我的体验是连接数据不稳定,时不时的要手机重新登陆WIFI,才有数据传输,可能是高校WLAN的问题,在家网速快的可以尝试一下) 5.通过这个问题的解决,我才知道原来MTP USB设备安装失败,未能成功安装设备驱动程序的原因是我 们手机里面没有启用该设备服务。今天才知道MTP USB设备是与手机里的共享手机网络中“USB绑定”服 务相关联的,是电脑用来使用手机WIFI网络连接进行上网的工具。

11-4~6 字符设备驱动开发

一、字符驱动初步认识 (2) (一)字符设备驱动框架 (2) (二)主设备号 (2) (三)创建设备节点: (4) 1.手动创建 (4) 2.自动创建(通过udev/mdev机制) (4) (四)应用程序与驱动的交互 (5) 1.驱动中实现文件io操作接口: (5) 2.调用IO接口 (7) 3.应用程序需要传递数据给驱动 (8) 4.控制外设 (9) 二、字符设备驱动开发 (10) (一)应用程序和驱动扮演的是什么角色 (10) (二)步骤: (10) 1.实现模块加载和卸载入口函数 (10) 2.在模块加载入口函数中 (10) (三)规范: (11) 1.面向对象编程思想 (11) (四)做出错处理 (12) (五)操作寄存器地址到方式: (12) 三、 Day4作业 (13) 四、 Day5作业 (14) 五、 Day6作业 (14)

一、字符驱动基本操作 (一)字符设备驱动框架 用户空间对驱动的操作其实就是文件IO 字符设备:所产生的数据是字符流 大部分设备都是字符设备,如:LCD,keyboard,I2c等。 因为字符设备的数据是从寄存器中产生,所以数据量不大,速度快 字符设备的读取方式:文件IO 块设备:存储设备,数据以块为单位。如:硬盘、u盘、flash、sd卡等 读取的数据量大,速度慢 内核对这样的操作进行优化机制,如缓冲,文件系统层等 网络设备:因为是走协议的,linux把网络设备全部做成socket设备 当用户空间输入open打开一个字符设备的时候,会调用在字符设备驱动中会对应的XX_open,这个XX_open是一一对应的。而用户空间的open和内核中的open 对应关系是由,设备节点管理的。而设备节点就是一个文件,在这个文件中通过设备号来做到意义对应。 作为字符设备驱动要素: 1,必须有一个设备号,用在众多到设备驱动中进行区分 2,用户必须知道设备驱动对应到设备节点(设备文件) linux把所有到设备都看成文件 crw-r----- 1 root root 13, 64 Mar 28 20:14 event0 crw-r----- 1 root root 13, 65 Mar 28 20:14 event1 crw-r----- 1 root root 13, 66 Mar 28 20:14 event2 3,对设备操作其实就是对文件操作,应用空间操作open,read,write的时候实际在驱动代码有对应到open, read,write (二)主设备号 作为驱动必须有一个主设备号--向系统申请 功能:申请主设备号 原型:int register_chrdev(unsigned int major, const char * name, const struct file_operations * fops) 参数:1:major:主设备号 设备号(32bit--dev_t)==主设备号(高12bit) + 次设备号(20bit) 主设备号:表示一类设备--camera 次设备号:表示一类设备中某一个:前置,后置 给定到方式有两种:

怎样写linux下的USB设备驱动程序

怎样写linux下的USB设备驱动程序 发布时间:2007年11月19日 引言 随着人们生活水平的提高,我们用到的USB设备也越来越多,但是Linux在硬件配置上仍然没有做到完全即插即用,对于Linux怎样配置和使用他们,也越来越成为困扰我们的一大问题;本文的目地是使大家了解怎样编制USB设备驱动,为更好地配置和使用USB设备提供方便;对于希望开发Linux系统下USB设备驱动的人员,也可作为进一步学习USB驱动的大体架构进而编写出特殊USB设备的驱动程序。 USB基础知识 USB是英文Universal Serial Bus的缩写,意为通用串行总线。USB最初是为了替代许多不同的低速总线(包括并行、串行和键盘连接)而设计的,它以单一类型的总线连接各种不同的类型的设备。USB的发展已经超越了这些低速的连接方式,它现在可以支持几乎所有可以连接到PC上的设备。最新的USB规范修订了理论上高达480Mbps的高速连接。Linux内核支持两种主要类型的USB驱动程序:宿主系统上的驱动程序和设备上的驱动程序,从宿主的观点来看(一个普通的宿主也就是一个PC机),宿主系统的USB设备驱动程序控制插入其中的USB设备,而USB设备的驱动程序控制该设备如何作为一个USB设备和主机通信。本文将详细介绍运行于PC机上的USB系统是如何运作的。并同时用USB驱动程序的框架程序当例子作详细的说明,我们在此文中不讨论USB器件的驱动程序。 USB驱动程序基础 在动手写USB驱动程序这前,让我们先看看写的USB驱动程序在内核中的结构,如下图: USB驱动程序存在于不同的内核子系统和USB硬件控制器之间,USB核心为USB驱动程序提供了一个用于访问和控制USB硬件的接口,而不必考虑系统当前存在的各种不同类型的USB硬件控制器。USB是一个非常复杂的设备,linux内核为我们提供了一个称为USB的核心的子系统来处理大部分的复杂性,USB

USB设备驱动程序的开发与USB协议

第1章绪论 1.1USB简介 USB是由世界著名计算机和通信公司等共同推出的新一代接口标准,全称为Universal Serial Bus(通用串行总线)[1],是一种快速、灵活的总线接口。它是为了解决日益增加的PC外设与有限的主板插槽和端口之间的矛盾而制定的一种串行通信标准。USB应用十分广泛,并具有下述优点: 1、适用于多种外设,使它不需要为不同的外设准备不同的接口和协议; 2、Windows能自动检测到USB设备的热插拔,并自动配置; 3、PC机上的接口线非常紧缺,而USB设备并不需要用户设置端口故无论从用户使用方便性,或从对资源的占用方面看,USB都很优秀; 4、当接入一个USB设备时,全速USB接口可达12Mbit/s。考虑到状态、控制和出错信息,最大理论速度仍可达到9.6Mbit/s,这是其他串行接口协议所不能比拟的,且USB也支持1.5Mbit/s的低速传输。

5、USB接口芯片价格低廉,这也大大促进USB设备的开发与应用。 在USB出现之前,计算机典型接口有并行口、串行口、鼠标口、键盘口、显示器口,及各种卡式接口等,与这些接口对应的有各种不同的电缆,在传输速度方面,这些接口都存在速度偏低的问题。在技术方面,这种设计容易产生I/O冲突,中断不够用,以及对于每一种新的外设都必须设计新的接口卡等缺点。当今的计算机外部设备,都在追求高速度和高通用性。USB接口适应了这种要求,并以其速度快、使用方便、成本低等优点,迅速得到了众多PC厂商和半导体厂商的大力支持,外设向USB过度成为必然趋势。 1.2USB驱动程序的意义 如果PC主机不知道如何与USB外设通信,那么这个USB外设一点用处都没有,人机接口设备(HID)[2]类是Windows完全支持的USB设备类型中的一种,应用程序可以使用操作系统内设置的驱动与HID通信,但与HID 通信不像打开一个端口,设定几个参数,然后就可以读写数据那么简单,在应用程序能与HID交换数据之前,它先要找到设备,获取有关它的报告信息。为做到这些,应用程序必须通过访问通信API函数,使位于上层的应用程序与位于下层的设备驱动程序进行数据交换。应用程序可以使用任何能访问API函数的程序语言,VC++是一种能访问API函数的功能强大的语言,因此,我们应用Visual C++6.0环境下编写与USB设备通信的Windows程序。 1.3VC++软件的介绍 应用基于MFC AppWizard的应用程序。MFC (Microsoft Foundation Class Library)中的各种类结合起来构成了一个应用程序框架,它的目的就是在此基础上来建立Windows下的应用程序,这是一种相对SDK来说更为简单的方法。因为总体上,MFC框架定义了应用程序的轮廓,并提供了用户接口的标准实现方法,要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓。Microsoft Visual C++提供了相应的工具来完成这个工作:

Windows_PCI设备驱动开发

PCI设备驱动开发 PCI设备驱动开发 2008-08-28 13:07 1. PCI 简介 PCI 总线标准是一种将系统外部设备连接起来的总线标准,是PC 中最重要的总线,实际上是系统的各个部分如何交互的接口。传输速率可达到133MB/s。在当前的PC 体系结构中,几乎所有的外部设备采用的各种各样的接口总线,均是通过桥接电路挂接到PCI 系统上。在这种PCI 系统中,Host/PCI 桥称为北桥,连接主处理器总线到基础PCI 局部总线。PCI 与其他总线的接口称为南桥,其中南桥还通常含有中断控制器、IDE 控制器、USB 控制器和DMA 控制器等。南桥和北桥组成主板的芯片组。 2. PCI配置空间 每个PCI设备都有自己的配置空间,用于支持即插即用,使之满足现行的系统配置结构。下面对PCI配置空间做一下简要介绍。 配置空间是一容量为256字节并具有特定结构的地址空间。这个空间又分为头标区和设备有关区两部分。头标区的长度是64字节,每个设备都必须配置该区的寄存器。该区中的各个字段用来唯一地识别设备。其余的192字节因设备而异。配置空间的头标区64个字节的使用情况如图1示。 为了实现即插即用,系统可根据硬件资源的使用情况,为PCI设备分配新的资源。因此编写设备驱动程序重点是获得基址寄存器(Base Address)和中断干线寄存器的内容。配置空间共有六个基址寄存器和一个中断干线寄存器,具体用法如下: PCI Base Address 0寄存器:系统利用此寄存器为PCI接口芯片的配置寄存器分配一段PCI地址空间,通过这段地址我们可以以内存映射的形式访问PCI接口芯片的配置寄存器。 PCI Base Address 1寄存器:系统利用此寄存器为PCI接口芯片的配置寄存器分配一段PCI地址空间,通过这段地址我们可以以I/O的形式访问PCI接口芯片的配置寄存器。 PCI Base Address 2、3、4、5寄存器:系统BIOS利用这些寄存器分配PCI地址空间以支持PCI接口芯片的局部配置寄存器0、1、2、3的访问。 在所有基址寄存器中,第0位均为只读位,表示这段地址映射到存储器空间还是I/O空间,如果是“1”表示映射到I/O空间,如果是“0”则表示映射到存储器空间。 中断干线寄存器(Interrupt Line):用于说明中断线的连接情况,这个寄存器的值与标准8259的IRQ编号(0~15)对应。

开发usb驱动程序的方法

开发驱动程序的方法(连载一) 开始驱动程序设计 下面的文字是从的帮助中节选出来的,它让我们明白在开始设计驱动程序应该注意些什么问题,这些都是具有普遍意义的开发准则。应该支持哪些请求在开始写任何代码之前,应该首先确定我们的驱动程序应该处理哪些例程。 如果你在设计一个设备驱动程序,你应该支持和其他相同类型设备的驱动程序相同的和请求代码。 如果你是在设计一个中间层驱动程序,应该首先确认你下层驱动程序所管理的设备,因为一个高层的驱动程序必须具有低层驱动程序绝大多数例程入口。高层驱动程序在接到请求时,在确定自身当前堆栈单元参数有效的前提下,设置好中下一个低层驱动程序的堆栈单元,然后再调用将请求传递给下层驱动程序处理。 一旦决定好了你的驱动程序应该处理哪些,就可以开始确定驱动程序应该有多少个例程。当然也可以考虑把某些处理的例程合并为同一例程处理。例如在和里,对和处理的例程就是同一函数。对和处理的例程也是同一个函数。 应该有多少个对象? 一个驱动程序必须为它所管理的每个可能成为请求的目标的物理和逻辑设备创建一个命名对象。一些低层的驱动程序还可能要创建一些不确定数目的对象。例如一个硬盘驱动程序必须为每一个物理硬盘创建一个对象,同时还必须为每个物理磁盘上的每个逻辑分区创建一个对象。 一个高层驱动驱动程序必须为它所代表的虚拟设备创建一个对象,这样更高层的驱动程序才能连接它们的对象到这个驱动程序的对象。另外,一个高层驱动程序通常为它低层驱动程序所创建的对象创建一系列的虚拟或逻辑对象。 尽管你可以分阶段来设计你的驱动程序,因此一个处在开发阶段的驱动程序不必一开始就创建出所有它将要处理的所有对象。但从一开始就确定好你最终要创建的所有对象将有助于设计者所要解决的任何同步问题。另外,确定所要创建的对象还有助于你定义对象的的内容和数据结构。 开始驱动程序开发 驱动程序的开发是一个从粗到细逐步求精的过程。的\ 目录下有一个庞大的样板代码,几乎覆盖了所有类型的设备驱动程序、高层驱动程序和过滤器驱动程序。在开始开发你的驱动程序之前,你应该在这个样板库下面寻找是否有和你所要开发的类似类型的例程。例如我们所开发的驱动程序,虽然对描述得不是很详细,我们还是可以在\\目录发现很多和设备有关的驱动程序。下面我们来看开发驱动程序的基本步骤。 最简的驱动程序框架 、写一个例程,在里面调用创建一个对象。 、写一个处理请求的例程的基本框架 (参见 4.4.3描述的一个例程所要完成的最基本工作。当然写了例程后,要在例程为初始化例程入口)。如果驱动程序创建了多于一个对象,则必须为请求写一个例程,该例程通常情况下可以和共用一个例程,参见参见。 、编译连接你的驱动程序。 用下面的方法来测试你的驱动程序。 首先按上面介绍的方法安装好驱动程序。 其次我们还得为逻辑设备名称和目标对象名称之间建立起符号连接,我们在前面已经知道对象名称对用户模式是不可见的,是不能直接通过来访问的,只能访问逻辑设备名称。我们可以通过修改注册表来建立这两种名称之间的符号连接。运行在\\ \ \\ \ 下建立起符号连接(这种符号连接也可以在驱动程序里调用函数来创建)。

usb设备驱动程序usb gadget driver(4)

USB设备驱动程序-USB Gadget Driver(4)  Gadget 功能层Gadget功能层完成USB设备的具体功能,其表现的形式各不相同,如键盘、鼠标、存储和网卡等等。功能层不仅涉及到Gadget驱动相关的内容,还涉及到其功能相关的内核子系统。如存储还涉及到内核存储子系统,网卡还涉及到网络驱动子系统。因此,Gadget功能的代码非常复杂。这里以zero.c为例,这个模块只是简单地将接收的数据回显回去。一、数据结构首先需要实现 usb_composite_driver函数集:static struct usb_composite_driver zero_driver = { .name = "zero", .dev = &device_desc, .strings = dev_strings, .bind = zero_bind, .unbind = zero_unbind, .suspend = zero_suspend, .resume = zero_resume, }; 二、主要函数这个模块的实现就是这么简单:static int __init init(void) { return usb_composite_register(&zero_driver); }

module_init(init); static void __exit cleanup(void) { usb_composite_unregister(&zero_driver); } Bind函数是功能层需要实现与设备层关联的重要函数:static int __init zero_bind(struct usb_composite_dev *cdev) { int gcnum; struct usb_gadget *gadget = cdev->gadget; //Gadget设备 int id; /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ /*分配字符串描述符的id,并赋值给设备描述符中字符串索引*/ id = usb_string_id(cdev); strings_dev[STRING_MANUFACTURER_IDX].id = id; device_desc.iManufacturer = id; id = usb_string_id(cdev); i strings_dev[STRING_PRODUCT_IDX].id = id; device_desc.iProduct = id; id = usb_string_id(cdev); strings_dev[STRING_SERIAL_IDX].id = id; device_desc.iSerialNumber = id; /*设置挂起后,设备自动恢复的定时器*/ setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev); /*核心代码,实现

相关主题