libusb的同步和异步
文章目录
- 一、同步传输(Synchronous Transfer)
- ✅ 特点
- 📌 常用函数
- 🧠 示例(bulk 传输)
- 二、异步传输(Asynchronous Transfer)
- ✅ 特点
- 📌 操作流程
- 📌 异步传输回调函数
- 📘 示例(异步 bulk 读取)
- 三、同步 vs 异步 对比总结
- 四、事件处理函数
- 五、常见错误排查
- 六、总结
libusb
是 Linux、Windows、macOS 上广泛使用的用户空间 USB 通用访问库。它提供同步和异步两种传输方式,用于控制、批量、等时和中断传输。下面详细讲解 libusb
中同步和异步传输机制、相关函数和操作流程。
一、同步传输(Synchronous Transfer)
✅ 特点
- 简单易用;
- 阻塞调用,调用线程会等待传输完成;
- 适用于一次性传输或简单应用。
📌 常用函数
int libusb_bulk_transfer(libusb_device_handle *dev_handle,unsigned char endpoint,unsigned char *data,int length,int *transferred,unsigned int timeout
);
其他同步函数包括:
函数 | 用途 |
---|---|
libusb_control_transfer | 控制传输(ep0) |
libusb_bulk_transfer | 批量传输 |
libusb_interrupt_transfer | 中断传输 |
🧠 示例(bulk 传输)
unsigned char data[512];
int transferred;
int r = libusb_bulk_transfer(dev_handle, 0x81, data, sizeof(data), &transferred, 1000);
if (r == 0) {printf("Read %d bytes\n", transferred);
} else {fprintf(stderr, "Transfer error: %s\n", libusb_error_name(r));
}
二、异步传输(Asynchronous Transfer)
✅ 特点
- 非阻塞,不会阻塞调用线程;
- 需要自行提交请求并等待回调;
- 适合高吞吐量、大量并发传输、实时数据场景(如摄像头、音频流);
- 更复杂,但性能更高。
📌 操作流程
-
分配并初始化传输
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
-
填充传输请求结构体
libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, data_buffer, length, callback_fn, user_data, timeout);
-
提交传输
libusb_submit_transfer(transfer);
-
等待/处理事件
libusb_handle_events(ctx); // 阻塞直到事件发生
-
释放传输资源
在回调函数中调用libusb_free_transfer()
释放内存。
📌 异步传输回调函数
void callback_fn(struct libusb_transfer *transfer) {if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {printf("Received %d bytes\n", transfer->actual_length);} else {fprintf(stderr, "Transfer failed: %d\n", transfer->status);}libusb_free_transfer(transfer); // 释放资源
}
📘 示例(异步 bulk 读取)
void cb_fn(struct libusb_transfer *transfer) {if (transfer->status == LIBUSB_TRANSFER_COMPLETED)fwrite(transfer->buffer, 1, transfer->actual_length, stdout);elsefprintf(stderr, "Error in async transfer\n");libusb_free_transfer(transfer);
}void start_async_read(libusb_device_handle* handle) {struct libusb_transfer *transfer = libusb_alloc_transfer(0);unsigned char *buf = malloc(512);libusb_fill_bulk_transfer(transfer, handle, 0x81, buf, 512, cb_fn, NULL, 1000);libusb_submit_transfer(transfer);// 阻塞处理事件(也可用 libusb_handle_events_timeout)while (1) {libusb_handle_events(NULL);}
}
三、同步 vs 异步 对比总结
特性 | 同步传输 | 异步传输 |
---|---|---|
阻塞线程 | 是 | 否 |
编程复杂度 | 简单 | 复杂 |
适用场景 | 简单控制或低频通信 | 高速传输、大量数据 |
性能 | 一般 | 高 |
实现机制 | 底层等待传输完成 | 提交后事件轮询或回调触发 |
四、事件处理函数
- 异步传输必须定期或持续调用以下函数处理事件:
函数 | 描述 |
---|---|
libusb_handle_events() | 阻塞等待事件 |
libusb_handle_events_timeout() | 等待带超时时间 |
libusb_handle_events_completed() | 等待直到某一事件完成 |
如果不调用这些函数,异步传输将无法执行完成,回调也不会被触发。
五、常见错误排查
问题 | 可能原因 |
---|---|
LIBUSB_ERROR_TIMEOUT | 设备响应慢、timeout 设置太小 |
actual_length = 0 | 设备无数据返回、endpoint 错误 |
回调未触发 | 未调用 libusb_handle_events() |
传输失败 | endpoint 设置错误或传输方向反了 |
六、总结
- 同步适合新手和简单场景;
- 异步适合对性能和响应有要求的应用;
- 推荐掌握基本同步用法后,再逐步过渡到异步实现;
- 异步时必须持续处理事件,否则传输不会完成。