基于mt6750T,Android 7.0,kernel 3.18.35,本文主要简述了USB的枚举过程,主要是从host的角度来看。
一.USB的拓扑结构
简单来说,USB由host和device两部分组成,hub和function device统称为device,最多支持128个设备。host和root hub是紧密联系的。
二.USB设备的枚举过程
1.host和hub已经初始化完,device并未插入hub的port,此时device处于UNATTACHED状态。
2.host通过status change ep(属于Interrupt类型)对hub进行轮询,当设备插入port,hub的状态发生改变,此时hub向host返回状态变更信息,此时device处于ATTACHED状态。
3.host查询hub的状态变更并确认变更信息
4.host已经确认有device插入,等待至少100ms等待device插好并且port口power保持稳定,此时device处于POWERED状态。
5.host对hub的port进行reset操作,port开始使能。device进入DEFAULT状态并且能够从port获取不超过100mA的电流,此时device的所有register和state都进行复位。
6.host给device分配一个特殊的地址(地址0,的确很特殊啊),此时device处于ADDRESSED状态。
7.device被分配为地址0,可以通过默认的控制管道(ep0)对device进行操作。host获取device的设备描述符,确认ep0最大的数据包长度。
8.host获取device的配置信息(配置描述符,接口描述符和端点描述符),从0~n-1,n是device的配置数。然后选取configuration和interface进行配置。此时设备处于CONFIGURED状态。
三.USB的状态变更图
四.代码分析
以下代码分析从bus->host controller->hub->device的顺序进行分析,代码分析以流程为主,细节这里就不列出来了。
4.1 Bus
//usb/core/usb.c
static int __init usb_init(void)
{
......
//注册usb总线
retval= bus_register(&usb_bus_type);
......//注册hub driver并创建workqueue “usb_hub_wq”
retval=usb_hub_init();
......
//注册usb设备驱动usb_generic_driver
retval= usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
......
}
usb_bus_type的match函数。usb里面区分设备和接口的概念,接口对应功能,一个usb设备可能包含多个接口,比如我们的android手机属于usb设备,插入usb可以选择usb模式,MTP、PTP、ADB等等,这些模式对应接口的概念。
设备包含一个或多个配置
配置包含一个或多个接口
接口包含零个或多个端点
struct bus_type usb_bus_type ={
.name= "usb",
.match=usb_device_match,
.uevent=usb_uevent,
};
/*
* 将usb设备及设备驱动,usb接口及接口驱动区分对待
*/static int usb_device_match(struct device *dev, struct device_driver *drv)
{//属于usb设备?
if(is_usb_device(dev)) {//不是usb设备驱动则直接返回
if (!is_usb_device_driver(drv))return 0;
return 1;
//属于usb接口?
}else if(is_usb_interface(dev)) {struct usb_interface *intf;struct usb_driver *usb_drv;const struct usb_device_id *id;//为usb设备类型则直接返回
if(is_usb_device_driver(drv))return 0;
intf=to_usb_interface(dev);
usb_drv=to_usb_driver(drv);
//接口和driver的id_table进行匹配
id= usb_match_id(intf, usb_drv->id_table);if(id)return 1;
//动态匹配相关
id=usb_match_dynamic_id(intf, usb_drv);if(id)return 1;
}return 0;
}
usb_hub_init分析,hub_driver的函数等到hub这节再进行分析
int usb_hub_init(void)
{//注册hub驱动
if (usb_register(&hub_driver) < 0) {