Monday, January 11, 2010

Section 23.8. Hot Plugging










23.8. Hot Plugging






The javax.usb.event.UsbServicesListener
interface can notify your program whenever a USB deviceeven one you've never seen beforeis plugged into or unplugged from the bus. This interface has two callback methods. usbDeviceAttached( ) is called when a device is plugged in, and usbDeviceDetached( ) is called when a device is unplugged (or turned off, which amounts to the same thing):



package javax.usb.event;
public interface UsbServicesListener extends java.util.EventListener {

public void usbDeviceAttached(UsbServicesEvent event);
public void usbDeviceDetached(UsbServicesEvent event);
}



Each of these methods receives a UsbServicesEvent object as an argument. This interface has a getUsbDevice( ) method that returns the device that was connected or disconnected:



public UsbDevice getUsbDevice( )



Example 23-9 is a simple implementation of this interface that prints the manufacturer string and other info for each device added to or removed from the bus.


Example 23-9. A listener for USB devices plugged in and unplugged




import javax.usb.*;
import javax.usb.event.*;
public class HotplugListener implements UsbServicesListener {
public void usbDeviceAttached(UsbServicesEvent event) {
UsbDevice device = event.getUsbDevice( );
System.out.println(getDeviceInfo(device) + " was added to the bus.");
}
public void usbDeviceDetached(UsbServicesEvent event) {
UsbDevice device = event.getUsbDevice( );
System.out.println(getDeviceInfo(device) + " was removed from the bus.");
}
private static String getDeviceInfo(UsbDevice device) {
try {
String product = device.getProductString( );
String serial = device.getSerialNumberString( );
if (product == null) return "Unknown USB device";
if (serial != null) return product + " " + serial;
else return product;
}
catch (Exception ex) {
}
return "Unknown USB device";
}
}



You register your listeners with a javax.usb.UsbServices object using the customary add and remove methods:



public void addUsbServicesListener(UsbServicesListener listener)
public void removeUsbServicesListener(UsbServicesListener listener)



This object then calls back to your listener to notify it of devices added and removed.


Example 23-10 is a simple program that uses the listener in Example 23-9 to notify the user when devices are plugged in and unplugged.


Example 23-10. A program that tells the user when USB devices are plugged in and unplugged




import javax.usb.*;
import javax.usb.event.*;
public class Hotplugger {
public static void main(String[] args)
throws UsbException, InterruptedException {
UsbServices services = UsbHostManager.getUsbServices( );
services.addUsbServicesListener(new HotplugListener( ));
// Keep this program from exiting immediately
Thread.sleep(500000);
}
}



Here's the output as I repeatedly connected and disconnected a couple of different devices from the bus:



Silicon Integrated Systems [SiS] USB 1.0 Controller 0000:00:02.2
was added to the bus.
USB-PS/2 Optical Mouse was added to the bus.
Silicon Integrated Systems [SiS] USB 1.0 Controller (#2) 0000:00:02.3
was added to the bus.
Unknown device was added to the bus.
Unknown device was removed from the bus.
Unknown device was added to the bus.
Unknown device was removed from the bus.
Unknown device was added to the bus.
Unknown device was removed from the bus.
DMC-FZ5 was added to the bus.
Unknown device was removed from the bus.
DMC-FZ5 was added to the bus.



Interestingly, when the program starts, usbDeviceAttached( ) is called once for each already attached device, including each of the USB controllers. You'll also notice that you can't get much info when a device is detached. All the usual methodsgetProductString( ), getSerialNumberString( ), etc.require the device to be connected to work. Otherwise, they throw an exception. However, the same object is returned when the device is detached as when it is attached, so you can load up all the information the first time, store it somewhere, and then retrieve it locally when the device is detached. Example 23-11 uses a HashMap to do this.


Example 23-11. A USB listener that remembers devices




import javax.usb.*;
import javax.usb.event.*;
import java.util.*;
public class ImprovedHotplugListener implements UsbServicesListener {
private Map devices = new HashMap( );

public void usbDeviceAttached(UsbServicesEvent event) {
UsbDevice device = event.getUsbDevice( );
String deviceInfo = getDeviceInfo(device);
devices.put(device, deviceInfo);
System.out.println(deviceInfo + " was added to the bus.");
}
public void usbDeviceDetached(UsbServicesEvent event) {
UsbDevice device = event.getUsbDevice( );
String deviceInfo = (String) devices.get(device);
System.out.println(deviceInfo + " was removed from the bus.");
}
private static String getDeviceInfo(UsbDevice device) {
try {
String product = device.getProductString( );
String serial = device.getSerialNumberString( );
if (product == null) return "Unknown USB device";
if (serial != null) return product + " " + serial;
else return product;
}
catch (Exception ex) {
}
return "Unknown USB device";
}
}



This only goes so far. The Java USB API does not recognize devices that are plugged in again: it creates a new UsbDevice object for a reconnected device.












No comments: