デバイスドライバを書いたこと
事の発端
コントローラのヘタリ
Logitec Wireless Gamepad F710の調子が悪いので、
分解メンテしてみようとしたが、特殊ネジで開けられなかった。
仕方ないので新しいのを買おうと物色していた。
最近、ゲームコントローラが高い。
ワイヤレスだったり、電池内蔵だったり、振動機能があったりして、
昔より高機能化しているのはわかるが、
1つ3000円から5000円位する。
(Sonyの純正PS4コントローラはもっと高い)
その価格が高いか安いかにかかわらず、
使ってみるまで使用感に満足できるかわからないので、
あまり高額なものは買いたくない。
というわけで、PS2のコントローラをPS3、PC用に変換できるケーブルをAmazonで買った。
ノーブランド品の為、説明書もサポートもドライバもない。(紙の箱には入ってた)
でも、送料込みで500円は安いし、PS2コントローラの使用感はよく知っている。
なにより、PS2コントローラは数があるので中古品ジャンクで格安で買える。
こんなの。
本編
調査
ドライバなど作ったことが無いので、作り方を調べる必要があるが、
その前に、本当にコントローラの信号が届いているか調べる必要がある。
lsusb
lsusbコマンドでコントローラが認識されているか確認する。
ボタン配置がデタラメなのはわかってるので、
認識されているはずだが、今一度確認。
$ lsusb ...... Bus 002 Device 013: ID 054c:0268 Sony Corp. Batoh Device / PlayStation 3 Controller ......
Sony云々と出るのはご愛嬌。
正式に許可を得た商品ではなさそうだし、PS3で認識される為にIDを偽装しているのだと思う。
hidusb-dump
hidusb-dumpコマンドを使うと、USBデバイスからの送信データが参照できるので、
ボタンのプッシュ/リリース動作で値が変わるかどうかを観察すれば、
信号が来ているかがわかる。
このコマンドはroot権限がないと実行できない。
$ sudo usbhid-dump -a 002:013 -e all ...... 002:013:000:STREAM 1567477856.950528 01 00 00 00 08 00 64 5D 80 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 EF 14 00 00 00 00 23 03 77 01 00 02 00 02 00 01 80 02 00 ......
こんな感じでデータが流れ続けた。
つないでいる限りデータが垂れ流されているようだ。
(ちなみに、Logitec Wireless Gamepad F710の場合、
ボタンを押したときのみデータが送信される方式だった。
どっちがいいかは、まぁ、わからんが、後者のほうがエコだよな)
この状態でコントローラのボタンを押すと、
押している間だけバイト値が変わることが
全ボタンで確認できたので、信号は来ている、という確証を得た。
コーディング
前置きが長くなったけど、
Arch Linux上で動く上記コントローラ用のドライバを書いた。
この記事を参考に、ほぼ丸パクリの形で作った。
Linuxでペンタブモジュールを作成しよう。 - memomuteki
このサイトでは対象がペンタブレットだったので、
ゲームパッド用の定義については、別途、こっちのページを参考にした。
また、定数なんかはlinux/input.hを直接見た。
4. Linux Gamepad Specification — The Linux Kernel documentation
Linux Input Subsystemの使い方
運用
ロード問題
参考サイトではドライバのロードを以下の手順で行っていた。
- usbhidドライバのデタッチ
- 自作ドライバの削除(すでにロードされている場合)
- 自作ドライバの登録
開発時はこれで問題ないが、
PCを再起動したり、コントローラを抜き差しする度に、
ドライバのロードを行わければならず、日常的な運用では不便すぎる。
modprobe
カーネルドライバを自動ロードする仕組みにmodprobeがあるので、
自作ドライバをmodprobeに登録して自動的にロードするように設定する。
以下、Arch Linuxの場合。
- /lib/modules/extramodules-ARCH/にモジュールを置く。
- /etc/modprobe.d/blacklist.conf*1に定義を書く。
- /etc/mkinitcpio.confのFILEの項に2.のパスを追加する。
- depmod -aを実行する。
- mkinitcpio -p linuxを実行してinitcpioを再作成する。
- 再起動
/etc/modprobe.d/blacklist.conf
/etc/modprobe.d/blacklist.conf ...... # vendor_id:product_id: HID_QUIRK_IGNORE = 4,…… options usbhid quirks=0x054c:0x0268:0x04 ......
これを書かないとusbhidドライバがロードされてしまい、
自作ドライバが適用されないので必ず作成する。
/etc/mkinitcpio.conf
/etc/mkinitcpio.conf ...... # FILES # This setting is similar to BINARIES above, however, files are added # as-is and are not parsed in any way. This is useful for config files. FILES=(/etc/modprobe.d/blacklist.conf) ......
ここにblacklistの定義を追加しないと、blacklistが有効にならない。
結果
コントローラをつなぐ度に自作ドライバがロードされ、
いつでも正しく使えるようになった。