USB

USB总线系统中的设备

USB 是以主机为中心的分层星形拓扑(tiered star),从上到下依次是:主机(含根集线器)→ 集线器 → 外围设备。

USB总线拓扑

USB主机

  • 每条 USB 总线(一棵拓扑树)有且只有一个主机。一个 SoC 可以有多个主机控制器。A1 的三个 DWC2 控制器各注册一条总线;但不能推广为所有控制器都一对一,例如 xHCI 通常分别注册 USB 2 和 USB 3 两条逻辑总线。
  • USB 2.0 的常规事务由主机调度,设备不能自行发起普通总线事务;远程唤醒等信号是另一回事。USB 3.x 还支持 ERDY 等设备通知,不能把“所有版本始终只能等待轮询”作为通用结论。
  • 主机按固定周期划分时间:每 1 ms 发一个 SOF(Start of Frame)包标识一帧;High Speed 下每帧再细分为 8 个 125 µs 的微帧(microframe)。
  • 负责枚举设备(分配地址、读取描述符、选择配置)、加载驱动,以及对总线上的错误进行管理和恢复。

USB Root Hub(根集线器)

  • 集成在主机控制器内部,不是独立芯片,由 HCD(Host Controller Driver)在注册总线时虚拟出来。
  • Linux 中设备名为 usbN(N 为总线号),接口为 N-0:1.0,绑定 hub 驱动。
  • VID:PID 固定为 Linux Foundation 的虚拟 ID:1d6b:0001(USB 1.1)、1d6b:0002(USB 2.0)、1d6b:0003(USB 3.x)。
  • 端口数等于控制器的物理端口数,见 sysfs 的 maxchild。君正A1 每个控制器只有 1 个端口。
  • product、manufacturer 由内核填写,A1 上分别是 DWC OTG Controller、Linux 4.4.94-20220517 dwc2_hsotg。

对应的启动日志:

dwc2 13680000.otg2: new USB bus registered, assigned bus number 3
hub 3-0:1.0: USB hub found
hub 3-0:1.0: 1 port detected

USB集线器(USB HUB)

  • 作用类似于网络集线器,用于扩展端口。
  • 检测下游端口的插拔,通过自身的中断端点上报主机;负责端口的复位、使能、供电和挂起。设备的"添加"(枚举、分配地址)由主机完成,Hub 只负责发现和上报。
  • USB 2.0 Hub 下行方向是广播转发,确实像网络集线器;USB 3.x SuperSpeed 按路由定向转发,更像交换机。
  • High Speed Hub 内有 TT(Transaction Translator),把 HS 事务转换成 FS/LS 事务,低速设备(键鼠)才能挂在 HS Hub 下。Hub 设备描述符的 bDeviceProtocol:0 = FS Hub,1 = HS 单 TT,2 = HS 多 TT。

USB总线设备

  • 即外围设备(Function),如U盘、键鼠、4G模块、摄像头。
  • 一个物理设备可以包含多个功能(Interface),称为复合设备(Composite Device)。例如 4G 模块同时提供 AT 串口、诊断口和网卡,一个功能可能由一个或多个 Interface 组成,例如 CDC 功能可同时使用控制接口与数据接口;不能把 Interface 与功能严格一一对应。

速度等级与主机控制器

速度速率引入版本sysfs speed典型设备
Low Speed (LS)1.5 MbpsUSB 1.x1.5键盘、鼠标
Full Speed (FS)12 MbpsUSB 1.x12早期U盘、USB 音频
High Speed (HS)480 MbpsUSB 2.0480U盘、4G模块、摄像头
SuperSpeed (SS)5 GbpsUSB 3.05000USB3 移动硬盘
主机控制器支持的速度Linux 驱动
OHCI / UHCIUSB 1.1(LS/FS)ohci-hcd / uhci-hcd
EHCIUSB 2.0 HS;LS/FS 设备通常交给配套的 OHCI/UHCI(companion)处理ehci-hcd
xHCIUSB 3.x,一个控制器支持所有速度xhci-hcd
DWC2Synopsys DesignWare HS OTG,自身支持 LS/FS/HS,嵌入式 SoC 常见dwc2

君正A1 有 3 个 DWC2 控制器(13600000.otg0、13640000.otg1、13680000.otg2),所以有 3 条总线,都是 USB 2.0。

USB描述符

描述符层次

设备通过描述符告诉主机"我是谁、有什么功能、怎么通信":

Device(设备描述符)               一个设备一个:USB 版本、VID/PID、EP0 最大包长
└── Configuration(配置描述符)    通常只有 1 个:供电方式、最大电流
    ├── Interface 0(接口描述符)  接口可独立或与其他接口组成一个功能,驱动可关联多个接口
    │   ├── Endpoint 0x81(IN)
    │   └── Endpoint 0x02(OUT)
    └── Interface 1 ...            复合设备有多个接口
  • sysfs 命名 <bus>-<port_path>:<config>.<interface> 中的 config、interface 就是这里的 bConfigurationValue 和 bInterfaceNumber。
  • 端点 0(EP0)每个设备都有,是双向的控制端点,用于枚举和标准请求,不出现在配置描述符里。
  • 端点地址 bit7 表示方向:1 = IN(设备→主机),0 = OUT(主机→设备);低 4 位是端点号。0x81 = EP1 IN,0x02 = EP2 OUT。
  • Device 绑定通用驱动 usb,Interface 绑定具体的类驱动(如 usb-storage、hub)。

实例:U盘的描述符

在君正A1 上读取 Kingston U盘的原始描述符(sysfs 的 descriptors 文件 = 设备描述符 + 所有配置描述符):

hexdump -C /sys/bus/usb/devices/1-1.1/descriptors
00000000  12 01 00 02 00 00 00 40  51 09 65 16 00 00 01 02  |.......@Q.e.....|
00000010  03 01 09 02 20 00 01 01  00 80 32 09 04 00 00 02  |.... .....2.....|
00000020  08 06 50 00 07 05 81 02  00 02 00 07 05 02 02 00  |..P.............|
00000030  02 00                                             |..|

按描述符拆开:

12 01 00 02 00 00 00 40 51 09 65 16 00 00 01 02 03 01   # 设备描述符(18 字节)
09 02 20 00 01 01 00 80 32                              # 配置描述符(9 字节)
09 04 00 00 02 08 06 50 00                              # 接口描述符(9 字节)
07 05 81 02 00 02 00                                    # 端点描述符(7 字节)
07 05 02 02 00 02 00                                    # 端点描述符(7 字节)
描述符字段值含义
设备bcdUSB0x0200USB 2.0
设备bDeviceClass0x00类别由接口描述符定义
设备bMaxPacketSize00x40EP0 最大包长 64 字节
设备idVendor / idProduct0x0951 / 0x1665Kingston / DataTraveler 2.0(小端存储)
设备bNumConfigurations11 个配置
配置wTotalLength0x0020配置 + 接口 + 端点共 32 字节
配置bNumInterfaces11 个接口
配置bConfigurationValue1配置编号 1,即 1-1.1:1.0 中的 1
配置bmAttributes0x80总线供电,不支持远程唤醒
配置bMaxPower0x3250 × 2 mA = 100 mA
接口bInterfaceNumber0接口 0,即 1-1.1:1.0 中的 0
接口bNumEndpoints22 个端点(不含 EP0)
接口bInterfaceClass / SubClass / Protocol0x08 / 0x06 / 0x50Mass Storage / SCSI 透明命令集 / Bulk-Only Transport
端点bEndpointAddress / bmAttributes / wMaxPacketSize0x81 / 0x02 / 0x0200EP1 IN,Bulk,512 字节
端点bEndpointAddress / bmAttributes / wMaxPacketSize0x02 / 0x02 / 0x0200EP2 OUT,Bulk,512 字节

常见设备类别

Class含义例子Linux 驱动
0x00由接口描述符定义大多数设备—
0x02 / 0x0aCDC 通信 / CDC 数据4G 模块网卡口、USB 串口cdc_ether、cdc_ncm、cdc_acm
0x03HID键盘、鼠标usbhid
0x08Mass StorageU盘、读卡器、移动硬盘usb-storage、uas
0x09HubHub、Root Hubhub
0x0eVideoUVC 摄像头uvcvideo
0xe0无线控制器RNDIS 网卡rndis_host
0xff厂商自定义4G 模块的 AT 口/诊断口option 等 usbserial 驱动

枚举流程

设备插入后,主机通过枚举识别设备并加载驱动:

  1. 检测插入:Hub 检测到端口连接状态变化,通过中断端点通知主机(Linux 中由 hub 驱动的 hub_event() 处理)。
  2. 复位端口:主机复位该端口,复位过程中确定设备速度(HS 设备通过 chirp 握手升到 480 Mbps)。
  3. 读设备描述符:设备此时使用默认地址 0。主机先读设备描述符,主要为了拿到 bMaxPacketSize0。Linux 这一步按 64 字节请求,日志里的 read/64 就是它。
  4. 分配地址:SET_ADDRESS 分配唯一地址(1~127),即 sysfs 的 devnum。每次插拔通常会递增,与端口无关。
  5. 读全部描述符:用新地址读完整的设备描述符(18 字节)、配置描述符(含接口、端点)和字符串描述符。
  6. 选择配置:SET_CONFIGURATION 选中配置(通常是 1),接口开始生效。
  7. 匹配驱动:内核为每个 Interface 生成 uevent,按驱动的 id_table(VID/PID 或 Class/SubClass/Protocol)匹配并调用 probe;mdev/udev 创建 /dev 节点。

驱动匹配用到的 MODALIAS 可以在 uevent 里看到:

cat /sys/bus/usb/devices/1-1.1:1.0/uevent
DEVTYPE=usb_interface
DRIVER=usb-storage
PRODUCT=951/1665/0
TYPE=0/0/0
INTERFACE=8/6/80
MODALIAS=usb:v0951p1665d0000dc00dsc00dp00ic08isc06ip50in00

君正A1 上插入U盘的实际日志:

[19845.669991] usb 1-1.1: new high-speed USB device number 7 using dwc2   # 复位完成,HS 设备,将分配地址 7
[19845.793363] usb-storage 1-1.1:1.0: USB Mass Storage device detected     # 接口匹配到 usb-storage
[19845.810874] scsi host5: usb-storage 1-1.1:1.0                           # usb-storage 注册 SCSI host
[19848.937381] scsi 5:0:0:0: Direct-Access  1.00 PQ: 0 ANSI: 4             # SCSI 扫描到 LUN
[19849.000416]  sda: sda1                                                   # 解析分区表
[19849.010995] sd 5:0:0:0: [sda] Attached SCSI removable disk              # /dev/sda 可用

拔出时:

[19843.623371] usb 1-1.2: USB disconnect, device number 6

传输类型

类型特点带宽 / 时延出错重传典型用途君正A1 实例
Control每个设备必有(EP0),Setup→可选 Data→Status保留一部分带宽是枚举、标准请求、设备配置所有设备的 ep_00
Bulk大块数据,只用空闲带宽不保证时延是U盘、打印机、4G 网卡数据U盘 ep_81(IN) / ep_02(OUT),512 字节
Interrupt少量数据,主机按 bInterval 周期轮询保证最大时延是键鼠、Hub 端口状态变化Hub ep_81,interval 256ms
Isochronous实时数据流预留带宽否UVC 摄像头、音频—
  • Interrupt 传输不是真正的中断,仍然是主机周期性轮询。
  • 周期性传输(Interrupt + Isochronous)最多占用 FS 帧的 90%、HS 微帧的 80%,剩余的留给 Control;Bulk 只能用剩下的空闲带宽,总线忙时会变慢。
  • LS 设备只支持 Control 和 Interrupt。
  • HS 下最大包长:Control 64、Bulk 512、Interrupt / Isochronous 最大 1024 字节。

查看端点:

cd /sys/bus/usb/devices
for e in 1-1.1/ep_00 1-1.1:1.0/ep_* 1-1:1.0/ep_*; do
    echo "$e addr=$(cat $e/bEndpointAddress) type=$(cat $e/type) dir=$(cat $e/direction) maxp=$(cat $e/wMaxPacketSize) interval=$(cat $e/interval)"
done
# 输出
1-1.1/ep_00 addr=00 type=Control dir=both maxp=0040 interval=0ms
1-1.1:1.0/ep_02 addr=02 type=Bulk dir=out maxp=0200 interval=0ms
1-1.1:1.0/ep_81 addr=81 type=Bulk dir=in maxp=0200 interval=0ms
1-1:1.0/ep_81 addr=81 type=Interrupt dir=in maxp=0001 interval=256ms

Linux USB 驱动栈

应用层        mount /dev/sda1      /dev/ttyUSB*         ethX / usbX         /dev/input/eventX
                   │                   │                    │                    │
子系统        文件系统 → sd → SCSI    tty               网络协议栈             input
                   │                   │                    │                    │
USB 类驱动     usb-storage         option/usbserial   cdc_ether/rndis_host/asix   usbhid
                   └───────────────────┴─────────┬──────────┴────────────────────┘
                                                 │  URB(USB Request Block)
USB Core                   usbcore:设备模型、驱动匹配、hub 驱动(端口管理与枚举)
                                                 │
HCD                        dwc2(otg0 / otg1 / otg2)
                                                 │
硬件                       DWC2 控制器 → Root Hub → Hub → 设备
  • 类驱动通过 URB 向 usbcore 提交传输请求,usbcore 交给 HCD 调度到总线上。
  • U盘的完整路径:dwc2 → usbcore → usb-storage → SCSI 中间层 → sd → /dev/sda → 文件系统。
  • 君正A1 上已注册的 USB 驱动(ls /sys/bus/usb/drivers):
驱动用途
usb、hub通用设备驱动、Hub 驱动
usbfs用户态访问 /dev/bus/usb/*(libusb)
usb-storageU盘、移动硬盘
usbhid键盘、鼠标
usbserial、option4G 模块的 AT 口/诊断口 → /dev/ttyUSB*
cdc_ether、cdc_ncm、cdc_subset、rndis_host、zaurus、net10804G 模块网卡口、USB 网络设备
asix、ax88179_178aUSB 有线网卡芯片

当时板上没有 /lib/modules,但仅凭目录缺失不能证明所有驱动都内置,也可能从其他位置加载模块。当时驱动列表中没有 uvcvideo、qmi_wwan、uas,只能说明这些驱动尚未注册;是否可用还需检查内核配置和可加载模块。没有 uas 也不代表 UAS 移动硬盘完全不能用:设备若支持 Bulk-Only Transport,可能通过 usb-storage 工作。

Linux sysfs 中的 USB 设备

命名格式

<bus>-<port_path>:<config>.<interface>

# 例如
1-1:1.0
│ │ │ │
│ │ │ └── Interface 0
│ │ └──── Configuration 1
│ └────── 根 Hub 的 Port 1
└──────── USB Bus 1

1-0:1.0
│ │ │ │
│ │ │ └── Interface 0
│ │ └──── Configuration 1
│ └────── Root Hub 的特殊标识 0
└──────── USB Bus 1
# 这里的 0 并不是物理 USB Port 0,而是 Linux 用于表示 Root Hub 的特殊命名。

1-1.1
│ │ │
│ │ └── 下一级 Hub 的 Port 1
│ └──── 根 Hub 的 Port 1
└────── USB Bus 1
# 其中的 . 表示又经过了一级 Hub。
  • 1-1 表示整个USB设备,1-1:1.0 表示USB设备的一个功能接口。
  • 端口路径对应物理端口,同一个口插什么设备名字都一样;换个口名字就变。程序里不要写死 1-1.2 这类路径。
  • devnum(设备地址)每次插拔通常递增,与端口无关。

常用属性与工具

文件位置含义君正A1 U盘(1-1.1)
idVendor / idProduct设备VID / PID0951 / 1665
manufacturer / product / serial设备字符串描述符Kingston / DataTraveler 2.0
speed设备实际协商速率(Mbps)480
version设备bcdUSB2.00
busnum / devnum设备总线号 / 设备地址1 / 7
devpath设备端口路径1.1
maxchild设备下游端口数,非 Hub 为 00
bMaxPower设备当前配置的最大电流100mA
descriptors设备原始描述符(二进制)见"USB描述符"
bInterfaceClass / SubClass / Protocol接口接口类别08 / 06 / 50
bNumEndpoints接口端点数(不含 EP0)02
ep_XX/设备/接口端点属性:type、direction、wMaxPacketSize、interval—
driver设备/接口绑定的驱动(符号链接)usb / usb-storage
uevent设备/接口热插拔环境变量,含 MODALIAS—

列出所有设备和接口:

cd /sys/bus/usb/devices
# 设备
for d in usb* [0-9]-[0-9]*; do
    case $d in *:*) continue ;; esac   # 跳过接口
    echo "$d  $(cat $d/idVendor):$(cat $d/idProduct)  speed=$(cat $d/speed)  $(cat $d/product 2>/dev/null)"
done
# 接口
for i in *:*; do
    echo "$i  class=$(cat $i/bInterfaceClass)  driver=$(basename $(readlink $i/driver))"
done

其他工具:

  • lsusb:板上是 busybox 版本,只能列出 Bus/Device/ID,不支持 -t 树形显示和厂商名称,详细信息要靠 sysfs。
  • dmesg | grep -iE "usb|hub":查看枚举和插拔日志。
  • /sys/kernel/debug/usb/devices:需要内核开启 debugfs 并挂载,A1 默认未挂载。

判断U盘

readlink -f /sys/block/sda/device/
# 得到
/sys/devices/platform/ahb2/13600000.otg0/usb1/1-1/1-1.1/1-1.1:1.0/host5/target5:0:0/5:0:0:0

路径逐段含义:

/sys/devices/platform/ahb2/13600000.otg0   ← DWC2 OTG 控制器(工作在 host 模式)
  /usb1                                    ← 总线 1 的 Root Hub
    /1-1                                   ← Root Hub 端口 1 上的 Hub
      /1-1.1                               ← 该 Hub 端口 1 上的设备 = U盘
        /1-1.1:1.0                         ← U盘的接口 0(Mass Storage,绑定 usb-storage)
          /host5/target5:0:0/5:0:0:0       ← usb-storage 注册的 SCSI host / target / LUN
  • 判断依据:路径里有 /usbN/ 说明 sda 挂在 USB 上;SATA 硬盘的路径里是 ataN。
case "$(readlink -f /sys/block/sda/device)" in
    */usb[0-9]*/*) echo "sda 是 USB 存储设备" ;;
    */ata[0-9]*/*) echo "sda 是 SATA 设备" ;;
esac
  • 局限:只能判断出"USB 存储设备"。U盘、USB 移动硬盘、读卡器都是 Mass Storage,路径区分不出来。/sys/block/sda/removable(A1 上U盘为 1)也不可靠,很多移动硬盘报 0,部分U盘也报 0。需要区分时只能结合容量、VID/PID 判断。
  • SCSI host 编号和 USB devnum 都属于运行时分配标识,可能被复用;不要依赖它们永久递增或用作设备的稳定身份。

君正A1的USB拓扑

2026-10-13 实测:

[root@Ingenic-uc1_1:devices]# ls /sys/bus/usb/devices
1-0:1.0    1-1.1      1-1:1.0    3-0:1.0    usb2
1-1        1-1.1:1.0  2-0:1.0    usb1       usb3
13600000.otg0 → usb1(Root Hub,1 口)
                 └── 1-1     USB HUB 1a86:8091(4 口,HS 多 TT)
                      ├── 1-1.1  Kingston U盘 0951:1665(HS)
                      ├── 1-1.2  空
                      ├── 1-1.3  空
                      └── 1-1.4  空
13640000.otg1 → usb2(Root Hub,1 口,未接设备)
13680000.otg2 → usb3(Root Hub,1 口,未接设备)
名称类型含义
usb1Root Hub控制器 otg0(13600000)的根 Hub,1 个端口
usb2Root Hub控制器 otg1(13640000)的根 Hub,1 个端口
usb3Root Hub控制器 otg2(13680000)的根 Hub,1 个端口
1-0:1.0 / 2-0:1.0 / 3-0:1.0Interface各根 Hub 的接口,绑定 hub 驱动
1-1Device(Hub)usb1 端口 1 上的 4 口 Hub,1a86:8091(南京沁恒 WCH),开机即存在
1-1:1.0Interface该 Hub 的接口,绑定 hub 驱动
1-1.1DeviceHub 端口 1 上的 Kingston U盘
1-1.1:1.0InterfaceU盘的 Mass Storage 接口,绑定 usb-storage 驱动

注意,Root Hub 比较特殊:它的 USB Device 目录叫 usb1,而不是 1-0,但其 Interface 仍使用 1-0:1.0。

开机时 1-1.1 上插的是一个低速 USB 鼠标,1-1.2 上是U盘。后来拔掉鼠标、把U盘换到端口 1,U盘的名字就从 1-1.2 变成了 1-1.1,devnum 也从 4 涨到了 7。低速鼠标能挂在 HS Hub 下,是靠 Hub 内部的 TT:

[    3.020085] usb 1-1.1: new low-speed USB device number 3 using dwc2
[    3.120089] usb 1-1.1: device descriptor read/64, error -32
[    3.357370] hid-generic 0003:13EE:0001.0001: input,hidraw0: USB HID v1.00 Mouse [MOON AND ] on usb-13600000.otg0-1.1/input0

热插拔检测

相关设备对象增删时,内核可产生 uevent,通知路径包括:

  1. 通过 NETLINK_KOBJECT_UEVENT 广播给用户态;
  2. 启用相应 helper 配置且路径非空时,调用 /proc/sys/kernel/hotplug 指定的程序;现代系统不一定启用此机制。A1 上是 /sbin/mdev,且没有 /etc/mdev.conf,只按默认规则在 /dev 下创建设备节点。

插一次U盘会依次产生 usb、scsi、block 等多个子系统的 uevent。应用一般只关心 SUBSYSTEM=block 的 add/remove,收到后再 mount/umount。

应用层监听 uevent 示例:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/netlink.h>

int main(void)
{
    struct sockaddr_nl addr;
    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_pid = 0;        // 0 表示由内核分配
    addr.nl_groups = 1;     // 订阅内核 uevent 组播组

    int fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
    if (fd < 0 || bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        perror("netlink");
        return 1;
    }

    char buf[4096];
    for (;;) {
        ssize_t len = recv(fd, buf, sizeof(buf) - 1, 0);
        if (len <= 0)
            continue;
        buf[len] = '\0';
        // 消息由多个 '\0' 分隔的字符串组成,例如:
        // "add@/devices/.../block/sda/sda1" "ACTION=add" "SUBSYSTEM=block" "DEVNAME=sda1" "DEVTYPE=partition" ...
        for (char *p = buf; p < buf + len; p += strlen(p) + 1)
            printf("%s\n", p);
        printf("\n");
    }
}

拔U盘前要先 umount。A1 上出现过拔出后再插入时的告警:

FAT-fs (sda1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.

常见故障与日志

错误码

USB 日志里的错误码是负的 errno。MIPS 的 errno 数值和 x86 不同,查日志时要按平台对照:

错误码MIPS(A1)x86含义
EPIPE-32-32端点 STALL,设备拒绝了该请求
ETIME-62-62总线上等不到设备应答(部分 HCD)
EPROTO-71-71协议错误:位填充错误、应答超时等,多为信号质量或供电问题
EOVERFLOW-79-75babble,设备发送的数据超过包长
EILSEQ-88-84CRC 错误(部分 HCD)
ETIMEDOUT-145-110同步传输(如控制传输)超时
ENODEV-19-19设备已拔出
ESHUTDOWN-143-108设备或主机控制器已关闭

常见日志

日志含义常见原因 / 处理
device descriptor read/64, error -71(或 -32、-145)地址 0 阶段读描述符失败偶发一次后能枚举成功可忽略(A1 开机时的低速鼠标就是 -32 后成功);反复出现查供电、线材、Hub
device not accepting address N, error -71SET_ADDRESS 失败多为信号质量、供电问题
unable to enumerate USB device多次重试后放弃枚举设备损坏、供电不足、兼容性问题
USB disconnect 后紧跟 new ... USB device,反复出现设备掉线重连供电不足(移动硬盘最常见)、接触不良、静电
reset high-speed USB device number N using dwc2设备无响应,被主机复位usb-storage 命令超时,常见于劣质U盘、供电不足
over-current condition端口过流短路、负载电流超过限流
FAT-fs (sda1): Volume was not properly unmounted文件系统脏标志未清除拔U盘前未 umount、写入过程中掉电

排查步骤

  1. dmesg | grep -iE "usb|hub":看有没有枚举日志、报什么错。
  2. sysfs 里有没有生成设备;speed 是否符合预期(HS 设备只跑到 12,说明降速了,查线材和 Hub)。
  3. 接口目录下有没有 driver 链接。没有说明没匹配到驱动:检查 bInterfaceClass 和 VID/PID 是否在驱动的 id_table 里,或内核根本没编译该驱动(见"Linux USB 驱动栈"中的驱动列表)。
  4. 换 Hub 口、去掉 Hub 直连、外接供电,排除供电和 Hub 问题。

参考:Linux USB API。