コメを噛め

コメを噛め

rerofumi の電子工作メモ

hatena bookmark

取り敢えず、調べてみたもののちとめんどくさそうだということでお蔵入り。
解析結果だけ置いておく。

■ 要求項目

「Wii のバーチャルコンソールを『ジョイスティック』で遊びたい」

そのために。
Wii リモコンに、クラシックコントローラの代わりにジョイスティックを接続したい。

それを実現するためには。
クラシックコントローラと同じプロトコルで通信し、クラシックコントローラを名乗るようなマイコンのソフトウェアを作成すれば良いだろう。後は、マイコンに任意の入力インタフェースを繋いでバーチャルコンソール遊び放題。

■ というわけで

Wii リモコンと拡張コントローラの通信を調べる。

■ 前提、調査前にわかっていたこと

Wii リモコンと拡張コントローラは I2C で通信を行っている。

先人による調査結果がいくつか存在する。
中でも WiiLi.org が一番情報も多く良くまとまっている。
だが、それらは全て Bluetooth 経由で PC から Wii リモコンを見ている時のものなので、ダイレクトにクラシックコントローラとお話した人はほとんど居ない。つか、そういったことをしようという目的が今まで無かったのだと思われる。

以下、概要。

・I2C バスは 3.3V でプルアップされており、クロックは 400kbps
・クラシックコントローラのスレーブアドレスは 0x52
・ヌンチャクのスレーブアドレスも 0x52
・クラコンかヌンチャクかは接続後 ID で判別し、対応を分ける
・I2Cデバイスとしては一般的な、送信データ先頭の1バイトを内部アドレスとして以後のデータはその内部アドレスからインクリメントされていく方式
・内部アドレスは 8bit(=1byte) 00h〜ffh
・内部アドレス 00h から 6byte 読み出すとそれがパッドの情報
・内部アドレス 40h に 0x00 を描き込むとデバイススタート、これを行わないとデータが出てこない
・送られてくるデータは暗号化されている

■ プロトコルを調査してわかったこと

単純にスレーブアドレス 0x52 の I2C デバイスをぶら下げてもパッドとして認識されない。Wii リモコンは拡張コントローラが接続されたときに確認のため、なにかしら認証通信を行っているはずである。
ケーブル内、白いコードがコントローラ内部で GND に結線されている。Wii リモコン本体はおそらくこれが GND に落ちることで、拡張コントローラが接続されたものと認識し、handshake を開始するものと思われる。

以下が接続時のプロトコル。
後述するけれども、値が毎回変わるので一例として。

ここから – – – – – – – – – – – – –
A4 F0 AA
A4 40 A4 DD 6D 0C 2F 7E
A4 46 F2 83 D4 E0 FD 26
A4 4C E3 B3 98 67
A4 FE
A5 B9 80
A4 00
A5 F0 9C D1 A6 3A EF
A4 00
A5 F0 9C D1 A6 3A EF
A4 00
A5 F0 9C D1 A6 3A EF
A4 20
A5 70 40 CD B0 1C 6F A3 FE
A5 EC 92 3F 24 1A 8F 3D B7
A4 30
A5 70 40 CD B0 1C 6F A3 FE
A5 EC 92 3F 24 1A 8F 3D B7
A4 00
A5 F0 9C D1 A6 3A EF
A4 00
A5 F0 9C D1 A6 3A EF
(以後パッドデータ通信が続く)
– – – – – – – – – – – – – ここまで

最初の F0h に 0xAA を書き込んでいるのは意味が無くて、おそらくコントローラの存在確認。
ここで ACK が返ってきていれば、コントローラが接続されているものと判断できる。

40h から 16byte 書き込んでいるが、この書き込む値は 16byte とも毎回異なっている。これが、暗号の鍵でこれによって以降コントローラが返す値が暗号化される。

次に FEh から 2byte 読み込んでいるが、ここで既にデータが先の鍵で暗号化されている。この 2byte がコントローラの種別を表す ID でヌンチャクとクラシックコントローラで異なっている。
ちなみにクラシックコントローラの時、素のデータは 01h,01h である。

00h から 6byte の読み込みはパッドデータの受信。
6byte のパッキングフォーマットは WiiLi.org の情報を参照する。

パッド情報を 3つ拾った後おもむろに 20h, 30h から 16byte ずつ読み込んでいるが、これはコントローラ個別のキャリブレーションデータではないかと言われている。基本 20h と 30h は同じ値が書かれている。冗長性(データが壊れたときのフォロー用)のためにセットであるのではないだろうか。値の意味は判明していない。
このデータは個体別で、同じヌンチャクであってもコントローラ毎に違う値を持っている。
おそらくは、先に 3つ読んでいるパッド情報とこのキャリブレーションデータから、なんらかの初期状態を読み取っているのだと思われる。

以降は 00h からパッド情報を読み取るだけとなる。

暗号については、40h に 0x00 を書き込んだとき、
x = (y xor 0x17) + 0x17 の x が送信されることがわかっている。
この 0x17 が暗号の鍵から生成されたシードで、鍵によって毎回変化しているのではないかと思われる。

■ というわけでひとまずあきらめ

実装をするためには、鍵とシードと暗号の関係をほぐさないとならないので今回はひとまずあきらめる。
といっても、特定条件時のシードはわかっているし、FEh からの固定値もわかっているので、後は何回かデータを収集して法則性を見つけるだけだとは思う。

ちなみに、マイコンにクラシックコントローラを繋いで入力インターフェースにすることは問題なくできた。でもそれは今回の要求ではないのです。

こんなところからマイコンシリアル通信に触れてみませんか?(とかいう

2 Comments to “Wii クラシックコントローラとの通信”

  1. kako Says:

    私もヌンチャクを調べていて同じような結果になりました。あと、ヌンチャクのチップを引っ剥がしてクラシックコントローラーの基板に取り付けると、クラシックコントローラーとして動作するというのを試してみました。しかし、どういう仕組みでパッドデータの送信フォーマットなどの挙動がヌンチャクとクラコンで替わるのかが謎。

  2. rerofumi Says:

    kakoさんの活躍に期待していました :-) コントローラ自体は同じものなのですか、興味深いですね

Leave a Reply