👻

Mistel Keyboardで発生した謎の現象と対策

2020/12/26に公開

tl;dr

  • PCから離れるとなぜかサスペンドから回復してしまう
  • 切りわけたらキーボードから割り込みがきてた
  • udevのruleを作ってキーボードを黙らせてワークアラウンドした

前提

自宅PCはこんな感じ

  • マウスコンピュータのデスクトップPC
  • OSはDebian stable にsidのパッケージもちょっと入ってたりする。
  • 周辺機器は有線キーボード、logicoolの専用ドングルで繋ぐ無線マウス、USB音声のマイク、USB音声の有線ヘッドセット、RadeonのGPUにディスプレイ、bluetoothアダプタ、USB接続のWebカム。
  • 最近分割キーボード Mistel BAROCCO MD770 RGB を導入した

謎の現象

ある日トイレに行こうとPCをサスペンドして数歩離れるとサスペンドから勝手にレジュームした。
「なにこれ?」と思って数回ためしたところ

  • ログを見る限りサスペンドは成功している
  • サスペンドしたあとPCの目の前に2分程度いるとレジュームはしない
  • サスペンドしたあとPCから1mくらい離れるとレジュームする

……なんだこれ?

原因の推測と切り分け

前提・サスペンドの動き

サスペンドに成功すると、PCは周辺機器のほとんどを停止または省電力モードでの動作に移行して、消費電力が少ないモードで割り込みを待つ。ここでの周辺機器はディスク、USBハブ、ファン、キーボード、マウス、各種のアダプタ、グラフィックカード、NICなどPCに直接繋がっているものとマザーボード上のチップセット。

前提・レジュームの契機

レジュームの契機は、周辺機器からCPUへの割り込み。時間経過によるタイマーや、キーボードを押した、電源ボタンを押した、マウスを動かしたなど。どのイベントを利用するかはファームウェアとOSのどちらかで設定できる。

切り分け

特に人感センサーになるような機器はつけていない。何か本来の操作ではない原因でイベントが発生しレジュームが発生しているっぽい。

いくつか推測シナリオを考えながら可能性をつぶしていく。

  1. とりあえずlspci, lsusbして知らない機器がないことを確認。
  2. (仮説)自分が動くことで机がちょっと揺れ→マウスがゆれ→ホイールがまわり→イベントが発生する。(確認)マウスの電源を切ってから机を離れても再現するのでマウスではない。
  3. (仮説)主に睡眠トラッキングのためにMi band 4をつけている。特に接続していないし、bluetoothアダプタのライトはついていないけど、検出できなくなってイベントが発生?? (確認)可能性をつぶすため、bluetoothアタプタを抜いて再現。bluetoothは関係ない。
  4. このへんで仮説はあきらめてしらみつぶしモード。ヘッドセットにボタンがあり早送りとかのキーボードイベントが送れるが……まずないだろ。と思いつつ抜いて再現を確認。ヘッドセットも関係ない。
  5. キーボードを抜いて……再現しなくなることを確認。

なんで? ぼくわからないよなんで?

対策方法の調査

切り分けの結果キーボードのなにかが原因っぽい。USB接続で、lsusbでみるとこんな感じに見える。

Bus 002 Device 003: ID 04d9:0339 Holtek Semiconductor, Inc. USB-HID Keyboard
  1. powertop のWakeUpタブで対応するUSBデバイスからのwakeupイベントをdisableして再現しなくなることを確認。powertopスクショ
  2. 頻発していれば 何かしらforumやバグレポートなどでやりとりがあるはずなので、 "04d9:0339" でGoogle検索するもめぼしい結果はみあたらず。
  3. メーカーのWebサイト Support | Mistel Keyboard にファームウェア更新はあるがWindowsでしか更新できない。ひょっとしたらこれで何とかなる可能性はあるけどWindows持ってない。
  4. あまり期待せずメーカーのfacebookに質問をなげておく。

ワークアラウンドの実施(tuned, 失敗)

キーボードによるレジュームを止めてもマウスを触ればレジュームできるので、powertopがやっていたようにwakeupイベントを止めてとりあえずのワークアラウンドにしよう。

echo 'disable' > /sys/bus/usb/devices/2-3/power/wakeup

ただこのコマンドをいちいち叩くのは面倒すぎるし忘れるので自動化する。

tunedによるsysfs設定

sysfsに値を書くのだとtunedでプロファイル書けばいいかということで tuned-adm profileで今のprofileがdesktop-powersaveだと確認。
プロファイルを継承して欲しいところだけ設定する新プロファイルnokeyboardwakeを作ることにした。

/etc/tuned/nokeyboardwake/tuned.conf を作って、

[main]
include=desktop-powersave
[sysfs]
/sys/bus/usb/devices/2-3/power/wakeup=disabled

として

# tuned-adm profile nokeyboardwake

ワークアラウンド失敗

これでええやろ。。 と思って再起動するとUSBデバイスのIDがかわってて失敗!
そうでした。非同期に検出するからタイミングでIDかわるんでした(汗)。
ついでにUSBキーボードは差したり抜いたりできるので別ポートにさしたりハブかえたりでもIDかわる。

ワークアラウンドの実施(udev rule, 成功)

ということでtunedによるアプローチは失敗。デバイス特有の操作といえばudevですね。

/etc/udev/rules.d/99-nokeyboardwake.rules を作る。

SUBSYSTEM=="usb", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="0339", TEST=="power/wakeup", ATTR{power/wakeup}="disabled"

udevadm monitor でudevの動作をながめつつ、適当にキーボードの抜き差しを行って、デバイス検出後自動的にwakeupがdisableされることを確認する。

オチ

期待通り動くようになったのであわててトイレいきました。先にいってればよかった。

Discussion