首页 文章

为什么我不能从WinUsb_ReadIsochPipeAsap获得全部带宽?

提问于
浏览
1

我一次在飞行中有多个 WinUsb_ReadIsochPipeAsap ,并且只要 WinUsb_GetOverlappedResult 成功完成第一个就排队 . 根据documentation

WinUsb_ReadIsochPipeAsap允许USB驱动程序堆栈选择传输的起始帧编号 . 如果 endpoints 上已有一个或多个传输已暂挂,则将在最后一个当前待处理传输的最后一个帧编号之后紧接着帧编号进行传输 .

(重点补充)

当我测量主机上的数据速率(读取完成率)时,我只看到6ms(每第6帧)的轮询速率,即使描述符 bInterval1 ,并且6ms甚至不是可能的轮询间隔等时 endpoints . 该文档让我觉得我应该在每一帧都看到转移,因为我总是有多个挂起转移 .

如果我用USB分析仪查看总线,我从设备上看不到任何 IN-NAK ,所以我怀疑Windows甚至没有提出请求 .

为什么我看不到完整的1000Hz传输速率?

1 回答

  • 1

    WinUsb_ReadIsochPipeAsap 的参数:

    BOOL __stdcall WinUsb_ReadIsochPipeAsap(
      _In_     PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle,
      _In_     ULONG                       Offset,
      _In_     ULONG                       Length,
      _In_     BOOL                        ContinueStream,
      _In_     PULONG                      NumberOfPackets,
               PUSBD_ISO_PACKET_DESCRIPTOR IsoPacketDescriptors,
      _In_opt_ LPOVERLAPPED                Overlapped
    );
    

    根据documentationContinueStream 的含义是:

    ContinueStream [in]表示只有在最后一次挂起转移后的第一帧中可以安排转移时才应提交转移 .

    (重点补充)

    这是事实 . 例如,如果您第一次调用 WinUsb_ReadIsochPipeAsap 传递 TRUE ,则会得到 ERROR_INVALID_PARAMETER ,因为没有任何内容可以继续 . 如果允许超过1帧的时间(全速1ms)并传递 TRUE ,则会得到 ERROR_INVALID_PARAMETER ,因为"first frame after the last pending transfer"不再可用 .

    However ,尽管关于"first frame after the last pending transfer"是非常相似的语言是默认行为, the only way Windows will actually schedule the transfers to be in sequential frames is if ContinueStream is set to TRUE . 你调用 WinUsb_ReadIsochPipeAsap 的速度和你做多少重叠的呼叫并不重要 .

    解决方案是始终尝试 ContinueStream ,但是如果出现故障则回退到不继续(否则在第一次失败之后你将永远失败 ContinueStream ):

    ContinueStream = FALSE;
    
    while (...)
    {
        if ( !WinUsb_ReadIsochPipeAsap( ..., ContinueStream, ... ) )
        {
            DWORD lastError = GetLastError();
    
            if ( lastError == ERROR_INVALID_PARAMETER && ContinueStream)
            {
                ContinueStream = FALSE;
                continue;
            }
        }
        ContinueStream = TRUE;
        ...
    }
    

    或者,您可以重写循环以使用 WinUsb_ReadIsochPipe (非ASAP版本),但这只需要您自己管理顺序帧编号 .

相关问题