2024年12月8日日曜日

Buildrootでiwdを使ってWiFiに自動で接続する。

 Luckfox Pico Mini BでRalink RT3070Realtek RTL8821CUを使ってWiFiに接続できたのは良いんだけど、起動時や途中で抜き差ししても自動で接続させたい。
カーネルモジュールの読み込みはudevでうまく動いたんだけど、ifupdown-scriptsのほうが組み込まれているためか、interfacesでallow-hotplugが使えなかったので他の手法を試してみることに。

wpa_supplicantの代替ということで、iwd (iNet Wireless Daemon)を試してみた。これはWiFiが切れたりしても自動で再接続してくれるし、hostapdいらずでAPモードも使えて便利そう。

Luckfox Pico Mini Bはフラッシュメモリが128MBなんだけど、色々入れすぎて容量がいっぱいになってしまったのでこの前入れたwpa_supplicant、iw、wireless toolsは削除して、iwdだけにしてみた。iwdはカーネルのCrypto APIの関係でカーネル側も変更が必要だった。

Ubuntu上のluckfoxのSDKで

cd $HOME/luckfox-pico/sysdrv/source/kernel
cp ./arch/arm/configs/luckfox_rv1106_linux_defconfig .config
make ARCH=arm menuconfig

メニューから選択してくのは面倒なので一旦Saveして閉じて
このディレクトリにある.configを開いて下記を全部yにする。

CONFIG_CRYPTO_USER
CONFIG_CRYPTO_USER_API_HASH
CONFIG_CRYPTO_USER_API_SKCIPHER
CONFIG_KEY_DH_OPERATIONS
CONFIG_CRYPTO_ECB
CONFIG_CRYPTO_MD5
CONFIG_CRYPTO_CBC
CONFIG_CRYPTO_SHA256
CONFIG_CRYPTO_AES
CONFIG_CRYPTO_DES
CONFIG_CRYPTO_CMAC
CONFIG_CRYPTO_HMAC
CONFIG_CRYPTO_SHA512
CONFIG_CRYPTO_SHA1
CONFIG_RFKILL

WiFi関連のためにmにしてあとから読み込んでいたのもあるんだけどinsmodしても認識されなかったのでyにして組み込んでしまった。

make ARCH=arm savedefconfig
cp defconfig ./arch/arm/configs/luckfox_rv1106_linux_defconfig

savedefconfigして次はアプリケーションの設定。

cd $HOME/luckfox-pico/sysdrv/source/buildroot/buildroot-2023.02.6/
make menuconfig

ここからwpa_supplicant、iw、wireless toolsのチェックを外して、iwdのチェックをいれる。

make savedefconfig
make clean
make

make cleanをしてしまったのでここで25分ぐらいかかった。make cleanしないとアプリケーションが消えないから容量が…

cd $HOME/luckfox-pico
./build.sh lunch
./build.sh

あとはビルドして書き込み。

luckfoxを起動したらluckfox側での作業。

udevでWiFiドングルが自動で読み込まれるようにまずはシェルスクリプトを編集する。
/oem/usr/koの中にinsmod_wifi.shがあったのでこれを書き換えた。ない場合は作ればいいかも。実行権限つけるの忘れずに。

#!/bin/sh
cmd=$(realpath $0)
_DIR=$(dirname $cmd)
cd $_DIR

export PATH=$PATH:/oem/usr/ko/

#RTL8821CU
if [ $1 = "8821cu" ]; then
	insmod cfg80211.ko
	insmod libarc4.ko
	insmod mac80211.ko
	insmod rtw88_core.ko 
	insmod rtw88_usb.ko 
	insmod rtw88_8821c.ko
	insmod rtw88_8821cu.ko
	insmod ctr.ko
	insmod ccm.ko
fi

if [ $1 = "r-8821cu" ]; then
	rmmod rtw88_8821cu.ko
	rmmod rtw88_8821c.ko
	rmmod rtw88_usb.ko 
	rmmod rtw88_core.ko 
fi

#RT2800USB
if [ $1 = "rt2800usb" ]; then
	insmod cfg80211.ko
	insmod libarc4.ko
	insmod mac80211.ko
	insmod rt2x00lib.ko
	insmod rt2x00usb.ko
	insmod crc-ccitt.ko
	insmod rt2800lib.ko
	insmod rt2800usb.ko
	insmod ctr.ko
	insmod ccm.ko
fi

if [ $1 = "r-rt2800usb" ]; then
	rmmod rt2800usb.ko
	rmmod rt2800lib.ko
	rmmod crc-ccitt.ko
	rmmod rt2x00usb.ko
	rmmod rt2x00lib.ko
fi

#No Wifi
/sbin/lsmod | grep -e "8821cu" -e "rt2800"
if [ $? -eq 1 ]; then
	rmmod ccm.ko
	rmmod ctr.ko
	rmmod mac80211.ko
	rmmod libarc4.ko
	rmmod cfg80211.ko
fi

この前組み込んだRTL8821CUとRT2800USBだけにして起動オプションで選べるようにしておいた。

お次はudevのruleを作成。/lib/udev/rules.dの中に99-usb-wifi.rulesを作成して

# Realtek 8211CU Wifi AC USB
ATTR{idVendor}=="0bda", ATTR{idProduct}=="1a2b", RUN+="/usr/sbin/usb_modeswitch -K -v 0bda -p 1a2b"
ATTR{idVendor}=="0bda", ATTR{idProduct}=="c811", RUN+="/oem/usr/ko/insmod_wifi.sh 8821cu"
ATTR{idVendor}=="0bda", ATTR{idProduct}=="c820", RUN+="/oem/usr/ko/insmod_wifi.sh 8821cu"
#SUBSYSTEM=="net", ACTION=="remove", ENV{ID_USB_DRIVER}=="rtw_8821cu", RUN+="/oem/usr/ko/insmod_wifi.sh r-8821cu"

# RT2800USB Wifi
ATTR{idVendor}=="0411", ATTR{idProduct}=="01ee", RUN+="/oem/usr/ko/insmod_wifi.sh rt2800usb"
ATTR{idVendor}=="0411", ATTR{idProduct}=="015d", RUN+="/oem/usr/ko/insmod_wifi.sh rt2800usb"
ATTR{idVendor}=="0411", ATTR{idProduct}=="0148", RUN+="/oem/usr/ko/insmod_wifi.sh rt2800usb"
#SUBSYSTEM=="net", ACTION=="remove", ENV{ID_USB_DRIVER}=="rt2800usb", RUN+="/oem/usr/ko/insmod_wifi.sh r-rt2800usb"

#SUBSYSTEM=="net", ACTION=="add", ENV{DEVTYPE}=="wlan", RUN+="/etc/init.d/S40iwd stop", RUN+="/etc/init.d/S40iwd start"
SUBSYSTEM=="net", ACTION=="add", ENV{DEVTYPE}=="wlan", RUN+="/etc/init.d/S40iwd start"

rt2800usbのドングルはVID PIDが色々あるのでとりあえず持っているWLI-UC-GNとWLI-UC-GNM2TとWLI-UC-G300HPのを追加しておいた。
コメントアウトしてるところはカーネルモジュールをrmmodしようとしたんだけどrt2800usbのほうがiwdでrfkillを入れたからなのか、指したときにremoveもされるのでうまく行かなくなってしまった(wlanの番号がどんどん増えてくし)
とりあえず動くのでいいか…

udevadm control --reload-rules

をやってruleを読み込んだらWiFiドングルを指してみるとip link showするとwlanが増えてるはず。

次にiwdの動作確認。/usr/libexec/iwdを実行してみてカーネルに組み込まれている暗号化モジュールが足りないって言われなければOK。

再起動してみたら今度はudevの起動順番が早すぎてusb_modeswitchは動いてるんだけどカーネルモジュールが読み込まれていない。USB WiFiを抜き差ししてみるとちゃんと繋がるんだけどね。
ということで起動時にもう一回udevadm triggerしてみる

/etc/init.d/S99xを作って

#!/bin/sh

sleep 1
/bin/udevadm trigger

としてchmod 755 /etc/init.d/S99xしておく。

これで起動時にWiFiが認識されるようになった。
最後にWiFiに接続してみる。

iwctlを実行して

wsc list
station wlan0 get-networks
station wifiカード名 connect アクセスポイント名

みたいな感じで簡単にアクセスポイントに接続できる。途中でWiFiアダプタを抜き差ししても自動で復帰してくれた。wpa_supplicantより断然楽かも。

WiFiが使えるようになったのでようやくLANケーブルを外してハンドリングが良くなった。
モバイルバッテリーに繋いでメカナムラジコンの上に乗せてustreamerでFPVもどきをやってみたけど広角レンズとか魚眼レンズ付けないと操作難しいかも。

0 件のコメント:

コメントを投稿