Arduino を Nintendo Switch のコントローラとして動かす方法。
Switch-Fightstick を利用する方法
Switch-Fightstickというものがある。
- オリジナルのプロジェクト
- Splatoon 2 で自動ドット打ちをしてくれるプロジェクト
- ゼルダの雪玉ボウリングを自動化してくれるプロジェクト
全部同じプロジェクト名なので注意が必要。
しかし、オリジナルのプロジェクトを fork して、それぞれの機能を付与しているだけなので、コアの部分は同じである。
色んな人が解説しているので、そちらを参照。
Arduino で使う場合は、AVR として使うため、Arduino の書き方や資産が利用できないので注意。
Switch-Arduino-Joystick を利用する方法
Switch-Arduino-Joystickというものがある。
こちらは多分未完成か、利用方法を説明していない。
使えるようにまでなったのでメモ書き程度に記載する。
前提
- リバースエンジニアリングをしているわけではないため、予想を含みます。
- マイコン歴も 10 日たらずで HID も全然わからないため、おかしなことを言っている可能性があります。
Switch に認識させる条件
- USB Host 機能を持つ Arduino(互換機)であること。
- Switch が認識する PID,VID とすること。
- デバイスの HID Report Descriptor は無視され、Switch が PID,VID をもとに HID Report Descriptor を指定している。(たぶん)
- 試しにデバイス(Arduino)の HID Report Descriptor で Button などを一切配置せずとも Switch を動かすことができる。
- ちなみに、プロコン自体に入っている HID Report Descriptor と Switch が指定する HID Report Descriptor が違うためか、この記事の方法ではプロコンの HID Report Descriptor を利用して、Switch に認識させることはできなかった。
Switch-Arduino-Joystick を認識させるために
- Switch-Fightstick も Switch-Arduino-Joystick もポッ拳プロコンの HID Report Descriptor を使用している。
- ポッ拳プロコンの HID Report Descriptor を使用する場合、PID,VID をポッ拳プロコンのものとすること。(下記「PID,VID の変更」参照)
- ポッ拳プロコンの HID Report Descriptor を利用する場合、REPORT ID がないため、Arduino 標準の
HID().SendReport(uint8_t id, const void* data, int len)
が利用できない点に注意。(下記「SendReport()の改変」参照)
PID,VID の変更
SparkFun のボードを利用している場合。
~/Library/Arduino15/packages/SparkFun/hardware/avr/1.1.12/boards.txt
を開き、利用しているボードの*.build.vid, *.build.pid を変更する。
SendReport()の改変
ポッ拳プロコンの HID Report Descriptor は、REPORT ID が記載されていない。
HID().SendReport()
の引数は(uint8_t id, const void* data, int len)であるため、先頭 1byte は id の送信に固定されている。
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/libraries/HID/src/HID.h
を下記の改変を行うことで回避する。
- HID.cpp(改変前)
int HID_::SendReport(uint8_t id, const void* data, int len)
{
auto ret = USB_Send(pluggedEndpoint, &id, 1);
if (ret < 0) return ret;
auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len);
if (ret2 < 0) return ret2;
return ret + ret2;
}
- HID.cpp(改変後)
int HID_::SendReport(uint8_t id, const void* data, int len)
{
// auto ret = USB_Send(pluggedEndpoint, &id, 1);
// if (ret < 0) return ret;
auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len);
if (ret2 < 0) return ret2;
// return ret + ret2;
return ret2;
}
上記手順にて、Arduino を Switch に認識させる事ができる。
全面コードを書き直して、新規ライブラリとして作成しました。
https://github.com/celclow/SwitchControlLibrary