USB gadget functionfs

yooooooo發表於2024-09-03

FunctionFS (Function Filesystem) 是 Linux USB Gadget 框架的一部分,專門用於從使用者空間實現和控制自定義的 USB 功能。它提供了一種檔案系統介面,使使用者能夠在使用者空間中直接定義 USB 裝置的介面、端點和描述符,並管理 USB 資料的傳輸。FunctionFS 常用於需要使用者空間控制的複雜 USB 協議和自定義裝置功能,比如 USB 音訊 (UAC)、影片 (UVC) 或其他特殊用途的裝置。

FunctionFS 的工作原理

FunctionFS 將 USB 裝置功能暴露給使用者空間,允許使用者空間應用程式控制 USB 裝置的行為。它透過檔案系統的方式讓使用者程式與核心 USB 子系統互動,從而避免了複雜的核心開發,使得 USB 裝置的開發和除錯更加靈活。

使用 FunctionFS 的步驟

  1. 載入核心模組

    • 首先,確保系統已啟用 FunctionFS 支援,並載入相關的 USB Gadget 模組。g_ffs 模組是 FunctionFS 的 Gadget driver,它允許從使用者空間定義 USB 功能。
    modprobe g_ffs
    
  2. 掛載 FunctionFS

    • 掛載 FunctionFS 檔案系統到一個目錄,這個目錄將用於配置 USB 功能的介面和端點。通常掛載到 /dev/ffs/<function_name>
    mkdir -p /dev/ffs/my_function
    mount -t functionfs my_function /dev/ffs/my_function
    
  3. 使用者空間程式配置

    • 使用者空間程式可以在掛載的 FunctionFS 目錄下建立描述符檔案和端點檔案。描述符檔案定義了裝置的 USB 描述符(裝置描述符、介面描述符、端點描述符等),而端點檔案用於讀寫資料。

    示例程式碼配置描述符:

    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    int main() {
        int fd = open("/dev/ffs/my_function/ep0", O_RDWR);
        if (fd < 0) {
            perror("Failed to open ep0");
            return 1;
        }
    
        // 在這裡寫入描述符資料,例如裝置描述符、介面描述符等
        // 描述符的詳細格式需要根據 USB 協議規範填寫
        write(fd, "descriptor data", sizeof("descriptor data"));
    
        close(fd);
        return 0;
    }
    
  4. 處理資料傳輸

    • 使用者空間應用程式可以透過檔案讀寫的方式操作端點檔案,處理 USB 資料的收發。例如,資料可以從 ep1 寫入,或從 ep2 讀取。
    int ep_in = open("/dev/ffs/my_function/ep1", O_WRONLY);
    int ep_out = open("/dev/ffs/my_function/ep2", O_RDONLY);
    
    // 寫資料到 IN 端點
    write(ep_in, "data to send", 12);
    
    // 從 OUT 端點讀資料
    char buffer[128];
    read(ep_out, buffer, sizeof(buffer));
    
  5. 解除掛載

    • 當不再需要使用該功能時,可以解除安裝 FunctionFS,並清理相關資源。
    umount /dev/ffs/my_function
    

適用場景

  • 自定義 USB 功能:適合需要自定義 USB 功能的場景,例如實現使用者定義的協議、特定控制傳輸的裝置等。
  • 高層協議支援:非常適合實現高層協議,如 USB 音訊(UAC)、影片(UVC)和其他需要複雜控制的裝置。
  • 使用者空間控制:FunctionFS 允許使用者空間應用直接控制 USB 資料流,便於除錯和開發。

FunctionFS 的優缺點

  • 優點

    • 靈活性:允許使用者完全控制 USB 功能的行為,適合快速開發和除錯。
    • 使用者空間實現:無需頻繁修改核心程式碼,可在使用者空間編寫邏輯程式碼,便於開發人員進行除錯。
    • 實時性:適合需要快速響應和實時處理的 USB 功能實現。
  • 缺點

    • 實現複雜:由於需要使用者空間應用參與控制,開發者需對 USB 協議有深入瞭解。
    • 效能限制:使用者空間與核心空間的頻繁互動可能帶來一定的效能損耗,尤其在高吞吐量場景下。
    • 資料同步問題:使用者空間和核心空間之間的資料同步和延遲控制需要仔細管理。

FunctionFS 和 CONFIGFS 的主要區別

特性 FunctionFS CONFIGFS
控制層級 使用者空間控制,適合自定義 USB 協議和功能 核心空間控制,透過檔案系統動態配置 USB 功能
實現複雜度 需要使用者空間程式參與資料處理和控制 無需使用者空間干預,功能由核心模組直接實現
適用功能 高度自定義的 USB 功能,如音訊、影片 標準 USB 功能,如 RNDIS、MTP、Mass Storage
配置方式 掛載到 /dev/ffs,使用者程式讀寫檔案配置 掛載到 /sys/kernel/config,核心空間操作
效能 使用者空間參與可能增加延遲 核心直接實現,效能更高

總結

  • FunctionFS 更靈活,適合自定義 USB 功能並允許使用者空間控制,但實現複雜,需要使用者程式處理資料流。
  • CONFIGFS 更簡單,適合標準 USB 功能配置,核心直接管理資料流,配置方便快捷。

選擇哪種方式取決於 USB 功能的需求:需要標準功能組合時用 CONFIGFS,需要自定義和使用者空間控制時用 FunctionFS

相關文章