Linux上USB驱动开发

Linux驱动开发培训系列教程网址https://edu.****.net/course/detail/26814

本次课程分3个部分讲述USB驱动开发
第一部分:USB基本概念
第二部分:USB设备驱动框架
第三部分:实例分析(****)

第一部分:USB基本概念

1,设备描述符:
设备描从整体述符描述了USB设备的通用信息,一个USB设备只有一个设备描述符。是在设备连接时,主机第一个读取的描述符。

typedef struct USB_DEVICE_DESCRIPTOR
{
BYTE bLength,
BYTE bDescriptorType,
WORD bcdUSB,
BYTE bDeviceClass,
BTYE bDeviceSubClass,
BYTE bDeviceProtol,
BYTE bMaxPacketSize0,
WORD idVenderI,
WORD idProduct,
WORD bcdDevice,
BYTE iManufacturer,
BYTE iProduct,
BYTE iSerialNumber,
BYTE iNumConfiguations
}USB_DEVICE_DESCRIPTOR;

1)、bLength
该字段表示整个设备描述符的字节数大小。而整个设备描述符占用了17个字节, 因此bLength的值是固定的, 就是18, 用十六进制表示就是0x12。

2)、bDescriptorType
设备描述符的类型。USB定义的设备描述符的类型编号为常数0x01,因此,该字段的值为固定值0x01。

3)、bcdUSB
该字段代表设备所遵循的USB协议的版本号。
USB1.1,其bcdUSB值为0x0110
USB2.0,其bcdUSB值为0x0200

4)、bDeviceClass
设备类型的代码。值从0x01~0xFE为USB定义的标准设备类,而值为0xFF时表示该设备类型代码是厂商自定义的类。如果设备类型不在设备描述符中定义的, 则该值为0(可以在接口描述符中定义设备类型)。比如人机接口设备 ( HID) 类。

5)、bDeviceSubClass
设备类中的子类类型。和bDeviceClass一样由USB规定和分配,当 上面一项为0时,本项也要设置为0。 代表该子类类型不在设备描述符中定义。 值为0xFF时, 也代表子类类型是由厂商所定义的。

6)、bDeviceProtocol
设备所遵循的协议,该值有USB协议规定,当值为0xFF时,表示该设备采用厂商自己为该类定义的协议。上面一项为0时,本项也要设置为0。

7)、bMaxPacketSize0
比较特殊的是, 默认控制管道的数据包的长度(也就是USB设备端点0的长度)是在设备描述符中定义的, 而不像其他端点一样是在端点描述符中定义的。
描述了端点0的最大包的大小, 低速设备的bMaxPacketSize0恒为8, 全速设备可以是一般为 8、16、32或64, 即0x08、0x10、0x20或0x40, 而高速设备则为64。

8)、idVendor
厂商编号。这个是需要跟USB组织申请的ID号,表示厂商代号。

9)、idProduct
该产品的编号。跟厂商编号一起配合使用,让主机注册该设备并加载相应的驱动程序。

10)、bcdDevice
设备出厂编号。

11)、iMenufacturer
设备生产厂商的字符串的索引值。值为0则代表没有使用该字段。在获取字符串描述符时,使用该索引号来识别不同的字符串。

12)、iProduct
描述该产品的字符串的索引值。值为0时表示没有使用该字段。同上。

13)、iSerialNumber
设备的***的索引值。每个设备都有一个特定的***, 可供主机来识别不同的设备。同上。

14)、bNumConfigurations
该设备总共支持的配置描述符的数量。

2,配置描述符:
配置描述符用于描述一个USB设备的属性和能力等配置信息。通常一个USB设备只需要一个配置描述符就可以了。比如一个USB接口的鼠标,其功能仅仅是简单的双向数据中断传输, 并且是总线供电。因此按照这些要求来填写一个配置描述符即可。
不过多用途的USB设备可以支持多个配置,但在同一时间只能有一个配置起作用。 每一个配置都需要一个配置描述符。配置描述符中包含设备的电源使用以及支持的接口数目。每一个配置描述符包含一个或多个接口描述符。
配置描述符不会单独发送给USB主机,通常会以集合的形式发送给主机。集合通常包含:配置描述符,接口描述符,端点描述符,HID描述符。这几个描述符组成一个大数组。
typedef struct USB_CONFIGURATION_DESCRIPTOR
{
BYTE bLength,
BYTE bDescriptorType,
WORD wTotalLength,
BYTE bNumInterfaces,
BYTE bConfigurationValue,
BYTE iConfiguration,
BYTE bmAttributes,
BYTE MaxPower
}USB_CONFIGURATION_DESCRIPTOR;

11)、bLedgth
整个配置描述符的长度, 因此bLength是固定的, 值为9, 即0x09。

2)、bDescriptorType
USB给配置描述符分配的类型编号, 值为常数0x02。

3)、wTotalLength
此配置信息的总长(包括配置,接口,端点),即:将要返回的配置信息总长度。

4)、bNumInterfaces
该配置所支持的接口总数。

5)、bConfigurationValue
配置值。
一个USB设备可以有多个配置,配置值就是每个配置的标识。设置配置请求时,会发送配置值。如果发送的值和这里值一样,说明这个配值被**(USB设备启用该配置)。
主机调用Get_Configuration读取某个配置。使用参数0,得到第一个配置描述符,使用参数1,得到第二个配置描述符。
主机调用Set_Configuration启用某个配置。把上一步取得的配置描述符中的bConfigurationValue值(不一定是从0开始),作为控制参数传递给USB设备,启动某个配置。

6)、iConfiguration
该字段指向描述该配置描述符的字符串。 如果该设备没有用字符串描述该配置, 那么此字段为0。

7)、bmAttributes
该字段1字节二进制数的每一位代表一个固定的含义:
D7:Reserve,固定为1;
D6:供电方式的选择, 值为1表示自供电, 值为0表示总线供电;
D5:远程唤醒功能的选择, 值为1表示支持远程唤醒, 值为0则不支持;
D4~D0:没有意义, 均把值固定为0。

8)、MaxPower
设备从总线上获取的电流总量。电流值为字段值的两倍,设备可以获取到的最大电流为500mA,所以字段值最大为0xFA;

说明:
如果主机发出标准命令Get_Descriptor要求获得设备的某个配置描述符时,该配置的所有信息都将发给主机,它包括:该标准配置符本身、该配置所包含的所有接口、端点描述符及设备类描述符和厂商描述符。

3,接口描述符:
接口描述符用于描述一个特定接口的属性。接口一般是由一系列端点所组成的集合体,用于实现某种特定的USB的数据传输功能。一般一个USB设备只需具有一个接口。比如,USB移动存储设备中就只有一个用于实现Mass Storage类的接口, 在该接口下使用了批量输入Bulk_IN和批量输出Bulk_OUT 2个非0端点用于传输文件。接口描述符还可以在配置后加以改变。前面已经提到, 标准的USB设备类型都是在设备描述符中定义的, 但是有些类是基于接口在接口描述符中定义的, 如HID设备。接口描述符对应一个逻辑设备。
typedef struct USB_INTERFACE_DESCRIPTOR
{
BYTE bLength,
BYTE bDescriptorType,
BYTE bInterfaceNumber,
BYTE bAlternateSetting,
BYTE bNumEndpoint,
BYTE bInterfaceClass,
BYTE bInterfaceSubClass,
BYTE bInterfaceProtocol,
BYTE iInterface
}USB_INTERFACE_DESCRIPTOR;

(1)、bLength
标准的接口描述符的长度是9个字节。

(2)、bDescriptorType
表示描述符的类型,接口描述符对应的值是4。

(3)、bInterfaceNumber
接口的编号。如果一个配置拥有N个接口, 那么这些接口都是互不相干的, 每一个接口都有惟一的编号, USB就是通过此字段来识别不同的接口。默认值为0。

(4)、bAlternateSetting
接口的备用编号,一般使用0。
上面讲的USB设备的配置与USB配置描述符是一一对应的, 即一个配置只能有一个配置描述符。USB允许一个接口有多个接口描述符, 而且这些描述符都可以通过命令来切换。此字段就是每一个这类描述符惟一的编号。USB可以通过调用这个字段来切换描述同一个接口的不同描述符。控制传输中可以通过Get_Interface和Set_Interface来获取、设置目前正在使用的描述一个确定接口的接口描述符的编号。

(5)、bNumEndpoints
该接口使用的端点总数(除端点0之外)。如果此值为0, 则意味着该接口只使用端点0。

(6)、bInterfaceClass
该接口所属的类别。这个类别编号由USB来分配。当值为0xFF时, 表示该接口是厂商所定义的接口类型。而值0保留。

(7)、bInterfaceSubClass
接口所属的类别中的子类类型。这个子类编号也由USB分配。同bInterfaceClass字段一样, 当其值为0xFF时代表该接口由厂商自己所定义。而值0保留。

(8)、bInterfaceProtocol
此接口类所遵循的类的协议。因而, 该字段的值跟bInterfaceClass和bInterfaceSubClass字段是相关的。其值从1~0xFE由USB分配, 代表不同标准的设备类的协议。 当值为0时, 表示该接口不遵循任何类协议; 而值为0xFF时, 表示该接口应用了厂商自定义的类协议。

(9)、iInterface
指向字符串描述符中相应的字符串内容, 用于描述该接口。 如果设备没有启用字符串描述符 , 则该值为0。

4,端点描述符:
端点描述符用于描述接口所使用的非0端点的属性, 包括输入/输出方向、端点编号、端点容量、数据传输方式。
USB设备中的每个端点都有自己的端点描述符,由接口描述符中的bNumEndpoint决定其数量。

typedef struct USB_ENDPOINT_DESCRIPTOR
{
BYTE bLength,
BYTE bDescriptorType,
BYTE bEndpointAddress,
BYTE bmAttributes,
WORD wMaxPacketSize,
BYTE bInterval
}USB_ENDPOINT_DESCRIPTOR;

(1)、bLength
这个端点描述符的长度。

(2)、bDescriptorType
USB为端点描述符分配的类型编号, 因此, 此字段的值固定, 即为0x05。

(3)、bEndpointAddress
D7 端点方向
0 OUT端点
1 IN端点
D6~D4 保留
D3~D0 端点编号

(4)、bmAttributes
D5~D4 用途
00 数据端点
01 反馈端点
10 隐式反馈数据端点
11 保留
D3~D2 同步类型
00 非同步
01 异步
10 自适应
11 同步
D1~D0 传输类型
00 控制传输
01 同步传输
10 块传输
11 中断传输
如果该端点不是同步端点,D5~D2保留且必须置0。

(5)、wMaxPacketSize
该端点最大包的大小。其中D10~D0位共11位为有效内容。在USB协议1 .1中D15~D11位保留, 值为0, 且最大包的大小范围为0~1023。

(6)、bIterval
主机轮询设备的周期。在USB协议1.1中, 对于中断端点, 该字段的值为1~255,时间单位ms,因此假设值为250, 则表示时间间隔为250ms; 对于同步端点, 该字段值固定为1 ; 而批量端点和控制端点则忽略该字段 ,值无效。

第二部分:USB设备驱动框架

一,和platform机制的对比
二,USB设备和驱动的配对机制

1,usb device driver
USB子系统初始化的时候就会注册驱动usb_generic_driver。它是USB系统中唯一的一个USB设备驱动,所有的USB设备都对应该驱动。
作用:
1)当主机上插入USB设备时,USB设备被探测并被注册到系统后(用device_add),
2)系统调用usb_bus_type.mach( )。只要是usb设备,都会跟usb_generic_driver匹配上。
3)调用usb_probe_device( ),从而调用usb_generic_driver的 probe( )函数。
4)probe( )函数为USB设备选择一个合适的配置,让设备进入configured状态。

2 ,usb driver

USB驱动(usb driver)就是USB设备的接口驱动程序,比如U盘驱动程序,鼠标驱动程序等等。

  • 从USB设备的配置中提取出接口,对接口调用device_add( ),向USB总线注册设备(此处指接口,逻辑设备)。
  • Linux启动时注册USB驱动,通过usb_register( )将USB驱动(接口驱动,或者叫逻辑设备驱动)提交给系统,添加到USB总线的驱动链表里。
  • 当驱动的id_table包含接口中的 bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol三项时, 说明该驱动和该接口匹配,系统会调用驱动的probe函数。

Linux上USB驱动开发

Linux上USB驱动开发

第三部分:实例分析

以****的形式进行讲解