Raspberry Pi ZeroをHID Keyboardとして使う


## はじめに（注意？）

Raspberry Pi（Zero）をHID Keyboardとして認識させたく、ネット上のいろいろ情報を参照して試してみましたが、どうしても下記のエラーを回避できませんでした。


```bash
cannot send after transport endpoint shutdown
```

これは、そもそもRaspberry PiをHIDディバイスとして認識できていないことに起因するとわかったのですが、その原因がソフト的なものではなく「USB Hubを経由していたため」に発生していたものでした。何か試すときはUSB Hubを経由せずに試すことをおすすめします。

>そもそもHub経由でなぜダメかは調査していません。電力不足？。またわかれば追記します。

## 準備

### Raspberry Pi (Zero)との接続（Keyboardとして）

![IMG_0273.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/867d9f78-ac6f-fd4d-95cf-e428e7486dd6.jpeg "IMG_0273.jpg")

> ポートを間違えないことはもちろん、無用なトラブル回避のため、（開発初期時点では）Hub等を経由せずに直接PCにつなぐこともお勧めします！

### Respberry Pi (Zero)との接続（操作用 SSHとして）

私はWi-Fi機能付きのRaspberry Pi Zero Wを利用しましたので、操作はWi-Fi経由のSSH接続で行いました。
その手順については[こちら](https://qiita.com/zaburo/items/752c45ffe86c356b8700)をどうぞ。

>5GのWi-Fiには対応していないようなので、お気をつけを（2.4GHzをご利用ください）。

## 環境

* 作業自体はMacで行いました
* Respberry Pi OSはLiteを利用しました（gitが無いのでsudo app-get install gitの必要があります）。

lsb_releaseの実行結果は下記の通りです。

```bash
lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 10 (buster)
Release:	10
Codename:	buster
```

## HID Keyboardとして認識させる

### 概要

手順は大きく、

1. そもそもHIDディバイスとして動くようにOTGを有効にするする（設定反映には再起動が必要）
2. Keyboardとして認識させる
3. 2の設定は再起動したら消えるので永続化する（/etc/rc.localへの記述）

という3ステップになります。なお、1,2の手順については[こちら](https://github.com/aidantwoods/RPi0w-keyboard)にサンプルスクリプトを準備してくれている方がいるので、そちらを利用するのがよく知られた手順のようです。

### 1. OTGを有効化する

作業は/home/piで行う想定です。

```bash
git clone https://github.com/aidantwoods/RPi0w-keyboard.git
```

```bash
sudo bash RPi0w-keyboard/src/install/setupOTG.sh
```

ソースを確認したら、下記のような感じです。

```bash
#!/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として認識させる

```bash
sudo bash RPi0w-keyboard/src/home/pi/hid.sh
```

```bash
ls -all /dev/hidg0
```

動作確認をするには、書きを実行すればいいのですが、開発端末でやるとコンソールにただ"a"が打たれる状態になります。なので、別のPCからRespberry Piにログインして、実行することが理想ではあります。

```bash
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 #すべてのキーを離す
```

ソースは下記のような感じになっているようです。必要に応じて変更する箇所は適宜変更したらいいのでしょう。ここでは一旦そのまま利用。

```bash
#!/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)の前に書きを追記します。

```bash:/etc/rc.local
/home/pi/RPi0w-keyboard/src/home/pi/hid.sh
chmod 777 /dev/hidg0
```

## 動作確認

### ハードウエアの認識

![スクリーンショット_2021-02-21_8_18_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/1f22dcb9-0cdd-d21d-5af5-f84a190d2370.png "スクリーンショット_2021-02-21_8_18_07.png")


### Key情報の送信

先程と同じですが、sudoをつけなくても動作するか確認しておきましょう。

```bash
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からの利用

バージョンが浅くて少々心配ですが、[これ](https://pypi.org/project/Py-Keyboard/)を試してみます。

Lite版にはpipがインストールされていないようなのでインストールします。念の為開発関連ライブラリも入れておきます。

```bash
sudo apt-get -y install python3-dev
sudo apt-get -y install python3-pip
```

```bash
pip3 install Py-Keyboard
```

コード。

```py
from Py_Keyboard.HID import Keyboard

kbd = Keyboard()

#kbd.press("CONTROL ALT T")
kbd.write('12345ABC\n')
```