Many different devices can be connected to a single computer through one USB port. The computers built-in USB hub provides power for about four not particularly power-hungry devices. However, additional powered hubs can be daisy chained to enable a single system to have up to 127 different USB devices (though some of these devices must be hubs). This means the first question a programmer will ask is which devices are on the bus where.
Enumerating the currently attached USB devices is not hard. In fact, its considerably easier than enumerating the mounted disks. Most applications begin by using the static UsbHostManager.getUsbServices( ) method to return a UsbServices object:
UsbServices services = UsbHostManager.getUsbServices( );
This method can throw a SecurityException if the program is not allowed to access the USB port. It can also throw a more specific UsbException if theres any sort of problem on the USB bus that prevents the query.
You then ask this object to give you the root UsbHub:
UsbHub root = services.getRootUsbHub( );
Now you can ask the hub for a list of all the devices connected to it:
List devices = root.getAttachedUsbDevices( );
Each object in this list is an instance of the javax.usb.UsbDevice interface. This interface provides various methods for sending data to and receiving data from the device. Ill have more to say about those shortly. However, for now Ill just need one method from this interface: isUsbHub( ), to tell if the device is itself another USB hub. Using these methods, Example 23-1 demonstrates a simple program that lists all the USB devices attached to a computer.
import java.util.*; import javax.usb.*; public class USBLister { public static void main(String[] args) throws UsbException { UsbServices services = UsbHostManager.getUsbServices( ); UsbHub root = services.getRootUsbHub( ); listDevices(root); } public static void listDevices(UsbHub hub) { List devices = hub.getAttachedUsbDevices( ); Iterator iterator = devices.iterator( ); while (iterator.hasNext( )) { UsbDevice device = (UsbDevice) iterator.next( ); System.out.println(device); if (device.isUsbHub( )) { listDevices((UsbHub) device); } } } } |
To compile this and any other program that uses the Java USB API, youll need the JAR file containing the API. You can download this and the other files youll need from http://javax-usb.org. This file is named jsr80-1.0.0.jar. (The USB API was defined in Java Specification Request 80.) When you compile USBLister.java, youll need to include jsr80-1.0.0.jar in the classpath:
$ javac -classpath jsr80-1.0.0.jar USBLister.java
To run it, youll need four more files in addition to jsr80-1.0.0.jar: the reference implementation JAR, a platform-specific JAR, a native library, and a javax.usb.properties file. These can be downloaded from the same location. The JARs are installed in the classpath like any other JARs. The native library is currently distributed with the name libJavaxUsb-1.0.0.so, but youll need to rename it to libJavaxUsb.so before it will work. For example, on Linux the directory containing libJavaxUsb-1.0.0.so must be included in the LD_LIBRARY_PATH environment variable:
$ export LD_LIBRARY_PATH=/where/you/put/libJavaxUsb.so
If LD_LIBRARY_PATH has already been defined, you need to redefine it like this instead:
$ export LD_LIBRARY_PATH=/where/you/put/libJavaxUsb.so:$ LD_LIBRARY_PATH
Note that this variable points to the parent directory, not to the libJavaxUsb.so file itself. For instance, I put libJavaxUsb.so in /home/elharo/jsr80, so I set the library path like this:
$ export LD_LIBRARY_PATH=/home/elharo/jsr80
Running on my Linux box, heres what I saw:
$ java -cp jsr80-1.0.0.jar:.:jsr80_ri-1.0.0.jar:jsr80_linux-1.0.0.jar USBLister $
After I remembered my Linux box was a server and didn have any USB devices connected, I plugged my digital camera into my desktop workstation, which already had a USB mouse, and tried running Example 23-1 there. The results were exactly the same. It turns out that this program requires root access to talk to the USB ports at such a low level. So I sud to root, set roots LD_LIBRARY_PATH environment variable, and ran it again. This time it found the devices:
# java -cp jsr80-1.0.0.jar:.:jsr80_ri-1.0.0.jar:jsr80_linux-1.0.0.jar USBLister com.ibm.jusb.UsbHubImp@ec16a4 com.ibm.jusb.UsbDeviceImp@1c29ab2 com.ibm.jusb.UsbHubImp@13a328f com.ibm.jusb.UsbDeviceImp@1cd8669