日記要素強めです。

Too long; don’t read

そうですか

自分語り

筆者は家で RealForce を 2 台机に並べて primitive な分割キーボードとしてタイプしています。 つい最近まで、持病の都合で治療を待つためにリモートワーク状態 (ワークしているとは言っていない) を続けていて、だらだら大学院に居座り続けていたのですが、 その間は時期はかなり快適にやれていました。 何年かリモートワーク (療養) して、 思いのほか長い時間身体が保ったため最近さすがに修了を見据える気になり、 検査結果が悪くならない程度に修了要件に向けて進捗が正の実数で表せるくらいにしながら治療を待つことにしようと思いました。 ミーティング参加や後輩指導、オンプレの計算機のメンテナンスの都合を考えて研究室に顔を出すように決めたのですが、 次いつ長めの病床休暇が必要になるかわかりませんからなるべく机の上に私物は置かないようにすることにしました。 そういうわけでキーボードも RealForce を持ち運ぶことにしたのですが、 さすがに 2 台は持ち歩くには大きすぎて重すぎます。 しばらくは片割れだけを使っていましたが、復帰をするほど分割が恋しくなってきました。 そういうわけで、aliexpress で sophisticated (antonym of primitive) な分割キーボードを試しに買ってみることにしました。 分割キーボードを使いたいだけかつ修了したいだけなので、買ってすぐ使い始めたいです。 巷で流行っている「自作キーボードではない」こと、つまり組み立て済みで余計なカスタマイズ要素がないことを要件にいくつか探して、最終的に一つ注文してみました。 注文して届いたあと、 aliexpress で買ったような信頼できない USB 機器を雑にコンピュータに接続するのはセキュリティイシューな気がして、念の為できることをやっておこうと思いました。 いろいろ試した結果、購入したキーボードを安全に使うためにできること、最終的にはやらなければいけないと判明したことが結構多かったので日記として残しておこうと思います。

ところで、大学院を修了/中退したあと (いつになるかわかりませんが) の就職先を探し始めようと思っています。ご興味のある方は contact よりご連絡ください。

セキュリティ上の考察

筆者はセキュリティの専門家ではありません。この記事の情報を活用したことによる損失の責任はなるべく取りたくないです。

買ったもの

AliExpress ですでに基板が完成しておりキーキャップまでついている分割キーボードを買いました。 何を買ったかは、責任をなるだけ取らなくていいようにフォロワーにだけ教えます。知りたい方は連絡ください。

開封

開けて気づいたのですが、思っていたよりキーが足りません。特に右手側 (図 )。 Shift や Enter などは親指で押すものだと理解していましたが、まさかセミコロンや brackets, undescore 等のキーがないとは思いませんでした。 後で調べてみたところによるとこれらは 36-key keyboards や 30% キーボードというジャンル [, , ] で、うまくキーマップすればまともに使えるようになるそうです。40 % キーボードにはコミュニティ [] まであるそうです。 工作やらキーマップやらをしたくなくてなるだけ既成品っぽいものを選んだのですが、この要求は早速崩れ去りました。 でもせっかく買ったので仕事はもう少し realforce × 1 でこなし、ちょっとだけ遊んでみようと思います (本末転倒)。

いずれにせよ、まだこのハードウェアを信用していないので一旦背面パネルを開けてみます。すると図 に示すようにキースイッチがつながる受け手と細かい受動部品部品、パッド加えて STM32F103C8T6 が見えます。 STM32 の他に集積回路のようなものは見当たらなかったので、これが USB をしゃべるのだと予想できます。 この時点でファームウェアは完全に書き換え可能である可能性がかなり高いので、ファームウェアやドライバに関するセキュリティリスクはいくつかのステップを踏むことである程度までクリアできそうだと考えました。

ちなみに、図 で左側のパッドが汚れているのは後述するようにデバッグをしたからで、届いた時点ではこんなに汚くありませんでした。

Appearance of the keyboard
購入したキーボードの外観
Inside backpanel
右手側キーボードのバックパネルを外したところ。STM32 が見える。

捨てる前のコンピュータと消火器を用意する

まずは一番プリミティブな危険性を考えます。 一般に、今どきのキーボードは USB (Universal Serial Bus) を介して電気によって動作します。 つまり悪意があるかもしれないハードウェアには電力が供給されます。 最悪な状況として、例えば電気式の信管が起動して封入されている火薬に引火し、爆発するかもしれません。 そこまでなくても、DCDC コンバータかなにかによって USB ポートに高電圧がかかり、コンピュータを故障させられる可能性もあります []。 あるいは、対策がゆるいコンピュータなら VCC と GND をショートさせるだけでもかなりのダメージとなるでしょう。

念の為、コンピューターは壊れてもよいものを使用し、横に消火器をおいて仕事にあたることにします。 筆者は今回 Thinkpad X61s に (万一の場合は) 犠牲になってもらうことにしました (図 )。

Prepare in case
万一に備えてどうなってもいいパソコンを使用し、消化器も用意する。

尤も、このような機能を実行することはこれらを AliExpress で販売しようとする開発者・販売者にとってメリットが薄いように思えます。 攻撃対象者にハードウェアを確実に持たせることはできませんし、対象者を絞らないのであれば単なる嫌がらせにしかなりません。 少なくとも、お金儲けのためにやるにはリスクが釣り合っていません。 テロを目的としていても早々に出品が取り消されてしまい起こせるインパクトは小さいでしょう。 本当のことを言うと、今回はこれについてはあまり警戒しませんでした。

近距離無線通信による情報漏洩

ハードウェアをよく見て、アンテナや発振・変調回路がないか確認しましょう。 日本海を横断できるようなトランスミッターは大きなアンテナを必要とするだろうから一目でわかるはずです。

簡単には見つからないような小さくて通信距離が短い無線通信ハードウェアが搭載されていて、 悪意のある第三者が国内におり、受信機を手に日本中を練り歩いている可能性は低そうですがなくはないです。 気になる方は放出電磁波をスペアナかなにかで確認してみましょう。 筆者は確認してません。

ソフトウェアに関する危険

このキーボードが、ひいては搭載されている MCU (STM32) が、 Bad USB [] である、またはであるような機能を実行する可能性は十分考えられます。 どこにプラグするにしても、最初にプラグする相手への損害は避けられません。 一方で、ファームウェアが完全に書き換え可能でかつ MCU がそのファームウェアを (本当に) 実行するならば 自分で信用できるファームウェアを書き込むことでかなりの危険性を排除できるはずです。 以下 X61s を犠牲にしてこのキーボードのファームウェアを書き換えることを考えます。

提供されているドライバの危険

ドライバはホストコンピュータでほぼ任意のコードが実行できてしまいます。 販売者から受け取ったプロプライエタリなドライバはインストールや実行をしないようにしましょう。

キーボード (あるいはマウス、ゲームパッドなど) の場合は USB Human Interface Device (HID) class として使用しましょう。 HID class はよく使われるデバイスに対してホストとデバイスのコミュニケーションスキームを定義するもので、 ファームウェアがその規格に準拠してさえいれば汎用なドライバでデバイスを使用できるように作られています。 このようなドライバは OS インストール時に標準で入っていたり、または信用できるコミュニティがメンテナンスしているものを使用したりすることができます。 HID ドライバを使えばホストが悪意のある販売者のコードを実行してしまうことはほぼないでしょう。

提供されているされているファームウェアの危険

HID に準拠するハードウェアを HID ドライバで使用していても完全に安全と言えるわけではありません。 ファームウェアは HID プロトコルの下で任意のコードを実行できるからです。 例えば、ファームウェアにキーロガーを仕込んでおけばパスワードやクレジットカードを簡単に保存できます。 保存したものは例えば無線通信でどこかに飛ばすことができるでしょう。

または、HID キーボードは必ずしもユーザーの入力を忠実にホストへ送信するとは限りません。 HID キーボードはそのプロトコルに則り、ファームウェアが任意のタイミングで任意のキーを送信することができます。 この機能がキーボードマクロに代表されるよく使う文字列を自動入力するような実装で使われれば便利ですが、 悪意のあるファームウェアならキーボードショートカットでターミナルエミュレータを起動し、 コンピュータの情報を curl コマンドで送信することができます。 このくらいであればユーザーは異変にすぐ気付くでしょうが (気づいた時点で遅いですが)、他にどんな悪知恵が編み出されているかわかりません。

ファームウェアも信用のできるものを使用するのがよいでしょう。 ただし、最初の接続ではどうしても販売元が書き込んだファームウェアを実行することになります。 やはり人柱 (コンピュータ柱?) を用意するのがよいです。

ハードウェアが偽物である可能性

STM32 が偽物だった場合はどうでしょう。 ファームウェアを書き込もうとすると無効な応答を返す (そのようなエラーをライターから受け取る) 場合は、 印字とは異なる MCU が使われているか、悪意のある機能を実行する専用回路が組まれているかもしれません。 そのような場合はコンピュータ柱とハードウェアは処分してしまいましょう。 ただ、ASIC の製造は最小ロットが大きい関係もありかなり開発費・製造費がかさむことが考えられます。 開発者・販売者に対する費用対効果を考えると、ユーザーがどのくらいこのリスクを考慮する必要があるかは限定的かもしれません。 ただし、彼らが本気であれば、ユーザーが何を書き込んでもライターに対して有効なレスポンスを返し、かつファームウェアを実行しているような挙動を見せながら 裏で悪意のある機能を実行するハードウェアを作ることは可能でしょう。 これもやはり開発・製造の手間がかかりますが、その代わりそのことをユーザーが検知することはかなり難しいです。

今回はリスクをどこまで考える?

まず、販売者提供のプロプライエタリなドライバは信用しません。 そのようなドライバがどうしても必要だとわかれば、 このキーボードを使うのは諦めます。 基本的には HID キーボードとして、100歩譲ってオープンソースなドライバで使います。

また、プレインストールのファームウェアは信用しません。 囮のホストコンピュータを用意し、そこでファームウェアを信用できるものに書き換えます。 プログラムメモリや EEPROM をすべて一旦消去するのを忘れないようにしましょう。 特に今回使う STM32F103 シリーズは USB 機能をハードウェアとして持っておらず、 ソフトウェアで USB 通信を行います。 これにより、ハードウェアがない MCU でも USB デバイスとしての機能はもちろん、 USB 経由でファームウェアの読み書きができるようになるます。 いわゆる「ブートローダ」や「USB DFU」 などと呼ばれます。 ここもしっかり書き換えましょう。

囮のコンピュータが Bad USB な本キーボードによって攻撃され、 ファームウェアの書き換えが成功しているように見せかけられる可能性も考えられますが、 基本的にはこのリスクを無視します。 悪意のあるファームウェアが Windows を想定していることを願って、 とりあえず多少マイナーな (?) Debian Linux を使って作業をすることでリスクをちょっとでも下げます。

ハードウェアが偽物である可能性についてはとりあえず書き込みが成功する挙動を見せれば本物であるとみなします。

作業はすべて Debian Linux のライブイメージで行いたかったのですが、 rootfs がかなり小さく開発キットのインストールに堪えられませんでした。 使う部分をうまく bind mount すればライブイメージのまま作業ができそうでしたが、 APT パッケージマネージャを使う場合は起動時にすでに存在するディレクトリやファイルが必要になるので うまくコピーしてやる必要があります。これがうまく行きませんでした。 どうにか rootfs のファイルシステムを伸長して使えないか考えたのですが、この rootfs が tempfs であることを考えると難しそうなので、 結局USB メモリに Linux をインストールしてそこで作業することにしました。 実際やってみると、古いホストコンピュータを使ったこともありインストールに時間がかかったので ライブイメージでどうにかそこそこのストレージを rootfs としてマウントできるようにする方法を考えたいです。 ライブイメージの仕組み [] を考えると、おそらくカーネルを読んだあとに squashfs を ブートデバイスの適当な領域にコピーしてどうこうすることになりそうですが、難しそうです。

設定手順

ファームウェアは qmk [] とし、 キーボード定義・キーマップは savurov 氏のもの [] を使用します。 savurov 氏が公開するこのファームウェアは販売者に連絡をすると送られてくるファームウェアのソースコードと同じもののようです。 どちらがオリジナルなのかはわかりません。savurov 氏が開発者なのかもしれないし、どちらかが無断で再配布しているかもしれません。

ちなみに、インターネットで x7s firmware などと検索すると gleber のファームウェアや reddit の投稿が一番に現れるのですが、 右手側のキーボードが動作しません。 同氏の gist [] のコメントでも報告されています。 ただし gleber 氏は miryoku [] 配列を X7S に移植してくれているので、この部分は有効に使います。

bootloader 書き換え

まず bootloader を含む firmware を書き換える方法を考えます。 製品詳細のページ [] (適当に見つけたページで、販売元からリンクが送られてきたものではない) にある PCB layout の図によれば、 図 の右側にある 2 つのパッドはリセットとつながっているようで、 この端子でリセットするとファームウェアが (対応していれば status register をみてリセットを検知し) DFU モードで起動します。 これにより USB 経由でファームウェアの書き換えができるようになります。 あるいは qmk ファームウェアによってあるキーに QK_BOOT を割り当てることで、そのキーを押しながら電源を入れても DFU モードで起動します。 また、図 の左側にある 4 つのパッドは SWD 端子のようで、こちらからもファームウェアを書き込めます。 今回はプレインストールのファームウェアを信用しないことにしたので、SWD 経由でまずブートローダを先に書き込んでしまいましょう。 ちなみに、BOOT0 ピンをプルアップしながら起動することで USART でも書き込みができるようですが、 今回購入した製品は BOOT0 がプルダウンなしで GND に直結されていたため一度 PCB から外さないとこの方法は使えません。

余談ですが、上記 PCB レイアウトは本製品よりもシルクスクリーンがわかりやすかったり回路が一部違ったりします。 特にレイアウト図では BOOT0 にプルダウン抵抗がついていており適当にジャンプすることで High Level を与えることができるはずなのがなっていません。 筆者が購入したのは古いバージョンなのかもしれません。

実際に書き換えていきます。 まずドライバやライターソフトウェアを用意します。STM32CubeProgrammer [] を使います。 ウィザードに従えばライターソフトウェアとドライバがついてくるはずです。

続いて SWD 対応のデバッガを用意します。ST-Link シリーズが使えます。筆者は nucleo UM1724 を持っていたので、それに備え付けの ST-Link 機能を使いました。 備え付けの ST-LINK は工場出荷時で基板搭載の MCU とコミュニケーションを取るように設定されています。 これが外部の MCU と通信できるように、ユーザーマニュアル [] に従いジャンパを 2 つ外します。 キーボードのパッドにメスのピンヘッダを取り付けます。あとで取り外しやすいようにランドにピンヘッダを通すことはせず、表面実装のようなやり方ではんだ付けしました (写真なし)。 Nucleo の ST-Link のピンをキーボードと接続します。電源検出ピン、SWD Clock、SWD Data I/O、GND がつながれば OK です。 Nucleo のユーザーマニュアル [] と PCB layout [] をよく見て対応するように接続します。

STM32CubeProgrammer でブートローダ generic_boot20_pc13.bin を書き込みます。 有志 [] によれば maple_rev5_boot20.bin を書き込んでブートローダとして使用できるようですが、 私が試したところ USB 経由での書き込みができなくなり、かつ ST-Link がホストコンピュータに認識されづらくなってしまいました。 接触が悪いような挙動で、USB ケーブルをいじっているとたまに認識されるような状況だったのですが、ときどき認識されるタイミングで STM32CubeProgrammer を使いファームウェアアップデートをしたところ直りました。未だに何が起こっていたのかよくわかりません。

アプリケーション firmware 書き込み

上記手順で DFU がインストールされたので、 あとは qmk のドキュメンテーション qmk.fm [] の The QMK Tutorial (Use The Source 版) を書き込めばアプリケーションプログラムを実行できます。

firmware をコンパイルします。qmk firmware [] を git clone します。 このプロジェクトの keyboards/ 以下にキーボード定義ファイルがありますので、 そこに savurov 氏のファームウェア [] をコピーし、

qmk compile -kb x7s -km via

とします。

firmware を MCU に書き込みます。 MCU を DFU モードでブートするためにまず特別なピンをプルアップしながら USB ケーブルを接続します。 これは QMK ファームウェアによって QK_BOOT として定義されています (または自分で定義します) [] が わからないときはキーボードを逆さまにしてテーブルに押し付け、すべてのキーを押しながら接続することでなんとかなります。

あとは

qmk flash -kb x7s -km via

すれば書き込まれ、とりあえず使用可能になります。

使いやすいように firmware/keymap 修正

まず、 VIA はよくわからないので無効化します。キーマップの修正はファームウェアごと書き換えることで行うことにします。 ついでに COMBO を有効化します。

diff --git a/keyboards/x7s/keymaps/via/rules.mk b/keyboards/x7s/keymaps/via/rule
s.mk
new file mode 100755
index 0000000000..ee39adf4ce
--- /dev/null
+++ b/keyboards/x7s/keymaps/via/rules.mk
@@ -0,0 +1,4 @@
+#LTO_ENABLE      = yes
+
+VIA_ENABLE = no
+COMBO_ENABLE = yes

gleber氏が作ってくれた miryoku [] の x7s 実装 [] を持ってきて keyboards/x7s/keymaps/via/keymap.c に適用します。 キーボート定義が gleber 氏のものと savurov 氏のもので異なるので、変更を加えます。 キーの数が異なり、gleber 氏は実物と同じ 36 keysとして、savurov 氏は 40 keys で定義し存在しないキーは KC_NO で定義していく形なので、 レイアウトごとに例えば

[1] = LAYOUT(
        RESET,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_AGIN, KC_UNDO, KC_CUT,  KC_COPY, KC_PSTE,
        KC_LGUI, KC_LALT, KC_LCTL, KC_LSFT, KC_NO,   KC_CAPS, KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT,
        KC_NO,   KC_RALT, KC_NO,   KC_NO,   KC_NO,   KC_INS,  KC_HOME, KC_PGDN, KC_PGUP, KC_END,
-        KC_NO,   KC_NO,   KC_NO,   KC_ENT,  KC_BSPC, KC_DEL
+       XXXXXXX, XXXXXXX,   KC_NO,   KC_NO,   KC_NO,   KC_ENT,  KC_BSPC, KC_DEL, XXXXXXX, XXXXXXX
    ),

というように KC_NO またはその alias である XXXXXXX を追記します。 ところで、LAYOUT() は preprocessor で処理されるマクロなので、最後のエントリのあとにカンマをつけると処理系でエラーとなります。 注意してください。

最初はこの配列で使っていたのですが、いくつか修正をしました。 全体像は筆者の fork のソースコードから確認できます。 まず、gleber 氏のソースは miryoku 配列と言いながらアルファベットは qwerty であるためクォートが存在しません。 タイプするだけなら IME 経由でできなくもないのですが、vim の register 操作でかなり困るので Symbols layer に追加しました。 次に、miryoku 配列では shift や ctrl などの modifier がアルファベットキー長押しに割り当てられていますが (e.g., hold F for shift) 筆者のタイピングは指がキーに残る傾向があり意図せず modifiers が効いてしまうためそれらを親指に割りてました。 Shift や Crtl はもちろんよく使いますが、WM に qtile を採用しているため Super キーもよく使います。ただキーが足りなかったのでこれは COMBO にしました。ちょっとやりづらいので良い方法を考え中です。例えばタイピングがそこで一旦止まることが多い period, comma やハテナの hold で割り当てるなど。 Modifiers を親指に割り当てた結果 layer が減ってしまったので単キーでの Copy/Paste を犠牲に arrow keys を割り当てました。クリップボード関連は親指を頑張って Ctrl-{X,C,V} で頑張ろうと思います。 あとは IME の direct/ひらがなの切り替えを変換/無変換キーで行っているのでそれらの割当も追加しました。マクロはなかったようなので キーコード (スキャンコード?) である 0x8A/0x8B を追加しました。USB の規格としても決まっているようです []。

keymap の diagram 生成

keymap を大きく変えたら、それを忘れてしまってもいいように assignment の図を作って忘れたときにスッと (ソースコードを見ずに) 参照できるようにしておきたいです。 keymap-drawer.streamlit.app というツールがあるのでこれを使います。 keymap-drawer は qmk c2jsonkeymap.c から出力する json ファイルから図を作ります。 ただ、いくつか制約がありました。 c2json が正しく json を出力しないこと、 X7S のキーボード定義が存在しないこと、 keymap-drawer が COMBO に対応していないことです。

c2json の出力の修正

まず、qmk c2json で得られる keyboards/x7s/keymap/via/keymap.c の json 表現から 変換/無変換キーを表す 0x8A, 0x8B という記述が無視されてしまいます。 空文字列なエントリが作成されるのではなくエントリの数が減ります。 こうなると keymap-drawer 側でキーが足りない旨のエラーが起こるので手動で文字列 "0x8A", "0x8B" を追加してあります。どうせ手で書き換えるので "Henkan""無変換" にしても良かったかもしれません。

X7S キーボード定義ファイルの作成

X7S キーボード定義ファイルが組み込みで存在しないので、似ているキーボード定義から作り直します。 今回は corne_rotated の LAYOUT_split_3x5_3 を編集します。実はこのレイアウトは X7S と同じなのですが savurov のファームウェアは親指キーを多く見積もっているのでそこを合わせます。 キーを 4 つ追加するだけです。

--- /tmp/original.json  2024-12-22 18:01:02.666168415 +0900
+++ /tmp/target.json    2024-12-22 18:01:21.056161344 +0900
@@ -30,11 +30,15 @@
     {"x": 10, "y": 2},
     {"x": 11, "y": 2.125},
     {"x": 12, "y": 2.375},
+    {"x": 0, "y": 3.2},
+    {"x": 1, "y": 3.2},
     {"x": 2.5, "y": 3.158},
     {"x": 3.6, "y": 3.305, "r": 15, "rx": 4.1, "ry": 3.805},
     {"x": 4.77, "y": 3.255, "h": 1.5, "r": 30, "rx": 5.27, "ry": 4.005},
     {"x": 7.23, "y": 3.255, "h": 1.5, "r": -30, "rx": 7.73, "ry": 4.005},
     {"x": 8.4, "y": 3.305, "r": -15, "rx": 8.9, "ry": 3.805},
-    {"x": 9.5, "y": 3.158}
+    {"x": 9.5, "y": 3.158},
+    {"x": 10.5, "y": 3.2},
+    {"x": 11.5, "y": 3.2}
   ]
 }

COMBO が表示されない

諦めます。

生成されたダイアグラム

に以上の手順を経て生成されたダイアグラムを示します。

generated keymap diagram
筆者の現状のキーマップ。COMBO は表示されていないが、ESC+DEL で Super、SPC+DEL で Alt が発効する。

使用感

以上でとりあえず使えるようになりました。 実際に使ってみると、筆者は行ががキー半個ずつズレているふつうの (?) レイアウトに慣れており、 たとえば B は右手の人指し指でタイプしたり、C は左手人差し指でタイプしたりするので その点でかなり慣れません。 また Enter, Backspace や Modifier など親指でタイプするやつも全然覚えられません。 このあたりは慣れればなんとかなると信じて毎日赤ちゃんみたいなタイピングを研究室でやっています。

数字と記号がテンキー式なのは結構うまく使えています。 数字と記号の対応が頭に入っているためそこそこ直感的に指を運べるのだと思います。

一部の modifier の組み合わせをタイプするのが複雑になるのが改善点です。 たとえば qtile にて window を workspace の ‘5’ に移動させたいときは Super-Shift-5 を押すことになっているのですが、Super は COMBO で 5 は Num layer にあるため

Super (左手親指と右手親指の COMBO)-Shift (左手親指)-Num Layer (右手親指)-5 (左手中指)

と (定義上) 親指一本で 2 つのキーを押す必要が出てきます。実際は指を弐寺プレイ時のように (弐寺やったことなし) くぐりまたがせてどうにか押しています。 指も苦しいしタイプするのに一瞬組み合わせを考えないといけないのがストレスなところですが、筆者はピアニストなのでそのうち慣れていきたいと思います (?)。

References

  • https://shop.yushakobo.jp/products/nomu30kit?srsltid=AfmBOopLUMC7mair6QRR_h4Q0YDsJQaHXU182xH2hQNqQ_LF6CQgavfh
  • https://cerbekos00.hatenablog.com/entry/tata30_buildguide
  • https://keeb-on.com/products/bethirty
  • https://www.google.com/search?q=30%25%20keyboard
  • DC Correspondent, "USB Killer: A device that can destroy a PC in seconds", DECCAN Chronicle, 2016, https://www.deccanchronicle.com/technology/in-other-news/120916/usb-killer-a-device-that-can-destroy-a-pc-in-seconds.html (accessed on Dec. 19, 2024)
  • Bernie Thompson, "What BadUSB Is and Isn't," Plugable Technologies, 2014, https://plugable.com/blogs/news/what-badusb-is-and-isnt?_gl=1%2A86afs9%2A_gcl_au%2AMTI3NjU5OTU2MS4xNzM0NTk4NDEx (accessed on Dec. 19, 2024)
  • https://plugable.com/blogs/news/what-badusb-is-and-isnt?_gl=1%2A86afs9%2A_gcl_au%2AMTI3NjU5OTU2MS4xNzM0NTk4NDEx
  • https://github.com/qmk/qmk_firmware
  • https://github.com/savurov/x7s
  • https://gist.github.com/gleber/8d6c90d16dee45db2dd458814d3dd1fc
  • https://admin.jlc-code.com/pages/review/index?context=bo&traceCode=2kx9vqhz04xv
  • https://www.st.com/ja/evaluation-tools/nucleo-l476rg.html#documentation
  • https://www.st.com/ja/development-tools/stm32cubeprog.html
  • https://gist.github.com/gleber/8d6c90d16dee45db2dd458814d3dd1fc?permalink_comment_id=5321335#gistcomment-5321335
  • https://qmk.fm/
  • https://github.com/qmk/qmk_firmware/blob/master/docs/flashing.md
  • https://github.com/manna-harbour/miryoku
  • USB Implementers' Forum, "Universal Serial Bus (USB) HID Usage Tables," usb.org, pp.53--60, https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf