
Raspberry Pi Pico W用ファームウェア。ドライバ不要のUSB Wi-Fiアダプタを作成し、透過的なレイヤ2ブリッジ、WPA2/WPA3認証、および帯域外管理コンソールを提供します。
= pico-usb-wifi :toc: macro :toclevels: 3 :idprefix: :idseparator: -
pico-usb-wifiは、Raspberry Pi Pico Wをドライバ不要のUSB Wi-Fiアダプタに変えるファームウェアで、USB CDC-NCMデバイスとして列挙されます。
:figure-caption: AIスロップ
.pico-usb-wifi 図 image::images/openrouter-banana2-rpi-pico.png[]
このファームウェアは、Pico Wの無線インターフェースとUSBインターフェースの間でフレームを転送する透過的なレイヤ2ブリッジとして動作します。 ホストのUSBインターフェースはPico WのWi-FiステーションのMACアドレスを採用し、エンドツーエンドで単一のMACおよびIP識別子を提供します。
ホスト側のドライバ、カーネルモジュール、ワイヤレススタックは不要です。<<no-host-side-wi-fi-stack,ホスト側Wi-Fiスタック不要>>を参照。
ホストに必要なのは、現代のすべてのLinux、macOS、Windows、モバイルOSに標準搭載されているcdc_ncmおよびcdc_acmドライバのみです。
== 機能
pico-usb-wifiは以下の機能を提供します:
.現実世界の状況 image::images/slop_2.png[]
== 存在理由
今後の組み込みLinuxプロジェクトでUSB Wi-Fiアダプタが必要だった。 安価なUSB Wi-Fiドングルを持っていなかったので、実店舗で5ドルで買いに行く代わりに、長い週末の2日間と約100万Claude Codeトークンを使ってこのファームウェアを構築した。
白一百, pico-usb-wifiの著者
Googleは実現不可能と言っていた:
.pico-usb-wifi "実現不可能" image::images/gemini_says_not_possible.png[]
toc::[]
== ホスト側Wi-Fiスタック不要
USB Wi-Fiドングルとは異なり、このアダプタはホストにイーサネットライクなインターフェースのみを公開します。 Pico Wが無線側全体(無線機、アソシエーション、WPA2/WPA3サプリカント、各国の規制ドメイン)を内包しています。
これにより、システムはwpa_supplicant、cfg80211/mac80211ワイヤレススタック、各国の規制データベース、チップセットファームウェアやベンダドライバのインストールを回避できます。
Wi-Fi認証情報のプロビジョニングは、ホスト側のワイヤレスツールではなく、デバイス上の帯域外管理コンソールを介して行われます。
これにより、リソースが制限されたアプライアンスホストや、ワイヤレスドライバがないホスト、あるいはベンダカーネルにワイヤレスドライバが不足しているホストでも、汎用CDCクラスドライバのみを使用して無線ネットワークに接続できます。
== 動作の仕組み
[#fig-topology] .トポロジ図 image::images/topology.svg[透過的なレイヤ2ブリッジトポロジ,820]
ホストのUSBインターフェースにはPico WのWi-FiステーションのMACアドレスが割り当てられるため、エンドツーエンドで単一のMACアドレスが存在し、Pico WはイーサネットフレームをUSBとWi-Fi間でそのまま転送できます。 Wi-Fiステーションは複数のMACアドレスをブリッジできないため、ホストとステーションを一つのMACに統合することで透過ブリッジが可能になります。 完全な根拠、データパス、IPv6/マルチキャスト処理については、<<architecture,アーキテクチャ>>を参照してください。
== ホスト要件
ホストには標準搭載のcdc_ncmおよびcdc_acmドライバが必要です。
どちらも10年以上メインラインLinuxの一部となっているため、現在サポートされているカーネルにはすべて含まれています。
外部モジュール、ファームウェアブロブ、ベンダドライバは一切不要です。
同じクラスドライバはmacOS、Windows 10以降、Android、iOSにも存在します。
[NOTE] 他のオペレーティングシステムではテストしていません。
== ビルド
このプロジェクトは標準のpico-sdk CMakeプロジェクトです。 ARM組み込みツールチェーン、CMake、ビルドバックエンド(NinjaまたはMake)、Python 3、およびサブモジュールを含むpico-sdkのチェックアウトが必要です。 pico-sdkにバンドルされているTinyUSBとlwIPはそのまま使用されます。
=== 依存関係
Arch系システム(Arch、CachyOS、Manjaro)では、公式リポジトリからツールチェーンが提供されます:
arm-none-eabi-newlibは組み込みCライブラリとヘッダを提供します。これがないとクロスコンパイラはstdint.hなどのヘッダを見つけられません。
libusbはpicotoolにのみ必要で、pico-sdkは最初のconfigure時にソースからビルドしてUF2を生成します。別途picotoolパッケージは不要です。
=== ビルド手順
git clone -b 2.2.0 --recurse-submodules https://github.com/raspberrypi/pico-sdk export PICO_SDK_PATH="$PWD/pico-sdk"
cp src/wifi_config.h.example src/wifi_config.h # その後SSID/パスワードを編集、または空白のまま cmake -S . -B build -G Ninja -DPICO_BOARD=pico_w -DCMAKE_BUILD_TYPE=Release cmake --build build
-G Ninjaフラグはオプションです。省略するとデフォルトのMakeジェネレータが使用されます(その場合はcmake --build build -j)。
wifi_config.hはコンパイル時のデフォルト認証情報を保持し、.gitignoreされています。
空白のままにすると、ベイクされた認証情報がないイメージが生成され、管理コンソール(<<management-console,管理コンソール>>)を使用して実行時にプロビジョニングされます。認証情報を記入すると、デフォルトネットワークがベイクされます。
== ファームウェアの書き込み
ここではボードへのファームウェアの書き込み手順を示します。
. BOOTSELボタンを押しながら、ボードをUSBで接続します。
ボードはRPI-RP2 USBマスストレージボリュームとしてマウントされます。通常は/run/media/<ユーザー>/RPI-RP2または/media/<ユーザー>/RPI-RP2にマウントされます。
. pico-usb-wifi.uf2をそのボリュームにコピーします。
ボードは自動的にファームウェアで再起動します。
. Wi-Fi接続を受け取るホストにボードを接続します。
== Linuxホストでの使用
デバイスをホストに接続し、管理コンソール(<<management-console,管理コンソール>>)を介してWi-Fi認証情報を一度プロビジョニングします。 ホストのインターフェースは、アクセスポイントのネットワーク上の有線接続と同様に動作します。
インターフェースを自動管理するホスト(NetworkManager、systemd-networkd、dhcpcd)は設定不要です。ブリッジ上でDHCPとSLAACを実行し、有線クライアントと同様に単一のIPv4アドレス、IPv6アドレス、アクセスポイントのゲートウェイ、DNSを取得します。
デバイス側のアドレスやゲートウェイを設定する必要はありません。Picoは何も保持していません。
インターフェースのMACアドレスはWi-FiステーションのMACであり、これによって単一の識別子がネットワークに提示されます。
ここでのipコマンドの出力は、結果のインターフェースを示しています:アクセスポイントのサブネット上の通常のDHCP/SLAACクライアントであり、ステーションのMACを持ち、Picoの痕跡はありません。
== 管理コンソール
管理コンソールは設定フロントエンドで、最初のCDC-ACMシリアル機能(通常は/dev/ttyACM0)にあります。
デバイスが列挙されるとすぐに(Wi-Fiがアソシエートされる前でも)アクセス可能なため、プロビジョニングにネットワークは不要です。
picocomやscreenなどのシリアルターミナルで開きます。USB CDCではボーレートは関係ありません。
コンソールは入力をエコーバックし、プロンプトを表示します。すべてのコマンドはデバイスの全状態を出力します。
Wi-Fi認証はWPA2-PSKまたはWPA3-SAE(AES)のいずれかです。
パスワードはネットワークのパスフレーズ、またはパスワードを空白にした場合はオープンです。
パスワードで保護されたプロファイルはWPA2/WPA3トランジションモードを使用するため、どちらの種類のアクセスポイントにも接続します。
コンソールは最大8つの認証情報_プロファイル_を保存します。1つは_アクティブ_プロファイルで、デバイスはそれにアソシエートします。
set ssid/set passはアクティブプロファイルを編集し、list/use/delはセットを管理し、scanは近隣のネットワークを検出し、番号付きリストから一つに接続します。これは、入力しづらい文字を含むSSIDに便利です。
コマンドワードは大文字小文字を区別しません。コンソールは小文字で表示します。
以下のセッションでは、スキャンによってネットワークをプロビジョニングしています。
$ picocom /dev/ttyACM0
変更は即座に反映され、アクティブプロファイルで再アソシエートします。再起動は不要です。
さらにネットワークを保存するには繰り返します。listで表示し、use <n>でアクティブプロファイルを切り替えます:
saveはすべてのプロファイルをフラッシュに永続化します。restoreは保存されたレコードを再読み込みすることで未保存の編集を破棄します。
以下の表はコマンドセットです。
[#tbl-config-commands] .管理コンソールコマンド [cols="2,3", options="header"] |=== |コマンド |効果
|set ssid <テキスト>
|アクティブプロファイルのSSIDを設定し(値にはスペースを含めることができます)、再アソシエートします。プロファイルが存在しない場合は最初のプロファイルを作成します。
|set pass <テキスト>
|アクティブプロファイルのWPA2/WPA3パスフレーズを設定し(オープンネットワークの場合は空白)、再アソシエートします。
|set country <CC\|WORLDWIDE>
|各国の規制コードを設定します(次回起動時に完全に適用されます)。
|set debug <on\|off>
|デバッグコンソールで診断情報をストリーム出力します。<<debug-console,デバッグコンソール>>を参照。
|list
|保存されたプロファイルを一覧表示し、アクティブなものをマークします。
|use <n>
|プロファイル_n_をアクティブにして再アソシエートします。
|del <n>
|プロファイル_n_を削除します。
|scan
|近隣のネットワークをスキャンし、スキャンサブメニューに入ります(back、join <n>、scanで繰り返し、またはliveで継続的な非アソシエートストリーム)。joinは選択したネットワークをアクティブプロファイルとしてステージし、set passの準備をします。
|save
|すべてのプロファイルと設定をフラッシュに永続化します。
|restore
|保存された設定を再読み込みして未保存の変更を破棄します。
|===
ホストに割り当てられたアドレスは、状態ダンプでhost IPv4およびhost IPv6として表示されます。Picoは報告するアドレスを持たないため、ブリッジトラフィックからパッシブにスヌーピングされます。
設定セクタはフラッシュの末尾にあり、プログラムイメージ(先頭)とは分離されているため、通常のpico-usb-wifi.uf2の再書き込みでは保存されたプロファイルはそのまま残ります(全チップ消去を行うと消去されます)。
例外はv1.1.0_への_アップグレードです。レコードレイアウトが複数プロファイルを保持するように変更されたため、v1.1.0より前のレコードは破棄され、ネットワークを再度入力する必要があります(変更履歴を参照)。
== デバッグコンソール
デバッグコンソールは、2番目のCDC-ACMシリアル機能(通常は/dev/ttyACM1)上の書き込み専用の診断ストリームです。
管理コンソールでset debug onが発行されるまで沈黙しているため、オフのときはコストがなく、管理を妨げることはありません。
有効にすると、アソシエーションの変更と定期的なブリッジ統計行を報告します(以下のセッションを参照)。
-DTRACE_FRAMES=1ビルドは、ブリッジされた各フレームの1行要約を追加しますが、負荷がかかるとコンソールが溢れるため、デフォルトではオフです。