USB mouse 枚举过程 在 linux 上的代码分析1 讲述了 usb1.0枚举过程 中的 1-4
本篇文章要讲述 usb1.0枚举过程 中的 5-8
// 关键看 hub_event 是什么时候发生的 TODO
什么时候 什么条件 kick_hub
什么时候 hub_event
- 可能的流程1
hub_probe
INIT_WORK(&hub->events, hub_event);
vic_handle_irq
...
usb_hcd_irq
...
hub_irq
kick_hub_wq(hub);
queue_work(hub_wq, &hub->events);
- 可能的流程1
ohci_irq
usb_hcd_poll_rh_status
hcd->driver->hub_status_data // 即ohci_s3c2410_hub_status_data
ohci_hub_status_data
ohci_root_hub_state_changes
usb_hcd_resume_root_hub
queue_work(pm_wq, &hcd->wakeup_work); // 对应 hcd_resume_work
kthread->worker_thread->process_one_work // 工作队列 的运行时机 在 worker_thread 内核线程 被调度时
hcd_resume_work
usb_remote_wakeup
[26] usb_remote_wakeup:3646: usb usb1: usb wakeup-resume
usb_autoresume_device
__pm_runtime_resume->rpm_resume->rpm_callback->__rpm_callback->usb_resume_both
usb_resume_device
usb_generic_driver_resume
hcd_bus_resume
[26] hcd_bus_resume:2182: usb usb1: usb auto-resume
ohci_bus_resume
ohci_rh_resume
[26] ohci_rh_resume:184: s3c2410-ohci s3c2410-ohci: wakeup root hub
usb_hcd_poll_rh_status
usb_resume_interface
driver->resume/ 即 hub_resume
[26] hub_resume:3807: hub 1-0:1.0: hub_resume
hub_activate
kick_hub_wq
- 流程2
kthread
worker_thread
process_one_work
hub_event
port_event
hub_port_connect_change
hub_port_connect
udev = usb_alloc_dev
usb_set_device_state(udev, USB_STATE_POWERED);
choose_devnum(udev); // 原来是 choose_address
status = hub_port_init(hub, udev, port1, i);
hub_port_reset(hub, port1, udev, delay, false); ----------------------- 波形1
// 之后开启 了 1ms 一次的 keep-alive
usb_control_msg(udev, usb_rcvaddr0pipe(), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, USB_DT_DEVICE << 8, 0, buf, GET_DESCRIPTOR_BUFSIZE, initial_descriptor_timeout); ----------------------- 波形2
hub_port_reset(hub, port1, udev, delay, false); ----------------------- 波形3 , 和 波形1 一样
hub_set_address(udev, devnum); ----------------------- 波形4
usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); ----------------------- 波形5
usb_new_device
usb_enumerate_device
usb_get_configuration
usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, desc, USB_DT_CONFIG_SIZE);----------------------- 波形6
usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);----------------------- 波形7
usb_parse_configuration
usb_parse_interface
[26] usb_parse_interface:554: usb 1-1: skipped 1 descriptor after interface
udev->product = usb_cache_string(udev, udev->descriptor.iProduct);----------------------- 波形8
udev->manufacturer = usb_cache_string(udev, udev->descriptor.iManufacturer);----------------------- 波形9
udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);----------------------- 波形10
[26] usb_get_langid:939: usb 1-1: default language 0x0409
[26] usb_new_device:2529: usb 1-1: udev 2, busnum 1, minor = 1
device_add
| [1] usb_probe_device:255: usb usb1: usb_probe_device
|
|
usb_generic_driver_probe // USB设备driver
usb_choose_configuration
[1] usb_choose_configuration:187: usb usb1: configuration #1 chosen from 1 choice
usb_set_configuration ----------------------- 波形11
[1] usb_set_configuration:2181: usb usb1: adding 1-0:1.0 (config #1, interface 0)
device_add(&intf->dev); // 注册 USB接口device // 为usbhid接口
|
| [1] usb_probe_interface:327: hub 1-0:1.0: usb_probe_interface
| [1] usb_probe_interface:349: hub 1-0:1.0: usb_probe_interface - got id
usbhid_probe // USB接口driver
hid->ll_driver = &usb_hid_driver;
hid_add_device(hid);
hdev->ll_driver->parse(hdev); // 即 usbhid_parse
hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
usb_control_msg(dev, usb_sndctrlpipe(dev, 0),HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report,ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT);
----------------------- 波形12
参考hid1_11.pdf 7.2 Class-Specific Requests
hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize);
usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,(type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT);
----------------------- 波形13
参考hid1_11.pdf 7.1.1 Get_Descriptor Request
GET_DESCRIPTOR , Descriptor Type : Report , Length : 64
之后流程的参考
按时间发生的参考波形
-
周期性波形
-
波形1 : port init 后的 port reset
-
波形2 : 对设备的标准请求:获取 设备描述符 长度为64
-
波形3 : port reset
-
波形4 : 对设备的标准请求:set address ,设置地址为14
hub_set_address调用过程中发生了两个中断
其中 usb_control_msg 有一个
另外一个 是 什么引起的呢??
下图set_address 为 usb_control_msg 的调用过程
下图set_address 为 hub_set_address 的调用过程
-
波形5 : 对设备的标准请求:获取 设备描述符 长度为18
-
波形6 : 对设备的标准请求:获取 配置描述符 长度为9
-
波形7 : 对设备的标准请求:获取 配置描述符 长度为34
-
波形8 : 对设备的标准请求:获取 字符串描述符 长度为255
-
波形9 : 对设备的标准请求:获取 字符串描述符(index:2,语言ID为0x0409) 长度为255
-
波形10 : 对设备的标准请求:获取 字符串描述符(index:1,语言ID为0x0409) 长度为255
-
波形11 : 对设备的标准请求:设置配置(配置值为1)
-
波形12 : 对接口的类请求 ,bRequest 为 10,为SET_IDLE
-
波形13 : 对接口的HID Class请求:获取Report描述符