这里主要收集了一些USB关于OTG、device、host相关的知识。
当设备检测到USB_ID信号为低时,表该设备应作为Host(主机,也称A设备)用。
当设备检测到USB_ID信号为高时,表示该设备作为Slave(外设,也称B设备)用。
因此,在主机侧的层次结构中,要实现的 USB 驱动包括两类:
USB 主机控制器驱动和 USB 设备驱动,前者控制插入其中的 USB 设备,后者控制USB 设备如何与主机通信。
在这棵树里,我们把树根比作主机控制器,树叶比作具体的 USB设备,树干和树枝就是 USB 总线。
树叶本身与树枝通过 usb_driver 连接,而树叶本身的驱动(读写、控制)则需要通过其树叶设备本身所属类设备驱动来完成。树根和树叶之间的“通信”依靠在树干和树枝里“流淌”的 URB 来完成。
由此可见,usb_driver 本身只是起到了找到 USB 设备、管理 USB 设备连接和断开的作用
OTG 检测的原理是:
USB OTG标准在完全兼容USB2.0标准的基础上,增添了电源管理(节省功耗)功能,它允许设备既可作为主机,也可作为外设操作(两用OTG)。USB OTG技术可实现没有主机时设备与设备之间的数据传输。例如:数码相机可以直接与打印机连接并打印照片,手机与手机之间可以直接传送数据等,从而拓展了USB技术的应用范围。在OTG中,初始主机设备称为A设备,外设称为B设备。也就是说,手机既可以做外设,又可以做主机来传送数据,可用电缆的连接方式来决定初始角色(由ID线的状态来决定)。
USB OTG接口中有5条线:
2条用来传送数据(D+ 、D-);
1条是电源线(VBUS);
1条则是接地线(GND)、
1条是ID线。ID线---以用于识别不同的电缆端点,mini-A插头(即A外设)中的ID引脚接地,mini-B插头(即B外设)中的ID引脚浮空。当OTG设备检测到接地的ID引脚时,表示默认的是A设备(主机),而检测到ID引脚浮空的设备则认为是B设备(外设)。
只有而言支持USB OTG的设备(即可以做USB Host有可以做Slave的设备),USB_ID信号才有意义。
当设备检测到USB_ID信号为低时,表该设备应作为Host(主机,也称A设备)用。
当设备检测到USB_ID信号为高时,表示该设备作为Slave(外设,也称B设备)用。
实际的USB连接线中,是没有USB_ID这根线的。 都是在接口部分直接拉死的的。
对于Host端,只需将连接线的USB_ID pin和地短接即可,
对于Slave端,USB连接线的USB_ID pin是悬空的。(设备内部上拉)。。
USB驱动程序框架
Linux内核提供了完整的USB驱动程序框架。USB总线采用树形结构,在一条总线上只能有唯一的主机设备。Linux内核从主机和设备两个角度观察USB总线结构。本节介绍Linux内核USB驱动程序框架。
25.2.1 Linux内核USB驱动框架
图25-2是Linux内核从主机和设备两个角度观察USB总线结构的示意图。
从图25-2中可以看出,Linux内核USB驱动是按照主机驱动和设备驱动两套体系实现的,下面介绍两套体系的结构和特点。
1.基本结构
图25-2的左侧是主机驱动结构。主机驱动的最底层是USB主机控制器,提供了OHCI/EHCI/UHCI这3种类型的总线控制功能。在USB控制器的上一层是主机控制器的驱动,分别对应OHCI/EHCI/UHCI这3种类型的总线接口。USB核心部分连接了USB控制器驱动和设备驱动,是两者之间的转换接口。USB设备驱动层提供了各种设备的驱动程序。
USB主机部分的设计结构完全是从USB总线特点出发的。在USB总线上可以连接各种不同类型的设备,包括字符设备、块设备和网络设备。所有类型的USB设备都是用相同的电气接口,使用的传输协议也基本相同。向用户提供某种特定类型的USB设备时,需要处理USB总线协议。内核完成所有的USB总线协议处理,并且向用户提供编程接口。
(点击查看大图)图25-2 Linux内核USB总线结构 |
图25-2右侧是设备驱动结构。与USB主机类似,USB设备提供了相同的层次结构与之对应。但是在USB设备一侧使用名为Gadget API的结构作为核心。Gadget API是Linux内核实现的对应USB设备的核心结构。Gadget API屏蔽了USB设备控制器的细节,控制具体的USB设备实现。
2.设备
每个USB设备提供了不同级别的配置信息。一个USB设备可以包含一个或多个配置,不同的配置使设备表现出不同的特点。其中,设备的配置是通过接口组成的。Linux内核定义了USB设备描述结构如下:
- struct usb_device_descriptor {
- __u8 bLength; // 设备描述符长度
- __u8 bDescriptorType; // 设备类型
- __le16 bcdUSB; // USB版本号(使用BCD编码)
- __u8 bDeviceClass; // USB设备类型
- __u8 bDeviceSubClass; // USB设备子类型
- __u8 bDeviceProtocol; // USB设备协议号
- __u8 bMaxPacketSize0; // 传输数据的最大包长
- __le16 idVendor; // 厂商编号
- __le16 idProduct; // 产品编号
- __le16 bcdDevice; // 设备出厂号
- __u8 iManufacturer; // 厂商字符串索引
- __u8 iProduct; // 产品字符串索引
- __u8 iSerialNumber; // 产品***索引
- __u8 bNumConfigurations; // 最大的配置数量
- } __attribute__ ((packed));
从usb_device_descriptor结构定义看出,一个设备描述符定义了与USB设备有关的所有信息。
3.接口
在USB体系中,接口是由多个端点组成的。一个接口代表一个基本的功能,是USB设备驱动程序控制的对象。一个USB设备最少有一个接口,功能复杂的USB设备可以有多个接口。接口描述定义如下:
- struct usb_interface_descriptor {
- __u8 bLength; // 描述符长度
- __u8 bDescriptorType; // 描述符类型
- __u8 bInterfaceNumber; // 接口编号
- __u8 bAlternateSetting; // 备用接口编号
- __u8 bNumEndpoints; // 端点数量
- __u8 bInterfaceClass; // 接口类型
- __u8 bInterfaceSubClass; // 接口子类型
- __u8 bInterfaceProtocol; // 接口使用的协议
- __u8 iInterface; // 接口索引字符串数值
- } __attribute__ ((packed));
4.端点
端点是USB总线通信的基本形式,每个USB设备接口可以认为是端点的集合。主机只能通过端点与设备通信。USB体系结构规定每个端点都有一个唯一的地址,由设备地址和端点号决定端点地址。端点还包括了与主机通信用到的属性,如传输方式、总线访问频率、带宽和端点号等。端点的通信是单向的,通过端点传输的数据只能是从主机到设备或者从设备到主机。端点定义描述如下:
- struct usb_endpoint_descriptor {
- __u8 bLength; // 描述符长度
- __u8 bDescriptorType; // 描述符类型
- __u8 bEndpointAddress; // 端点地址
- __u8 bmAttributes; // 端点属性
- __le16 wMaxPacketSize; // 端点接收的最大数据包长度
- __u8 bInterval; // 轮询端点的时间间隔
- /* NOTE: these two are _only_ in audio endpoints. */
- /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
- __u8 bRefresh;
- __u8 bSynchAddress;
- } __attribute__ ((packed));
5.配置
配置是一个接口的集合。Linux内核配置的定义如下:
- struct usb_config_descriptor {
- __u8 bLength; // 描述符长度
- __u8 bDescriptorType; // 描述符类型
- __le16 wTotalLength; // 配置返回数据长度
- __u8 bNumInterfaces; // 最大接口数
- __u8 bConfigurationValue; // 配置参数值
- __u8 iConfiguration; // 配置描述字符串索引
- __u8 bmAttributes; // 供电模式
- __u8 bMaxPower; // 接口的最大电流
- } __attribute__ ((packed));
配置描述符结构定义了配置的基本属性和接口数量等信息。