Usb子系统的入口函数在
kernel/drivers/usb/core/usb.c
static int __init usb_init(void)
{
//其实usb设备都连接到hub上面的;主要就是监控hub端口的状态变化;
retval = usb_hub_init(); //khubd监控线程就在这个函数里;监控hub接口的状态改变;
}
kernel_imx/drivers/usb/core/hub.c
int usb_hub_init(void)
{
//hub_thread(khubd)监控线程起来了,khubd线程就是监控usb端口状态的变化;;ps -aux | grep khubd 可以查看;
khubd_task = kthread_run(hub_thread, NULL, "khubd");
if (!IS_ERR(khubd_task))
return 0;
}
static int hub_thread(void *__unused)
{
do {
//最主要的就是録ub_events()函数;监控端口状态函数就在它里面;
hub_events();
} while (!kthread_should_stop() || !list_empty(&hub_event_list));
}
<pre name="code" class="cpp">static void hub_events(void)
{
<span style="white-space:pre"> </span>//usb_interface在usb驱动中很重要;
intf = to_usb_interface(hub_dev); <span style="white-space:pre"> </span>//从usb设备得到usb端口;
<span style="white-space:pre"> </span>if (connect_change){
<span style="white-space:pre"> </span>//这个函数是主要函数;
<span style="white-space:pre"> </span>hub_port_connect_change(hub, i, portstatus, portchange); //连接usb设备就会调用这个函数;
}
}
static void hub_port_connect_change(struct usb_hub *hub, int port1,
u16 portstatus, u16 portchange)
{
<span style="white-space:pre"> </span>/* reset (non-USB 3.0 devices) and get descriptor */
status = hub_port_init(hub, udev, port1, i);
<span style="white-space:pre"> </span>f (!status) {
//打印设备信息,添加设备到usb总线,获取设备描述符,绑定驱动在这个函数里;
status = usb_new_device(udev);
}
}
int usb_new_device(struct usb_device *udev)
{
<span style="white-space:pre"> </span>//枚举设备;即读取设备描述符;
err = usb_enumerate_device(udev); /* Read descriptors */
<span style="white-space:pre"> </span>announce_device(udev); <span style="white-space:pre"> </span>//打印新设备连接信息(vid/pid等)需要打开"make menuconfig -> Device drivers -> usb support -> usb verbose debug messages";
<span style="white-space:pre"> </span>err = device_add(&udev->dev); //注册usb设备;并会查找驱动链表绑定一个驱动;
}
<pre name="code" class="cpp" style="orphans: 2; widows: 2;">//kernel/drivers/base/core.c
int device_add(struct device *dev)
<span style="font-family: Tahoma; text-align: -webkit-auto;">{</span>
error = bus_add_device(dev); //把这个设备添加到usb总线;
bus_probe_device(dev); //为设备匹配一个驱动;}
<pre name="code" class="cpp" style="font-size:14px; orphans: 2; widows: 2;">//kernel/drivers/base/bus.c
void bus_probe_device(struct device *dev){struct bus_type *bus = dev->bus;int ret;if (bus && bus->p->drivers_autoprobe) {ret = device_attach(dev); //查找设备驱动;WARN_ON(ret < 0);}}
<pre name="code" class="cpp" style="font-size:14px; orphans: 2; widows: 2;">//kernel/drivers/base/db.c
int device_attach(struct device *dev){if (dev->driver) {//为usb设备查找匹配的驱动;if (klist_node_attached(&dev->p->knode_driver)) {ret = 1;goto out_unlock;}ret = device_bind_driver(dev); //usb设备和驱动绑定;if (ret == 0)ret = 1;else {dev->driver = NULL;ret = 0;}}
int device_bind_driver(struct device *dev)
{
int ret;
ret = driver_sysfs_add(dev);
if (!ret)
driver_bound(dev); //设备和驱动绑定;
return ret;
}
static void driver_bound(struct device *dev)
{
if (klist_node_attached(&dev->p->knode_driver)) {
printk(KERN_WARNING "%s: device %s already bound\n",
__func__, kobject_name(&dev->kobj));
return;
}
pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),
__func__, dev->driver->name);
klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_BOUND_DRIVER, dev);
}