「RapberryPi Zero WをUSBマウスに」でRapberryPi Zero WのUSBマウスを作成しましたが、今回はゲームパッドを作成し、接続されたパソコン側でゲームパッドからデータを入力します。
RapberryPi Zero Wをゲームパッドに
HIDリポートディスクリプタは、HID Descriptor Toolを使用します。「HID Descriptor Tool」からHID Descriptor Tool「dt2_4.zip」をダウンロード・インストールし、入出力するHIDリポートディスクリプタを定義していきます。次にHID Descriptor ToolでゲームパッドのHIDリポートディスクリプタを定義した画面を示します。
入力したHIDリポートディスクリプタを次に示します。ボタンは3個、3ビットで、-32767~32767のx回転、y回転、z回転のそれぞれ16ビットデータのトータル7バイトをゲームパッドから入力できるようにしました。
char ReportDescriptor[54] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x05, // USAGE (Game Pad)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x33, // USAGE (Rx)
0x09, 0x34, // USAGE (Ry)
0x09, 0x35, // USAGE (Rz)
0x16, 0x01, 0x80, // LOGICAL_MINIMUM (-32767)
0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
「RapberryPi Zero WをUSBマウスに」のシェル「hid.sh」で作成したUSBマウスのHIDリポートディスクリプタを、19行目のようにHID Descriptor Toolで作成したゲームパッドのHIDリポートディスクリプタに書き換え、製品名称を13行目のような「TomoSoft USB Game Pad」に変更します。
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 "TomoSoft USB Game Pad" > 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\\x04\\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\\x03\\x05\\x01\\x09\\x33\\x09\\x34\\x09\\x35\\x16\\x01\\x80\\x26\\xff\\x7f\\x75\\x10\\x95\\x03\\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デバイス(ゲームパッド)の設定確認
パソコンで「コントロールパネル」から「デバイスとプリンター」を選択すると、次のようにゲームパッド「TomoSoft USB Game Pad」が表示されます。
ゲームパッド「TomoSoft USB Game Pad」を右クリックし、表示されたメニューから「ゲームコントローラの設定」を選択し、表示されたダイアログの「プロパティ」ボタンを押すと、つぎのようにHIDリポートディスクリプタが表示されます。
RapberryPi Zero WでのPythonスクリプトの作成
RapberryPi Zero Wで次ののゲームパッドPythonスクリプト「GamepadExample.py」を作成します。8行目で7バイトのデータを作成します。
GamepadExample.py
#!/usr/bin/env python3
def write_report(report):
with open('/dev/hidg0', 'rb+') as fd:
fd.write(report.encode())
def main():
write_report(chr(1)+chr(0x02)+chr(0)+chr(0x03)+chr(0)+chr(0x04)+chr(0))
if __name__ == "__main__":
main()
パソコンでのゲームパッドデータ入力ソフトの作成
ゲームパッドデータ入力ソフトはC#言語で作成し、「MightyDevices/MightyHID」で「MightyHID」のソースコードはそのまま、「MightyHIDTest」のソースコードを次のように書き換えます。
- 13行目で接続されているHID機器を取得します。
- 28行目で4番目に接続されているHID機器からのデータを受信できるようにOpenします。4番目としたのはゲームパッドが4番目の機器として接続されていることが、あらかじめわかっているためです。
- 30行目でゲームパッドからのデータを入力します。
using System;
using Mighty.HID;
namespace MightyHIDTest
{
class Program
{
static void Main(string[] args)
{
/* hello, world! */
Console.WriteLine("List of USB HID devices:");
/* browse for hid devices */
var devs = HIDBrowse.Browse();
/* display VID and PID for every device found */
foreach (var dev in devs)
{
Console.WriteLine("VID = " + dev.Vid.ToString("X4") +
" PID = " + dev.Pid.ToString("X4") +
" Product: " + dev.Product);
}
/* try to connect to first device */
if (devs.Count > 0)
{
/* new device */
HIDDev dev = new HIDDev();
/* connect */
dev.Open(devs[3]);
byte[] report = new byte[10];
dev.Read(report);
Console.WriteLine("input: " + report[0] + " " + report[1] + " " + report[2] + " " + report[3] + " " + report[4] + " " + report[5]+ " " + report[6] + " " + report[7]);
}
}
}
}
ゲームパッドの動作確認
パソコンでプログラムを実行すると次のデータが表示されます。RapberryPi Zero Wで作成したゲームパッドは最下段「VID = 1D6B PID = 0104 Product: TomoSoft USB Game Pad」に表示されています。
List of USB HID devices: VID = 1395 PID = 0025 Product: Sennheiser USB headset VID = 046D PID = C246 Product: G300s Optical Gaming Mouse VID = 08BB PID = 2704 Product: USB Audio DAC VID = 1D6B PID = 0104 Product: TomoSoft USB Game Pad
RapberryPi Zero Wで作成したPythonスクリプト「 GamepadExample.py」を実行して、ゲームパッドのデータをパソコンに送信します。
$ sudo python3 GamepadExample.py
ゲームパッドから送信されたHIDリポートディスクリプタが、次のようにパソコンの表示に追加されます。この値は、作成したPythonスクリプトで設定した値となります。ただし、最初の1バイトについては、制御情報(??)を付与するために追加されるようです。
input: 0 1 2 0 3 0 4 0
ゲームパッドからのHIDリポートディスクリプタが、次のように「ゲームコントローラの設定」で表示されたダイアログの「プロパティ」に表示されます。1番目のボタンが赤く点灯し、x回転、y回転、z回転のデータが少しづつ増加していることがわかります。



