1. USB host Controller驱动程序
* 处理USB状态,管理并报告状态信息
* 数据并/传转换
* 生成frame或者microframe
* 处理数据传输的请求
* 处理USB总线协议
* 进行差错检测和控制
* 处理电源管理请求, 把总线置为suspended状态以及响应wakeup事件
* 提供root hub功能, 让设备可以连接到主机控制器
2. USB请求块 - urb(USB request block)
* linux内核中通过urb来进行异步数据交换.
* 设备和多个端点之间可以使用同样或者不同的urb,端点可以处理一个urb队列.
* urb使用流程:
1) USB设备驱动创建一个urb
2) 设置urb, 将它关联到某个端点
3) 设备驱动程序将urb提交给usbcore
4) usbcore解析urb关联的设备,并把它发送到适当的USB主控器
5) 主控器按照urb内容,驱动总线设备完成传输,当传输完成时告知设备驱动
6) 发送urb的设备驱动或者usbcore也可以取消urb
* 控制请求(cr) --- 8个字节的数据包(参考USB规范)
1)请求类型: bit[1:0] 接受请求:设备/接口/端点/其他
bit[6:5] USB的类型:标准/类/产商/保留
bit[7] 请求方向(IN : 到主机)
2)请求
USB_REQ_GET_STATUS(00h) : 获取状态
A[ to device ]
* Bit[0] : 0总线供电, 1 自供电
* Bit[1] : 远程唤醒(0:不支持, 1:支持)
* Bit[15:2] : 保留
B[ to interface ]
* 全部保留,返回0
C[ to endpoint ]
* Bit[0] : Halt(0表示端点允许,1表示端点禁止)
* Bit[15:1] : 保留
USB_REQ_CLEAR_FEATURE(01h)
A[ to device ] : 清除设备的远程唤醒功能,并返回一个空包
B[ to endpoint ] : 解禁端点
USB_REQ_SET_FEATURE(03h)
A[ to device ] : 设置设备远程唤醒功能,并返回一个空包
B[ to endpoint ] : 禁止端点
USB_REQ_SET_ADDRESS(05h)
A[ to device ] : 设置设备地址
USB_REQ_GET_DESCRIPTOR(06h)
A[ to device ] : 获取设备描述符
协议版本,设备端点0的FIFO,以及设备ID号等.
B[ to configuration ] : 获取配置描述符
描述USB设备接口个数及是否有自供电能力等
C[ to interface ] : 获取接口描述符
描述端点0以外的物理端点个数等信息
D[ to endpoint ] : 获取端点描述符
描述端点的传输类型和最大信息包大小和端点传输方向
USB_REQ_SET_DESCRIPTOR(07h) : 可选,无法设置描述符
USB_REQ_GET_CONFIGURATION(08h) : 获取配置信息
USB_REQ_SET_CONFIGURATION(09h) : 设置配置信息
A[ to configuration ] : 设置配置描述符
B[ to interface ] : 设置接口描述符
C[ to endpoint ] : 设置端点描述符
USB_REQ_GET_INTERFACE(0Ah) : 获取接口信息
USB_REQ_SET_INTERFACE(0Bh) : 设置接口信息
USB_REQ_SYNCH_FRAME(0Ch) : 设备设置和报告一个端点的同步帧
US_BULK_GET_MAX_LUN(feh) : 获取max lun
3)值
4)接受请求设备/接口/端点的索引号
5)数据长度
* USB设备/管道/发送的包/发送的数据及长度/完成回调及回调数据
* 发送长度,错误次数,状态,
USB接口驱动结构体(usb_driver): 用来识别USB接口到usb核心.USB接口驱动必须提供名字,探测函数和断开函数,以及一个设备id表,其他是可选的.
@name : USB驱动唯一名称,通常与模块名称相同
@probe : 探测函数
@disconnect : 当接口不可访问时调用,由于设备断开或者模块卸载
@ioctl : 通过usbfs文件系统与用户空间交互
@suspend : 挂起操作
@resume : 恢复操作
@reset_resume : 设备挂起时复位
@pre_reset : 复位前调用
@post_reset : 复位后调用
@id_table : 驱动支持的USB设备id表
@dynids : 内部保存添加到驱动的设备id列表
@drvwrap : 驱动-模型核心结构体封装
@no_dynamic_id : 1表示USB核心不允许动态设备添加到驱动
@supports_autosuspend : 0表示USB核心不允许在驱动外边自动挂起接口
@soft_unbind : 1表示在调用驱动disconnect前不会杀掉URBs和禁用端点
USB设备驱动结构体(usb_device_driver) : 识别USB设备到USB核心.必须提供所有函数.
@name : USB驱动名称,通常与模块名相同
@probe : 探测函数
@disconnect : 断开连接,设备断开或者驱动卸载时调用
@suspend : 挂起
@resume : 恢复
@drvwarp : 设备-模型核心结构体封装
@supports_autosuspend : 0表示USB核心不允许在驱动外边自动挂起接口
USB主机接口结构体(usb_host_interface) : 表示USB接口的配置信息
@desc : 接口描述符(描述符类型,端点数量,接口编号/类型/子类/协议等)
@endpoint : 端点数组
@string : 接口描述串
@extra : 额外描述串
@extralen : 额外长度
USB主机端点结构体(usb_host_endpoint) : 表示端点的配置信息
@desc : 端点描述符(长度,描述符类型,端点地址/属性等)
@urb_list : urb请求列表
@hcpriv : 控制器私有数据
@ep_dev : 端点设备
@ss_ep_comp : SS设备
@extra : 额外描述
@extralen : 额外长度
@enabled : 使能
USB设备结构体(usb_device) :
@devnum : usb设备号
@devpath : 设备id串(在消息中使用)
@route :
设备描述符:
描述符的字节数大小
描述符类型编号
USB版本
USB设备类码
USB设备子类码
USB设备协议码
端点0的最大包大小
产商编号,产品号,设备出厂编号,产商字符串索引
产品字符串索引,系列号字符串索引
配置描述符的数量
配置描述符:
描述符的字节数大小,类型编号
此配置返回的所有数据大小
此配置支持的接口数量
配置命令所需的参数值
该配置描述符的字符串索引值
供电模式选择
设备从总线提取的最大电流
接口描述符
描述符字节数大小和类型编号
接口编号
备用接口描述符编号
该接口使用的端点数,不包括端点0
接口类型,子类型,协议
该接口的字符串索引
端点描述符:
属性(bit[1:0]) : 传输类型, 0-控制, 1-等时, 2-批量, 3-中断
端点地址(bit[7]) : 传输方向, 0-OUT, 1-IN(相对主机而言)
端点地址(bit[3:0]) : 端点号
间隔时间 : 中断端点的(两个中断的)间隔时间
端点收,发的最大包大小
USB数据构成:
* 二进制流构成域
1)同步域(SYNC) : 固定八位为:0000 0001, 用于本地时钟与输入同步
2)标识域(PID) : 由四位标识符+四位标识符反码构成, 表明包的类型和格式
3)地址域(ADDR) : 七位地址,代表设备在主机上的地址. 0地址是任何一个设备
第一次连接到主机时, 在被主机配置,枚举前的默认地址.
4)端点域(ENDP) : 四位端点地址
5)帧号域(FRAM) : 11位,每个帧都有一个特定的帧号,最大为0x800.
6)数据域(DATA) : 长度为0~1023字节
7)校验域(CRC) : 对令牌包和数据包中非PID域进行校验.
* 域构成包,有四种类型,分别为令牌包,数据包,握手包和特殊包.
1)令牌包可分为输入包,输出包,设置包和帧起始包.
输入/输出和设置包的格式为: SYNC + PID + ADDR + ENDP + CRC5
帧起始包格式: SYNC + PID + FRAM + CRC5
2)数据包,分为DATA0和DATA1包.当USB发送数据的时候,当一次发送的数据长度大于相应端点的容量时,就需要把数据包分为好几个包,分批发送,DATA0和DATA1包交替发送(同步传输时,所有的包都是DATA0).格式如下:
SYNC + PID + DATA + CRC16
3)握手包: SYNC + PID.
* 包构成事务,事务分为IN事务,OUT事务和SETUP事务三种,每一种事务都由令牌包,数据包,握手包构成.每个包的发送有一定的时间先后顺序,因此事务分为三个阶段:
1)令牌包阶段: 启动一个输入/输出/设置的事务
2)数据包阶段: 按输入/输出发送相应的数据
3)握手包阶段: 返回数据接收情况,在同步传输的IN和OUT事务中没有这个阶段.
@ IN事务:主机发送PID为IN的输入包给设备,设备会作出三种应答:
A.设备端点正常,设备往主机发送数据包(DATA0和DATA1交替)
B.设备忙,发送NAK无效包,IN事务提前结束.
C.相应设备的端点被禁止,发送错误包STALL包,事务提前结束.
主机正确接收到数据包之后就会向设备发送ACK包.
@ OUT事务:主机发送PID为OUT的输出包给设备,然后发送数据包,握手时设备反应:
A.设备端点正确接收, 设备往主机返回ACK,通知主机可以发送新的数据
B.设备忙,发送NAK无效包,通知主机再次发送数据
C.端点被禁止,发送STALL包,事务提前结束
@ SETUP事务:主机发送SETUP输出包,然后发送8字节的DATA0包(设备请求命令),设备接收到主机命令后返回ACK.
* 事务构成传输(中断/等时/批量/控制传输)
1)中断传输: 由OUT事务和IN事务构成,用于键盘,鼠标等HID设备的数据传输
2)批量传输: 由OUT事务和IN事务构成,用于大容量数据传输,没有固定的传输速率,也不占用带宽,当总线忙时,USB会优先进行其他类型的数据传输,而暂时停止批量传输
3)等时传输: 由OUT事务和IN事务构成,没有握手包,数据都是DATA0
4)控制传输: 由三个阶段构成(初始设置,可选数据,状态信息).每个阶段看成一个传输.控制传输其实由三个传输构成的,用来USB设备初次连接到主机之后,主机通过控制传输来交换信息,设备地址和读取设备的描述符,使得主机识别设备,并安装相应的驱动.
初始设备--- 由SET事务构成的传输
可选数据--- 由IN或OUT事务构成(可选,由SET事务发送的标准请求命令决定)
状态信息--- 由IN或OUT事务构成(A.传输方向相反 B.数据包长度为0)
USB枚举过程:
第一来回:
1)检测到设备,主机总线复位(是SIE根据总线状态通知用户的一种复位).
2)主机发SETUP包(0地址0端点),主机数据包(请求设备描述符),设备握手包ACK.
设备产生端点0数据中断,端点0输入缓冲区准备好设备描述符.
3)数据过程,主机先发一个IN令牌包,设备发一个数据包,主机发ACK包
SIE产生端点0数据输入中断,表明主机已取走设备的数据,用户中断程序处理.
4)状态过程,主机发OUT包,主机发0字节状态数据包(表明收到设备描述符),设备回ACK.
第二来回:
5)主机再次复位总线,进入地址设置控制传输阶段
6)主机SETUP包,主机数据包(请求设置地址),设备握手包ACK.
7)数据过程,本次没有数据传输
8)状态过程,主机发IN包,设备发0字节状态数据包(表明地址设置成功),主机发ACK包.
第三来回:
9)主机采用新地址发起第一个控制传输
10)主机发SETUP包(新地址),主机数据包(请求设备描述符),设备握手ACK包
11)数据过程,主机先发一个IN令牌包,设备发一个数据包,主机发ACK包.
数据量大时,重复执行
12)状态过程,主机发OUT包,主机发0字节状态数据包,设备回ACK包
获取配置描述符,配置集合,字符串描述符,报告描述符的过程差不多.