一、层次结构
# app:
-------------------------------------------
USB设备驱动程序 // 解析usb设备通过usb总线传输过来的数据含义,或者发送特定含义的数据给usb设备
# 内核 --------------------------------------
USB总线驱动程序 // 1. 识别, 2. 找到匹配的设备驱动, 3. 提供USB读写函数 (不关心数据含义)
(drivers/usb/core/hub.c)
-------------------------------------------
USB主机控制器
UHCI OHCI EHCI XHCI
# 硬件 ---------------
USB设备
二. USB主机控制器驱动(HCD hub control drvier)初始化工作
// 一、hub初始化
usb_hub_init
// 1. hub drv注册
usb_register(&hub_driver)
hub_probe
hub_configure
//(1) urb alloc
hub->urb = usb_alloc_urb(0, GFP_KERNEL);
//(2)fill urb hub_irq urb完成处理函数 《☆ 1.2》
usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq,hub, endpoint->bInterval);
// (3) 提交urb
hub_activate
usb_submit_urb(hub->urb, GFP_NOIO);
// 2. 启动 “khubd” 线程
khubd_task = kthread_run(hub_thread, NULL, "khubd");
hub_thread
do {
hub_events(); // hub事件处理函数 《☆ 2.1》
// 等待唤醒事件
wait_event_freezable(khubd_wait,
!list_empty(&hub_event_list) ||
kthread_should_stop());
} while (!kthread_should_stop() || !list_empty(&hub_event_list));
//☆ 1.2 hub_irq urb完成处理函数(说明hub上有事件发生了)
hub_irq
kick_khubd(hub); // 踢一脚(唤醒)“khubd” 线程
usb_submit_urb (hub->urb, GFP_ATOMIC)); // 重新提交urb
----------
// ☆ 2.1 hub事件处理函数 hub_events
hub_events
port_event(hub, i); //检测那个port发生改变
if (connect_change)
hub_port_connect_change
hub_port_connect
udev = usb_alloc_dev(hdev, hdev->bus, port1);
dev->dev.bus = &usb_bus_type;
choose_address(udev); // 给新设备分配编号(地址)
hub_port_init // usb 1-1: new full speed USB device using s3c2410-ohci and address 3
hub_set_address // 把编号(地址)告诉USB设备
usb_get_device_descriptor(udev, 8); // 获取设备描述符长度
usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); // 获取所有设备描述符
usb_new_device(udev) // ☆ 解析设备的各种描述符信息,分配资源,并与相应的设备驱动程序建立联系。
usb_enumerate_device
usb_get_configuration(udev); // 把所有的描述符都读出来,并解析
usb_get_descriptor
usb_parse_configuration
device_add // 把device放入usb_bus_type的dev链表,
// 从usb_bus_type的driver链表里取出usb_driver,
// 把usb_interface和usb_driver的id_table比较
// 如果能匹配,调用usb_driver的probe
函数usb_new_device主要完成以下工作:
1.调用usb_set_address把新分配的设备地址传送给设备。
2.调用usb_get_descriptor获得设备的设备描述符,得到设备端点的包的最大长度,接下来的控制传输按这个数据包最大长度进行。
3.调用usb_get_configuration得到设备的所有配置描述符、接口描述符和端点描述符信息。
4.调用usb_set_configuration激活当前的配置作为默认工作配置。
5.在目录“proc/bus/usb”中为设备创建节点。
6.在USB子系统中,通过函数usb_find_drivers和usb_find_interface_driver,为设备的每一个接口寻找相应的驱动程序,驱动程序对接口进行配置并为它们分配所需的资源。当每个接口被成功驱动后,此设备就能正常工作了。