HID (Human Interface Device)を使って、RapberryPi Zero WをUSBマウスとしてパソコンに接続し、Pythonスクリプトによりマウスカーソルを移動させます。RapberryPi Zero WはUSB OTGの機能を持ち、パソコン無しでUSB機器どうしを接続でき、この機能によりUSBの親や子で動作できます。

RapberryPi Zero Wとパソコンの接続

HID化するためにパソコンとRapberryPi Zero W(電源でないほうのUSBコネクタ ー 下に示す画像を参照)にUSBケーブルで接続します。これにより、RapberryPi Zero Wに電源が入りraspbianが起動します。

RapberryPi Zero Wとパソコンの接続

RapberryPi 4についてもUSB OTGの機能を持っているため、次のようにUSB typeCの電源コネクタとパソコンとを接続するだけで、USBマウスとして動作します。

RapberryPi Zero WのHID化及びPythonスクリプトの作成は、WiFiを使ってSSHプロトコルで接続します。

RapberryPi Zero WをUSBマウスに

HID化のコードは、「aidantwoods/RPi0w-keyboard」を参照しています。次に示すシェルには実行権限を付与します。

次のシェル「setupOTG.sh」を使って、「/boot/config.txt」に「dtoverlay=dwc2」、「/etc/modules」に「dwc2」をそれぞれ追加して再起動します。USB OTGドライバー「 dwc2」を動作可能に設定します。

setupOTG.sh

#!/bin/bash

echo "dtoverlay=dwc2" | sudo tee -a /boot/config.txt
echo "dwc2" | sudo tee -a /etc/modules

次のコマンドでシェル「setupOTG.sh」を実行します。

$ chmod 777 setupOTG.sh
$ sudo ./setupOTG.sh
dtoverlay=dwc2
dwc2

次のシェル「hid.sh」により、RapberryPi Zero WをUSBマウス「Generic USB Mouse」として認識させます。

hid.sh

#!/bin/bash
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 "S/N 000-00" > strings/0x409/serialnumber
echo "tomosoft.jp" > strings/0x409/manufacturer
echo "Generic USB Mouse" > strings/0x409/product
N="usb0"
mkdir -p functions/hid.$N
echo 1 > functions/hid.$N/protocol
echo 1 > functions/hid.$N/subclass
echo 8 > functions/hid.$N/report_length
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
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/
# End functions
ls /sys/class/udc > UDC

次のコマンドで、シェル「hid.sh」を実行します。

 
$ chmod 777 hid.sh
$ sudo ./hid.sh

<参考>
USB Descriptor and Request Parser」を使用して、HIDのレポートディスクリプタを確認します。なお、HIDの仕様については「Device Class Definition for Human Interface Devices (HID)」を参照してください。

HIDレポートディスクリプタの確認

HIDデバイス(マウス)の設定確認

次のHIDのデバイスディスクリプタ「hidg0」がRapberryPi Zero Wに作成されていることを確認します。

$  ls -all /dev/hidg0
crw------- 1 root root 243, 0 10月 27 03:54 /dev/hidg0

次のコマンドをRapberryPi Zero Wで実行し、パソコン側でマウスカーソルの移動を確認します。

$ sudo su
# echo -ne "\0\x10\0" > /dev/hidg0

パソコン側で「usbview」を実行し、RapberryPi Zero WがUSBマウスとして認識されていることを確認します。表示された内容を見ると、「iManufacturer: “tomosoft.jp”」、「iProduct: “Generic USB Mouse”」、「iSerialNumber: “S/N 000-00″」と、シェル「hid.sh」で設定したデータが、パソコン側で受け取れていることが確認できます。

Device Descriptor:
bcdUSB:             0x0200
bDeviceClass:         0x00
bDeviceSubClass:      0x00
bDeviceProtocol:      0x00
bMaxPacketSize0:      0x40 (64)
idVendor:           0x1D6B
idProduct:          0x0104
bcdDevice:          0x0100
iManufacturer:        0x01
0x0409: "tomosoft.jp"
iProduct:             0x02
0x0409: "Generic USB Mouse"
iSerialNumber:        0x03
0x0409: "S/N 000-00"
bNumConfigurations:   0x01

ConnectionStatus: DeviceConnected
Current Config Value: 0x01
Device Bus Speed:     High
Device Address:       0x0C
Open Pipes:              2

Endpoint Descriptor:
bEndpointAddress:     0x81  IN
Transfer Type:   Interrupt
wMaxPacketSize:     0x0008 (8)
bInterval:            0x04

Endpoint Descriptor:
bEndpointAddress:     0x01  OUT
Transfer Type:   Interrupt
wMaxPacketSize:     0x0008 (8)
bInterval:            0x04

Configuration Descriptor:
wTotalLength:       0x0029
bNumInterfaces:       0x01
bConfigurationValue:  0x01
iConfiguration:       0x04
0x0409: "Config 1: ECM network"
bmAttributes:         0x80 (Bus Powered )
MaxPower:             0x7D (250 Ma)

Interface Descriptor:
bInterfaceNumber:     0x00
bAlternateSetting:    0x00
bNumEndpoints:        0x02
bInterfaceClass:      0x03 (HID)
bInterfaceSubClass:   0x01
bInterfaceProtocol:   0x01
iInterface:           0x05
0x0409: "HID Interface"

HID Descriptor:
bcdHID:             0x0101
bCountryCode:         0x00
bNumDescriptors:      0x01
bDescriptorType:      0x22
wDescriptorLength:  0x0032

Endpoint Descriptor:
bEndpointAddress:     0x81  IN
Transfer Type:   Interrupt
wMaxPacketSize:     0x0008 (8)
bInterval:            0x04

Endpoint Descriptor:
bEndpointAddress:     0x01  OUT
Transfer Type:   Interrupt
wMaxPacketSize:     0x0008 (8)
bInterval:            0x04

Pythonスクリプトの作成

HIDのデバイスディスクリプタ「hidg0」に対して、x軸方向に移動に移動させるために、データの2バイト目に「0x10」を書き込みます

MouseExample.py

#!/usr/bin/env python3
NULL_CHAR = chr(0)

def write_report(report):
    with open('/dev/hidg0', 'rb+') as fd:
        fd.write(report.encode())

# x軸方向に移動
write_report(NULL_CHAR+chr(0x10)+NULL_CHAR)

pythonスクリプトの実行

作成したPythonスクリプト「MouseExample.py」を次のコマンドで実行します。実行すると接続されているパソコンのカーソルがx軸方向に移動します。

$ sudo python3 MouseExample.py

接続時にUSBマウスとして認識

RapberryPi Zero Wをパソコンに接続したときにUSBマウスとして認識するように、「 /etc/rc.local」 に次のスクリプトを追記します。また、chmod コマンドによりユーザにも使用を許可します。

/home/pi/hidtest/hid.sh
chmod -R 777 /dev/hidg0