序章
完璧な世界では、 USB デバイスと hubs は適切に動作し、遭遇した問題を解決することができます。実際には、あらゆる種類の奇妙なことが起こり、それを何とかする必要があります。一般的な解決策は、 USB プラグを抜いて、デバイスを再度接続することです。しかし、これが自動的に行われる必要がある場合はどうでしょうか?
最も劇的な解決策は、 別の Web ページで紹介されています。 USB hubの driversのシャットダウンと再起動が発生します。この効果は、コンピューター上のすべての USB デバイスを切断して再接続するのとほぼ同じです。それは最も重いハンマーであり、時には必要です。
このページでは、1 つの特定の USB デバイスをリセットする 2 つの方法を紹介します。まず、いくつかの最小限の説明を加えて、各方法を実行する方法を紹介します。この後、多くの技術的な詳細に入ります。
ここで紹介する 2 番目の方法はおそらく他のプラットフォームでも可能ですが、ここでは説明全体を Linux に限定します。
ここでの多くの情報は、 Universal Serial Bus Specification Revision 2.0から取得されます。このドキュメントのファイル名は通常 usb_20.pdfです。
方法 #1: Linux kernel にデバイスのリセットを依頼する
これを行うために使用できるツールがいくつかあります。最も高度なツールは usbutilsの一部です。 usbreset.c をダウンロードし、その compilationに gcc を使用します。
$ gcc -O3 -Wall -g usbreset.c -o usbreset
その後:
$ ./usbreset Usage: usbreset PPPP:VVVV - reset by product and vendor id usbreset BBB/DDD - reset by bus and device number usbreset "Product" - reset by product name Devices: Number 001/004 ID 045e:07b2 Microsoft® Nano Transceiver v1.0 Number 001/002 ID 04f3:0103 $ ./usbreset 001/004 Resetting Microsoft® Nano Transceiver v1.0 ... can't open [Permission denied] $ sudo ./usbreset 001/004 Resetting Microsoft® Nano Transceiver v1.0 ... ok $ sudo ./usbreset 045e:07b2 Resetting Microsoft® Nano Transceiver v1.0 ... ok
リセットに応じて、 kernel logに次のように表示されます。
usb 1-6: reset full-speed USB device number 4 using xhci_hcd
このセッションの内容:
- argumentsがない場合、 usbreset は USB デバイスのリストで応答します。 lsusbでも同じ情報が得られます。
- 実際にデバイスをリセットするには、 root である必要があります (したがって、 sudo)。
- デバイスは、その bus address (bus number および device number) によって選択できます。 bus address は、デバイスが接続されるたびに変化することに注意してください。
- デバイスは、その Vendor / Product IDsによって選択することもできます。これは、同じ種類の USB デバイスが 1 つしかない場合に推奨される方法です。
- デバイスは、 USB bus でそのアドレスを変更しませんでした (リセットの結果として再列挙されませんでした)。
では、 usbreset は何をするのでしょうか? USB デバイスの device fileでは、次のコマンドに要約されます。
ioctl(fd, USBDEVFS_RESET, 0)
これは、デバイスをリセットするだけでなく、 kernelの usb_reset_device()への関数呼び出しで終わります。アイデアは、プロセス全体をスムーズにすることです。 この関数は、要求があった場合、デバイスの driver にリセットの前後に通知します。リセット前に driver のバインドを解除し、後でバインドし直します。デバイスの configuration もリセット後にロードされます。これがないと、デバイスは bus address を認識できず、データ交換の準備ができません。
つまり、デバイスを再接続するのとほぼ同じですが、(情報が既にわかっているため) デバイス自体の識別を求めたり、新しいアドレスを割り当てたりする必要はありません。
USB 3.xの場合、これは hot resetであり、効率の低いタイプです。 hot reset の詳細については、以下をご覧ください。
方法 #2: USB portの power state を切り替えます
この目的のためのツールもいくつかあります。この方法を hubpowerでデモンストレーションします。 hubpower.cをダウンロードし、 compilationを実行します。
$ gcc -O3 -Wall -g hubpower.c -o hubpower
コマンドが USB デバイス自体に送信されないため、このツールを使用するのはやや複雑です。代わりに、 USB デバイスが接続されている USB hub に要求が送信されます。
したがって、最初のステップは、これがどの hub であるかを把握することです。まず、 USB デバイスのアドレスを見つけてみましょう。
$ lsusb Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 004: ID 045e:07b2 Microsoft Corp. Bus 001 Device 002: ID 04f3:0103 Elan Microelectronics Corp. ActiveJet K-2024 Multimedia Keyboard Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
したがって、デバイスは bus number 1 と device number 4にあります。 USB デバイスが列挙されるたびに device number が変更されることに注意してください。
では、 USB デバイスはどの hub に接続されているのでしょうか?そして、どの portに?
$ lsusb -t /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 5000M /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M |__ Port 6: Dev 4, If 0, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 6: Dev 4, If 1, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 6: Dev 4, If 2, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 11: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M |__ Port 11: Dev 2, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M
したがって、デバイス番号 4 は port #6に接続されます。 hubの bus number は 1 で、その device number は 1 です ( root hubとして機能する motherboardの USB controllerです)。
hubpower がこれについて何と言っているか見てみましょう:
$ sudo ./hubpower 1:1 status
Port 1 status: 0100 Power-On
Port 2 status: 0100 Power-On
Port 3 status: 0100 Power-On
Port 4 status: 0100 Power-On
Port 5 status: 0100 Power-On
Port 6 status: 0103 Power-On Enabled Connected
Port 7 status: 0100 Power-On
Port 8 status: 0100 Power-On
Port 9 status: 0100 Power-On
Port 10 status: 0100 Power-On
Port 11 status: 0303 Low-Speed Power-On Enabled Connected
Port 12 status: 0100 Power-On
「1:1」の部分は hubの bus addressであることに注意してください。これが外部 hubの場合、この address は、 hub がコンピューターに接続されるたびに変更されます。
ただし、 ports の番号は変更されません (デバイスが同じ物理 portに接続されている限り)。
デバイスの port numberがわかったら、リセットします。
$ sudo ./hubpower 1:1 power 6 off Port 6 status: 0000 Power-Off $ sudo ./hubpower 1:1 power 6 on Port 6 status: 0100 Power-On
最初のコマンドの後、 kernel logでデバイスが切断されたと報告されます。
usb 1-6: USB disconnect, device number 4
2 番目のコマンドの後、コンピューターはデバイスが物理的に接続されているかのように動作します。
usb 1-6: new full-speed USB device number 5 using xhci_hcd
usb 1-6: New USB device found, idVendor=045e, idProduct=07b2, bcd Device= 7.04
usb 1-6: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-6: Product: Microsoft® Nano Transceiver v1.0
usb 1-6: Manufacturer: Microsoft
[ ... ]
この re-enumerationのため、新しい bus address がデバイスに割り当てられます。
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 005: ID 045e:07b2 Microsoft Corp.
Bus 001 Device 002: ID 04f3:0103 Elan Microelectronics Corp. ActiveJet K-2024 Multimedia Keyboard
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
これは USB デバイスを物理的に切断して接続し直すようなものですか?答えは多分: ほとんどの場合、 hubpower コマンドは実際には USB デバイスの電源をオフにしません。したがって、デバイスは引き続き VBUS voltage (5V) を受け取ります。実際に電源をオフにする USB hubs はほとんどありません。これについては、以下で詳しく説明します。
hubsの大部分では、最初のコマンド (「電源オフ」) は port をデバイスを無視する状態にするだけです。2 番目のコマンド (「電源オン」) は port を自然な状態に戻します。デバイスが検出され、その初期化手順が開始されます. とりわけ、デバイスがリセットされて列挙され、その driver がデバイスを初期化します.
そのため、特にデバイスが USB plugから電源供給を受けている場合は、通常、これらのコマンドよりも物理的な切断の方が効果的です。しかし、 hub が実際に VBUSをシャットダウンする場合、 hubpower は効果的です。
この例では、コマンドが motherboardの USB controller ( root hub) に送信されていることに注意してください。その理由は、 USB デバイスがコンピューターに直接接続されていたためです。このデバイスが外部 hubを介してコンピュータに接続されている場合、コマンドはこの外部 hubに送信される必要があります。どちらの場合も、 hubpower は同じように使用されます。
残念ながら、hubpower は USB 3.0 (SuperSpeed) をサポートしていません。詳細については、以下をご覧ください。
2 つの方法の違い
では、2 番目の方法 ( hubpowerを使用) と最初の方法 ( usbresetを使用) はどう違うのでしょうか?デバイスの問題を解決するために、どちらの方法も本質的に同じことを行います。 彼らはリセットコマンドを送信します。これが発生する方法は劇的に異なりますが、おそらく問題を解決するのはおそらくこのリセットコマンドです.
ただし、いくつかの重要な違いがあります。
- hubpower は、デバイスが busで認識されない場合でも機能します。たとえば、コンピューターがデバイスの列挙を数回試みた後、あきらめた場合です。この場合、デバイスはコンピュータに物理的に接続できますが、デバイスに bus addressがないため、 usbreset は役に立ちません。
- USB port が無効になる場合に役立つのは、 hubpower だけです。 この portでいくつかのエラーが発生した後、コンピュータが USB port を完全に無視することがあります。 hubpower はこれを解決するはずです。
- hubpower は SuperSpeed (USB 3.x) では動作しません。それはおそらくサポートを追加することの問題です。以下の SuperSpeed の詳細を参照してください。
- hubpower は、 USB デバイスの power supply を制御することもできます (ただし、通常はそうはなりません)。これは、デバイスが問題を解決するためにパワー リサイクルを必要とする場合に有利です。
- hubpower での作業はより困難です。 hubの ports のどれが USB デバイスに接続されているかを見つける必要があります。そして hubの bus addressも。
電装品の制御(?)
このページの主なトピックは USB デバイスの問題を修正する方法ですが、興味深い副作用もあります。 USB portの 5V power supplyを制御できる場合があります。つまり、シンプルで安価な USB hub を使用して、 2.5 Wattsを処理できる power supply のオンとオフを切り替えることができます。
これは、 electromechanical relayを制御するには十分すぎるほどです。したがって、 110V / 220Vで動作する電化製品を制御するために追加する必要があるコンポーネントは 1 つだけです。 USB hub を損傷から保護するために、単純なダイオードも追加することをお勧めします。しかし、それだけです。
残念ながら、 power supply を制御する機能はオプションです。 USB 2.0 仕様のセクション 11.11 によると、 hub には、 port が Powered-Off 状態にあるときに、 5V power supply を port にオフにする power switches がある場合があります。あるいは、 power switch を使用して複数の ports (「ganged power switching」) の電源を制御することもできます。電源を制御する主な目的は、過剰な電流を消費する USB デバイスを遮断して、残りの ports が引き続き正常に動作できるようにすることです。
ただし、既に述べたように、物理的な電力制御はオプションです。 hubpower が実際に行うことは、 portの PORT_POWER 属性の値を変更することです ( USB specificationsでは「feature」と呼ばれます)。この変更は、 hubの portの 2 つの異なる側面に関連しています。
- 必須: portの論理状態。 PORT_POWER がゼロの場合、 port は Powered-Off 状態 (または Not Configured) にのみなることができます。つまり、 hub は portに電圧がかかっていないかのように動作する必要があるため、接続されているデバイスが存在する場合は無視します。
- オプション: portの電源ワイヤ上の VBUS ( 5V 電圧) の存在。 hub がこの機能をサポートしていない場合、 PORT_POWER がゼロの場合でも電圧が存在する可能性があります。
PORT_POWER については、以下で詳しく説明します。
hub は電圧を制御しますか?
hub が実際に電圧をオフにするかどうかは、どうすればわかりますか?確実に知る唯一の方法は、テストすることです。 USB デバイスではなく、 USB portから電力を消費するものを接続します。実際の USB デバイスは混乱を招く可能性があります。たとえば、光学式マウスは通常、 5V 電圧が残っている場合でも、電源オフ コマンドに応答して LED をオフにします。
各 hub は、"lsusb -v" で表示される情報 (仕様のセクション 11.23.2.1 で定義されている Hub Descriptor内) で、電圧を制御するかどうか、およびどのような精度で制御するかを宣言します。 hub は、電圧を制御しないこと、または ports のグループ ("gangs") で電圧を制御すること、または各 port の電圧を個別に制御することを宣言できます。 USB 2.0 仕様のセクション11.11によれば、「a hub with power switches can switch power to all ports as a group/gang, to each port individually, or have an arbitrary number of gangs of one or more ports」。
ただし、この情報は信頼できません。電圧を制御すると宣言している hubs をいくつか見かけましたが、実際に制御しているものはありませんでした。
たとえば、これは「lsusb -v」の出力の
Bus 001 Device 073: ID 0bda:5411 Realtek Semiconductor Corp. Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.10 bDeviceClass 9 Hub bDeviceSubClass 0 Unused bDeviceProtocol 2 TT per port bMaxPacketSize0 64 idVendor 0x0bda Realtek Semiconductor Corp. idProduct 0x5411 bcdDevice 1.23 iManufacturer 1 Generic iProduct 2 4-Port USB 2.0 Hub iSerial 0 bNumConfigurations 1 Configuration Descriptor: [ ... ] Hub Descriptor: bLength 9 bDescriptorType 41 nNbrPorts 4 wHubCharacteristic 0x00a9 Per-port power switching Per-port overcurrent protection TT think time 16 FS bits Port indicators bPwrOn2PwrGood 0 * 2 milli seconds bHubContrCurrent 100 milli Ampere DeviceRemovable 0x00 PortPwrCtrlMask 0xff Hub Port Status: Port 1: 0000.0503 highspeed power enable connect Port 2: 0000.0503 highspeed power enable connect Port 3: 0000.0100 power Port 4: 0000.0100 power
楽観的ですね。実際、この hub は電圧をまったく制御しません。
対照的に、これは単純なマザーボードの hubです。
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 9 Hub bDeviceSubClass 0 Unused bDeviceProtocol 1 Single TT bMaxPacketSize0 64 idVendor 0x1d6b Linux Foundation idProduct 0x0002 2.0 root hub bcdDevice 4.15 iManufacturer 3 Linux 4.15.0-20-generic xhci-hcd iProduct 2 xHCI Host Controller iSerial 1 0000:06:00.0 bNumConfigurations 1 Configuration Descriptor: [ ... ] Hub Descriptor: bLength 9 bDescriptorType 41 nNbrPorts 2 wHubCharacteristic 0x000a No power switching (usb 1.0) Per-port overcurrent protection TT think time 8 FS bits bPwrOn2PwrGood 10 * 2 milli seconds bHubContrCurrent 0 milli Ampere DeviceRemovable 0x00 PortPwrCtrlMask 0xff Hub Port Status: Port 1: 0000.0100 power Port 2: 0000.0100 power Device Status: 0x0001 Self Powered
したがって、この hub は、電圧制御をサポートしていないことを認めています。
電源切り替えに関する情報に加えて、各 port に関するステータス情報も「Hub Port Status」としてあることに注意してください。これらの status bits は、 USB 2.0 仕様の表 11-21 (セクション 11.24.2.7.1) で定義されています。これは、 hubpowerによって取得される情報と同じです。
uhubctl ツール
USB hub で relay を制御するというアイデアは、多くのイニシアチブの動機です。主に、このプロジェクトは電圧を制御する USB hubs のリストを維持しているため、 uhubctlを見る価値があります。
このツールは明らかに電圧制御のみを目的としており、 USB デバイスの問題を解決するためのものではありません。たとえば、デフォルトでは、 uhubctl は、 portごとに個別に電圧を制御する機能を宣言していない hubs を無視します。
これらのコマンドは、上記の hubpower コマンドと同等です。
$ sudo ./uhubctl -f -l 1 -p 6 -a 0 Current status for hub 1 [1d6b:0002 Linux 5.16.0 xhci-hcd xHCI Host Controller 0000:00:14.0, USB 2.00, 12 ports, nops] Port 6: 0103 power enable connect [045e:07b2 Microsoft Microsoft? Nano Transceiver v1.0] Sent power off request New status for hub 1 [1d6b:0002 Linux 5.16.0 xhci-hcd xHCI Host Controller 0000:00:14.0, USB 2.00, 12 ports, nops] Port 6: 0000 off $ sudo ./uhubctl -f -l 1 -p 6 -a 1 Current status for hub 1 [1d6b:0002 Linux 5.16.0 xhci-hcd xHCI Host Controller 0000:00:14.0, USB 2.00, 12 ports, nops] Port 6: 0000 off Sent power on request New status for hub 1 [1d6b:0002 Linux 5.16.0 xhci-hcd xHCI Host Controller 0000:00:14.0, USB 2.00, 12 ports, nops] Port 6: 0100 power
コマンド構文はあまり便利ではありません。以下に簡単に説明します。
uhubctl は libusbに基づいているため、このツールは他のオペレーティング システムでも動作します。対照的に、 hubpower は /dev/bus/usb/ (または /proc/bus/usb/) 内の hubの device file に直接アクセスし、 Linuxでのみ動作します。
uhubctl は USB 3.x もサポートします ( git commit とそのフォローアップを参照)。ただし、実際の USB デバイスが hubに接続されたときに何が起こるかは、誰も気にしていないようです。 SuperSpeed デバイスをリセットしようとすると、奇妙な結果になりました。 power が返されたとき、デバイスは Polling 状態のままであり、列挙されませんでした。また、 power がオフの間、「lsusb -v」がスタックしていました。それで、そこで何か悪いことが起こりました。
これらは、 SuperSpeed portで電源をオフにしてから再度オンにするコマンドです。 SuperSpeed の詳細については、以下をご覧ください。
# ./uhubctl -f -e -l 2 -p 4 -a 0 # ./uhubctl -f -e -l 2 -p 4 -a 1
- -f は、 hub が個々の portの電圧制御をサポートしていないと報告した場合でも、 hub で動作することを意味します。
- -e は「正確な位置」を意味します。つまり、 SuperSpeed port を 2 つの hubsとして数えます。
- -l 2 は 2 番目の hub を意味します (最初の hub は私のコンピューターの USB 2.0 hub でした)
- -p 4 は、 port の 4 番を意味します。
- -a 0 は電源を切ることを意味します (action #0)
- -a 1 は、電源をオンにすることを意味します (action #1)
PORT_POWER の説明
host から PORT_POWER をゼロに変更するコマンドが到着すると、 port は無条件に Powered-off 状態に入ります。これは、 hub がデバイスに 5V 電源を供給し続けている場合でも当てはまります。 PORT_POWER がゼロになる理由は他にもあります。特に、 port での overcurrent の状態 (デバイスが大量の電流を消費する) があります。
PORT_POWER を '1' に変更する唯一の方法は、 hostからのコマンドによるものです。これにより、 port が Disconnected 状態になります。何も接続されていない USB ports は、通常、この状態にあります。 portでデバイスが検出されると、少し遅れて状態が Disabled に変わります。デバイスがすでに接続されていて、 PORT_POWER が '1'に変更された場合、これはすぐに発生します。
この状態からデバイスをアクティブ化するための唯一の方法は、 port をリセットすることです ( PORT_RESETの場合、以下を参照)。それができるのは host だけです。したがって、 hub ができる唯一のことは、注意が必要なデバイスが接続されていることを host に通知することです。
これは、 portの status bits の 1 つが登場する場所です。 PORT_CONNECTION. port が Powered-off 状態または Disconnected 状態にある場合、この bit はゼロでなければなりません。 port が Disconnected 状態から Disabled 状態に移行すると、 PORT_CONNECTION は '1' に変化します。 PORT_CONNECTION の変更は hub eventを生成するため、 driver に通知されます (つまり、 kernelの hub.c での port_event() への関数呼び出しは、 USB_PORT_FEAT_C_CONNECTION が有効な状態で行われます)。 driver は、( portの PORT_RESET ビットを '1'に変更することによって) port をリセットし、接続されたデバイスを列挙することで応答します。
これはすべて USB 2.0に関連しています。 USB 2.0 仕様の図 11-10 は、 hubの port がどのように状態を変更するかを示しています。
PORT_RESET と PORT_ENABLE を直接制御する
hubpower には、他の 2 つの属性を直接変更する機能もあります。 PORT_RESET と PORT_ENABLE。実際、私はこのツールの fork にこの機能を追加しました。ただし、これでできることは、故意に USB デバイスを故障させることだけであることに注意してください (したがって、コンピュータにデバイスをリセットさせて修正させます)。より詳細に:
USB 2.0 仕様のセクション 11.5.1.5 に従って port reset を開始するには、 host によってPORT_RESET を '1' に設定する必要があります。 hub は、リセットの完了後に PORT_RESET を '0' に戻します。 hub はそれ自身のイニシアチブで port reset を開始することはなく、 host はこの属性に '0' を書き込むことはできません (セクション 11.24.2.7.1.5)。
port が Powered-off または Disconnected 状態にある場合、この hub は PORT_RESET を無視します。
PORT_ENABLEについて: この属性が '0'に変更されると、 port は Disabled 状態に変更されます。これは、 hostからの要求、 USB デバイスの切断、 port の電源がオフの状態、または reset プロセス中のエラーが原因で発生する可能性があります。
PORT_ENABLE は、 host からの port reset 要求の結果としてのみ '1' に変更できます ( USB 2.0 仕様のセクション 11.24.2.7.1.2)。
したがって、 host は、 PORT_RESET を '0' に変更したり、 PORT_ENABLE を '1'に変更したりすることはできません。これを行おうとすると、 hub からエラー応答が返されます (関連する ioctl() コマンドは error statusを返します)。
hubpower は、 portの PORT_RESET を '1'に変更することにより、直接リセットを要求できます。これにより、 USB デバイスがリセットされ、その結果、デバイスは bus address を忘れます。そのため、デバイスにアクセスできなくなります。
このコマンドは hubに直接送信されるため、 Linux kernel 内の hubの driver はこれが発生したことを知りません。実際、コンピューターは、 USB デバイスにアクセスしようとするまで、何かが変更されたことに気付きません。次に何が起こるかは、デバイスの driverによって異なります。デバイスは、何らかのハードウェア エラーがあるかのように扱われます。したがって、何らかのエラー訂正措置が講じられます。ほとんどの場合、これにはリセットが含まれます。
したがって、 hubpower を使用して直接リセットを行うと、おそらく望ましい結果が得られますが、不必要なドラマがたくさんあります。 PORT_POWER はこれをよりエレガントに行います。直接の PORT_RESET の唯一の利点は、 driver が「このデバイスに何か問題があるので、根本的な解決策を講じましょう」と言う可能性があることです。そして、それは役立つかもしれません。
PORT_ENABLEの操作に関しては、同じことが起こります。 デバイスが突然消えます。この場合でも、コンピューターは何かが起こったことをすぐには認識しません。 USB 2.0 specificationのセクション 11.24.2.7.2.2 によると、 PORT_ENABLE (つまり C_PORT_ENABLE) の変更通知は、リンク上のエラーが原因で port が無効になった場合にのみトリガーされます。仕様では、この通知は他の理由では行われないと明示的に述べています。
したがって、 PORT_ENABLE をゼロに変更すると、 PORT_RESET を直接変更するのとほぼ同じ効果があります。欠点が 1 つあります。 USB 3.0 仕様のセクション 10.14.2.6.1 によれば、 PORT_ENABLE "is not supported by SuperSpeed hubs"。
SuperSpeed (USB 3.x)
何よりもまず: USB 3.x デバイスに問題があるためにこれを読んでいる場合は、 USB 3.x が提供する data rate が本当に必要かどうか自問してください。答えが否定的な場合は、 USB 3.x をサポートしていない USB hub (または短い USB 2.0 ケーブル) を介してデバイスをコンピューターに接続してみてください。これだけで問題が解決する場合があります。
SuperSpeed USB ( USB 3.xと同じ意味) は USB 2.0と並行して共存します。すべての SuperSpeed デバイスは実質的に 2 つのデバイスで構成されています。 SuperSpeed用の 1 つの別個のデバイスと、 USB 2.0用の別の別個のデバイス。これら 2 つの USB versions のそれぞれは、 USB cableの個別のワイヤに依存しています。それらは、電子的にも概念的にも相互に独立しています。
USB 仕様では、すべての SuperSpeed デバイスがこれら 2 つのデバイスで構成されている必要がありますが、これは実際には必要ありません。つまり、 USB 2.0 をサポートしていない SuperSpeed デバイスは、 SuperSpeed portに接続すると正しく動作します。
SuperSpeed デバイスが SuperSpeed portに接続されている場合、最初の試みは SuperSpeed インターフェイスを介した接続です。それが失敗した場合、 USB 2.0 を介した接続が試行されます。実際には (そして仕様によれば)、 USB デバイスは両方のバージョンを同時に接続することはありません。ただし、これは可能であり、 USB デバイスが 2 つの別個のデバイスであるかのように動作します。
SuperSpeed hub は、並列の 2 つの hubs で構成されます。 USB 2.0 用に 1 つ、 SuperSpeed用に 1 つ。外部 SuperSpeed USB hub をコンピューターに接続すると、2 つの hubs がシステムに追加されます。それらは 2 つの別個のデバイスとして表示されます。プレーンな USB デバイスでは、両方のバージョンを並行して使用することはできませんが、 hub ではこれを行う必要があります。
SuperSpeed hub が USB 2.0 portに接続されている場合、通常の USB 2.0 hubのように動作します。
一般に、これら 2 つの hubs はそれぞれ独立して動作します。各 hub には独自の portsがあり、これらの ports はそれぞれ独立して動作します。特に、これらの並列 hubsの 1 つで port のパラメータが変更された場合、これは他の hubの portsには影響しません。
もう 1 つの結論は、「lsusb -t」がデバイスが SuperSpeed root hubを介してコンピュータに接続されていることを示している場合、そのデバイスは SuperSpeed デバイスとして動作するということです。つまり、そのデータレートは 5 Gbit/s 以上です。同様に、このデバイスが USB 2.0 root hubを介して接続されている場合、そのデータ レートは 480 Mbit/s 以下です。
SuperSpeed および PORT_POWER
hubpower が実際に行ったことは、 portの PORT_POWER 属性を変更することだったことを思い出してください。
ただし、 SuperSpeed hub は 2 つの hubs を並列に接続したものです。これら 2 つの hubs にはそれぞれ、 portごとに独自の独立した PORT_POWER 属性があります。では、いつ hub が VBUS powerをオフにすべきでしょうか?各物理 power switch は、並列 hubsのそれぞれから 1 つずつ、2 つの PORT_POWER 属性に依存します。
USB 3.0 specification の表 10-2 は、 hub が電源を有効にするかどうかの真理値表を示しています。次のように要約できます。 hub が USB 2.0 hub としてのみ動作する場合 (たとえば、 SuperSpeedをサポートしていないコンピューターに接続されている場合)、 USB 2.0の PORT_POWERに従います。 SuperSpeed hub として接続されている (または両方の並列 hubs が接続されている) 場合、 VBUS は、両方の PORT_POWER がゼロの場合にのみオフになります。
複雑に聞こえるかもしれませんが、実際には簡単な部分でした。 hub の SuperSpeed 部分には、異なる内部 state machineがあります。 link training は別の方法で行われるため、これは当然のことです。ただし、この state machine には、 PORT_POWER がゼロの場合に適格な 3 つの異なる状態 ( USB 2.0のような 1 つではなく) があります。
- DSPORT.Powered-off。これは、 port が完全に非アクティブであることを意味します。
- DSPORT.Powered-off-detect。これは、 port が SuperSpeed リンク パートナーを検出しようとすることを意味します。
- DSPORT.Powered-off-reset。これは、 port が warm reset を link partner に対して実行することを意味します ( warm reset の詳細は後述)。
最後の 2 つの状態の目的は、独自の電源を備えた SuperSpeed デバイスが portに接続されている場合、接続が USB 2.0にフォールバックしないようにすることです。これは、デバイスが SuperSpeed portに接続されていることを認識する方法がないために発生します。
では、このことから何を学んだでしょうか。主に、 SuperSpeed hub で PORT_POWER を変更してデバイスをリセットすることは、 USB 2.0 hubの場合ほど単純ではありません。
SuperSpeed: warm reset および hot reset
USB 2.0 には、デバイスをリセットする簡単な方法が 1 つあります。 両方のワイヤは、 hub から ground (SE0) に 10 ミリ秒間接続されます。一方、 SuperSpeed デバイスには、デバイスを reset する 2 つの方法があります。 warm reset と hot reset。これらを、リセットの理由を定義するために使用される用語である PowerOn Reset および Inband Resetと混同しないでください。 Inband Reset は、 hostからの要求によりリセットが発生したことを意味します。これにより、リクエストのタイプに応じて、 warm reset または hot resetが発生する可能性があります (詳細は後述)。
warm reset と hot resetを区別することが重要です。 特に、 warm reset では、 data stream を停止して最初から起動する必要があります。 hot reset は data stream 自体に送信され、この data stream を実行し続けます。したがって、 hot reset ははるかに高速ですが、 data stream を再起動することで解決できる問題がある場合は、 warm reset が必要です。このような問題の例として、 physical layer上に bit errors がある場合があります。 bitstream を停止して最初からやり直すと、おそらく equalizerの最適ではないチューニングを修正できるため、これを修正できる可能性があります。
usbreset は USBDEVFS_RESETで ioctl() を実行することを思い出してください。発生する他のすべてのことの中で、これにより、デバイスの USB バージョン ( Linux kernel v5.16の時点) に関係なく、 PORT_RESET がゼロに変更されます。
USB 3.0 仕様のセクション 7.4.2 によると、 PORT_RESET 要求は Hot Resetになります。これは、 data stream がアクティブな場合、解体されず、この data streamでリセット コマンドが送信されることを意味します。この仕様では、 warm reset を強制する BH_PORT_RESET (feature 番号 28) も定義しています ( port が無効になっていない場合)。このリセットはより基本的なものです。 data streamを停止し、再度起動するための手順を再開します ( LFPS signalingのおかげで)。重要な違いは、 data stream の再起動が必要な場合、 BH_PORT_RESET は再起動しますが、 PORT_RESET は再起動しないことです。
新しい SuperSpeed デバイスの接続には、 Warm Resetが含まれます。したがって、 SuperSpeed portで PORT_POWER を操作できるツールがないように見えるのは残念です。前述のように、 uhubctl は技術的にはこれを行うことができますが、デバイスは厄介な状態になります。
残り物
これらは役立つ可能性のあるランダムな情報ですが、適切なコンテキストはありません。
- PORT_POWER のようなコマンドのコードは、 USB 2.0 仕様の表 11-17 および USB 3.0 仕様の表 10-8 に Hub class feature selectors としてリストされています。
- PORT_RESET を有効にする kernel の機能は hub_port_reset()です。しかし、実際に portを再初期化するために、所有している driver をリセット用に準備し、 usb_reset_and_verify_device()への関数呼び出しを行う usb_reset_device()があります。これらの関数はすべて drivers/usb/core/hub.cで定義されており、 usb_reset_device() のみがエクスポートされます。
- drivers/usb/core/devio.cでは、 usb_reset_device() は proc_resetdevice()によって呼び出され、関連する device file上の USBDEVFS_RESET ioctl() によってトリガーされます。これが usbreset の機能です (上記参照)。
- これは、 linux_usbfs.c の libusbの op_reset_device() と同等です (代わりに IOCTL_USBFS_RESET を使用しますが、 USBDEVFS_RESETと同じです。どちらも 20 です。 kernelの include/uapi/linux/usbdevice_fs.hと比較してください)。 libusbの関数は、インターフェイスの要求も解除します。 deviceのインターフェースのいずれかが要求されている場合、proc_resetdevice() は丁寧に拒否します。
- hub.cでは、 port_event() は hub_event()によって呼び出されます。前者は、 portのビットの変化を検出するものです。 hub_event() は、 kick_hub_wq() (特に、この目的のために指定された hubの IN endpointに到着するステータス変更通知に応答して "fires on port status changes and various faults" となる hub_irq()) によって開始される work itemです。