?
<
p
>
Java?平臺(tái)一直都以其平臺(tái)無(wú)關(guān)性自豪。雖然這種無(wú)關(guān)性有許多好處,但是它也使得編寫(xiě)與硬件交互的?
??????????????Java?應(yīng)用程序的過(guò)程變得相當(dāng)復(fù)雜。在本文中,研究科學(xué)家蔣清野討論了兩個(gè)項(xiàng)目,它們通過(guò)提供使Java?應(yīng)用程序可以使用?USB?
??????????????設(shè)備的?API?而使這個(gè)過(guò)程變得更容易。雖然這兩個(gè)項(xiàng)目仍然處于萌芽狀態(tài),但是它們都顯示了良好的前景,并已經(jīng)成為一些實(shí)用應(yīng)用程序的基礎(chǔ)。?
????????????
</
p
>
????????????
<
p
>
通用串行總線(Universal?Serial?Bus?USB)規(guī)范的第一個(gè)版本發(fā)表于?1996年?1月。因?yàn)樗牡统杀尽⒏邤?shù)據(jù)傳輸率、使用容易和靈活性,USB?
??????????????在計(jì)算機(jī)行業(yè)里獲得了廣泛接受。今天,許多周邊設(shè)備和裝置都是通過(guò)?USB?接口連接到計(jì)算機(jī)上的。目前,大多數(shù)一般用途的操作系統(tǒng)都提供了對(duì)?
??????????????USB?設(shè)備的支持,并且用?C?或者?C++?可以相對(duì)容易地開(kāi)發(fā)訪問(wèn)這些外設(shè)的應(yīng)用程序。不過(guò),Java?編程語(yǔ)言在設(shè)計(jì)上對(duì)硬件訪問(wèn)提供的支持很少,所以編寫(xiě)與?
??????????????USB?設(shè)備交互的應(yīng)用程序是相當(dāng)困難的。?
</
p
>
?
????????????
<
p
>
IBM?的?Dan?Streetman?最早開(kāi)始了在?Java?語(yǔ)言中提供對(duì)?USB?設(shè)備的訪問(wèn)的努力。2001年,他的項(xiàng)目通過(guò)?
??????????????Java?規(guī)范請(qǐng)求(Java?Specification?Request,JSR)過(guò)程被接受為?Java?語(yǔ)言的候選擴(kuò)展標(biāo)準(zhǔn)。這個(gè)項(xiàng)目現(xiàn)在稱(chēng)為?
??????????????JSR-80?并且指定了官方包?javax.usb。同時(shí),在?2000年?6月,Mojo?Jojo?和?David?Brownell?
??????????????在?SourceForge?開(kāi)始了?jUSB?項(xiàng)目。這兩個(gè)項(xiàng)目都開(kāi)發(fā)出了?Linux?開(kāi)發(fā)人員可以使用的包,盡管它們都還很不完善。這兩個(gè)項(xiàng)目也都開(kāi)始試圖向其他操作系統(tǒng)上的?
??????????????Java?應(yīng)用程序提供對(duì)?USB?設(shè)備的訪問(wèn),盡管它們都還沒(méi)有開(kāi)發(fā)出可以使用的包(參閱?參考資料?中有關(guān)本文中討論的這兩個(gè)項(xiàng)目及其他項(xiàng)目的資料)。
</
p
>
?
????????????
<
p
>
在本文中,將對(duì)?jUSB?和?JSR-80?項(xiàng)目作一個(gè)簡(jiǎn)要介紹,不過(guò),我們首先要看一下?USB?協(xié)議的具體細(xì)節(jié),這樣您就可以理解這兩個(gè)項(xiàng)目是如何與?
??????????????USB?設(shè)備交互的。我們還將提供代碼片段以展示如何用這兩個(gè)項(xiàng)目的?API?訪問(wèn)?USB?設(shè)備。?USB?介紹
</
p
>
?
????????????
<
p
>
1994年,一個(gè)由四個(gè)行業(yè)伙伴(Compaq、Intel、Microsoft?和?NEC)組成的聯(lián)盟開(kāi)始制定?USB?協(xié)議。該協(xié)議最初的目的是將?
??????????????PC?與電話相連并提供容易擴(kuò)展和重新配置的?I/O?接口。1996年?1月,發(fā)表了?USB?規(guī)范的第一個(gè)版本,1998年?9月發(fā)表了后續(xù)版本(版本?
??????????????1.1)。這個(gè)規(guī)范允許?127臺(tái)設(shè)備同時(shí)連接到一起,總的通信帶寬限制為?12?Mbps。后來(lái),又有三個(gè)成員(Hewlett-Packard、Lucent?
??????????????和?Philips)加入了這個(gè)聯(lián)盟。2000年?4月,發(fā)表了?USB?規(guī)范的?2.0版本,它支持高達(dá)?480?Mbps?的傳輸率。今天,USB?
??????????????在高速(視頻、圖像、儲(chǔ)存)和全速(音頻、寬帶、麥克風(fēng))數(shù)據(jù)傳輸應(yīng)用中起了關(guān)鍵作用。它還使各種低速設(shè)備(鍵盤(pán)、鼠標(biāo)、游戲外設(shè)、虛擬現(xiàn)實(shí)外設(shè))連接到?
??????????????PC?上。
</
p
>
?
????????????
<
p
>
USB?協(xié)議有嚴(yán)格的層次結(jié)構(gòu)。在所有?USB?系統(tǒng)中,只有一個(gè)主設(shè)備,到主計(jì)算機(jī)的的?USB?接口稱(chēng)為主控器(host?controller)。主控器有兩個(gè)標(biāo)準(zhǔn)??開(kāi)放主控器接口(Compaq?
??????????????的?Open?Host?Controller?Interface,OHCI)和通用主控器接口(Intel?的?Universal?
??????????????Host?Controller?Interface,UHCI)。這兩個(gè)標(biāo)準(zhǔn)提供了同樣的能力,并可用于所有的?USB?設(shè)備,UHCI?
??????????????的硬件實(shí)現(xiàn)更簡(jiǎn)單一些,但是需要更復(fù)雜的設(shè)備驅(qū)動(dòng)程序(因而?CPU?的負(fù)荷更大一些)。
</
p
>
?
????????????
<
p
>
USB?物理互連是分層的星形拓樸,最多有七層。一個(gè)?hub?是每個(gè)星形的中心,USB?主機(jī)被認(rèn)為是?root?hub。每一段連線都是?
??????????????hub?與?USB?設(shè)備的點(diǎn)對(duì)點(diǎn)連接,后者可以是為系統(tǒng)提供更多附加點(diǎn)的另一個(gè)?hub,也可以是一個(gè)提供功能的某種設(shè)備。主機(jī)使用主/從協(xié)議與?
??????????????USB?設(shè)備通信。這種方式解決了包沖突的問(wèn)題,但是同時(shí)也阻止了附加的設(shè)備彼此建立直接通信。
</
p
>
?
????????????
<
p
>
所有傳輸?shù)臄?shù)據(jù)都是由主控器發(fā)起的。數(shù)據(jù)從主機(jī)流向設(shè)備稱(chēng)為下行(downstream)或者輸出(out)傳輸,數(shù)據(jù)從設(shè)備流向主機(jī)稱(chēng)為上?
??????????????行(upstream)或者輸入(in)傳輸。數(shù)據(jù)傳輸發(fā)生在主機(jī)和?USB?設(shè)備上特定的端點(diǎn)(endpoint)?之間,主機(jī)與端點(diǎn)之間的數(shù)據(jù)鏈接稱(chēng)為管道(pipe)。?
??????????????一個(gè)給定的?USB?設(shè)備可以有許多個(gè)端點(diǎn),主機(jī)與設(shè)備之間數(shù)據(jù)管道的數(shù)量與該設(shè)備上端點(diǎn)的數(shù)量相同。一個(gè)管道可以是單向或者是雙向的,一個(gè)管道中的數(shù)據(jù)流與所有其他管道中的數(shù)據(jù)流無(wú)關(guān)。
</
p
>
?
????????????
<
p
>
USB?網(wǎng)絡(luò)中的通信可以使用下面四種數(shù)據(jù)傳輸類(lèi)型中的任意一種:
</
p
>
?
????????????
<
p
>
控制傳輸:?這些是一些短的數(shù)據(jù)包,用于設(shè)備控制和配置,特別是在設(shè)備附加到主機(jī)上時(shí)。?
</
p
>
????????????
<
p
>
批量傳輸:?這些是數(shù)量相對(duì)大的數(shù)據(jù)包。像掃描儀或者?SCSI?適配器這樣的設(shè)備使用這種傳輸類(lèi)型。?
</
p
>
?
????????????
<
p
>
中斷傳輸:?這些是定期輪詢(xún)的數(shù)據(jù)包。主控器會(huì)以特定的間隔自動(dòng)發(fā)出一個(gè)中斷。?
</
p
>
????????????
<
p
>
等時(shí)傳輸:?這些是實(shí)時(shí)的數(shù)據(jù)流,它們對(duì)帶寬的要求高于可靠性要求。音頻和視頻設(shè)備一般使用這種傳輸類(lèi)型。?
</
p
>
????????????
<
p
>
像串行端口一樣,計(jì)算機(jī)上每一個(gè)?USB?端口都由?USB?控制器指定了一個(gè)惟一的標(biāo)識(shí)數(shù)字(端口?ID)。當(dāng)?USB?設(shè)備附加到?
??????????????USB?端口上時(shí),就將這個(gè)?惟一端口?ID?分配給這臺(tái)設(shè)備,并且?USB?控制器會(huì)讀取設(shè)備描述符。設(shè)備描述符包括適用于該設(shè)備的全局信息、以及設(shè)備的配置信息。配置定義了一臺(tái)?
??????????????USB?設(shè)備的功能和?I/O?行為。一臺(tái)?USB?設(shè)備可以有一個(gè)或者多個(gè)配置,這由它們相應(yīng)的配置描述符所描述。每一個(gè)配置都有一個(gè)或者多個(gè)接口,它可以視為一個(gè)物理通信渠道?
??????????????;每一個(gè)接口有零個(gè)或者多個(gè)端點(diǎn),它可以是數(shù)據(jù)提供者或者數(shù)據(jù)消費(fèi)者,或者同時(shí)具有這兩種身份。接口由接口描述符描述,端點(diǎn)由端點(diǎn)描述符描述。并且一臺(tái)?
??????????????USB?設(shè)備可能還有字符串描述符以提供像廠商名、設(shè)備名或者序列號(hào)這樣的附加信息。
</
p
>
?
????????????
<
p
>
正如您所看到的,像?USB?這樣的協(xié)議為使用?Java?這種強(qiáng)調(diào)平臺(tái)和硬件無(wú)關(guān)性的語(yǔ)言的開(kāi)發(fā)人員提出了挑戰(zhàn)。現(xiàn)在讓我們看兩個(gè)試圖解決這個(gè)問(wèn)題的項(xiàng)目。
</
p
>
?
????????????
<
p
><
span?
class
="f14"
><
b
>
jUSB?API
</
b
></
span
></
p
>
????????????
<
p
><
span?
class
="f14"
>
?jUSB?項(xiàng)目是由?Mojo?Jojo?和?David?Brownell?于?2000年?
??????????????6月創(chuàng)立的。其目標(biāo)是提供一組免費(fèi)的、在?Linux?平臺(tái)上訪問(wèn)?USB?設(shè)備的?Java?API。這個(gè)?API?是按照?Lesser?
??????????????GPL?(LGPL)條款發(fā)表的,這意味著您可以在專(zhuān)有和免費(fèi)軟件項(xiàng)目中使用它。這個(gè)?API?提供了對(duì)多個(gè)物理?USB?設(shè)備的多線程訪問(wèn),并支持本機(jī)和遠(yuǎn)程設(shè)備。具有多個(gè)接口的設(shè)備可以同時(shí)被多個(gè)應(yīng)用程序(或者設(shè)備驅(qū)動(dòng)程序)所訪問(wèn),其中每一個(gè)應(yīng)用程序(或者設(shè)備驅(qū)動(dòng)程序)都占據(jù)一個(gè)不同的接口。該?
??????????????API?支持控制傳輸、批量傳輸和中斷傳輸,不支持等時(shí)傳輸,因?yàn)榈葧r(shí)傳輸用于媒體數(shù)據(jù)(如音頻和視頻),JMF?API?已經(jīng)在其他標(biāo)準(zhǔn)設(shè)備驅(qū)動(dòng)程序上對(duì)此提供了很好的支持(參閱?
??????????????參考資料)。當(dāng)前,該?API?可以在具有?Linux?2.4?核心或者以前的?2.2.18?核心的?GNU/Linux?版本上工作。因此可支持大多數(shù)最新的版本,例如,該?
??????????????API?可以在沒(méi)有任何補(bǔ)丁或者升級(jí)的?Red?Hat?7.2?和?9.0?上工作。
</
span
></
p
>
????????????
<
p
><
span?
class
="f14"
>
?jUSB?API?包括以下包:
<
br
>
??????????????
<
br
>
??????????????·usb.core:?這個(gè)包是?jUSB?API?的核心部分。它使得?Java?應(yīng)用程序可以從?USB?主機(jī)訪問(wèn)?USB?設(shè)備。
<
br
>
??????????????·usb.linux:?這個(gè)包包含?usb.core.Host?對(duì)象的?Linux?實(shí)現(xiàn)、bootstrapping?支持和其他可以提升?
??????????????Linux?USB?支持的類(lèi)。這個(gè)實(shí)現(xiàn)通過(guò)虛擬?USB?文件系統(tǒng)(usbdevfs)訪問(wèn)?USB?設(shè)備。
<
br
>
??????????????·usb.windows:?這個(gè)包包含?usb.core.Host?對(duì)象的?Windows?實(shí)現(xiàn)、bootstrapping?支持和其他可以提升?
??????????????Windows?USB?支持的類(lèi)。這個(gè)實(shí)現(xiàn)仍然處于非常初級(jí)的階段。
<
br
>
??????????????·usb.remote:?這個(gè)包是?usb.core?API?的遠(yuǎn)程版本。它包括一個(gè)?RMI?proxy?和一個(gè)?daemon?
??????????????應(yīng)用程序,它讓?Java?應(yīng)用程序可以訪問(wèn)遠(yuǎn)程計(jì)算機(jī)上的?USB?設(shè)備。
<
br
>
??????????????·usb.util:?這個(gè)包提供了一些有用的實(shí)用程序,可以將?firmware下載到?USB?設(shè)備上、將?USB?系統(tǒng)的內(nèi)容轉(zhuǎn)儲(chǔ)到?
??????????????XML?中、以及將只有?bulk?I/O?的?USB?設(shè)備工具轉(zhuǎn)換成一個(gè)套接字(socket)。
<
br
>
??????????????·usb.devices:?這個(gè)可選包收集了用?jUSB?API?訪問(wèn)不同?USB?設(shè)備的?Java?代碼,包括柯達(dá)數(shù)碼相機(jī)和?
??????????????Rio?500?MP3?播放器。這些?API?經(jīng)過(guò)特別編寫(xiě)以簡(jiǎn)化訪問(wèn)特定?USB?設(shè)備的過(guò)程,并且不能用于訪問(wèn)其他設(shè)備。這些?API?
??????????????是在?usb.core?API?之上構(gòu)建的,它們可以工作在所有支持?jUSB?的操作系統(tǒng)上。
<
br
>
??????????????·usb.view:?這個(gè)可選包提供了基于?Swing?的?USB?樹(shù)簡(jiǎn)單瀏覽器。它是一個(gè)展示?jUSB?API?應(yīng)用的很好的示例程序。
</
span
></
p
>
????????????
<
p
><
span?
class
="f14"
>
?盡管?usb.core.Host?對(duì)象的實(shí)現(xiàn)對(duì)于不同的操作系統(tǒng)是不同的,但是?Java?
??????????????程序員只需要理解?usb.core?包就可以用?jUSB?API?開(kāi)始應(yīng)用程序的開(kāi)發(fā)。表?1?列出了?usb.core?的接口和類(lèi),Java?
??????????????程序員應(yīng)該熟悉它們:
</
span
></
p
>
????????????
<
p
><
span?
class
="f14"
>
?表?1.?jUSB?中的接口和類(lèi)
</
span
></
p
>
????????????
<
span?
class
="f14"
>
????????????
<
table?
width
="90%"
?border
="1"
?align
="center"
?cellPadding
="2"
?cellSpacing
="0"
?class
="content"
>
??????????????
<
tbody
>
????????????????
<
tr
>
??????????????????
<
td
>
接口
</
td
>
??????????????????
<
td
>
說(shuō)明
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
??????????????????
<
td
>
Bus
</
td
>
??????????????????
<
td
>
將一組?USB?設(shè)備連接到?Host?上
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
??????????????????
<
td
>
Host
</
td
>
??????????????????
<
td
>
表示具有一個(gè)或者多個(gè)?Bus?的?USB?控制器
</
td
>
????????????????
</
tr
>
??????????????
</
tbody
>
????????????
</
table
>
????????????
<
br
>
????????????
<
table?
width
="90%"
?border
="1"
?align
="center"
?cellPadding
="2"
?cellSpacing
="0"
?class
="content"
>
??????????????
<
tbody
>
????????????????
<
tr
>
??????????????????
<
td?
width
="17%"
>
類(lèi)
</
td
>
??????????????????
<
td?
width
="83%"
>
說(shuō)明
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
??????????????????
<
td?
width
="17%"
>
Configuration
</
td
>
??????????????????
<
td?
width
="83%"
>
提供對(duì)設(shè)備所支持的?USB?
????????????????????配置的訪問(wèn),以及對(duì)與該配置關(guān)聯(lián)的接口的訪問(wèn)
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
??????????????????
<
td?
width
="17%"
>
Descriptor
</
td
>
??????????????????
<
td?
width
="83%"
>
具有?USB?
????????????????????類(lèi)型的描述符的實(shí)體的基類(lèi)
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
??????????????????
<
td?
width
="17%"
>
Device
</
td
>
??????????????????
<
td?
width
="83%"
>
提供對(duì)?USB?設(shè)備的訪問(wèn)
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
??????????????????
<
td?
width
="17%"
>
DeviceDescriptor
</
td
>
??????????????????
<
td?
width
="83%"
>
提供對(duì)?USB?設(shè)備描述符的訪問(wèn)
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
??????????????????
<
td?
width
="17%"
>
EndPoint
</
td
>
??????????????????
<
td?
width
="83%"
>
提供對(duì)?USB?
????????????????????端點(diǎn)描述符的訪問(wèn)、在給定設(shè)備配置中構(gòu)造設(shè)備數(shù)據(jù)輸入或者輸出
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
??????????????????
<
td?
width
="17%"
>
HostFactory
</
td
>
??????????????????
<
td?
width
="83%"
>
包含?bootstrapping?方法
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
??????????????????
<
td?
width
="17%"
>
Hub
</
td
>
??????????????????
<
td?
width
="83%"
>
提供對(duì)?USB?hub?描述符以及一些?hub?
????????????????????操作的訪問(wèn)
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
??????????????????
<
td?
width
="17%"
>
Interface
</
td
>
??????????????????
<
td?
width
="83%"
>
描述一組端點(diǎn),并與一個(gè)特定設(shè)備配置相關(guān)聯(lián)
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
??????????????????
<
td?
width
="17%"
>
PortIdentifier
</
td
>
??????????????????
<
td?
width
="83%"
>
為?USB?
????????????????????設(shè)備提供穩(wěn)定的字符串標(biāo)識(shí)符,以便在操作和故障診斷時(shí)使用
</
td
>
????????????????
</
tr
>
??????????????
</
tbody
>
????????????
</
table
>
????????????
</
span
>
?
<
p
><
span?
class
="f14"
><
br
>
??????????????用?jUSB?API?訪問(wèn)一臺(tái)?USB?設(shè)備的正常過(guò)程如下:
<
br
>
??????????????
</
span
><
span?
class
="f14"
><
br
>
??????????????·通過(guò)從?HostFactory?得到?USB?Host?進(jìn)行?Bootstrap。
<
br
>
??????????????·從?Host?訪問(wèn)?USB?Bus,然后從這個(gè)?Bus?訪問(wèn)?USB?root?hub(即?USB?Device)。
<
br
>
??????????????·得到?hub?上可用的?USB?端口數(shù)量,遍歷所有端口以找到正確的?Device。
<
br
>
??????????????·訪問(wèn)附加到特定端口上的?USB?Device。可以用一臺(tái)?Device?的?PortIdentifier?直接從?Host?訪問(wèn)它,也可以通過(guò)從?
??????????????root?hub?開(kāi)始遍歷?USB?Bus?找到它。
<
br
>
??????????????·用?ControlMessage?與該?Device?直接交互,或者從該?Device?的當(dāng)前?Configuration?中要求一個(gè)?
??????????????Interface,并與該?Interface?上可用的?Endpoint?進(jìn)行?I/O?。
</
span
></
p
>
????????????
<
p
><
span?
class
="f14"
>
清單?1?展示了如何用?jUSB?API?獲得?USB?系統(tǒng)中的內(nèi)容。這個(gè)程序編寫(xiě)為只是查看?
??????????????root?hub?上可用的?USB?設(shè)備,但是很容易將它改為遍歷整個(gè)?USB?樹(shù)。這里的邏輯對(duì)應(yīng)于上述步驟?1?到步驟?4。
</
span
></
p
>
????????????
<
p
><
span?
class
="f14"
>
清單?1.?用?jUSB?API?獲得?USB?系統(tǒng)的內(nèi)容
</
span
></
p
>
????????????
<
span?
class
="f14"
>
????????????
<
table?
width
="90%"
?border
="1"
?align
="center"
?borderColor
="#ffcc66"
?bgColor
="#dadacf"
?class
="content"
>
??????????????
<
tbody
>
????????????????
<
tr
>
??????????????????
<
td
>
import?usb.core.*;
<
br
>
????????????????????
<
br
>
????????????????????public?class?ListUSB
<
br
>
????????????????????{
<
br
>
???????????????????? public?static?void?main(String[]?args)
<
br
>
???????????????????? {
<
br
>
???????????????????? try
<
br
>
???????????????????? {
<
br
>
???????????????????? //?Bootstrap?by?getting?the?USB?Host?from?the?
????????????????????HostFactory.
<
br
>
???????????????????? Host?host?=?HostFactory.getHost();
<
br
>
????????????????????
<
br
>
???????????????????? //?Obtain?a?list?of?the?USB?buses?available?on?the?
????????????????????Host.
<
br
>
???????????????????? Bus[]?bus?=?host.getBusses();
<
br
>
???????????????????? int?total_bus?=?bus.length;
<
br
>
????????????????????
<
br
>
???????????????????? //?Traverse?through?all?the?USB?buses.
<
br
>
???????????????????? for?(int?i=0;?i
<
total_bus;?i++)
<
br
>
???????????????????? {
<
br
>
???????????????????? //?Access?the?root?hub?on?the?USB?bus?and?obtain?
????????????????????the
<
br
>
???????????????????? //?number?of?USB?ports?available?on?the?root?
????????????????????hub.
<
br
>
???????????????????? Device?root?=?bus[i].getRootHub();
<
br
>
???????????????????? int?total_port?=?root.getNumPorts();
<
br
>
????????????????????
<
br
>
???????????????????? //?Traverse?through?all?the?USB?ports?available?
????????????????????on?the
<
br
>
???????????????????? //?root?hub.?It?should?be?mentioned?that?the?
????????????????????numbering
<
br
>
???????????????????? //?starts?from?1,?not?0.
<
br
>
???????????????????? for?(int?j=1;?j
<
=total_port;?j++)
<
br
>
???????????????????? {
<
br
>
???????????????????? //?Obtain?the?Device?connected?to?the?port.
<
br
>
???????????????????? Device?device?=?root.getChild(j);
<
br
>
???????????????????? if?(device?!=?null)
<
br
>
???????????????????? {
<
br
>
???????????????????? //?USB?device?available,?do?something?
????????????????????here.
<
br
>
???????????????????? }
<
br
>
???????????????????? }
<
br
>
???????????????????? }
<
br
>
???????????????????? }?catch?(Exception?e)
<
br
>
???????????????????? {
<
br
>
???????????????????? System.out.println(e.getMessage());
<
br
>
???????????????????? }
<
br
>
???????????????????? }
</
td
>
????????????????
</
tr
>
??????????????
</
tbody
>
????????????
</
table
>
????????????
</
span
><
br
>
????????????
<
p
><
span?
class
="f14"
>
清單?2?展示了在應(yīng)用程序成功地找到了?Device?的條件下,如何與?Interface?
??????????????和?EndPoint?進(jìn)行批量?I/O。?這個(gè)代碼段也可以修改為執(zhí)行控制或者中斷?I/O。它對(duì)應(yīng)于上述步驟?5。
</
span
>
????????????
<
p
><
span?
class
="f14"
>
?清單?2.?用?jUSB?API?執(zhí)行批量?I/O
</
span
><
span?
class
="f14"
>
?
????????????
<
table?
width
="90%"
?border
="1"
?align
="center"
?borderColor
="#ffcc66"
?bgColor
="#dadacf"
?class
="content"
>
??????????????
<
tbody
>
????????????????
<
tr
>
?
??????????????????
<
td
>
if?(device?!=?null)
<
br
>
????????????????????{
<
br
>
???????????????????? //?Obtain?the?current?Configuration?of?the?device?and?the?
????????????????????number?of
<
br
>
???????????????????? //?Interfaces?available?under?the?current?Configuration.
<
br
>
???????????????????? Configuration?config?=?device.getConfiguration();
<
br
>
???????????????????? int?total_interface?=?config.getNumInterfaces();
<
br
>
?
<
br
>
???????????????????? //?Traverse?through?the?Interfaces
<
br
>
???????????????????? for?(int?k=0;?k
<
total_interface;?k++)
<
br
>
???????????????????? {
<
br
>
???????????????????? //?Access?the?currently?Interface?and?obtain?the?number?
????????????????????of
<
br
>
???????????????????? //?endpoints?available?on?the?Interface.
<
br
>
???????????????????? Interface?itf?=?config.getInterface(k,?0);
<
br
>
???????????????????? int?total_ep?=?itf.getNumEndpoints();
<
br
>
?
<
br
>
???????????????????? //?Traverse?through?all?the?endpoints.
<
br
>
???????????????????? for?(int?l=0;?l
<
total_ep;?l++)
<
br
>
???????????????????? {
<
br
>
???????????????????? //?Access?the?endpoint,?and?obtain?its?I/O?type.
<
br
>
???????????????????? Endpoint?ep?=?itf.getEndpoint(l);
<
br
>
???????????????????? String?io_type?=?ep.getType();
<
br
>
???????????????????? boolean?input?=?ep.isInput();
<
br
>
?
<
br
>
???????????????????? //?If?the?endpoint?is?an?input?endpoint,?obtain?its
<
br
>
???????????????????? //?InputStream?and?read?in?data.
<
br
>
???????????????????? if?(input)
<
br
>
???????????????????? {
<
br
>
???????????????????? InputStream?in;
<
br
>
???????????????????? in?=?ep.getInputStream();
<
br
>
???????????????????? //?Read?in?data?here
<
br
>
???????????????????? in.close();
<
br
>
???????????????????? }
<
br
>
???????????????????? //?If?the?Endpoint?is?and?output?Endpoint,?obtain?its
<
br
>
???????????????????? //?OutputStream?and?write?out?data.
<
br
>
???????????????????? else
<
br
>
???????????????????? {
<
br
>
???????????????????? OutputStream?out;
<
br
>
???????????????????? out?=?ep.getOutputStream();
<
br
>
???????????????????? //?Write?out?data?here.
<
br
>
???????????????????? out.close();
<
br
>
???????????????????? }
<
br
>
???????????????????? }
<
br
>
???????????????????? }
<
br
>
????????????????????}
</
td
>
????????????????
</
tr
>
??????????????
</
tbody
>
????????????
</
table
>
????????????
</
span
>
????????????
<
p
><
span?
class
="f14"
>
jUSB?項(xiàng)目在?2000年?6月到?2001年?2月期間非常活躍。該?API?的最新的版本?
??????????????0.4.4發(fā)表于?2001年?2月?14日。從那以后只提出了很少的改進(jìn),原因可能是?IBM?小組成功地成為了?Java?語(yǔ)言的候選擴(kuò)展標(biāo)準(zhǔn)。不過(guò),基于?
??????????????jUSB?已經(jīng)開(kāi)發(fā)出一些第三方應(yīng)用程序,包括?JPhoto?項(xiàng)目(這是一個(gè)用?jUSB?連接到數(shù)碼照相機(jī)的應(yīng)用程序)和?jSyncManager?
??????????????項(xiàng)目(這是一個(gè)用?jUSB?與使用?Palm?操作系統(tǒng)的?PDA?同步的應(yīng)用程序)。
</
span
>
?
</
p
>
????????????
<
p
><
span?
class
="f14"
><
b
>
JSR-80?API?(javax.usb)
</
b
></
span
>
????????????
<
p
><
span?
class
="f14"
>
正如前面提到的,JSR-80?項(xiàng)目是由?IBM?的?Dan?Streetman?于?1999年創(chuàng)立的。2001年,這個(gè)項(xiàng)目通過(guò)?
??????????????Java?規(guī)范請(qǐng)求(JSR)過(guò)程被接受為?Java?語(yǔ)言的候選擴(kuò)展標(biāo)準(zhǔn)。這個(gè)項(xiàng)目現(xiàn)在稱(chēng)為?JSR-80?并且被正式分派了?Java?
??????????????包?javax.usb。這個(gè)項(xiàng)目使用?Common?Public?License?的許可證形式,并通過(guò)?Java?Community?
??????????????Process?進(jìn)行開(kāi)發(fā)。這個(gè)項(xiàng)目的目標(biāo)是為?Java?平臺(tái)開(kāi)發(fā)一個(gè)?USB?接口,可以從任何?Java?應(yīng)用程序中完全訪問(wèn)?USB?
??????????????系統(tǒng)。JSR-80?API?支持?USB?規(guī)范所定義的全部四種傳輸類(lèi)型。目前,該?API?的?Linux?實(shí)現(xiàn)可以在支持?2.4?
??????????????核心的大多數(shù)最新?GNU/Linux?版本上工作,如?Red?Hat?7.2?和?9.0。
</
span
>
????????????
<
p
><
span?
class
="f14"
>
?JSR-80?項(xiàng)目包括三個(gè)包:javax-usb?(javax.usb?API)、javax-usb-ri?
??????????????(操作系統(tǒng)無(wú)關(guān)的基準(zhǔn)實(shí)現(xiàn)的公共部分)以及?javax-usb-ri-linux?(Linux?平臺(tái)的基準(zhǔn)實(shí)現(xiàn),它將公共基準(zhǔn)實(shí)現(xiàn)鏈接到?
??????????????Linux?USB?堆棧)。所有這三個(gè)部分都是構(gòu)成?Linux?平臺(tái)上?java.usb?API?完整功能所必需的。在該項(xiàng)目的電子郵件列表中可以看到有人正在致力于將這個(gè)?
??????????????API?移植到其他操作系統(tǒng)上(主要是?Microsoft?Windows),但是還沒(méi)有可以工作的版本發(fā)表。
</
span
>
????????????
<
p
><
span?
class
="f14"
>
?盡管?JSR-80?API?的操作系統(tǒng)無(wú)關(guān)的實(shí)現(xiàn)在不同的操作系統(tǒng)上是不同的,但是?Java?
??????????????程序員只需要理解?javax.usb?包就可以開(kāi)始開(kāi)發(fā)應(yīng)用程序了。表?2?列出了?javax.usb?中的接口和類(lèi),?Java?
??????????????程序員應(yīng)該熟悉它們:
</
span
>
????????????
<
p
><
span?
class
="f14"
>
?表?2.?JSR-80?API?中的接口和類(lèi)
</
span
><
span?
class
="f14"
>
?
????????????
<
table?
width
="90%"
?border
="1"
?align
="center"
?cellPadding
="2"
?cellSpacing
="0"
?class
="content"
>
??????????????
<
tbody
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
接口
</
td
>
??????????????????
<
td?
width
="75%"
>
說(shuō)明
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbConfiguration
</
td
>
??????????????????
<
td?
width
="75%"
>
表示?USB?設(shè)備的配置
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbConfigurationDescriptor
</
td
>
??????????????????
<
td?
width
="75%"
>
USB?配置描述符的接口
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbDevice
</
td
>
??????????????????
<
td?
width
="75%"
>
USB?設(shè)備的接口
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbDeviceDescriptor
</
td
>
??????????????????
<
td?
width
="75%"
>
USB?設(shè)備描述符的接口
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbEndpoint
</
td
>
??????????????????
<
td?
width
="75%"
>
USB?端點(diǎn)的接口
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbEndpointDescriptor
</
td
>
??????????????????
<
td?
width
="75%"
>
USB?端點(diǎn)描述符的接口
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbHub
</
td
>
??????????????????
<
td?
width
="75%"
>
USB?hub?的接口
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbInterface
</
td
>
??????????????????
<
td?
width
="75%"
>
USB?接口的接口
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbInterfaceDescriptor
</
td
>
??????????????????
<
td?
width
="75%"
>
USB?接口描述符的接口
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbPipe
</
td
>
??????????????????
<
td?
width
="75%"
>
USB?管道的接口
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbPort
</
td
>
??????????????????
<
td?
width
="75%"
>
USB?端口的接口
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbServices
</
td
>
??????????????????
<
td?
width
="75%"
>
javax.usb?實(shí)現(xiàn)的接口
</
td
>
????????????????
</
tr
>
??????????????
</
tbody
>
????????????
</
table
>
????????????
<
br
>
????????????
<
table?
width
="90%"
?border
="1"
?align
="center"
?cellPadding
="2"
?cellSpacing
="0"
?class
="content"
>
??????????????
<
tbody
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
類(lèi)
</
td
>
??????????????????
<
td?
width
="75%"
>
說(shuō)明
</
td
>
????????????????
</
tr
>
????????????????
<
tr
>
?
??????????????????
<
td?
width
="25%"
>
UsbHostManager
</
td
>
??????????????????
<
td?
width
="75%"
>
javax.usb?的入口點(diǎn)
</
td
>
????????????????
</
tr
>
??????????????
</
tbody
>
????????????
</
table
>
????????????
</
span
>
????????????
<
p
><
span?
class
="f14"
>
用?JSR-80?API?訪問(wèn)?USB?設(shè)備的正常過(guò)程如下:
<
br
>
??????????????
<
br
>
??????????????·通過(guò)從?UsbHostManager?得到相應(yīng)的?UsbServices?進(jìn)行?Bootstrap。
<
br
>
??????????????·通過(guò)?UsbServices?訪問(wèn)?root?hub。在應(yīng)用程序中?root?hub?就是一個(gè)?UsbHub。
<
br
>
??????????????·獲得連接到?root?hub?的?UsbDevices?清單。遍歷所有低級(jí)?hub?以找到正確的?UsbDevice。
<
br
>
??????????????·用控制消息(UsbControlIrp)與?UsbDevice?直接交互,或者從?UsbDevice?的相應(yīng)?UsbConfiguration?
??????????????中要求一個(gè)?UsbInterface?并與該?UsbInterface?上可用的?UsbEndpoint?進(jìn)行?I/O。
<
br
>
??????????????·如果一個(gè)?UsbEndpoint?用于進(jìn)行?I/O,那么打開(kāi)與它關(guān)聯(lián)的?UsbPipe。通過(guò)這個(gè)?UsbPipe?可以同步或者異步提交上行數(shù)據(jù)(從?
??????????????USB?設(shè)備到主計(jì)算機(jī))和下行數(shù)據(jù)(從主計(jì)算機(jī)到?USB?設(shè)備)。
<
br
>
??????????????·當(dāng)應(yīng)用程序不再需要訪問(wèn)該?UsbDevice?時(shí),關(guān)閉這個(gè)?UsbPipe?并釋放相應(yīng)的?UsbInterface。
<
br
>
??????????????
<
br
>
??????????????在清單?3?中,我們用?JSR-80?API?獲得?USB?系統(tǒng)的內(nèi)容。這個(gè)程序遞歸地遍歷?USB?系統(tǒng)上的所有?USB?hub?
??????????????并找出連接到主機(jī)計(jì)算機(jī)上的所有?USB?設(shè)備。這段代碼對(duì)應(yīng)于上述步驟?1?到步驟?3。
</
span
></
p
>
????????????
<
p
><
span?
class
="f14"
>
?清單?3.?用?JSR-80?API?獲得?USB?系統(tǒng)的內(nèi)容
</
span
></
p
>
????????????
<
span?
class
="f14"
>
?
????????????
<
table?
width
="90%"
?border
="1"
?align
="center"
?borderColor
="#ffcc66"
?bgColor
="#dadacf"
?class
="content"
>
??????????????
<
tbody
>
????????????????
<
tr
>
?
??????????????????
<
td
>
import?javax.usb.*;
<
br
>
????????????????????import?java.util.List;
<
br
>
?
<
br
>
????????????????????public?class?TraverseUSB
<
br
>
????????????????????{
<
br
>
???????????????????? public?static?void?main(String?argv[])
<
br
>
???????????????????? {
<
br
>
???????????????????? try
<
br
>
???????????????????? {
<
br
>
???????????????????? //?Access?the?system?USB?services,?and?access?to?the?root
<
br
>
???????????????????? //?hub.?Then?traverse?through?the?root?hub.
<
br
>
???????????????????? UsbServices?services?=?UsbHostManager.getUsbServices();
<
br
>
???????????????????? UsbHub?rootHub?=?services.getRootUsbHub();
<
br
>
???????????????????? traverse(rootHub);
<
br
>
???????????????????? }?catch?(Exception?e)?{}
<
br
>
???????????????????? }
<
br
>
?
<
br
>
???????????????????? public?static?void?traverse(UsbDevice?device)
<
br
>
???????????????????? {
<
br
>
???????????????????? if?(device.isUsbHub())
<
br
>
???????????????????? {
<
br
>
???????????????????? //?This?is?a?USB?Hub,?traverse?through?the?hub.
<
br
>
???????????????????? List?attachedDevices?=?((UsbHub)?device).getAttachedUsbDevices();
<
br
>
???????????????????? for?(int?i=0;?i
<
attachedDevices.size();?i++)
<
br
>
???????????????????? {
<
br
>
???????????????????? traverse((UsbDevice)?attachedDevices.get(i));
<
br
>
???????????????????? }
<
br
>
???????????????????? }
<
br
>
???????????????????? else
<
br
>
???????????????????? {
<
br
>
???????????????????? //?This?is?a?USB?function,?not?a?hub.
<
br
>
???????????????????? //?Do?something.
<
br
>
???????????????????? }
<
br
>
???????????????????? }
<
br
>
????????????????????}
</
td
>
????????????????
</
tr
>
??????????????
</
tbody
>
????????????
</
table
>
????????????
</
span
>
????????????
<
p
><
span?
class
="f14"
>
清單?4?展示了在應(yīng)用程序成功地找到?Device?后,如何與?Interface?和?EndPoint?
??????????????進(jìn)行?I/O。這段代碼還可以修改為進(jìn)行所有四種數(shù)據(jù)傳輸類(lèi)型的?I/O。它對(duì)應(yīng)于上述步驟?4?到步驟?6。
</
span
></
p
>
????????????
<
p
><
span?
class
="f14"
>
?清單?4.?用?JSR-80?API?進(jìn)行?I/O
</
span
></
p
>
????????????
<
span?
class
="f14"
>
?
????????????
<
table?
width
="90%"
?border
="1"
?align
="center"
?borderColor
="#ffcc66"
?bgColor
="#dadacf"
?class
="content"
>
??????????????
<
tbody
>
????????????????
<
tr
>
?
??????????????????
<
td
>
public?static?void?testIO(UsbDevice?device)
<
br
>
????????????????????{
<
br
>
???????????????????? try
<
br
>
???????????????????? {
<
br
>
???????????????????? //?Access?to?the?active?configuration?of?the?USB?device,?
????????????????????obtain
<
br
>
???????????????????? //?all?the?interfaces?available?in?that?configuration.
<
br
>
???????????????????? UsbConfiguration?config?=?device.getActiveUsbConfiguration();
<
br
>
???????????????????? List?totalInterfaces?=?config.getUsbInterfaces();
<
br
>
?
<
br
>
???????????????????? //?Traverse?through?all?the?interfaces,?and?access?the?endpoints
<
br
>
???????????????????? //?available?to?that?interface?for?I/O.
<
br
>
???????????????????? for?(int?i=0;?i
<
totalInterfaces.size();?i++)
<
br
>
???????????????????? {
<
br
>
???????????????????? UsbInterface?interf?=?(UsbInterface)?totalInterfaces.get(i);
<
br
>
???????????????????? interf.claim();
<
br
>
???????????????????? List?totalEndpoints?=?interf.getUsbEndpoints();
<
br
>
???????????????????? for?(int?j=0;?j
<
totalEndpoints.size();?j++)
<
br
>
???????????????????? {
<
br
>
???????????????????? //?Access?the?particular?endpoint,?determine?the?direction
<
br
>
???????????????????? //?of?its?data?flow,?and?type?of?data?transfer,?and?open?
????????????????????the
<
br
>
???????????????????? //?data?pipe?for?I/O.
<
br
>
???????????????????? UsbEndpoint?ep?=?(UsbEndpoint)?totalEndpoints.get(i);
<
br
>
???????????????????? int?direction?=?ep.getDirection();
<
br
>
???????????????????? int?type?=?ep.getType();
<
br
>
???????????????????? UsbPipe?pipe?=?ep.getUsbPipe();
<
br
>
???????????????????? pipe.open();
<
br
>
???????????????????? //?Perform?I/O?through?the?USB?pipe?here.
<
br
>
???????????????????? pipe.close();
<
br
>
???????????????????? }
<
br
>
???????????????????? interf.release();
<
br
>
???????????????????? }
<
br
>
???????????????????? }?catch?(Exception?e)?{}
<
br
>
????????????????????}
</
td
>
????????????????
</
tr
>
??????????????
</
tbody
>
????????????
</
table
>
????????????
</
span
>
????????????
<
p
><
span?
class
="f14"
>
JSR-80?項(xiàng)目從一開(kāi)始就非常活躍。2003年?2月發(fā)表了?javax.usb?API、RI?
??????????????和?RI?的?0.10.0?版本。看起來(lái)這一版本會(huì)提交給?JSR-80?委員會(huì)做最終批準(zhǔn)。預(yù)計(jì)正式成為?Java?語(yǔ)言的擴(kuò)展標(biāo)準(zhǔn)后,其他操作系統(tǒng)上的實(shí)現(xiàn)會(huì)很快出現(xiàn)。Linux?
??????????????開(kāi)發(fā)者團(tuán)體看來(lái)對(duì)?JSR-80?項(xiàng)目的興趣比?jUSB?項(xiàng)目更大,使用?Linux?平臺(tái)的?javax.usb?API?的項(xiàng)目數(shù)量在不斷地增加。
</
span
></
p
>
????????????
<
p
><
span?
class
="f14"
><
b
>
結(jié)束語(yǔ)
</
b
></
span
></
p
>
????????????
<
p
><
span?
class
="f14"
>
?jUSB?API?和?JSR-80?API?都為應(yīng)用程序提供了從運(yùn)行?Linux?操作系統(tǒng)的計(jì)算機(jī)中訪問(wèn)?
??????????????USB?設(shè)備的能力。JSR-80?API?提供了比?jUSB?API?更多的功能,很有可能成為?Java?語(yǔ)言的擴(kuò)展標(biāo)準(zhǔn)。目前,只有?
??????????????Linux?開(kāi)發(fā)人員可以利用?jUSB?和?JSR-80?API?的功能。不過(guò),有人正在積極地將這兩種?API?移植到其他操作系統(tǒng)上。Java?
??????????????開(kāi)發(fā)人員應(yīng)該在不久就可以在其他操作系統(tǒng)上訪問(wèn)?USB?設(shè)備。從現(xiàn)在起就熟悉這些?API,當(dāng)這些項(xiàng)目可以在多個(gè)平臺(tái)上發(fā)揮作用時(shí),您就可以在自己的應(yīng)用程序中加入?
??????????????USB?功能了。
</
span
></
p
></
td
>
????????
</
tr
>
??????
</
table
>