Uhubctl –在智能USB集线器上控制每个端口的USB电源

2020-12-13 18:14:10

uhubctl是用于控制智能USB集线器上每个端口的USB电源的实用程序。智能集线器定义为实现每个端口电源切换的设备。

请注意,实际上很少有集线器支持每个端口的电源交换,其中一些不再制造并且很难找到。

该表绝不是完整的。如果您的集线器可与uhubctl一起使用,但未在上面列出,请通过在https://github.com/mvp/uhubctl/issues中打开新问题进行报告,以便将其添加到支持的表。在您的报告中,请提供确切的产品型号并添加uhubctland的输出,请按照常见问题解答中的以下说明测试VBUS关闭支持。

请注意,相当多的现代主板具有支持此功能的内置根集线器-您甚至不需要购买任何外部集线器。

如果您将USB 3.0集线器连接到USB3上游端口,它将被检测为2个独立的虚拟集线器:USB2和USB3,并且您的USB设备将根据其功能和连接速度连接到USB2或USB3虚拟集线器。集线器,必须关闭/打开USB2和USB3虚拟集线器的电源,以使电源关闭/打开更改生效。 uhubctl将尝试自动执行此操作(除非您使用选项-e禁用此行为)。

不幸的是,尽管大多数集线器会断开数据USB连接,但有些集线器可能仍无法断开VBUS到端口的连接,这意味着所连接的电话可能仍会继续从uhubctl断电的端口继续充电。

该实用程序经过了测试,可以在Linux(Ubuntu / Debian,Redhat / Fedora / CentOS,Arch Linux,Gentoo,openSUSE,Buildroot),FreeBSD,NetBSD,SunOS和MacOS上编译和运行。

尽管uhubctl在Windows上编译,但USB电源切换在Windows上不起作用,因为libusbis使用winusb.sys驱动程序,根据Microsoft的说法,该驱动程序不支持必要的USB控制请求。如果libusb开始在Windows上支持其他驱动程序,则可以修复此问题。

请注意,强烈建议安装pkg-config(许多平台默认提供)。

首先,您需要安装库libusb-1.0(版本1.0.12或更高版本,建议使用1.0.16或更高版本):

要编译,只需运行make-这将生成uhubctl二进制文件。请注意,在某些操作系统(例如FreeBSD / NetBSD)上,您需要使用gmake进行编译。

这意味着在默认的智能集线器上运行并关闭端口2(-p 2)的电源(-a关闭或-a 0)。支持的操作为关闭/打开/循环(或0/1/2)。循环意味着关闭电源,等待一些延迟(可通过-d配置)然后重新打开。端口可以是逗号分隔的列表,并且可以使用-表示范围,例如2或2,4或2-5或1-2,5-8。

⚠️关闭内置USB端口可能会切断键盘或鼠标,因此请注意要关闭哪些端口!

如果连接了多个智能USB集线器,则应使用-l(位置)参数选择特定的集线器进行控制。要找到集线器位置,只需运行不带任何参数的uhubctl。集线器位置类似于bx.yz,其中b是USB总线数字和x,y,z ...是链中所有集线器的端口号,从给定USB总线的根集线器开始。此地址是半稳定的-如果拔出/重新插入(或关闭),则该地址不会更改/ on)将USB设备插入相同的物理USB端口(Linux内核中也使用此方法)。

在Linux上,您应该配置udev USB权限(否则必须使用sudo uhubctl以root身份运行它)。要修复USB权限,请先运行sudo uhubctl并注意所有vid:pid所需要控制的集线器,然后添加一个或更多类似下面的udev规则来归档/etc/udev/rules.d/52-usb.rules(替换为您的供应商ID):

请注意,对于USB3集线器,某些集线器对同一芯片的USB2和USB3组件使用不同的供应商ID,并且两个集线器都需要具有权限才能使uhubctl正常工作。例如。对于Raspberry Pi 4B,您需要添加以下两行:

如果您不喜欢全开模式0666,则可以按组限制访问,如下所示:

根据USB 2.0规范,USB集线器不能通告任何电源切换,成组(所有端口一次)电源切换或每个端口(单个)电源切换。请注意,uhubctl仅会检测支持每个端口电源切换的USB集线器。通过使用sudo lsusb -v可以找到您的硬件支持哪种电源切换:

运行sudo uhubctl。如果未列出您的集线器,则不支持该集线器。或者,您可以运行sudo lsusb -v并检查每端口电源切换-如果在lsusb输出中看不到该行,则不支持集线器。

检查是否支持VBUS(电压)关闭:将电话,USB照明器或USB风扇插入集线器的USB端口。尝试使用uhubctl关闭该端口的电源,然后检查电话是否停止充电,USB指示灯停止闪烁或USB风扇停止旋转如果VBUS无法关闭,则您的集线器制造商未提供实际切断电源的电路。这样的集线器仍然可以断开USB数据连接,但无法关闭电源,因此我们不考虑此支持的设备。

如果以上测试成功,请在https://github.com/mvp/uhubctl/issues上打开新版本报告您的中心,以便我们将其添加到支持的设备列表中。

关闭USB端口电源后,udev不会发生任何事件,因此会保留设备文件,但是尝试访问设备文件将导致IO错误。

这是Linux内核问题。它可能最终会在内核中修复,请参见此处的更多讨论。基本上,这里发生的是内核USB驱动程序知道关闭电源,但不会将有关它的通知发送给udev。

设备文件将被udev删除,但USB设备在lsusb中仍然可见。请注意,路径/sys/bus/usb/devices/${location}。${port}仅在该端口上检测到设备时存在。重新打开电源后,设备应正确重新枚举(无需再次调用udevadm)。

USB设备被关闭并自动尝试重新打开电源后,内核中的某些设备驱动程序会感到惊讶。

您可以使用-r N选项(其中N是从10到1000的某个数字)来解决此问题-uhubctl会尝试快速连续多次关闭电源,并且应该禁止这样做。最终可能会在内核中修复,请参见更多讨论这里。

在使用uhubctl关闭电源之前,为有问题的设备禁用USB授权应该可以:

如果您的设备是USB大容量存储,则在调用uhubctl之前调用udisksctl应该也有帮助:

许多集线器制造商使用基本的4端口USB芯片来构建其USB集线器。要制作7个端口集线器,它们将两个4端口集线器以菊花链方式连接-菊花链丢失了1个端口,因此它成为4 + 4-1 = 7端口集线器。同样,可以将10个端口集线器构建为3个4端口集线器,以菊花链方式链接在一起,从而提供4 + 4 + 4-2 = 10个可用端口。

请注意,切勿尝试将用于将内部集线器以菊花链方式连接在一起的端口的电源状态更改为电源状态,否则会混淆内部集线器电路并导致不可预知的行为。

主集线器1-1,所有4个端口组合在一起,都由端口2控制(也关闭了辅助集线器端口)。端口1连接下面的集线器1-1.1,端口2和3外部布线,端口4不布线。

备用集线器1-1.1(以菊花链方式连接到主集线器):3个端口,端口1用于以太网+ WiFi,端口2和3连接到外部。

⚠️如果您的VL805固件版本早于00137ad(请使用sudo rpi-eeprom-update检查),则必须更新固件才能在RPi 4B上进行电源切换。

解决方法是,您可以从支持的列表中购买任何外部USB集线器,将其连接到Raspberry Pi的任何USB端口,并独立控制其端口的电源。

可以根据GNU通用公共许可证版本2的条款和条件分发此文件。