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