usbcore-y 这个 obj-y 的区别?

usbcore 这个模块代表的不是某一个设备,而是所有 USB 设备赖以生存的模块,它就是 USB 子系统。
一、拓扑结构

- 之所以要规定这个树形拓扑结构是为了避免环形连接;
- 一条 USB 总线有且只有一个 USBHost,对应一个 RootHub
- USB 设备分为两类,Hub 和 Functions,Hub 通过端口 Port 连接更多 USB 设备,Functions 即 USB 外接从设备
- 层次最多 7 层,且第 7 层不能有 Hub,只能有 functions。
- CompoundDevice-一个 Hub 上接多个设备组成一个小设备。
- CompositeDevice-一个 USB 外接设备具有多个复用功能。
二、USB 子系统的初始化
USBcore 源码位于 ./drivers/usb/core,其中的 Makefile 摘要如下,

在 ./drivers/usb/core/usb.c 里实现了初始化,源代码如下:
- bus
- device_driver
- device
static int __init usb_init(void)
{
retval = usb_debugfs_init(); //1.usb debugfs初始化
if (retval)
goto out;
retval = bus_register(&usb_bus_type); //注册USB总线,也就是USB子系统
if (retval)
goto bus_register_failed;
retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb); //注册内核通知链,用于设备和接口注册的通知
if (retval)
goto bus_notifier_failed;
retval = usb_major_init(); //usb主设备号初始化
if (retval)
goto major_init_failed;
retval = usb_register(&usbfs_driver); //注册usb文件系统
if (retval)
goto driver_register_failed;
retval = usb_devio_init(); //usb设备字符设备初始化
if (retval)
goto usb_devio_init_failed;
retval = usb_hub_init(); //usb hub初始化
if (retval)
goto hub_init_failed;
retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE); //注册一个USB设备(不是接口)驱动程序
if (!retval)
goto out;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
usbcore 注册了 USB 总线,USB 文件系统,USBHub 以及 USB 的设备驱动 usb generic driver 等。
三、usb debugfs 初始化

static int usb_debugfs_init(void)
{
usb_debug_root = debugfs_create_dir("usb", NULL); //创建"$(debugfs)/usb"
if (!usb_debug_root)
return -ENOENT;
//创建"$(debugfs)/usb/device",捆绑usbfs_devices_fops结构体,位置 /sys/kernel/debug/usb/device,打印所有总线下的设备
usb_debug_devices = debugfs_create_file("devices", 0444,usb_debug_root, NULL,&usbfs_devices_fops);
}2
3
4
5
6
7
8
四、usb 总线的注册
struct bus_type usb_bus_type = {
.name = "usb", //总线名
.match = usb_device_match, //匹配方法,应该用于usb驱动id_table的匹配
.uevent = usb_uevent, //事件处理
};2
3
4
5
static int usb_device_match(struct device *dev, struct device_driver *drv)
{
/* devices and interfaces are handled separately */
if (is_usb_device(dev)) {
/* interface drivers never match devices */
if (!is_usb_device_driver(drv))
return 0;
/* TODO: Add real matching code */
return 1;
} else if (is_usb_interface(dev)) {
struct usb_interface *intf;
struct usb_driver *usb_drv;
const struct usb_device_id *id;
/* device drivers never match interfaces */
if (is_usb_device_driver(drv))
return 0;
intf = to_usb_interface(dev);
usb_drv = to_usb_driver(drv);
id = usb_match_id(intf, usb_drv->id_table);
if (id)
return 1;
id = usb_match_dynamic_id(intf, usb_drv);
if (id)
return 1;
}
return 0;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
usb_match_id
const struct usb_device_id *usb_match_id(struct usb_interface *interface,
const struct usb_device_id *id)
{
/* proc_connectinfo in devio.c may call us with id == NULL. */
if (id == NULL)
return NULL;
/* It is important to check that id->driver_info is nonzero,
since an entry that is all zeroes except for a nonzero
id->driver_info is the way to create an entry that
indicates that the driver want to examine every
device and interface. */
for (; id->idVendor || id->idProduct || id->bDeviceClass ||
id->bInterfaceClass || id->driver_info; id++) {
if (usb_match_one_id(interface, id))
return id;
}
return NULL;
}
EXPORT_SYMBOL_GPL(usb_match_id);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
五、注册 usb 总线通知链
int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
{
return blocking_notifier_chain_register(&bus->p->bus_notifier, nb);
}2
3
4
当总线添加删除设备的时候会调用 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)); //生成sysfs节点/sys/devices/platform/soc@0/38100000.usb/xhci-hcd.0.auto/usb1
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;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
六、初始化 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;
}2
3
4
5
6
7
8
捆绑 usb_fops
static const struct file_operations usb_fops = {
.owner = THIS_MODULE,
.open = usb_open,
.llseek = noop_llseek,
};2
3
4
5
七、注册 usbfs_driver
usb_register(&usbfs_driver); //通过 usb_register() 将 usbfs 驱动提交个设备模型,添加到 USB 总线的驱动链表里。
/* use a define to avoid include chaining to get THIS_MODULE & friends */
//其实是调用usb_register_driver,注册一个usb接口驱动
#define usb_register(driver) \
usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)2
3
4
struct usb_driver usbfs_driver = {
.name = "usbfs", //在/sys/bus/usb/drivers/usbfs
.probe = driver_probe,
.disconnect = driver_disconnect,
.suspend = driver_suspend,
.resume = driver_resume,
};2
3
4
5
6
7
八、usb_devio_init USB_DEVICE_DEV=189
//用于应用程序直接访问 usb 设备
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;
}
usb_register_notify(&usbdev_nb); //注册设备通知链
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
usb 注册的通知链
void usb_register_notify(struct notifier_block *nb)
{
blocking_notifier_chain_register(&usb_notifier_list, nb);
}2
3
4
sb 通知链表头为 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:
break;
case USB_DEVICE_REMOVE:
usbdev_remove(dev);
break;
}
return NOTIFY_OK;
}2
3
4
5
6
7
8
9
10
11
12
八、usb hub 初始化
后续详细分析
九、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;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
}2
3
4
5
6
7
8
9
10
11
12
接着调用 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,
};2
3
4
5
6
7
8
9
10
对应到 root hub,流程会转入到 generic_probe() 代码如下:
static int generic_probe(struct usb_device *udev)
{
/* Choose and set the configuration. This registers the interfaces
* with the driver core and lets interface drivers bind to them.
*/
if (udev->authorized == 0) //至于udev->authorized,在root hub的初始化中,是会将其初始化为1的.后面的逻辑就更简单了.为root hub 选择一个配置然后再设定这个配置.
dev_err(&udev->dev, "Device is not authorized for usage\n");
else {
c = usb_choose_configuration(udev); //Usb2.0 spec上规定,对于hub设备,只能有一个config,一个interface,一个endpoint.实际上,在这里,对hub的选择约束不大,反正就一个配置,不管怎么样,选择和设定都是这个配置.
if (c >= 0) {
err = usb_set_configuration(udev, c);
if (err && err != -ENODEV) {
dev_err(&udev->dev, "can't set config #%d, error %d\n",
c, err);
/* This need not be fatal. The user can try to
* set other configurations. */
}
}
}
/* USB device state == configured ... usable */
usb_notify_add_device(udev);
return 0;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23