busName added to be able to distinguish multiple instances of the same device on Linux

getRegisteredDevice fixed
documentation updates and other minor improvements

git-svn-id: https://svn.code.sf.net/p/libusbjava/code/trunk@273 94ad28fe-ef68-46b1-9651-e7ae4fcf1c4c
This commit is contained in:
spandi
2009-05-15 19:04:59 +00:00
parent ab05c5b054
commit 519dac0002
16 changed files with 279 additions and 70 deletions

View File

@@ -3,8 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: Java libusb wrapper
Bundle-SymbolicName: ch.ntb.usb
Bundle-Version: 1.0.2
Bundle-Localization: plugin
Bundle-Vendor: libusbjava.sourceforge.net
Eclipse-LazyStart: false
Require-Bundle: org.junit4
Export-Package: ch.ntb.usb
Bundle-RequiredExecutionEnvironment: J2SE-1.5

View File

@@ -34,6 +34,12 @@ public class Device {
*/
private String filename;
/**
* Optional identification value for the device (e.g. if there are multiple
* devices with the same vendor and product id).
*/
private String busName;
private int dev_configuration, dev_interface, dev_altinterface;
private long usbDevHandle;
@@ -53,12 +59,14 @@ public class Device {
this.filename = null;
}
protected Device(short idVendor, short idProduct, String filename) {
protected Device(short idVendor, short idProduct, String busName,
String filename) {
resetOnFirstOpen = false;
resetDone = false;
maxPacketSize = -1;
this.idVendor = idVendor;
this.idProduct = idProduct;
this.busName = busName;
this.filename = filename;
}
@@ -86,11 +94,11 @@ public class Device {
/**
* Initializes the device. The parameters <code>idVendor</code> and
* <code>idProduct</code> are mandatory. The parameter
* <code>filename</code> is optional.
* <code>idProduct</code> are mandatory. The parameter <code>filename</code>
* is optional.
*/
private Usb_Device initDevice(int idVendorParam, int idProductParam,
String filename) throws USBException {
String busName, String filename) throws USBException {
Usb_Bus bus = USB.getBus();
Usb_Device device = null;
@@ -99,18 +107,38 @@ public class Device {
device = bus.getDevices();
while (device != null) {
Usb_Device_Descriptor devDesc = device.getDescriptor();
if (filename != null
&& filename.compareTo(device.getFilename()) == 0
&& devDesc.getIdVendor() == idVendorParam
&& devDesc.getIdProduct() == idProductParam) {
// idVendor, idProduct and filename
logger.info("Device found: " + device.getFilename());
updateMaxPacketSize(device);
return device;
} else if (devDesc.getIdVendor() == idVendorParam
&& devDesc.getIdProduct() == idProductParam) {
// only idVendor and idProduct
logger.info("Device found: " + device.getFilename());
if (busName != null && filename != null) {
if (busName.compareTo(bus.getDirname()) == 0
&& filename.compareTo(device.getFilename()) == 0
&& devDesc.getIdVendor() == idVendor
&& devDesc.getIdProduct() == idProduct) {
logger.info("Device found. bus: " + bus.getDirname()
+ ", filename: " + device.getFilename());
updateMaxPacketSize(device);
return device;
}
} else if (filename != null) {
if (filename.compareTo(device.getFilename()) == 0
&& devDesc.getIdVendor() == idVendor
&& devDesc.getIdProduct() == idProduct) {
logger.info("Device found. bus: " + bus.getDirname()
+ ", filename: " + device.getFilename());
updateMaxPacketSize(device);
return device;
}
} else if (busName != null) {
if (busName.compareTo(bus.getDirname()) == 0
&& devDesc.getIdVendor() == idVendor
&& devDesc.getIdProduct() == idProduct) {
logger.info("Device found. bus: " + bus.getDirname()
+ ", filename: " + device.getFilename());
updateMaxPacketSize(device);
return device;
}
} else if (devDesc.getIdVendor() == idVendor
&& devDesc.getIdProduct() == idProduct) {
logger.info("Device found. bus: " + bus.getDirname()
+ ", filename: " + device.getFilename());
updateMaxPacketSize(device);
return device;
}
@@ -129,7 +157,7 @@ public class Device {
* @throws USBException
*/
public void updateDescriptors() throws USBException {
dev = initDevice(idVendor, idProduct, filename);
dev = initDevice(idVendor, idProduct, busName, filename);
}
/**
@@ -166,8 +194,8 @@ public class Device {
* Opens the device and claims the specified configuration, interface and
* altinterface.<br>
* First the bus is enumerated. If the device is found its descriptors are
* read and the <code>maxPacketSize</code> value is updated. If no
* endpoints are found in the descriptors an exception is thrown.
* read and the <code>maxPacketSize</code> value is updated. If no endpoints
* are found in the descriptors an exception is thrown.
*
* @param configuration
* the configuration, see
@@ -177,8 +205,8 @@ public class Device {
* {@link Usb_Interface_Descriptor#getBInterfaceNumber()}
* @param altinterface
* the alternate interface, see
* {@link Usb_Interface_Descriptor#getBAlternateSetting()}. If
* no alternate interface must be set <i>-1</i> can be used.
* {@link Usb_Interface_Descriptor#getBAlternateSetting()}. If no
* alternate interface must be set <i>-1</i> can be used.
* @throws USBException
*/
public void open(int configuration, int interface_, int altinterface)
@@ -191,7 +219,7 @@ public class Device {
throw new USBException("device opened, close or reset first");
}
dev = initDevice(idVendor, idProduct, filename);
dev = initDevice(idVendor, idProduct, busName, filename);
if (dev != null) {
long res = LibusbJava.usb_open(dev);
@@ -203,10 +231,8 @@ public class Device {
}
if (dev == null || usbDevHandle == 0) {
throw new USBException("USB device with idVendor 0x"
+ Integer.toHexString(idVendor & 0xFFFF)
+ " and idProduct 0x"
+ Integer.toHexString(idProduct & 0xFFFF) + " not found");
throw new USBException("USB device with " + toString()
+ " not found on USB");
}
claim_interface(usbDevHandle, configuration, interface_, altinterface);
if (resetOnFirstOpen & !resetDone) {
@@ -245,7 +271,13 @@ public class Device {
/**
* Sends an USB reset to the device. The device handle will no longer be
* valid. To use the device again, {@link #open(int, int, int)} must be
* called.
* called.<br>
* Note that the device is re-attached to the USB which may cause the bus
* and filename to be changed. If the bus and filename parameters are used
* in {@link USB#getDevice(short, short, String, String)} unregister the
* device using {@link USB#unregisterDevice(Device)}, re-enumerate the bus
* and create a new device instance. If that is not done the device may not
* be found.
*
* @throws USBException
*/
@@ -742,15 +774,27 @@ public class Device {
/**
* Returns the optional filename which is set when there are multiple
* devices with the same vendor and product id. See
* {@link USB#getDevice(short, short, String)}. Use
* {@link USB#getDevice(short, short, String, String)}. Use
* {@link Usb_Device#getFilename()} to read the filename of a device.
*
* @return the filename if set or null
* @return the filename or null
*/
protected String getFilename() {
return filename;
}
/**
* Returns the optional bus name which is set when there are multiple
* devices with the same vendor and product id. See
* {@link USB#getDevice(short, short, String, String)}. Use
* {@link Usb_Bus#getDirname()} to read the name of a bus.
*
* @return the bus name or null
*/
protected String getBusName() {
return busName;
}
/**
* Returns the Usb_Device instance associated with this device. This value
* is only valid after opening the device.
@@ -760,4 +804,13 @@ public class Device {
public Usb_Device getDevice() {
return dev;
}
@Override
public String toString() {
return "idVendor: 0x" + Integer.toHexString(getIdVendor() & 0xffff)
+ ", idProduct: 0x"
+ Integer.toHexString(getIdProduct() & 0xffff) + ", busName: "
+ getBusName() + ", filename: " + getFilename();
}
}

View File

@@ -170,66 +170,113 @@ public class USB {
private static boolean initUSBDone = false;
/**
* Create a new device an register it in a device queue. If the device is
* Create a new device an register it in a device list. If the device is
* already registered, a reference to it will be returned.<br>
* After resetting or re-attaching a device the busName and filename may
* change. You can unregister the current device instance (see
* {@link #unregisterDevice(Device)}) and get a new instance with the
* updated bus and filename.
*
* @param idVendor
* the vendor id of the USB device
* @param idProduct
* the product id of the USB device
* @param busName
* optional name of the bus which can be used to distinguish
* multiple devices with the same vendor and product id.<br>
* see {@link Usb_Bus#getDirname()}
* @param filename
* an optional filename which can be used to distinguish multiple
* devices with the same vendor and product id.
* optional filename which can be used to distinguish multiple
* devices with the same vendor and product id.<br>
* see {@link Usb_Device#getFilename()}
* @return a newly created device or an already registered device
*/
public static Device getDevice(short idVendor, short idProduct,
String filename) {
String busName, String filename) {
// check if this device is already registered
Device dev = getRegisteredDevice(idVendor, idProduct, filename);
Device dev = getRegisteredDevice(idVendor, idProduct, busName, filename);
if (dev != null) {
logger.info("return already registered device");
logger.info("return already registered device: " + dev);
return dev;
}
dev = new Device(idVendor, idProduct, filename);
logger.info("create new device");
dev = new Device(idVendor, idProduct, busName, filename);
logger.info("create new device: " + dev);
devices.add(dev);
return dev;
}
/**
* See {@link #getDevice(short, short, String)}. The parameter
* <code>filename</code> is set to null.
* See {@link #getDevice(short, short, String, String)}. The parameter
* <code>filename</code> and <code>busName</code>is set to null.
*
* @param idVendor
* @param idProduct
* @return a newly created device or an already registered device
*/
public static Device getDevice(short idVendor, short idProduct) {
return getDevice(idVendor, idProduct, null);
return getDevice(idVendor, idProduct, null, null);
}
/**
* Unregister a registered device.
*
* @param dev
* the device to unregister
* @return true if the device has been removed, else false
*/
public static boolean unregisterDevice(Device dev) {
return devices.remove(dev);
}
/**
* Get an already registered device or null if the device does not exist.<br>
* To uniquely identify a device bus and filename should be set. If only one
* of those is set the first device matching the criteria is returned.
*
* @param idVendor
* the vendor id of the USB device
* @param idProduct
* the product id of the USB device
* @param busName
* the name of the bus which can be used to distinguish multiple
* devices with the same vendor and product id.<br>
* see {@link Usb_Bus#getDirname()}
* @param filename
* an optional filename which can be used to distinguish multiple
* devices with the same vendor and product id.
* devices with the same vendor and product id. see
* {@link Usb_Device#getFilename()}
*
* @return the device or null
*/
private static Device getRegisteredDevice(short idVendor, short idProduct,
String filename) {
String busName, String filename) {
for (Iterator<Device> iter = devices.iterator(); iter.hasNext();) {
Device dev = iter.next();
if (filename != null && dev.getFilename() != null
&& filename.compareTo(dev.getFilename()) == 0
&& dev.getIdVendor() == idVendor
&& dev.getIdProduct() == idProduct) {
return dev;
// bus and filename
if (busName != null && filename != null) {
if (busName.compareTo(dev.getBusName() == null ? "" : dev
.getBusName()) == 0
&& filename.compareTo(dev.getFilename() == null ? ""
: dev.getFilename()) == 0
&& dev.getIdVendor() == idVendor
&& dev.getIdProduct() == idProduct) {
return dev;
}
} else if (filename != null) {
if (filename.compareTo(dev.getFilename() == null ? "" : dev
.getFilename()) == 0
&& dev.getIdVendor() == idVendor
&& dev.getIdProduct() == idProduct) {
return dev;
}
} else if (busName != null) {
if (busName.compareTo(dev.getBusName() == null ? "" : dev
.getBusName()) == 0
&& dev.getIdVendor() == idVendor
&& dev.getIdProduct() == idProduct) {
return dev;
}
} else if (dev.getIdVendor() == idVendor
&& dev.getIdProduct() == idProduct) {
return dev;
@@ -262,7 +309,7 @@ public class USB {
/**
* Explicitly calls {@link LibusbJava#usb_init()}. Note that you don't need
* to call this procedure as it is called implicitly when creating a new
* device with {@link USB#getDevice(short, short, String)}.
* device with {@link USB#getDevice(short, short, String, String)}.
*/
public static void init() {
LibusbJava.usb_init();

View File

@@ -35,7 +35,6 @@ public class Usb_Device {
* The address of the device structure to be passed to usb_open. This value
* is used only internally so we don't use getter or setter methods.
*/
@SuppressWarnings("unused")
public long devStructAddr;
/**

View File

@@ -66,7 +66,9 @@ public class Usb_Endpoint_Descriptor extends Usb_Descriptor {
* <br>
* Bits 3..0: Endpoint number <br>
* Bits 6..4: Reserved. Set to zero <br>
* Bit 7: Direction. 0 = Out, 1 = In (ignored for control endpoints)<br>
* Bit 7: Direction (host to device). 0 = OUT (send data from host to
* device), 1 = IN (host receives data from device). Note: these values are
* ignored for control endpoints.<br>
*
* @return the endpoint address
*/

View File

@@ -13,6 +13,10 @@ public abstract class AbstractDeviceInfo {
private short idProduct;
private String filename = null;
private String busName = null;
private int timeout;
private int configuration;
@@ -188,4 +192,20 @@ public abstract class AbstractDeviceInfo {
public void setSerialVersion(String serialVersion) {
this.serialVersion = serialVersion;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getBusName() {
return busName;
}
public void setBusName(String busName) {
this.busName = busName;
}
}

View File

@@ -75,7 +75,7 @@ public class UsbView extends JFrame {
* @return void
*/
private void initialize() {
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setJMenuBar(getJJMenuBar());
this.setSize(APP_WIDTH, APP_HIGHT);
this.setContentPane(getJContentPane());

View File

@@ -73,7 +73,8 @@ public class DeviceTest {
readData = new byte[testData.length];
// initialise the device
LibusbJava.usb_set_debug(255);
dev = USB.getDevice(devinfo.getIdVendor(), devinfo.getIdProduct());
dev = USB.getDevice(devinfo.getIdVendor(), devinfo.getIdProduct(),
devinfo.getBusName(), devinfo.getFilename());
assertNotNull(dev);
// print the devices
@@ -102,6 +103,7 @@ public class DeviceTest {
@Test
public void initalReset() throws Exception {
doOpen();
// this may change the bus and file name of the device
dev.reset();
timeout();
}
@@ -153,19 +155,69 @@ public class DeviceTest {
}
@Test
public void openWithFilename() throws Exception {
// get device by filename
public void open() throws Exception {
// get device by busname
doOpen();
assertNotNull(dev.getDevice());
String oldFilename = dev.getDevice().getFilename();
String oldBusName = dev.getDevice().getBus().getDirname();
assertNotNull(oldFilename);
log.info("Filename: " + oldFilename);
assertNotNull(oldBusName);
log.info("filename: " + oldFilename + ", busName: " + oldBusName);
Device dev2 = USB.getDevice(devinfo.getIdVendor(), devinfo
.getIdProduct(), oldFilename);
assertEquals(dev, dev2);
.getIdProduct());
doClose();
assertEquals(dev, dev2);
}
@Test
public void openWithBusName() throws Exception {
// get device by busname
doOpen();
assertNotNull(dev.getDevice());
String oldFilename = dev.getDevice().getFilename();
String oldBusName = dev.getDevice().getBus().getDirname();
assertNotNull(oldFilename);
assertNotNull(oldBusName);
log.info("filename: " + oldFilename + ", busName: " + oldBusName);
Device dev2 = USB.getDevice(devinfo.getIdVendor(), devinfo
.getIdProduct(), oldBusName, null);
doClose();
assertEquals(dev, dev2);
}
@Test
public void openWithFilename() throws Exception {
// get device by busname
doOpen();
assertNotNull(dev.getDevice());
String oldFilename = dev.getDevice().getFilename();
String oldBusName = dev.getDevice().getBus().getDirname();
assertNotNull(oldFilename);
assertNotNull(oldBusName);
log.info("filename: " + oldFilename + ", busName: " + oldBusName);
Device dev2 = USB.getDevice(devinfo.getIdVendor(), devinfo
.getIdProduct(), null, oldFilename);
doClose();
assertEquals(dev, dev2);
}
@Test
public void openWithBusAndFilename() throws Exception {
// get device by busname and filename
doOpen();
assertNotNull(dev.getDevice());
String oldFilename = dev.getDevice().getFilename();
String oldBusName = dev.getDevice().getBus().getDirname();
assertNotNull(oldFilename);
assertNotNull(oldBusName);
log.info("filename: " + oldFilename + ", busName: " + oldBusName);
Device dev2 = USB.getDevice(devinfo.getIdVendor(), devinfo
.getIdProduct(), oldBusName, oldFilename);
doClose();
assertEquals(dev, dev2);
}
@Test
public void bulkWriteRead() throws Exception {
checkBulkEndpoints();
@@ -398,6 +450,7 @@ public class DeviceTest {
return b;
}
@SuppressWarnings("unused")
private void logData(byte[] data, int length) {
if (length > 0) {
log.info("length: " + length);

View File

@@ -89,7 +89,7 @@ public class MemoryLeakTest {
@Test
public void bulkWriteReadMultiple() throws Exception {
final int NumberOfIterations = 30000;
final int NumberOfIterations = 3000;
devinfo.setMode(TransferMode.Bulk);
doOpen();
@@ -104,7 +104,7 @@ public class MemoryLeakTest {
@Test
public void interruptWriteReadMultiple() throws Exception {
final int NumberOfIterations = 30000;
final int NumberOfIterations = 3000;
devinfo.setMode(TransferMode.Interrupt);
doOpen();

View File

@@ -216,9 +216,9 @@ public class TestLibUsbJava {
verbose = false;
}
// used for debugging. 0 = no debugging.
// used for debugging. 0 = no debugging, 255 = with debugging
//
LibusbJava.usb_set_debug(0);
LibusbJava.usb_set_debug(255);
LibusbJava.usb_init();

View File

@@ -5,7 +5,7 @@
* http://libusbjava.sourceforge.net
* This library is covered by the LGPL, read LGPL.txt for details.
*/
package ch.ntb.usb.test;
package ch.ntb.usb.test.devices;
import ch.ntb.usb.USB;
import ch.ntb.usb.testApp.AbstractDeviceInfo;

View File

@@ -5,7 +5,7 @@
* http://libusbjava.sourceforge.net
* This library is covered by the LGPL, read LGPL.txt for details.
*/
package ch.ntb.usb.test;
package ch.ntb.usb.test.devices;
import ch.ntb.usb.USB;
import ch.ntb.usb.testApp.AbstractDeviceInfo;

View File

@@ -5,7 +5,7 @@
* http://libusbjava.sourceforge.net
* This library is covered by the LGPL, read LGPL.txt for details.
*/
package ch.ntb.usb.test;
package ch.ntb.usb.test.devices;
import ch.ntb.usb.testApp.AbstractDeviceInfo;

View File

@@ -0,0 +1,34 @@
/*
* Java libusb wrapper
* Copyright (c) 2005-2006 Andreas Schl<68>pfer <spandi at users.sourceforge.net>
*
* http://libusbjava.sourceforge.net
* This library is covered by the LGPL, read LGPL.txt for details.
*/
package ch.ntb.usb.test.devices;
import ch.ntb.usb.testApp.AbstractDeviceInfo;
public class MousePlus extends AbstractDeviceInfo {
@Override
public void initValues() {
setIdVendor((short) 0x046d);
setIdProduct((short) 0xc016);
setBusName("bus-0");
setFilename("\\\\.\\libusb0-0001--0x046d-0xc016");
setTimeout(2000);
setConfiguration(1);
setInterface(0);
setAltinterface(0);
setOutEPInt(-1);
setInEPInt(0x81);
setOutEPBulk(-1);
setInEPBulk(-1);
setSleepTimeout(5000);
setMaxDataSize(4);
setMode(TransferMode.Interrupt);
// we only read data -> don't compare
setDoCompareData(false);
}
}

View File

@@ -4,8 +4,10 @@
################################################################
# Atmel AVR AT90USB1287
# testdeviceInfo=ch.ntb.usb.test.AT90USB1287
testdeviceInfo=ch.ntb.usb.test.devices.AT90USB1287
# Cypress FX2 CY7C68013A
# testdeviceInfo=ch.ntb.usb.test.CY7C68013A
#testdeviceInfo=ch.ntb.usb.test.devices.CY7C68013A
# MX500 Mouse
testdeviceInfo=ch.ntb.usb.test.MX500
#testdeviceInfo=ch.ntb.usb.test.devices.MX500
# Logitech Notebook Mouse Plus
#testdeviceInfo=ch.ntb.usb.test.devices.MousePlus

View File

@@ -1,3 +1,3 @@
[InternetShortcut]
URL=http://www.staruml.com/
URL=http://staruml.sourceforge.net/
Modified=7081E8FF540DC70101