注意事项(Caveats)

 

设备复位

libusb_reset_device() 函数允许你复位一个设备。 如果你的程序已经调用了这个函数,需要注意的一点是复位将会导致设备状态的改变(如:寄存器的值也许会被复位)。

问题在于任何时候任何其他的程序都可能会复位你的程序正在使用的设备。libusb并没有提供当复位发生时可以通知你的机制 ,所以如果有其他人复位了你的设备,你自己的程序将不清楚为什么设备状态改变了。

最后,这是一个在用户空间编写驱动所受的限制。由于来自位于低层内核的USB栈的隔离,使得系统很难传递这样一个消息通知你的程序。Linux内核的 USB栈允许这样一个复位 消息被传递给内核中的USB驱动,但是,如何将这样的消息传递给存在于用户空间的二级驱动仍没有可行的方法。

阻塞操作

下面列出的功能仅能通过同步方式使用,属于阻塞函数。没有异步/非阻塞的方式,而且没有什么好的方法可以实现它们。

不支持热拔插

libusb-1.0缺乏当设备插入或移除操作时提供通知的功能。这个功能计划在libusb-1.1中实现。

这就是说,对于打开的设备句柄,只有基本的断开处理:

  • 如果存在正在执行的传输, libusb的handle_events 循环将会检测到断开并且以LIBUSB_TRANSFER_NO_DEVICE状态代码结束正在执行的传输。
  • 很多函数如 libusb_set_configuration() 在当设备已经被断开连接时,返回特定的 LIBUSB_ERROR_NO_DEVICE 错误代码。

配置选择和处理

当libusb为一个程序提供了一个设备句柄,存在一种可能的情况,相应的设备处于为配置状态。多配置设备,同样有一种可能当前选择的配置并不是应用程序要使用的。

很明显解决方法就是增加一个调用libusb_set_configuration() 在你的设备初始化例程,但是有以下注意事项:

  1. 如果设备已经处于所期望的配置,使用相同的配置调用libusb_set_configuration() 将会引起一个轻量级的复位。 这可能不是一个期望的行为。
  2. 如果设备处于另一个配置并且其他程序或驱动已经在该配置下声明了接口,libusb将不能改变配置。
  3. 在所期望的配置被启用的情况下,libusb可能甚至不能执行一个轻量级的复位。例如,拿我带指纹读取功能的USB键盘来说:我很想使用libusb来驱动指纹读取器 ,但是内核的USB-HID驱动几乎总是已经声明了键盘接口。由于内核已经声明了一个接口,执行一个轻量级的复位甚至是不可能的。所以libusb_set_configuration() 将会失败。 (幸运的是,有问题的设备只有一个单一配置)

一个解决以上问题的解决方案是考虑当前启用的配置。如果当前是我们想要的配置,我们不需要选择任何配置:

cfg = libusb_get_configuration(dev);

if (cfg != desired)

    libusb_set_configuration(dev, desired);

对大部分情况来说这也许时最适合的,但不是最好的:另一个应用程序或者驱动也许会在调用libusb_get_configuration() 改变被选择的配置。

甚至在某些调用 libusb_set_configuration() 成功的情况下,想象其他的应用程序和驱动也许会在你的应用程序调用libusb_set_configuration()后改变配置。

一个可行的锁定特定的配置的方法如下:

  1. 设置需要的配置 (或者使用上面提供的方法判断已经是需要的配置)
  2. 声明你希望使用的接口
  3. 检查当前启用的配置是否是你所期望使用的

以上的方法之所以有效是因为一个接口一但被声明,没有应用程序或驱动可以选择另一个配置。

提前的传输完成

注意: 这段是以Linux为主的。我不确定是否适用于Darwin和其他平台。.

当一个传输提前结束(例如:在任何一个包中,当少于传输缓冲区要求的数据被接收或者发送时),这种情况libusb被设计成直接结束传输,除非用户将其他传输放置到队列中,否则都不会再传输或者接收任何数据。

在原有的平台, libusb在所有的平台下都无法做到。在一个不完整的包出现后, "多余的" 数据可能会被传输。在libusb v1.0.2之前,这个信息是丢失的(并且对于device-to-host 传输,相应的数据是被丢弃的)。 到了libusb v1.0.3,这个信息是被保留的。this information is kept (传输的数据长度会被更新) ,并且对于device-to-host传输,任何多余的数据都会被增加到缓冲区。但是,这不是一个很好的解决方案,因为它会丢失短数据包的结束信息。 而且,用户可能想让多余的数据在下个逻辑传输时到达。

先前的解决方法只是提交大小为16kb或者更少的数据。

等到libusb v1.0.4和Linux v2.6.32,这个问题被解决了。 对这一问题的技术解释如下:

当你让libusb提交体积大于16kb的块传输时,libusb将它分解为一系列更小的子传输。这是因为usbfs内核接口只接受最大16kb的传输。这些子传输会被一次全部提交,以便于内核能在硬件层面上使其队列化,因此是总线吞吐量最大化。

在原有平台上, 在这一事件上当传输提前完成时会引起问题,内核将会结束所有在那个子传输中的将要到来的包 (但不是任何接下来的子传输)。libusb将会注意到这个事件,并且直接取消已经在队列中的接下来的子传输 ,但是libusb通常并非足够快,在libusb抽出时间去取消它们的时候,子传输很可能已经开始了

感谢usbfs的API扩展,最近的内核和libusb发布版本修复了这个问题。这个解决方案允许libusb在逻辑层面的libusb-level间的传输时使用临界区与内核通信。当一个短数据传输(或者其他错误) 发生时,在没有允许这些传输开始前,内核将取消所有的子传输,直到临界区结束。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值