1. 启动过程分析
a. 入口
a.1 在usb模块的启动函数中usb_init调用了usb_hub_init
a.2 usb_hub_init向usb_core注册了hub_driver
a.3 并启动线程hub_thread
b. hub_thread
b.1 线程hub_thread 会卡在等侍消息上,
b.2 当有u盘插入时,触发中断hub_irq并通过kick_khubd(hub)将消息插入到队列中,
b.3 这时hub_thread就会被激活,进入处理函数hub_events中
c. hub_events
a. usb_husb向device发送get_status命令,此时portchange是STAT_C_CONNECTION
设标志位connect_change=1,进入hub_port_connect_change处理
b. hub_port_connect_change的处理
b.1 hub_port_debounce-->判断usb口是否真正有设备接入
类似于去抖: 每隔100ms查询usb口的状态,执行三次如果都是CONNECTION,说明hub上有usb设备接入了
b.2 choose_address --> 为usb设备选一个地址
b.3 hub_port_init --> hub_port_reset后获取dev_descriptor
b.4 判断descriptor中类型,若不为hub,则说明是usb_device,就usb_new_device
c. usb_new_device的处理
c.1 usb_detect_quirks, 判断是不是黑名单的usb设备
c.2 usb_configure_device
c.2.1 usb_get_configuration,先获取一次descriptor(主要是为了获取整个descriptor的长度),知道长度之后获取完整的descriptor
然后调用usb_parse_configuration,解析配置描述符和接口描述符
c.2.2 usb_cache_string获取product manufactor与serial并储存在缓存中
c.3 device_add历级一系列的调用最终会调到probe函数usb_probe_interface
2.总结
2.1 当有一个u盘插入到hub时,其调用关系如下:
hub_thread() -> hub_events() -> hub_port_connect_change() ->usb_new_device() -> device_add()
2.2 device_add的过程
device_add() -> bus_probe_device() -> device_attach() -> __device_attach() -> driver_probe_device() -> really_probe()--> usb_probe_interface
为什么device_add之后会调用storage_probe呢? 这个地方还没有看懂,只是通过打印信息发现是在really_probe中,
调用了usb_probe_interface
--> struct usb_driver *driver = to_usb_driver(dev->driver);
--> error = driver->probe(intf, id);
这个driver->probe就是storage_probe,应该是在really_probe中把driver赋值的,但具体是根据什么赋值的还没有搞明白。
usb_match_id分析:
1.预先写好usb设备列表:
-
./drivers/usb/storage/usual-tables.c
-
struct usb_device_id usb_storage_usb_ids[] = {
-
# include "unusual_devs.h"
-
{ } /* Terminating entry */
-
};
-
分为两种:
-
/work/tq/kernel/drivers/usb/storage/unusual_devs.h
-
a. 特殊的设备用PID与VID匹配
-
/* Reported by Alessio Treglia <quadrispro@ubuntu.com> */
-
UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001,
-
"TGE",
-
"Digital MP3 Audio Player",
-
US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
-
b.普通的设备,直接跳过PID与VID匹配,只看其class类型
-
USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0),
2. usb_match_id过程
a. for循环遍历usb设备列表中的每一项,调用usb_match_one_id进行匹配
a.1 usb_match_one_id先调用usb_match_device匹配特殊的设备
a.2 若为普通设备,则不关心PID与VID,只检查class sub_class protocol,若匹配说明是普通设备
阅读(2174) | 评论(0) | 转发(0) |