1. はじめに
日本ではSwitchScienceで購入可能な D-Robotics RDK S100Pですが、販売開始からまだそれほど経っていないせいか公式イメージのV4.0.5を書き込んでもいろいろ不具合というか手間のかかる子です。
Discodeで公式とやり取りをしているところなので、今後のアップデートで改善されるかもしれませんが、2026.04.02現在は
- M.2 Key-E スロットにWi-Fiモジュールがセットされておらず、自前で用意しても認識されない
- TP-Link T2UB Nano (Realtek RTL8821CU)のドライバのビルドに失敗する
という問題があり、ネットワークを使用した初期セットアップには有線接続するしかなくエッジコンピュータとしては致命的な状態です。
このうち、2. に関してはClaudeCodeで外部からssh接続して何とか解消できたので、その方法を紹介します。
2. 環境
- デバイス: D-Robotics RDK S100P
- OS: Ubuntu 22.04.5 LTS (arm64)
- システムイメージ: V4.0.5 (https://archive.d-robotics.cc/downloads/os_images/rdk_s100/RDKS100-V4.0.5/RDK_LNX_SDK/firmwares/product.zip)
-
カーネル:
6.1.158-rt58-DR-4.0.5-2603031328(カスタムリアルタイムカーネル) -
使用アダプタ: TP-Link T2UB Nano (
Realtek RTL8821CU0bda:c820, 802.11ac) - 接続: USB
カーネルにモジュール署名強制 (CONFIG_MODULE_SIG_FORCE=y) が設定されているため、ビルドしたモジュールをカーネルの秘密鍵で署名する必要があります。
3. 必要なもの
- 有線Ethernetで SSH 接続できる & インターネット接続できるPC(今回は Windows11 + Python を使用)
- RTL8821CU USB Wi-Fi アダプタ(
lsusbで0bda:c820と表示されるもの)
4. 手順
4.1. デバイスへの SSH 接続確認
下図のU45のRJ45ポートが 192.168.127.10の固定IPが振られた Eth1 ポートなので、ここに有線Ethernetでssh接続します。
# Python の paramiko でパスワード認証する場合
pip install paramiko
# または sshpass が使える環境なら
sshpass -p sunrise ssh sunrise@192.168.127.10
4.2. カーネルヘッダの確認
カーネルヘッダが /usr/src/linux-headers-$(uname -r) に存在することを確認します。
ls /usr/src/linux-headers-$(uname -r)
また、ビルドツールが揃っているか確認します。
which gcc make
4.3. ドライバのダウンロードと転送
PC 側でドライバをダウンロードし、デバイスへ転送します。
PC 側(Python):
import urllib.request
url = "https://github.com/morrownr/8821cu-20210916/archive/refs/heads/main.zip"
urllib.request.urlretrieve(url, "rtl8821cu.zip")
デバイスへ転送(SCP または SFTP):
scp rtl8821cu.zip sunrise@192.168.127.10:~/
デバイス側で展開:
cd ~
unzip rtl8821cu.zip
4.4. カーネルビルドスクリプトの準備
カスタムカーネルのヘッダにはビルド用のバイナリが含まれていないため、手動でコンパイルします。
KDIR=/usr/src/linux-headers-$(uname -r)
MODDIR=$KDIR/scripts/mod
# fixdep のコンパイル
sudo gcc -o $KDIR/scripts/basic/fixdep $KDIR/scripts/basic/fixdep.c
sudo chmod 755 $KDIR/scripts/basic/fixdep
# mk_elfconfig のコンパイルと elfconfig.h の生成
sudo gcc -o $MODDIR/mk_elfconfig $MODDIR/mk_elfconfig.c
sudo gcc -c -o $MODDIR/empty.o $MODDIR/empty.c
sudo bash -c "$MODDIR/mk_elfconfig < $MODDIR/empty.o > $MODDIR/elfconfig.h"
# devicetable-offsets.s の生成
sudo gcc -S \
-I$KDIR/include \
-I$KDIR/arch/arm64/include \
-include $KDIR/include/linux/compiler_types.h \
-D__KERNEL__ -DMODULE \
-o $MODDIR/devicetable-offsets.s \
$MODDIR/devicetable-offsets.c
devicetable-offsets.h の生成(Python スクリプト):
import re
with open(f"{MODDIR}/devicetable-offsets.s") as f:
content = f.read()
defs = []
for m in re.finditer(r'\.ascii\s+"->(\w+)\s+(-?\d+)', content):
defs.append(f"#define {m.group(1)} {m.group(2)}")
with open(f"{MODDIR}/devicetable-offsets.h", "w") as f:
f.write("\n".join(defs) + "\n")
または bash で代替:
grep -oP '(?<=ascii ").+?(?=")' $MODDIR/devicetable-offsets.s | \
awk '/^->/{print "#define " $1 " " $2}' | sed 's/^#define ->//' > \
$MODDIR/devicetable-offsets.h
modpost のコンパイル:
sudo gcc -I$MODDIR \
-o $MODDIR/modpost \
$MODDIR/modpost.c $MODDIR/file2alias.c $MODDIR/sumversion.c
autoconf.h の生成:
# .config から autoconf.h を生成するスクリプト
sudo python3 - <<'EOF'
import re
kdir = "/usr/src/linux-headers-$(uname -r のフルパス)"
with open(f"{kdir}/.config") as f:
config = f.read()
lines = ["#ifndef __LINUX_AUTOCONF_H__", "#define __LINUX_AUTOCONF_H__", ""]
for line in config.split('\n'):
line = line.strip()
if not line or line.startswith('#'):
continue
if '=' in line:
key, val = line.split('=', 1)
if val == 'y' or val == 'm':
lines.append(f"#define {key} 1")
elif val == 'n':
lines.append(f"#undef {key}")
else:
lines.append(f"#define {key} {val}")
lines += ["", "#endif"]
with open(f"{kdir}/include/generated/autoconf.h", "w") as f:
f.write("\n".join(lines))
print("Generated autoconf.h")
EOF
$(uname -r のフルパス) は実際のカーネルバージョン文字列で置き換えてください(例: 6.1.158-rt58-DR-4.0.5-2603031328-g9f678e-g6caa4d)。
4.5. ドライバのビルド
KDIR=/usr/src/linux-headers-$(uname -r)
sudo make -C ~/8821cu-20210916-main \
KSRC=$KDIR \
ARCH=arm64 \
-j$(nproc)
成功すると ~/8821cu-20210916-main/8821cu.ko が生成されます。
4.6. モジュールへの署名
このデバイスはモジュール署名が強制されているため、カーネルの秘密鍵で署名します。
KDIR=/usr/src/linux-headers-$(uname -r)
# sign-file ユーティリティを使用(5.15のものが流用可能)
sudo /usr/src/linux-headers-5.15.0-25-generic/scripts/sign-file \
sha512 \
$KDIR/certs/module_signature.pem \
$KDIR/certs/signing_key.x509 \
~/8821cu-20210916-main/8821cu.ko
echo "署名完了"
署名に使う秘密鍵は $KDIR/certs/module_signature.pem(-----BEGIN PRIVATE KEY----- を含む PEM ファイル)です。
sign-file バイナリは別カーネルヘッダのものを流用できます。
4.7. モジュールのインストールと読み込み
# カーネルモジュールディレクトリにコピー
sudo cp ~/8821cu-20210916-main/8821cu.ko \
/lib/modules/$(uname -r)/kernel/drivers/net/wireless/
# モジュール依存関係の更新
sudo depmod -a
# モジュールの読み込み
sudo modprobe 8821cu
# wlan0 インターフェースの確認
ip link show wlan0
wlan0 が表示されれば成功です。
4.8. 起動時の自動ロード設定
echo '8821cu' | sudo tee /etc/modules-load.d/8821cu.conf
4.9. Wi-Fi への接続
# 周辺の Wi-Fi をスキャン
nmcli dev wifi list
# Wi-Fi に接続
nmcli dev wifi connect "SSID名" password "パスワード"
# 接続確認
ip addr show wlan0
5. トラブルシューティング
5.1. Key was rejected by service エラー
モジュールに署名されていません。手順 6 の署名ステップを実施してください。
5.2. scripts/basic/fixdep: not found エラー
手順 4 の fixdep のコンパイルを実施してください。
5.3. No rule to make target 'scripts/mod/modpost' エラー
手順 4 の modpost のコンパイルを実施してください。
5.4. Kernel configuration is invalid エラー
手順 4 の autoconf.h の生成を実施してください。
5.5. 再起動後に wlan0 が消える
/etc/modules-load.d/8821cu.conf が作成されているか確認し、手順 8 を実施してください。また、カーネルアップデート後はモジュールの再ビルド・再署名が必要です。
6. 参考情報
| 項目 | 値 |
|---|---|
| 使用ドライバリポジトリ | morrownr/8821cu-20210916 |
| USB ID |
0bda:c820 (Realtek RTL8821CU) |
| Wi-Fi 規格 | 802.11ac (5GHz/2.4GHz) |
| 生成されるインターフェース名 | wlan0 |
| 署名アルゴリズム | SHA-512 |
