现状 OK6410A linux-5.11
1个 roothub 上面接了2个 port , 无接其他设备
具体过程:
===========================
初始化第1.1阶段
ohci_hcd_s3c2410_probe
s3c_usb_phy_init
s3c2410_start_hc
开启时钟
调用 usb_add_hcd
注册 usb bus
hcd->driver->reset(hcd);
注册 中断
hcd->driver->start(hcd);
获取设备描述符
获取配置描述符
选择配置
get_hub_descriptor
hub_activate.1
hub_power_on
延时调用 第二阶段
===========================
初始化第1.2阶段
hub_init_func2
hub_activate.2
走init2和init3
kick_hub_wq->queue_work(hub_wq, &hub->events)
===========================
初始化第二阶段
hub_event
枚举 roothub 上的 所有port 上的设备(包括hub)
hub_suspend
===========================
初始化完成
===========================
运行时流程
host 定时问 hub 有没有中断?还是有没有port 改变(插入,拔出)事件(有的话调用hub_irq)
usb_hcd_irq
hcd->driver->irq
...
urb->complete(urb)
hub_irq
kick_hub_wq(hub);
hub_event
根据 changebit 对 hub 上的 改变事件对应的设备 进行枚举
usb_add_hcd(struct usb_hcd *hcd,unsigned int irqnum, unsigned long irqflags)
usb_register_bus(&hcd->self);
s3c2410-ohci: new USB bus registered, assigned bus number 1
hcd->driver->reset(hcd);
s3c2410-ohci: created debug files
usb_hcd_request_irqs(hcd, irqnum, irqflags);
s3c2410-ohci: irq 79, io mem 0x74300000
hcd->driver->start(hcd)
register_root_hub(hcd);
usb_set_device_state(usb_dev, USB_STATE_ADDRESS);
usb_get_device_descriptor
usb_new_device
usb_enumerate_device
usb_get_configuration
usb_get_descriptor
udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
[1] usb_get_langid:939: usb usb1: default language 0x0409
[1] usb_new_device:2554: usb usb1: udev 1, busnum 1, minor = 0
device_add(&udev->dev);
| [1] usb_probe_device:255: usb usb1: usb_probe_device
|
|
usb_generic_driver_probe
usb_choose_configuration
[1] usb_choose_configuration:187: usb usb1: configuration #1 chosen from 1 choice
usb_set_configuration
[1] usb_set_configuration:2181: usb usb1: adding 1-0:1.0 (config #1, interface 0)
device_add(&intf->dev);
|
| [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
hub_probe
hub 1-0:1.0: USB hub found
hub_configure
get_hub_descriptor(hdev, hub->descriptor);
[1] ohci_s3c2410_hub_control:194: s3c2410-ohci s3c2410-ohci: s3c2410_hub_control((ptrval),0xa006,0x2900,0x0000,(ptrval),000f)
hub 1-0:1.0: 2 ports detected
[1] hub_configure:1474: hub 1-0:1.0: standalone hub
[1] hub_configure:1486: hub 1-0:1.0: no power switching (usb 1.0)
[1] hub_configure:1495: hub 1-0:1.0: individual port over-current protection
[1] hub_configure:1570: hub 1-0:1.0: power on to power good time: 4ms
hub_hub_status(hub, &hubstatus, &hubchange);
[1] ohci_s3c2410_hub_control:194: s3c2410-ohci s3c2410-ohci: s3c2410_hub_control((ptrval),0xa000,0x0000,0x0000,(ptrval),0004)
[1] hub_configure:1628: hub 1-0:1.0: local power source is good
usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq, hub, endpoint->bInterval);
urb->complete = hub_irq;
hub_activate.1(hub, HUB_INIT);
走 type == HUB_INIT
hub_power_on
[1] hub_power_on:914: hub 1-0:1.0: trying to enable port power on non-switchable hub
set_port_feature
[1] ohci_s3c2410_hub_control:194: s3c2410-ohci s3c2410-ohci: s3c2410_hub_control((ptrval),0x2303,0x0008,0x0001,(ptrval),0000)
[1] ohci_s3c2410_hub_control:194: s3c2410-ohci s3c2410-ohci: s3c2410_hub_control((ptrval),0x2303,0x0008,0x0002,(ptrval),0000)
INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
queue_delayed_work(system_power_efficient_wq, &hub->init_work, msecs_to_jiffies(delay));
return;
hub_init_func2
hub_activate.2
走init2和init3
usb_control_msg
kick_hub_wq->queue_work(hub_wq, &hub->events)
hub_event
port_event
hub_port_connect_change
hub_port_connect
usb_new_device
device_add(&udev->dev);
usb_disconnect
device_del(&udev->dev);
hub_suspend
hub_event 的连锁反应
枚举过程的 control 信息的收发
usb_control_msg
有时候会调用 ohci_s3c2410_hub_control
有时候不调用 ohci_s3c2410_hub_control
USB 设备的初始化都是 Hub 这边发起的
只要你有 USB 主机控制器,就一定会有 Root Hub,
对于 Hub 来说,当你插入一个设备到 Hub 口里,就会触发一件事件。而第一件事件的发生其实是 Hub 驱动程序本身的初始化
hub的中断
hub_irq
hub的IN中断传输
usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq, hub, endpoint->bInterval);
这是hub准备的一个 int传输包,用于一次IN传输,让HOST定时访问hub
为什么 hub_probe之后要 kick event
因为要 hub 干活(枚举hub 所有port 上的设备)
hub_probe 设置了 该 hub的驱动 , 但是 该 hub 上可能接了设备,所以要处理一下
表现形式为 最后发了一个 消息
hub_event
port_event
hub_port_connect_change
hub_port_connect
usb_new_device
device_add(&udev->dev);
usb_disconnect
device_del(&udev->dev);
凡是真正的有端口变化事件发生,hub_irq 就会被调用,而 hub_irq()
最终会调用 kick_khubd(),触发 Hub 的 event_list,于是再次调用 hub_events()函数
我们曾经在 hub_configure 中讲过中断传输,当时调用了 usb_fill_int_urb()函数,并且把
hub_irq 作为一个参数传递了进去,最终把 urb->complete 赋值为 hub_irq。
然后,主机控制器会 定期询问 Hub,每当 Hub 端口上有一个设备插入或者拔除时,它就会向主机控制器打小报告。
具体来说,从硬件的角度看,就是 Hub 会向主机控制器返回一些信息,或者说 Data,这个 Data 被称作“Hub and Port Status Change Bitmap”,
而从软件角度来看,主机控制器的驱动程序接下 来会在处理好这个过程的 urb 之后,调用该 urb 的 complete 函数,
对于 Hub 来说,这个函数就 是 hub_irq()