C语言使用开源库libusb进行USB设备操作

⌚Time: 2022-12-28 21:04:14

👨‍💻Author: Jack Ge

libusb官网

https://libusb.info/

介绍

libusb is a C library that provides generic access to USB devices. It is intended to be used by developers to facilitate the production of applications that communicate with USB hardware.

It is portable: Using a single cross-platform API, it provides access to USB devices on Linux, macOS, Windows, etc.

It is user-mode: No special privilege or elevation is required for the application to communicate with a device.

It is version-agnostic: All versions of the USB protocol, from 1.0 to 3.1 (latest), are supported.

支持的平台

Linux, macOS, Windows (Vista and newer), Android, OpenBSD/NetBSD, Haiku, Solaris.

下载地址

https://github.com/libusb/libusb

https://sourceforge.net/projects/libusb-win32

https://sourceforge.net/projects/libusb/

使用测试

将下载的libusb文件libusb-win32-bin-1.2.7.2解压,得到文件夹

对于libusb-win32库,需要安装usb设备的驱动程序才能够识别,对于64位系统,在bin\amd64文件夹下有install-filter-win.exe,运行

选择需要的usb设备安装驱动

编辑测试代码


/*

 * testlibusb.c

 *

 *  Test suite program

 */

#include <stdio.h>

#include <string.h>

#include <lusb0_usb.h>



int verbose = 0;



void print_endpoint(struct usb_endpoint_descriptor *endpoint)

{

  printf("      bEndpointAddress: %02xh\n", endpoint->bEndpointAddress);

  printf("      bmAttributes:     %02xh\n", endpoint->bmAttributes);

  printf("      wMaxPacketSize:   %d\n", endpoint->wMaxPacketSize);

  printf("      bInterval:        %d\n", endpoint->bInterval);

  printf("      bRefresh:         %d\n", endpoint->bRefresh);

  printf("      bSynchAddress:    %d\n", endpoint->bSynchAddress);

}



void print_altsetting(struct usb_interface_descriptor *interface)

{

  int i;



  printf("    bInterfaceNumber:   %d\n", interface->bInterfaceNumber);

  printf("    bAlternateSetting:  %d\n", interface->bAlternateSetting);

  printf("    bNumEndpoints:      %d\n", interface->bNumEndpoints);

  printf("    bInterfaceClass:    %d\n", interface->bInterfaceClass);

  printf("    bInterfaceSubClass: %d\n", interface->bInterfaceSubClass);

  printf("    bInterfaceProtocol: %d\n", interface->bInterfaceProtocol);

  printf("    iInterface:         %d\n", interface->iInterface);



  for (i = 0; i < interface->bNumEndpoints; i++)

    print_endpoint(&interface->endpoint[i]);

}



void print_interface(struct usb_interface *interface)

{

  int i;



  for (i = 0; i < interface->num_altsetting; i++)

    print_altsetting(&interface->altsetting[i]);

}



void print_configuration(struct usb_config_descriptor *config)

{

  int i;



  printf("  wTotalLength:         %d\n", config->wTotalLength);

  printf("  bNumInterfaces:       %d\n", config->bNumInterfaces);

  printf("  bConfigurationValue:  %d\n", config->bConfigurationValue);

  printf("  iConfiguration:       %d\n", config->iConfiguration);

  printf("  bmAttributes:         %02xh\n", config->bmAttributes);

  printf("  MaxPower:             %d\n", config->MaxPower);



  if(config->interface)

    for (i = 0; i < config->bNumInterfaces; i++)

      print_interface(&config->interface[i]);

}



int print_device(struct usb_device *dev, int level)

{

  usb_dev_handle *udev;

  char description[256];

  char string[256];

  int ret, i;



  udev = usb_open(dev);

  if (udev) {

    if (dev->descriptor.iManufacturer) {

      ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer, string,

                                  sizeof(string));

      if (ret > 0)

        snprintf(description, sizeof(description), "%s - ", string);

      else

        snprintf(description, sizeof(description), "%04X - ",

                 dev->descriptor.idVendor);

    } else

      snprintf(description, sizeof(description), "%04X - ",

               dev->descriptor.idVendor);



    if (dev->descriptor.iProduct) {

      ret = usb_get_string_simple(udev, dev->descriptor.iProduct, string, 

                                  sizeof(string));

      if (ret > 0)

        snprintf(description + strlen(description), sizeof(description) -

                 strlen(description), "%s", string);

      else

        snprintf(description + strlen(description), sizeof(description) -

                 strlen(description), "%04X", dev->descriptor.idProduct);

    } else

      snprintf(description + strlen(description), sizeof(description) -

               strlen(description), "%04X", dev->descriptor.idProduct);



  } else

    snprintf(description, sizeof(description), "%04X - %04X",

             dev->descriptor.idVendor, dev->descriptor.idProduct);



  printf("%.*sDev #%d: %s\n", level * 2, "                    ", dev->devnum,

         description);



  if (udev && verbose) {

    if (dev->descriptor.iSerialNumber) {

      ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, string,

                                  sizeof(string));

      if (ret > 0)

        printf("%.*s  - Serial Number: %s\n", level * 2,

               "                    ", string);

    }

  }



  if (udev)

    usb_close(udev);



  if (verbose) {

    if (!dev->config) {

      printf("  Couldn't retrieve descriptors\n");

      return 0;

    }



    for (i = 0; i < dev->descriptor.bNumConfigurations; i++)

      print_configuration(&dev->config[i]);

  } else {

    for (i = 0; i < dev->num_children; i++)

      print_device(dev->children[i], level + 1);

  }



  return 0;

}



int main(int argc, char *argv[])

{

  struct usb_bus *bus;



  if (argc > 1 && !strcmp(argv[1], "-v"))

    verbose = 1;



  usb_init();

  usb_set_debug(0);



  usb_find_busses();

  usb_find_devices();



  for (bus = usb_get_busses(); bus; bus = bus->next) {

    if (bus->root_dev && !verbose)

      print_device(bus->root_dev, 0);

    else {

      struct usb_device *dev;



      for (dev = bus->devices; dev; dev = dev->next)

        print_device(dev, 0);

    }

  }



  return 0;

}


使用mingw-gcc进行编译连接


gcc TestLibUsb.c -ID:\libs\libusb-win32-bin-1.2.7.2\include -LD:\libs\libusb-win32-bin-1.2.7.2\lib\gcc -lusb

编译链接参数指定libusb头文件和库文件目录和gcc链接到的库文件libusb.a

结果

运行程序a.exe输出usb设备列表

运行程序时使用-v参数获取所有usb设备的详细信息


a.exe -v

Dev #1: PixArt - USB Optical Mouse

  wTotalLength:         34

  bNumInterfaces:       1

  bConfigurationValue:  1

  iConfiguration:       0

  bmAttributes:         a0h

  MaxPower:             50

    bInterfaceNumber:   0

    bAlternateSetting:  0

    bNumEndpoints:      1

    bInterfaceClass:    3

    bInterfaceSubClass: 1

    bInterfaceProtocol: 2

    iInterface:         0

      bEndpointAddress: 81h

      bmAttributes:     03h

      wMaxPacketSize:   4

      bInterval:        10

      bRefresh:         0

      bSynchAddress:    0

Dev #2: CASUE - U+P Keyboard

  wTotalLength:         34

  bNumInterfaces:       1

  bConfigurationValue:  1

  iConfiguration:       4

  bmAttributes:         a0h

  MaxPower:             50

    bInterfaceNumber:   0

    bAlternateSetting:  0

    bNumEndpoints:      1

    bInterfaceClass:    3

    bInterfaceSubClass: 1

    bInterfaceProtocol: 1

    iInterface:         5

      bEndpointAddress: 81h

      bmAttributes:     03h

      wMaxPacketSize:   8

      bInterval:        10

      bRefresh:         0

      bSynchAddress:    0

函数列表

库初始化与反初始化(Library initialization/deinitialization)


void libusb_set_debug (libusb_context *ctx, int level)

设置libusb调试等级,方便查看调试过程和log信息。

void libusb_set_log_cb (libusb_context *ctx, libusb_log_cb cb, int mode)

设置log处理程序,libusb 会将其日志消息重定向到提供的回调函数。

int libusb_set_option (libusb_context *ctx, enum libusb_option option,...)

设置库选项,使用此函数可配置库中的特定选项。

int libusb_init (libusb_context **context)

初始化 libusb。 必须在调用任何其他 libusb 函数之前调用此函数。

void libusb_exit (libusb_context *ctx)

取消初始化 libusb。 应在关闭所有打开的设备后和应用程序终止之前调用。

设备处理和枚举(Device handling and enumeration)


ssize_t libusb_get_device_list (libusb_context *ctx, libusb_device ***list)

返回当前连接到系统的 USB 设备列表。 这是查找要操作的 USB 设备的入口点。

void libusb_free_device_list (libusb_device **list, int unref_devices)

释放先前使用 libusb_get_device_list() 发现的设备列表。 如果设置了 unref_devices 参数,则列表中每个设备的引用计数减 1

uint8_t libusb_get_bus_number (libusb_device *dev)

获取设备连接的总线编号。

uint8_t libusb_get_port_number (libusb_device *dev)

获取设备连接的端口号。

int libusb_get_port_numbers (libusb_device *dev, uint8_t *port_numbers, int port_numbers_len)

获取指定设备的从根节点开始的所有端口号列表

int libusb_get_port_path (libusb_context *ctx, libusb_device *dev, uint8_t *port_numbers, uint8_t port_numbers_len)

请使用 libusb_get_port_numbers API 替代

libusb_device * libusb_get_parent (libusb_device *dev)

从指定设备获取父设备。

uint8_t libusb_get_device_address (libusb_device *dev)

获取设备在它所连接的总线上的地址。

int libusb_get_device_speed (libusb_device *dev)

获取设备的协商连接速度,返回码见 libusb_speed。

int libusb_get_max_packet_size (libusb_device *dev, unsigned char endpoint)

获取特定端点的 wMaxPacketSize 值。

int libusb_get_max_iso_packet_size (libusb_device *dev, unsigned char endpoint)

基于端点描述符中的 wMaxPacketSize 字段,计算特定端点在 1 个微帧的持续时间内能够发送或接收的最大数据包大小。

libusb_device * libusb_ref_device (libusb_device *dev)

增加设备的引用计数。

void libusb_unref_device (libusb_device *dev)

减少设备的引用计数。 如果递减操作导致引用计数达到零,则设备将被销毁。

int libusb_wrap_sys_device (libusb_context *ctx, intptr_t sys_dev, libusb_device_handle **dev_handle)

(不常用,略)

int libusb_open (libusb_device *dev, libusb_device_handle **dev_handle)

打开设备并获取设备句柄。 句柄允许您在相关设备上执行 I/O。

libusb_device_handle * libusb_open_device_with_vid_pid (libusb_context *ctx, uint16_t vendor_id, uint16_t product_id)

打开特定 idVendor/idProduct 组合的USB设备。

void libusb_close (libusb_device_handle *dev_handle)

关闭设备句柄。 应在应用程序退出之前在所有打开的句柄上调用。

libusb_device * libusb_get_device (libusb_device_handle *dev_handle)

获取设备句柄关联的 libusb_device 底层设备。

int libusb_get_configuration (libusb_device_handle *dev_handle, int *config)

确定当前活动配置的 bConfigurationValue。

int libusb_set_configuration (libusb_device_handle *dev_handle, int configuration)

设置设备的活动配置。这在支持多个配置的USB设备中会用到。

int libusb_claim_interface (libusb_device_handle *dev_handle, int interface_number)

在给定的设备句柄上声明一个接口。 您必须先声明要使用的接口,然后才能在其任何端点上执行 I/O。

int libusb_release_interface (libusb_device_handle *dev_handle, int interface_number)

释放先前使用 libusb_claim_interface() 声明的接口。 您应该在关闭设备句柄之前释放所有声明的接口。

int libusb_set_interface_alt_setting (libusb_device_handle *dev_handle, int interface_number, int alternate_setting)

激活接口的备用设置。 该接口必须先前已使用 libusb_claim_interface() 声明。

int libusb_clear_halt (libusb_device_handle *dev_handle, unsigned char endpoint)

清除端点的暂停/停止条件。 处于停止状态的端点无法接收或发送数据,直到停止条件停止。

int libusb_reset_device (libusb_device_handle *dev_handle)

执行 USB 复位以重新初始化设备。

int libusb_kernel_driver_active (libusb_device_handle *dev_handle, int interface_number)

确定内核驱动程序是否在接口上处于活动状态。 如果内核驱动程序处于活动状态,则不能声明该接口,并且 libusb 将无法执行 I/O。

int libusb_detach_kernel_driver (libusb_device_handle *dev_handle, int interface_number)

分离接口和内核驱动程序。 如果成功,您将能够声明接口并执行 I/O。

int libusb_attach_kernel_driver (libusb_device_handle *dev_handle, int interface_number)

重新附加接口的内核驱动程序,该驱动程序之前使用 libusb_detach_kernel_driver() 分离。

int libusb_set_auto_detach_kernel_driver (libusb_device_handle *dev_handle, int enable)

启用/禁用 libusb 的自动内核驱动程序分离。 启用此功能后,libusb 将在声明接口时自动分离接口上的内核驱动程序,并在释放接口时附加它。

标准USB描述符操作(USB descriptors)


int libusb_get_device_descriptor (libusb_device *dev, struct libusb_device_descriptor *desc)

获取指定设备的USB设备描述符。

int libusb_get_active_config_descriptor (libusb_device *dev, struct libusb_config_descriptor **config)

获取当前活动配置的 USB 配置描述符。

int libusb_get_config_descriptor (libusb_device *dev, uint8_t config_index, struct libusb_config_descriptor **config)

根据其索引获取 USB 配置描述符。

int libusb_get_config_descriptor_by_value (libusb_device *dev, uint8_t bConfigurationValue, struct libusb_config_descriptor **config)

获取具有特定 bConfigurationValue 的 USB 配置描述符。

void libusb_free_config_descriptor (struct libusb_config_descriptor *config)

释放从如上API获取的USB配置描述符。

int libusb_get_ss_endpoint_companion_descriptor (libusb_context *ctx, const struct libusb_endpoint_descriptor *endpoint, struct libusb_ss_endpoint_companion_descriptor **ep_comp)

获取端点超高速端点伴随描述符(如果有)。

void libusb_free_ss_endpoint_companion_descriptor (struct libusb_ss_endpoint_companion_descriptor *ep_comp)

释放超高速端点伴随描述符。

int libusb_get_bos_descriptor (libusb_device_handle *dev_handle, struct libusb_bos_descriptor **bos)

获取二进制对象存储 (BOS) 描述符 这是一个 BLOCKING(阻塞) 函数,它将向设备发送请求。

void libusb_free_bos_descriptor (struct libusb_bos_descriptor *bos)

释放BOS描述符。

int libusb_get_usb_2_0_extension_descriptor (libusb_context *ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension)

获取 USB 2.0 扩展描述符。

void libusb_free_usb_2_0_extension_descriptor (struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension)

释放 USB 2.0 扩展描述符。

int libusb_get_ss_usb_device_capability_descriptor (libusb_context *ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap)

获取 SuperSpeed USB 设备功能描述符。

void libusb_free_ss_usb_device_capability_descriptor (struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap)

释放 SuperSpeed USB 设备功能描述符。

int libusb_get_container_id_descriptor (libusb_context *ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, struct libusb_container_id_descriptor **container_id)

获取容器 ID 描述符。

void libusb_free_container_id_descriptor (struct libusb_container_id_descriptor *container_id)

释放容器 ID 描述符

int libusb_get_string_descriptor_ascii (libusb_device_handle *dev_handle, uint8_t desc_index, unsigned char *data, int length)

以 C 风格的 ASCII 检索字符串描述符。

static int libusb_get_descriptor (libusb_device_handle *dev_handle, uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length)

从默认控制管道中检索描述符。

static int libusb_get_string_descriptor (libusb_device_handle *dev_handle, uint8_t desc_index, uint16_t langid, unsigned char *data, int length)

获取设备字符串描述符。返回的字符串是 Unicode,详见 USB 规范。

设备热插拔事件通知(Device hotplug event notification)


int libusb_hotplug_register_callback (libusb_context *ctx, int events, int flags, int vendor_id, int product_id, int dev_class, libusb_hotplug_callback_fn cb_fn, void *user_data, libusb_hotplug_callback_handle *callback_handle)

注册热插拔回调函数。

void libusb_hotplug_deregister_callback (libusb_context *ctx, libusb_hotplug_callback_handle callback_handle)

取消注册热插拔回调。

void * libusb_hotplug_get_user_data (libusb_context *ctx, libusb_hotplug_callback_handle callback_handle)

获取与热插拔回调关联的 user_data。

异步设备I/O(Asynchronous device I/O)


int libusb_alloc_streams (libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints, int num_endpoints)

在指定的端点上分配最多 num_streams 个 USB 批量流。

int libusb_free_streams (libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints)

释放流。

unsigned char * libusb_dev_mem_alloc (libusb_device_handle *dev_handle, size_t length)

尝试分配适合针对给定设备进行传输的 DMA 内存块。

int libusb_dev_mem_free (libusb_device_handle *dev_handle, unsigned char *buffer, size_t length)

释放DMA内存块。

struct libusb_transfer * libusb_alloc_transfer (int iso_packets)

使用指定数量的同步数据包描述符分配 libusb 传输。

void libusb_free_transfer (struct libusb_transfer *transfer)

释放libusb传输。

int libusb_submit_transfer (struct libusb_transfer *transfer)

提交一次传输。

int libusb_cancel_transfer (struct libusb_transfer *transfer)

取消传输。

void libusb_transfer_set_stream_id (struct libusb_transfer *transfer, uint32_t stream_id)

设置传输批量流ID。

uint32_t libusb_transfer_get_stream_id (struct libusb_transfer *transfer)

获取传输批量流ID。

static unsigned char * libusb_control_transfer_get_data (struct libusb_transfer *transfer)

获取控制传输的数据部分。

static struct libusb_control_setup * libusb_control_transfer_get_setup (struct libusb_transfer *transfer)

获取控制传输的控制Setup包。

static void libusb_fill_control_setup (unsigned char *buffer, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength)

辅助函数用于填充Setup包(数据缓冲区的前 8 个字节)以进行控制传输。

static void libusb_fill_control_transfer (struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)

用于填充控制传输所需的 libusb_transfer 字段的辅助函数。

static void libusb_fill_bulk_transfer (struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)

用于填充批量传输所需的 libusb_transfer 字段的辅助函数。

static void libusb_fill_bulk_stream_transfer (struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char endpoint, uint32_t stream_id, unsigned char *buffer, int length, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)

使用批量流填充批量传输所需的 libusb_transfer 字段的辅助函数。

static void libusb_fill_interrupt_transfer (struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)

用于填充中断传输所需的 libusb_transfer 字段的辅助函数。

static void libusb_fill_iso_transfer (struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, int num_iso_packets, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)

用于填充同步传输所需的 libusb_transfer 字段的辅助函数。

static void libusb_set_iso_packet_lengths (struct libusb_transfer *transfer, unsigned int length)

根据传输结构中的 num_iso_packets 字段设置同步传输中所有数据包长度的便捷功能。

static unsigned char * libusb_get_iso_packet_buffer (struct libusb_transfer *transfer, unsigned int packet)

定位同步数据包在同步传输缓冲区内的位置的便捷功能。

static unsigned char * libusb_get_iso_packet_buffer_simple (struct libusb_transfer *transfer, unsigned int packet)

定位同步数据包在同步传输缓冲区内的位置的便捷功能,用于每个数据包大小相同的传输。

​​​​​​​轮询和计时(Polling and timing)

只有异步 API 的用户才需要这些函数。 如果只使用更简单的同步 API,那么不需要调用这些函数。


int libusb_try_lock_events (libusb_context *ctx)

尝试获取事件处理锁。

void libusb_lock_events (libusb_context *ctx)

获取事件处理锁,如果有争用则阻塞直到成功获取。

void libusb_unlock_events (libusb_context *ctx)

释放锁。

int libusb_event_handling_ok (libusb_context *ctx)

确定该线程是否仍然可以进行事件处理。

int libusb_event_handler_active (libusb_context *ctx)

确定活动线程是否正在处理事件(即是否有人持有事件处理锁)。

void libusb_interrupt_event_handler (libusb_context *ctx)

中断正在处理事件的任何活动线程。 当应用程序希望调用 libusb_exit() 时,这主要用于中断专用的事件处理线程。

void libusb_lock_event_waiters (libusb_context *ctx)

获取事件等待者锁。

void libusb_unlock_event_waiters (libusb_context *ctx)

释放事件等待者锁。

int libusb_wait_for_event (libusb_context *ctx, struct timeval *tv)

等待另一个线程发出事件完成的信号。

int libusb_handle_events_timeout_completed (libusb_context *ctx, struct timeval *tv, int *completed)

处理任何挂起事件。

int libusb_handle_events_timeout (libusb_context *ctx, struct timeval *tv)

处理任何挂起事件。

int libusb_handle_events (libusb_context *ctx)

在阻塞模式下处理任何挂起的事件。

int libusb_handle_events_completed (libusb_context *ctx, int *completed)

在阻塞模式下处理任何挂起的事件。

int libusb_handle_events_locked (libusb_context *ctx, struct timeval *tv)

通过轮询文件描述符处理任何挂起的事件,而不检查是否有任何其他线程已经在这样做。 必须在持有事件锁的情况下调用,请参阅 libusb_lock_events()。

int libusb_pollfds_handle_timeouts (libusb_context *ctx)

确定您的应用程序在监视 libusb 的文件描述符时是否必须应用特殊的时序注意事项。

int libusb_get_next_timeout (libusb_context *ctx, struct timeval *tv)

确定 libusb 需要处理的下一个内部超时。

void libusb_set_pollfd_notifiers (libusb_context *ctx, libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, void *user_data)

为文件描述符添加/删除注册通知函数。 将为 libusb 用作事件源的每个新的或删除的文件描述符调用这些函数。

const struct libusb_pollfd ** libusb_get_pollfds (libusb_context *ctx)

检索应由主循环轮询作为 libusb 事件源的文件描述符列表。

void libusb_free_pollfds (const struct libusb_pollfd **pollfds)

释放 libusb_pollfd 结构的列表。 这应该为所有使用 libusb_get_pollfds() 分配的 pollfd 列表调用。

同步设备I/O(Synchronous device I/O)

在进行简单传输可采用如下I/O,高级功能建议使用异步设备 I/O函数集。


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

执行 USB 控制传输。

int libusb_bulk_transfer (libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout)

执行 USB 批量传输。

int libusb_interrupt_transfer (libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout)

执行 USB 中断传输。