|
|
// 1. 获取配置描述符
const usb_config_desc_t *config_desc;
err = usb_host_get_active_config_descriptor(temp_dev_hdl, &config_desc);
if (err != ESP_OK) {
Serial.println("Failed to get config descriptor");
return;
}
Serial.printf("Parsing configuration descriptor (Total Length: %d)...", config_desc->wTotalLength);
// 2. 手动遍历描述符链,寻找接口和端点
// p 是当前遍历的指针,end 是整个描述符的结束地址
uint8_t *p = (uint8_t *)config_desc;
uint8_t *end = p + config_desc->wTotalLength;
while (p < end) {
// 描述符的前两个字节固定是:bLength(长度), bDescriptorType(类型)
uint8_t len = p[0];
uint8_t type = p[1];
// 如果长度为0或者超出范围,说明描述符异常,跳出防止死循环
if (len == 0) break;
// 类型 0x04 代表接口描述符 (USB_DT_INTERFACE)
if (type == 0x04) {
const usb_intf_desc_t *intf = (const usb_intf_desc_t *)p;
Serial.printf("Found Interface %d, Class: 0x%02X", intf->bInterfaceNumber, intf->bInterfaceClass);
// 抢占接口(Claim Interface),告诉底层驱动这个接口归我们管
// 注意:必须在提交任何传输(Transfer)之前 Claim
err = usb_host_interface_claim(naobo->clientHandle, naobo->deviceHandle, intf->bInterfaceNumber, intf->bAlternateSetting);
if (err == ESP_OK) {
Serial.printf("Interface %d claimed successfully!", intf->bInterfaceNumber);
} else {
Serial.printf("Failed to claim interface %d: %d", intf->bInterfaceNumber, err);
}
}
// 类型 0x05 代表端点描述符 (USB_DT_ENDPOINT)
else if (type == 0x05) {
const usb_ep_desc_t *ep = (const usb_ep_desc_t *)p;
uint8_t ep_addr = ep->bEndpointAddress;
uint8_t ep_dir = ep_addr & 0x80; // 0x80 表示 IN (设备->ESP32),0x00 表示 OUT
if (ep_dir) {
naobo->ep_in_addr = ep_addr;
naobo->ep_in_max_size = ep->wMaxPacketSize;
Serial.printf("Found IN Endpoint: 0x%02X, Max Size: %d", ep_addr, ep->wMaxPacketSize);
} else {
naobo->ep_out_addr = ep_addr;
Serial.printf("Found OUT Endpoint: 0x%02X", ep_addr);
}
}
// 指针跳到下一个描述符的起始位置
p += len;
} |
|