當前位置:才華齋>計算機>作業系統>

Linux系統下USB驅動程式的設計與開發

作業系統 閱讀(1.33W)

論文導讀::作業系統是一個原始碼公開、結構清晰、功能強大。匯流排具有低成本、使用簡單、支援即插即用、易於擴充套件等特點。本文首先介紹linux驅動程式的架構。

Linux系統下USB驅動程式的設計與開發

關鍵詞:Linux,USB,驅動程式

0引言

Linux作業系統是一個原始碼公開、結構清晰、功能強大,且已成為一個穩定可靠功能完善的系統。其開發群體的有效組織和高效工作,使得linux系統穩定發展並得到良好維護。

USB匯流排是Intel、DEC、MicroSoft、IBM等公司聯合提出的一種新的序列匯流排標準,主要用於PC機與外圍裝置的互聯。USB匯流排具有低成本、使用簡單、支援即插即用、易於擴充套件等特點,已被廣泛地用在PC機及嵌入式系統上。

在已經研製的家庭閘道器中,CPU通過自帶的USB介面控制USB裝置。本文首先介紹linux驅動程式的架構發表論文,然後介紹USB匯流排,重點說明USB驅動程式的實現。

x驅動程式基礎

裝置驅動程式是作業系統核心和機器硬體之間的介面,為應用程式遮蔽了硬體的細節。應用程式看待硬體裝置只是一個裝置檔案,應用程式可以象操作普通檔案一樣對硬體裝置進行操作。裝置驅動程式是核心的一部分,它主要完成以下功能:對裝置進行初始化,使裝置投入執行和退出服務;把資料從核心傳送到裝置和從裝置接受資料;以及檢測和處理裝置出現的錯誤等。

Linux系統的裝置一般分為字元裝置、塊裝置和網路裝置三種。字元裝置是指存取時沒有快取的裝置。塊裝置的讀寫都有快取來支援,並且塊裝置必須能夠隨機存取,字元裝置則沒有這個要求。一個檔案系統要安裝進入作業系統必須在塊裝置上。網路裝置在Linux裡做專門的處理。Linux的網路系統主要是基於BSD unix的socket機制。在系統和驅動程式之間定義有專門的資料結構(sk—buff)進行資料的傳遞。系統裡支援對傳送資料和接收資料的快取,提供流量控制機制,提供對多協議的支援。

系統匯流排介紹

每一個USB裝置會有一個或者多個的邏輯連線點,每個連線點叫埠。每個埠有4種資料傳送方式:控制方式;等時方式;中斷方式和大量方式。但是所有的埠0都是被用來傳送配置和控制資訊。

在主機和裝置的埠之間的連線叫作管道,與埠0連線的一般稱作為預設管道。對於同樣性質的一組埠的組合叫做介面發表論文,如果一個裝置包含不止一個的介面就可以稱之為複合裝置。

同理,對於同樣的型別的介面的組合可以稱之為配置。但是每次只能有一個配置是可用的,而一旦該配置啟用,裡面的介面和埠就都同時可以使用。主機從裝置發過來的描述符中來判斷用的是哪個配置,哪個介面等等,而這些的描述字通常是在埠0中傳送。

子系統

USB 是一種分層的匯流排結構,並且是由一個主機(host)來控制。主機用主/副協議來和外部USB裝置通訊。USB上的'通訊主要是兩個方向進行的,一個是主機到裝置的下行方向, 一個是裝置到主機的上行方向,不支援裝置間的直接通訊。依靠不同的裝置型別,主要有4 種的傳輸方式::控制(control)、中斷(interrupt)、同步(isochronous)、資料塊(bulk);如果是從硬體開始來設計整個的系統,還要正確選擇傳輸的方式。而作為一個驅動程式的書寫者就只需要弄清楚他是採用的什麼工作方式就行了。通常所有的傳輸方式下的主動權都在 host邊。

在Linux系統中編寫主機部分的USB驅動發表論文,我們不必瞭解太多的硬體知識,因為Linux 核心模組中提供了一塊USB核心(USBcore),它給出專門的API來支援USB裝置和主控制器。通過定義一系列資料結構,巨集命令和函式對所有的硬體和裝置支援部分進行抽象。

USB核心包含了所有USB裝置驅動和主控制器驅動的共同的USB程式。這些函式主要集中在上層和底層API。如圖1所示,有一個USB裝置的驅動的API和一個主控制器的驅動。

圖1USB核心API層

裝置驅動框架

USB裝置驅動在核心模組中需要註冊和登出。因此一個驅動必須註冊2個入口點和一個裝置節點。對於特別的USB裝置(他們不適合在子系統中註冊)一個驅動可以註冊一對檔案操作符和一個次裝置號。一般一個驅動可以服務16個相似的USB裝置。幾乎所有的USB裝置主裝置號都是180。

4.1框架資料結構

所有的USB相關的函式和資料結構的名字都是以USB_開頭的。下面給出在子系統中註冊一個USB驅動程式的資料結構。

struct usb _driver {

const char *name; / /模組的名字

void* ( *probe)(struct usb_device *,unsigned int) ;/ /函式的進入指標

void ( *disconnect) ( struct usb_device *,void * ) ; / /撤銷連線的函式進入指標

struct list_headdriver_list ;/ /給子系統內部使用,初始化時為 NULL

structfile_operations *fops ;/ /檔案操作列表指標

int minor ;/ /次裝置號

} ;

這裡特別要提的就是檔案操作的結構(structfile_operations),隨著新功能不斷加入 Linux核心,此檔案操作的結構也變得越來越大,這種增長是不會有副作用的。因為對於特定的裝置驅動,我們可以選擇自己需要的函式,不需要的就設為NULL值就可以。下面主要列舉一些USB常用的幾個檔案操作函式:

(1)int ( *open) ( struct inode *, struct file*) ; 裝置開啟操作一般是裝置的第一個操作,不過有的裝置可以不選擇這個函式。那樣裝置的開啟操作就會永遠成功發表論文,但系統不會通知你的驅動程式。

(2) void ( *release)( struct inode * , struct file* ) ; 當節點關閉時呼叫這個操作。

(3) int ( *read) ( struct inode * , struct file * ,char * , int) ; 用來從裝置中讀取資料。函式返回一個非負值表示成功的讀取了多時位元組。

(4) int ( *write) ( struct inode * , struct file * ,const char * , int ) ; 向裝置發資料。如果返回值非負,它就表示成功寫入的位元組數。

(5) int ( *select) (struct inode * , struct file * ,int , select_table * ) ; select一般用於程式詢問裝置是否可讀或可寫,或是否一個“異常”條件發生了。

(6) int ( *ioctl) ( struct inode * , struct file * ,unsigned int , unsigned long) ; 系統呼叫 ioctl 提供一種呼叫裝置相關命令的方法。

(7) int ( *mmap) ( struct inode * , struct file* , struct vm_area _struct * ) ; 用來將裝置記憶體對映到程序記憶體中。

(8) int ( *fsync) ( struct inode * , struct file* ) ; 重新整理裝置。

4.2框架進入指標

USB 驅動的框架增加了兩個進入指標給普通的裝置驅動。

(1) void * probe( struct usb_device * dev , unsigned int interface) ; 當一個新裝置加入匯流排時,這個進入指標就被呼叫。然後裝置驅動將建立一個新的裝置資料結構例項。引數dev表示裝置的上下文,他包含了所有USB描述符的地址。引數interface表示介面值。如果一個USB驅動想要繫結一個特別的裝置或者介面,它必須返回一個指標。這個指標通常指向裝置驅動的上下文結構。

(2) voiddisconnect ( struct usb_device * dev ,void * drv_context) ; 這個函式是在裝置撤銷連線時呼叫的。引數dev列出了裝置上下文。撤銷連線函式完成後,裝置就脫離了USB的框架。以後USB驅動就不能再呼叫它了。

4.3框架函式

(1)int usb_register ( struct usb_driver * drv) ;這個函式是用來註冊一個新的 USB 裝置驅動。指標drv指向結構usb_driver。函式成功返回0。要不然返回一個錯誤值。

(2)voidusb_deregister ( struct usb_driver *drv) ; 此函式是登出 USB 裝置驅動。

(3)voidusb_driver_claim_interface ( struct usb_driver * driver , struct usb_interface *iface ,void * drv_context) ; 此函式是在probe函式執行後,開始為裝置驅動申請更多的介面。Drive指標指向一個完整的已經初始化的usb_driver結構。Iface 指向usb_interface結構,此結構是usb_config_descriptor(可以在usb_device結構中看到)的一部分(在probe函式中賦值)。Drv_context 指標主要指向裝置驅動的上下文結構(看probe函式的返回值)。

(4)intusb_interface_claimed (struct usb_inter2face * iface); 這個函式是檢查是否有其他驅動已經聲明瞭這個介面。如果介面沒有被其它驅動申請就返回0。

(5)voidusb_driver_release_interface(structusb_driver * driver , struct usb_interface * iface); 這個函式主要是來釋放先前申請的介面。在 disconnect函式中, , 你不必釋放任何在probe函式中申請的介面。

5.配置USB裝置

USB核心API除了包括了一套選擇或詢問的描述符,還有一些配置和更換的裝置函式。所有這些標準操作都是通過控制傳輸給裝置的。

5.1資料結構的描述

Linux USB子系統通過擴充套件或內嵌標準的USB描述符來說明描述符的分級結構。這種結構有助於儲存指向可選配置和介面的指標。只要被API呼叫,這些結構的元素就會被描述。關於描述符的詳細資訊可以在USB.H查到。

struct usb_device{

. . .

struct usb_config_descriptor* actconfig ;/ * the active configuration * /

. . .

struct usb_device_descriptordescriptor ;/ * Descriptor * /

struct usb_config_descriptor* config ; / * 所有的引數 * }

usb_device 結構是所有USB專門的描述符的根節點。在用驅動配置裝置或者請求傳輸的時候發表論文,就必須分解描述符。

5.2標準的裝置申請

為了查詢或者設定一個特殊的配置或可選設定,可以用一個整型函式。並用這個函式建立標準的裝置申請(指定裝置的控制傳輸)。

(1)intusb_set_configuration (struct usb_device* dev , int configuration); 此函式是啟用特殊的配置。0 < =configuration < dev - > descriptor Configurations.

設configuration為0將裝置設為無地址狀態。這個意思是裝置脫離這個裝置地址並準備接受一個新的。一般不要設0。因為你將不能訪問裝置,直到被物理的重新連線到總線上。

(2) intusb_set_interface ( struct usb_device *dev , int interface , int alternate) ; 這個函式啟用指定介面的可選設定。

(3) intusb_get_device_descriptor ( struct usb_device * dev) ; 這個函式取出了裝置完整的描述符結構樹。當一個裝置連上匯流排時,這個函式就會自動被喚醒。或者當一個USB描述符改變時,此函式被呼叫。

(4) intusb_get_string ( struct usb_device *dev , unsigned short langid , unsigned charindex , void* buf , int size) ; 如果一個裝置,配置或者介面描述符涉及到字串索引值,這個函式可以用來重新獲得字元描述符。標準的USB字串是以UNICODE編碼的。如果成功就返回0,要不然返回一個錯誤值。

6.結束語

USB的應用越來越廣泛,傳輸速率越來越高。而Linux作為一種新的作業系統,其發展前景是無法估量的,同時也為USB匯流排與各種新型裝置互連成為可能。在Linux下編寫驅動程式的原理和思想與window環境下的驅動程式有很大的區別,在Linux環境下設計驅動程式發表論文,思想簡潔,功能也很強大,但是支援函式少,只能依賴kernel中的函式,有些常用的操作要自己來編寫,而且除錯也不方便,還要考慮核心的前後相容性,因此在設計和實現USB裝置時應該注意這些問題。

參考文獻:

[1]毛德操,胡希明x核心原始碼情景分析[M].杭州:浙江大學出版社,2003.

[2]Universal Serial Bus SpecificationRevision[Z]. Compaq, IBM, Intel, Microsoft, NEC, Northern Telecom, 1995.

[3]王偉,王自強,都思丹裝置上構建Linux系統的關鍵問題[J].電子測量技術,2008,(06).

[4]沈玉偉,楊永傑,房立鑫.基於μClinux嵌入式網路印表機伺服器[J].計算機時代,2008,(05).

[5]吳麗麗.嵌入式平臺下USB攝像頭驅動的開發與載入[J].科技資訊(學術研究),2008,(26).

[6]杜敏傑,馬彥恆,劉利民x下基於CY7C68013晶片的USB裝置驅動程式開發[J].科學、技術與工程,2008,(21).

[7]盧志剛,劉建華,劉寶旭,許榕生.基於HID的USB監控技術的設計與實現[J].計算機工程,2010,(04).

[8]宋麗華,高珂.嵌入式Linux下USB攝像頭驅動實現[J].計算機工程,2010,(09).

[9]孫永剛,張學勇,遲歡歡.基於Linux的USB裝置驅動的實現[].資訊科技,2010,(08).

[10]劉飛,張曦煌.基於嵌入式平臺的USB攝像頭驅動程式的實現[J].計算機工程與設計,2008,(08).

[11]肖珂,歐東梅,郭書軍.嵌入式Linux下高速USB主控制器的設計與實現[J].現代電子技術,2009,(24).

[12]熊春傑x核心移植與USB驅動開發[D].電子科技大學,2007.

[13]程科.嵌入式Linux裝置驅動程式的設計與研究[D].電子科技大學,2007.

[14]王強東.面向嵌入式系統的多功能USB裝置驅動研究[D].華中科技大學,2007.