基于WinUSB的异步方式bulk传输的稳定性问题

某项目中,设备与PC之间通过USB Bulk模式进行数据传输,PC端的APP跑在Win10上,跟设备通信这部分原本是基于libusb开发的,运行稳定。后来考虑到PC端APP只有for Windows一个版本,使用libusb的意义不大(libusb最大的好处是跨平台),因此打算去掉libusb,直接基于微软WinUSB实现与设备通信(在Windows上libusb缺省也是基于WinUSB实现的)。

libusb中用于bulk通信的API函数libusb_bulk_transfer有一个timeout参数,去掉libusb后直接调用WinUSB的API函数WinUsb_ReadPipe和WinUsb_WritePipe来实现bulk读写,但是这两个函数没有timeout参数,缺省方式调用这两个函数如果没有完成操作(例如WinUsb_ReadPipe一直读不到数据)就会无限期等待而不返回,这不符合我们的要求。不过这两个函数都提供了一个Overlapped参数用于实现异步操作方式,标准调用流程如下(以bulk读为例):

DWORD WinUSBBulkRead(WINUSB_INTERFACE_HANDLE hWinusb, UCHAR endpoint, UCHAR *data, DWORD length, DWORD timeout)
{
    DWORD ret = ERROR_SUCCESS;
    OVERLAPPED ov;
    DWORD n;

	ResetEvent(&eventReadPipe);
	memset(&ov, 0, sizeof(ov));
	ov.hEvent = eventReadPipe;

    if (!WinUsb_ReadPipe(hWinusb, endpoint, data, length, NULL, &ov)) {
        ret = GetLastError();
        if (ret == ERROR_IO_PENDING) {
            ret = WaitForSingleObject(eventReadPipe, timeout);
            if (ret == WAIT_OBJECT_0) {
                ret = ERROR_SUCCESS;
            }
            else if (ret == WAIT_TIMEOUT) {
                ret = ERROR_TIMEOUT;
            }
            else {
                ret = GetLastError();
            }
        }
    }

    if (ret == ERROR_SUCCESS) {
        if (!WinUsb_GetOverlappedResult(hWinusb, &ov, &n, FALSE)) {
            ret = GetLastError();
        }
    }

    return ret;
}

然而上面这段代码在实际运行中发现不稳定,跑一段时间以后经常会出现接收超时,网上查到的参考代码也都是这么写的,不知道问题在哪里。查看libusb源码中调用WinUSB的部分,在调用WinUsb_ReadPipe和WinUsb_WritePipe时用的也是Overlapped方式,但对timeout的处理不太一样,因代码太复杂,没有时间仔细看。这时在微软文档上看到WinUsb_SetPipePolicy可以设置的Policy里面有一个PIPE_TRANSFER_TIMEOUT,之前初始化WinUSB调用WinUsb_SetPipePolicy设置Policy时这个PIPE_TRANSFER_TIMEOUT设的是0,从文档描述看这个值如果设成非0就可以实现我们想要的timeout的效果,而WinUsb_ReadPipe和WinUsb_WritePipe那里不再使用Overlapped方式,代码也因此更简单。试了一下果然可以,而且运行很稳定。

微软文档里对将PIPE_TRANSFER_TIMEOUT设成非0值有一个说明:
A minor performance penalty will occur due to timer management.
但是实际测下来的性能比之前用libusb还要更好一些,能满足我们的要求。

 

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值