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

相关文章
|
编解码 监控 API
Android平台GB28181设备接入侧音频采集推送示例
GB/T28181是广泛应用于视频监控行业的标准协议规范,可以在不同设备之间实现互联互通。今天我们主要探讨Android平台的Audio采集部分。
126 1
|
2月前
Netty 与硬件设备交互,下行命令时(服务对设备),如何等待设备响应,再进行业务操作解决方案
Netty 与硬件设备交互,下行命令时(服务对设备),如何等待设备响应,再进行业务操作解决方案
|
3月前
|
编解码 网络协议 前端开发
如何实现Android平台GB28181设备接入模块按需打开摄像头并回传数据
后台采集摄像头,如果想再进一步扩展,可以把android平台gb28181的camera2 demo,都移植过来,实现功能更强大的国标设备侧,这里主要是展示,收到国标平台侧的回传请求后,才打开摄像头,才开始编码打包,最大限度的减少资源的占用
|
开发工具 Android开发
Android平台GB28181设备接入端预置位查询(PresetQuery)探讨和技术实现
之前blog介绍了GB28181云台控制(PTZCmd)相关,本文主要是介绍下GB28181预置位查询。
168 0
|
11月前
|
存储 网络协议 数据安全/隐私保护
逆向USB设备共享:利用内网穿透让远程设备访问本地USB设备
逆向USB设备共享:利用内网穿透让远程设备访问本地USB设备
逆向USB设备共享:利用内网穿透让远程设备访问本地USB设备
|
编解码 监控 网络协议
Android平台GB28181设备接入侧如何实现按需打开视音频采集传输
Android平台GB28181设备接入侧如何实现按需打开视音频采集传输
157 2
4G、Wifi、蓝牙所谓的AT指令模式和数据透传模式到底是什么意思?
4G、Wifi、蓝牙所谓的AT指令模式和数据透传模式到底是什么意思?
520 0
|
监控 Android开发 开发者
Android平台GB28181设备接入端本地SIP端口被占用或屏蔽怎么办?
好多开发者或厂商,对Android平台GB28181接入模块的定位,大多是IPC国标流程打通模拟,基于这个目的,很难按照标准SPEC规范实现Android平台GB28181设备接入,我们在跟第三方国标平台厂商对接时发现,部分公司,尽管参与了标准的制定或审校,自身实现,细节仍不尽人意。
100 0
|
数据采集 监控 前端开发
GB28181设备接入端如何播放语音广播数据?
GB28181设备接入端如何播放语音广播数据?
135 0
|
编解码 监控 安全
Android平台GB28181设备接入侧如何同时对外输出RTSP流?
Android平台GB28181设备接入侧如何同时对外输出RTSP流?
139 0