<
p
>
Java 平台一直都以其平台无关性自豪。虽然这种无关性有许多好处,但是它也使得编写与硬件交互的
Java 应用程序的过程变得相当复杂。在本文中,研究科学家蒋清野讨论了两个项目,它们通过提供使Java 应用程序可以使用 USB
设备的 API 而使这个过程变得更容易。虽然这两个项目仍然处于萌芽状态,但是它们都显示了良好的前景,并已经成为一些实用应用程序的基础。
</
p
>
<
p
>
通用串行总线(Universal Serial Bus USB)规范的第一个版本发表于 1996年 1月。因为它的低成本、高数据传输率、使用容易和灵活性,USB
在计算机行业里获得了广泛接受。今天,许多周边设备和装置都是通过 USB 接口连接到计算机上的。目前,大多数一般用途的操作系统都提供了对
USB 设备的支持,并且用 C 或者 C++ 可以相对容易地开发访问这些外设的应用程序。不过,Java 编程语言在设计上对硬件访问提供的支持很少,所以编写与
USB 设备交互的应用程序是相当困难的。
</
p
>
<
p
>
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 设备的访问,尽管它们都还没有开发出可以使用的包(参阅 参考资料 中有关本文中讨论的这两个项目及其他项目的资料)。
</
p
>
<
p
>
在本文中,将对 jUSB 和 JSR-80 项目作一个简要介绍,不过,我们首先要看一下 USB 协议的具体细节,这样您就可以理解这两个项目是如何与
USB 设备交互的。我们还将提供代码片段以展示如何用这两个项目的 API 访问 USB 设备。 USB 介绍
</
p
>
<
p
>
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 上。
</
p
>
<
p
>
USB 协议有严格的层次结构。在所有 USB 系统中,只有一个主设备,到主计算机的的 USB 接口称为主控器(host controller)。主控器有两个标准??开放主控器接口(Compaq
的 Open Host Controller Interface,OHCI)和通用主控器接口(Intel 的 Universal
Host Controller Interface,UHCI)。这两个标准提供了同样的能力,并可用于所有的 USB 设备,UHCI
的硬件实现更简单一些,但是需要更复杂的设备驱动程序(因而 CPU 的负荷更大一些)。
</
p
>
<
p
>
USB 物理互连是分层的星形拓朴,最多有七层。一个 hub 是每个星形的中心,USB 主机被认为是 root hub。每一段连线都是
hub 与 USB 设备的点对点连接,后者可以是为系统提供更多附加点的另一个 hub,也可以是一个提供功能的某种设备。主机使用主/从协议与
USB 设备通信。这种方式解决了包冲突的问题,但是同时也阻止了附加的设备彼此建立直接通信。
</
p
>
<
p
>
所有传输的数据都是由主控器发起的。数据从主机流向设备称为下行(downstream)或者输出(out)传输,数据从设备流向主机称为上
行(upstream)或者输入(in)传输。数据传输发生在主机和 USB 设备上特定的端点(endpoint) 之间,主机与端点之间的数据链接称为管道(pipe)。
一个给定的 USB 设备可以有许多个端点,主机与设备之间数据管道的数量与该设备上端点的数量相同。一个管道可以是单向或者是双向的,一个管道中的数据流与所有其他管道中的数据流无关。
</
p
>
<
p
>
USB 网络中的通信可以使用下面四种数据传输类型中的任意一种:
</
p
>
<
p
>
控制传输: 这些是一些短的数据包,用于设备控制和配置,特别是在设备附加到主机上时。
</
p
>
<
p
>
批量传输: 这些是数量相对大的数据包。像扫描仪或者 SCSI 适配器这样的设备使用这种传输类型。
</
p
>
<
p
>
中断传输: 这些是定期轮询的数据包。主控器会以特定的间隔自动发出一个中断。
</
p
>
<
p
>
等时传输: 这些是实时的数据流,它们对带宽的要求高于可靠性要求。音频和视频设备一般使用这种传输类型。
</
p
>
<
p
>
像串行端口一样,计算机上每一个 USB 端口都由 USB 控制器指定了一个惟一的标识数字(端口 ID)。当 USB 设备附加到
USB 端口上时,就将这个 惟一端口 ID 分配给这台设备,并且 USB 控制器会读取设备描述符。设备描述符包括适用于该设备的全局信息、以及设备的配置信息。配置定义了一台
USB 设备的功能和 I/O 行为。一台 USB 设备可以有一个或者多个配置,这由它们相应的配置描述符所描述。每一个配置都有一个或者多个接口,它可以视为一个物理通信渠道
;每一个接口有零个或者多个端点,它可以是数据提供者或者数据消费者,或者同时具有这两种身份。接口由接口描述符描述,端点由端点描述符描述。并且一台
USB 设备可能还有字符串描述符以提供像厂商名、设备名或者序列号这样的附加信息。
</
p
>
<
p
>
正如您所看到的,像 USB 这样的协议为使用 Java 这种强调平台和硬件无关性的语言的开发人员提出了挑战。现在让我们看两个试图解决这个问题的项目。
</
p
>
<
p
><
span
class
="f14"
><
b
>
jUSB API
</
b
></
span
></
p
>
<
p
><
span
class
="f14"
>
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 上工作。
</
span
></
p
>
<
p
><
span
class
="f14"
>
jUSB API 包括以下包:
<
br
>
<
br
>
·usb.core: 这个包是 jUSB API 的核心部分。它使得 Java 应用程序可以从 USB 主机访问 USB 设备。
<
br
>
·usb.linux: 这个包包含 usb.core.Host 对象的 Linux 实现、bootstrapping 支持和其他可以提升
Linux USB 支持的类。这个实现通过虚拟 USB 文件系统(usbdevfs)访问 USB 设备。
<
br
>
·usb.windows: 这个包包含 usb.core.Host 对象的 Windows 实现、bootstrapping 支持和其他可以提升
Windows USB 支持的类。这个实现仍然处于非常初级的阶段。
<
br
>
·usb.remote: 这个包是 usb.core API 的远程版本。它包括一个 RMI proxy 和一个 daemon
应用程序,它让 Java 应用程序可以访问远程计算机上的 USB 设备。
<
br
>
·usb.util: 这个包提供了一些有用的实用程序,可以将 firmware下载到 USB 设备上、将 USB 系统的内容转储到
XML 中、以及将只有 bulk I/O 的 USB 设备工具转换成一个套接字(socket)。
<
br
>
·usb.devices: 这个可选包收集了用 jUSB API 访问不同 USB 设备的 Java 代码,包括柯达数码相机和
Rio 500 MP3 播放器。这些 API 经过特别编写以简化访问特定 USB 设备的过程,并且不能用于访问其他设备。这些 API
是在 usb.core API 之上构建的,它们可以工作在所有支持 jUSB 的操作系统上。
<
br
>
·usb.view: 这个可选包提供了基于 Swing 的 USB 树简单浏览器。它是一个展示 jUSB API 应用的很好的示例程序。
</
span
></
p
>
<
p
><
span
class
="f14"
>
尽管 usb.core.Host 对象的实现对于不同的操作系统是不同的,但是 Java
程序员只需要理解 usb.core 包就可以用 jUSB API 开始应用程序的开发。表 1 列出了 usb.core 的接口和类,Java
程序员应该熟悉它们:
</
span
></
p
>
<
p
><
span
class
="f14"
>
表 1. jUSB 中的接口和类
</
span
></
p
>
<
span
class
="f14"
>
<
table
width
="90%"
border
="1"
align
="center"
cellPadding
="2"
cellSpacing
="0"
class
="content"
>
<
tbody
>
<
tr
>
<
td
>
接口
</
td
>
<
td
>
说明
</
td
>
</
tr
>
<
tr
>
<
td
>
Bus
</
td
>
<
td
>
将一组 USB 设备连接到 Host 上
</
td
>
</
tr
>
<
tr
>
<
td
>
Host
</
td
>
<
td
>
表示具有一个或者多个 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%"
>
类
</
td
>
<
td
width
="83%"
>
说明
</
td
>
</
tr
>
<
tr
>
<
td
width
="17%"
>
Configuration
</
td
>
<
td
width
="83%"
>
提供对设备所支持的 USB
配置的访问,以及对与该配置关联的接口的访问
</
td
>
</
tr
>
<
tr
>
<
td
width
="17%"
>
Descriptor
</
td
>
<
td
width
="83%"
>
具有 USB
类型的描述符的实体的基类
</
td
>
</
tr
>
<
tr
>
<
td
width
="17%"
>
Device
</
td
>
<
td
width
="83%"
>
提供对 USB 设备的访问
</
td
>
</
tr
>
<
tr
>
<
td
width
="17%"
>
DeviceDescriptor
</
td
>
<
td
width
="83%"
>
提供对 USB 设备描述符的访问
</
td
>
</
tr
>
<
tr
>
<
td
width
="17%"
>
EndPoint
</
td
>
<
td
width
="83%"
>
提供对 USB
端点描述符的访问、在给定设备配置中构造设备数据输入或者输出
</
td
>
</
tr
>
<
tr
>
<
td
width
="17%"
>
HostFactory
</
td
>
<
td
width
="83%"
>
包含 bootstrapping 方法
</
td
>
</
tr
>
<
tr
>
<
td
width
="17%"
>
Hub
</
td
>
<
td
width
="83%"
>
提供对 USB hub 描述符以及一些 hub
操作的访问
</
td
>
</
tr
>
<
tr
>
<
td
width
="17%"
>
Interface
</
td
>
<
td
width
="83%"
>
描述一组端点,并与一个特定设备配置相关联
</
td
>
</
tr
>
<
tr
>
<
td
width
="17%"
>
PortIdentifier
</
td
>
<
td
width
="83%"
>
为 USB
设备提供稳定的字符串标识符,以便在操作和故障诊断时使用
</
td
>
</
tr
>
</
tbody
>
</
table
>
</
span
>
<
p
><
span
class
="f14"
><
br
>
用 jUSB API 访问一台 USB 设备的正常过程如下:
<
br
>
</
span
><
span
class
="f14"
><
br
>
·通过从 HostFactory 得到 USB Host 进行 Bootstrap。
<
br
>
·从 Host 访问 USB Bus,然后从这个 Bus 访问 USB root hub(即 USB Device)。
<
br
>
·得到 hub 上可用的 USB 端口数量,遍历所有端口以找到正确的 Device。
<
br
>
·访问附加到特定端口上的 USB Device。可以用一台 Device 的 PortIdentifier 直接从 Host 访问它,也可以通过从
root hub 开始遍历 USB Bus 找到它。
<
br
>
·用 ControlMessage 与该 Device 直接交互,或者从该 Device 的当前 Configuration 中要求一个
Interface,并与该 Interface 上可用的 Endpoint 进行 I/O 。
</
span
></
p
>
<
p
><
span
class
="f14"
>
清单 1 展示了如何用 jUSB API 获得 USB 系统中的内容。这个程序编写为只是查看
root hub 上可用的 USB 设备,但是很容易将它改为遍历整个 USB 树。这里的逻辑对应于上述步骤 1 到步骤 4。
</
span
></
p
>
<
p
><
span
class
="f14"
>
清单 1. 用 jUSB API 获得 USB 系统的内容
</
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 展示了在应用程序成功地找到了 Device 的条件下,如何与 Interface
和 EndPoint 进行批量 I/O。 这个代码段也可以修改为执行控制或者中断 I/O。它对应于上述步骤 5。
</
span
>
<
p
><
span
class
="f14"
>
清单 2. 用 jUSB API 执行批量 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 项目在 2000年 6月到 2001年 2月期间非常活跃。该 API 的最新的版本
0.4.4发表于 2001年 2月 14日。从那以后只提出了很少的改进,原因可能是 IBM 小组成功地成为了 Java 语言的候选扩展标准。不过,基于
jUSB 已经开发出一些第三方应用程序,包括 JPhoto 项目(这是一个用 jUSB 连接到数码照相机的应用程序)和 jSyncManager
项目(这是一个用 jUSB 与使用 Palm 操作系统的 PDA 同步的应用程序)。
</
span
>
</
p
>
<
p
><
span
class
="f14"
><
b
>
JSR-80 API (javax.usb)
</
b
></
span
>
<
p
><
span
class
="f14"
>
正如前面提到的,JSR-80 项目是由 IBM 的 Dan Streetman 于 1999年创立的。2001年,这个项目通过
Java 规范请求(JSR)过程被接受为 Java 语言的候选扩展标准。这个项目现在称为 JSR-80 并且被正式分派了 Java
包 javax.usb。这个项目使用 Common Public License 的许可证形式,并通过 Java Community
Process 进行开发。这个项目的目标是为 Java 平台开发一个 USB 接口,可以从任何 Java 应用程序中完全访问 USB
系统。JSR-80 API 支持 USB 规范所定义的全部四种传输类型。目前,该 API 的 Linux 实现可以在支持 2.4
核心的大多数最新 GNU/Linux 版本上工作,如 Red Hat 7.2 和 9.0。
</
span
>
<
p
><
span
class
="f14"
>
JSR-80 项目包括三个包:javax-usb (javax.usb API)、javax-usb-ri
(操作系统无关的基准实现的公共部分)以及 javax-usb-ri-linux (Linux 平台的基准实现,它将公共基准实现链接到
Linux USB 堆栈)。所有这三个部分都是构成 Linux 平台上 java.usb API 完整功能所必需的。在该项目的电子邮件列表中可以看到有人正在致力于将这个
API 移植到其他操作系统上(主要是 Microsoft Windows),但是还没有可以工作的版本发表。
</
span
>
<
p
><
span
class
="f14"
>
尽管 JSR-80 API 的操作系统无关的实现在不同的操作系统上是不同的,但是 Java
程序员只需要理解 javax.usb 包就可以开始开发应用程序了。表 2 列出了 javax.usb 中的接口和类, Java
程序员应该熟悉它们:
</
span
>
<
p
><
span
class
="f14"
>
表 2. JSR-80 API 中的接口和类
</
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%"
>
说明
</
td
>
</
tr
>
<
tr
>
<
td
width
="25%"
>
UsbConfiguration
</
td
>
<
td
width
="75%"
>
表示 USB 设备的配置
</
td
>
</
tr
>
<
tr
>
<
td
width
="25%"
>
UsbConfigurationDescriptor
</
td
>
<
td
width
="75%"
>
USB 配置描述符的接口
</
td
>
</
tr
>
<
tr
>
<
td
width
="25%"
>
UsbDevice
</
td
>
<
td
width
="75%"
>
USB 设备的接口
</
td
>
</
tr
>
<
tr
>
<
td
width
="25%"
>
UsbDeviceDescriptor
</
td
>
<
td
width
="75%"
>
USB 设备描述符的接口
</
td
>
</
tr
>
<
tr
>
<
td
width
="25%"
>
UsbEndpoint
</
td
>
<
td
width
="75%"
>
USB 端点的接口
</
td
>
</
tr
>
<
tr
>
<
td
width
="25%"
>
UsbEndpointDescriptor
</
td
>
<
td
width
="75%"
>
USB 端点描述符的接口
</
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 实现的接口
</
td
>
</
tr
>
</
tbody
>
</
table
>
<
br
>
<
table
width
="90%"
border
="1"
align
="center"
cellPadding
="2"
cellSpacing
="0"
class
="content"
>
<
tbody
>
<
tr
>
<
td
width
="25%"
>
类
</
td
>
<
td
width
="75%"
>
说明
</
td
>
</
tr
>
<
tr
>
<
td
width
="25%"
>
UsbHostManager
</
td
>
<
td
width
="75%"
>
javax.usb 的入口点
</
td
>
</
tr
>
</
tbody
>
</
table
>
</
span
>
<
p
><
span
class
="f14"
>
用 JSR-80 API 访问 USB 设备的正常过程如下:
<
br
>
<
br
>
·通过从 UsbHostManager 得到相应的 UsbServices 进行 Bootstrap。
<
br
>
·通过 UsbServices 访问 root hub。在应用程序中 root hub 就是一个 UsbHub。
<
br
>
·获得连接到 root hub 的 UsbDevices 清单。遍历所有低级 hub 以找到正确的 UsbDevice。
<
br
>
·用控制消息(UsbControlIrp)与 UsbDevice 直接交互,或者从 UsbDevice 的相应 UsbConfiguration
中要求一个 UsbInterface 并与该 UsbInterface 上可用的 UsbEndpoint 进行 I/O。
<
br
>
·如果一个 UsbEndpoint 用于进行 I/O,那么打开与它关联的 UsbPipe。通过这个 UsbPipe 可以同步或者异步提交上行数据(从
USB 设备到主计算机)和下行数据(从主计算机到 USB 设备)。
<
br
>
·当应用程序不再需要访问该 UsbDevice 时,关闭这个 UsbPipe 并释放相应的 UsbInterface。
<
br
>
<
br
>
在清单 3 中,我们用 JSR-80 API 获得 USB 系统的内容。这个程序递归地遍历 USB 系统上的所有 USB hub
并找出连接到主机计算机上的所有 USB 设备。这段代码对应于上述步骤 1 到步骤 3。
</
span
></
p
>
<
p
><
span
class
="f14"
>
清单 3. 用 JSR-80 API 获得 USB 系统的内容
</
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 展示了在应用程序成功地找到 Device 后,如何与 Interface 和 EndPoint
进行 I/O。这段代码还可以修改为进行所有四种数据传输类型的 I/O。它对应于上述步骤 4 到步骤 6。
</
span
></
p
>
<
p
><
span
class
="f14"
>
清单 4. 用 JSR-80 API 进行 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 项目从一开始就非常活跃。2003年 2月发表了 javax.usb API、RI
和 RI 的 0.10.0 版本。看起来这一版本会提交给 JSR-80 委员会做最终批准。预计正式成为 Java 语言的扩展标准后,其他操作系统上的实现会很快出现。Linux
开发者团体看来对 JSR-80 项目的兴趣比 jUSB 项目更大,使用 Linux 平台的 javax.usb API 的项目数量在不断地增加。
</
span
></
p
>
<
p
><
span
class
="f14"
><
b
>
结束语
</
b
></
span
></
p
>
<
p
><
span
class
="f14"
>
jUSB API 和 JSR-80 API 都为应用程序提供了从运行 Linux 操作系统的计算机中访问
USB 设备的能力。JSR-80 API 提供了比 jUSB API 更多的功能,很有可能成为 Java 语言的扩展标准。目前,只有
Linux 开发人员可以利用 jUSB 和 JSR-80 API 的功能。不过,有人正在积极地将这两种 API 移植到其他操作系统上。Java
开发人员应该在不久就可以在其他操作系统上访问 USB 设备。从现在起就熟悉这些 API,当这些项目可以在多个平台上发挥作用时,您就可以在自己的应用程序中加入
USB 功能了。
</
span
></
p
></
td
>
</
tr
>
</
table
>