You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux内核自定义USB驱动中两个URB超时问题求助

Linux内核USB驱动URB超时问题排查

问题背景

学习Linux内核USB驱动开发,使用Seeeduino Xiao SAMD21设备,修改其VID/PID作为自定义设备使用。设备端逻辑为:接收串口数据做ROT13转换后回传。使用默认cdc_acm驱动时功能正常,为测试需求将该驱动加入黑名单,自行编写驱动后出现异常。

驱动关键代码

Probe函数

static int probe(struct usb_interface *interface, const struct usb_device_id *id) 
{
    if (...make sure idVendor/Product match ...)
    {
      struct usb_host_interface *iface_desc;
      struct usb_endpoint_descriptor *epd;
      unsigned int i;

      struct usb_device *dev = interface_to_usbdev(interface);
      my_usb_device->dev = dev;  

      iface_desc = interface->cur_altsetting;

      for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
             epd = &iface_desc->endpoint[i].desc;

             pr_info("Endpoint %d",i);
             pr_info("  bLength %d  bDescriptorType %d",epd->bLength,epd->bDescriptorType);
             pr_info("  bEndpointAddress %d bmAttributes %d wMaxPacketSize %d", epd->bEndpointAddress,  epd->bmAttributes,  epd->wMaxPacketSize);

             if (usb_endpoint_is_int_in(epd))   { my_usb_device->int_endpoint = epd;      pr_info("Set Int endpoint");      }
             if (usb_endpoint_is_bulk_in(epd))  { my_usb_device->bulk_in_endpoint = epd;  pr_info("Set Bulk In endpoint");  }
             if (usb_endpoint_is_bulk_out(epd)) { my_usb_device->bulk_out_endpoint = epd; pr_info("Set Bulk Out endpoint"); }
         }

      my_usb_device->probed = 1; 
    }
}

URB请求触发函数

void try_urbs()
{
   if (!my_usb_device->probed) { return; }
   pr_info("Sending URBS\n");

   int actual_length=8;
   int result = -1;

   result = usb_interrupt_msg(my_usb_device->dev,
               usb_rcvintpipe(my_usb_device->dev, my_usb_device->int_endpoint->bEndpointAddress),
                 my_usb_device->intbuffer, MAX_PACKET_SIZE_INT, &actual_length, my_usb_device->int_endpoint->bInterval);

   pr_info("USB Interrupt in Address %d Message result %d %d\n",my_usb_device->int_endpoint->bEndpointAddress,result,actual_length);

   result = usb_bulk_msg(my_usb_device->dev,
               usb_sndbulkpipe(my_usb_device->dev, my_usb_device->bulk_out_endpoint->bEndpointAddress),
                 my_usb_device->writebuffer, MAX_PACKET_SIZE, &actual_length, 5000);

   pr_info("USB Send Bulk Message result %d %d\n",result,actual_length);

   result = usb_bulk_msg(my_usb_device->dev,
               usb_rcvbulkpipe(my_usb_device->dev, my_usb_device->bulk_in_endpoint->bEndpointAddress),
                 my_usb_device->readbuffer, MAX_PACKET_SIZE, &actual_length, 5000);

   pr_info("USB Recv Bulk Message Address %d result %d %d\n",my_usb_device->bulk_in_endpoint->bEndpointAddress,result,actual_length);

   return;
}

运行日志

[  117.048729] Endpoint 0
[  117.048733]   bLength 7  bDescriptorType 5
[  117.048735]   bEndpointAddress 129 bmAttributes 3 wMaxPacketSize 16
[  117.048737] Set Int endpoint
[  117.048801] Endpoint 0
[  117.048802]   bLength 7  bDescriptorType 5
[  117.048803]   bEndpointAddress 2 bmAttributes 2 wMaxPacketSize 64
[  117.048805] Set Bulk Out endpoint
[  117.048806] Endpoint 1
[  117.048807]   bLength 7  bDescriptorType 5
[  117.048808]   bEndpointAddress 131 bmAttributes 2 wMaxPacketSize 64
[  117.048809] Set Bulk In endpoint
[  117.050378] Sending URBS
[  117.068767] USB Interrupt in Address 129 Message result -110 0
[  117.069142] USB Send Bulk Message result 0 64
[  122.428806] USB Recv Bulk Message Address 131 result -110 0

问题现象

  • 中断IN和批量IN的URB请求均超时(错误码-110)
  • 批量OUT请求返回正常,但设备端接收指示灯未触发(cdc_acm驱动下可正常触发)

排查方向

  • 缺少CDC类控制请求处理:原cdc_acm驱动会处理CDC规范的控制命令(如SET_LINE_CODING、SET_CONTROL_LINE_STATE),设备端可能依赖这些请求初始化串口功能。即使修改了VID/PID,设备端依旧是CDC ACM逻辑,需要在自定义驱动中实现这些必要的控制请求,否则设备不会响应端点数据传输。比如发送SET_CONTROL_LINE_STATE设置DTR有效,设备端通常需要该信号启动串口接收。
  • 中断URB超时参数错误:usb_interrupt_msg的最后一个参数是超时时间(单位毫秒),你直接传入了端点的bInterval(单位是帧,1帧=1ms),这会导致超时时间过短(比如bInterval为1时,超时仅1ms),必然触发超时。应改为合理的毫秒值,如1000。
  • probe函数返回值异常:当前probe函数没有明确的return语句,会返回随机值,可能导致内核认为probe失败,驱动未正确绑定设备。需在probe成功时返回0,失败时返回对应错误码(如-EINVAL)。同时要调用usb_set_intfdata(interface, my_usb_device)完成接口与设备数据的关联。
  • 端点数据未正确同步到设备:虽然批量OUT请求返回0,但数据可能仅停留在USB主机控制器,设备端因未初始化(如未收到DTR信号)未开启接收,所以指示灯不亮。可以通过USB抓包工具(如usbmon)确认主机是否发送了必要的控制请求,设备是否响应。
  • 端点描述符引用问题:确保my_usb_device中保存的端点描述符是有效且稳定的,避免使用临时结构的指针。可直接复制端点描述符内容到自定义结构体,而非保存指针。

内容的提问来源于stack exchange,提问作者BarkerChippy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 03:50:05