Added configuration.

Added scanHierarchy config to switch between scanning root_dev or devices list.
Added configuration to filter for vendors and products for a better performance when many devices are connected.
This commit is contained in:
Klaus Reimer 2011-02-11 17:51:16 +01:00 committed by k
parent 58ff002bf8
commit 78e525d8b2
4 changed files with 184 additions and 7 deletions

View File

@ -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();
}

View File

@ -0,0 +1,128 @@
/*
* Copyright (C) 2011 Klaus Reimer <k@ailis.de>
* 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<Integer> vendors;
/** The product filter list or null if not filtering. */
private Set<Integer> 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<Integer> vendors = new HashSet<Integer>();
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<Integer> products = new HashSet<Integer>();
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<Integer> 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<Integer> getProducts()
{
return this.products;
}
}

View File

@ -103,6 +103,7 @@ public abstract class LibUsbDevice implements UsbDevice
new ArrayList<LibUsbConfiguration>(configs.length);
for (final USB_Config_Descriptor config : configs)
{
if (config == null) continue;
final LibUsbConfiguration configuration = new LibUsbConfiguration(
this, config);
configurations.add(configuration);

View File

@ -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<USB_Device> devices = new ArrayList<USB_Device>();
while (bus != null)
{
final USB_Device device = bus.root_dev();
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<LibUsbDevice> oldDevices = ports.getAttachedUsbDevices();
final List<LibUsbDevice> newDevices = new ArrayList<LibUsbDevice>(
devices.length);
final Set<Integer> vendors = this.config.getVendors();
final Set<Integer> 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());
}
}