はじめに(注意?)
Raspberry Pi(Zero)をHID Keyboardとして認識させたく、ネット上のいろいろ情報を参照して試してみましたが、どうしても下記のエラーを回避できませんでした。
cannot send after transport endpoint shutdown
これは、そもそもRaspberry PiをHIDディバイスとして認識できていないことに起因するとわかったのですが、その原因がソフト的なものではなく「USB Hubを経由していたため」に発生していたものでした。何か試すときはUSB Hubを経由せずに試すことをおすすめします。
そもそもHub経由でなぜダメかは調査していません。電力不足?。またわかれば追記します。
準備
Raspberry Pi (Zero)との接続(Keyboardとして)
ポートを間違えないことはもちろん、無用なトラブル回避のため、(開発初期時点では)Hub等を経由せずに直接PCにつなぐこともお勧めします!
Respberry Pi (Zero)との接続(操作用 SSHとして)
私はWi-Fi機能付きのRaspberry Pi Zero Wを利用しましたので、操作はWi-Fi経由のSSH接続で行いました。
その手順についてはこちらをどうぞ。
5GのWi-Fiには対応していないようなので、お気をつけを(2.4GHzをご利用ください)。
環境
- 作業自体はMacで行いました
- Respberry Pi OSはLiteを利用しました(gitが無いのでsudo app-get install gitの必要があります)。
lsb_releaseの実行結果は下記の通りです。
lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 10 (buster)
Release: 10
Codename: buster
HID Keyboardとして認識させる
概要
手順は大きく、
- そもそもHIDディバイスとして動くようにOTGを有効にするする(設定反映には再起動が必要)
- Keyboardとして認識させる
- 2の設定は再起動したら消えるので永続化する(/etc/rc.localへの記述)
という3ステップになります。なお、1,2の手順についてはこちらにサンプルスクリプトを準備してくれている方がいるので、そちらを利用するのがよく知られた手順のようです。
1. OTGを有効化する
作業は/home/piで行う想定です。
git clone https://github.com/aidantwoods/RPi0w-keyboard.git
sudo bash RPi0w-keyboard/src/install/setupOTG.sh
ソースを確認したら、下記のような感じです。
#!/bin/bash
# See https://gist.github.com/gbaman/50b6cca61dd1c3f88f41 for more info
echo "dtoverlay=dwc2" | sudo tee -a /boot/config.txt
echo "dwc2" | sudo tee -a /etc/modules
実行したら再起動します。
2. Keyboardとして認識させる
sudo bash RPi0w-keyboard/src/home/pi/hid.sh
ls -all /dev/hidg0
動作確認をするには、書きを実行すればいいのですが、開発端末でやるとコンソールにただ"a"が打たれる状態になります。なので、別のPCからRespberry Piにログインして、実行することが理想ではあります。
sudo echo -ne "\0\0\x4\0\0\0\0\0" > /dev/hidg0 #aのキーを押す
sudo echo -ne "\0\0\0\0\0\0\0\0" > /dev/hidg0 #すべてのキーを離す
ソースは下記のような感じになっているようです。必要に応じて変更する箇所は適宜変更したらいいのでしょう。ここでは一旦そのまま利用。
#!/bin/bash
# Snippet from https://github.com/girst/hardpass-sendHID/blob/master/README.md . In which, the following notice was left:
# this is a stripped down version of https://github.com/ckuethe/usbarmory/wiki/USB-Gadgets - I don't claim any rights
modprobe libcomposite
cd /sys/kernel/config/usb_gadget/
mkdir -p g1
cd g1
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
mkdir -p strings/0x409
echo "deadbeef01234567890" > strings/0x409/serialnumber
echo "example.com" > strings/0x409/manufacturer
echo "Generic USB Keyboard" > 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
3. 設定を永続化する
/etc/rc.localのexit(0)の前に書きを追記します。
/home/pi/RPi0w-keyboard/src/home/pi/hid.sh
chmod 777 /dev/hidg0
動作確認
ハードウエアの認識
Key情報の送信
先程と同じですが、sudoをつけなくても動作するか確認しておきましょう。
echo -ne "\0\0\x4\0\0\0\0\0" > /dev/hidg0 #aのキーを押す
echo -ne "\0\0\0\0\0\0\0\0" > /dev/hidg0 #すべてのキーを離す
入力の簡素化とPythonからの利用
バージョンが浅くて少々心配ですが、これを試してみます。
Lite版にはpipがインストールされていないようなのでインストールします。念の為開発関連ライブラリも入れておきます。
sudo apt-get -y install python3-dev
sudo apt-get -y install python3-pip
pip3 install Py-Keyboard
コード。
from Py_Keyboard.HID import Keyboard
kbd = Keyboard()
#kbd.press("CONTROL ALT T")
kbd.write('12345ABC\n')