diff --git a/src/main/java/de/ailis/usb4java/Services.java b/src/main/java/de/ailis/usb4java/Services.java index 902aa02..1f30417 100644 --- a/src/main/java/de/ailis/usb4java/Services.java +++ b/src/main/java/de/ailis/usb4java/Services.java @@ -9,11 +9,13 @@ import static de.ailis.usb4java.jni.USB.usb_init; import javax.usb.UsbDevice; import javax.usb.UsbException; +import javax.usb.UsbHostManager; import javax.usb.UsbHub; import javax.usb.UsbServices; import javax.usb.event.UsbServicesEvent; import javax.usb.event.UsbServicesListener; +import de.ailis.usb4java.support.Config; import de.ailis.usb4java.support.UsbServicesListenerList; import de.ailis.usb4java.topology.UsbDeviceScanner; import de.ailis.usb4java.topology.VirtualRootHub; @@ -47,16 +49,24 @@ public final class Services implements UsbServices /** The USB device scanner. */ private final UsbDeviceScanner deviceScanner; + /** If devices should be scanned by hierarchy. */ + private final Config config; + /** * Constructor. + * + * @throws UsbException + * When properties could not be loaded. */ - public Services() + public Services() throws UsbException { + this.config = new Config(UsbHostManager.getProperties()); usb_init(); this.rootHub = new VirtualRootHub(); - this.deviceScanner = new UsbDeviceScanner(this, this.rootHub); + this.deviceScanner = + new UsbDeviceScanner(this, this.rootHub, this.config); this.deviceScanner.start(); } diff --git a/src/main/java/de/ailis/usb4java/support/Config.java b/src/main/java/de/ailis/usb4java/support/Config.java new file mode 100644 index 0000000..d9d3b8c --- /dev/null +++ b/src/main/java/de/ailis/usb4java/support/Config.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2011 Klaus Reimer + * See LICENSE.txt for licensing information. + */ + +package de.ailis.usb4java.support; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; + + +/** + * Configuration. + * + * @author Klaus Reimer (k@ailis.de) + */ + +public class Config +{ + /** Base key name for properties. */ + private final static String KEY_BASE = "de.ailis.usb4java."; + + /** Key name for scanHierarchy property. */ + private final static String SCAN_HIERARCHY_KEY = KEY_BASE + "scanHierarchy"; + + /** Key name for vendors filter property. */ + private final static String VENDORS_KEY = KEY_BASE + "vendors"; + + /** Key name for product filter property. */ + private final static String PRODUCTS_KEY = KEY_BASE + "products"; + + /** If device hierarchy should be scanned. */ + private boolean scanHierarchy; + + /** The vendor filter list or null if not filtering. */ + private Set vendors; + + /** The product filter list or null if not filtering. */ + private Set products; + + + /** + * Constructs new configuration from the specified properties. + * + * @param properties + * The properties to read the configuration from. + */ + + public Config(final Properties properties) + { + // Read scanHierarchy property. If not set then hierarchy scan is + // disabled on Mac OS X (because libusb always returns a null root_dev + // on this platform) and true for all other platforms. + if (properties.containsKey(SCAN_HIERARCHY_KEY)) + this.scanHierarchy = Boolean.parseBoolean(properties.getProperty( + SCAN_HIERARCHY_KEY)); + else + this.scanHierarchy = + !System.getProperty("os.name").startsWith("Mac OS X"); + + // Read vendor filter list + if (properties.containsKey(VENDORS_KEY)) + { + final Set vendors = new HashSet(); + final String value = properties.getProperty(VENDORS_KEY); + for (final String item : value.trim().split("\\s+")) + { + final Integer vendor = Integer.valueOf(item, 16); + vendors.add(vendor); + } + this.vendors = Collections.unmodifiableSet(vendors); + } + + // Read product filter list + if (properties.containsKey(PRODUCTS_KEY)) + { + final Set products = new HashSet(); + final String value = properties.getProperty(PRODUCTS_KEY); + for (final String item : value.trim().split("\\s+")) + { + if (item.trim().isEmpty()) continue; + final Integer product = Integer.valueOf(item, 16); + products.add(product); + } + this.products = Collections.unmodifiableSet(products); + } + } + + + /** + * Checks if device hierarchy should be scanned. + * + * @return True if device hierarchy should be scanned, false if not. + */ + + public boolean getScanHierarchy() + { + return this.scanHierarchy; + } + + + /** + * Returns the vendor filter list or null if vendors must not be + * filtered. + * + * @return The vendor filter list or null if unfiltered. + */ + + public Set getVendors() + { + return this.vendors; + } + + + /** + * Returns the product filter list or null if products must not be + * filtered. + * + * @return The product filter list or null if unfiltered. + */ + + public Set getProducts() + { + return this.products; + } +} diff --git a/src/main/java/de/ailis/usb4java/topology/LibUsbDevice.java b/src/main/java/de/ailis/usb4java/topology/LibUsbDevice.java index 063c85a..c0b7e63 100644 --- a/src/main/java/de/ailis/usb4java/topology/LibUsbDevice.java +++ b/src/main/java/de/ailis/usb4java/topology/LibUsbDevice.java @@ -103,6 +103,7 @@ public abstract class LibUsbDevice implements UsbDevice new ArrayList(configs.length); for (final USB_Config_Descriptor config : configs) { + if (config == null) continue; final LibUsbConfiguration configuration = new LibUsbConfiguration( this, config); configurations.add(configuration); diff --git a/src/main/java/de/ailis/usb4java/topology/UsbDeviceScanner.java b/src/main/java/de/ailis/usb4java/topology/UsbDeviceScanner.java index 6db484b..5b1013c 100644 --- a/src/main/java/de/ailis/usb4java/topology/UsbDeviceScanner.java +++ b/src/main/java/de/ailis/usb4java/topology/UsbDeviceScanner.java @@ -12,10 +12,13 @@ import static de.ailis.usb4java.jni.USB.usb_get_busses; import java.util.ArrayList; import java.util.List; +import java.util.Set; import de.ailis.usb4java.Services; import de.ailis.usb4java.jni.USB_Bus; import de.ailis.usb4java.jni.USB_Device; +import de.ailis.usb4java.jni.USB_Device_Descriptor; +import de.ailis.usb4java.support.Config; import de.ailis.usb4java.support.UsbLock; @@ -36,6 +39,9 @@ public final class UsbDeviceScanner /** If scanner already scanned for devices. */ private boolean scanned = false; + /** If configuration */ + private final Config config; + /** * Constructor. @@ -44,12 +50,15 @@ public final class UsbDeviceScanner * The USB services. * @param rootHub * The virtual USB root hub. + * @param config + * The configuration */ public UsbDeviceScanner(final Services services, - final VirtualRootHub rootHub) + final VirtualRootHub rootHub, final Config config) { this.rootHub = rootHub; + this.config = config; } @@ -70,8 +79,20 @@ public final class UsbDeviceScanner final List devices = new ArrayList(); while (bus != null) { - final USB_Device device = bus.root_dev(); - if (device != null) devices.add(device); + USB_Device device = bus.root_dev(); + if (this.config.getScanHierarchy()) + { + if (device != null) devices.add(device); + } + else + { + device = bus.devices(); + while (device != null) + { + devices.add(device); + device = device.next(); + } + } bus = bus.next(); } updateHub(this.rootHub, devices.toArray(new USB_Device[devices @@ -122,16 +143,33 @@ public final class UsbDeviceScanner final List oldDevices = ports.getAttachedUsbDevices(); final List newDevices = new ArrayList( devices.length); + final Set vendors = this.config.getVendors(); + final Set products = this.config.getProducts(); for (final USB_Device dev : devices) { if (dev == null) continue; + final USB_Device_Descriptor descriptor = dev.descriptor(); + + if (!this.config.getScanHierarchy() + || descriptor.bDeviceClass() != USB_CLASS_HUB) + { + // Filter for vendors if needed + if (vendors != null && !vendors.contains(descriptor.idVendor())) + continue; + + // Filter for products if needed + if (products != null + && !products.contains(descriptor.idProduct())) + continue; + } + final LibUsbDevice device = createUsbDevice(dev); newDevices.add(device); // Update existing devices if (oldDevices.contains(device)) { - if (device.isUsbHub()) + if (this.config.getScanHierarchy() && device.isUsbHub()) { final LibUsbHub hub = (LibUsbHub) oldDevices.get(oldDevices .indexOf(device)); @@ -143,7 +181,7 @@ public final class UsbDeviceScanner else { ports.connectUsbDevice(device); - if (device.isUsbHub()) + if (this.config.getScanHierarchy() && device.isUsbHub()) updateHub((LibUsbHub) device, dev.children()); } }