iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0
Software Development

從零打造邊緣運算閘道器:Raspberry Pi 與 Linux 底層軟硬整合實戰系列 第 9

[Day 09] ConfigFS 實戰 (一):從無到有,把樹莓派變成一顆 USB 隨身碟

  • 分享至 

  • xImage
  •  

前言
在昨天 [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。

  1. 載入核心模組並建立 Gadget 根目錄
    首先,我們需要載入 libcomposite,這是 Linux 處理多功能 USB 設備 (Composite Device) 的核心模組。接著,在 ConfigFS 的 usb_gadget 目錄下,建立一個屬於我們專案的資料夾 g1。

bash

#!/bin/bash
# 載入 composite 模組
modprobe libcomposite
# 建立名為 g1 的 gadget 目錄
cd /sys/kernel/config/usb_gadget/
mkdir -p g1
cd g1

當 mkdir g1 執行的瞬間,Linux 核心會自動在裡面生成一大堆設定檔與次目錄,準備讓我們進行配置。

  1. 定義 USB 設備的身分證 (VID & PID)
    任何 USB 設備插上電腦時,作業系統都是靠 Vendor ID (VID) 與 Product ID (PID) 來決定要掛載什麼驅動程式。

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
  1. 賦予設備靈魂:字串定義 (Strings)
    冰冷的 VID/PID 對人類來說很難辨識。我們需要設定語系 (0x409 代表英文),並填寫製造商、產品名稱以及序號。當隨身碟插上 Windows 時,裝置管理員就會顯示這些好讀的名字。

bash

mkdir -p strings/0x409
echo "00000000" > strings/0x409/serialnumber
echo "EdgeNode Corp." > strings/0x409/manufacturer
echo "DataGateway USB Device" > strings/0x409/product
  1. 建立設定檔 (Config)
    一個 USB 設備可以有多種不同的 Configuration (例如省電模式、高效能模式)。我們建立一個標準的配置 c.1,並設定最大耗電量 (MaxPower,單位為 2mA)。

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
  1. 宣告功能:Mass Storage
    這一步是重頭戲!我們要在 functions 目錄下,宣告這是一個 mass_storage 功能,實例名稱為 usb0。

bash
mkdir -p functions/mass_storage.usb0
建立完成後,這個目錄裡會自動出現用來設定隨身碟參數的檔案 (如 file, ro, removable 等)。 這時,我們需要給這顆隨身碟一個「實體載體」,也就是一個 Backing File (虛擬磁碟映像檔,例如 /opt/gateway/piusb.bin)。我們把這個檔案路徑塞進 file 中。

bash
echo "/opt/gateway/piusb.bin" > functions/mass_storage.usb0/lun.0/file
(註:至於這個 piusb.bin 是怎麼憑空捏出來並格式化成 FAT32 的?這牽涉到 Linux 的 File System,我們會在 Day 14 專門用一整篇文章來探討!)

  1. 組合與點火:綁定 UDC
    最後,我們把設定好的功能 (Function) 用 Soft Link (軟連結) 綁定到配置 (Config) 上。 然後,將這個 Gadget 送進 USB Device Controller (UDC) 進行「點火」。一旦把 UDC 設備名稱寫入,硬體就會立刻通電,Windows 那端就會聽到「叮咚」的 USB 插入聲!

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 (可移除) 屬性,打造出一顆堅不可摧的防呆隨身碟!


上一篇
Day 08 - 拋棄傳統核心模組:為什麼現代開發者都該用 ConfigFS?
下一篇
[Day 10] 隨身碟參數全解密:ro, removable, cdrom 與防呆設計
系列文
從零打造邊緣運算閘道器:Raspberry Pi 與 Linux 底層軟硬整合實戰26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言