背景
XboxのコントローラーをESP32でBLE通信して使うライブラリを更新していたところ、HID(service: 0x1812)のReport(characteristic: 0x2a4d)が書き込み可能と気づきました。XboxのコントローラーにはLEDは無いものの振動(バイブレーション)機能はあるのでそれの制御口と期待して試行錯誤したところ、期待通り制御できました。
分かったことを記事にまとめます。
対象
Xboxのコントローラー【純正品】Xbox ワイヤレス コントローラー + USB-C ケーブル
9000円弱出して2週間ほど待って良いのならxbox design labで色を選んで買えます。
Xbox Design Lab
コントローラーのファームウェアはxbox accessoriesで最新版にしてください。
この記事では2022年9月に公開されたであろうxbox accessoriesを利用して、バージョン5.15.3168のファームウェアをコントーローラーに書き込んで動作確認しています。
把握した書き込み内容
試行錯誤の末把握したHID Reportの内容がこちらです。byte順 | 役割 | 設定範囲 |
---|---|---|
0 | モーターの選択 0bit: 中央モーター 1bit: 揺さぶりモーター 2bit: 右モーター 3bit: 左モーター 4-7bit:未使用 | 0:無効 1:有効 |
1 | 左モーターの強さ | 0~100 |
2 | 右モーターの強さ | 0~100 |
3 | 揺さぶりモーターの強さ | 0~100 |
4 | 中央左モーターの強さ | 0~100 |
5 | 振動時間 | 0~255(最長2.55秒) |
6 | 休止時間 | 0~255(最長2.55秒) |
7 | 繰り返し回数 | 0~255(回) |
範囲が0~100の領域に100以上の値を書き込むと100と同じ動作をします。
0byteの4-7bitは後半で解説するReport Mapでも用途が示されない最大値が0の区画なので、使用されていないようです。
上記の設定により下記の動作をします。
- 休止時間分待つ
- 振動時間分選択したモーターを指定された強さで駆動
- 繰り返し回数が1回以上の場合、上記1と2を指定回数分繰り返す
動作中に書き込みがあった場合、動作を止めて新しい指示に従います。
通信が途切れると動作停止します。
全てのビットを1にして8byteを送信すると2.55秒毎に全てのモーターの全力振動が255回繰り返されるので、意図せずそうなった場合は通信を切るか新しく何かを書き込むのが良いです。
書き込み先はservice: 0x1812, characteristic 0x2a4dの書き込み可能な方
ESP32でNimBLEを利用してHID(service: 0x1812)に紐づくcharacteristicを表示すると、下記の情報を確認できます。Service: uuid: 0x1812, start_handle: 22 0x0016, end_handle: 35 0x0023
Characteristic: uuid: 0x2a4a, handle: 24 0x0018, props: 0x02
Characteristic: uuid: 0x2a4c, handle: 26 0x001a, props: 0x04
Characteristic: uuid: 0x2a4b, handle: 28 0x001c, props: 0x02
Characteristic: uuid: 0x2a4d, handle: 30 0x001e, props: 0x12
Descriptor: uuid: 0x2902, handle: 31
Characteristic: uuid: 0x2a4d, handle: 34 0x0022, props: 0x0e
Reportである0x2a4dは2つありまして、その片方のhandleが34のものが書き込み可能なReportのcharacteristicです。
2つあるのが詰まりどころで、serviceとcharacteristicのidで取得を試みると書き込みできない方のcharacteristicが先にあるためそちらが取り出されてしまいます。
characteristicの絞り込み条件に書き込み可能の有無を指定できない場合は、一覧を出して書き込み可能なものを取り出すのが良いです。
書き込み内容はReport MapのReport ID3として説明がある
s:0x1812 c:0x2a4b h:28で読み取れる情報はReport Mapと言う情報の構造説明になっています。これをReport Mapの解析webサービスに渡して見やすくしてもらい、Report ID3を抜粋したのが下記です。
0x05, 0x0F, // Usage Page (PID Page)
0x09, 0x21, // Usage (0x21)
0x85, 0x03, // Report ID (3)
0xA1, 0x02, // Collection (Logical)
0x09, 0x97, // Usage (0x97)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x00, // Logical Maximum (0)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x09, 0x70, // Usage (0x70)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x64, // Logical Maximum (100)
0x75, 0x08, // Report Size (8)
0x95, 0x04, // Report Count (4)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x09, 0x50, // Usage (0x50)
0x66, 0x01, 0x10, // Unit (System: SI Linear, Time: Seconds)
0x55, 0x0E, // Unit Exponent (-2)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x09, 0xA7, // Usage (0xA7)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x65, 0x00, // Unit (None)
0x55, 0x00, // Unit Exponent (0)
0x09, 0x7C, // Usage (0x7C)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
これを解釈すると
Report IDのPageの用途は0x21 Physical Interface Devices 物理装置
各Unitの解釈は
用途 | 試行錯誤して分かった用途 | ビット数 | 組数 | 最大値 | その他 |
---|---|---|---|---|---|
0x97 System Function Shift | モーターの選択 | 1 | 4 | 1 | |
空欄 | 不明 | 1 | 4 | 0 | |
0x70 Magnitude 大きさ | モーターの強さ | 8 | 4 | 100 | |
0x50 Duration 期間 | モーターの駆動時間 | 8 | 1 | 255 | 単位0.01 |
0x7a System Speaker Mute 消音 | 休止時間 | 8 | 1 | 255 | 単位0.01 |
0x7c Loop Count 繰り返し回数 | 繰り返し回数 | 8 | 1 | 255 |
用途の把握はHID Usage Tables (PDF)やDevice Class Definition for Physical Interface Devices(PDF)を参照しました。
Report Mapだけを見たときは意味を解釈できなかったのですが、試行錯誤して機能を把握した上で読み解くと試行錯誤して分かったのと同様の用途や数値などが指定されていたと分かりました。
ESP32で振動させました
何をどこに送ればコントローラーをどのように振動させられるか分かったので、ESP32のライブラリにも機能を追加しました。横で下記のプログラムを書き込んだESP32とxboxのコントローラーを接続すれば振動します。
examples/vibration/vibration.ino
終わり
Report ID3として管理される0x2a4dのcharactaristicに情報を書き込みxboxのコントローラーを振動させれました。BLEのReport IDの読み方を大まかに把握できました。
成果としてESP32のライブラリでコントローラーを振動させれました。
参考
BLE Keyboard(Surface キーボード) の Report MapUSB Descriptor and Request Parser(Report Mapの解析webサービス)
examples/vibration/vibration.ino
変更履歴
2024.10.05iframeのamazonへのリンクが無効になっていたので張り直しました。
0 件のコメント :
コメントを投稿