RaspberryPiでUSB接続のPC音量調整ボタンを作る方法

あまり需要ないかも知れませんが、下記の「Arduinoで作成したUSB接続のPC音量調整ボタン」のRaspberry Piバージョンを作成したので、その手順と説明メモになります。

https://qiita.com/kwbt/items/0c9f930a236ca989e402

## Raspberry PiをUSB機器（ガジェット）にするざっくりとした説明
通常、Raspberry Pi のUSB端子には、マウスやキーボードといったRaspberry Piで使う周辺機器を接続するのですが、Raspberry Pi Zeroは、PCとUSBケーブルで接続して、自分自身をPCのUSB機器（ガジェット）にすることができます。

USBにはOTGという、PC無しでUSB機器どうしを接続させる規格があって、それを使うとUSBの親になったり、子なったりできます。

そして、LinuxにはUSB OTGドライバーが入っているので、今回それを用いてRaspberry PiをUSBの子機として動作させることにより、Raspberry PiをUSBガジェットにしています。

しかし残念なことに、全てのRaspberry PiがUSBガジェットになれるかというとそうではなく、下記記事によると、ハードウェアの仕様により、他のRaspberry PiはUSBガジェットにはできないようです。

http://intothevoid.hatenablog.com/entry/2016/04/22/230303

ドライバーを使ってUSBガジェットをフルスクラッチするとなると気が遠くなりそうですが、幸い、Linuxには、いくつかの設定を行うだけでお手軽にUSBガジェットが作成できる「Composite USB Gadgets」という、 USB OTGのラッパーフレームワークが入っているので、今回はそれを用いて、USBガジェット、つまり、PC音量調整するUSB HIDを作成しました。

## 手順
### USB OTGドライバとComposite USB Gadgetsの読み込み
**「/boot/config.txt」に下記を追記します**

```sh
dtoverlay=dwc2
```

**「/etc/modules」に下記を追記します**

```sh
dwc2
libcomposite
```

「 dwc2」がUSB OTGドライバー、「libcomposite」がComposite USB Gadgetsで、それらがRaspberry Pi起動時に読み込まれるようになります。

**Raspberry Piを再起動します。**

Raspberry Piが立ち上がると、既にComposite USB Gadgetsが動作しているので、続いてUSBガジェットを作成します。

## USBガジェットの作成
**下記シェルスクリプトを``sudo``で実行します。**


```sh:usb_volume_button.sh
#!/bin/bash

CONFIGS_HOME=/sys/kernel/config
GADGET_NAME=g1
NAME=c
NUMBER=1
FUNC_NAME=hid
INSTANCE_NAME=usb0
BASE=${CONFIGS_HOME}/usb_gadget/${GADGET_NAME}

mkdir -p ${BASE}/
cd ${BASE}/
echo 0x1d6b > idVendor
echo 0x0104 > idProduct

mkdir -p ${BASE}/configs/${NAME}.${NUMBER}/
mkdir -p ${BASE}/functions/${FUNC_NAME}.${INSTANCE_NAME}/
cd ${BASE}/functions/${FUNC_NAME}.${INSTANCE_NAME}/
echo 0 > protocol
echo 0 > subclass
echo 1 > report_length
echo -ne \\x05\\x0c\\x09\\x01\\xa1\\x01\\x15\\x00\\x25\\x01\\x09\\xe9\\x09\\xea\\x09\\xe2\\x75\\x01\\x95\\x03\\x81\\x02\\x75\\x01\\x95\\x05\\x81\\x03\\xc0 > report_desc

cd ${BASE}/
ln -s functions/${FUNC_NAME}.${INSTANCE_NAME} configs/${NAME}.${NUMBER}
ls /sys/class/udc > UDC
```

ディスクリプタはArduinoで作成した時と同じです。ただし、ReportIDはComposite USB Gadgetsの方で決まっているようで、指定すると動作しなかったのでここでは外しました。

シェルスクリプトを実行すると、Raspberry Piが音量調整コントローラーのUSBガジェットになります。

Raspberry PiをPCにつなぐと、デバイスマネージャーの[ヒューマンインターフェイスデバイス]-[HID準拠コンシューマ制御デバイス]に現れます。

「HID準拠コンシューマ制御デバイス」は複数あったりするんですが、[プロパティ]-[詳細]-[ハードウェアID]を見て、上記シェルスクリプトで設定したベンダーIDが「1D6B」、プロダクトIDが「0104」となっているものが、Raspberry Piです。

![20190131031924.png](https://qiita-image-store.s3.amazonaws.com/0/100574/8f4c6f75-8e04-b97a-5bd8-dc153b45a29d.png)

## 音量調整信号の送信
USBガジェットが作成されると、「/dev/hidg0」というファイルが作成されるので、このファイルを介して、PCとデータの送受信を行います。

音量調整信号は下位ビットから「音量UP→音量DOWN→消音」の順で割り当てたので、送信のサンプルは下記のようになります。（sudoで実行します）

```sh:send_volume_control_signal.sh
#!/bin/bash

echo -ne "\x1" > /dev/hidg0 # UP
echo -ne "\0" > /dev/hidg0 # RELEASE

echo -ne "\x2" > /dev/hidg0 # DOWN
echo -ne "\0" > /dev/hidg0 # RELEASE

echo -ne "\x4" > /dev/hidg0 # MUTE
echo -ne "\0" > /dev/hidg0 # RELEASE
```

## USBガジェットの削除
``sudo echo "" > /sys/kernel/config/usb_gadget/g1/UDC``で作成したUSBガジェットが削除されます。

PCにつないだままUSBガジェットの作成・削除を行っても大丈夫です。

削除すると、PCからは、そのUSBガジェットが取り外されたように見えます。


## 応用
他のHIDを作成する際

- マウスの場合は「protocolを2、subclassを1」
- キーボードの場合は「protocolを1、subclassを1」
- その他の場合は「protocolを0、subclassを0」

に設定します。

通常HIDはPCのOSが立ち上がってから認識されるのですが、マウス・キーボードはこの設定により、PCのブート時にも認識されて使えるようになります。

Composite USB GadgetsはHID以外に、ストレージ・LAN・シリアルなどのUSBガジェットも作成できるので、暇があったら試してみたいですね。

**Composite USB Gadgets ファンクション一覧**

```text
1. ACM function
2. ECM function
3. ECM subset function
4. EEM function
5. FFS function
6. HID function
7. LOOPBACK function
8. MASS STORAGE function
9. MIDI function
10. NCM function
11. OBEX function
12. PHONET function
13. RNDIS function
14. SERIAL function
15. SOURCESINK function
16. UAC1 function (legacy implementation)
17. UAC2 function
18. UVC function
19. PRINTER function
20. UAC1 function (new API)
```

## 元記事
[ラズベリーパイでUSB接続のPC音量調整ボタンを作る方法](https://www.kwbtblog.com/entry/2019/01/31/103542)