You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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错误。

我的排查尝试

  1. 用USB抓包工具监控总线,发现设备已经把所有的回复包都发送给主机了,但代码就是无法读取到第二个及以后的包;
  2. 尝试把读取用的buffer数组改大(比如改成256字节),但问题依然存在,第二次读取还是会阻塞/超时。

我怀疑是不是libusb_interrupt_transfer不适合用来连续读取多个中断包?但又不知道有什么更合适的替代API来处理这种场景,希望有经验的朋友能指点一下,谢谢!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 11:50:31