基于Linux的USB主/從設(shè)備之間的三種通信方式
在usb -char中,真正的操作開(kāi)始于usbc_open()函數(shù),列表1給出了函數(shù)的一部分代碼。筆者由于臨時(shí)的興趣,對(duì)該代碼做了一點(diǎn)修改,取消了錯(cuò)誤和超時(shí)句柄。在此向代碼的原作者Brad Parker、Nicolas Pitre 和Ward Willats致歉。
twiddle_descriptors()函數(shù)用于設(shè)置設(shè)備的USB描述符。在描述符設(shè)置好之后,我們就可以開(kāi)始進(jìn)行設(shè)備查詢(xún),并從USB 主機(jī)接收一幀數(shù)據(jù)。kick_start_rx()函數(shù)段的代碼主要用于調(diào)用sa1100_usb_recv(),建立回調(diào)。
在USB主機(jī)發(fā)送一個(gè)數(shù)據(jù)包時(shí),設(shè)備的內(nèi)核模塊會(huì)通過(guò)回調(diào)方式調(diào)用rx_done_callback_packet_buffer()函數(shù),將數(shù)據(jù)包的內(nèi)容送入一個(gè)FIFO隊(duì)列,以便能通過(guò)read()函數(shù)將該數(shù)據(jù)包返回給usb-char設(shè)備節(jié)點(diǎn)。
2. USB主機(jī)端通信過(guò)程
對(duì)于運(yùn)行Linux操作系統(tǒng)的USB 主機(jī),與usb-char相應(yīng)的USB 主機(jī)模塊叫做usbserial。大多數(shù)Linux版本中都包含了該模塊,但它并不總能自動(dòng)加載。通常應(yīng)在主機(jī)與USB設(shè)備之間的連接建立之前利用 modprobe 或insmod加載該模塊。
USB設(shè)備查詢(xún)完成之后,主機(jī)上的一項(xiàng)應(yīng)用就會(huì)利用某個(gè)usbserial設(shè)備節(jié)點(diǎn)(字符型, major 為188, minor 大于等于0)與其通信。這些節(jié)點(diǎn)通常叫做/dev/ttyUSBn。Usbserial模塊會(huì)報(bào)告它將哪一個(gè)節(jié)點(diǎn)分配給了哪一臺(tái)USB設(shè)備,并將這一信息按如下方式記載在內(nèi)核消息記錄中: =================================== usbserial.c:檢測(cè)到一般轉(zhuǎn)換器 usbserial.c:將一般轉(zhuǎn)換器加入ttyUSB0 ==================================
這種連接一旦建立,USB 主機(jī)上的應(yīng)用就可以通過(guò)向特定的節(jié)點(diǎn)讀或?qū)懙姆绞脚c某USB設(shè)備通信。
此時(shí),筆者并未考慮在運(yùn)行Win32或其他類(lèi)型操作系統(tǒng)的主機(jī)上已有類(lèi)似usbserial的模塊。但用于這些主機(jī)上的任何USB驅(qū)動(dòng)程序,只要能夠進(jìn)行bulk-in 和 bulk-out數(shù)據(jù)傳輸,就很可能是一個(gè)近乎完整的驅(qū)動(dòng)程序,只需進(jìn)行一定的產(chǎn)品調(diào)整,并添加與產(chǎn)品綁定的廠商ID。
Linux 主機(jī)上還有另一種類(lèi)似usbserial模塊的庫(kù),叫做libusb (參見(jiàn)libusb.sourceforge.net)。該庫(kù)通過(guò)低級(jí)的內(nèi)核系統(tǒng)調(diào)用而不是通過(guò)usbserial模塊來(lái)完成USB數(shù)據(jù)傳輸,因而在 Linux kernel版本上更容易設(shè)置和使用。同時(shí),該庫(kù)還能提供大量實(shí)用的調(diào)試功能,十分利于對(duì)USB鏈接上運(yùn)行的復(fù)雜的通信協(xié)議進(jìn)行調(diào)試。
為了通過(guò)libusb與一個(gè)采用了usb-char模塊的USB設(shè)備進(jìn)行通信,Linux主機(jī)應(yīng)用首先通過(guò)庫(kù)中的usb_open()函數(shù)與設(shè)備建立連接,然后利用函數(shù)usb_bulk_read()和usb_bulk_write()與設(shè)備交換數(shù)據(jù)。Libusb中含有幾個(gè)程序范例。
利用USB實(shí)現(xiàn)以太網(wǎng)連接
1. USB 設(shè)備端通信過(guò)程
如果利用USB連接來(lái)實(shí)現(xiàn)高速串口并非您所希望,那么您還可以將所有USB連接用作一個(gè)以太網(wǎng)。不論在主機(jī)端還是在設(shè)備端,Linux均有模塊能實(shí)現(xiàn)這一功能。iPAQ(掌上電腦)的Linux內(nèi)核就獨(dú)一無(wú)二地采用了這種通信策略,因?yàn)閕PAQ硬件中既沒(méi)有可訪問(wèn)的串口也沒(méi)有專(zhuān)門(mén)的網(wǎng)絡(luò)接口。
StrongARM Linux內(nèi)核中,有一個(gè)叫做usb-eth的模塊(arch/arm/mach-sa1100/usb-eth.c),它利用USB作為物理媒介,模擬出一個(gè)虛構(gòu)的以太網(wǎng)設(shè)備。一旦這種網(wǎng)絡(luò)接口創(chuàng)建起來(lái)之后,就可以為它分配IP地址,并且外部環(huán)境均將其作為一個(gè)普通的以太網(wǎng)硬件對(duì)待。一旦USB 主機(jī)連接建立起來(lái),usb-eth模塊就允許USB設(shè)備“瀏覽”因特網(wǎng),拼其他的IP地址,甚至通過(guò)DHCP、HTTP、NFS或者遠(yuǎn)程網(wǎng)“交談”,以及收發(fā)電子郵件。簡(jiǎn)而言之,任何能夠在真正的以太網(wǎng)接口上運(yùn)行的應(yīng)用都可以原封不動(dòng)地在usb-eth 上運(yùn)行,因?yàn)檫@些應(yīng)用無(wú)法識(shí)別它們所使用的其實(shí)并非真正的以太網(wǎng)硬件。
2. USB 主機(jī)端通信過(guò)程
相應(yīng)的,在運(yùn)行 Linux操作系統(tǒng)的主機(jī)一端,可用來(lái)在USB上實(shí)現(xiàn)以太網(wǎng)連接的內(nèi)核模塊叫做usbnet。安裝了該模塊之后,一旦主機(jī)與USB設(shè)備的連接建立起來(lái),它就會(huì)創(chuàng)建一個(gè)虛擬的以太網(wǎng)接口,在主機(jī)一端的內(nèi)核模塊以及用戶(hù)應(yīng)用看來(lái),這個(gè)虛擬的接口與真正的以太網(wǎng)接口別無(wú)二致。主機(jī)端的應(yīng)用可以通過(guò)拼一個(gè)USB設(shè)備的IP地址來(lái)檢查該設(shè)備是否已經(jīng)連上,如果拼操作成功,那么就表示設(shè)備已經(jīng)連接成功。
最近出現(xiàn)了一種針對(duì)Win32主機(jī)的usbnet風(fēng)格的驅(qū)動(dòng),叫做Bahia網(wǎng)絡(luò)驅(qū)動(dòng),關(guān)于該驅(qū)動(dòng)的詳細(xì)信息請(qǐng)?jiān)L問(wèn)www.bahia21.com/download.htm。
USB通信的調(diào)試
遺憾的是,在USB 主機(jī)與Linux USB設(shè)備之間進(jìn)行通信時(shí),能夠幫助我們跟蹤通信過(guò)程中出現(xiàn)的問(wèn)題的工具實(shí)在不多。除了libusb所提供的調(diào)試功能以外(該功能十分強(qiáng)大,但對(duì)于內(nèi)核的系統(tǒng)調(diào)用接口則無(wú)能為力),在一次失敗的設(shè)備查詢(xún)或數(shù)據(jù)傳輸?shù)膰L試過(guò)程中發(fā)生了什么問(wèn)題?只有內(nèi)核源代碼和記錄能夠提供一些線索。筆者嘗試在開(kāi)發(fā)過(guò)程中向 USB 主機(jī)和設(shè)備代碼中大量添加printk()函數(shù)調(diào)用,但這種方法會(huì)引入額外開(kāi)銷(xiāo),從而改變USB代碼自身的性能,這在有些情況下反而是事與愿違。
對(duì)那些希望對(duì) USB設(shè)備接口進(jìn)行逆向工程處理,或者希望查找其產(chǎn)品缺陷的Linux開(kāi)發(fā)者而言,一個(gè)叫做USB Snoopy (home.jps.net/~koma)的程序是個(gè)不錯(cuò)的選擇。只是USB Snoopy僅能在Win32主機(jī)上運(yùn)行。關(guān)于USB Snoopy的詳細(xì)信息或關(guān)于常規(guī)的USB調(diào)試,請(qǐng)參看本文末給出的參考文獻(xiàn)中Jan Axelson撰寫(xiě)的 “USB Debug Tips”。
Linux已成為通用型操作系統(tǒng)
如今Linux已不再是USB 主機(jī)專(zhuān)用的操作系統(tǒng)了,USB設(shè)備也可以方便地選擇它。而且Linux下的USB通信太靈活易用了,因而筆者采用其他易用型串口(RS-232)的日子很可能就此結(jié)束,對(duì)我而言,這是件好事。
參考文獻(xiàn):
[1].major datasheethttp://www.dzsc.com/datasheet/major+_2533383.html.
linux操作系統(tǒng)文章專(zhuān)題:linux操作系統(tǒng)詳解(linux不再難懂)
linux操作系統(tǒng)文章專(zhuān)題:linux操作系統(tǒng)詳解(linux不再難懂)linux相關(guān)文章:linux教程
評(píng)論