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

Linux USB驱动:如何将URB Function设置为URB_FUNCTION_VENDOR_DEVICE

Linux USB驱动控制请求无响应问题排查与解决

问题描述

开发Linux USB驱动时,发送usb_ctrlrequest请求无法获取数据,但相同请求在Windows下可正常工作。通过Wireshark抓包发现:

  • Linux下发送的请求对应的URB Function字段为URB_FUNCTION_CONTROL_TRANSFER_EX
  • Windows下正常工作的请求对应的URB Function为URB_FUNCTION_VENDOR_DEVICE

Linux的URB结构中没有Windows_URB_HEADER里的URB Function字段,需要解决如何在Linux驱动中发送对应URB_FUNCTION_VENDOR_DEVICE语义的USB请求。

现有Linux驱动代码

int rv;
struct urb* urb;
struct usb_ctrlrequest* dr;

dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
if (!dr)
    return -ENOMEM;

dr->bRequestType = 0xC0;
dr->bRequest = 144;
dr->wValue = cpu_to_le16(0);
dr->wIndex = cpu_to_le16(0x3000);
dr->wLength = cpu_to_le16(0);

urb = usb_alloc_urb(0, GFP_NOIO);   
usb_fill_control_urb(urb, device, usb_rcvctrlpipe(device, 0x80), (unsigned char *)dr, 0, 0, usb_api_blocking_completion, NULL);

rv = usb_submit_urb(urb, GFP_NOIO);

问题分析

Windows的URB_FUNCTION_VENDOR_DEVICE本质就是标准USB厂商控制请求,Linux下抓包显示的URB_FUNCTION_CONTROL_TRANSFER_EX只是Linux USB栈的封装形式,设备真正识别的是USB标准控制请求包的参数。你当前代码的核心问题:

  • wLength设为0,且未提供接收数据缓冲区,设备没有返回数据的存储位置
  • usb_fill_control_urb的接收缓冲区参数传0,无法承载设备返回的数据

解决方案

1. 分配接收数据缓冲区

先确定设备返回的数据长度(比如示例中设为64字节,需根据设备协议调整),分配对应缓冲区:

#define DATA_LEN 64 // 根据设备实际需求修改
unsigned char *data_buf = kmalloc(DATA_LEN, GFP_NOIO);
if (!data_buf) {
    kfree(dr);
    return -ENOMEM;
}

2. 修正控制请求参数与URB填充

更新wLength为实际接收长度,同时将缓冲区传入usb_fill_control_urb:

dr->wLength = cpu_to_le16(DATA_LEN); // 设置实际需要接收的数据长度

// 修正usb_fill_control_urb参数:传入接收缓冲区及长度
usb_fill_control_urb(urb, device, usb_rcvctrlpipe(device, 0x80), 
                     (unsigned char *)dr, data_buf, DATA_LEN, 
                     usb_api_blocking_completion, NULL);

3. 资源释放与数据处理

URB完成后需释放资源,若为阻塞回调可直接处理返回数据:

rv = usb_submit_urb(urb, GFP_NOIO);
if (rv == 0) {
    // 处理data_buf中的返回数据,示例逻辑
    process_received_data(data_buf, DATA_LEN);
}

// 释放分配的资源
usb_free_urb(urb);
kfree(dr);
kfree(data_buf);

关键说明

Linux中无需刻意模拟Windows的URB Function字段:你代码中bRequestType = 0xC0已经是设备到主机的厂商请求(bit7=1表示IN方向,bit6-5=10表示厂商类型,bit4-0=0表示设备接收端),完全对应URB_FUNCTION_VENDOR_DEVICE的语义。设备只会识别USB标准控制请求的参数,而非操作系统的URB封装标识。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 06:52:40