USB论坛
直播中

杨静

8年用户 1526经验值
私信 关注
[问答]

如何检测USB设备IN端点缓冲区内是否存在待传输的数据?

我需要调用 USBDevice->BulkInEndPt->XferData 来获取 USB IN 缓冲区的数据大小(按字节),但这样做会导致数据被传递到主机。目前,我打算先判断 USB IN 是否存在数据,再执行后续获取数据的步骤,但一旦调用 USBDevice->BulkInEndPt->XferData,就无法再次获取数据。是否有其他 USB API 可以实现我的这一功能?#CYUSB3KIT-003           

回帖(1)

gvxiaot

2025-7-30 18:04:05

在 Cypress CYUSB3KIT-003/EZ-USB FX3 SDK 的 CyAPI 库中,没有直接查询 USB IN 端点缓冲区数据状态(不触发传输)的 API。所有数据读取操作(如 XferData)都会发起传输。以下是实现目标的替代方案:




推荐解决方案:短时等待 + 传输尝试


使用非阻塞的 短时等待(Short Timeout) 配合 XferData,避免阻塞主线程:


CCyBulkEndPoint* inEndPt = USBDevice->BulkInEndPt;
inEndPt->SetTimeOut(1);  // 设置超时为1毫秒(非阻塞)

LONG length = BufferSize;  // 缓冲区大小
UCHAR* buffer = new UCHAR[BufferSize];

if (inEndPt->XferData(buffer, length)) {
    if (length > 0) {
        // 成功读取到数据,处理数据
        ProcessData(buffer, length);
    } else {
        // 收到零长度包(设备无数据)
    }
} else {
    DWORD error = GetLastError();
    if (error == ERROR_IO_TIMEOUT) {
        // 超时:端点无数据
    } else {
        // 其他错误处理
    }
}

delete[] buffer;



高级方案:异步传输(Overlapped I/O)


通过异步操作检查传输是否立即完成:


CCyBulkEndPoint* inEndPt = USBDevice->BulkInEndPt;
OVERLAPPED ov;
HANDLE hEvent = CreateEvent(NULL, true, false, NULL);
ov.hEvent = hEvent;

LONG length = BufferSize;
UCHAR* buffer = new UCHAR[BufferSize];

inEndPt->BeginDataXfer(buffer, length, &ov);
if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) {
    // 传输已完成(有数据)
    inEndPt->FinishDataXfer(buffer, length, &ov);
    ProcessData(buffer, length);
} else {
    // 传输未完成 -> 无数据
    CancelIo(inEndPt->hDevice);  // 取消传输
}
CloseHandle(hEvent);
delete[] buffer;



关键注意事项



  1. 硬件限制

    USB 协议规定数据只能通过主机主动请求传输(IN Token)。无预先查询机制

  2. 固件配合

    确保设备固件在无数据时返回 NAK(自动由FX3处理),避免虚假超时。

  3. 超时设定  

    • 短超时(1-10ms)适合实时性高的场景。

    • 长超时适合等待设备响应。


  4. 零长度包

    设备发送 Zero-Length Packet (ZLP) 表示数据传输结束(不一定是错误)。




为何没有直接查询API?


USB 协议要求主机主动发起 IN 请求才能获取设备状态。调用 XferData 本质是发送 IN Token 并等待响应。设备在无数据时返回 NAK(被 SDK 处理为超时/错误)。



结论:通过设置短超时 + 检查 ERROR_IO_TIMEOUT 是最接近查询功能的方法,且无需固端修改。


举报

更多回帖

发帖
×
20
完善资料,
赚取积分