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 设备自定义批量传输的设备描述符实现,有关不同的平台,设备驱动实现方式不一。掌握了描述符,基本就掌握了设备实现的核心。参考对应平台做相关移植即可。

相关文章
|
Ubuntu Linux API
libusb简介及在Linux中安装libusb
最近做了关于在X86环境下通过FT232H芯片实现的USB转SPI的相关驱动,接触到了libusb。libusb是一个开源的用C实现的,应用程序与用户的USB设备进行通信的库。它是可移植的,对外使用统一的API,支持Windows、macOS、Linux、Android。它是用户模式(user-mode),应用程序与USB设备通信不需要高权限,但是在Android下好像有些接口需要root权限才能调用成功。它支持所有版本的USB协议。它的License是LGPL,源码地址在https://github.com/libusb/libusb,最新发布版本为1.0.23。
libusb简介及在Linux中安装libusb
|
存储 安全 Linux
linux系统中u-boot命令的EMMC和SD卡操作命令分析
linux系统中u-boot命令的EMMC和SD卡操作命令分析
1892 1
|
3月前
|
域名解析 缓存 网络协议
Linux dnsmasq完全教程
dnsmasq是轻量级DNS+DHCP一体化工具,专为小型局域网设计。它能实现DNS缓存加速、内网域名解析(如用“server.local”代替IP)、自动分配IP地址,配置简单、资源占用低,树莓派或老旧服务器也能流畅运行,是家庭、工作室网络管理的“全能小管家”。
|
安全 Unix Linux
VMware Workstation 17.6.3 发布下载,现在完全免费无论个人还是商业用途
VMware Workstation 17.6.3 发布下载,现在完全免费无论个人还是商业用途
135672 65
|
数据处理 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的协同工作能力,使其在现代计算系统中发挥重要作用。
USB Type-C引脚解析 && CC、DFP、UFP、DRP用途解析
USB Type-C引脚解析 && CC、DFP、UFP、DRP用途解析
|
Unix Linux API
开源库介绍:libusb 及其使用
开源库介绍:libusb 及其使用
7507 0
开源库介绍:libusb 及其使用
|
网络协议 NoSQL 算法
TCP协议:超时重传、流量控制、keep-alive和端口号,你真的了解吗?
【6月更文挑战第2天】本文探讨了TCP协议的关键机制,包括超时重传计算(基于SRTT和RTT),流量控制(使用滑动窗口适应接收方处理能力),TCP keep-alive(通过定期探测保持连接活性),以及端口号的作用(区分不同服务和应用)。这些内容对于理解TCP的工作原理和面试准备至关重要。
833 1
|
人工智能 Linux Shell
Linux——vim简介、配置方案(附带超美观的配置方案)、常用模式的基本操作
Linux——vim简介、配置方案(附带超美观的配置方案)、常用模式的基本操作
1428 2