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卡操作命令分析
2063 1
|
9月前
|
存储 监控 API
京东电子面单API对接指南:实现订单自动打单,发货效率提升300%
电子面单通过API自动化实现降本增效,显著提升订单处理效率。对接需准备app_key、access_token等参数,结合京东API实现快速打单。系统设计支持自动打印与异常告警,实测日均处理量提升316%,错单率大幅下降,人力成本节省超65%。
|
Ubuntu Unix Linux
Linux网络文件系统NFS:配置与管理指南
NFS 是 Linux 系统中常用的网络文件系统协议,通过配置和管理 NFS,可以实现跨网络的文件共享。本文详细介绍了 NFS 的安装、配置、管理和常见问题的解决方法,希望对您的工作有所帮助。通过正确配置和优化 NFS,可以显著提高文件共享的效率和安全性。
4517 7
|
C++ Windows
[c++][记录]libwdi编译
[c++][记录]libwdi编译
448 0
|
数据处理 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的协同工作能力,使其在现代计算系统中发挥重要作用。
|
芯片
STM32CubeMX TM1637驱动数码管
STM32CubeMX TM1637驱动数码管
1795 6
|
Unix Linux API
开源库介绍:libusb 及其使用
开源库介绍:libusb 及其使用
7841 0
开源库介绍:libusb 及其使用
|
存储 数据采集 数据安全/隐私保护
使用STM32F103读取TF卡并模拟U盘:使用标准库实现
通过以上步骤,你可以实现用STM32F103将TF卡内容变成U盘进行读取。这种功能在数据采集、便携式存储设备等应用中非常有用。如果你有更多的需求,可以进一步扩展此项目,例如添加文件管理功能、加密存储等。希望这篇博客能帮到你,如果有任何问题,欢迎在评论区留言讨论!
2104 1