USB 设备:自定义批量传输及实现

简介: USB 设备:自定义批量传输及实现

在进行 usb 传输的过程中,往往需要大容量传输。无外乎批量传输。典型的批量传输协议如下:


cdc-acm :usb 转串口。win10 以下需要 pc 驱动。


mass-stroage:U 盘设备。


通常仅仅只需要批量传输,而不想引入复杂的协议,这个时候自定义接口进行批量传输就比较合适了,需要注意的是自定义接口需要安装pc驱动, host 并不支持自定义的接口。


描述符布局



  • 设备描述符:bDeviceClass 改为0xFF


  • 配置描述符:常规配置

  • 接口描述符:bInterfaceClass 改为 0xFF


Inerface Descriptor
Endpoint Descruptor(in)
Endpoint Descruptor(out)


描述符介绍


这里只介绍接口描述符和端点描述符,并且是独立的接口设备。


自定义接口:关联两个端点


static struct usb_interface_descriptor intf_desc = {
        .bLength                = sizeof(intf_desc),
        .bDescriptorType        = USB_DT_INTERFACE,
        .bNumEndpoints          = 0x02,
        .bInterfaceClass        = 0xFF,
        .bInterfaceSubClass     = 0x0,
        .bInterfaceProtocol     = 0x0,
};


端点描述符:in/out 端点


static struct usb_endpoint_descriptor hs_bulk_in_desc = {
        .bLength                = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType        = USB_DT_ENDPOINT,
        .bEndpointAddress       = USB_DIR_IN,
        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
        .wMaxPacketSize         = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor hs_bulk_out_desc = {
        .bLength                = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType        = USB_DT_ENDPOINT,
        .bEndpointAddress       = USB_DIR_OUT,
        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
        .wMaxPacketSize         = cpu_to_le16(512),
};


整体接口描述符:


static struct usb_descriptor_header *hs_intf_descs[] = {
        //(struct usb_descriptor_header *) &iad_desc,
        (struct usb_descriptor_header *) &intf_desc,
        (struct usb_descriptor_header *) &hs_bulk_out_desc,
        (struct usb_descriptor_header *) &hs_bulk_in_desc,
        NULL,
};


接口描述符如下:



复合设备


有的时候我们需要在已有的设备功能上,添加一个接口自定义功能。这个时候就需要添加复合设备。复合设备独立接口设备唯一区别在于接口描述符和设备描述符不同。


  • 设备描述符:按照杂项设备处理



  • 自定义接口,添加一个iad 关联


IAD Descriptor
Inerface Descriptor
Endpoint Descruptor(in)
Endpoint Descruptor(out)


IAD 描述符:


static struct usb_interface_assoc_descriptor iad_desc = {        
        .bLength                = sizeof(iad_desc),
        .bDescriptorType        = USB_DT_INTERFACE_ASSOCIATION,
        .bFirstInterface        = 0,  // 动态修改
        .bInterfaceCount        = 1,
        .bFunctionClass         = 0xFF, // vendor
        .bFunctionSubClass      = 0x00,
        .bFunctionProtocol      = 0x00,
        .iFunction              = 0,
};


整体接口描述符:


static struct usb_descriptor_header *hs_intf_descs[] = {
        (struct usb_descriptor_header *) &iad_desc,
        (struct usb_descriptor_header *) &intf_desc,
        (struct usb_descriptor_header *) &hs_bulk_out_desc,
        (struct usb_descriptor_header *) &hs_bulk_in_desc,
        NULL,
};


自定义接口描述符如下:



驱动适配


对于自定义接口,需要按照pc 驱动,否则 windows 端无法识别。


使用 zadig-2.5.exe 按照对应接口的设备驱动。这里是接口2



不同的驱动对应不同的系统调用。


winUSB:对应 libusb(1.0) 系统调用


libusbK:对应libusbK 系统调用


libusb-win32:对应libusb-0.1(libusb-win32) 系统调用


有关libusb、libusbK、libusb-win32 之间的关系本文不做过多介绍,这里只是版本的差异。


主机应用


以libusb 为例介绍。


控制传输


int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle,
 uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
 unsigned char *data, uint16_t wLength, unsigned int timeout);


控制写:


...
  libusb_device_handle* handle = dev->handle;    
  int status = libusb_control_transfer(
        handle,
        /* bmRequestType */ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_INTERFACE,
        /* bRequest      */ bRequest,
        /* wValue        */ 0,
        /* wIndex        */ 0,
        /* Data          */ (unsigned char *)data,
        /* wLength       */ len,
        ms);


控制读:


...
   libusb_device_handle* handle = dev->handle;
   int status = libusb_control_transfer(
            handle,
            /* bmRequestType */ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_INTERFACE,
            /* bRequest      */ bRequest,
            /* wValue        */ 0,
            /* wIndex        */ 0,
            /* Data          */ (unsigned char*)(*data),
            /* wLength       */ len,
            ms);
    return status;


批量传输


int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle,
 unsigned char endpoint, unsigned char *data, int length,
 int *actual_length, unsigned int timeout);


批量读:


int bulk_read(struct bulkusbdev* dev, void* buffer, size_t len, int ms)
{
    int size, errcode;
    libusb_device_handle* handle = dev->handle;
    uint8_t endpoint_in = dev->endpoint_in;
    errcode = libusb_bulk_transfer(handle, endpoint_in,(unsigned char*) buffer, len, &size, ms);
    if (errcode < 0)
    {
        printf("read:   %s\n", libusb_strerror((enum libusb_error)errcode));
        return -1;
    }
    return size;
}


批量写:


int bulk_write(struct bulkusbdev* dev, void* buffer, int len, int ms)
{
    int size, errcode;
    libusb_device_handle* handle = dev->handle;
    uint8_t endpoint_out = dev->endpoint_out;
    errcode = libusb_bulk_transfer(handle, endpoint_out, (unsigned char*)buffer, len, &size, ms);
    if (errcode<0)
    {
        printf("write:   %s\n", libusb_strerror((enum libusb_error)errcode));
        return -1;
    }
    return size;
}


总结


本文简单介绍了,USB 设备自定义批量传输的设备描述符实现,有关不同的平台,设备驱动实现方式不一。掌握了描述符,基本就掌握了设备实现的核心。参考对应平台做相关移植即可。

相关文章
|
Linux 开发者
交叉编译工具链的下载与安装
交叉编译工具链的下载与安装
2828 1
|
传感器 监控 测试技术
Visual Studio 2022 常用快捷键,记录一下别忘记~
Visual Studio 2022 常用快捷键,记录一下别忘记~
2479 0
Beyond Compare 4密钥过期解决办法,超实用
Beyond Compare 4密钥过期解决办法,超实用
28607 1
|
9月前
|
安全 Unix Linux
VMware Workstation 17.6.3 发布下载,现在完全免费无论个人还是商业用途
VMware Workstation 17.6.3 发布下载,现在完全免费无论个人还是商业用途
83658 65
|
开发工具 git 开发者
|
数据处理 API 流计算
XDMA与FPGA:高效数据传输的艺术
XDMA(Xilinx&#39;s DMA/Bridge Subsystem for PCI Express)是Xilinx推出的一种高效数据传输引擎,专为PCIe总线设计。通过封装PCIe协议,XDMA提供简化的API接口,支持Scatter-Gather DMA和Block DMA模式,特别适用于高性能计算、实时视频处理和大数据分析等领域的数据传输。XDMA通过链表传输和高效的PCIe接口,减少了主机CPU的负担,提高了数据传输效率。AXI4和AXI4-Stream接口进一步增强了XDMA与FPGA的协同工作能力,使其在现代计算系统中发挥重要作用。
|
C++ Windows
[c++][记录]libwdi编译
[c++][记录]libwdi编译
356 0
|
测试技术 Linux Android开发
i2c总线及设备测试工具i2ctools:i2cdetect、i2cdump、i2cget、i2cset
本文介绍了i2ctools工具集的使用,包括i2cdetect、i2cdump、i2cget和i2cset,这些工具有助于I2C设备的开发和调试,通过检测设备、读写寄存器和数据块来提高开发效率。
3521 1
Clion+STM 32Warn : Failed to open device: LIBUSB_ERROR_NOT_SUPPORTED
Clion+STM 32Warn : Failed to open device: LIBUSB_ERROR_NOT_SUPPORTED
577 0
|
Unix Linux API
开源库介绍:libusb 及其使用
开源库介绍:libusb 及其使用
6800 0
开源库介绍:libusb 及其使用