您的位置:首页 > 其它

USB core(三) - hub.c

2015-11-04 22:43 375 查看
core/hub.c文件中主要分为两块去理解:

一是hub_thread这个线程,当被唤醒后会调用hub_events

另外一个是root_hub经过与usb_device_driver匹配后添加的intf->dev,intf->dev与hub_driver匹配进入hub_probe函数。

hub_thread

hub_thread

static int hub_thread(void *__unused)
{
/* khubd needs to be freezable to avoid intefering with USB-PERSIST
* port handover.  Otherwise it might see that a full-speed device
* was gone before the EHCI controller had handed its port over to
* the companion full-speed controller.
*/
set_freezable();

do {
hub_events();
wait_event_freezable(khubd_wait,
!list_empty(&hub_event_list) ||
kthread_should_stop());
} while (!kthread_should_stop() || !list_empty(&hub_event_list));

pr_debug("%s: khubd exiting\n", usbcore_name);
return 0;
}


hub_thread这个线程平时都处于睡眠状态,通过wake_up(&khubd_wait)将线程唤醒执行hub_events函数

hub_events

static void hub_events(void)
{
while (1) {
spin_lock_irq(&hub_event_lock);

//如果hub_event_list链表为空,那么什么都不做
if (list_empty(&hub_event_list)) {
spin_unlock_irq(&hub_event_lock);
break;
}
tmp = hub_event_list.next;
list_del_init(tmp);

//根据event_list,获得struct usb_hub
hub = list_entry(tmp, struct usb_hub, event_list);
spin_unlock_irq(&hub_event_lock);

...
/* deal with port status changes */
for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {
//查看connect_change,wakeup_change,event_bits是否有变化,
//有才继续执行下去,否则查看下一个port

hub_port_status(hub, i, &portstatus, &portchange);
if (portchange & USB_PORT_STAT_C_CONNECTION) {
usb_clear_port_feature(hdev, i,
USB_PORT_FEAT_C_CONNECTION);
connect_change = 1;
}

if (portchange & USB_PORT_STAT_C_ENABLE)
...

if (connect_change)
hub_port_connect_change(hub, i, portstatus, portchange);
}
}


在hub_events中主要做的事是从hub_events_list中获取struct usb_hub,然后读取这个usb_hub port的portstatus和portchange,将portstatus和portchange传给hub_port_connect_change处理。

hub_port_connect_change

static void hub_port_connect_change(struct usb_hub *hub, int port1,
u16 portstatus, u16 portchange)
{
struct usb_device *udev;

hub_port_debounce_be_stable(hub, port1);

udev = usb_alloc_dev(hdev, hdev->bus, port1);

hub_port_init(hub, udev, port1, i);
hub_port_reset(hub, port1, udev, delay, false);
usb_control_msg(udev, usb_rcvaddr0pipe(), USB_REQ_GET_DESCRIPTOR...
hub_port_reset(hub, port1, udev, delay, false);
hub_set_address(udev, devnum);
usb_get_device_descriptor(udev, 8);

usb_new_device(udev);
usb_enumerate_device(udev);
usb_get_configuration(udev);
announce_device(udev);
device_add(&udev->dev);
}


hub_port_connect_change查看是否真有设备插入,如果有,则分配一个struct usb_device,然后获取这个usb_device的描述符等信息,最后添加这个usb_device,usb_device将会与usb_device_driver匹配进入generic_probe函数,之后添加intf->dev,与interface层面的usb driver匹配,进入xxx_probe函数。

hub_probe

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: