关键词:linux、驱动、usb、usb core
USB Core负责实现一些核心的功能,为别的设备驱动程序提供服务,提供一个用于访问和控制USB硬件的接口,而不用去考虑系统当前存在哪种主机控制器。至于USB Core、USB主机控制器和USB设备驱动三者之间的关系,如图7所示。
主机控制器的驱动(HCD)必须位于USB软件的最下一层。HCD提供主机控制器硬件的抽象,隐藏硬件的细节,在主机控制器之下是物理的USB及所有与之连接的USB设备。而HCD只有一个客户,对一个人负责,就是咱们的USB Core,USB Core将用户的请求映射到相关的HCD,用户不能直接访问HCD。
写USB驱动时,只能调用core的接口,core会将咱们的请求发送给相应的HCD,core为咱们完成了大部分的工作。
usb core 驱动linux-rk3128\drivers\usb\core\usb.c 主要注册USB总线 struct bus_type usb_bus_type,对应目录 /sys/bus/usb,同时创建 调试目录/sys/kernel/debug/usb,以及调用 usb_hub_init() 注册 usb hub 驱动:
subsys_initcall(usb_init);
static int __init usb_init(void)->
usb_init_pool_max();
retval = usb_debugfs_init()->
/*
以 rk3128 为例,
root@mxlos:/sys/kernel/debug/usb# ls
devices ohci usbmon uvcvideo
*/
struct dentry *usb_debug_root = debugfs_create_dir("usb", NULL);// 创建调试目录/sys/kernel/debug/usb
struct dentry *usb_debug_devices = debugfs_create_file("devices", 0444, usb_debug_root, NULL,&usbfs_devices_fops);
/*
对应文件 /sys/kernel/debug/usb/devices
root@mxlos:/sys/kernel/debug/usb# lsusb
Bus 002 Device 002: ID 05e3:0610
Bus 001 Device 001: ID 1d6b:0002
Bus 002 Device 001: ID 1d6b:0002
Bus 003 Device 001: ID 1d6b:0001
Bus 002 Device 004: ID 2c7c:6005
Bus 002 Device 003: ID 0bda:818b
root@mxlos:/sys/kernel/debug/usb# ls
devices ohci usbmon uvcvideo
root@mxlos:/sys/kernel/debug/usb# cat devices
T: Bus=03 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 1
B: Alloc= 0/900 us ( 0%), #Int= 0, #Iso= 0
D: Ver= 1.10 Cls=09(hub ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=1d6b ProdID=0001 Rev= 4.04
S: Manufacturer=Linux 4.4.194 ohci_hcd
S: Product=Generic Platform OHCI controller
S: SerialNumber=101e0000.usb
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr= 0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 2 Ivl=255ms
T: Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=480 MxCh= 1
B: Alloc= 0/800 us ( 0%), #Int= 1, #Iso= 0
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=1d6b ProdID=0002 Rev= 4.04
S: Manufacturer=Linux 4.4.194 ehci_hcd
S: Product=EHCI Host Controller
S: SerialNumber=101c0000.usb
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr= 0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 4 Ivl=256ms
T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 4
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=02 MxPS=64 #Cfgs= 1
P: Vendor=05e3 ProdID=0610 Rev=61.60
S: Product=USB2.0 Hub
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=01 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=256ms
I:* If#= 0 Alt= 1 #EPs= 1 Cls=09(hub ) Sub=00 Prot=02 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=256ms
T: Bus=02 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 4 Spd=480 MxCh= 0
D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=2c7c ProdID=6005 Rev= 3.18
S: Manufacturer=Android
S: Product=Android
S: SerialNumber=0000
C:* #Ifs= 5 Cfg#= 1 Atr=e0 MxPwr=500mA
A: FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=06 Prot=00
I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=06 Prot=00 Driver=cdc_ether
E: Ad=87(I) Atr=03(Int.) MxPS= 64 Ivl=4096ms
I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_ether
I:* If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_ether
E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=0c(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=0b(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=89(I) Atr=03(Int.) MxPS= 64 Ivl=4096ms
E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=0f(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=88(I) Atr=03(Int.) MxPS= 64 Ivl=4096ms
E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=0a(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
T: Bus=02 Lev=02 Prnt=02 Port=03 Cnt=02 Dev#= 3 Spd=480 MxCh= 0
D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=0bda ProdID=818b Rev= 2.00
S: Manufacturer=Realtek
S: Product=802.11n NIC
S: SerialNumber=347DE462B432
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 5 Cls=ff(vend.) Sub=ff Prot=ff Driver=rtl8192eu
E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=87(I) Atr=03(Int.) MxPS= 64 Ivl=500us
E: Ad=08(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=480 MxCh= 1
B: Alloc= 0/800 us ( 0%), #Int= 0, #Iso= 0
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=1d6b ProdID=0002 Rev= 4.04
S: Manufacturer=Linux 4.4.194 dwc2_hsotg
S: Product=DWC OTG Controller
S: SerialNumber=10180000.usb
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr= 0mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 4 Ivl=256ms
root@mxlos:/sys/kernel/debug/usb#
*/
usb_acpi_register()->
return register_acpi_bus_type(&usb_acpi_bus);
retval = bus_register(&usb_bus_type)->
/*
struct bus_type usb_bus_type 对应目录 /sys/bus/usb
struct bus_type usb_bus_type = {
.name = "usb",
.match = usb_device_match,
.uevent = usb_uevent,
};
*/
struct subsys_private *priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);
priv->bus = bus;
bus->p = priv;
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
priv->subsys.kobj.kset = bus_kset;
priv->subsys.kobj.ktype = &bus_ktype;
priv->drivers_autoprobe = 1;
retval = kset_register(&priv->subsys);
retval = bus_create_file(bus, &bus_attr_uevent); //对应文件 /sys/bus/usb/uevent
priv->devices_kset = kset_create_and_add("devices", NULL, &priv->subsys.kobj); //对应目录 /sys/bus/usb/devices
priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj); //对应目录 /sys/bus/usb/drivers
INIT_LIST_HEAD(&priv->interfaces);
__mutex_init(&priv->mutex, "subsys mutex", key);
klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
klist_init(&priv->klist_drivers, NULL, NULL);
retval = add_probe_files(bus)->
retval = bus_create_file(bus, &bus_attr_drivers_probe); //对应文件 /sys/bus/usb/drivers_probe
retval = bus_create_file(bus, &bus_attr_drivers_autoprobe);//对应文件 /sys/bus/usb/drivers_autoprobe
retval = bus_add_groups(bus, bus->bus_groups)->
return sysfs_create_groups(&bus->p->subsys.kobj, groups);
pr_debug("bus: '%s': registered\n", bus->name);
retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb)->
/*
&bus->p->bus_notifier 在函数bus_register() 中初始化:
BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
static struct notifier_block usb_bus_nb = {
.notifier_call = usb_bus_notify,
};
*/
return blocking_notifier_chain_register(&bus->p->bus_notifier, nb);
retval = usb_major_init()->
/*
#define USB_MAJOR 180
#define USB_DEVICE_MAJOR 189
static const struct file_operations usb_fops = {
.owner = THIS_MODULE,
.open = usb_open,
.llseek = noop_llseek,
};
root@mxlos:/sys/bus/usb# cat /proc/devices
Character devices:
180 usb
189 usb_device
242 usbmon
*/
error = register_chrdev(USB_MAJOR, "usb", &usb_fops); //预先注册 usb 字符设备
retval = usb_register(&usbfs_driver)->
/*
struct usb_driver usbfs_driver 对应目录 /sys/bus/usb/drivers/usbfs
root@mxlos:/sys/bus/usb/drivers/usbfs# ls
bind module new_id remove_id uevent unbind
struct usb_driver usbfs_driver = {
.name = "usbfs",
.probe = driver_probe,
.disconnect = driver_disconnect,
.suspend = driver_suspend,
.resume = driver_resume,
};
*/
usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)->
new_driver->drvwrap.for_devices = 0;
new_driver->drvwrap.driver.name = new_driver->name;
new_driver->drvwrap.driver.bus = &usb_bus_type;
new_driver->drvwrap.driver.probe = usb_probe_interface;
new_driver->drvwrap.driver.remove = usb_unbind_interface;
new_driver->drvwrap.driver.owner = owner;
new_driver->drvwrap.driver.mod_name = mod_name;
spin_lock_init(&new_driver->dynids.lock);
INIT_LIST_HEAD(&new_driver->dynids.list);
retval = driver_register(&new_driver->drvwrap.driver);
retval = usb_create_newid_files(new_driver);
//实际打印:usbcore: registered new interface driver usbfs
pr_info("%s: registered new interface driver %s\n", usbcore_name, new_driver->name);
retval = usb_devio_init()->
/*
#define USB_DEVICE_MAJOR 189
#define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0)
*/
retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX, "usb_device");
/*
const struct file_operations usbdev_file_operations = {
.owner = THIS_MODULE,
.llseek = usbdev_lseek,
.read = usbdev_read,
.poll = usbdev_poll,
.unlocked_ioctl = usbdev_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = usbdev_compat_ioctl,
#endif
.mmap = usbdev_mmap,
.open = usbdev_open,
.release = usbdev_release,
};
*/
cdev_init(&usb_device_cdev, &usbdev_file_operations);
retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);
/*
static struct notifier_block usbdev_nb = {
.notifier_call = usbdev_notify,
};
*/
usb_register_notify(&usbdev_nb);
retval = usb_hub_init()->
usb_register(&hub_driver)-> // 注册 usb hub 驱动,对应目录 /sys/bus/usb/drivers/hub
/*
root@mxlos:/sys/bus/usb/drivers/hub# ls
1-0:1.0 2-0:1.0 2-1:1.0 3-0:1.0 bind module new_id remove_id uevent unbind
static struct usb_driver hub_driver = {
.name = "hub",
.probe = hub_probe,
.disconnect = hub_disconnect,
.suspend = hub_suspend,
.resume = hub_resume,
.reset_resume = hub_reset_resume,
.pre_reset = hub_pre_reset,
.post_reset = hub_post_reset,
.unlocked_ioctl = hub_ioctl,
.id_table = hub_id_table,
.supports_autosuspend = 1,
};
*/
usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)->
new_driver->drvwrap.for_devices = 0;
new_driver->drvwrap.driver.name = new_driver->name;
new_driver->drvwrap.driver.bus = &usb_bus_type;
new_driver->drvwrap.driver.probe = usb_probe_interface;
new_driver->drvwrap.driver.remove = usb_unbind_interface;
new_driver->drvwrap.driver.owner = owner;
new_driver->drvwrap.driver.mod_name = mod_name;
spin_lock_init(&new_driver->dynids.lock);
INIT_LIST_HEAD(&new_driver->dynids.list);
retval = driver_register(&new_driver->drvwrap.driver); //对应目录 /sys/bus/usb/drivers/hub
retval = usb_create_newid_files(new_driver)->
driver_create_file(&usb_drv->drvwrap.driver, &driver_attr_new_id); //对应文件 /sys/bus/usb/drivers/new_id
driver_create_file(&usb_drv->drvwrap.driver, &driver_attr_remove_id); //对应文件 /sys/bus/usb/drivers/remove_id
//实际打印:usbcore: registered new interface driver hub
pr_info("%s: registered new interface driver %s\n", usbcore_name, new_driver->name);
struct workqueue_struct *hub_wq = alloc_workqueue("usb_hub_wq", WQ_FREEZABLE, 0);
retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE)-> //对应目录 /sys/bus/usb/drivers/usb
/*
struct usb_device_driver usb_generic_driver = {
.name = "usb",
.probe = generic_probe,
.disconnect = generic_disconnect,
.suspend = generic_suspend,
.resume = generic_resume,
.supports_autosuspend = 1,
};
*/
new_udriver->drvwrap.for_devices = 1;//for_devices用来表示该驱动是设备驱动还是接口驱动
/*
Do the same for device drivers and interface drivers
在函数 is_usb_device_driver() 中判断
return container_of(drv, struct usbdrv_wrap, driver)->for_devices;
在 usb 总线的匹配函数struct bus_type usb_bus_type.match = usb_device_match 中会判断 for_devices 的值:
static int usb_device_match(struct device *dev, struct device_driver *drv)
{
// devices and interfaces are handled separately
if (is_usb_device(dev))->
return dev->type == &usb_device_type;
{
// interface drivers never match devices
if (!is_usb_device_driver(drv))->
return container_of(drv, struct usbdrv_wrap, driver)->for_devices;
{
return 0;
}
return 1;
}
else if (is_usb_interface(dev)) ->
return dev->type == &usb_if_device_type;
{
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;
}
return 0;
}
*/
new_udriver->drvwrap.driver.name = new_udriver->name;
new_udriver->drvwrap.driver.bus = &usb_bus_type;
new_udriver->drvwrap.driver.probe = usb_probe_device;
new_udriver->drvwrap.driver.remove = usb_unbind_device;
new_udriver->drvwrap.driver.owner = owner;
retval = driver_register(&new_udriver->drvwrap.driver);