The Java platform has traditionally prided itself on its platform independence. While that independence has many benefits, it makes the process of writing Java applications that interact with hardware quite tricky. In this article, research scientist Qingye Jiang examines two projects that are making the process easier by providing APIs through which Java applications can make use of USB devices. While both projects are still in embryo form, both show promise and are already serving as the foundations of some real-world applications.
The first version of the Universal Serial Bus (USB) specification was released in January 1996. Because of its low cost, high data-transfer rate, ease of use, and flexibility, USB has gained wide acceptance in the computer industry. Today, many peripherals and devices connect to computers through USB interfaces. Currently, most general-purpose operating systems provide support for USB devices, and it is relatively easy to develop applications in C or C++ that access such peripherals. However, the Java programming language by design provides very little support for hardware access, so writing Java applications that interact with USB devices has proved quite difficult.
Efforts to provide access to USB devices in the Java language were initiated in 1999 by Dan Streetman at IBM. In 2001, his project was accepted as a candidate extended standard of the Java language through the Java Specification Request (JSR) process. The project is now called JSR-80 and has been officially assigned the Java package javax.usb
. Meanwhile, in June 2000, Mojo Jojo and David Brownell started the jUSB project at SourceForge. Both of these projects have since produced usable packages for Linux developers, although neither is close to perfect. Both projects also have begun attempts to provide access to USB devices for Java applications on other operating systems, though usable packages have not yet emerged from either. (See Resources for references to these and other projects discussed in this article.)
In this article, you‘ll get a brief introduction to the jUSB and JSR-80 projects; first, however, we‘ll take a look at the nuts and bolts of the USB protocol, so that you can understand how both of those projects interact with USB devices. We‘ll also offer code snippets to show how you‘d use both projects‘ APIs to access USB devices.
In 1994, an alliance of four industrial partners (Compaq, Intel, Microsoft, and NEC) started specifying the USB protocol. The original goal of the protocol was to connect the PC to the telephone and to provide I/O interfaces that were easy to expand and reconfigure. In January 1996, the first version of the USB specification was released, and a subsequent revision (version 1.1) was released in September 1998. The specification allowed 127 devices to be connected together at the same time, with the total communication bandwidth limited to 12 Mbps. Later on, three more members (Hewlett-Packard, Lucent, and Philips) joined the alliance. In April 2000, version 2.0 of the USB specification, which supports transfer rates up to 480 Mbps, was released. Today, USB plays a key role in high-speed (video, imaging, storage) and full-speed (audio, broadband, microphone) data-transfer applications. It also connects a variety of low-speed devices (keyboards, mice, game peripherals, virtual reality peripherals) to the PC.
The USB protocol is strictly hierarchical. In any USB system there is only a single host, and the USB interface to the host computer is referred to as the host controller. There are two standards for host controllers -- the Open Host Controller Interface (OHCI, by Compaq) and the Universal Host Controller Interface (UHCI, by Intel). Both standards provide the same capabilities and work with all USB devices; the hardware implementation of a UHCI is simpler, but requires a more complex device driver (and thus puts more load onto the CPU).
The USB physical interconnect is a tiered star topology, with up to seven tiers. A hub is at the center of each star, and the USB host is considered the root hub. Each wired segment is a point-to-point connection between a hub and USB device; the latter can be either another hub that provides additional attachment points to the system, or a device of some sort that provides functional capabilities. The host uses a master/subordinate protocol to communicate with the USB devices. This approach solves the problem of packet collision but also prevents the attached devices from establishing direct communication with each other.
All the data transfers are initiated by the host controller. Data directed from the host to a device is called downstream or out transfer; data directed from a device to the host is called upstream or in transfer. Data transfer occurs between the host and a particular endpoint on the USB device, and the data link between the host and the endpoint is called a pipe. A given USB device may have many endpoints, and the number of data pipes between the host and the device is the same as the number of endpoints on the device. A pipe may be uni-directional or bi-directional, and the data flow in one pipe is independent of the data flow in any other pipes.
Communication on the USB network can use any one of four different data transfer types:
Like a serial port, each USB port on a computer is assigned a unique identification number (port ID) by the USB controller. When a USB device is attached to a USB port, this unique port ID is assigned to the device and the device descriptor is read by the USB controller The device descriptor includes information that applies globally to the device, as well as information on the configuration of the device. A configuration defines the functionality and I/O behavior of a USB device. A USB device may have one or more configurations, which are described by their corresponding configuration descriptors. Each configuration has one or more interfaces, which can be considered as a physical communication channel; each interface has zero or more endpoints, which can be either data providers or data consumers, or both. Interfaces are described by interface descriptors, and endpoints are described by end-point descriptors. Furthermore, a USB device might also have string descriptors to provide additional information such as vendor name, device name, or serial numbers.
As you can see, a protocol like USB offers challenges to developers who use the Java language, which strives for platform- and hardware-independence. Let‘s now take a look at two projects that have tried to bridge the gap.
![]() |
|
The jUSB project was created by Mojo Jojo and David Brownell in June 2000. Its objective was to provide a set of free software Java APIs to access USB devices on Linux platforms. The API is distributed under the Lesser GPL (LGPL), which means that you can use it in proprietary as well as free software projects. The API provides multithreaded access to multiple physical USB devices, and supports both native and remote devices. Devices with multiple interfaces can be accessed by multiple applications (or device drivers) simultaneously, with each application (or device driver) claiming a different interface. The API supports control transfers, bulk transfers, and interrupt transfers; isochronous transfers are not supported because these are used for media data (such as audio and video) that are already well supported by the JMF API (see Resources) over other standardized device drivers. Currently, the API works on GNU/Linux distributions with either the Linux 2.4 kernel or a back port into 2.2.18 kernel. Thus, most recent distributions are supported; for example, the API works on Red Hat 7.2 and 9.0 without any patches or other upgrades.
The jUSB API includes the following packages:
usb.core
: This package is the core part of the jUSB API. It allows Java applications to access USB devices from USB hosts. usb.linux
: This package contains a Linux implementation of a usb.core.Host
object, bootstrapping support, and other classes leveraging Linux USB support. This implementation accesses the USB devices through the virtual USB device file system (usbdevfs
).usb.windows
: This package has a Windows implementation of a usb.core.Host
object, bootstrapping support, and other classes leveraging Windows USB support. This implementation is still in its very early stage.usb.remote
: This package is a remote version of the usb.core
API. It includes an RMI proxy and a daemon application, which allow Java applications to access USB devices on a remote computer.usb.util
: This package provides some useful utilities to download firmware to USB devices, dump the content of the USB system into XML, and convert a USB device with only bulk I/O into a socket. usb.devices
: This optional package collects Java code to access a variety of USB devices with the jUSB API, including Kodak digital cameras and Rio 500 MP3 Players. These APIs were specially written to simplify the process of accessing the designated USB devices and cannot be used to access other devices. The APIs were built upon the usb.core
APIs, and they will work on any operating system where jUSB is supported.usb.view
: This optional package provides a simple USB tree browser based on Swing. It is a very good example program illustrating the use of the jUSB API. Although the implementation of the usb.core.Host
object varies from operating system to operating system, a Java programmer needs to understand only the usb.core
package to start developing applications with the jUSB APIs. Table 1 outlines the interfaces and classes from usb.core
with which a Java programmer should be familiar:
Table 1. Interfaces and classes in jUSB
Interface | Description |
Bus | Connects a set of USB devices to a Host |
Host | Represents a USB controller with one or more Bus es |
Class | Description |
Configuration | Provides access to a USB configuration supported by a device and to the interfaces associated with that configuration |
Descriptor | Base class for entities with USB typed descriptors |
Device | Provides access to a USB device |
DeviceDescriptor | Provides access to a USB device descriptor |
EndPoint | Provides access to a USB end-point descriptor, structuring device data input or output in a given device configuration |
HostFactory | Contains bootstrapping methods |
Hub | Provides access to a USB hub descriptor and some hub operations |
Interface | Describes sets of endpoints, and is associated with a particular device configuration |
PortIdentifier | Provides stable string identifiers for USB devices, appropriate for use in operations and troubleshooting |
The normal procedure to access a USB device with the jUSB API is as follows:
Host
from the HostFactory
.Bus
from the Host
, then access the USB root hub (which is a USB Device
) from the Bus
.Device
.Device
that is attached to a particular port. A Device
can be accessed directly from the Host
with its PortIdentifier
, or can be found by traversing the USB Bus
starting from the root hub. Device
directly with ControlMessage
, or claim an Interface
from the current Configuration
of the Device
and perform I/O with the Endpoint
available on the Interface
. Listing 1 illustrates how to obtain the content of a USB system with the jUSB API. The program as written simply looks at the root hub for available USB devices, but it would be easy to improve it to traverse the whole USB tree. The logic here corresponds to steps 1 through 4 above.
|
Listing 2 illustrates how to perform bulk I/O with Interface
and EndPoint
, assuming that the application has successfully located the Device
. This code snippet can also be modified to perform control or interrupt I/O. It corresponds to step 5 above.
|
The jUSB project was very active from June 2000 to February 2001. The most recent release of the API, version 0.4.4, was made available on February 14, 2001. Only some minor progress has been reported since that time, probably due to the success of the IBM group in becoming a candidate extended standard of the Java language. However, several third-party applications have been developed based on jUSB, including the JPhoto project (an application using jUSB to connect to digital cameras) and the jSyncManager project (an application using jUSB to synchronize with a Palm OS-based PDA).
![]() |
|
As noted earlier, the JSR-80 project was created by Dan Streetman at IBM in 1999. In 2001, the project was accepted as a candidate extended standard of the Java language through the Java Specification Request (JSR) process. The project is now called JSR-80 and has been officially assigned the Java package javax.usb
. The project is licensed under the Common Public License and is developed using the Java Community Process. The objective of this project is to develop a USB interface for the Java platform that will allow full access to the USB system for any Java application or middleware component. The JSR-80 API provides full support for all four transfer types defined by the USB specification. Currently, the Linux implementation of the API works on most recent GNU/Linux distributions with 2.4 kernel support, such as Red Hat 7.2 and 9.0.
The JSR-80 project includes three packages: javax-usb
(the javax.usb
API), javax-usb-ri
(the common part of the OS-independent reference implementation), and javax-usb-ri-linux
(the reference implementation for the Linux platform, which connects the common reference implementation to the Linux USB stack). All three parts are required to form a complete functioning java.usb
API on the Linux platform. Independent efforts aimed at porting the API to other operating systems (primarily Microsoft Windows) have been reported on the project e-mail list, but no functioning packages have been released yet.
Although the OS-dependent implementation of the JSR-80 APIs varies from operating system to operating system, a Java programmer needs to understand only the javax.usb
package to start developing applications. Table 2 lists the interfaces and classes in javax.usb
with which a Java programmer should be familiar:
Table 2. Interfaces and classes in the JSR-80 APIs
Interface | Description |
UsbConfiguration | Represents a configuration of a USB device |
UsbConfigurationDescriptor | Interface for a USB configuration descriptor |
UsbDevice | Interface for a USB device |
UsbDeviceDescriptor | Interface for a USB device descriptor |
UsbEndpoint | Interface for a USB endpoint |
UsbEndpointDescriptor | Interface for a USB endpoint descriptor |
UsbHub | Interface for a USB hub |
UsbInterface | Interface for a USB interface |
UsbInterfaceDescriptor | Interface for a USB interface descriptor |
UsbPipe | Interface for a USB pipe |
UsbPort | Interface for a USB port |
UsbServices | Interface for a javax.usb implementation |
Class | Description |
UsbHostManager | Entry point for javax.usb |
The normal procedure for accessing a USB device with the JSR-80 API is as follows:
UsbServices
from the UsbHostManager
. UsbServices
. The root hub is considered as a UsbHub
in the application.UsbDevice
s that are connected to the root hub. Traverse through all the lower-level hubs to find the appropriate UsbDevice
.UsbDevice
directly with a control message (UsbControlIrp
), or claim a UsbInterface
from the appropriate UsbConfiguration
of the UsbDevice
and perform I/O with the UsbEndpoint
available on the UsbInterface
.UsbEndpoint
is used to perform I/O, open the UsbPipe
associated with it. Both upstream data (from the USB device to the host computer) and downstream data (from the host computer to the USB device) can be submitted either synchronously or asynchronously through the UsbPipe
.UsbPipe
and release the appropriate UsbInterface
when the application no longer needs access to the UsbDevice
. In Listing 3, we obtain the content of the USB system with the JSR-80 API. The program recursively traverses through all the USB hubs on the USB system and locates all the USB devices connected to the host computer. The code corresponds to steps 1 through 3 above.
|
Listing 4 illustrates how to perform I/O with Interface
and EndPoint
, assuming that the application has successfully located a Device
. This code snippet can also be modified to perform I/O of all four data transfer types. It corresponds to steps 4 through 6 above.
|
The JSR-80 project has been very active from its very beginning. Version 0.10.0 of the javax.usb
API, RI, and RI for Linux were released in February 2003. It is likely that this version will be submitted to the JSR-80 committee for final approval. It is expected that implementations for other operating systems will soon be available after JSR-80 formally becomes an extended standard of the Java language. The Linux developer community seems to show more interest in the JSR-80 project than the jUSB project, and there have been an increasing number of projects launched using the javax.usb
API on the Linux platform.
![]() |
|
Both the jUSB API and the JSR-80 API provide Java applications with the capability to access USB devices from a machine running the Linux operating system. The JSR-80 API provides more functionality than the jUSB API, and has the potential of becoming an extended standard of the Java language. Currently, only Linux developers can take advantage of the jUSB and JSR-80 APIs. However, active efforts to port both APIs to other operating systems have been reported. Java developers should be able to access USB devices on other operating systems in the near future. By familiarizing yourself with these APIs now, you can be ready to add USB functionality to your applications when these projects are ready for prime time on multiple platforms.
![]() |
|
联系客服