现象
重复启动设备,偶现一次无法识别到USB身份证模块
内核正常日志
[ 23.705662] insmod_host_driver
[ 23.705662]
[ 23.705666] [ehci0-controller]: sunxi_usb_enable_ehci
[ 23.705672] [sunxi-ehci0]: probe, pdev->name: 5101000.ehci0-controller, sunxi_ehci: 0xffffff800960aa58, 0x:ffffff80097c4000, irq_no:166
[ 23.752831] sunxi-ehci 5101000.ehci0-controller: SW USB2.0 'Enhanced' Host Controller (EHCI) Driver
[ 23.753568] sunxi-ehci 5101000.ehci0-controller: new USB bus registered, assigned bus number 3
[ 23.773479] sunxi-ehci 5101000.ehci0-controller: irq 358, io mem 0xffffffc03f711b00
[ 23.785720] sunxi-ehci 5101000.ehci0-controller: USB 0.0 started, EHCI 1.00
[ 23.785729] sunxi-ehci 5101000.ehci0-controller: ehci_irq: highspeed device connect
[ 23.792290] hub 3-0:1.0: USB hub found
[ 23.792378] hub 3-0:1.0: 1 port detected
[ 23.792818] [ohci0-controller]: sunxi_usb_enable_ohci
[ 23.792824] [sunxi-ohci0]: probe, pdev->name: 5101000.ohci0-controller, sunxi_ohci: 0xffffff800960b4f0
[ 23.793192] sunxi-ohci 5101000.ohci0-controller: SW USB2.0 'Open' Host Controller (OHCI) Driver
[ 23.793729] sunxi-ohci 5101000.ohci0-controller: new USB bus registered, assigned bus number 4
[ 23.793802] sunxi-ohci 5101000.ohci0-controller: irq 359, io mem 0xffffffc03f711b00
[ 23.854740] hub 4-0:1.0: USB hub found
[ 23.854797] hub 4-0:1.0: 1 port detected
[ 24.063170] sunxi-ehci 5101000.ehci0-controller: ehci_irq: highspeed device disconnect
[ 24.405559] usb 4-1: new full-speed USB device number 2 using sunxi-ohci
内核异常日志
12-16 18:21:25.860270[ 19.387334] insmod_host_driver
# 使能 EHCI(USB2.0 高速)控制器
12-16 18:21:25.860458[ 19.387347] [ehci0-controller]: sunxi_usb_enable_ehci
12-16 18:21:25.860521[ 19.387359] [sunxi-ehci0]: probe, pdev->name: 5101000.ehci0-controller, sunxi_ehci: 0xffffff800960aa58, 0x:ffffff80097c4000, irq_no:166
12-16 18:21:25.860581[ 19.389818] sunxi-ehci 5101000.ehci0-controller: SW USB2.0 'Enhanced' Host Controller (EHCI) Driver
12-16 18:21:25.860640[ 19.390456] sunxi-ehci 5101000.ehci0-controller: new USB bus registered, assigned bus number 3
12-16 18:21:25.863487[ 19.393111] sunxi-ehci 5101000.ehci0-controller: irq 358, io mem 0x00000002
12-16 18:21:25.877041[ 19.403975] sunxi-ehci 5101000.ehci0-controller: USB 0.0 started, EHCI 1.00
# 检测到 高速 USB 设备接入(High-Speed)
12-16 18:21:25.877209[ 19.403989] sunxi-ehci 5101000.ehci0-controller: ehci_irq: highspeed device connect
12-16 18:21:25.877270[ 19.405770] hub 3-0:1.0: USB hub found
12-16 18:21:25.877327[ 19.406247] hub 3-0:1.0: 1 port detected
# 使能 OHCI(USB1.1 全速)控制器
12-16 18:21:25.877385[ 19.406666] [ohci0-controller]: sunxi_usb_enable_ohci
12-16 18:21:25.877442[ 19.406674] [sunxi-ohci0]: probe, pdev->name: 5101000.ohci0-controller, sunxi_ohci: 0xffffff800960b4f0
12-16 18:21:25.877500[ 19.407046] sunxi-ohci 5101000.ohci0-controller: SW USB2.0 'Open' Host Controller (OHCI) Driver
12-16 18:21:25.880137[ 19.408699] sunxi-ohci 5101000.ohci0-controller: new USB bus registered, assigned bus number 4
12-16 18:21:25.880316[ 19.408791] sunxi-ohci 5101000.ohci0-controller: irq 359, io mem 0xffffffc03e0f8000
12-16 18:21:25.940616[ 19.469431] hub 4-0:1.0: USB hub found
12-16 18:21:25.940780[ 19.469469] hub 4-0:1.0: 1 port detected
# 关键异常:高速枚举失败 → 设备掉线
12-16 18:21:26.136911[ 19.667395] sunxi-ehci 5101000.ehci0-controller: ehci_irq: highspeed device disconnect
# 设备 以 Full-Speed(USB1.1)重新接入
# Host 在做兼容性回退
12-16 18:21:26.460186[ 19.987402] usb 4-1: new full-speed USB device number 2 using sunxi-ohci
# 致命错误:USB 描述符非法(根因)
12-16 18:21:26.616832[ 20.145752] usb 4-1: config index 0 descriptor too short (expected 32, got 9)
12-16 18:21:26.617015[ 20.145767] usb 4-1: config 1 has 0 interfaces, different from the descriptor's value: 1
日志分析
- USB Host(EHCI / OHCI)初始化完全正常
- USB 设备尝试以 High-Speed 枚举,但迅速断开
- Host 回退到 Full-Speed 重新枚举
- 设备返回了非法的 Configuration Descriptor(长度不足、接口数量不一致)
- 枚举失败,后续 Android Framework 解析 Descriptor 时必然异常
sunxi_usb_enable_ohci降级到了sunxi-ohci
| 原因 | 说明 |
|---|---|
| PHY 初始化失败 | 高速 PHY 可能没上电或复位失败 |
| 电流不足 | EHCI 端口无法稳定供电,高速设备无法枚举 |
| 硬件兼容性 | 某些 USB 设备在 EHCI 下握手失败 |
| 内核驱动 fallback 机制 | EHCI 初始化失败 → USB core 尝试 OHCI,保证低速设备能用 |
sunxi_ehci 对比 sunxi_ohci
| 维度 | sunxi_ehci | sunxi_ohci |
|---|---|---|
| USB 规范 | USB 2.0 | USB 1.1 |
| 速率 | High-Speed 480 Mbps | Full-Speed 12 Mbps / Low-Speed 1.5 Mbps |
| 控制器角色 | 优先尝试者 | 失败回退兜底 |
| 是否必须存在 | 可选(失败可退出) | 必须存在 |
| 对时序/信号要求 | 非常苛刻 | 非常宽松 |
| 对设备描述符要求 | 严格 | 相对宽松 |
| 常见问题暴露 | HS chirp / HS 描述符 | 很少 |
| 在 A133 上 | 和 OHCI 共享同一 PHY | 和 EHCI 共享同一 PHY |
A133 USB 口分配
┌─────────────┐
│ 物理 USB 口0 │ <─ EHCI0 / OHCI0 共用
└─────┬───────┘
│
┌─────┴───────┐
│ Root Hub 1 │ (EHCI0/OHCI0)
│ 1 port │
└─────┬───────┘
│
┌────────┴────────┐
│ USB 设备 (高速尝试失败, fallback 全速) │
└─────────────────┘
┌─────────────┐
│ 物理 USB 口1 │ <─ EHCI1 / OHCI1 共用
└─────┬───────┘
│
┌─────┴───────┐
│ Root Hub 2 │ (EHCI1/OHCI1)
│ 1 port │
└─────┬───────┘
│
┌────────┴────────┐
│ 其他 USB 设备 │
└─────────────────┘
注解:
- EHCIx = 高速 USB 2.0 控制器
- OHCIx = 全速/低速 USB 1.1 控制器
- 同一个物理口的 EHCI 和 OHCI 共用 PHY
- 高速设备如果枚举失败,会 fallback 到 OHCI(full-speed)
- OTG 功能可复用 EHCI0/OHCI0,但当前为 Host 模式
android 日志
12-16 18:21:26.621237 2027 2226 I UsbDescriptorParser: Unknown Descriptor len: 0 type:0x0
12-16 18:21:26.624328 2027 2226 E UsbDescriptorParser: Exception allocating USB descriptor.
12-16 18:21:26.624328 2027 2226 E UsbDescriptorParser: java.lang.IllegalArgumentException
12-16 18:21:26.624328 2027 2226 E UsbDescriptorParser: at com.android.server.usb.descriptors.UsbDescriptor.<init>(UsbDescriptor.java:140)
12-16 18:21:26.624328 2027 2226 E UsbDescriptorParser: at com.android.server.usb.descriptors.UsbUnknown.<init>(UsbUnknown.java:26)
12-16 18:21:26.624328 2027 2226 E UsbDescriptorParser: at com.android.server.usb.descriptors.UsbDescriptorParser.allocDescriptor(UsbDescriptorParser.java:201)
12-16 18:21:26.624328 2027 2226 E UsbDescriptorParser: at com.android.server.usb.descriptors.UsbDescriptorParser.parseDescriptors(UsbDescriptorParser.java:227)
12-16 18:21:26.624328 2027 2226 E UsbDescriptorParser: at com.android.server.usb.descriptors.UsbDescriptorParser.<init>(UsbDescriptorParser.java:64)
12-16 18:21:26.624328 2027 2226 E UsbDescriptorParser: at com.android.server.usb.UsbHostManager.usbDeviceAdded(UsbHostManager.java:372)
12-16 18:21:26.624328 2027 2226 E UsbDescriptorParser: at com.android.server.usb.UsbHostManager.monitorUsbHostBus(Native Method)
12-16 18:21:26.624328 2027 2226 E UsbDescriptorParser: at com.android.server.usb.UsbHostManager.lambda$XT3F5aQci4H6VWSBYBQQNSzpnvs(Unknown Source:0)
12-16 18:21:26.624328 2027 2226 E UsbDescriptorParser: at com.android.server.usb.-$$Lambda$UsbHostMa
日志分析
Android 在解析 USB 设备上报的 Descriptor 时,收到了一个“非法的 USB 描述符(bLength=0)”,直接违反 USB 规范,因此 framework 直接抛异常
AI 分析
【硬件】
USB 设备上电 / 复位
↓
【Kernel】
USB Host Controller 枚举设备
├─ 发 GET_DESCRIPTOR
├─ 收到 descriptor 数据(⚠️ 这里已可能异常)
├─ 生成 usb_device / uevent
↓
【Framework】
UsbHostManager 收到 uevent
└─ UsbDescriptorParser 解析 descriptor
└─ 抛出 IllegalArgumentException
分析结论
- ❌ 不是 Framework bug
- ❌ 不是 App bug
- ⚠️ Framework 只是“放大器”
✅ 问题根因 100% 在:
- USB 设备端上电 / 复位时序
- USB HUB / PHY
- Host Controller 在设备未 ready 时读取 descriptor
核心问题实际上是 EHCI 控制器无法正确初始化高速设备,所以内核 fallback 到 OHCI。OHCI 的低速/全速端口在枚举高速设备时往往会出现 descriptor 不完整、字段异常等情况,才导致 Framework 抛异常
可能触发降级的原因
(1) PHY/硬件原因
- PHY 初始化失败或时序不稳定
- 电源不足或波动(尤其是板载 HUB 或长线)
- USB 上电/复位顺序不对
- 设备未完全 ready,EHCI 就发送 GET_DESCRIPTOR
- 触发高速枚举失败
(2) 内核/驱动限制
- EHCI 驱动超时(默认 50~100ms)
- 设备 descriptor 超出 EHCI 支持范围或返回异常
(3) 设备端问题
- 高速设备在刚上电时响应慢
- Descriptor 不符合 USB 2.0 标准
报错源码
A133_android_10/longan/kernel/linux-4.9/drivers/usb/core/config.c
/*
* Get the USB config descriptors, cache and parse'em
*
* hub-only!! ... and only in reset path, or usb_new_device()
* (used by real hubs and virtual root hubs)
*/
int usb_get_configuration(struct usb_device *dev)
{
struct device *ddev = &dev->dev; // 指向该 USB 设备的 device 结构
int ncfg = dev->descriptor.bNumConfigurations; // 设备声明的配置数量
int result = 0;
unsigned int cfgno, length;
unsigned char *bigbuffer;
struct usb_config_descriptor *desc;
cfgno = 0;
result = -ENOMEM;
// 如果设备声明的配置数量超过内核允许的最大值,则截断
if (ncfg > USB_MAXCONFIG) {
dev_warn(ddev, "too many configurations: %d, "
"using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
}
// 如果没有配置,直接报错返回
if (ncfg < 1) {
dev_err(ddev, "no configurations\n");
return -EINVAL;
}
// 为每个配置分配内核缓存结构 usb_host_config
length = ncfg * sizeof(struct usb_host_config);
dev->config = kzalloc(length, GFP_KERNEL);
if (!dev->config)
goto err2;
// 为每个配置分配 raw descriptor 指针数组
length = ncfg * sizeof(char *);
dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
if (!dev->rawdescriptors)
goto err2;
// 临时缓冲区,用于读取配置描述符的起始部分
desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL); // USB_DT_CONFIG_SIZE = 9
if (!desc)
goto err2;
result = 0;
for (; cfgno < ncfg; cfgno++) {
/*
* 先读取配置描述符前 9 字节,以获取 wTotalLength,
* 用于知道整个配置描述符的长度
*/
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
desc, USB_DT_CONFIG_SIZE);
if (result < 0) {
dev_err(ddev, "unable to read config index %d "
"descriptor/%s: %d\n", cfgno, "start", result);
if (result != -EPIPE)
goto err;
// 如果管道错误,说明设备不能读取该配置
dev_err(ddev, "chopping to %d config(s)\n", cfgno);
dev->descriptor.bNumConfigurations = cfgno;
break;
} else if (result < 4) {
// descriptor 太短,至少要 4 字节(USB规范要求)
dev_err(ddev, "config index %d descriptor too short "
"(expected %i, got %i)\n", cfgno,
USB_DT_CONFIG_SIZE, result);
result = -EINVAL;
goto err;
}
// wTotalLength 指出整个配置描述符的总长度
length = max((int) le16_to_cpu(desc->wTotalLength),
USB_DT_CONFIG_SIZE);
/*
* 根据 wTotalLength 分配 bigbuffer,读取整个配置描述符
*/
bigbuffer = kmalloc(length, GFP_KERNEL);
if (!bigbuffer) {
result = -ENOMEM;
goto err;
}
// 某些设备需要延时初始化
if (dev->quirks & USB_QUIRK_DELAY_INIT)
msleep(200);
// 读取整个配置描述符,包括接口和端点
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
bigbuffer, length);
if (result < 0) {
dev_err(ddev, "unable to read config index %d "
"descriptor/%s\n", cfgno, "all");
kfree(bigbuffer);
goto err;
}
if (result < length) {
// 如果读取长度小于 wTotalLength,打印警告
dev_warn(ddev, "config index %d descriptor too short "
"(expected %i, got %i)\n", cfgno, length, result);
length = result;
}
// 保存 raw descriptor,供后续解析使用
dev->rawdescriptors[cfgno] = bigbuffer;
// 解析配置描述符到内核结构
result = usb_parse_configuration(dev, cfgno,
&dev->config[cfgno], bigbuffer, length);
if (result < 0) {
++cfgno;
goto err;
}
}
result = 0;
err:
// 释放临时缓冲区
kfree(desc);
// 更新设备配置数量
dev->descriptor.bNumConfigurations = cfgno;
err2:
if (result == -ENOMEM)
dev_err(ddev, "out of memory\n");
return result;
}
这段代码是 Linux 内核 usb_get_configuration() 函数的实现(hub-only 情况下),它就是负责读取 USB 设备的 配置描述符 并解析成内核可用结构
可能的原因
设备端固件缺陷
- 配置描述符只返回了起始 9 字节,wTotalLength 指向的长度不对或者设备没有提供完整接口描述符。
- bNumInterfaces = 1,但实际读取到的接口描述符 = 0。
USB 通信异常
- 数据传输被截断(线材、USB hub、信号干扰),导致内核拿不到完整描述符。
内核/quirks 不匹配
- 某些自研 USB 设备需要 USB_QUIRK_* 才能兼容(例如强制延时、修正 wTotalLength 等)。
- 你的代码里有:
if (dev->quirks & USB_QUIRK_DELAY_INIT)
msleep(200);
如果设备需要特殊延时或 workaround,但没有设置 quirks,也可能返回不全。
修改方案
/*
* Get the USB config descriptors, cache and parse'em
*
* hub-only!! ... and only in reset path, or usb_new_device()
* (used by real hubs and virtual root hubs)
*/
int usb_get_configuration(struct usb_device *dev)
{
struct device *ddev = &dev->dev;
int ncfg = dev->descriptor.bNumConfigurations;
int result = 0;
unsigned int cfgno, length;
unsigned char *bigbuffer;
struct usb_config_descriptor *desc;
//lixiaogang add start
int retry;
//lixiaogang add end
cfgno = 0;
result = -ENOMEM;
if (ncfg > USB_MAXCONFIG) {
dev_warn(ddev, "too many configurations: %d, "
"using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
}
if (ncfg < 1) {
dev_err(ddev, "no configurations\n");
return -EINVAL;
}
length = ncfg * sizeof(struct usb_host_config);
dev->config = kzalloc(length, GFP_KERNEL);
if (!dev->config)
goto err2;
length = ncfg * sizeof(char *);
dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
if (!dev->rawdescriptors)
goto err2;
desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
if (!desc)
goto err2;
result = 0;
for (; cfgno < ncfg; cfgno++) {
/* We grab just the first descriptor so we know how long
* the whole configuration is */
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
desc, USB_DT_CONFIG_SIZE);
if (result < 0) {
dev_err(ddev, "unable to read config index %d "
"descriptor/%s: %d\n", cfgno, "start", result);
if (result != -EPIPE)
goto err;
dev_err(ddev, "chopping to %d config(s)\n", cfgno);
dev->descriptor.bNumConfigurations = cfgno;
break;
} else if (result < 4) {
dev_err(ddev, "config index %d descriptor too short "
"(expected %i, got %i)\n", cfgno,
USB_DT_CONFIG_SIZE, result);
result = -EINVAL;
goto err;
}
length = max((int) le16_to_cpu(desc->wTotalLength),
USB_DT_CONFIG_SIZE);
/* Now that we know the length, get the whole thing */
bigbuffer = kmalloc(length, GFP_KERNEL);
if (!bigbuffer) {
result = -ENOMEM;
goto err;
}
if (dev->quirks & USB_QUIRK_DELAY_INIT)
msleep(200);
//modify by lixiaogang start
//result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
// bigbuffer, length);
/* 只在读取完整配置 descriptor 时增加重试 */
for (retry = 0; retry < 5; retry++) {
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);
if (result >= length)
break; // 成功读取完整 descriptor
dev_warn(ddev, "full config index %d descriptor too short (attempt %d, got %d bytes)\n",
cfgno, retry+1, result);
msleep(50); // 偶发问题加小延时
}
//modify by lixiaogang end
if (result < 0) {
dev_err(ddev, "unable to read config index %d "
"descriptor/%s\n", cfgno, "all");
kfree(bigbuffer);
goto err;
}
if (result < length) {
dev_warn(ddev, "config index %d descriptor too short "
"(expected %i, got %i)\n", cfgno, length, result);
length = result;
}
// lixiaogang add start
dev_info(&dev->dev, "cfg%d raw descriptor (%d bytes):", cfgno, length);
int i;
for (i = 0; i < length; i++) {
dev_info(&dev->dev, " %02x", bigbuffer[i]);
}
dev_info(&dev->dev, "\n");
// lixiaogang add end
dev->rawdescriptors[cfgno] = bigbuffer;
result = usb_parse_configuration(dev, cfgno,
&dev->config[cfgno], bigbuffer, length);
if (result < 0) {
++cfgno;
goto err;
}
}
result = 0;
err:
kfree(desc);
dev->descriptor.bNumConfigurations = cfgno;
err2:
if (result == -ENOMEM)
dev_err(ddev, "out of memory\n");
return result;
}
修改后的打印日志如下
[ 24.261716] hub 4-0:1.0: USB hub found
[ 24.261763] hub 4-0:1.0: 1 port detected
[ 24.463807] sunxi-ehci 5101000.ehci0-controller: ehci_irq: highspeed device disconnect
[ 24.825425] usb 4-1: new full-speed USB device number 2 using sunxi-ohci
[ 24.994858] usb 4-1: full config index 0 descriptor too short (attempt 1, got 9 bytes)
[ 25.050783] usb 4-1: cfg0 raw descriptor (32 bytes):
[ 25.050790] usb 4-1: 09
[ 25.050793] usb 4-1: 02
[ 25.050796] usb 4-1: 20
[ 25.050799] usb 4-1: 00
[ 25.050802] usb 4-1: 01
[ 25.050805] usb 4-1: 01
[ 25.050808] usb 4-1: 00
[ 25.050810] usb 4-1: 40
[ 25.050813] usb 4-1: 32
[ 25.050816] usb 4-1: 09
[ 25.050819] usb 4-1: 04
[ 25.050822] usb 4-1: 00
[ 25.050824] usb 4-1: 00
[ 25.050827] usb 4-1: 02
[ 25.050830] usb 4-1: 00
[ 25.050833] usb 4-1: 00
[ 25.050836] usb 4-1: 00
[ 25.050839] usb 4-1: 00
[ 25.050842] usb 4-1: 07
[ 25.050845] usb 4-1: 05
[ 25.050848] usb 4-1: 81
[ 25.050850] usb 4-1: 02
[ 25.050853] usb 4-1: 40
[ 25.050856] usb 4-1: 00
[ 25.050859] usb 4-1: 0a
[ 25.050862] usb 4-1: 07
[ 25.050865] usb 4-1: 05
[ 25.050867] usb 4-1: 01
[ 25.050870] usb 4-1: 02
[ 25.050873] usb 4-1: 40
[ 25.050876] usb 4-1: 00
[ 25.050879] usb 4-1: 0a
[ 25.050882] usb 4-1:
完整描述符
usb 4-1: cfg0 raw descriptor (32 bytes):
usb 4-1: 09 02 20 00 01 01 00 40 32 09 04 00 00 02 00 00 00 00 07 05 81 02 40 00 0a 07 05 01 02 40 00 0a
配置描述符 (Configuration Descriptor)
| 字节位置 | 值 | 字段 | 说明 |
|---|---|---|---|
| 0 | 09 | bLength | 描述符长度 = 9 字节 |
| 1 | 02 | bDescriptorType | 描述符类型 = CONFIGURATION (0x02) |
| 2-3 | 20 00 | wTotalLength | 总长度 = 0x0020 = 32 字节(包括配置 + 接口 + 端点) |
| 4 | 01 | bNumInterfaces | 接口数量 = 1 |
| 5 | 01 | bConfigurationValue | 配置值 = 1 |
| 6 | 00 | iConfiguration | 配置描述符字符串索引 = 0(无字符串) |
| 7 | 40 | bmAttributes | 属性 = 0x40 → 自供电 (0x40) |
| 8 | 32 | bMaxPower | 最大功率 = 0x32 × 2 mA = 100 mA |
接口描述符 (Interface Descriptor)
| 字节位置 | 值 | 字段 | 说明 |
|---|---|---|---|
| 9 | 09 | bLength | 描述符长度 = 9 |
| 10 | 04 | bDescriptorType | INTERFACE (0x04) |
| 11 | 00 | bInterfaceNumber | 接口号 = 0 |
| 12 | 00 | bAlternateSetting | 备用设置 = 0 |
| 13 | 02 | bNumEndpoints | 端点数量 = 2 |
| 14 | 00 | bInterfaceClass | 类 = 0 (未指定) |
| 15 | 00 | bInterfaceSubClass | 子类 = 0 |
| 16 | 00 | bInterfaceProtocol | 协议 = 0 |
| 17 | 00 | iInterface | 接口字符串索引 = 0 |
第一个端点描述符 (Endpoint Descriptor)
| 字节位置 | 值 | 字段 | 说明 |
|---|---|---|---|
| 18 | 07 | bLength | 描述符长度 = 7 |
| 19 | 05 | bDescriptorType | ENDPOINT (0x05) |
| 20 | 81 | bEndpointAddress | 0x81 → IN 端点 1 |
| 21 | 02 | bmAttributes | 传输类型 = BULK (0x02) |
| 22-23 | 40 00 | wMaxPacketSize | 最大包大小 = 0x0040 = 64 bytes |
| 24 | 0a | bInterval | 轮询间隔 = 10 ms(对 BULK 端点一般无意义) |
第二个端点描述符 (Endpoint Descriptor)
| 字节位置 | 值 | 字段 | 说明 |
|---|---|---|---|
| 25 | 07 | bLength | 描述符长度 = 7 |
| 26 | 05 | bDescriptorType | ENDPOINT (0x05) |
| 27 | 01 | bEndpointAddress | 0x01 → OUT 端点 1 |
| 28 | 02 | bmAttributes | BULK 端点 |
| 29-30 | 40 00 | wMaxPacketSize | 64 bytes |
| 31 | 0a | bInterval | 10 ms |
这个 USB 设备的配置描述符翻译如下:
- 配置:1 个接口,自供电,最大功率 100 mA
- 接口 0:2 个端点,类和协议未指定
- 端点 1 IN:BULK, 64 bytes
- 端点 1 OUT:BULK, 64 bytes
这是一种典型的 USB BULK 设备(比如 USB 串口、USB CDC 设备)配置。