一、背景介绍
上一篇博客主要介绍了libusb在linux系统下的详细安装过程,目前新的libusb离线包已经不需要再单独安装libusb-compat资料包了。libusb 较大版本变动以 V1.0 为分界线,访问官网:http://libusb.info 时可以发现文档说明都以 V1.0 为主了。
官网界面清晰明了,分类十分明确,开发者可以直接从网站下载文档,API使用说明,例程等内容。V1.0 相对于之前版本,提供了更丰富的功能和接口,本篇直接基于新版本 libusb 库 API 进行说明与使用介绍。
二、libusb API 参考与特点
介绍
libusb 是一个开源库,允许从用户空间与 USB 设备进行通信。 其面向希望通过自己的软件与 USB 外围设备进行通信的应用程序开发人员。在进行开发之前,建议先通过USB规范文档对USB有一定的了解,如描述符、配置、接口、端点、控制/批量/中断/等时传输等。这样在软件操作 USB 设备时才会得心应手。
libusb库特点
- 支持所有传输类型(控制/批量/中断/等时)
- 同步传输(简单)
- 异步传输(更复杂,但更强大)
- 线程安全(异步接口通常不需要线程处理)
- 轻量级的精简 API
- 通过 libusb-compat-0.1 转换层兼容 libusb-0.1
- 热插拔支持(在某些平台上)。
要开始阅读 API 文档,建议先从不同类别的 libusb 功能的 Module 页面开始。
进行数据传输时需要决定使用同步还是异步数据传输,同步和异步设备 I/O 文档提供了有关此主题的介绍,我们稍后会进行介绍。
一些示例程序可以在 libusb 源代码发行版中的“examples”子目录下找到。 libusb 主页包括使用 libusb 的真实项目示例列表。建议读者直接从例子程序开始,这样可以快速掌握 libusb 的用法并了解相关函数的功能。
三、libusb API列表
编程经验比较丰富的开发者可以直接在安装路径下找到我们编程时需要引用的头文件usb.h,头文件中代码上部分为 usb 协议标准术语的宏定义,中间为相关结构体定义,后半部为编程使用的 API 声明,下面根据 API 功能和使用顺序进行分类描述:
库初始化与反初始化(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)
设备热插拔事件通知(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)
Functions | |
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 中断传输。 |