歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> 實現支持基於Linux的USB設備的三種方法

實現支持基於Linux的USB設備的三種方法

日期:2017/2/28 17:52:58   编辑:Linux教程

引言
通用串行總線(USB)是一種快速而靈活地連接配件與計算機工作站的接口,其應用非常廣泛。Linux中除了包含對USB主機控制器的驅動,還含有USB設備控制器,尤其是集成在StrongARM SA1110處理器上的控制器的驅動。這些控制器驅動通過使用USB可使基於Linux的嵌入式系統與主機 (運行的可以是Linux,或不是)進行通信。這裡提供三種方法給運行Linux操作系統的嵌入式系統增加USB支持,可采用其中一種與USB主機展開通信。
第一種,最復雜的設備采用專門編寫的內核模塊解析標准USB總線上通行的錯綜復雜的高層協議;相應的USB主機定制驅動和應用程序來完成連接。第二種,有些基於Linux的設備把總線當作一種簡單的運行在主機上的點對點串行連接使用;主機應用程序采用主機操作系統提供的USB編程界面,而其外在表現則仿佛是在通過一種典型的串行端口進行通信。第三種,另有一些設備把USB看作一種以太網絡,它們用主機作網關,把USB設備與辦公LAN或 Internet相連接。通常的做法是使用專門的主機驅動實現它。
最佳方案的選擇取決於研發所需時間,以及針對具體嵌入式應用,要把USB接口作成什麼樣。以下對這三種方法如何在基於Linux的USB設備上的應用逐一進行描述。本文是關於如何在基於Linux的照相機和PDA之類的USB設備上使用Linux的論述,在此,USB是指由方形連接器而非扁平矩形連接器構成的USB設備。
內核模塊
把USB加到基於Linux的設備上的第一種方法是編寫一個定制的Linux內核模塊。這種方法通常要求相應開發主機操作系統(Windows、Linux以及其它OS)的驅動。
借助定制內核模塊在設備中的安裝,可以進行文件系統仿真等,使嵌入式應用將其USB主機當作遠程存儲設備對待。這一方法的另一潛在用途是構成一種存儲轉發字符設備,從嵌入式應用程序中緩沖數據流,直到USB主機連接完成建立為止。
對於基於StrongARM的Linux設備,其USB應用內核模塊調用sa1100_usb_open(),對管理芯片的板上USB設備控制器外設的內核代碼進行初始化。然後該模塊調用sa1100_usb_get_descriptor_ptr()和 sa1100_usb_set_string_descriptor(),通過枚舉過程對USB主機的給定USB描述符進行設置。這些描述符包括設備供貨商及產品的數字標識符、正文字符串等主機可用來對設備進行識別的信息。甚至有一個序列號域,以便主機唯一地識別設備或對USB上相同設備的多個實例加以區分。
內核模塊必須在開始USB通信前完成USB描述符的建立,這是因為枚舉過程由USB設備控制器驅動,一旦USB主機連上後會自動執行。一切准備就緒後,USB設備模塊便調用sa1100_usb_start(),告訴內核接受來自主機的USB連接請求。如果模塊在USB主機連上前調用 sa1100_set_configured_ callback(),那麼內核將會在枚舉過程結束時調用所提供的回調函數。回調函數能很好地對設備完成連接狀態進行可視化指示。
如果USB通信不再需要,那麼設備的內核模塊便調用sa1100_usb_stop(),然後是 sa1100_usb_close(),關閉SA1100的USB控制器。
StrongARM USB控制器支持數據傳輸作業的bulk-in 和bulk-out。在從USB主機接收數據包時,內核模塊調用sa1100_usb_recv(),把數據緩沖區和回調函數地址傳遞給它。然後內核的底層USB設備控制代碼對來自主機的bulk-out包進行檢索,把內容放於緩沖區中,並調用回調函數。
回調函數必須從接收緩沖區提取數據並保存於其它位置或者把緩沖區空間加到一個隊列中,為下一個數據包的接收分配新的緩沖區。而後回調函數二次調用sa1100_usb_recv(),在需要時進行下一個數據包的接收。過程與對USB主機的數據傳輸相類似。在聚集起一幀的數據量後,內核模塊將數據的地址、長度和回調地址傳遞給 sa1100_usb_send()。傳輸完成時,內核調用回調函數。
主機端USB驅動的幾個例子在主流的Linux版本以及 Linux內核檔案組織分配的原始內核源中都有提供。用於Handspring Visor(drivers/usb/serial/visor.c)的模塊是編寫較為簡潔易懂的模塊之一,作為USB主機端模塊的模板 (drivers/usb/usb-skeleton.c)使用。

Copyright © Linux教程網 All Rights Reserved