您的位置:首页 > 其它

Usb 子系统初始化和驱动绑定流程

2015-03-04 11:30 281 查看
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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: