首页 > 编程知识 正文

Bulk-In, Interface驱动开发用法介绍

时间:2023-11-22 12:08:29 阅读:293931 作者:IUQJ

本文将从多个方面对Bulk-In, Interface驱动进行详细的阐述和解答,包含代码示例。

一、USB传输模式介绍

USB(Universal Serial Bus)是一种通用的数字式通信接口标准,让不同设备可以通过单一的USB接口连接,并实现不同的数字通信需求。USB 接口有四种传输方式:Control、Bulk、Interrupt、Isochronous。

Bulk-In,Interface驱动是一种通过Bulk传输方式的USB设备驱动。Bulk-In指从设备到主机的数据传输,Interface则是该传输模式的一种。

二、Bulk-In, Interface驱动开发前提条件

开始开发之前,我们需要了解基本的开发环境和软件:Linux操作系统、libusb-1.0库、C语言开发工具。

三、Bulk-In, Interface驱动数据传输

Bulk-In, Interface驱动的数据传输可以分为两个步骤:端点准备和传输数据。

1. 端点准备

首先,我们需要找到USB设备的接口和端点地址。可以使用lsusb命令查看设备的厂商ID、产品ID、接口和端点信息:

$ lsusb -d 1234:5678 -v

Bus 003 Device 017: ID 1234:5678
Device Descriptor:
  ...
  idVendor           0x1234
  idProduct          0x5678
  ...
  iInterface         2
  ...

Interface Descriptor:
  bInterfaceNumber   2
  bAlternateSetting  1
  bNumEndpoints      2
  bInterfaceClass    0xff
  bInterfaceSubClass 0xff
  bInterfaceProtocol 0xff
  iInterface         3

Endpoint Descriptor:
  bEndpointAddress  0x01  EP 1 IN
  bmAttributes      0x02
  wMaxPacketSize    0x0040  // 最大包长度为64
  ...
  
Endpoint Descriptor:
  bEndpointAddress  0x82  EP 2 OUT
  bmAttributes      0x02
  wMaxPacketSize    0x0040  // 最大包长度为64
  ...

从上述输出中,我们可以得到接口编号为2,IN端点地址为1,OUT端点地址为2。

在使用libusb_bulk_transfer()传输数据之前,还需要进行端点参数的设置:

libusb_claim_interface(devh, interface_number);  // 申请接口
libusb_set_interface_alt_setting(devh, interface_number, alternate_setting);  // 设置接口备用状态
libusb_get_endpoint_descriptor(devh, endpoint_address_bulk, &endpoint);  // 获取端点描述符
libusb_set_interface_alt_setting(devh, interface_number, alternate_setting);  // 选择接口状态

2. 传输数据

设置端点参数完成后,我们就可以进行Bulk-In, Interface数据传输了。以下是简单的示例代码:

int transferred;
unsigned char data[64];  // 缓存区大小需等于wMaxPacketSize

int r = libusb_bulk_transfer(devh, endpoint->bEndpointAddress, data, sizeof(data), &transferred, 1000);
if (r == 0) {
  printf("%d bytes readn", transferred);
} else {
  printf("Bulk-In transfer error %dn", r);
}

四、Bulk-In, Interface驱动数据解析

在进行Bulk-In传输数据之后,需要解析USB设备传输的数据。这里我们以设备传输字符串为例进行说明。

1. 字符串解析

如果设备传输的数据是字符串,我们可以使用以下的方式进行解析:

if (transferred > 0) {
  // 构造字符串
  char str[transferred + 1];
  memset(str, 0, transferred + 1);
  memcpy(str, data, transferred);

  printf("Received %d bytes: %sn", transferred, str);
}

2. 结构体解析

如果设备传输的数据是结构体,我们可以使用以下的方式进行解析:

struct my_struct {
  uint16_t val1;
  uint8_t val2;
  uint32_t val3;
} __attribute__((packed));

struct my_struct *ptr;
if (transferred == sizeof(struct my_struct)) {
  ptr = (struct my_struct *)data;
  printf("Received val1=%d val2=%d val3=%dn", ptr->val1, ptr->val2, ptr->val3);
}

五、Bulk-In, Interface驱动常见问题解答

1. 为什么读取的数据不正确?

可能是数据传输时,缓存区大小不够,应确保缓存区大小等于端点的最大包长度。

2. 如何确定设备的接口和端点地址?

可以使用lsusb命令查看设备的厂商ID、产品ID、接口和端点信息。

六、Bulk-In, Interface驱动代码示例

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <usb.h>

int main(void)
{
  int r = 1;
  struct usb_device *dev;
  struct usb_dev_handle *devh = NULL;
  unsigned char data[64];
  int transferred;

  // 初始化USB库
  usb_init();
  usb_find_busses();
  usb_find_devices();

  // 查找设备
  dev = usb_find_device(0x1234, 0x5678);
  if (dev) {
    // 打开设备
    devh = usb_open(dev);
    if (devh) {
      // 申请接口
      int interface_number = 2;
      usb_detach_kernel_driver_np(devh, interface_number - 1);
      r = usb_set_configuration(devh, 1);
      r = usb_claim_interface(devh, interface_number);
      int alternate_setting = 1;
      r = usb_set_altinterface(devh, alternate_setting);
      struct usb_endpoint_descriptor *endpoint;

      // 获取IN端点的描述符
      uint8_t endpoint_address_bulk = 0x81;
      endpoint = (struct usb_endpoint_descriptor *)dev->config->
                 interface[interface_number - 1].altsetting[alternate_setting].endpoint;
      for (int i = 0; i < dev->config->interface[interface_number - 1].
           altsetting[alternate_setting].bNumEndpoints; i++) {
        if ((endpoint + i)->bEndpointAddress == endpoint_address_bulk) {
          endpoint = endpoint + i;
          break;
        }
      }

      // 读取数据
      r = usb_bulk_read(devh, endpoint->bEndpointAddress, data, sizeof(data), 1000);
      if (r >= 0) {
        printf("Bulk-In data: ");
        for (int i = 0; i < r; i++) {
          printf("%02x ", data[i]);
        }
        printf("n");
      } else {
        printf("Bulk-In transfer errorn");
      }

      // 释放接口
      r = usb_release_interface(devh, interface_number);

      // 关闭设备
      usb_close(devh);
    }
  }
  return 0;
}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。