USBモデムのエラー device descriptor read/64, error -71
Debianを11(bullseye)から12(bookworm)へアップグレードしたころから、dmessageに「 device descriptor read/64, error -71 」が表示されるようになりました。
そして、hylafaxで利用していた USB FAXモデムが使えなくなりました。同様の他の環境にしても、予備のモデムに変えてみても同じ症状です。
そこで、USBの自動サスペンド( auto suspend )との相性の問題ではないかと思い至り、調整をしてみることにしました。
追記
後日判明したのですが、このあと紹介するUSB自動サスペンドはこのエラーに影響していないかもしれません。環境によって改善したりしなかったりします。
chatGPTによるとエラー-71は次のようなエラー内容のようです。
ちなみにhylafaxのエラーはhylafax+(プラス)に差し替えることで改善しました。
dmesageの詳細
dmessage にどのようなエラーがでていたかの詳細です。
USBを抜き差しするたびに下記の下線のようなエラーが表示されていました。
[5328727.081745] usb 1-10: new full-speed USB device number 15 using xhci_hcd [5328727.209794] usb 1-10: device descriptor read/64, error -71 [5328727.445791] usb 1-10: device descriptor read/64, error -71 [5328727.681761] usb 1-10: new full-speed USB device number 16 using xhci_hcd [5328728.064056] usb 1-10: New USB device found, idVendor=0000, idProduct=9999, bcdDevice= 1.00 [5328728.064071] usb 1-10: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [5328728.064076] usb 1-10: Product: USB Modem [5328728.064080] usb 1-10: Manufacturer: Conexant [5328728.064084] usb 1-10: SerialNumber: 00000F8C [5328728.068229] cdc_acm 1-10:1.0: ttyACM0: USB ACM device
カーネルコマンドラインによる修正
まず、USBの自動サスペンドが本当に原因なのかを確認するために、カーネルコマンドラインを使ってすべてのUSB自動サスペンドを停止させてみます。
GRUB_CMDLINE_LINUX_DEFAULTに、usbcore.autosuspend=-1 を追加します。
これは /etc/grub.d/10_linux の先頭付近に設定するのが適当ではないかと思います。
/etc/grub.d/10_linux
... GRUB_CMDLINE_LINUX_DEFAULT="${GRUB_CMDLINE_LINUX_DEFAULT} usbcore.autosuspend=-1" ...
設定をしたら grubを更新する必要があります。
リブートして dmessage のエラーが表示が消えるか確認します。
筆者の場合はこの設定でエラーが消えたので原因は自動サスペンドのようです。
udev
先の設定のままでもいいのですが、せっかくの省電力モードを無効にするのももったいない気がするので、今度はデバイスを限定して省電力を停止してみたいと思います。
いったん先ほどの GRUB の設定を削除し、反映させた後リブートします。エラーが再度出るのを確認したら作業を進めます。
(どういう原理かは不明ですが、筆者の場合設定を消した後の初回のリブートではエラーがでませんでした。)
デバイスの管理は udevデーモンによって管理されています。それを使って自動サスペンドモードを切り替えたいと思います。ちなみにUSBを差し込むと /dev にリストされるのもこのデーモンの働きによるものです。
/etc/udev/rules.d ディレクトリはそのようなudevルールファイルを格納する場所となっています。ここに、90-usb-autosuspend.rules というファイルを生成します。
まずはここに、すべてのUSBデバイスに対してオートサスペンドを無効にする設定をしてみます。
/etc/udev/rules.d/90-usb-autosuspend.rules
ACTION=="add", SUBSYSTEM=="usb", TEST=="power/control", ATTR{power/control}="on"これらの指示の内容は次のようになっています。
- ACTION=="add"
USBデバイスが追加された時のルールを指定します。
- SUBSYSTEM=="usb"
USBサブシステムの属するデバイスを対象にします。
- TEST=="power/control"
power/control 属性があるかどうかを判定して、なければ実行しません。
この「属性」はファイルとして管理されており、/sys/bus/usb/debices/[対象のデバイス]/power/control というパスが存在することがその判定の基準となります。
- ATTR{power/control}="on"
power/control を on に設定しています。これを auto とすれば自動となります。
次のようにしてudevにルールの再読み込みを指示することができますが、筆者の環境ではOSの再起動が必要でした。
次は、部分的に設定する為に、デバイスのベンダーIDとプロダクトIDを指定します。
ただ、次に紹介する方法はうまくいかない時がありましたので、安定稼働を希望するなら後で紹介するTLPを用いることをおすすめします。
ベンダーIDとプロダクトIDは lsusbで確認することができます。
# lsusb Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 002 Device 002: ID 0000:9999 ...USB Modem Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
この0000の部分がベンダーID、9999の部分がプロダクトIDとなります。これを使って次のように設定します。
/etc/udev/rules.d/90-usb-autosuspend.rules
ACTION=="add" ATTR{idVendor}=="0000", ATTR{idProduct}=="9999", TEST=="power/control", ATTR{power/control}="on"または KERNEL キーを使ってttyACMを指定する事も可能です。この時 * を用いて複数のデバイスにも対応できます。
/etc/udev/rules.d/90-usb-autosuspend.rules
ACTION=="add" KERNEL=="ttyACM*", TEST=="power/control", ATTR{power/control}="on"筆者の環境ではこれらの設定がうまくいったりうまくいかなかったりしました。おそらく、ATTRやKERNELもUSBイニシャル時に取得・判定されるため、自動サスペンドの設定をOFFとする処理が間に合わないのだと思います。
ちなみに、特定のデバイスを検知した時にスクリプトを実行したい場合は、RUN を使って指定する事ができます。
+=で既存ののRUN属性に追加する設定となります。=とするとば指定したコマンドのみが実行されます。
他、udevのルールファイルの記述方法は man udevに載っています。
TLP
TLPはLinuxの電源管理のためのツールです。
サービスとして在中させないといけないのがネックですが、このツールの中にUSB自動サスペンドの設定が存在します。
# apt install tlp ...
インストールが終わったら /etc/tlp.conf の次の部分を修正します。
/etc/
... # 378行目付近 # こちらを 0にすると全体で自動サスペンドを無効にします # Set to 0 to disable, 1 to enable USB autosuspend feature. # Default: 1 #USB_AUTOSUSPEND=1 # 自動サスペンドの例外設定を ベンダーID:プロダクトIDの対で記載します # Exclude listed devices from USB autosuspend (separate with spaces). # Use lsusb to get the ids. # Note: input devices (usbhid) and libsane-supported scanners are excluded # automatically. # Default: <none> USB_DENYLIST="1111:2222 3333:4444" ...
TLPを再起動します。
現状のTLPの設定値を確認するには tlp-stat -c とします。