libusb注意事项笔记

1、线程安全

libusb 被设计为完全线程安全的,但与任何 API 一样,它无法阻止用户故意或无意地破坏自己。

请遵循以下一般准则:

  • 释放资源的函数(例如libusb_close()libusb_free_config_descriptor())不应在同一资源上同时调用。这与在同一分配的指针上同时调用 free() 没什么不同。

  • 每个单独的libusb_transfer都应由单个线程准备。换句话说,任何两个线程都不应同时填写libusb_transfer的字段。您可以将其比作从多个线程使用同一目标缓冲区调用 sprintf()。除非输入参数全部相同,否则结果可能不是您想要的,但最好完全避免这种情况。

  • 在传输提交和调用完成回调之间,不应访问libusb_transfer结构及其相关数据缓冲区。你可以认为在传输处于活动状态时,这些东西的"所有权"被转移给了 libusb。

  • 不应同时在资源上调用各种"setter"函数(例如libusb_set_log_cb()libusb_set_pollfd_notifiers())。虽然这样做不会导致任何未定义的行为,但可能会产生应用程序不期望的结果。

2、fork注意事项

ibusb并非设计用于跨 fork() 调用工作。根据平台的不同,父进程中可能存在子进程无法使用的资源(例如 Linux 上的热插拔监视器线程)。

3、设备重置

libusb_reset_device()函数允许你重置设备。如果你的程序必须调用这样的函数,显然应该意识到重置将导致设备状态改变(例如寄存器值可能会被重置)。libusb 不提供一种机制来通知您,如果其他人重置了您的设备,您自己的程序将不清楚设备状态发生变化的原因。

4、只有阻塞实现的函数

下面列出的功能只能通过同步、阻塞函数实现。没有异步/非阻塞替代方案,也没有明确的实现方法。

5、配置选择和处理

对于具有多个配置的设备,当前选择的配置也可能不是应用程序想要使用的配置。

显而易见的解决方案是在设备初始化例程的早期添加对libusb_set_configuration()的调用,但需要注意一些事项:

  • 如果设备已经处于所需配置,则使用相同配置值调用libusb_set_configuration()将导致轻量级设备重置。这可能不是理想的行为。

  • 如果所需配置已处于活动状态,libusb 甚至可能无法执行轻量级设备重置。例如,以我的带指纹读取器的 USB 键盘为例:我有兴趣通过 libusb 驱动指纹读取器接口,但内核的 USB-HID 驱动程序几乎总是会声明键盘接口。由于内核已声明接口,因此甚至无法执行轻量级设备重置,因此libusb_set_configuration()将失败。(幸运的是,相关设备只有一个配置。)

  • 如果其他程序或驱动程序已声明接口,libusb 将无法设置配置。具体而言,这意味着在libusb_set_configuration()成功之前,内核驱动程序必须与所有接口分离。

解决上述问题的一个方法是考虑当前活动的配置。如果我们想要的配置已经处于活动状态,那么我们不必选择任何配置:

cpp 复制代码
cfg = -1;
libusb_get_configuration(dev, &cfg);
if (cfg != desired)
    libusb_set_configuration(dev, desired);

这可能适用于大多数场景,但本质上是危险的:另一个应用程序或驱动程序可能会在libusb_get_configuration()调用之后更改所选的配置。

即使在libusb_set_configuration()成功的情况下,也请考虑在您的应用程序调用libusb_set_configuration()后其他应用程序或驱动程序可能会更改配置。

将设备锁定为特定配置的一种可能方法如下:

  • 设置所需的配置(或使用上面的逻辑来实现它已经处于所需的配置)
  • 声明您希望使用的接口
  • 检查当前活动配置是否是您想要使用的配置。

上述方法之所以有效,是因为一旦声明了接口,任何应用程序或驱动程序都无法选择其他配置。

6、零长度数据包

  • libusb 能够通过提交零长度的传输来向端点发送零长度的数据包。

  • LIBUSB_TRANSFER_ADD_ZERO_PACKET标志目前在 Linux、Darwin 和 Windows(WinUSB)上受支持。

相关推荐
冰山一脚20135 个月前
libspice显示命令调用流程分析
spice
冰山一脚20131 年前
spice VDAgent简介
spice