Java 平台一直都以其平台無關性自豪。雖然這種無關性有許多好處,但是它也使得編寫與硬件交互的 Java 應用程序的過程變得相當復雜。在本文中,研究科學家蔣清野討論了兩個項目,它們通過提供使Java 應用程序可以使用 USB 設備的 API 而使這個過程變得更容易。雖然這兩個項目仍然處於萌芽狀態,但是它們都顯示了良好的前景,並已經成為一些實用應用程序的基礎。
通用串行總線(Universal Serial Bus USB)規范的第一個版本發表於 1996年 1月。因為它的低成本、高數據傳輸率、使用容易和靈活性,USB 在計算機行業裡獲得了廣泛接受。今天,許多周邊設備和裝置都是通過 USB 接口連接到計算機上的。目前,大多數一般用途的操作系統都提供了對 USB 設備的支持,並且用 C 或者 C++ 可以相對容易地開發訪問這些外設的應用程序。不過,Java 編程語言在設計上對硬件訪問提供的支持很少,所以編寫與 USB 設備交互的應用程序是相當困難的。
IBM 的 Dan Streetman 最早開始了在 Java 語言中提供對 USB 設備的訪問的努力。2001年,他的項目通過 Java 規范請求(Java Specification Request,JSR)過程被接受為 Java 語言的候選擴展標准。這個項目現在稱為 JSR-80 並且指定了官方包 javax.usb。同時,在 2000年 6月,Mojo Jojo 和 David Brownell 在 SourceForge 開始了 jUSB 項目。這兩個項目都開發出了 Linux 開發人員可以使用的包,盡管它們都還很不完善。這兩個項目也都開始試圖向其他操作系統上的 Java 應用程序提供對 USB 設備的訪問,盡管它們都還沒有開發出可以使用的包(參閱 參考資料 中有關本文中討論的這兩個項目及其他項目的資料)。
在本文中,將對 jUSB 和 JSR-80 項目作一個簡要介紹,不過,我們首先要看一下 USB 協議的具體細節,這樣您就可以理解這兩個項目是如何與 USB 設備交互的。我們還將提供代碼片段以展示如何用這兩個項目的 API 訪問 USB 設備。
USB 介紹
1994年,一個由四個行業伙伴(Compaq、Intel、Microsoft 和 NEC)組成的聯盟開始制定 USB 協議。該協議最初的目的是將 PC 與電話相連並提供容易擴展和重新配置的 I/O 接口。1996年 1月,發表了 USB 規范的第一個版本,1998年 9月發表了後續版本(版本 1.1)。這個規范允許 127台設備同時連接到一起,總的通信帶寬限制為 12 Mbps。後來,又有三個成員(Hewlett-Packard、Lucent 和 Philips)加入了這個聯盟。2000年 4月,發表了 USB 規范的 2.0版本,它支持高達 480 Mbps 的傳輸率。今天,USB 在高速(視頻、圖像、儲存)和全速(音頻、寬帶、麥克風)數據傳輸應用中起了關鍵作用。它還使各種低速設備(鍵盤、鼠標、游戲外設、虛擬現實外設)連接到 PC 上。
USB 協議有嚴格的層次結構。在所有 USB 系統中,只有一個主設備,到主計算機的的 USB 接口稱為主控器(host controller)。主控器有兩個標准??開放主控器接口(Compaq 的 Open Host Controller Interface,OHCI)和通用主控器接口(Intel 的 Universal Host Controller Interface,UHCI)。這兩個標准提供了同樣的能力,並可用於所有的 USB 設備,UHCI 的硬件實現更簡單一些,但是需要更復雜的設備驅動程序(因而 CPU 的負荷更大一些)。
USB 物理互連是分層的星形拓樸,最多有七層。一個 hub 是每個星形的中心,USB 主機被認為是 root hub。每一段連線都是 hub 與 USB 設備的點對點連接,後者可以是為系統提供更多附加點的另一個 hub,也可以是一個提供功能的某種設備。主機使用主/從協議與 USB 設備通信。這種方式解決了包沖突的問題,但是同時也阻止了附加的設備彼此建立直接通信。
所有傳輸的數據都是由主控器發起的。數據從主機流向設備稱為下行(downstream)或者輸出(out)傳輸,數據從設備流向主機稱為上 行(upstream)或者輸入(in)傳輸。數據傳輸發生在主機和 USB 設備上特定的端點(endpoint) 之間,主機與端點之間的數據鏈接稱為管道(pipe)。 一個給定的 USB 設備可以有許多個端點,主機與設備之間數據管道的數量與該設備上端點的數量相同。一個管道可以是單向或者是雙向的,一個管道中的數據流與所有其他管道中的數據流無關。
USB 網絡中的通信可以使用下面四種數據傳輸類型中的任意一種:
控制傳輸: 這些是一些短的數據包,用於設備控制和配置,特別是在設備附加到主機上時。
批量傳輸: 這些是數量相對大的數據包。像掃描儀或者 SCSI 適配器這樣的設備使用這種傳輸類型。
中斷傳輸: 這些是定期輪詢的數據包。主控器會以特定的間隔自動發出一個中斷。
等時傳輸: 這些是實時的數據流,它們對帶寬的要求高於可靠性要求。音頻和視頻設備一般使用這種傳輸類型。
像串行端口一樣,計算機上每一個 USB 端口都由 USB 控制器指定了一個惟一的標識數字(端口 ID)。當 USB 設備附加到 USB 端口上時,就將這個 惟一端口 ID 分配給這台設備,並且 USB 控制器會讀取設備描述符。設備描述符包括適用於該設備的全局信息、以及設備的配置信息。配置定義了一台 USB 設備的功能和 I/O 行為。一台 USB 設備可以有一個或者多個配置,這由它們相應的配置描述符所描述。每一個配置都有一個或者多個接口,它可以視為一個物理通信渠道 ;每一個接口有零個或者多個端點,它可以是數據提供者或者數據消費者,或者同時具有這兩種身份。接口由接口描述符描述,端點由端點描述符描述。並且一台 USB 設備可能還有字符串描述符以提供像廠商名、設備名或者序列號這樣的附加信息。
正如您所看到的,像 USB 這樣的協議為使用 Java 這種強調平台和硬件無關性的語言的開發人員提出了挑戰。現在讓我們看兩個試圖解決這個問題的項目。
jUSB API
jUSB 項目是由 Mojo Jojo 和 David Brownell 於 2000年 6月創立的。其目標是提供一組免費的、在 Linux 平台上訪問 USB 設備的 Java API。這個 API 是按照 Lesser GPL (LGPL)條款發表的,這意味著您可以在專有和免費軟件項目中使用它。這個 API 提供了對多個物理 USB 設備的多線程訪問,並支持本機和遠程設備。具有多個接口的設備可以同時被多個應用程序(或者設備驅動程序)所訪問,其中每一個應用程序(或者設備驅動程序)都占據一個不同的接口。該 API 支持控制傳輸、批量傳輸和中斷傳輸,不支持等時傳輸,因為等時傳輸用於媒體數據(如音頻和視頻),JMF API 已經在其他標准設備驅動程序上對此提供了很好的支持(參閱 參考資料)。當前,該 API 可以在具有 Linux 2.4 核心或者以前的 2.2.18 核心的 GNU/Linux 版本上工作。因此可支持大多數最新的版本,例如,該 API 可以在沒有任何補丁或者升級的 Red Hat 7.2 和 9.0 上工作。
jUSB API 包括以下包:
·usb.core: 這個包是 jUSB API 的核心部分。它使得 Java 應用程序可以從 USB 主機訪問 USB 設備。
·usb.linux: 這個包包含 usb.core.Host 對象的 Linux 實現、bootstrapping 支持和其他可以提升 Linux USB 支持的類。這個實現通過虛擬 USB 文件系統(usbdevfs)訪問 USB 設備。
·usb.windows: 這個包包含 usb.core.Host 對象的 Windows 實現、bootstrapping 支持和其他可以提升 Windows USB 支持的類。這個實現仍然處於非常初級的階段。
·usb.remote: 這個包是 usb.core API 的遠程版本。它包括一個 RMI proxy 和一個 daemon 應用程序,它讓 Java 應用程序可以訪問遠程計算機上的 USB 設備。
·usb.util: 這個包提供了一些有用的實用程序,可以將 firmware下載到 USB 設備上、將 USB 系統的內容轉儲到 XML 中、以及將只有 bulk I/O 的 USB 設備工具轉換成一個套接字(socket)。
·usb.devices: 這個可選包收集了用 jUSB API 訪問不同 USB 設備的 Java 代碼,包括柯達數碼相機和 Rio 500 MP3 播放器。這些 API 經過特別編寫以簡化訪問特定 USB 設備的過程,並且不能用於訪問其他設備。這些 API 是在 usb.core API 之上構建的,它們可以工作在所有支持 jUSB 的操作系統上。
·usb.view: 這個可選包提供了基於 Swing 的 USB 樹簡單浏覽器。它是一個展示 jUSB API 應用的很好的示例程序。
盡管 usb.core.Host 對象的實現對於不同的操作系統是不同的,但是 Java 程序員只需要理解 usb.core 包就可以用 jUSB API 開始應用程序的開發。表 1 列出了 usb.core 的接口和類,Java 程序員應該熟悉它們:
表 1. jUSB 中的接口和類
接口 說明
Bus 將一組 USB 設備連接到 Host 上
Host 表示具有一個或者多個 Bus 的 USB 控制器
類 說明
Configuration 提供對設備所支持的 USB 配置的訪問,以及對與該配置關聯的接口的訪問
Descriptor 具有 USB 類型的描述符的實體的基類
Device 提供對 USB 設備的訪問
DeviceDescriptor 提供對 USB 設備描述符的訪問
EndPoint 提供對 USB 端點描述符的訪問、在給定設備配置中構造設備數據輸入或者輸出
HostFactory 包含 bootstrapping 方法
Hub 提供對 USB hub 描述符以及一些 hub 操作的訪問
Interface 描述一組端點,並與一個特定設備配置相關聯
PortIdentifier 為 USB 設備提供穩定的字符串標識符,以便在操作和故障診斷時使用
用 jUSB API 訪問一台 USB 設備的正常過程如下:
·通過從 HostFactory 得到 USB Host 進行 Bootstrap。
·從 Host 訪問 USB Bus,然後從這個 Bus 訪問 USB root hub(即 USB Device)。
·得到 hub 上可用的 USB 端口數量,遍歷所有端口以找到正確的 D