《精通linux设备驱动程序开发》——USB

一、USB体系架构

一)、简介

1、USB通信协议采用主从结构,实现了主机控制器和外围设备的通信。USB主机控制器属于南桥芯片的一部分,通过PCI总线和处理器通信。

2、PC机上的USB系统(P217 图11-1)和嵌入式设备上的USB系统(P217 图11-2)。

3、嵌入式设备上的USB系统中的SOC内嵌了USB控制器,该控制器支持4条总线和3种操作模式。

1)、总线1工作在主机模式下,通过(P217 图11-1)收发器和A型接口有限连接。该A型接口可用来连接笔驱动或者键盘。

2)、总线2工作在主机模式下,其USB收发器连接的是内嵌USB设备。

3)、总线3工作在设备模式下,通过USB收发器和B型接口有线连接,B型接口通过一条B-A线和主机连接。在该模式下,该嵌入式设备可以当USB笔驱动设备使用,同时也可

为主机提供另一个存储分区。

4)、总线4接的是OTG控制器。使用这种接口,既可以把笔驱动器连接到系统上,也可以把系统连接到另一台主机上。

二)、总线速度

1、USB传输的速度有三种:

1)、USB1.0标准支持的速度是1.5MB/s,称为低速USB。

2)、USB1.1标准支持的速度是12MB/s,称为全速USB。

3)、USB2.0标准支持的速度是480MB/s,称为高速速USB。

三)、主机控制器

1、USB主机控制器分为以下几种:

1)、UHCI(通用主机控制器接口)。

2)、OHCI(开放主机控制器接口)。

3)、FHCI(增强主机控制器接口)。

4)、USB OTG控制器。

四)、传输模式

1、USB传输数据的模式有四种:

1)、控制传输模式,用来传输外设和主机之间的控制、状态、配置等信息。

2)、批量传输模式,传输大量时延要求不高的数据。

3)、中断传输模式,传输数据量小,但是对传输时延敏感,要求马上相应。

4)、等时传输模式,传输实时数据,传输速率要预先可知。

五)、寻址

1、USB设备里的每个可寻址单元称作端点。为每个端点分配的地址称为端点地址。

1)、每个端点地址都有与之相关的传输模式。地址为0的端点专门用来配置设备。控制管道和它相连,完成设备枚举过程。

2)、每个端点可以沿上行方向发送数据,也可以沿下行方向接收数据。沿上行方向从设备接收数据叫IN传输。 沿下行方向到达设备叫OUT传输。

二、Linux-USB子系统

1、Linux-USB子系统架构。(P220 图11-3)

2、Linux-USB子系统组成:

1)、USB核心。

2)、驱动不同主机控制器的HCD。

3)、用于根集线器的hub驱动和一个内核辅助线程khubd。

4)、用于USB客户设备的设备驱动程序。

5)、USB文件系统usbfs,它能够让你从用户空间驱动USB设备。

三、驱动程序的数据结构

一)、usb_device结构体

struct usb_device {

/* …… */

enum usb_device_state state;

enum usb_device_speed speed;

/* …… */

struct usb_device *parent;

/* …… */

struct usb_device_descriptor descriptor;

struct usb_host_config *config;

struct usb_host_config *actconfig;

/* …… */

int maxchild;

struct usb_device *children[USB_MAXCHILDREN];

/* …… */

};

二)、URB

1、URB是USB数据传输机制使用的核心数据结构。URB供USB协议栈使用。

2、URB结构

struct urb {

struct kref kref;

/* …… */

struct usb_device *dev;

unsigned int pipe;

int status;

unsigned int transfer_flags;

void *transfer_dma;

dma_addr_t trsanfer_dma;

int tranfer_buffer_length;

/* …… */

unsigned char *setup_packet;

/* …… */

int interval;

/* …… */

void *context;

usb_complete complete;

/* …… */

};

3、URB的使用分3步:分配内存,初始化,提交。

1)、URB的内存是调用usb_alloc_urb()方法来分配的,该函数分配内存并将其置零,之后初始化URB相关的kobject和用于保护URB的自旋锁。

2)、为了提交URB以便进行数据传输,需调用usb_submit_urb()函数。该函数异步提交URB。回调函数的地址作为参数传递给usb_fill_[control | int | bluk]_urb()函数。回

调函数在URB提交过后被调用,负责完成检查提交状态、释放传输数据缓冲区等事情。

3)、USB核心也提供了同步提交URB的接口函数:int usb_[control | interrupt | bilk]_msg()。

4)、URB的任务完成后,usb_free_urb()函数释放该实例。usb_unlink_urb()取消一个待处理的URB。

四)、管道

1、管道包括以下几个部分:

1)、端点地址。

2)、数据传输方向。

3)、数据传输模式。

2、管道的创建

1)、USB核心提供现成的宏来创建管道。

usb_[rcv | snd] [ctrl | int | bulk | isoc]pipe(struct usb_device *usb_dev, __u8 endpointAddress);

五)、描述符接口

1、USB标准定义了一系列的描述符数据结构来保护设备的信息。Linux-USB核心定义的描述符有四种类型。

1)、设备描述符存放设备的普通信息。usb_device_descriptor结构体表示设备描述符。

2)、配置描述符用来描述设备配置模式。usb_config_descriptor结构体用于表示配置描述符。

3)、接口描述符使得USB能支持多种功能。usb_interface_descriptor结构体表示接口描述符。

4)、端点描述符存放设备最终的端点信息。usb_endpoint_descriptor结构体用于表示端点描述符。

四、枚举

1、枚举过程是热插拔USB设备的其实步骤,该过程中,主机控制器获得设备的相关信息并配置好设备。在linux-USB子系统中,集线器驱动程序负责该枚举过程。

五、设备实例:遥测卡

一)、简介

1、遥控卡的寄存器

2、USB遥测卡端点说明:

1)、控制端点附在一个卡上配置寄存器中。

2)、批量IN端点负责把卡收集到的遥测数据传递个给处理器。

3)、批量OUT端点负责接收处理器传递过来的数据。

二)、初始化和探测过程

1、USB驱动程序用probe()/disconnect()方法支持热插拔,用设备ID表识别驱动程序所支持的设备。

struct usb_device_id {

/* …. */

__u16 idVendor;

__u16 idProduct;

/* …. */

__u8 bDeviceClass;

__u8 bDeviceSubClass;

__u8 bDeviceProtocol;

/* …. */

};

1)、idVendor和idProduct分别表示厂商ID和产品ID。

2)、bDeviceClass、bDeviceSubClass、bDeviceProtocol则基于设备的功能对其进行归类。

2、遥测卡驱动程序初始化及代码解析(代码清单11-2)

3、遥测卡探测和断开连接及代码解析(代码清单11-3)

三)、寄存器访问

1、当应用程序打开/dev/tele设备文件的时候,open()方法立刻初始化遥测卡的配置寄存器。

2、usb_ctrlrequest结构体

struct usb_ctrlrequest {

__u8 bRequestType;

__u8 bRequest;

__le16 wValue;

__le16 wIndex;

__le16 wLength;

}__attribute__((packed));

1)、bRequest域用来标识该控制请求。

2)、bRequestType表示数据传输方向、请求类别以及数据接收方是何种类型。

3)、wValue存放即将写到寄存器里的数据。

4)、wIndex是寄存器的偏移地址。

5)、wLength是传输数据的字节数。

3、初始化遥测卡配置寄存器及代码解析(代码清单11-4)

四)、数据传输

1、遥测卡的数据交换(代码清单11-5)

六、类驱动程序

一)、简介

1、USB规范引入了设备类的概念,根据每一类驱动程序的功能吧USB设备分为几大类标准的几大类包括:

1)、大容量存储类。

2)、网络类。

3)、集线器类。

4)、串行转换器类。

5)、音频类。

6)、视频类。

7)、图像类。

8)、调制解调器。

9)、打印机。

10)、HID(人机接口设备)。

每一大类的驱动程序对属于这类的所有设备通用,不需要另外开发和安装驱动程序就可以使用。

2、每个USB设备都有类代码和子类代码。设备驱动程序的usb_device_id结构体就包含类代码成员和子类代码成员。也可以从/proc/bus/usb/device的输出结果“I:”行看到设

备 的类代码和子类代码信息。

二)、大容量存储设备

1、通常来讲,USB大容量存储设备主要指USB硬盘、笔驱动器、CD-ROM、软驱以及类似的存储设备。USB大容量存储设备利用了SCSI(小型计算机系统接口)协议和主机

系统通信。(P237 图11-4)

2、SCSI子系统的结构分为3层:

1)、位于顶层的设备驱动程序。

2)、扫描总线,配置设备和将底层驱动程序相关联的中层驱动程序。

3)、底层SCSI适配器驱动程序。

3、大容量存储驱动程序把自己注册成一个虚拟的SCSI适配器。该虚拟适配器在上行方向上通过SCSI命令和上层通信,在下行方向上通过URB与块存储器交换数据。

4、让usbfs中也能显示设备结点。(代码清单11-6)

三)、USB-串行端口转换器

1、USB-串行端口转换器能把USB接口转换成串行端口。(P241 图11-5)

2、USB-串行端口转换器驱动程序与其他USB设备驱动程序相似,其除了利用了USN核心外,还利用了USB-Serial核心。

1)、USB-Serial核心提供的功能如下:

I、tty驱动程序把底层USB-串行端口转换器驱动程序和高层的串行端口层分开。

II、通用的probe()和disconnect()函数能被所有的USB-串行端口转换器驱动程序共用。

III、有了设备结点,从用户空间就能访问USB-串行端口转换器。应用程序通过/dev/tty/USBX设备结点就能操作USB-串行端口转换器。

2)、底层USB-串行端口驱动程序功能如下:

I、调用usb_serial_register()函数向USB-Seral核心注册usb_serial_driver结构体。usb_serial_driver结构体的入口点是驱动程序的核心。

II、初始化一个usb_driver结构体并调用usb_register()函数向USB核心注册。除了USB-串行端口转换器能利用USB-Seral核心提供的probe()和disconnect()函数外,其他的

过程和遥测卡的驱动程序很相似。

3、FTDI驱动程序代码片段。(代码清单11-7)

四)、人机接口设备

五)、蓝牙

七、gadget驱动程序

1、USB gadget驱动程序使嵌入式linux系统设备可以工作在USB设备模式。

2、USB gadget支持属于内核的一部分,包括以下几项内容:

1)、用于集成SoC的USB设备控制器的驱动程序。

2)、针对存储设备、网络设备和串行端口转换器使用的驱动程序。

3)、框架性驱动可以用来测试设备控制器驱动程序。

八、调试(略)

找回自我,歇够了,再飞回来,继续面对自己的人生。

《精通linux设备驱动程序开发》——USB

相关文章:

你感兴趣的文章:

标签云: