linux USB驱动分析(二)USB core驱动分析

关键词: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);

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值