爱悠闲 > 二、usb子系统初始化

二、usb子系统初始化

分类: linux设备驱动  |  作者: orz415678659 相关  |  发布日期 : 2014-07-26  |  热度 : 8°

    在/drivers/usb/core/Usb.c中,subsys_initcall(usb_init)声明了usb子系统入口函数usb_init

static int __init usb_init(void)
{
	int retval;
	if (nousb) {
		pr_info("%s: USB support disabled\n", usbcore_name);
		return 0;
	}
	retval = usb_debugfs_init();	//1.usb debugfs初始化
	if (retval)
		goto out;
	retval = bus_register(&usb_bus_type);	//2.usb总线注册
	if (retval)
		goto bus_register_failed;
	retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb);	//3.usb总线通知链注册
	if (retval)
		goto bus_notifier_failed;
	retval = usb_major_init();	//4.注册usb主控器字符设备
	if (retval)
		goto major_init_failed;
	retval = usb_register(&usbfs_driver);	//5.注册usbfs驱动
	if (retval)
		goto driver_register_failed;
	retval = usb_devio_init();	//6.usb设备字符设备初始化
	if (retval)
		goto usb_devio_init_failed;
	retval = usbfs_init();	//7.usbfs初始化
	if (retval)
		goto fs_init_failed;
	retval = usb_hub_init();	//8.usb hub初始化
	if (retval)
		goto hub_init_failed;
	retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);	//9.usb注册同样设备驱动
	if (!retval)
		goto out;
	usb_hub_cleanup();
hub_init_failed:
	usbfs_cleanup();
fs_init_failed:
	usb_devio_cleanup();
usb_devio_init_failed:
	usb_deregister(&usbfs_driver);
driver_register_failed:
	usb_major_cleanup();
major_init_failed:
	bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
bus_notifier_failed:
	bus_unregister(&usb_bus_type);
bus_register_failed:
	usb_debugfs_cleanup();
out:
	return retval;
}

1.usb_debugfs_init --usb debugfs初始化

static int usb_debugfs_init(void)
{
	usb_debug_root = debugfs_create_dir("usb", NULL);	//创建"$(debugfs)/usb"
	if (!usb_debug_root)
		return -ENOENT;		
	usb_debug_devices = debugfs_create_file("devices", 0444,usb_debug_root, NULL,&usbfs_devices_fops);
	//创建"$(debugfs)/usb/device",捆绑usbfs_devices_fops结构体
	if (!usb_debug_devices) {	//若创建失败
		debugfs_remove(usb_debug_root);	//则必须把“$(debugfs)/usb”也删除掉
		usb_debug_root = NULL;
		return -ENOENT;
	}
	return 0;
}

要使用debugfs下面的usb功能,需要先挂着debugfs(mount -t debugfs none $(debugfs) ),具体初始化了啥调试接口,看下usbfs_devices_fops操作函数集
2.usb总线的注册

struct bus_type usb_bus_type = {
	.name =	"usb",	//总线名
	.match =	usb_device_match,	//匹配方法
	.uevent =	usb_uevent,	//事件处理
#ifdef CONFIG_USB_SUSPEND
	.pm =	&usb_bus_pm_ops,	//电源管理
#endif
};

这里总线的match方法是usb设备与usb驱动匹配的函数.

3.注册usb总线通知链

int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
{
	return blocking_notifier_chain_register(&bus->p->bus_notifier, nb);
}

当总线添加删除设备的时候会调用usb_bus_nb指定的notifier_cal方法,既usb_bus_notify

static int usb_bus_notify(struct notifier_block *nb, unsigned long action,void *data)
{
	struct device *dev = data;
	switch (action) {
	case BUS_NOTIFY_ADD_DEVICE:	//添加设备
		if (dev->type == &usb_device_type)	//usb设备
			(void) usb_create_sysfs_dev_files(to_usb_device(dev));
		else if (dev->type == &usb_if_device_type)	//usb接口
			(void) usb_create_sysfs_intf_files(to_usb_interface(dev));
		break;
	case BUS_NOTIFY_DEL_DEVICE:	//删除设备
		if (dev->type == &usb_device_type)	//usb设备
			usb_remove_sysfs_dev_files(to_usb_device(dev));
		else if (dev->type == &usb_if_device_type)	//usb接口
			usb_remove_sysfs_intf_files(to_usb_interface(dev));
		break;
	}
	return 0;
}

4.初始化usb主控器字符设备,USB_MAJOR=180

int usb_major_init(void)
{
	int error;
	error = register_chrdev(USB_MAJOR, "usb", &usb_fops);	//注册usb控制器字符设备,捆绑usb_fops
	if (error)
		printk(KERN_ERR "Unable to get major %d for usb devices\n",USB_MAJOR);
	return error;
}

捆绑usb_fops

static const struct file_operations usb_fops = {
	.owner =	THIS_MODULE,
	.open =	usb_open,
	.llseek =	noop_llseek,
};

5.注册usbfs_driver

struct usb_driver usbfs_driver = {
	.name =	"usbfs",
	.probe =	driver_probe,
	.disconnect = driver_disconnect,
	.suspend = driver_suspend,
	.resume =	driver_resume,
};

6.usb_devio_init     USB_DEVICE_DEV=189

int __init usb_devio_init(void)
{
	int retval;
	retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,"usb_device");	//分配设备号
	if (retval) {
		printk(KERN_ERR "Unable to register minors for usb_device\n");
		goto out;
	}
	cdev_init(&usb_device_cdev, &usbdev_file_operations);	//字符设备初始化
	retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);	//添加字符设备
	if (retval) {
		printk(KERN_ERR "Unable to get usb_device major %d\n",USB_DEVICE_MAJOR);
		goto error_cdev;
	}
#ifdef CONFIG_USB_DEVICE_CLASS
	usb_classdev_class = class_create(THIS_MODULE, "usb_device");	//创建"/sys/class/usb_device"
	if (IS_ERR(usb_classdev_class)) {
		printk(KERN_ERR "Unable to register usb_device class\n");
		retval = PTR_ERR(usb_classdev_class);
		cdev_del(&usb_device_cdev);	
		usb_classdev_class = NULL;
		goto out;
	}
	usb_classdev_class->dev_kobj = NULL;
#endif
	usb_register_notify(&usbdev_nb);	//注册设备通知链
out:
	return retval;
error_cdev:
	unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);
	goto out;
}

usb注册的通知链

void usb_register_notify(struct notifier_block *nb)
{
	blocking_notifier_chain_register(&usb_notifier_list, nb);
}

usb通知链表头为usb_notifier_list

在/drivers/usb/core/Notify.c文件中,有四个函数()对usb_notifier_list中发送通知,这四个函数如下:

usb_notify_add_device    //有设备添加
usb_notify_remove_device    //有设备移除
usb_notify_add_bus    //总线添加
usb_notify_remove_bus    //总线移除

当这些事件发生后会调用usbdev_nb指定的notifier_cal方法,既usbdev_notify

static int usbdev_notify(struct notifier_block *self,unsigned long action, void *dev)
{
	switch (action) {
	case USB_DEVICE_ADD:	//设备添加
		if (usb_classdev_add(dev))
			return NOTIFY_BAD;
		break;
	case USB_DEVICE_REMOVE:	//设备删除
		usb_classdev_remove(dev);
		usbdev_remove(dev);
		break;
	}
	return NOTIFY_OK;
}

7.usbfs初始化

int __init usbfs_init(void)
{
	int retval;
	retval = register_filesystem(&usb_fs_type);	//注册文件系统
	if (retval)
		return retval;
	usb_register_notify(&usbfs_nb);	//注册通知链
	usbdir = proc_mkdir("bus/usb", NULL);	//创建"/proc/bus/usb"
	return 0;
}

通知链回调函数

static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)
{
	switch (action) {
	case USB_DEVICE_ADD:	//设备添加
		usbfs_add_device(dev);
		break;
	case USB_DEVICE_REMOVE:	//设备移除
		usbfs_remove_device(dev);
		break;
	case USB_BUS_ADD:	//总线添加
		usbfs_add_bus(dev);
		break;
	case USB_BUS_REMOVE:	//总线移除
		usbfs_remove_bus(dev);
	}
	usbfs_update_special();
	usbfs_conn_disc_event();
	return NOTIFY_OK;
}

8.usb hub初始化

int usb_hub_init(void)
{
	if (usb_register(&hub_driver) < 0) {	//注册usb hub设备驱动
		printk(KERN_ERR "%s: can't register hub driver\n",usbcore_name);
		return -1;
	}
	khubd_task = kthread_run(hub_thread, NULL, "khubd");	//创建守护进程
	if (!IS_ERR(khubd_task))
		return 0;
	usb_deregister(&hub_driver);
	printk(KERN_ERR "%s: can't start khubd\n", usbcore_name);
	return -1;
}

hub也是usb设备,所以需要注册器设备驱动,创建hub_thread守护进程
捆绑的hub usb设备驱动

static struct usb_driver hub_driver = {
	.name = "hub",
	.probe =	hub_probe,	//hub连接上
	.disconnect = hub_disconnect,	//hub断开
	.suspend = hub_suspend,	//hub挂起
	.resume =	hub_resume,	//hub唤醒
	.reset_resume = hub_reset_resume,	//hub复位唤醒
	.pre_reset = hub_pre_reset,	
	.post_reset = hub_post_reset,
	.unlocked_ioctl = hub_ioctl,
	.id_table = hub_id_table,	//hub设备驱动 id表
	.supports_autosuspend = 1,
};

hub_thread守护进程

static int hub_thread(void *__unused)
{
	set_freezable();	//设置可冻结
	do {
		hub_events();	//hub事件处理函数
		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;
}

这里while循环是在hub_event_list不为空时候循环执行

当hub_events执行完,会执行wait_event_freezable进入睡眠,其他函数调用wake_up(&khubd_wait)唤醒队列
hub_events函数

static void hub_events(void)
{
	struct list_head *tmp;
	struct usb_device *hdev;
	struct usb_interface *intf;
	struct usb_hub *hub;
	struct device *hub_dev;
	u16 hubstatus;
	u16 hubchange;
	u16 portstatus;
	u16 portchange;
	int i, ret;
	int connect_change;

	while (1) {
		spin_lock_irq(&hub_event_lock);
		//第一次执行假设usb主控器还没注册
		if (list_empty(&hub_event_list)) {	//usb事件链表为空
			spin_unlock_irq(&hub_event_lock);
			break;	//跳出循环
		}
		tmp = hub_event_list.next;	
		list_del_init(tmp);
		hub = list_entry(tmp, struct usb_hub, event_list);	
		kref_get(&hub->kref);
		spin_unlock_irq(&hub_event_lock);
		hdev = hub->hdev;	
		hub_dev = hub->intfdev;	
		intf = to_usb_interface(hub_dev);
		usb_lock_device(hdev);
		if (unlikely(hub->disconnected))
			goto loop_disconnected;
		if (hdev->state == USB_STATE_NOTATTACHED) {
			hub->error = -ENODEV;
			hub_quiesce(hub, HUB_DISCONNECT);
			goto loop;
		}
		ret = usb_autopm_get_interface(intf);
		if (ret) {
			dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);
			goto loop;
		}
		if (hub->quiescing)
			goto loop_autopm;
		if (hub->error) {
			dev_dbg (hub_dev, "resetting for error %d\n",hub->error);
			ret = usb_reset_device(hdev);	
			if (ret) {
				dev_dbg (hub_dev,"error resetting hub: %d\n", ret);
				goto loop_autopm;
			}
			hub->nerrors = 0;
			hub->error = 0;
		}
		for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {
			if (test_bit(i, hub->busy_bits))
				continue;
			connect_change = test_bit(i, hub->change_bits);
			if (!test_and_clear_bit(i, hub->event_bits) &&!connect_change)
				continue;
			ret = hub_port_status(hub, i,&portstatus, &portchange);
			if (ret < 0)
				continue;
			if (portchange & USB_PORT_STAT_C_CONNECTION) {
				clear_port_feature(hdev, i,USB_PORT_FEAT_C_CONNECTION);
				connect_change = 1;
			}
			if (portchange & USB_PORT_STAT_C_ENABLE) {
				if (!connect_change)
					dev_dbg (hub_dev,"port %d enable change,status %08x\n",i, portstatus);
				clear_port_feature(hdev, i,USB_PORT_FEAT_C_ENABLE);
				if (!(portstatus & USB_PORT_STAT_ENABLE)&& !connect_change&& hdev->children[i-1]) {
					dev_err (hub_dev,"port %i disabled by hub (EMI?),re-enabling...\n",i);
					connect_change = 1;
				}
			}
			if (portchange & USB_PORT_STAT_C_SUSPEND) {
				struct usb_device *udev;
				clear_port_feature(hdev, i,USB_PORT_FEAT_C_SUSPEND);
				udev = hdev->children[i-1];
				if (udev) {
					msleep(10);
					usb_lock_device(udev);
					ret = usb_remote_wakeup(hdev->children[i-1]);
					usb_unlock_device(udev);
					if (ret < 0)
						connect_change = 1;
				} else {
					ret = -ENODEV;
					hub_port_disable(hub, i, 1);
				}
				dev_dbg (hub_dev,"resume on port %d, status %d\n",i, ret);
			}
			
			if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
				dev_err (hub_dev,"over-current change on port %d\n",i);
				clear_port_feature(hdev, i,USB_PORT_FEAT_C_OVER_CURRENT);
				hub_power_on(hub, true);
			}
			if (portchange & USB_PORT_STAT_C_RESET) {
				dev_dbg (hub_dev,"reset change on port %d\n",i);
				clear_port_feature(hdev, i,USB_PORT_FEAT_C_RESET);
			}

			if (connect_change)
				hub_port_connect_change(hub, i,portstatus, portchange);
		}
		if (test_and_clear_bit(0, hub->event_bits) == 0)
			;			
		else if (hub_hub_status(hub, &hubstatus, &hubchange) < 0)
			dev_err (hub_dev, "get_hub_status failed\n");
		else {
			if (hubchange & HUB_CHANGE_LOCAL_POWER) {
				dev_dbg (hub_dev, "power change\n");
				clear_hub_feature(hdev, C_HUB_LOCAL_POWER);
				if (hubstatus & HUB_STATUS_LOCAL_POWER)
					hub->limited_power = 1;
				else
					hub->limited_power = 0;
			}
			if (hubchange & HUB_CHANGE_OVERCURRENT) {
				dev_dbg (hub_dev, "overcurrent change\n");
				msleep(500);
				clear_hub_feature(hdev, C_HUB_OVER_CURRENT);
                        	hub_power_on(hub, true);
			}
		}
 loop_autopm:
		usb_autopm_put_interface_no_suspend(intf);
 loop:
		usb_autopm_put_interface(intf);
 loop_disconnected:
		usb_unlock_device(hdev);
		kref_put(&hub->kref, hub_release);
        }
}

9.usb注册通用设备驱动

int usb_register_device_driver(struct usb_device_driver *new_udriver,struct module *owner)
{
	int retval = 0;
	if (usb_disabled())
		return -ENODEV;
	new_udriver->drvwrap.for_devices = 1;	//usb设备
	new_udriver->drvwrap.driver.name = (char *) new_udriver->name;	//设备名
	new_udriver->drvwrap.driver.bus = &usb_bus_type;	//总线类型
	new_udriver->drvwrap.driver.probe = usb_probe_device;	//probe方法
	new_udriver->drvwrap.driver.remove = usb_unbind_device;	//remove方法
	new_udriver->drvwrap.driver.owner = owner;	//模块所有者
	retval = driver_register(&new_udriver->drvwrap.driver);	//注册设备驱动
	if (!retval) {
		pr_info("%s: registered new device driver %s\n",usbcore_name, new_udriver->name);
		usbfs_update_special();
	} else {
		printk(KERN_ERR "%s: error %d registering device driver %s\n",usbcore_name, retval, new_udriver->name);
	}
	return retval;
}

usb_device_driver结构体是usb_driver的简化版本,这里注册的是usb设备(非接口)驱动

usb总线的match方法对usb设备和usb接口做了区分处理,针对usb设备,直接match的,(分析match时候再细化)

然后调用usb设备驱动的probe方法

static int usb_probe_device(struct device *dev)
{
	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
	struct usb_device *udev = to_usb_device(dev);
	int error = 0;
	dev_dbg(dev, "%s\n", __func__);
	if (!udriver->supports_autosuspend)	//条件成立
		error = usb_autoresume_device(udev);
	if (!error)
		error = udriver->probe(udev);	//调用usb_device_driver的probe方法
	return error;
}

接着调用usb_generic_driver的probe方法

struct usb_device_driver usb_generic_driver = {
	.name =	"usb",
	.probe = generic_probe,
	.disconnect = generic_disconnect,
#ifdef	CONFIG_PM
	.suspend = generic_suspend,
	.resume = generic_resume,
#endif
	.supports_autosuspend = 1,
};

所以generic_probe函数会接着被调用

static int generic_probe(struct usb_device *udev)
{
	int err, c;
	if (usb_device_is_owned(udev))
		;
	else if (udev->authorized == 0)	//明显不执行
		dev_err(&udev->dev, "Device is not authorized for usage\n");
	else {	//
		c = usb_choose_configuration(udev);	//选择一个配置
		if (c >= 0) {
			err = usb_set_configuration(udev, c);	//设置一个配置
			if (err) {
				dev_err(&udev->dev, "can't set config #%d, error %d\n",c, err);
			}
		}
	}
	/* USB device state == configured ... usable */
	usb_notify_add_device(udev);	//发送设备添加通知
	return 0;
}


<---usb子系统相关结构体
--->usb主控器注册