使用libusb读取多DATAx包中断传输时阻塞/超时的问题求助
使用libusb读取多DATAx包中断传输时阻塞/超时的问题求助
大家好,我正在开发一个基于libusb的C程序,目标是和一个仅暴露单个中断端点的USB设备通信。这个设备的收发数据都以固定64字节的DATAx包为单位,如果数据长度超过64字节,就会拆分成多个包发送/接收。
我写了一段代码来实现“发送多包数据并读取设备回复”的逻辑,但目前遇到了一个棘手的问题,想请大家帮忙排查:
我的代码实现
#include <libusb.h> #include <stdlib.h> #include <string.h> #include <stdint.h> // 假设这两个端点宏已根据设备实际情况定义 #define ENDPOINT_OUT 0x01 #define ENDPOINT_IN 0x81 #define MIN(a,b) ((a) < (b) ? (a) : (b)) /* * 该函数将outpackets中的数据拆分为64字节的包发送给设备 * 然后读取设备的回复包,拼接后通过reply和rlen返回 */ int write_packets_and_read_reply(libusb_device_handle *handle, uint8_t *outpackets, size_t outlen, uint8_t **reply, size_t *rlen){ size_t sent_packets = 0; uint8_t buffer[64]; int bytes_transferred; int r; size_t index = 0; int32_t remaining = -1; // 拆分输出数据为64字节包,逐个发送 while (outlen > 0){ if ((r = libusb_interrupt_transfer(handle, ENDPOINT_OUT, outpackets + sent_packets * 64, MIN(64, outlen - sent_packets * 64), &bytes_transferred, 0)) != 0) return r; sent_packets++; outlen -= bytes_transferred; } *reply = NULL; do { size_t old_index = index; // 每次读取64字节的中断包 if ((r = libusb_interrupt_transfer(handle, ENDPOINT_IN, buffer, 64, &bytes_transferred, 0)) != 0) return r; index += bytes_transferred; // 扩容回复缓冲区并拷贝新读取的数据 *reply = (uint8_t*)realloc(*reply, index * sizeof(uint8_t)); memcpy((*reply) + old_index, buffer, 64); if (remaining < 0) { // 自定义协议:从第一个包的buffer[5]和buffer[6]拼接出回复总长度 remaining = (buffer[5] << 8) | buffer[6]; } remaining -= bytes_transferred; } while (remaining > 0); *rlen = index; return 0; }
遇到的问题
代码逻辑看似清晰:先把输出数据拆分成64字节的包逐个发送,然后循环读取设备的回复包,直到根据第一个包中的长度字段判断所有数据都读完。但实际运行时:
- 当回复长度≤64字节时,代码完全正常,能正确收发数据;
- 当回复长度>64字节时,第一次读取包成功,但第二次调用
libusb_interrupt_transfer读取IN端点时会无限阻塞(超时设为0时);如果给该函数设置非0超时,就会返回LIBUSB_TIMEOUT错误。
我的排查尝试
- 用USB抓包工具监控总线,发现设备已经把所有的回复包都发送给主机了,但代码就是无法读取到第二个及以后的包;
- 尝试把读取用的
buffer数组改大(比如改成256字节),但问题依然存在,第二次读取还是会阻塞/超时。
我怀疑是不是libusb_interrupt_transfer不适合用来连续读取多个中断包?但又不知道有什么更合适的替代API来处理这种场景,希望有经验的朋友能指点一下,谢谢!
内容来源于stack exchange
相关产品推荐
相关产品推荐

