鹿児島らぐの「鹿児島Linux勉強会 2018.04」で発表予定だったけど参加者が1名(自分)だったのでblogで供養しておきます><
発表スライドを社会性フィルタにかけて加筆修正した感じのものです.テキスト量は10倍以上になっています??

おさらい

「鹿児島linux勉強会 2017.01」でRaspberry Pi Zeroを利用してUSB OTGでserial/ethernet/mass strageを紹介しました.

ちょっとした設定でRaspberry Pi ZeroをUSBデバイスに見せることが出来ました.でもこのときHIDはうまく行かず宿題に.

今回はRaspbery Pi ZeroのHID(キーボード/マウス)化の紹介です.

用意したもの

  • Raspberry Pi Zero v1.2
    • Raspberry Pi Zero W/HW/A/A+も利用可能です.(USBが2つ以上ある物は不可)
  • Raspbian stretchを導入したmicroSD

  • UARTに繋ぐためにGPIOにピンヘッダを接続(Raspberry Pi Zero HWやA/A+ならそのまま)
  • PCとPiのUARTを繋ぐために3V3のUSB-UARTケーブルを利用
  • テスト用のPC等(作業マシンと同じでもOKだけどたまに混乱するので分けたほうが無難)

ピンヘッダ?

Raspberry Pi Zero/Zero WにはGPIOにピンが実装されていません.必要な場合は自分で実装する必要があります.基本的に2.54mmピッチのオスの2列タイプを必要なピン数を折って使います.Raspberry Pi Zero のGPIOピン数は2x20です.今回の用途のみであれば1x3でもok.(手持ちにより1x20を2つ使うなどもok)

色付きのものやメスタイプやL字タイプなどいろいろあるので用途に合わせて変更してもいいです.(ピンの用途ごとに色を変えたり,高さを出したくない場合はL字型にしたり,オスのピンは曲がりやすいので持ち運びの多い場合はメスのピンソケットにする等)

他に私は利用したことがないのですが,はんだ付けの必要のないHammer Headrというものもあります.

ちなみにRaspberry Zero HWというピンヘッダが実装済のモデルも存在するのでこれを利用することではんだ付けなどの取り付け作業は必要なくなります.

UART接続

GPIOのUARTのSerial経由でConsoleにつないで操作するために

  • 操作用にGPIOのUARTを利用

    GPIOを利用するためピンヘッダを取り付けてある

    • Hostからは3v3なUSB-UARTのアダプタ経由で操作
    • Raspberry Pi HWならピンヘッダが釣りつけられているのでそのまま利用できます.
  • 操作にUSB以外の方法でアクセスする必要がある

  • 今回はRaspberry Pi Zero v1.2でGPIOのTTLでgetty経由で操作

  • ZeroWだとWi-Fi/Bluetoothなども使える
    • USB Hubを繋ぐとOTGが使えなくなると思う
  • HOSTもできれば操作用と実行用に2台あると便利

キーボード化

  • libcomposite moduleを利用する
  • これまでと違い読み込むだけでは使えずいろいろ設定が必要
  • scriptにしておいて呼ぶようにする

キーボード化script例

#!/bin/bash
modprobe libcomposite
cd /sys/kernel/config/usb_gadget/
mkdir -p g1
cd g1
echo 0x1d6b > idVendor
echo 0x0104 > idProduct
echo 0x0100 > bcdDevice
echo 0x0200 > bcdUSB
mkdir -p strings/0x409
echo "fedcba9876543210" > strings/0x409/serialnumber
echo "matoken" > strings/0x409/manufacturer 
echo "kbdtest" > strings/0x409/product
N="usb0"
mkdir -p functions/hid.$N
echo 1 > functions/hid.usb0/protocol
echo 1 > functions/hid.usb0/subclass
echo 8 > functions/hid.usb0/report_length
echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.usb0/report_desc
C=1
mkdir -p configs/c.$C/strings/0x409
echo "Config $C: ECM network" > configs/c.$C/strings/0x409/configuration 
echo 250 > configs/c.$C/MaxPower 
ln -s functions/hid.$N configs/c.$C/
ls /sys/class/udc > UDC

host PCでの認識例

[782125.818181] usb 1-1.2: new high-speed USB device number 49 using sunxi-ehci
[782125.931156] input: matoken kbdtest as /devices/soc.0/1c1b000.ehci1-controller/usb1/1-1/1-1.2/1-1.2:1.0/input/input28
[782125.931652] hid-generic 0003:1D6B:0104.0017: input: USB HID v1.01 Mouse [matoken kbdtest] on usb-sunxi-ehci-1.2/input0

キーボードとして振る舞う1

# echo -ne "\0\0\x4\0\0\0\0\0" > /dev/hidg0
# echo -ne "\0\0\0\0\0\0\0\0" > /dev/hidg0
  • 1行目でaを押して2行目でキーを離す
  • めんどい

キーボードとして振る舞う2

$ echo -n "hello world!" | sudo ./scan /dev/hidg0 1 2
  • 入力したい文字列を指定するとその文字列をテーブルで変換して渡してくれる :)

マウス化

マウス化script例

キーボード化とreport descripter(report_desc)行だけ変える

echo -ne \\x05\\x01\\x09\\x02\\xa1\\x01\\x09\\x01\\xa1\\x00\\x05\\x09\\x19\\x01\\x29\\x03\\x15\\x00\\x25\\x01\\x95\\x03\\x75\\x01\\x81\\x02\\x95\\x01\\x75\\x05\\x81\\x01\\x05\\x01\\x09\\x30\\x09\\x31\\x15\\x81\\x25\\x7f\\x75\\x08\\x95\\x02\\x81\\x06\\xc0\\xc0 > functions/hid.usb0/report_desc

マウスとして振る舞う

  • 座標移動
# echo -ne "\0\x20\0" > /dev/hidg0  #Xを+20
# echo -ne "\0\0\x20" > /dev/hidg0  #Yを+20
  • クリック(キーボードと同様押したら離す必要がある)
# echo -ne "\x1\0\0" > /dev/hidg0   # 右クリック
# echo -ne "\0\0\0" > /dev/hidg0    # リリース

mouse button -> p67

嵌まったところ

  • USB cable接触不良orz
  • Synergycでローカルキーボード無視

活用例?

Arduinoでも十分?

  • ArduinoやマイコンでもUSB-HIDはできる
  • 開発はPiなどのほうが楽なのでテストには良いかも
  • 若しくはネットワークやBluetooth機器との連携など複雑なことをするときに

USB保護

参考URL

"RaspberryPiをUSBHIDデバイスとして使う - Qiita" https://qiita.com/sgrk/items/7a818b2a059d5b06b209

mouse button -> p67

[782125.818181] usb 1-1.2: new high-speed USB device number 49 using sunxi-ehci
[782125.931156] input: matoken kbdtest as /devices/soc.0/1c1b000.ehci1-controller/usb1/1-1/1-1.2/1-1.2:1.0/input/input28
[782125.931652] hid-generic 0003:1D6B:0104.0017: input: USB HID v1.01 Mouse [matoken kbdtest] on usb-sunxi-ehci-1.2/input0
Apr 20 01:12:11 pinebook kernel: [782125.818181] usb 1-1.2: new high-speed USB device number 49 using sunxi-ehci
Apr 20 01:12:11 pinebook kernel: [782125.931156] input: matoken kbdtest as /devices/soc.0/1c1b000.ehci1-controller/usb1/1-1/1-1.2/1-1.2:1.0/input/input28
Apr 20 01:12:11 pinebook kernel: [782125.931652] hid-generic 0003:1D6B:0104.0017: input: USB HID v1.01 Mouse [matoken kbdtest] on usb-sunxi-ehci-1.2/input0
Apr 20 01:33:48 pinebook kernel: [783401.712540] usb 1-1.2: new high-speed USB device number 55 using sunxi-ehci
Apr 20 01:33:48 pinebook kernel: [783401.825821] input: matoken kbdtest as /devices/soc.0/1c1b000.ehci1-controller/usb1/1-1/1-1.2/1-1.2:1.0/input/input29
Apr 20 01:33:48 pinebook kernel: [783401.826115] hid-generic 0003:1D6B:0104.0018: input: USB HID v1.01 Mouse [matoken kbdtest] on usb-sunxi-ehci-1.2/input0
Apr 20 01:33:48 pinebook mtp-probe: checking bus 1, device 55: "/sys/devices/soc.0/1c1b000.ehci1-controller/usb1/1-1/1-1.2"