赞
踩
当前系统中的usb 3.0控制器是pcie设备:
- [root@localhost devices]# lspci |grep USB
- 04:00.0 USB controller: Device 1db7:dc27
- 04:00.1 USB controller: Device 1db7:dc27
- 04:00.2 USB controller: Device 1db7:dc27
- 04:00.3 USB controller: Device 1db7:dc27
- 04:00.4 USB controller: Device 1db7:dc27
- 04:00.5 USB controller: Device 1db7:dc27
- 04:00.6 USB controller: Device 1db7:dc27
- 04:00.7 USB controller: Device 1db7:dc27
lsusb列举当前的usb设备: root_hub是当前控制器上的hub。hub也是一个特殊的usb设备。 下面才是常规的usb设备。
- lsusb -tv:
-
- /: Bus 16.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M //3.0 ?
- /: Bus 15.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M //2.0 ?
- |__ Port 1: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
- |__ Port 1: Dev 2, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M
- /: Bus 14.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 13.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- /: Bus 12.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 11.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- /: Bus 10.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 09.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- |__ Port 1: Dev 2, If 0, Class=Audio, Driver=snd-usb-audio, 12M
- |__ Port 1: Dev 2, If 1, Class=Audio, Driver=snd-usb-audio, 12M
- |__ Port 1: Dev 2, If 2, Class=Audio, Driver=snd-usb-audio, 12M
- |__ Port 1: Dev 2, If 3, Class=Human Interface Device, Driver=, 12M
- /: Bus 08.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 07.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- /: Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- /: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- |__ Port 1: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
- /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
根据上面的lspci和lsusb。应该是一个控制器带了两个root_hub。一个高速的一个低速的。lsusb -v 可以看到iSerial信息。其中有具体的pcie设备。
- [root@localhost devices]# lsusb -s 16:1 -v
-
- Bus 016 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
- Device Descriptor:
- bLength 18
- bDescriptorType 1
- bcdUSB 3.10
- bDeviceClass 9 Hub
- bDeviceSubClass 0
- bDeviceProtocol 3
- bMaxPacketSize0 9
- idVendor 0x1d6b Linux Foundation
- idProduct 0x0003 3.0 root hub
- bcdDevice 4.19
- iManufacturer 3 Linux 4.19.152+ xhci-hcd
- iProduct 2 xHCI Host Controller
- iSerial 1 0000:04:00.7 //pcie usb控制器
- bNumConfigurations 1
- Configuration Descriptor:
- bLength 9
- 。。。。省略
-
-
- [root@localhost devices]# lsusb -s 15:1 -v
-
- Bus 015 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
- Device Descriptor:
- bLength 18
- bDescriptorType 1
- bcdUSB 2.00
- bDeviceClass 9 Hub
- bDeviceSubClass 0
- bDeviceProtocol 1 Single TT
- bMaxPacketSize0 64
- idVendor 0x1d6b Linux Foundation
- idProduct 0x0002 2.0 root hub
- bcdDevice 4.19
- iManufacturer 3 Linux 4.19.152+ xhci-hcd
- iProduct 2 xHCI Host Controller
- iSerial 1 0000:04:00.7 //pcie usb控制器
- bNumConfigurations 1
- Configuration Descriptor:
- 。。。。省略
如果我插入一个绿联usb2.0的 集线器,上面接了鼠标键盘后lsusb查看:
- [root@localhost devices]# lsusb -tv
- /: Bus 16.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 15.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- |__ Port 1: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
- |__ Port 1: Dev 2, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M
- /: Bus 14.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 13.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- /: Bus 12.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 11.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- /: Bus 10.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 09.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- |__ Port 1: Dev 2, If 0, Class=Audio, Driver=snd-usb-audio, 12M
- |__ Port 1: Dev 2, If 1, Class=Audio, Driver=snd-usb-audio, 12M
- |__ Port 1: Dev 2, If 2, Class=Audio, Driver=snd-usb-audio, 12M
- |__ Port 1: Dev 2, If 3, Class=Human Interface Device, Driver=, 12M
- /: Bus 08.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 07.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- /: Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M //多了一个hub,下面挂了结构设备。
- |__ Port 2: Dev 3, If 0, Class=Vendor Specific Class, Driver=ftdi_sio, 12M
- |__ Port 3: Dev 4, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
- |__ Port 4: Dev 5, If 0, Class=Human Interface Device, Driver=usbhid, 12M
- |__ Port 4: Dev 5, If 1, Class=Human Interface Device, Driver=usbhid, 12M
- /: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
- |__ Port 1: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
- /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 10000M
- /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
可以发现,新加入的hub已经出现了,并且是接在Bus 05,Port 1:Dev1 下面。这是一个普通的hub。
1:xhci控制器通过usb_alloc_dev创建usb_device,其总线是usb_type_bus,type是usb_device_type。 参考usb_alloc_dev。
2:usb_register_devie_driver在drivers./usb/core/usb.c的usb_init中。注册一个usb_deviec_driver(drivers/usb/core/generic.c)。其bus也是usb_type_bus。
3:任何usb_device都将第一步匹配到usb_device_driver。
4:generic_probe创建创建device(usb_interface),其总线是usb_type_bus, type是usb_interface_type,参考usb_set_configuration。
5:usb_type_bus的match函数usb_device_match,根据type来匹配。
总结:一个usb的设备会经过两层的匹配,第一次匹配usb_device_type。第二次匹配usb_interface_type。第一次的驱动是usb_device_driver,内核中就是generic.c中定义的。第二次是usb_driver,具体到不同的驱动,包括hub.c中的hub驱动。
USB各种描述的层次结构:
- Device Descriptor: //设备描述
- Configuration Descriptor: //配置描述0,一个设备可能有多个配置,当前激活的。
- Interface Descriptor: //接口描述0。
- HID Device Descriptor:
- Endpoint Descriptor: //端点描述
- Interface Descriptor: //接口描述1。
- HID Device Descriptor:
- Endpoint Descriptor: //端点描述
- ......
-
-
-
- 相关结构体:
-
- struct usb_device {
- struct usb_device_descriptor descriptor;
- struct usb_host_bos *bos;
- struct usb_host_endpoint ep0; //0端口,用来作为控制使用指向ep_in[0]/ep_out[0]
-
- struct usb_host_config *config; //一个usb_device 可以有多个configuration
- struct usb_host_config *actconfig; //当前激活的configuration
-
- struct usb_host_endpoint *ep_in[16]; //IN ENDPOINT 总共16个
- struct usb_host_endpoint *ep_out[16];
- }
-
-
- struct usb_host_config {
- struct usb_config_descriptor desc;
- char *string; /* iConfiguration string, if present */
- struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];
- struct usb_interface *interface[USB_MAXINTERFACES]; //32个。
- struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];
- unsigned char *extra; /* Extra descriptors */
- int extralen;
- };
-
- struct usb_interface {
- struct usb_host_interface *altsetting;
- struct usb_host_interface *cur_altsetting; /* the currently
- * active alternate setting */
- unsigned num_altsetting; /* number of alternate settings */
- struct usb_interface_assoc_descriptor *intf_assoc;
- };
-
- struct usb_host_interface {
- struct usb_interface_descriptor desc; //接口描述符,其中会描述该接口有多少个端口
-
- int extralen;
- unsigned char *extra; /* Extra descriptors */
- struct usb_host_endpoint *endpoint; //端口数组。IN/OUT
-
- char *string; /* iInterface string, if present */
- };
-
-
- struct usb_host_endpoint {
- struct usb_endpoint_descriptor desc; //bEndpointAddress这个字段描述的信息挺多的,比如这个端点是输入端点还是输出端点,这个端点的地址等
- struct usb_ss_ep_comp_descriptor ss_ep_comp;
- struct usb_ssp_isoc_ep_comp_descriptor ssp_isoc_ep_comp;
- struct list_head urb_list;
- void *hcpriv;
- struct ep_device *ep_dev; /* For sysfs info */
-
- unsigned char *extra; /* Extra descriptors */
- int extralen;
- int enabled;
- int streams;
- };
-
- 创建usb_device的过程中解析描述符:
- hub_port_connect
- hub_port_init
- usb_get_device_descriptor
- usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
-
- usb_new_device //hub.c
- usb_enumerate_device //hub.c
- usb_get_configuration //config.c 为N个config循环处理,一次性获取配置描述符,接口描述符,端口描述符。
- usb_get_descriptor //usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,desc, USB_DT_CONFIG_SIZE);
- usb_parse_configuration
- usb_parse_interface
- usb_parse_endpoint //解析当前interface下面所有的endpoint。
-
-
- usb_device匹配generic_probe后的初始化interface:
- usb_set_configuration //循环为N个interface,创建usb_interface ....
- usb_enable_interface
- usb_enable_endpoint
- //根据endpoint的bEndpointAddress,计算第N个endpoint,并设置dev->ep_in/ep_out
- device_add
- create_intf_ep_devs
-
-
-
-
- 插入usb网卡到endpoint解析:
- ==================================================
- [ 322.032676] usbnet_get_endpoints+0x3c/0x1d0 [usbnet]
- [ 322.032681] ax88179_bind+0x3c/0x354 [ax88179_178a]
- [ 322.032686] usbnet_probe+0x2d0/0x830 [usbnet]
- [ 322.032689] usb_probe_interface+0xe8/0x300
- [ 322.032694] really_probe+0xfc/0x560
- [ 322.032697] driver_probe_device+0x108/0x190
- [ 322.032700] __device_attach_driver+0xe0/0x180
- [ 322.032703] bus_for_each_drv+0x7c/0xdc
- [ 322.032705] __device_attach+0xe4/0x1e0
- [ 322.032708] device_initial_probe+0x20/0x30
- [ 322.032711] bus_probe_device+0xa4/0xb0
- [ 322.032713] device_add+0x354/0x770
- [ 322.032717] usb_set_configuration+0x508/0xaa0
- [ 322.032720] usb_generic_driver_probe+0x70/0xb0
- [ 322.032723] usb_probe_device+0x4c/0x12c
- [ 322.032726] really_probe+0xfc/0x560
- [ 322.032728] driver_probe_device+0x108/0x190
- [ 322.032731] __device_attach_driver+0xe0/0x180
- [ 322.032734] bus_for_each_drv+0x7c/0xdc
- [ 322.032736] __device_attach+0xe4/0x1e0
- [ 322.032739] device_initial_probe+0x20/0x30
- [ 322.032742] bus_probe_device+0xa4/0xb0
- [ 322.032744] device_add+0x354/0x770
- [ 322.032747] usb_new_device+0x1e0/0x520
- [ 322.032749] hub_event+0x144c/0x182c
drivers/hid/usbhid/hid-core.c 中注册了usb_deriver:hid_driver:
- static const struct usb_device_id hid_usb_ids[] = {
- { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
- .bInterfaceClass = USB_INTERFACE_CLASS_HID },
- { } /* Terminating entry */
- };
-
- MODULE_DEVICE_TABLE (usb, hid_usb_ids);
-
- static struct usb_driver hid_driver = {
- .name = "usbhid",
- .probe = usbhid_probe,
- .disconnect = usbhid_disconnect,
- #ifdef CONFIG_PM
- .suspend = hid_suspend,
- .resume = hid_resume,
- .reset_resume = hid_reset_resume,
- #endif
- .pre_reset = hid_pre_reset,
- .post_reset = hid_post_reset,
- .id_table = hid_usb_ids,
- .supports_autosuspend = 1,
- };
-
-
- //然后在usbhid_probe中创建usbhid设备:
- static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id)
- {
- struct usb_host_interface *interface = intf->cur_altsetting;
- struct usb_device *dev = interface_to_usbdev(intf);
- struct usbhid_device *usbhid;
- struct hid_device *hid;
- unsigned int n, has_in = 0;
- size_t len;
- int ret;
-
- dbg_hid("HID probe called for ifnum %d\n",
- intf->altsetting->desc.bInterfaceNumber);
-
- for (n = 0; n < interface->desc.bNumEndpoints; n++)
- if (usb_endpoint_is_int_in(&interface->endpoint[n].desc))
- has_in++;
- if (!has_in) {
- hid_err(intf, "couldn't find an input interrupt endpoint\n");
- return -ENODEV;
- }
-
- hid = hid_allocate_device(); //drivers/hid/hid-core.c
-
-
- ....
-
-
- }
-
- drivers/hid/hid-core.c 中注册了bus_register(&hid_bus_type); 总线
- drivers/his/hid-generic.c 中注册了hid_driver:hid_generic 。
- 因此将完成hid总线的匹配流程;
- hid最终通过input_register_device 创建input设备。。。。。
- 具体按键触发中断,怎么从xhci接口到input 可以查看"当我们切换linux终端时,背后发生了什么?" 那篇https://mp.csdn.net/mp_blog/creation/editor/129945303
(139条消息) USB驱动框架_WuYuJun's blog的博客-CSDN博客
usb中断和hub创建:
(139条消息) Kernel-USB 驱动架构_kernel usb驱动_未来的全栈工程师的博客-CSDN博客
hub创建usb_device:
- hub_probe
- INIT_WORK(&hub->events, hub_event); //初始化工作队列 ,hub_event为处理函数
-
- hub_irq
- kick_hub_wq
- queue_work(hub_wq, &hub->events); //激活工作队列
-
-
- hub_event
- hub_port_connect_change
- hub_port_connect
- usb_alloc_dev
- hub_port_init
- usb_new_device
-
-
-
- 如何才能激活tasklet? 调用hub_irq
- usb_hcd_giveback_urb
- __usb_hcd_giveback_urb //完成urb的complete回调hub_irq
- hub_irq
- tasklet_hi_schedule/tasklet_schedule //激活tasklet usb_add_hcd的时候init_giveback_urb_bh初始化。
- usb_giveback_urb_bh
- __usb_hcd_giveback_urb
- hub_irq
-
-
-
-
- 插入:
- [ 445.397729] ===usb_hcd_giveback_urb
- [ 445.401297] CPU: 0 PID: 13 Comm: kworker/0:1 Not tainted 4.19.152+ #38
- [ 445.407808] Hardware name: PHYTIUM LTD D2000/D2000, BIOS
- [ 445.413286] Workqueue: pm hcd_resume_work
- [ 445.417282] Call trace:
- [ 445.419718] dump_backtrace+0x0/0x198
- [ 445.423366] show_stack+0x24/0x30
- [ 445.426668] dump_stack+0x9c/0xd0
- [ 445.429970] usb_hcd_giveback_urb+0x108/0x198 //tasklet
- [ 445.434312] rh_call_control+0x1ec/0x820
- [ 445.438221] usb_hcd_submit_urb+0x104/0x310
- [ 445.442389] usb_submit_urb+0x1e8/0x558
- [ 445.446211] usb_start_wait_urb+0x70/0x160
- [ 445.450293] usb_control_msg+0xc4/0x138
- [ 445.454115] hub_ext_port_status+0xac/0x188
- [ 445.458284] hub_activate+0x120/0x6d0
- [ 445.461932] hub_resume+0x4c/0x140
- [ 445.465320] usb_resume_interface.isra.1+0xbc/0x138
- [ 445.470183] usb_resume_both+0xdc/0x138
- [ 445.474004] usb_runtime_resume+0x24/0x30
- [ 445.478001] __rpm_callback+0x150/0x258
- [ 445.481823] rpm_callback+0x34/0x98
- [ 445.485297] rpm_resume+0x65c/0x840
- [ 445.488772] __pm_runtime_resume+0x70/0xb0
- [ 445.492854] usb_autoresume_device+0x28/0x60
- [ 445.497109] usb_remote_wakeup+0x60/0xb8
- [ 445.501017] hcd_resume_work+0x20/0x30
- [ 445.504753] process_one_work+0x1ac/0x3e0
- [ 445.508748] worker_thread+0x44/0x448
- [ 445.512397] kthread+0x130/0x138
- [ 445.515612] ret_from_fork+0x10/0x18
-
-
-
- 。。。。。。。。
-
- [ 446.576330] usb_submit_urb+0x1e8/0x558
- [ 446.580152] usb_start_wait_urb+0x70/0x160
- [ 446.584234] usb_control_msg+0xc4/0x138
- [ 446.588055] usb_clear_port_feature+0x5c/0x70
- [ 446.592397] hub_port_reset+0x1e8/0x630
- [ 446.596218] hub_port_init+0x28c/0xb20
- [ 446.599952] hub_port_connect+0x26c/0xa10
- [ 446.603947] port_event+0x37c/0x700
- [ 446.607421] hub_event+0x138/0x3d0
USB网卡驱动usbnet
(143条消息) usbnet驱动深入分析-usb虚拟网卡host端_ldd的博客-CSDN博客
触发了软中断 tasklet_schedule后在硬件中断后irq_exit会执行SOFTIRQ中的TASKLET:
- asix:网卡接收数据
- ================================================
- [ 122.536037] ===rx_submit
- [ 122.536275] CPU: 4 PID: 0 Comm: swapper/4 Not tainted 5.10.0 #2
- [ 122.536511] Hardware name: PHYTIUM LTD D2000/D2000, BIOS
- [ 122.536746] Call trace:
- [ 122.536980] dump_backtrace+0x0/0x1dc
- [ 122.537216] show_stack+0x24/0x70
- [ 122.537453] dump_stack+0xd0/0x12c
- [ 122.537690] rx_submit+0x188/0x2c4 [usbnet]
- [ 122.538001] rx_complete+0x2a8/0x310 [usbnet]
- [ 122.538233] __usb_hcd_giveback_urb+0xa4/0x154
- [ 122.538465] usb_giveback_urb_bh+0xf8/0x200
- [ 122.538697] tasklet_action_common.constprop.0+0x154/0x1dc
- [ 122.538930] tasklet_action+0x34/0x40
- [ 122.539161] __do_softirq+0x160/0x594
- [ 122.539394] irq_exit+0xbc/0x104
- [ 122.539627] __handle_domain_irq+0x8c/0xf0
- [ 122.539859] gic_handle_irq+0xd8/0x384
- [ 122.540091] el1_irq+0xd0/0x180
- [ 122.540324] arch_cpu_idle+0x18/0x40
- [ 122.540556] default_idle_call+0x4c/0x220
- [ 122.540711] do_idle+0x264/0x330
- [ 122.540714] cpu_startup_entry+0x34/0xa0
- [ 122.540717] secondary_start_kernel+0x16c/0x220
-
-
- 网卡发送数据:
- ====================================================
- [ 337.134965] usbnet_start_xmit+0x44/0xb74 [usbnet]
- [ 337.134969] dev_hard_start_xmit+0xe4/0x2d0
- [ 337.134973] sch_direct_xmit+0x154/0x54c
- [ 337.134975] __dev_queue_xmit+0x8ec/0xa90
- [ 337.134978] dev_queue_xmit+0x20/0x30
- [ 337.134983] packet_sendmsg+0xa00/0x12b0
- [ 337.134987] sock_sendmsg+0x60/0x7c
- [ 337.134990] sock_write_iter+0xa4/0x104 //socket_file_ops->sock_write_iter
- [ 337.134994] new_sync_write+0x17c/0x1a0
- [ 337.134997] vfs_write+0x224/0x2bc
- [ 337.134999] ksys_write+0xe8/0x100
- [ 337.135002] __arm64_sys_write+0x28/0x3c
- [ 337.135006] el0_svc_common.constprop.0+0x88/0x220
- [ 337.135009] do_el0_svc+0x34/0xa0
- [ 337.135012] el0_svc+0x28/0x70
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。