前言
在昨天 [Day 08] 的文章中,我們了解了現代 Linux 核心為何逐漸拋棄死板的傳統核心模組,改擁抱靈活彈性的 ConfigFS。今天,我們終於要動手寫下第一行腳本,開始我們的「黑魔法」實戰:透過 ConfigFS 把一台單板電腦 (Raspberry Pi) 偽裝成一顆普通的 USB 隨身碟,讓 Windows 電腦一插上 USB 線,就能立刻讀取到 EdgeNode 所收集的醫療數據。
問題情境
在 DataGateway 的使用情境裡,設備常常會被部署在沒有網路、沒有專業 IT 人員的偏鄉醫療站。當醫師需要索取這些儲存下來的生理訊號時,我們不可能要求他們使用 SFTP 或指令列來下載資料。
「最直覺的作法,就是讓設備本身變成一顆隨身碟 (Mass Storage)。」 只要插上 Type-C 傳輸線,Windows 就會跳出磁碟機代號,這是每個人都會的操作。為了達成這個目標,我們將使用 Linux 核心的 libcomposite 模組,結合 ConfigFS 來定義這顆「虛擬隨身碟」。
實戰步驟:Step by Step 建立 USB Gadget
前置作業:請確保您的 Linux 核心支援 USB Gadget 模式,並且已經在 /boot/config.txt 中啟用了 dtoverlay=dwc2。
bash
#!/bin/bash
# 載入 composite 模組
modprobe libcomposite
# 建立名為 g1 的 gadget 目錄
cd /sys/kernel/config/usb_gadget/
mkdir -p g1
cd g1
當 mkdir g1 執行的瞬間,Linux 核心會自動在裡面生成一大堆設定檔與次目錄,準備讓我們進行配置。
idVendor:製造商代碼 (這裡我們借用 Linux Foundation 的 0x1d6b)。
idProduct:產品代碼 (0x0104 代表 Composite 設備)。
bcdDevice 與 bcdUSB:定義設備版本與 USB 版本 (0x0200 代表 USB 2.0)。
bash
echo 0x1d6b > idVendor
echo 0x0104 > idProduct
echo 0x0100 > bcdDevice
echo 0x0200 > bcdUSB
bash
mkdir -p strings/0x409
echo "00000000" > strings/0x409/serialnumber
echo "EdgeNode Corp." > strings/0x409/manufacturer
echo "DataGateway USB Device" > strings/0x409/product
bash
mkdir -p configs/c.1/strings/0x409
echo "Config 1: Mass Storage" > configs/c.1/strings/0x409/configuration
echo 250 > configs/c.1/MaxPower
bashmkdir -p functions/mass_storage.usb0
建立完成後,這個目錄裡會自動出現用來設定隨身碟參數的檔案 (如 file, ro, removable 等)。 這時,我們需要給這顆隨身碟一個「實體載體」,也就是一個 Backing File (虛擬磁碟映像檔,例如 /opt/gateway/piusb.bin)。我們把這個檔案路徑塞進 file 中。
bashecho "/opt/gateway/piusb.bin" > functions/mass_storage.usb0/lun.0/file
(註:至於這個 piusb.bin 是怎麼憑空捏出來並格式化成 FAT32 的?這牽涉到 Linux 的 File System,我們會在 Day 14 專門用一整篇文章來探討!)
bash
# 綁定功能到設定檔
ln -s functions/mass_storage.usb0 configs/c.1/
# 尋找可用的 UDC 並啟動設備
ls /sys/class/udc > UDC
小結
恭喜!只用了短短 20 行 Bash 腳本,我們就徹底改變了樹莓派的硬體行為,讓它化身為一顆隨身碟。這就是 ConfigFS 的迷人之處:一切都是檔案,一切皆可動態組合。
但您可能會問:「萬一醫生在 Windows 端把重要檔案誤刪了怎麼辦?」「隨身碟如果不小心被格式化了,我們的系統不就崩潰了?」 別擔心,明天 [Day 10 - 隨身碟參數全解密],我們將深入解析 mass_storage 模組的進階參數,教你如何利用 ro (唯讀) 與 removable (可移除) 屬性,打造出一顆堅不可摧的防呆隨身碟!