USB OTG 设备在拔出并重新插入后不工作
USB OTG device does not work after unplugging and replugging
我正在尝试连接 Android 上的 USB OTG 设备。由于代码有点长,我就简单概括一下:
- 清单中声明了一个 activity,其中包含
USB_DEVICE_ATTACHED
的 Intent 过滤器(针对我感兴趣的设备 ID 进行过滤)。
- 当 activity 以该特定意图启动时,它会启动一项服务并将 USB 设备作为参数传递。
- 服务启动时,它会为
USB_DEVICE_DETACHED
注册一个广播接收器,然后连接到设备并开始与其交互(当前生成一些日志输出)。
- 当收到 USB 断开连接广播时并且设备是当前正在使用的设备,
close()
在 USB 设备连接上被调用并且服务停止。
该设备是一个 Si4701 USB FM 调谐器,显示为 USB HID 设备。
当我第一次插入设备时,我看到我的服务连接到它,可以更改频道并接收 RDS 数据。
然而,当我拔下它并重新插入时,我看到服务再次连接到它(显然再次成功读取设备寄存器),但它无法更改频率并且我从未看到任何 RDS 数据。
如果我强制应用程序在拔出和重新插入设备之间停止,设备在重新插入后可以正常工作。
这表明某些清理工作未能进行,或者某些资源未正确释放。然而:
- 我没有在连接之间保留任何与设备相关的数据结构。与 USB 连接相关的所有内容都在检测到设备时创建的 class 实例中,并且这些 classes 的所有静态成员都是最终的。
- 有些事情在重新插入设备后会起作用,例如读取设备类型和固件版本的寄存器(通过获取 USB HID 功能报告起作用)。初始化还设置了一些寄存器(通过发送 USB 功能报告),这不会 return 错误 — 但更改频率(也涉及设置寄存器)不起作用。
- 拔出和重新插入之间约 15 分钟的间隔无效(设备不工作)。另一方面,如果我拔下设备,终止服务并重新插入,它会立即工作——所以问题肯定在 Android 端,而不是在设备端。
我需要做什么才能使 USB 设备在 unplug/replug 周期后正常工作?
我仍然不完全明白这里发生了什么,但现在似乎可以工作了。
我应该提到该应用程序是多线程的,Si470x 包装器 class 从多个线程调用。
由于这导致了竞争条件(一个线程在另一个线程刚刚关闭设备时访问该设备),我正确地将所有方法声明为 synchronized
以便没有两个线程可以访问调谐器的方法 class同时。插入设备,拔掉它,再重新插入——你瞧,它改变了频率并按照预期的方式吐出 RDS 数据。
怀疑:
UsbDeviceConnection#close()
可能不是线程安全的。
结论:
- 总是在使用完设备后调用
UsbDeviceConnection#close()
(包括分离设备时)。
- 如果您的应用程序是多线程的,请确保访问您的 USB 连接(直接或间接)的所有内容都已正确同步。
我正在尝试连接 Android 上的 USB OTG 设备。由于代码有点长,我就简单概括一下:
- 清单中声明了一个 activity,其中包含
USB_DEVICE_ATTACHED
的 Intent 过滤器(针对我感兴趣的设备 ID 进行过滤)。 - 当 activity 以该特定意图启动时,它会启动一项服务并将 USB 设备作为参数传递。
- 服务启动时,它会为
USB_DEVICE_DETACHED
注册一个广播接收器,然后连接到设备并开始与其交互(当前生成一些日志输出)。 - 当收到 USB 断开连接广播时并且设备是当前正在使用的设备,
close()
在 USB 设备连接上被调用并且服务停止。
该设备是一个 Si4701 USB FM 调谐器,显示为 USB HID 设备。
当我第一次插入设备时,我看到我的服务连接到它,可以更改频道并接收 RDS 数据。
然而,当我拔下它并重新插入时,我看到服务再次连接到它(显然再次成功读取设备寄存器),但它无法更改频率并且我从未看到任何 RDS 数据。
如果我强制应用程序在拔出和重新插入设备之间停止,设备在重新插入后可以正常工作。
这表明某些清理工作未能进行,或者某些资源未正确释放。然而:
- 我没有在连接之间保留任何与设备相关的数据结构。与 USB 连接相关的所有内容都在检测到设备时创建的 class 实例中,并且这些 classes 的所有静态成员都是最终的。
- 有些事情在重新插入设备后会起作用,例如读取设备类型和固件版本的寄存器(通过获取 USB HID 功能报告起作用)。初始化还设置了一些寄存器(通过发送 USB 功能报告),这不会 return 错误 — 但更改频率(也涉及设置寄存器)不起作用。
- 拔出和重新插入之间约 15 分钟的间隔无效(设备不工作)。另一方面,如果我拔下设备,终止服务并重新插入,它会立即工作——所以问题肯定在 Android 端,而不是在设备端。
我需要做什么才能使 USB 设备在 unplug/replug 周期后正常工作?
我仍然不完全明白这里发生了什么,但现在似乎可以工作了。
我应该提到该应用程序是多线程的,Si470x 包装器 class 从多个线程调用。
由于这导致了竞争条件(一个线程在另一个线程刚刚关闭设备时访问该设备),我正确地将所有方法声明为 synchronized
以便没有两个线程可以访问调谐器的方法 class同时。插入设备,拔掉它,再重新插入——你瞧,它改变了频率并按照预期的方式吐出 RDS 数据。
怀疑:
UsbDeviceConnection#close()
可能不是线程安全的。
结论:
- 总是在使用完设备后调用
UsbDeviceConnection#close()
(包括分离设备时)。 - 如果您的应用程序是多线程的,请确保访问您的 USB 连接(直接或间接)的所有内容都已正确同步。