Infinity ErgoDox のファームウェアを Kiibohd から QMK に変更した方法

Infinity ErgoDox のキーカスタマイズは Kiibohd がデフォルトですが、それを QMK に変更したのでその方法をまとめました。Infinity ErgoDox を作ったときの記事は[こちら](https://qiita.com/ma2ge/items/d7f951a19b556a720641)。

目的としてはもともと持っていた ErgoDox EZ 向けにカスタムした QMK のキーマップをそのまま Infinity ErgoDox でも使いたかったためです。せっかく [Elixir の `|>` を1つキーを押せば入力できるようにした](https://speakerdeck.com/ma2gedev/make-it-easy-to-input)ので、Kiibohd でもう一回同じことをするのを避けたかったというのもあります。

:warning: 自分が試してできたことを記載していますが、実際に挑戦するときは自己責任で。

## 環境

- Mac OSX
- Infinity ErgoDox(2017/5 に Massdrop で購入)


## tools

### ファームウェアの書き込み

- dfu-util
  - http://dfu-util.sourceforge.net/

```bash
$ brew install dfu-util
```

[公式にも書いてある](https://input.club/configurator-setup/)ようにファームウェアの書き込みは dfu-util を使う。
dfu-util はファームウェアをデバイス上に USB を通して書き込んだり、逆に取得したりできるツールのようです。


### QMK のビルド向け

[QMK の公式](https://docs.qmk.fm/getting_started_build_tools.html#macos)にあるように homebrew で以下をインストールする。5月くらいにビルドした時よりツールが増えていたので、上手くいかない時は公式を改めて見た方が良い。

```bash
$ brew tap osx-cross/avr
$ brew tap PX4/homebrew-px4
$ brew update
$ brew install avr-gcc
$ brew install dfu-programmer
$ brew install gcc-arm-none-eabi
```


## Infinity ErgoDox への書き込み手順

基本的には [QMK のドキュメント](https://github.com/qmk/qmk_firmware/blob/master/keyboards/ergodox_infinity/readme.md)にある手順のまま実行しています。
Infinity ErgoDox は右手左手それぞれ独立したボードなので、それぞれに対して書き込みをする必要があります。

※ 全て root ユーザで全て実行しています
※ 以下の KEYMAPNAME の所を自分のマップ名にしてください


1. まず fork して `git clone git@github.com:qmk/qmk_firmware.git` してきた qmk_firmware のトップディレクトリへ移動しておく
1. `$ make ergodox_infinity:KEYMAPNAME` でビルド
1. 左手用の Infinity ErgoDox を接続し(右手側は接続しないこと)、ボードの裏にあるリセットボタンを押す
  - ![リセットボタンを押すと LCD がオレンジに光る](https://qiita-image-store.s3.amazonaws.com/0/17636/bb63d62f-d279-be59-d0c4-81386c8d6b30.jpeg "リセットボタンを押すと LCD がオレンジに光る")
1. `$ make ergodox_infinity:KEYMAPNAME:dfu-util` で書き込み
  - 自分の場合はここで失敗したので(*1 詳細は後述)、`$ dfu-util --device 1c11:b007 -D .build/ergodox_infinity_KEMAPNAME.bin` としました
1. `$ make ergodox_infinity:KEYMAPNAME MASTER=right` で右手側をビルド
1. 右手用の Infinity ErgoDox を接続し(左手側は接続しないこと)、ボードの裏にあるリセットボタンを押す
1. `$ make ergodox_infinity:KEYMAPNAME:dfu-util MASTER=right` で書き込み
こちらも自分の環境では同じように失敗したので、`$ dfu-util --device 1c11:b007 -D .build/ergodox_infinity_KEMAPNAME.bin` で書き込みました
1. 各キーが意図した通りに動くか確認

書き込みが正しくできると LCD 部分が Input Club のロゴから QMK 独自のものに変わります。

![LCD に表示されるデフォルトの Input Club のロゴ](https://qiita-image-store.s3.amazonaws.com/0/17636/1362e3fe-f8c4-428d-786e-e2bfbec573b4.jpeg "デフォルトの Input Club のロゴ")

![QMK へ書き換え後の LCD 表示上が起動時で、下が起動中](https://qiita-image-store.s3.amazonaws.com/0/17636/1d72982c-3ac8-e143-625e-45d3ea54e87c.jpeg "QMK へ書き換え後の LCD 表示上が起動時で、下が起動中")


#### *1 `$ make ergodox_infinity:KEYMAPNAME:dfu-util` でのエラーについて

具体的には以下のようなエラーが出てきました。いくつか USB 関連デバイスがあることが原因のようです。

```
dfu-util: More than one DFU capable USB device found! Try `--list' and specify the serial number or disconnect all but one device
```

対処で示した --device の `1c11:b007` は `dfu-util --list` を実行して出てきた、Infinity ErgoDox の PCB を指しています。

```
$ dfu-util --list
...省略...
Found DFU: [1c11:b007] ver=0000, devnum=13, cfg=1, intf=0, path="20-1", alt=0, name="Kiibohd DFU", serial="mk20dx256vlh7"
```

## QMK で KC_LANG1, KC_LANG2 が動かない

上記まででほとんど上手くいっていたのですが、LANG1, LANG2 が動かないことに気づきました。
自分の場合は Mac で英数、かな切り替えに頻繁に利用するキーなので使えないのは困ります。

調べてみると、ErgoDox EZ は vvakame さんの Issue レポート経由で直っています。事実自分の ErgoDox EZ では問題なく動いています。

> Can't use KC_LANG1 & KC_LANG2 key · Issue #312 · qmk/qmk_firmware https://github.com/qmk/qmk_firmware/issues/312

コードリーディングしてみると、そもそも下回りがかなり違うことを知りました。
ビルドする際にも EZ と比べて Infinity ErgoDox 向けにはかなり大量のファイルをコンパイルしています。

そのため ErgoDox EZ と同じ問題が、Infinity ErgoDox 向けで治っていないと当たりをつけて対応したところ動きました。
この対応は [Pull Request](https://github.com/qmk/qmk_firmware/pull/1936) を送ってマージしてもらったので、たぶん今後は起こらないと思います。

問題としては USB の HID Report Descriptor を返すところで、キーボード側が送るキーコードの最大値として 255 を送っているつもりが、
signed int 扱いで -1 を返していることが原因なようです。これを 255 と認識できるように返すようにしました。

vvakame さんの Issue で解決されたものと同一原因だったので対応としては簡易だったのですが、
どういった問題か理解するために [USB の仕様書](http://www.usb.org/developers/hidpage/HID1_11.pdf)を読むことになったり、
[hid_listen.mac](https://www.pjrc.com/teensy/hid_listen.html) で Infinity ErgoDox が送ってくるキーのデバッグをしたり、普段とは違う世界を体験できて楽しかった。

## FAQ

FAQ というか自分が疑問に思ったこと。


### QMK に変更したら Kiibohd へ戻せるのか?

実は Infinity ErgoDox を作り終えた時点でデフォルトのファームウェアが ErgoDox EZ と異なるとは考えてもいなかったので、キーマップを共通化させられないかも?と思い慌てましたが、結論としては QMK から Kiibohd にも戻すことができました。

Input Club の configurator で作ったバイナリや、Kiibohd-controller で作ったバイナリを用意して、dfu-util で左手右手の PCB に書き込みを行えば元に戻せます。

戻し方はこんな感じでバイナリを焼くところは一緒。

```
# configurator で落としてきた firmware を解凍し、left_kiibohd.dfu.bin, right_kiibohd.dfu.bin をそれぞれの PCB に焼く
# 左手側を繋ぎ、リセットボタンを押す
$ dfu-util --download left_kiibohd.dfu.bin
# 右手側を繋ぎ、リセットボタンを押す
$ dfu-util --download right_kiibohd.dfu.bin
```


### なぜファームウェアを変更できるのか?

bootloader がよしなにやってくれるため。Infinity ErgoDox の bootloader については以下のドキュメントに書いてある。

> https://github.com/kiibohd/controller/tree/master/Bootloader

プロテクトされた領域に bootloader が置かれているようなので、間違って bootloader を書き換えてしまうリスクは低く、色々なファームウェアの書き換えに挑戦しやすくできている。


### QMK は Infinity ErgoDox もサポートしている?

QMK が Infinity ErgoDox へ対応したのはこの PR のおかげ。感謝!!! :pray:

> ChibiOS and Infinity Ergodox support for QMK · Issue #381 · qmk/qmk_firmware https://github.com/qmk/qmk_firmware/issues/381


### ErgoDox EZ と Infinity ErgoDox の下回りは何が違う?

QMK の `rules.mk` に書かれている内容を見る限り、ErgoDox EZ は ATmega32U4 で、Infinity ErgoDox は Cortex-M4 とのこと。この辺りよくわかっていないので参考程度に見ていただきたいですが、以下のような感じっぽい。

|   | ErgoDox EZ | Infinity ErgoDox |
|:-:|:-:|:-:|
| CPU  |  16 MHz | 72 MHz |
| Flash | 32K | 256K |
| RAM  | 2.5K | 64K |

qmk_firmware でコンパイルされるコードが大きく異なっているのも納得です。

```
# rules.mk
# ErgoDox EZ
MCU = atmega32u4

# Infinity ErgoDox
MCU_FAMILY = KINETIS
MCU_SERIES = K20x
MCU_LDSCRIPT = MK20DX256BLDR8
MCU  = cortex-m4
```

## まとめ

ファームウェアが異なるので色々心配でしたが、[こちら](http://hidekingerz.hatenablog.com/entry/2017/10/04/231532)のブログ記事を読んだり、ErgoDox EZ とキーマップを共通化したかったので、チャレンジしてみました。結果としてはトラブルありつつも、普段とは違うことができ、最終的には目的が達成できたので満足。


## 参考リンク

- https://github.com/ma2gedev/qmk_firmware/tree/ma2gedev
  - 自分のキーマップはこちら
- InfinityErgodoxを作った話 - 人生の暇潰し http://hidekingerz.hatenablog.com/entry/2017/10/03/231712
- MacbookPro15inchでInfinityErgodoxに直接ファームを焼く話 - 人生の暇潰し http://hidekingerz.hatenablog.com/entry/2017/10/04/231532
  - QMK が焼けることをこちらで知りました。感謝。
- Install Build Tools · QMK Firmware https://docs.qmk.fm/getting_started_build_tools.html#macos
  - QMK で必要なビルドツール
- http://www.usb.org/developers/hidpage/HID1_11.pdf
  - USB の Human Interface Device 向け仕様書
- Can't use KC_LANG1 & KC_LANG2 key · Issue #312 · qmk/qmk_firmware https://github.com/qmk/qmk_firmware/issues/312
  - ErgoDox EZ で KC_LANG1, KC_LANG2 が動かない件の Issue レポート
- controller/Bootloader at master · kiibohd/controller https://github.com/kiibohd/controller/tree/master/Bootloader
  - Infinity ErgoDox の bootloader(たぶん)
- HID Listen program, or simple text debug output with Teensy USB https://www.pjrc.com/teensy/hid_listen.html