diff --git a/src/main/java/ch/ntb/usb.r273/Device.java b/src/main/java/ch/ntb/usb.r273/Device.java new file mode 100644 index 0000000..7398295 --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/Device.java @@ -0,0 +1,816 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import ch.ntb.usb.logger.LogUtil; + +/** + * This class represents an USB device.
+ * To get an instance of an USB device use USB.getDevice(...). + * + */ +public class Device { + + private static final Logger logger = LogUtil.getLogger("ch.ntb.usb"); + + private int maxPacketSize; + + /** + * Mandatory identification values for the device. + */ + private int idVendor, idProduct; + + /** + * Optional identification value for the device (e.g. if there are multiple + * devices with the same vendor and product id). + */ + 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; + + private boolean resetOnFirstOpen, resetDone; + + private int resetTimeout = 2000; + + private Usb_Device dev; + + protected Device(short idVendor, short idProduct) { + resetOnFirstOpen = false; + resetDone = false; + maxPacketSize = -1; + this.idVendor = idVendor; + this.idProduct = idProduct; + this.filename = null; + } + + 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; + } + + private void updateMaxPacketSize(Usb_Device device) throws USBException { + maxPacketSize = -1; + Usb_Config_Descriptor[] confDesc = device.getConfig(); + for (int i = 0; i < confDesc.length; i++) { + Usb_Interface[] int_ = confDesc[i].getInterface(); + for (int j = 0; j < int_.length; j++) { + Usb_Interface_Descriptor[] intDesc = int_[j].getAltsetting(); + for (int k = 0; k < intDesc.length; k++) { + Usb_Endpoint_Descriptor[] epDesc = intDesc[k].getEndpoint(); + for (int l = 0; l < epDesc.length; l++) { + maxPacketSize = Math.max(epDesc[l].getWMaxPacketSize(), + maxPacketSize); + } + } + } + } + if (maxPacketSize <= 0) { + throw new USBException( + "No USB endpoints found. Check the device configuration"); + } + } + + /** + * Initializes the device. The parameters idVendor and + * idProduct are mandatory. The parameter filename + * is optional. + */ + private Usb_Device initDevice(int idVendorParam, int idProductParam, + String busName, String filename) throws USBException { + Usb_Bus bus = USB.getBus(); + + Usb_Device device = null; + // search for device + while (bus != null) { + device = bus.getDevices(); + while (device != null) { + Usb_Device_Descriptor devDesc = device.getDescriptor(); + 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; + } + device = device.getNext(); + } + bus = bus.getNext(); + } + return null; + } + + /** + * Updates the device and descriptor information from the bus.
+ * The descriptors can be read with {@link #getDeviceDescriptor()} and + * {@link #getConfigDescriptors()}. + * + * @throws USBException + */ + public void updateDescriptors() throws USBException { + dev = initDevice(idVendor, idProduct, busName, filename); + } + + /** + * Returns the device descriptor associated with this device.
+ * The descriptor is updated by calling {@link #updateDescriptors()} or + * {@link #open(int, int, int)}. + * + * @return the device descriptor associated with this device or + * null + */ + public Usb_Device_Descriptor getDeviceDescriptor() { + if (dev == null) { + return null; + } + return dev.getDescriptor(); + } + + /** + * Returns the configuration descriptors associated with this device.
+ * The descriptors are updated by calling {@link #updateDescriptors()} or + * {@link #open(int, int, int)}. + * + * @return the configuration descriptors associated with this device or + * null + */ + public Usb_Config_Descriptor[] getConfigDescriptors() { + if (dev == null) { + return null; + } + return dev.getConfig(); + } + + /** + * Opens the device and claims the specified configuration, interface and + * altinterface.
+ * First the bus is enumerated. If the device is found its descriptors are + * read and the maxPacketSize value is updated. If no endpoints + * are found in the descriptors an exception is thrown. + * + * @param configuration + * the configuration, see + * {@link Usb_Config_Descriptor#getBConfigurationValue()} + * @param interface_ + * the interface, see + * {@link Usb_Interface_Descriptor#getBInterfaceNumber()} + * @param altinterface + * the alternate interface, see + * {@link Usb_Interface_Descriptor#getBAlternateSetting()}. If no + * alternate interface must be set -1 can be used. + * @throws USBException + */ + public void open(int configuration, int interface_, int altinterface) + throws USBException { + this.dev_configuration = configuration; + this.dev_interface = interface_; + this.dev_altinterface = altinterface; + + if (usbDevHandle != 0) { + throw new USBException("device opened, close or reset first"); + } + + dev = initDevice(idVendor, idProduct, busName, filename); + + if (dev != null) { + long res = LibusbJava.usb_open(dev); + if (res == 0) { + throw new USBException("LibusbJava.usb_open: " + + LibusbJava.usb_strerror()); + } + usbDevHandle = res; + } + + if (dev == null || usbDevHandle == 0) { + throw new USBException("USB device with " + toString() + + " not found on USB"); + } + claim_interface(usbDevHandle, configuration, interface_, altinterface); + if (resetOnFirstOpen & !resetDone) { + logger.info("reset on first open"); + resetDone = true; + reset(); + try { + Thread.sleep(resetTimeout); + } catch (InterruptedException e) { + // + } + open(configuration, interface_, altinterface); + } + } + + /** + * Release the claimed interface and close the opened device.
+ * + * @throws USBException + */ + public void close() throws USBException { + if (usbDevHandle == 0) { + throw new USBException("invalid device handle"); + } + release_interface(usbDevHandle, dev_interface); + if (LibusbJava.usb_close(usbDevHandle) < 0) { + usbDevHandle = 0; + throw new USBException("LibusbJava.usb_close: " + + LibusbJava.usb_strerror()); + } + usbDevHandle = 0; + maxPacketSize = -1; + logger.info("device closed"); + } + + /** + * 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.
+ * 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 + */ + public void reset() throws USBException { + if (usbDevHandle == 0) { + throw new USBException("invalid device handle"); + } + release_interface(usbDevHandle, dev_interface); + if (LibusbJava.usb_reset(usbDevHandle) < 0) { + usbDevHandle = 0; + throw new USBException("LibusbJava.usb_reset: " + + LibusbJava.usb_strerror()); + } + usbDevHandle = 0; + logger.info("device reset"); + } + + /** + * Write data to the device using a bulk transfer.
+ * + * @param out_ep_address + * endpoint address to write to + * @param data + * data to write to this endpoint + * @param size + * size of the data + * @param timeout + * amount of time in ms the device will try to send the data + * until a timeout exception is thrown + * @param reopenOnTimeout + * if set to true, the device will try to open the connection and + * send the data again before a timeout exception is thrown + * @return the actual number of bytes written + * @throws USBException + */ + public int writeBulk(int out_ep_address, byte[] data, int size, + int timeout, boolean reopenOnTimeout) throws USBException { + if (usbDevHandle == 0) { + throw new USBException("invalid device handle"); + } + if (data == null) { + throw new USBException("data must not be null"); + } + if (size <= 0 || size > data.length) { + throw new ArrayIndexOutOfBoundsException("invalid size: " + size); + } + int lenWritten = LibusbJava.usb_bulk_write(usbDevHandle, + out_ep_address, data, size, timeout); + if (lenWritten < 0) { + if (lenWritten == LibusbJava.ERROR_TIMEDOUT) { + // try to reopen the device and send the data again + if (reopenOnTimeout) { + logger.info("try to reopen"); + reset(); + open(dev_configuration, dev_interface, dev_altinterface); + return writeBulk(out_ep_address, data, size, timeout, false); + } + throw new USBTimeoutException("LibusbJava.usb_bulk_write: " + + LibusbJava.usb_strerror()); + } + throw new USBException("LibusbJava.usb_bulk_write: " + + LibusbJava.usb_strerror()); + } + + logger.info("length written: " + lenWritten); + if (logger.isLoggable(Level.FINEST)) { + StringBuffer sb = new StringBuffer("bulkwrite, ep 0x" + + Integer.toHexString(out_ep_address) + ": " + lenWritten + + " Bytes sent: "); + for (int i = 0; i < lenWritten; i++) { + sb.append("0x" + String.format("%1$02X", data[i]) + " "); + } + logger.info(sb.toString()); + } + return lenWritten; + } + + /** + * Read data from the device using a bulk transfer.
+ * + * @param in_ep_address + * endpoint address to read from + * @param data + * data buffer for the data to be read + * @param size + * the maximum requested data size + * @param timeout + * amount of time in ms the device will try to receive data until + * a timeout exception is thrown + * @param reopenOnTimeout + * if set to true, the device will try to open the connection and + * receive the data again before a timeout exception is thrown + * @return the actual number of bytes read + * @throws USBException + */ + public int readBulk(int in_ep_address, byte[] data, int size, int timeout, + boolean reopenOnTimeout) throws USBException { + if (usbDevHandle == 0) { + throw new USBException("invalid device handle"); + } + if (data == null) { + throw new USBException("data must not be null"); + } + if (size <= 0 || size > data.length) { + throw new ArrayIndexOutOfBoundsException("invalid size: " + size); + } + int lenRead = LibusbJava.usb_bulk_read(usbDevHandle, in_ep_address, + data, size, timeout); + if (lenRead < 0) { + if (lenRead == LibusbJava.ERROR_TIMEDOUT) { + // try to reopen the device and send the data again + if (reopenOnTimeout) { + logger.info("try to reopen"); + reset(); + open(dev_configuration, dev_interface, dev_altinterface); + return readBulk(in_ep_address, data, size, timeout, false); + } + throw new USBTimeoutException("LibusbJava.usb_bulk_read: " + + LibusbJava.usb_strerror()); + } + throw new USBException("LibusbJava.usb_bulk_read: " + + LibusbJava.usb_strerror()); + } + + logger.info("length read: " + lenRead); + if (logger.isLoggable(Level.FINEST)) { + StringBuffer sb = new StringBuffer("bulkread, ep 0x" + + Integer.toHexString(in_ep_address) + ": " + lenRead + + " Bytes received: "); + for (int i = 0; i < lenRead; i++) { + sb.append("0x" + String.format("%1$02X", data[i]) + " "); + } + logger.info(sb.toString()); + } + return lenRead; + } + + /** + * Write data to the device using a interrupt transfer.
+ * + * @param out_ep_address + * endpoint address to write to + * @param data + * data to write to this endpoint + * @param size + * size of the data + * @param timeout + * amount of time in ms the device will try to send the data + * until a timeout exception is thrown + * @param reopenOnTimeout + * if set to true, the device will try to open the connection and + * send the data again before a timeout exception is thrown + * @return the actual number of bytes written + * @throws USBException + */ + public int writeInterrupt(int out_ep_address, byte[] data, int size, + int timeout, boolean reopenOnTimeout) throws USBException { + if (usbDevHandle == 0) { + throw new USBException("invalid device handle"); + } + if (data == null) { + throw new USBException("data must not be null"); + } + if (size <= 0 || size > data.length) { + throw new ArrayIndexOutOfBoundsException("invalid size: " + size); + } + int lenWritten = LibusbJava.usb_interrupt_write(usbDevHandle, + out_ep_address, data, size, timeout); + if (lenWritten < 0) { + if (lenWritten == LibusbJava.ERROR_TIMEDOUT) { + // try to reopen the device and send the data again + if (reopenOnTimeout) { + logger.info("try to reopen"); + reset(); + open(dev_configuration, dev_interface, dev_altinterface); + return writeInterrupt(out_ep_address, data, size, timeout, + false); + } + throw new USBTimeoutException( + "LibusbJava.usb_interrupt_write: " + + LibusbJava.usb_strerror()); + } + throw new USBException("LibusbJava.usb_interrupt_write: " + + LibusbJava.usb_strerror()); + } + + logger.info("length written: " + lenWritten); + if (logger.isLoggable(Level.FINEST)) { + StringBuffer sb = new StringBuffer("interruptwrite, ep 0x" + + Integer.toHexString(out_ep_address) + ": " + lenWritten + + " Bytes sent: "); + for (int i = 0; i < lenWritten; i++) { + sb.append("0x" + String.format("%1$02X", data[i]) + " "); + } + logger.info(sb.toString()); + } + return lenWritten; + } + + /** + * Read data from the device using a interrupt transfer.
+ * + * @param in_ep_address + * endpoint address to read from + * @param data + * data buffer for the data to be read + * @param size + * the maximum requested data size + * @param timeout + * amount of time in ms the device will try to receive data until + * a timeout exception is thrown + * @param reopenOnTimeout + * if set to true, the device will try to open the connection and + * receive the data again before a timeout exception is thrown + * @return the actual number of bytes read + * @throws USBException + */ + public int readInterrupt(int in_ep_address, byte[] data, int size, + int timeout, boolean reopenOnTimeout) throws USBException { + if (usbDevHandle == 0) { + throw new USBException("invalid device handle"); + } + if (data == null) { + throw new USBException("data must not be null"); + } + if (size <= 0 || size > data.length) { + throw new ArrayIndexOutOfBoundsException("invalid size: " + size); + } + int lenRead = LibusbJava.usb_interrupt_read(usbDevHandle, + in_ep_address, data, size, timeout); + if (lenRead < 0) { + if (lenRead == LibusbJava.ERROR_TIMEDOUT) { + // try to reopen the device and send the data again + if (reopenOnTimeout) { + logger.info("try to reopen"); + reset(); + open(dev_configuration, dev_interface, dev_altinterface); + return readInterrupt(in_ep_address, data, size, timeout, + false); + } + throw new USBTimeoutException("LibusbJava.usb_interrupt_read: " + + LibusbJava.usb_strerror()); + } + throw new USBException("LibusbJava.usb_interrupt_read: " + + LibusbJava.usb_strerror()); + } + + logger.info("length read: " + lenRead); + if (logger.isLoggable(Level.FINEST)) { + StringBuffer sb = new StringBuffer("interrupt, ep 0x" + + Integer.toHexString(in_ep_address) + ": " + lenRead + + " Bytes received: "); + for (int i = 0; i < lenRead; i++) { + sb.append("0x" + String.format("%1$02X", data[i]) + " "); + } + logger.info(sb.toString()); + } + return lenRead; + } + + /** + * Performs a control request to the default control pipe on a device.
+ * The parameters mirror the types of the same name in the USB + * specification. + * + * @param requestType + * USB device request type (USB specification 9.3, + * bmRequestType). Use constants from {@link ch.ntb.usb.USB} + * (REQ_TYPE_xxx). + * @param request + * specific request (USB specification 9.4, bRequest). Use + * constants from {@link ch.ntb.usb.USB} (REQ_xxx). + * @param value + * field that varies according to request (USB specification 9.4, + * wValue) + * @param index + * field that varies according to request (USB specification 9.4, + * wIndex) + * @param data + * the send/receive buffer + * @param size + * the buffer size. 0 is a valid value, but there must still be a + * dummy data buffer provided. + * @param timeout + * amount of time in ms the device will try to send/receive data + * until a timeout exception is thrown + * @param reopenOnTimeout + * if set to true, the device will try to open the connection and + * send/receive the data again before a timeout exception is + * thrown + * @return the number of bytes written/read + * @throws USBException + */ + public int controlMsg(int requestType, int request, int value, int index, + byte[] data, int size, int timeout, boolean reopenOnTimeout) + throws USBException { + if (usbDevHandle == 0) { + throw new USBException("invalid device handle"); + } + if (data == null) { + throw new USBException("data must not be null"); + } + if (size < 0 || size > data.length) { + throw new ArrayIndexOutOfBoundsException("invalid size: " + size); + } + int len = LibusbJava.usb_control_msg(usbDevHandle, requestType, + request, value, index, data, size, timeout); + if (len < 0) { + if (len == LibusbJava.ERROR_TIMEDOUT) { + // try to reopen the device and send the data again + if (reopenOnTimeout) { + logger.info("try to reopen"); + reset(); + open(dev_configuration, dev_interface, dev_altinterface); + return controlMsg(requestType, request, value, index, data, + size, timeout, false); + } + throw new USBTimeoutException("LibusbJava.controlMsg: " + + LibusbJava.usb_strerror()); + } + throw new USBException("LibusbJava.controlMsg: " + + LibusbJava.usb_strerror()); + } + + logger.info("length read/written: " + len); + if (logger.isLoggable(Level.FINEST)) { + StringBuffer sb = new StringBuffer("controlMsg: " + len + + " Bytes received(written: "); + for (int i = 0; i < len; i++) { + sb.append("0x" + String.format("%1$02X", data[i]) + " "); + } + logger.info(sb.toString()); + } + return len; + } + + /** + * Claim an interface to send and receive USB data.
+ * + * @param usb_dev_handle + * the handle of the device (MUST BE VALID) + * @param configuration + * the configuration to use + * @param interface_ + * the interface to claim + * @param altinterface + * the alternate interface to use. If no alternate interface must + * be set -1 can be used. + * @throws USBException + * throws an USBException if the action fails + */ + private void claim_interface(long usb_dev_handle, int configuration, + int interface_, int altinterface) throws USBException { + if (LibusbJava.usb_set_configuration(usb_dev_handle, configuration) < 0) { + usbDevHandle = 0; + throw new USBException("LibusbJava.usb_set_configuration: " + + LibusbJava.usb_strerror()); + } + if (LibusbJava.usb_claim_interface(usb_dev_handle, interface_) < 0) { + usbDevHandle = 0; + throw new USBException("LibusbJava.usb_claim_interface: " + + LibusbJava.usb_strerror()); + } + if (altinterface >= 0) { + if (LibusbJava.usb_set_altinterface(usb_dev_handle, altinterface) < 0) { + try { + release_interface(usb_dev_handle, interface_); + } catch (USBException e) { + // ignore + } + usbDevHandle = 0; + throw new USBException("LibusbJava.usb_set_altinterface: " + + LibusbJava.usb_strerror()); + } + } + logger.info("interface claimed"); + } + + /** + * Release a previously claimed interface.
+ * + * @param dev_handle + * the handle of the device (MUST BE VALID) + * @param interface_ + * the interface to claim + * @throws USBException + * throws an USBException if the action fails + */ + private void release_interface(long dev_handle, int interface_) + throws USBException { + if (LibusbJava.usb_release_interface(dev_handle, interface_) < 0) { + usbDevHandle = 0; + throw new USBException("LibusbJava.usb_release_interface: " + + LibusbJava.usb_strerror()); + } + logger.info("interface released"); + } + + /** + * Returns the product ID of the device.
+ * + * @return the product ID of the device. + */ + public int getIdProduct() { + return idProduct; + } + + /** + * Returns the vendor ID of the device.
+ * + * @return the vendor ID of the device. + */ + public int getIdVendor() { + return idVendor; + } + + /** + * Returns the alternative interface.
+ * This value is only valid after opening the device. + * + * @return the alternative interface. This value is only valid after opening + * the device. + */ + public int getAltinterface() { + return dev_altinterface; + } + + /** + * Returns the current configuration used.
+ * This value is only valid after opening the device. + * + * @return the current configuration used. This value is only valid after + * opening the device. + */ + public int getConfiguration() { + return dev_configuration; + } + + /** + * Returns the current interface.
+ * This value is only valid after opening the device. + * + * @return the current interface. This value is only valid after opening the + * device. + */ + public int getInterface() { + return dev_interface; + } + + /** + * Returns the maximum packet size in bytes which is allowed to be + * transmitted at once.
+ * The value is determined by reading the endpoint descriptor(s) when + * opening the device. It is invalid before the device is opened! Note that + * if some endpoints use different packet sizes the maximum packet size is + * return. This value may be used to determine if a device is opened in + * fullspeed or highspeed mode. + * + * @return the maximum packet size + */ + public int getMaxPacketSize() { + return maxPacketSize; + } + + /** + * Check if the device is open.
+ * This checks only for a valid device handle. It doesn't check if the + * device is still attached or working. + * + * @return true if the device is open + */ + public boolean isOpen() { + return usbDevHandle != 0; + } + + /** + * If enabled, the device is reset when first opened.
+ * This will only happen once. When the application is started, the device + * state is unknown. If the device is not reset, read or write may result in + * a {@link USBTimeoutException}.
+ *
+ * This feature is disabled by default. + * + * @param enable + * true if the device should be reset when first opened + * @param timeout + * the timeout between the reset and the reopening + */ + public void setResetOnFirstOpen(boolean enable, int timeout) { + resetOnFirstOpen = enable; + resetTimeout = timeout; + } + + /** + * 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, String)}. Use + * {@link Usb_Device#getFilename()} to read the filename of a device. + * + * @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. + * + * @return the Usb_Device instance associated with this 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(); + } + +} diff --git a/src/main/java/ch/ntb/usb.r273/LibusbJava.java b/src/main/java/ch/ntb/usb.r273/LibusbJava.java new file mode 100644 index 0000000..c976af2 --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/LibusbJava.java @@ -0,0 +1,378 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +/** + * This class represents the Java Native Interface to the shared library which + * is (with some exceptions) a one-to-one representation of the libusb API.
+ *
+ *

Project Description

+ * Java libusb is a Java wrapper for the libusb and libusb-win32 USB library. + * + * libusb aim is to create a + * library for use by user level applications to access USB devices regardless + * of OS.
+ * Libusb-win32 is a port of + * the USB library libusb to the + * Windows operating systems. The library allows user space applications to + * access any USB device on Windows in a generic way without writing any line of + * kernel driver code.
+ *
+ * The API description of this class has been copied from the libusb documentation + * and adapted where neccessary.
+ * + */ +public class LibusbJava { + + /** + * System error codes.
+ * This list is not complete! For more error codes see the file 'errorno.h' + * on your system. + */ + public static int ERROR_SUCCESS, ERROR_BAD_FILE_DESCRIPTOR, + ERROR_NO_SUCH_DEVICE_OR_ADDRESS, ERROR_BUSY, + ERROR_INVALID_PARAMETER, ERROR_TIMEDOUT, ERROR_IO_ERROR, + ERROR_NOT_ENOUGH_MEMORY;; + + /** + * Sets the debugging level of libusb.
+ * + * The range is from 0 to 255, where 0 disables debug output and 255 enables + * all output. On application start, debugging is disabled (0). + * + * @param level + * 0 to 255 + */ + public static native void usb_set_debug(int level); + + // Core + /** + * Just like the name implies, usb_init sets up some internal + * structures. usb_init must be called before any other + * libusb functions. + */ + public static native void usb_init(); + + /** + * usb_find_busses will find all of the busses on the system. + * + * @return the number of changes since previous call to this function (total + * of new busses and busses removed). + */ + public static native int usb_find_busses(); + + /** + * usb_find_devices will find all of the devices on each bus. + * This should be called after usb_find_busses. + * + * @return the number of changes since the previous call to this function + * (total of new device and devices removed). + */ + public static native int usb_find_devices(); + + /** + * usb_get_busses returns a tree of descriptor objects.
+ * The tree represents the bus structure with devices, configurations, + * interfaces and endpoints. Note that this is only a copy. To refresh the + * information, usb_get_busses() must be called again.
+ * The name of the objects contained in the tree is starting with + * Usb_. + * + * @return the structure of all busses and devices. Note: The + * java objects are copies of the C structs. + */ + public static native Usb_Bus usb_get_busses(); + + // Device Operations + /** + * usb_open is to be used to open up a device for use. + * usb_open must be called before attempting to perform any + * operations to the device. + * + * @param dev + * The device to open. + * @return a handle used in future communication with the device. 0 if an + * error has occurred. + */ + public static native long usb_open(Usb_Device dev); + + /** + * usb_close closes a device opened with + * usb_open. + * + * @param dev_handle + * The handle to the device. + * @return 0 on success or < 0 on error. + */ + public static native int usb_close(long dev_handle); + + /** + * Sets the active configuration of a device + * + * @param dev_handle + * The handle to the device. + * @param configuration + * The value as specified in the descriptor field + * bConfigurationValue. + * @return 0 on success or < 0 on error. + */ + public static native int usb_set_configuration(long dev_handle, + int configuration); + + /** + * Sets the active alternate setting of the current interface + * + * @param dev_handle + * The handle to the device. + * @param alternate + * The value as specified in the descriptor field + * bAlternateSetting. + * @return 0 on success or < 0 on error. + */ + public static native int usb_set_altinterface(long dev_handle, int alternate); + + /** + * Clears any halt status on an endpoint. + * + * @param dev_handle + * The handle to the device. + * @param ep + * The value specified in the descriptor field bEndpointAddress. + * @return 0 on success or < 0 on error. + */ + public static native int usb_clear_halt(long dev_handle, int ep); + + /** + * Resets a device by sending a RESET down the port it is connected to.
+ *
+ * Causes re-enumeration: After calling usb_reset, + * the device will need to re-enumerate and thusly, requires you to find the + * new device and open a new handle. The handle used to call + * usb_reset will no longer work. + * + * @param dev_handle + * The handle to the device. + * @return 0 on success or < 0 on error. + */ + public static native int usb_reset(long dev_handle); + + /** + * Claim an interface of a device.
+ *
+ * Must be called!: usb_claim_interface must be + * called before you perform any operations related to this interface (like + * usb_set_altinterface, usb_bulk_write, etc). + * + * @param dev_handle + * The handle to the device. + * @param interface_ + * The value as specified in the descriptor field + * bInterfaceNumber. + * @return 0 on success or < 0 on error. + */ + public static native int usb_claim_interface(long dev_handle, int interface_); + + /** + * Releases a previously claimed interface + * + * @param dev_handle + * The handle to the device. + * @param interface_ + * The value as specified in the descriptor field + * bInterfaceNumber. + * @return 0 on success or < 0 on error. + */ + public static native int usb_release_interface(long dev_handle, + int interface_); + + // Control Transfers + /** + * Performs a control request to the default control pipe on a device. The + * parameters mirror the types of the same name in the USB specification. + * + * @param dev_handle + * The handle to the device. + * @param requesttype + * @param request + * @param value + * @param index + * @param bytes + * @param size + * @param timeout + * @return the number of bytes written/read or < 0 on error. + */ + public static native int usb_control_msg(long dev_handle, int requesttype, + int request, int value, int index, byte[] bytes, int size, + int timeout); + + /** + * Retrieves the string descriptor specified by index and langid from a + * device. + * + * @param dev_handle + * The handle to the device. + * @param index + * @param langid + * @return the descriptor String or null + */ + public static native String usb_get_string(long dev_handle, int index, + int langid); + + /** + * usb_get_string_simple is a wrapper around + * usb_get_string that retrieves the string description + * specified by index in the first language for the descriptor. + * + * @param dev_handle + * The handle to the device. + * @param index + * @return the descriptor String or null + */ + public static native String usb_get_string_simple(long dev_handle, int index); + + /** + * Retrieves a descriptor from the device identified by the type and index + * of the descriptor from the default control pipe.
+ *
+ * See {@link #usb_get_descriptor_by_endpoint(long, int, byte, byte, int)} + * for a function that allows the control endpoint to be specified. + * + * @param dev_handle + * The handle to the device. + * @param type + * @param index + * @param size + * number of charactes which will be retrieved (the length of the + * resulting String) + * @return the descriptor String or null + */ + public static native String usb_get_descriptor(long dev_handle, byte type, + byte index, int size); + + /** + * Retrieves a descriptor from the device identified by the type and index + * of the descriptor from the control pipe identified by ep. + * + * @param dev_handle + * The handle to the device. + * @param ep + * @param type + * @param index + * @param size + * number of charactes which will be retrieved (the length of the + * resulting String) + * @return the descriptor String or null + */ + public static native String usb_get_descriptor_by_endpoint(long dev_handle, + int ep, byte type, byte index, int size); + + // Bulk Transfers + /** + * Performs a bulk write request to the endpoint specified by ep. + * + * @param dev_handle + * The handle to the device. + * @param ep + * @param bytes + * @param size + * @param timeout + * @return the number of bytes written on success or < 0 on error. + */ + public static native int usb_bulk_write(long dev_handle, int ep, + byte[] bytes, int size, int timeout); + + /** + * Performs a bulk read request to the endpoint specified by ep. + * + * @param dev_handle + * The handle to the device. + * @param ep + * @param bytes + * @param size + * @param timeout + * @return the number of bytes read on success or < 0 on error. + */ + public static native int usb_bulk_read(long dev_handle, int ep, + byte[] bytes, int size, int timeout); + + // Interrupt Transfers + /** + * Performs an interrupt write request to the endpoint specified by ep. + * + * @param dev_handle + * The handle to the device. + * @param ep + * @param bytes + * @param size + * @param timeout + * @return the number of bytes written on success or < 0 on error. + */ + public static native int usb_interrupt_write(long dev_handle, int ep, + byte[] bytes, int size, int timeout); + + /** + * Performs a interrupt read request to the endpoint specified by ep. + * + * @param dev_handle + * The handle to the device. + * @param ep + * @param bytes + * @param size + * @param timeout + * @return the number of bytes read on success or < 0 on error. + */ + public static native int usb_interrupt_read(long dev_handle, int ep, + byte[] bytes, int size, int timeout); + + /** + * Returns the error string after an error occured. + * + * @return the last error sring. + */ + public static native String usb_strerror(); + + /** **************************************************************** */ + + /** + * Maps the Java error code to the system error code.
+ *
+ * Note that not all error codes are be mapped by this method. For more + * error codes see the file 'errno.h' on your system.
+ *
+ * 1: EBADF: Bad file descriptor.
+ * 2: ENXIO: No such device or address.
+ * 3: EBUSY: Device or resource busy.
+ * 4: EINVAL: Invalid argument.
+ * 5: ETIMEDOUT: Connection timed out.
+ * 6: EIO: I/O error.
+ * 7: ENOMEM: Not enough memory.
+ * + * + * @return the system error code or 100000 if no mapping has been found. + */ + private static native int usb_error_no(int value); + + static { + String os = System.getProperty("os.name"); + if (os.contains("Windows")) { + System.loadLibrary("LibusbJava"); + } else { + System.loadLibrary("usbJava"); + } + // define the error codes + ERROR_SUCCESS = 0; + ERROR_BAD_FILE_DESCRIPTOR = -usb_error_no(1); + ERROR_NO_SUCH_DEVICE_OR_ADDRESS = -usb_error_no(2); + ERROR_BUSY = -usb_error_no(3); + ERROR_INVALID_PARAMETER = -usb_error_no(4); + ERROR_TIMEDOUT = -usb_error_no(5); + ERROR_IO_ERROR = -usb_error_no(6); + ERROR_NOT_ENOUGH_MEMORY = -usb_error_no(7); + } +} \ No newline at end of file diff --git a/src/main/java/ch/ntb/usb.r273/USB.java b/src/main/java/ch/ntb/usb.r273/USB.java new file mode 100644 index 0000000..f372ef3 --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/USB.java @@ -0,0 +1,318 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.logging.Logger; + +import ch.ntb.usb.logger.LogUtil; + +/** + * This class manages all USB devices and defines some USB specific constants.
+ * + */ +public class USB { + + // Standard requests (USB spec 9.4) + /** + * This request returns status for the specified recipient (USB spec 9.4.5). + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_GET_STATUS = 0x00; + /** + * This request is used to clear or disable a specific feature (USB spec + * 9.4.1). + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_CLEAR_FEATURE = 0x01; + // 0x02 is reserved + /** + * This request is used to set or enable a specific feature (USB spec + * 9.4.9). + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_SET_FEATURE = 0x03; + // 0x04 is reserved + /** + * This request sets the device address for all future device accesses (USB + * spec 9.4.6). + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_SET_ADDRESS = 0x05; + /** + * This request returns the specified descriptor if the descriptor exists + * (USB spec 9.4.3). + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_GET_DESCRIPTOR = 0x06; + /** + * This request is optional and may be used to update existing descriptors + * or new descriptors may be added (USB spec 9.4.8). + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_SET_DESCRIPTOR = 0x07; + /** + * This request returns the current device configuration value (USB spec + * 9.4.2). + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_GET_CONFIGURATION = 0x08; + /** + * This request sets the device configuration (USB spec 9.4.7). + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_SET_CONFIGURATION = 0x09; + /** + * This request returns the selected alternate setting for the specified + * interface (USB spec 9.4.4). + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_GET_INTERFACE = 0x0A; + /** + * This request allows the host to select an alternate setting for the + * specified interface (USB spec 9.4.10). + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_SET_INTERFACE = 0x0B; + /** + * This request is used to set and then report an endpoint’s synchronization + * frame (USB spec 9.4.11). + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_SYNCH_FRAME = 0x0C; + + // data transfer direction (USB spec 9.3) + /** + * Identifies the direction of data transfer in the second phase of the + * control transfer.
+ * The state of the Direction bit is ignored if the wLength field is zero, + * signifying there is no Data stage.
+ * Specifies bit 7 of bmRequestType. + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_TYPE_DIR_HOST_TO_DEVICE = (0x00 << 7), + REQ_TYPE_DIR_DEVICE_TO_HOST = (0x01 << 7); + + // request types (USB spec 9.3) + /** + * Specifies the type of the request.
+ * Specifies bits 6..5 of bmRequestType. + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_TYPE_TYPE_STANDARD = (0x00 << 5), + REQ_TYPE_TYPE_CLASS = (0x01 << 5), + REQ_TYPE_TYPE_VENDOR = (0x02 << 5), + REQ_TYPE_TYPE_RESERVED = (0x03 << 5); + + // request recipient (USB spec 9.3) + /** + * Specifies the intended recipient of the request.
+ * Requests may be directed to the device, an interface on the device, or a + * specific endpoint on a device. When an interface or endpoint is + * specified, the wIndex field identifies the interface or endpoint.
+ * Specifies bits 4..0 of bmRequestType. + * + * @see ch.ntb.usb.Device#controlMsg(int, int, int, int, byte[], int, int, + * boolean) + */ + public static final int REQ_TYPE_RECIP_DEVICE = 0x00, + REQ_TYPE_RECIP_INTERFACE = 0x01, REQ_TYPE_RECIP_ENDPOINT = 0x02, + REQ_TYPE_RECIP_OTHER = 0x03; + + /** + * The maximum packet size of a bulk transfer when operating in highspeed + * (480 MB/s) mode. + */ + public static int HIGHSPEED_MAX_BULK_PACKET_SIZE = 512; + + /** + * The maximum packet size of a bulk transfer when operating in fullspeed + * (12 MB/s) mode. + */ + public static int FULLSPEED_MAX_BULK_PACKET_SIZE = 64; + + private static final Logger logger = LogUtil.getLogger("ch.ntb.usb"); + + private static LinkedList devices = new LinkedList(); + + private static boolean initUSBDone = false; + + /** + * Create a new device an register it in a device list. If the device is + * already registered, a reference to it will be returned.
+ * 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.
+ * see {@link Usb_Bus#getDirname()} + * @param filename + * optional filename which can be used to distinguish multiple + * devices with the same vendor and product id.
+ * see {@link Usb_Device#getFilename()} + * @return a newly created device or an already registered device + */ + public static Device getDevice(short idVendor, short idProduct, + String busName, String filename) { + + // check if this device is already registered + Device dev = getRegisteredDevice(idVendor, idProduct, busName, filename); + if (dev != null) { + logger.info("return already registered device: " + dev); + return dev; + } + dev = new Device(idVendor, idProduct, busName, filename); + logger.info("create new device: " + dev); + devices.add(dev); + return dev; + } + + /** + * See {@link #getDevice(short, short, String, String)}. The parameter + * filename and busNameis 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, 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.
+ * 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.
+ * 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. see + * {@link Usb_Device#getFilename()} + * + * @return the device or null + */ + private static Device getRegisteredDevice(short idVendor, short idProduct, + String busName, String filename) { + for (Iterator iter = devices.iterator(); iter.hasNext();) { + Device dev = iter.next(); + // 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; + } + } + return null; + } + + /** + * Returns the root {@link Usb_Bus} element. + * + * @return the root {@link Usb_Bus} element + * @throws USBException + */ + public static Usb_Bus getBus() throws USBException { + if (!initUSBDone) { + init(); + } + LibusbJava.usb_find_busses(); + LibusbJava.usb_find_devices(); + + Usb_Bus bus = LibusbJava.usb_get_busses(); + if (bus == null) { + throw new USBException("LibusbJava.usb_get_busses(): " + + LibusbJava.usb_strerror()); + } + return bus; + } + + /** + * 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, String)}. + */ + public static void init() { + LibusbJava.usb_init(); + initUSBDone = true; + } +} diff --git a/src/main/java/ch/ntb/usb.r273/USBException.java b/src/main/java/ch/ntb/usb.r273/USBException.java new file mode 100644 index 0000000..21f1f5c --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/USBException.java @@ -0,0 +1,23 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +import java.io.IOException; + +public class USBException extends IOException { + + public USBException(String string) { + super(string); + } + + /** + * + */ + private static final long serialVersionUID = 1690857437804284710L; + +} diff --git a/src/main/java/ch/ntb/usb.r273/USBTimeoutException.java b/src/main/java/ch/ntb/usb.r273/USBTimeoutException.java new file mode 100644 index 0000000..4b8c3c6 --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/USBTimeoutException.java @@ -0,0 +1,21 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +public class USBTimeoutException extends USBException { + + public USBTimeoutException(String string) { + super(string); + } + + /** + * + */ + private static final long serialVersionUID = -1065328371159778249L; + +} diff --git a/src/main/java/ch/ntb/usb.r273/Usb_Bus.java b/src/main/java/ch/ntb/usb.r273/Usb_Bus.java new file mode 100644 index 0000000..a7c59fc --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/Usb_Bus.java @@ -0,0 +1,86 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +/** + * Represents an USB bus.
+ * This is the root class for the representation of the libusb USB structure. + * Zero or more devices may be connected to an USB bus. + * + */ +public class Usb_Bus { + + private Usb_Bus next, prev; + + private String dirname; + + private Usb_Device devices; + + private long location; + + private Usb_Device root_dev; + + /** + * Get the first device ojects of the devices linked list.
+ * + * @return the first device ojects of the devices linked list or null + */ + public Usb_Device getDevices() { + return devices; + } + + /** + * Returns the systems String representation of the bus.
+ * + * @return the systems String representation of the bus + */ + public String getDirname() { + return dirname; + } + + /** + * Returns the next bus object.
+ * + * @return Returns the next bus object or null + */ + public Usb_Bus getNext() { + return next; + } + + /** + * Returns the previous bus object.
+ * + * @return Returns the previous bus object or null + */ + public Usb_Bus getPrev() { + return prev; + } + + /** + * Get the root device of this bus.
+ * + * @return the root device oject or null + */ + public Usb_Device getRootDev() { + return root_dev; + } + + /** + * Returns the location in the USB bus linked list.
+ * + * @return the location in the USB bus linked list + */ + public long getLocation() { + return location; + } + + @Override + public String toString() { + return "Usb_Bus " + dirname; + } +} \ No newline at end of file diff --git a/src/main/java/ch/ntb/usb.r273/Usb_Config_Descriptor.java b/src/main/java/ch/ntb/usb.r273/Usb_Config_Descriptor.java new file mode 100644 index 0000000..9bf6ff5 --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/Usb_Config_Descriptor.java @@ -0,0 +1,139 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +/** + * Represents the descriptor of a USB configuration.
+ * A USB device can have several different configuration.
+ *
+ * The length of the configuration descriptor is + * {@link ch.ntb.usb.Usb_Descriptor#USB_DT_CONFIG_SIZE} and the type is + * {@link ch.ntb.usb.Usb_Descriptor#USB_DT_CONFIG}. + * + */ +public class Usb_Config_Descriptor extends Usb_Descriptor { + + /** + * Maximum number of configurations per device + */ + public static final int USB_MAXCONFIG = 8; + + private short wTotalLength; + + private byte bNumInterfaces; + + private byte bConfigurationValue; + + private byte iConfiguration; + + private byte bmAttributes; + + private byte MaxPower; + + private Usb_Interface[] interface_; + + private byte[] extra; /* Extra descriptors */ + + private int extralen; + + /** + * Returns the value to use as an argument to select this configuration ({@link LibusbJava#usb_set_configuration(long, int)}). + * + * @return the value to use as an argument to select this configuration + */ + public byte getBConfigurationValue() { + return bConfigurationValue; + } + + /** + * Returns the power parameters for this configuration.
+ *
+ * Bit 7: Reserved, set to 1 (USB 1.0 Bus Powered)
+ * Bit 6: Self Powered
+ * Bit 5: Remote Wakeup
+ * Bit 4..0: Reserved, set to 0 + * + * @return the power parameters for this configuration + */ + public byte getBmAttributes() { + return bmAttributes; + } + + /** + * Returns the number of interfaces.
+ * + * @return the number of interfaces + */ + public byte getBNumInterfaces() { + return bNumInterfaces; + } + + /** + * Returns the data of extra descriptor(s) if available.
+ * + * @return null or a byte array with the extra descriptor data + */ + public byte[] getExtra() { + return extra; + } + + /** + * Returns the number of bytes of the extra descriptor.
+ * + * @return the number of bytes of the extra descriptor + */ + public int getExtralen() { + return extralen; + } + + /** + * Returns the index of the String descriptor describing this configuration.
+ * + * @return the index of the String descriptor + */ + public byte getIConfiguration() { + return iConfiguration; + } + + /** + * Returns the USB interface descriptors.
+ * + * @return the USB interface descriptors + */ + public Usb_Interface[] getInterface() { + return interface_; + } + + /** + * Returns the maximum power consumption in 2mA units.
+ * + * @return the maximum power consumption in 2mA units + */ + public byte getMaxPower() { + return MaxPower; + } + + /** + * Returns the total length in bytes of all descriptors.
+ * When the configuration descriptor is read, it returns the entire + * configuration hierarchy which includes all related interface and endpoint + * descriptors. The wTotalLength field reflects the number of + * bytes in the hierarchy. + * + * @return the total length in bytes of all descriptors + */ + public short getWTotalLength() { + return wTotalLength; + } + + @Override + public String toString() { + return "Usb_Config_Descriptor bNumInterfaces: 0x" + + Integer.toHexString(bNumInterfaces); + } +} \ No newline at end of file diff --git a/src/main/java/ch/ntb/usb.r273/Usb_Descriptor.java b/src/main/java/ch/ntb/usb.r273/Usb_Descriptor.java new file mode 100644 index 0000000..6aee245 --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/Usb_Descriptor.java @@ -0,0 +1,59 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +/** + * Common USB descriptor values.
+ * + */ +public class Usb_Descriptor { + + /** + * Descriptor types ({@link #bDescriptorType}). + */ + public static final int USB_DT_DEVICE = 0x01, USB_DT_CONFIG = 0x02, + USB_DT_STRING = 0x03, USB_DT_INTERFACE = 0x04, + USB_DT_ENDPOINT = 0x05; + + /** + * Descriptor types ({@link #bDescriptorType}). + */ + public static final int USB_DT_HID = 0x21, USB_DT_REPORT = 0x22, + USB_DT_PHYSICAL = 0x23, USB_DT_HUB = 0x29; + + /** + * Descriptor sizes per descriptor type ({@link #bLength}). + */ + public static final int USB_DT_DEVICE_SIZE = 18, USB_DT_CONFIG_SIZE = 9, + USB_DT_INTERFACE_SIZE = 9, USB_DT_ENDPOINT_SIZE = 7, + USB_DT_ENDPOINT_AUDIO_SIZE = 9 /* Audio extension */, + USB_DT_HUB_NONVAR_SIZE = 7; + + private byte bLength; + + private byte bDescriptorType; + + /** + * Get the type of this descriptor.
+ * + * @return the type of this descriptor + */ + public byte getBDescriptorType() { + return bDescriptorType; + } + + /** + * Get the size of this descriptor in bytes.
+ * + * @return the size of this descriptor in bytes + */ + public byte getBLength() { + return bLength; + } + +} diff --git a/src/main/java/ch/ntb/usb.r273/Usb_Device.java b/src/main/java/ch/ntb/usb.r273/Usb_Device.java new file mode 100644 index 0000000..5cb314a --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/Usb_Device.java @@ -0,0 +1,125 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +/** + * Represents an USB device.
+ * An USB device has one device descriptor and it may have multiple + * configuration descriptors. + * + */ +public class Usb_Device { + + private Usb_Device next, prev; + + private String filename; + + private Usb_Bus bus; + + private Usb_Device_Descriptor descriptor; + + private Usb_Config_Descriptor[] config; + + private byte devnum; + + private byte num_children; + + private Usb_Device children; + + /** + * 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. + */ + public long devStructAddr; + + /** + * Returns the reference to the bus to which this device is connected.
+ * + * @return the reference to the bus to which this device is connected + */ + public Usb_Bus getBus() { + return bus; + } + + /** + * Returns a reference to the first child.
+ * + * @return a reference to the first child + */ + public Usb_Device getChildren() { + return children; + } + + /** + * Returns the USB config descriptors.
+ * + * @return the USB config descriptors + */ + public Usb_Config_Descriptor[] getConfig() { + return config; + } + + /** + * Returns the USB device descriptor.
+ * + * @return the USB device descriptor + */ + public Usb_Device_Descriptor getDescriptor() { + return descriptor; + } + + /** + * Returns the number assigned to this device.
+ * + * @return the number assigned to this device + */ + public byte getDevnum() { + return devnum; + } + + /** + * Returns the systems String representation.
+ * + * @return the systems String representation + */ + public String getFilename() { + return filename; + } + + /** + * Returns the pointer to the next device.
+ * + * @return the pointer to the next device or null + */ + public Usb_Device getNext() { + return next; + } + + /** + * Returns the number of children of this device.
+ * + * @return the number of children of this device + */ + public byte getNumChildren() { + return num_children; + } + + /** + * Returns the pointer to the previous device.
+ * + * @return the pointer to the previous device or null + */ + public Usb_Device getPrev() { + return prev; + } + + @Override + public String toString() { + return "Usb_Device " + filename; + } +} \ No newline at end of file diff --git a/src/main/java/ch/ntb/usb.r273/Usb_Device_Descriptor.java b/src/main/java/ch/ntb/usb.r273/Usb_Device_Descriptor.java new file mode 100644 index 0000000..5cf30e9 --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/Usb_Device_Descriptor.java @@ -0,0 +1,190 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +/** + * Represents the descriptor of a USB device.
+ * A USB device can only have one device descriptor. It specifies some basic, + * yet important information about the device.
+ *
+ * The length of the device descriptor is + * {@link ch.ntb.usb.Usb_Descriptor#USB_DT_DEVICE_SIZE} and the type is + * {@link ch.ntb.usb.Usb_Descriptor#USB_DT_DEVICE}. + * + */ +public class Usb_Device_Descriptor extends Usb_Descriptor { + /** + * Device and/or interface class codes. + */ + public static final int USB_CLASS_PER_INTERFACE = 0, USB_CLASS_AUDIO = 1, + USB_CLASS_COMM = 2, USB_CLASS_HID = 3, USB_CLASS_PRINTER = 7, + USB_CLASS_MASS_STORAGE = 8, USB_CLASS_HUB = 9, USB_CLASS_DATA = 10, + USB_CLASS_VENDOR_SPEC = 0xff; + + private short bcdUSB; + + private byte bDeviceClass; + + private byte bDeviceSubClass; + + private byte bDeviceProtocol; + + private byte bMaxPacketSize0; + + private short idVendor; + + private short idProduct; + + private short bcdDevice; + + private byte iManufacturer; + + private byte iProduct; + + private byte iSerialNumber; + + private byte bNumConfigurations; + + /** + * Returns the device release number.
+ * Assigned by the manufacturer of the device. + * + * @return the device release number + */ + public short getBcdDevice() { + return bcdDevice; + } + + /** + * Returns the USB specification number to which the device complies to.
+ * This field reports the highest version of USB the device supports. The + * value is in binary coded decimal with a format of 0xJJMN where JJ is the + * major version number, M is the minor version number and N is the sub + * minor version number.
+ * Examples: USB 2.0 is reported as 0x0200, USB 1.1 as 0x0110 and USB 1.0 as + * 0x100 + * + * @return the USB specification number to which the device complies to + */ + public short getBcdUSB() { + return bcdUSB; + } + + /** + * Returns the class code (Assigned by www.usb.org)
+ * If equal to zero, each interface specifies it's own class code. If equal + * to 0xFF, the class code is vendor specified. Otherwise the field is a + * valid class code. + * + * @return the class code + */ + public byte getBDeviceClass() { + return bDeviceClass; + } + + /** + * Returns the protocol code (Assigned by www.usb.org)
+ * + * @return the protocol code + */ + public byte getBDeviceProtocol() { + return bDeviceProtocol; + } + + /** + * Returns the subclass code (Assigned by www.usb.org)
+ * + * @return the subclass code + */ + public byte getBDeviceSubClass() { + return bDeviceSubClass; + } + + /** + * Returns the maximum packet size for endpoint zero.
+ * Valid sizes are 8, 16, 32, 64. + * + * @return the maximum packet size for endpoint zero + */ + public byte getBMaxPacketSize0() { + return bMaxPacketSize0; + } + + /** + * Returns the number of possible configurations supported at its current + * speed.
+ * + * @return the number of possible configurations supported at its current + * speed + */ + public byte getBNumConfigurations() { + return bNumConfigurations; + } + + /** + * Returns the product ID (Assigned by www.usb.org)
+ * + * @return the product ID + */ + public short getIdProduct() { + return idProduct; + } + + /** + * Returns the Vendor ID (Assigned by www.usb.org)
+ * + * @return the Vendor ID + */ + public short getIdVendor() { + return idVendor; + } + + /** + * Returns the index of the manufacturer string descriptor.
+ * If this value is 0, no string descriptor is used. + * + * @return the index of the manufacturer string descriptor + */ + public byte getIManufacturer() { + return iManufacturer; + } + + /** + * Returns the index of the product string descriptor.
+ * If this value is 0, no string descriptor is used. + * + * @return the index of the product string descriptor + */ + public byte getIProduct() { + return iProduct; + } + + /** + * Returns the index of serial number string descriptor.
+ * If this value is 0, no string descriptor is used. + * + * @return the index of serial number string descriptor + */ + public byte getISerialNumber() { + return iSerialNumber; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("Usb_Device_Descriptor idVendor: 0x" + + Integer.toHexString(idVendor & 0xFFFF) + ", idProduct: 0x" + + Integer.toHexString(idProduct & 0xFFFF)); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/ch/ntb/usb.r273/Usb_Endpoint_Descriptor.java b/src/main/java/ch/ntb/usb.r273/Usb_Endpoint_Descriptor.java new file mode 100644 index 0000000..00e4bbc --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/Usb_Endpoint_Descriptor.java @@ -0,0 +1,158 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +/** + * Represents the descriptor of an USB endpoint.
+ * Endpoint descriptors are used to describe endpoints other than endpoint zero. + * Endpoint zero is always assumed to be a control endpoint and is configured + * before any descriptors are even requested. The host will use the information + * returned from these descriptors to determine the bandwidth requirements of + * the bus.
+ *
+ * The length of the configuration descriptor is + * {@link ch.ntb.usb.Usb_Descriptor#USB_DT_ENDPOINT_SIZE} and the type is + * {@link ch.ntb.usb.Usb_Descriptor#USB_DT_ENDPOINT}. + * + */ +public class Usb_Endpoint_Descriptor extends Usb_Descriptor { + + /** + * Maximum number of endpoints + */ + public static final int USB_MAXENDPOINTS = 32; + + /** + * Endpoint address mask (in bEndpointAddress). + */ + public static final int USB_ENDPOINT_ADDRESS_MASK = 0x0f, + USB_ENDPOINT_DIR_MASK = 0x80; + + /** + * Endpoint type mask (in bmAttributes). + */ + public static final int USB_ENDPOINT_TYPE_MASK = 0x03; + + /** + * Possible endpoint types (in bmAttributes). + */ + public static final int USB_ENDPOINT_TYPE_CONTROL = 0, + USB_ENDPOINT_TYPE_ISOCHRONOUS = 1, USB_ENDPOINT_TYPE_BULK = 2, + USB_ENDPOINT_TYPE_INTERRUPT = 3; + + private byte bEndpointAddress; + + private byte bmAttributes; + + private short wMaxPacketSize; + + private byte bInterval; + + private byte bRefresh; + + private byte bSynchAddress; + + private byte[] extra; /* Extra descriptors */ + + private int extralen; + + /** + * Returns the endpoint address.
+ *
+ * Bits 3..0: Endpoint number
+ * Bits 6..4: Reserved. Set to zero
+ * 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.
+ * + * @return the endpoint address + */ + public byte getBEndpointAddress() { + return bEndpointAddress; + } + + /** + * Returns the intervall for polling endpoint data transfers.
+ * Value in frame counts. Ignored for Bulk & Control eEndpoints. Isochronous + * endpoints must equal 1 and field may range from 1 to 255 for interrupt + * endpoints. + * + * @return the intervall for polling endpoint data transfers + */ + public byte getBInterval() { + return bInterval; + } + + /** + * Returns the attributes of this endpoint.
+ * + * Bits 1..0: Transfer Type (see USB_ENDPOINT_TYPE_XXX).
+ * Bits 7..2: Reserved.
+ * + *
+	 * 	If isochronous endpoint:
+	 * 		Bits 3..2: Synchronisation type
+	 *  		00 = No synchronisation
+	 * 			01 = Asynchronous
+	 *          10 = Adaptive
+	 *          11 = Synchronous
+	 *     	Bits 5..4: Usage Type
+	 *      	00 = Data endpoint
+	 *      	01 = Feedback endpoint
+	 *      	10 = Explicit feedback data endpoint
+	 *      	11 = Reserved
+	 * 
+ * + * @return the attributes of this endpoint + */ + public byte getBmAttributes() { + return bmAttributes; + } + + public byte getBRefresh() { + return bRefresh; + } + + public byte getBSynchAddress() { + return bSynchAddress; + } + + /** + * Returns the data of extra descriptor(s) if available.
+ * + * @return null or a byte array with the extra descriptor data + */ + public byte[] getExtra() { + return extra; + } + + /** + * Returns the number of bytes of the extra descriptor.
+ * + * @return the number of bytes of the extra descriptor + */ + public int getExtralen() { + return extralen; + } + + /** + * Returns the maximum packet size of this endpoint is capable of sending or + * receiving.
+ * + * @return the maximum packet size + */ + public short getWMaxPacketSize() { + return wMaxPacketSize; + } + + @Override + public String toString() { + return "Usb_Endpoint_Descriptor bEndpointAddress: 0x" + + Integer.toHexString(bEndpointAddress & 0xFF); + } +} diff --git a/src/main/java/ch/ntb/usb.r273/Usb_Interface.java b/src/main/java/ch/ntb/usb.r273/Usb_Interface.java new file mode 100644 index 0000000..a8bb6bc --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/Usb_Interface.java @@ -0,0 +1,50 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +/** + * Represents an USB interface.
+ * An interface is a group of alternate settings of a configuration.
+ * + */ +public class Usb_Interface { + + /** + * Maximal number of alternate settings + */ + public static final int USB_MAXALTSETTING = 128; /* Hard limit */ + + private Usb_Interface_Descriptor[] altsetting; + + private int num_altsetting; + + @Override + public String toString() { + return "Usb_Interface num_altsetting: 0x" + + Integer.toHexString(num_altsetting); + } + + /** + * Retuns an array of interface descriptors.
+ * + * @return an array of interface descriptors + */ + public Usb_Interface_Descriptor[] getAltsetting() { + return altsetting; + } + + /** + * Returns the number of alternate settings.
+ * + * @return the number of alternate settings + */ + public int getNumAltsetting() { + return num_altsetting; + } + +} diff --git a/src/main/java/ch/ntb/usb.r273/Usb_Interface_Descriptor.java b/src/main/java/ch/ntb/usb.r273/Usb_Interface_Descriptor.java new file mode 100644 index 0000000..a36d3ed --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/Usb_Interface_Descriptor.java @@ -0,0 +1,145 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +/** + * Represents the descriptor of a USB interface.
+ * The interface descriptor could be seen as a header or grouping of the + * endpoints into a functional group performing a single feature of the device.
+ *
+ * The length of the interface descriptor is + * {@link ch.ntb.usb.Usb_Descriptor#USB_DT_INTERFACE_SIZE} and the type is + * {@link ch.ntb.usb.Usb_Descriptor#USB_DT_INTERFACE}. + * + */ +public class Usb_Interface_Descriptor extends Usb_Descriptor { + + /** + * Maximum number of interfaces + */ + public static final int USB_MAXINTERFACES = 32; + + private byte bInterfaceNumber; + + private byte bAlternateSetting; + + private byte bNumEndpoints; + + private byte bInterfaceClass; + + private byte bInterfaceSubClass; + + private byte bInterfaceProtocol; + + private byte iInterface; + + private Usb_Endpoint_Descriptor[] endpoint; + + private byte[] extra; /* Extra descriptors */ + + private int extralen; + + @Override + public String toString() { + return "Usb_Interface_Descriptor bNumEndpoints: 0x" + + Integer.toHexString(bNumEndpoints); + } + + /** + * Returns the value used to select the alternate setting ({@link LibusbJava#usb_set_altinterface(long, int)}).
+ * + * @return the alternate setting + */ + public byte getBAlternateSetting() { + return bAlternateSetting; + } + + /** + * Returns the class code (Assigned by www.usb.org).
+ * + * @return the class code + */ + public byte getBInterfaceClass() { + return bInterfaceClass; + } + + /** + * Returns the number (identifier) of this interface.
+ * + * @return the number (identifier) of this interface + */ + public byte getBInterfaceNumber() { + return bInterfaceNumber; + } + + /** + * Returns the protocol code (Assigned by www.usb.org).
+ * + * @return the protocol code + */ + public byte getBInterfaceProtocol() { + return bInterfaceProtocol; + } + + /** + * Returns the subclass code (Assigned by www.usb.org).
+ * + * @return the subclass code + */ + public byte getBInterfaceSubClass() { + return bInterfaceSubClass; + } + + /** + * Returns the number of endpoints used for this interface.
+ * + * @return the number of endpoints used for this interface + */ + public byte getBNumEndpoints() { + return bNumEndpoints; + } + + /** + * Returns an array of endpoint descriptors.
+ * + * @return an array of endpoint descriptors + */ + public Usb_Endpoint_Descriptor[] getEndpoint() { + return endpoint; + } + + /** + * Returns the data of extra descriptor(s) if available.
+ * + * @return null or a byte array with the extra descriptor data + */ + public byte[] getExtra() { + return extra; + } + + /** + * Returns the number of bytes of the extra descriptor.
+ * + * @return the number of bytes of the extra descriptor + */ + public int getExtralen() { + return extralen; + } + + /** + * Returns the index of the String descriptor describing this interface.
+ * + * @return the index of the String descriptor + */ + public byte getIInterface() { + return iInterface; + } +} diff --git a/src/main/java/ch/ntb/usb.r273/Utils.java b/src/main/java/ch/ntb/usb.r273/Utils.java new file mode 100644 index 0000000..d13a5ba --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/Utils.java @@ -0,0 +1,60 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb; + +import java.io.PrintStream; + +public class Utils { + + public static void logBus(Usb_Bus bus) { + logBus(bus, System.out); + } + + public static void logBus(Usb_Bus bus, PrintStream out) { + Usb_Bus usb_Bus = bus; + while (usb_Bus != null) { + out.println(usb_Bus.toString()); + Usb_Device dev = usb_Bus.getDevices(); + while (dev != null) { + out.println("\t" + dev.toString()); + // Usb_Device_Descriptor + Usb_Device_Descriptor defDesc = dev.getDescriptor(); + out.println("\t\t" + defDesc.toString()); + // Usb_Config_Descriptor + Usb_Config_Descriptor[] confDesc = dev.getConfig(); + for (int i = 0; i < confDesc.length; i++) { + out.println("\t\t" + confDesc[i].toString()); + Usb_Interface[] int_ = confDesc[i].getInterface(); + if (int_ != null) { + for (int j = 0; j < int_.length; j++) { + out.println("\t\t\t" + int_[j].toString()); + Usb_Interface_Descriptor[] intDesc = int_[j] + .getAltsetting(); + if (intDesc != null) { + for (int k = 0; k < intDesc.length; k++) { + out.println("\t\t\t\t" + + intDesc[k].toString()); + Usb_Endpoint_Descriptor[] epDesc = intDesc[k] + .getEndpoint(); + if (epDesc != null) { + for (int e = 0; e < epDesc.length; e++) { + out.println("\t\t\t\t\t" + + epDesc[e].toString()); + } + } + } + } + } + } + } + dev = dev.getNext(); + } + usb_Bus = usb_Bus.getNext(); + } + } +} diff --git a/src/main/java/ch/ntb/usb.r273/logger/LogUtil.java b/src/main/java/ch/ntb/usb.r273/logger/LogUtil.java new file mode 100644 index 0000000..998b602 --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/logger/LogUtil.java @@ -0,0 +1,135 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb.logger; + +import java.io.InputStream; +import java.util.Properties; +import java.util.logging.ConsoleHandler; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.Logger; + +public class LogUtil { + + // debug this class + private static final boolean debugLogUtil = false; + + private static final String PLUGIN_ID = "ch.ntb.usb"; + private static final String PROPERTIES_FILE = ".configure"; + private static final String LOGGER_WARNING = "Warning in class " + + LogUtil.class.getName() + + ": could not load the logger properties file " + PROPERTIES_FILE; + + private static boolean debugEnabled; + + static { + createLoggersFromProperties(); + } + + private static void debugMsg(String method, String message) { + if (debugLogUtil) { + System.out.println(method + ": " + message); + } + } + + public static void setLevel(Logger logger, Level loglevel) { + Handler[] h = logger.getHandlers(); + for (int i = 0; i < h.length; i++) { + System.out.println("setLevel " + loglevel.toString()); + h[i].setLevel(loglevel); + } + logger.setLevel(loglevel); + } + + public static Logger getLogger(String name) { + debugMsg("getLogger", name); + LogManager manager = LogManager.getLogManager(); + // check if logger is already registered + Logger logger = manager.getLogger(name); + if (logger == null) { + logger = Logger.getLogger(name); + setLevel(logger, Level.OFF); + manager.addLogger(logger); + debugMsg("getLogger", "creating new logger"); + } + if (logger.getLevel() == null) { + debugMsg("getLogger", "level == null -> setLevel to OFF "); + setLevel(logger, Level.OFF); + } + debugMsg("getLogger", "logLevel " + logger.getLevel().getName()); + return logger; + } + + private static void initLevel(Logger logger, Level loglevel) { + Handler[] h = logger.getHandlers(); + for (int i = 0; i < h.length; i++) { + logger.removeHandler(h[i]); + } + Handler console = new ConsoleHandler(); + console.setLevel(loglevel); + logger.addHandler(console); + logger.setLevel(loglevel); + logger.setUseParentHandlers(false); + } + + private static void createLoggersFromProperties() { + try { + debugMsg(LogUtil.class.getName(), "createLoggersFromProperties"); + InputStream is = LogUtil.class.getClassLoader() + .getResourceAsStream(PROPERTIES_FILE); + if (is == null) { + System.err.println(LOGGER_WARNING); + } else { + Properties prop = new Properties(); + prop.load(is); + debugMsg("createLoggersFromProperties", + "properties file loaded: " + PROPERTIES_FILE); + debugMsg("createLoggersFromProperties", "file content:\n" + + prop.toString()); + // get global debug enable flag + debugEnabled = Boolean.parseBoolean(prop.getProperty(PLUGIN_ID + + "/debug")); + debugMsg("createLoggersFromProperties", "debuging enabled: " + + debugEnabled); + // get and configure loggers + boolean moreLoggers = true; + int loggerCount = 0; + while (moreLoggers) { + String loggerProp = prop.getProperty(PLUGIN_ID + + "/debug/logger" + loggerCount); + loggerCount++; + if (loggerProp != null) { + // parse string and get logger name and log level + int slashIndex = loggerProp.indexOf('/'); + String loggerName = loggerProp.substring(0, slashIndex) + .trim(); + String logLevel = loggerProp.substring(slashIndex + 1, + loggerProp.length()); + // register logger + Level level; + if (debugEnabled) { + level = Level.parse(logLevel); + } else { + level = Level.OFF; + } + Logger logger = getLogger(loggerName); + initLevel(logger, level); + debugMsg("createLoggersFromProperties", + "create logger " + loggerName + " with level " + + level.toString()); + } else { + moreLoggers = false; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/ch/ntb/usb.r273/logger/package.html b/src/main/java/ch/ntb/usb.r273/logger/package.html new file mode 100644 index 0000000..fe57a92 --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/logger/package.html @@ -0,0 +1,16 @@ + + + + + +Logging related classes. + +

Related Resources

+ +For more information about this project visit +http://libusbjava.sourceforge.net +. + + + diff --git a/src/main/java/ch/ntb/usb.r273/package.html b/src/main/java/ch/ntb/usb.r273/package.html new file mode 100644 index 0000000..147866d --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/package.html @@ -0,0 +1,26 @@ + + + + + +Includes the main classes for the Java libusb wrapper. +
+LibusbJava.java +is the JNI class to the +LibusbJava.dll +. Every class starting with +Usb_ +represents a descriptor of the bus structure which is retrieved by +calling +LibusbJava.usb_get_busses() +. + +

Related Resources

+ +For more information about this project visit +http://libusbjava.sourceforge.net +. + + + diff --git a/src/main/java/ch/ntb/usb.r273/usbView/UsbTreeModel.java b/src/main/java/ch/ntb/usb.r273/usbView/UsbTreeModel.java new file mode 100644 index 0000000..8e4b1ca --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/usbView/UsbTreeModel.java @@ -0,0 +1,495 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb.usbView; + +import java.util.Vector; + +import javax.swing.JTextArea; +import javax.swing.JTree; +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; + +import ch.ntb.usb.LibusbJava; +import ch.ntb.usb.Usb_Bus; +import ch.ntb.usb.Usb_Config_Descriptor; +import ch.ntb.usb.Usb_Device; +import ch.ntb.usb.Usb_Device_Descriptor; +import ch.ntb.usb.Usb_Endpoint_Descriptor; +import ch.ntb.usb.Usb_Interface; +import ch.ntb.usb.Usb_Interface_Descriptor; + +public class UsbTreeModel implements TreeModel, TreeSelectionListener { + + private Usb_Bus rootBus; + + private static final String USB_ROOT = "USB"; + + private JTextArea textArea; + + private Vector treeModelListeners = new Vector(); + + /** + * Default constructor.
+ * + * @param rootBus + * the root bus from which the data is read + * @param textArea + * the text area to which the data is written + */ + public UsbTreeModel(Usb_Bus rootBus, JTextArea textArea) { + this.rootBus = rootBus; + this.textArea = textArea; + } + + /** + * Returns the root of the tree. + */ + public Object getRoot() { + return USB_ROOT; + } + + /** + * Returns the child of parent at index index in the parent's child array. + */ + public Object getChild(Object parent, int index) { + + if (parent instanceof String && ((String) parent).compareTo(USB_ROOT) == 0) + { + Usb_Bus curBus = rootBus; + + for (int i = 0; curBus != null; curBus = curBus.getNext(), i++) + { + if (i == index) + return curBus; + } + } + + else if (parent instanceof Usb_Bus) { + Usb_Device device = ((Usb_Bus) parent).getDevices(); + int count = 0; + while (device != null) { + if (count == index) + return device; + count++; + device = device.getNext(); + } + return null; + } else if (parent instanceof Usb_Device) { + Usb_Device dev = (Usb_Device) parent; + // return the Usb_Device_Descriptor at index 0 + if (index == 0) { + return dev.getDescriptor(); + } + Usb_Config_Descriptor[] confDescs = dev.getConfig(); + if (index >= confDescs.length + 1) + return null; + return confDescs[index - 1]; + } else if (parent instanceof Usb_Config_Descriptor) { + Usb_Interface[] intDescs = ((Usb_Config_Descriptor) parent) + .getInterface(); + if (index >= intDescs.length) + return null; + return intDescs[index]; + } else if (parent instanceof Usb_Interface) { + Usb_Interface_Descriptor[] altSettings = ((Usb_Interface) parent) + .getAltsetting(); + if (index >= altSettings.length) + return null; + return altSettings[index]; + } else if (parent instanceof Usb_Interface_Descriptor) { + Usb_Endpoint_Descriptor[] endpoints = ((Usb_Interface_Descriptor) parent) + .getEndpoint(); + if (index >= endpoints.length) + return null; + return endpoints[index]; + } + return null; + } + + /** + * Returns the number of children of parent. + */ + public int getChildCount(Object parent) + { + if (parent instanceof String && ((String) parent).compareTo(USB_ROOT) == 0) + { + int count = 0; + + Usb_Bus curBus = rootBus; + + for (; curBus != null; curBus = curBus.getNext()) + { + count++; + } + + return count; + + } + else if (parent instanceof Usb_Bus) { + Usb_Device device = ((Usb_Bus) parent).getDevices(); + int count = 0; + while (device != null) { + count++; + device = device.getNext(); + } + return count; + } else if (parent instanceof Usb_Device) { + // add the Usb_Device_Descriptor + return ((Usb_Device) parent).getConfig().length + 1; + } else if (parent instanceof Usb_Config_Descriptor) { + return ((Usb_Config_Descriptor) parent).getInterface().length; + } else if (parent instanceof Usb_Interface) { + return ((Usb_Interface) parent).getAltsetting().length; + } else if (parent instanceof Usb_Interface_Descriptor) { + return ((Usb_Interface_Descriptor) parent).getEndpoint().length; + } + return 0; + } + + /** + * Returns true if node is a leaf. + */ + public boolean isLeaf(Object node) { + return false; + } + + /** + * Messaged when the user has altered the value for the item identified by + * path to newValue. Not used by this model. + */ + public void valueForPathChanged(TreePath path, Object newValue) { + System.out.println("*** valueForPathChanged : " + path + " --> " + + newValue); + } + + /** + * Returns the index of child in parent. + */ + public int getIndexOfChild(Object parent, Object child) { + return 0; + } + + public void addTreeModelListener(TreeModelListener l) { + treeModelListeners.addElement(l); + } + + public void removeTreeModelListener(TreeModelListener l) { + treeModelListeners.removeElement(l); + } + + /** + * The only event raised by this model is TreeStructureChanged with the root + * as path, i.e. the whole tree has changed. + */ + protected void fireTreeStructureChanged(Usb_Bus newRootBus) { + rootBus = newRootBus; + int len = treeModelListeners.size(); + TreeModelEvent e = new TreeModelEvent(this, new Object[] { newRootBus }); + for (int i = 0; i < len; i++) { + treeModelListeners.elementAt(i).treeStructureChanged(e); + } + } + + public void valueChanged(TreeSelectionEvent e) { + JTree tree = (JTree) e.getSource(); + Object component = tree.getLastSelectedPathComponent(); + if (component instanceof Usb_Bus) { + Usb_Bus bus = (Usb_Bus) component; + StringBuffer sb = new StringBuffer("Usb_Bus\n"); + sb.append("\tdirname: " + bus.getDirname() + "\n"); + sb.append("\tlocation: 0x" + Long.toHexString(bus.getLocation()) + + "\n"); + textArea.setText(sb.toString()); + } else if (component instanceof Usb_Device) { + Usb_Device device = (Usb_Device) component; + StringBuffer sb = new StringBuffer("Usb_Device\n"); + sb.append("\tfilename: " + device.getFilename() + "\n"); + sb.append("\tdevnum: " + device.getDevnum() + "\n"); + sb.append("\tnum_children: " + device.getNumChildren() + "\n"); + textArea.setText(sb.toString()); + } else if (component instanceof Usb_Device_Descriptor) { + Usb_Device_Descriptor devDesc = (Usb_Device_Descriptor) component; + StringBuffer sb = new StringBuffer("Usb_Device_Descriptor\n"); + sb.append("\tblenght: 0x" + + Integer.toHexString(devDesc.getBLength() & 0xFF) + "\n"); + sb.append("\tbDescriptorType: 0x" + + Integer.toHexString(devDesc.getBDescriptorType() & 0xFF) + + "\n"); + sb.append("\tbcdUSB: 0x" + + Integer.toHexString(devDesc.getBcdUSB() & 0xFFFF) + "\n"); + sb.append("\tbDeviceClass: 0x" + + Integer.toHexString(devDesc.getBDeviceClass() & 0xFF) + + "\n"); + sb.append("\tbDeviceSubClass: 0x" + + Integer.toHexString(devDesc.getBDeviceSubClass() & 0xFF) + + "\n"); + sb.append("\tbDeviceProtocol: 0x" + + Integer.toHexString(devDesc.getBDeviceProtocol() & 0xFF) + + "\n"); + sb.append("\tbMaxPacketSize0: 0x" + + Integer.toHexString(devDesc.getBMaxPacketSize0() & 0xFF) + + " (" + devDesc.getBMaxPacketSize0() + ")\n"); + sb.append("\tidVendor: 0x" + + Integer.toHexString(devDesc.getIdVendor() & 0xFFFF) + + "\n"); + sb.append("\tidProduct: 0x" + + Integer.toHexString(devDesc.getIdProduct() & 0xFFFF) + + "\n"); + sb + .append("\tbcdDevice: 0x" + + Integer + .toHexString(devDesc.getBcdDevice() & 0xFF) + + "\n"); + sb.append("\tiManufacturer: 0x" + + Integer.toHexString(devDesc.getIManufacturer() & 0xFF) + + "\n"); + sb.append("\tiProduct: 0x" + + Integer.toHexString(devDesc.getIProduct()) + "\n"); + sb.append("\tiSerialNumber: 0x" + + Integer.toHexString(devDesc.getISerialNumber() & 0xFF) + + "\n"); + sb + .append("\tbNumConfigurations: 0x" + + Integer.toHexString(devDesc + .getBNumConfigurations() & 0xFF) + "\n"); + // get device handle to retrieve string descriptors + Usb_Bus bus = rootBus; + while (bus != null) { + Usb_Device dev = bus.getDevices(); + while (dev != null) { + Usb_Device_Descriptor tmpDevDesc = dev.getDescriptor(); + if ((dev.getDescriptor() != null) + && ((dev.getDescriptor().getIManufacturer() > 0) + || (dev.getDescriptor().getIProduct() > 0) || (dev + .getDescriptor().getISerialNumber() > 0))) { + if (tmpDevDesc.equals(devDesc)) { + long handle = LibusbJava.usb_open(dev); + sb.append("\nString descriptors\n"); + if (handle <= 0) { + sb.append("\terror opening the device\n"); + break; + } + if (dev.getDescriptor().getIManufacturer() > 0) { + String manufacturer = LibusbJava + .usb_get_string_simple(handle, devDesc + .getIManufacturer()); + if (manufacturer == null) + manufacturer = "unable to fetch manufacturer string"; + sb.append("\tiManufacturer: " + manufacturer + + "\n"); + } + if (dev.getDescriptor().getIProduct() > 0) { + String product = LibusbJava + .usb_get_string_simple(handle, devDesc + .getIProduct()); + if (product == null) + product = "unable to fetch product string"; + sb.append("\tiProduct: " + product + "\n"); + } + if (dev.getDescriptor().getISerialNumber() > 0) { + String serialNumber = LibusbJava + .usb_get_string_simple(handle, devDesc + .getISerialNumber()); + if (serialNumber == null) + serialNumber = "unable to fetch serial number string"; + sb.append("\tiSerialNumber: " + serialNumber + + "\n"); + } + LibusbJava.usb_close(handle); + } + } + dev = dev.getNext(); + } + bus = bus.getNext(); + } + textArea.setText(sb.toString()); + } else if (component instanceof Usb_Config_Descriptor) { + Usb_Config_Descriptor confDesc = (Usb_Config_Descriptor) component; + StringBuffer sb = new StringBuffer("Usb_Config_Descriptor\n"); + sb.append("\tblenght: 0x" + + Integer.toHexString(confDesc.getBLength()) + "\n"); + sb.append("\tbDescriptorType: 0x" + + Integer.toHexString(confDesc.getBDescriptorType() & 0xFF) + + "\n"); + sb.append("\tbNumInterfaces: 0x" + + Integer.toHexString(confDesc.getBNumInterfaces() & 0xFF) + + "\n"); + sb + .append("\tbConfigurationValue: 0x" + + Integer.toHexString(confDesc + .getBConfigurationValue() & 0xFF) + "\n"); + sb.append("\tiConfiguration: 0x" + + Integer.toHexString(confDesc.getIConfiguration() & 0xFF) + + "\n"); + sb.append("\tbmAttributes: 0x" + + Integer.toHexString(confDesc.getBmAttributes() & 0xFF) + + "\n"); + sb.append("\tMaxPower [mA]: 0x" + + Integer.toHexString(confDesc.getMaxPower() & 0xFF) + " (" + + confDesc.getMaxPower() + ")\n"); + sb.append("\textralen: 0x" + + Integer.toHexString(confDesc.getExtralen()) + "\n"); + sb.append("\textra: " + extraDescriptorToString(confDesc.getExtra()) + "\n"); + // get device handle to retrieve string descriptors + Usb_Bus bus = rootBus; + while (bus != null) { + Usb_Device dev = bus.getDevices(); + while (dev != null) { + Usb_Config_Descriptor[] tmpConfDesc = dev.getConfig(); + for (int i = 0; i < tmpConfDesc.length; i++) { + if ((tmpConfDesc.equals(confDesc)) + && (confDesc.getIConfiguration() > 0)) { + long handle = LibusbJava.usb_open(dev); + sb.append("\nString descriptors\n"); + if (handle <= 0) { + sb.append("\terror opening the device\n"); + break; + } + String configuration = LibusbJava + .usb_get_string_simple(handle, confDesc + .getIConfiguration()); + if (configuration == null) + configuration = "unable to fetch configuration string"; + sb.append("\tiConfiguration: " + configuration + + "\n"); + + LibusbJava.usb_close(handle); + + } + } + dev = dev.getNext(); + } + bus = bus.getNext(); + } + textArea.setText(sb.toString()); + } else if (component instanceof Usb_Interface) { + Usb_Interface int_ = (Usb_Interface) component; + StringBuffer sb = new StringBuffer("Usb_Interface\n"); + sb.append("\tnum_altsetting: 0x" + + Integer.toHexString(int_.getNumAltsetting()) + "\n"); + sb.append("\taltsetting: " + int_.getAltsetting() + "\n"); + textArea.setText(sb.toString()); + } else if (component instanceof Usb_Interface_Descriptor) { + Usb_Interface_Descriptor intDesc = (Usb_Interface_Descriptor) component; + StringBuffer sb = new StringBuffer("Usb_Interface_Descriptor\n"); + sb.append("\tblenght: 0x" + + Integer.toHexString(intDesc.getBLength() & 0xFF) + "\n"); + sb.append("\tbDescriptorType: 0x" + + Integer.toHexString(intDesc.getBDescriptorType() & 0xFF) + + "\n"); + sb.append("\tbInterfaceNumber: 0x" + + Integer.toHexString(intDesc.getBInterfaceNumber() & 0xFF) + + "\n"); + sb.append("\tbAlternateSetting: 0x" + + Integer + .toHexString(intDesc.getBAlternateSetting() & 0xFF) + + "\n"); + sb.append("\tbNumEndpoints: 0x" + + Integer.toHexString(intDesc.getBNumEndpoints() & 0xFF) + + "\n"); + sb.append("\tbInterfaceClass: 0x" + + Integer.toHexString(intDesc.getBInterfaceClass() & 0xFF) + + "\n"); + sb + .append("\tbInterfaceSubClass: 0x" + + Integer.toHexString(intDesc + .getBInterfaceSubClass() & 0xFF) + "\n"); + sb + .append("\tbInterfaceProtocol: 0x" + + Integer.toHexString(intDesc + .getBInterfaceProtocol() & 0xFF) + "\n"); + sb.append("\tiInterface: 0x" + + Integer.toHexString(intDesc.getIInterface()) + "\n"); + sb.append("\textralen: 0x" + + Integer.toHexString(intDesc.getExtralen()) + "\n"); + sb.append("\textra: " + extraDescriptorToString(intDesc.getExtra()) + "\n"); + // get device handle to retrieve string descriptors + Usb_Bus bus = rootBus; + while (bus != null) { + Usb_Device dev = bus.getDevices(); + while (dev != null) { + Usb_Config_Descriptor[] confDescs = dev.getConfig(); + for (int i = 0; i < confDescs.length; i++) { + Usb_Interface[] ints = confDescs[i].getInterface(); + for (int j = 0; j < ints.length; j++) { + Usb_Interface_Descriptor[] tmpIntDescs = ints[j] + .getAltsetting(); + for (int k = 0; k < ints.length; k++) { + if (i < tmpIntDescs.length && tmpIntDescs[i].equals(intDesc) + && (intDesc.getIInterface() > 0)) { + long handle = LibusbJava.usb_open(dev); + sb.append("\nString descriptors\n"); + if (handle <= 0) { + sb + .append("\terror opening the device\n"); + break; + } + String interface_ = LibusbJava + .usb_get_string_simple(handle, + intDesc.getIInterface()); + if (interface_ == null) + interface_ = "unable to fetch interface string"; + sb.append("\tiInterface: " + interface_ + + "\n"); + LibusbJava.usb_close(handle); + } + } + } + } + dev = dev.getNext(); + } + bus = bus.getNext(); + } + textArea.setText(sb.toString()); + } else if (component instanceof Usb_Endpoint_Descriptor) { + Usb_Endpoint_Descriptor epDesc = (Usb_Endpoint_Descriptor) component; + StringBuffer sb = new StringBuffer("Usb_Endpoint_Descriptor\n"); + sb.append("\tblenght: 0x" + + Integer.toHexString(epDesc.getBLength() & 0xFF) + "\n"); + sb.append("\tbDescriptorType: 0x" + + Integer.toHexString(epDesc.getBDescriptorType() & 0xFF) + + "\n"); + sb.append("\tbEndpointAddress: 0x" + + Integer.toHexString(epDesc.getBEndpointAddress() & 0xFF) + + "\n"); + sb.append("\tbmAttributes: 0x" + + Integer.toHexString(epDesc.getBmAttributes() & 0xFF) + + "\n"); + sb.append("\twMaxPacketSize: 0x" + + Integer.toHexString(epDesc.getWMaxPacketSize() & 0xFFFF) + + " (" + epDesc.getWMaxPacketSize() + ")\n"); + sb.append("\tbInterval: 0x" + + Integer.toHexString(epDesc.getBInterval() & 0xFF) + "\n"); + sb.append("\tbRefresh: 0x" + + Integer.toHexString(epDesc.getBRefresh() & 0xFF) + "\n"); + sb.append("\tbSynchAddress: 0x" + + Integer.toHexString(epDesc.getBSynchAddress()) + "\n"); + sb.append("\textralen: 0x" + + Integer.toHexString(epDesc.getExtralen()) + "\n"); + sb.append("\textra: " + extraDescriptorToString(epDesc.getExtra()) + "\n"); + textArea.setText(sb.toString()); + } + } + + private String extraDescriptorToString(byte[] extra) { + if (extra != null) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < extra.length; i++) { + sb.append("0x"); + sb.append(Integer.toHexString(extra[i] & 0xff)); + sb.append(' '); + } + return sb.toString(); + } + return null; + } +} diff --git a/src/main/java/ch/ntb/usb.r273/usbView/UsbView.java b/src/main/java/ch/ntb/usb.r273/usbView/UsbView.java new file mode 100644 index 0000000..c531812 --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/usbView/UsbView.java @@ -0,0 +1,403 @@ +/* + * Java libusb wrapper + * Copyright (c) 2005-2006 Andreas Schläpfer + * + * http://libusbjava.sourceforge.net + * This library is covered by the LGPL, read LGPL.txt for details. + */ +package ch.ntb.usb.usbView; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTextArea; +import javax.swing.JTree; +import javax.swing.KeyStroke; +import javax.swing.tree.TreePath; + +import ch.ntb.usb.LibusbJava; +import ch.ntb.usb.Usb_Bus; +import ch.ntb.usb.Usb_Config_Descriptor; +import ch.ntb.usb.Usb_Device; +import ch.ntb.usb.Usb_Device_Descriptor; +import ch.ntb.usb.Usb_Endpoint_Descriptor; +import ch.ntb.usb.Usb_Interface_Descriptor; +import ch.ntb.usb.testApp.TestApp; +import ch.ntb.usb.testApp.TestDevice; +import ch.ntb.usb.testApp.AbstractDeviceInfo.TransferMode; + +public class UsbView extends JFrame { + + private static final long serialVersionUID = 4693554326612734263L; + + private static final int APP_WIDTH = 600, APP_HIGHT = 800; + + private JPanel jContentPane = null; + private JMenuBar jJMenuBar = null; + private JMenu commandsMenu = null; + private JMenuItem exitMenuItem = null; + private JMenuItem updateMenuItem = null; + JTree usbTree = null; + private JSplitPane jSplitPane = null; + + private JTextArea jPropertiesArea = null; + + UsbTreeModel treeModel; + + JPopupMenu testAppPopup; + + protected JPopupMenu endpointPopup; + + /** + * This is the default constructor + */ + public UsbView() { + super(); + initialize(); + } + + /** + * This method initializes this + * + * @return void + */ + private void initialize() { + this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + this.setJMenuBar(getJJMenuBar()); + this.setSize(APP_WIDTH, APP_HIGHT); + this.setContentPane(getJContentPane()); + this.setTitle("USB View"); + } + + /** + * This method initializes jContentPane + * + * @return javax.swing.JPanel + */ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(new BorderLayout()); + jContentPane.add(getJSplitPane(), java.awt.BorderLayout.CENTER); + } + return jContentPane; + } + + /** + * This method initializes jJMenuBar + * + * @return javax.swing.JMenuBar + */ + private JMenuBar getJJMenuBar() { + if (jJMenuBar == null) { + jJMenuBar = new JMenuBar(); + jJMenuBar.add(getFileMenu()); + } + return jJMenuBar; + } + + /** + * This method initializes jMenu + * + * @return javax.swing.JMenu + */ + private JMenu getFileMenu() { + if (commandsMenu == null) { + commandsMenu = new JMenu(); + commandsMenu.setText("Commands"); + commandsMenu.add(getUpdateMenuItem()); + commandsMenu.add(getExitMenuItem()); + } + return commandsMenu; + } + + /** + * This method initializes jMenuItem + * + * @return javax.swing.JMenuItem + */ + private JMenuItem getExitMenuItem() { + if (exitMenuItem == null) { + exitMenuItem = new JMenuItem(); + exitMenuItem.setText("Exit"); + exitMenuItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.exit(0); + } + }); + } + return exitMenuItem; + } + + /** + * This method initializes jMenuItem + * + * @return javax.swing.JMenuItem + */ + private JMenuItem getUpdateMenuItem() { + if (updateMenuItem == null) { + updateMenuItem = new JMenuItem(); + updateMenuItem.setText("Update"); + updateMenuItem.setAccelerator(KeyStroke.getKeyStroke( + KeyEvent.VK_F5, 0, true)); + updateMenuItem + .addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent e) { + // open bus + LibusbJava.usb_init(); + LibusbJava.usb_find_busses(); + LibusbJava.usb_find_devices(); + + Usb_Bus bus = LibusbJava.usb_get_busses(); + if (bus != null) { + treeModel.fireTreeStructureChanged(bus); + expandAll(usbTree); + } + } + }); + } + return updateMenuItem; + } + + /** + * This method initializes usbTree + * + * @return javax.swing.JTree + */ + private JTree getUsbTree() { + if (usbTree == null) { + // open bus + LibusbJava.usb_init(); + LibusbJava.usb_find_busses(); + LibusbJava.usb_find_devices(); + + Usb_Bus bus = LibusbJava.usb_get_busses(); + + treeModel = new UsbTreeModel(bus, jPropertiesArea); + usbTree = new JTree(treeModel); + expandAll(usbTree); + usbTree.addTreeSelectionListener(treeModel); + getJTestAppPopup(); + usbTree.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + if (e.isPopupTrigger()) { + Object source = e.getSource(); + if (source instanceof JTree) { + JTree tree = (JTree) source; + TreePath path = tree.getPathForLocation(e.getX(), e + .getY()); + if (path != null + && (path.getLastPathComponent() instanceof Usb_Interface_Descriptor)) { + usbTree.setSelectionPath(path); + testAppPopup.show(tree, e.getX(), e.getY()); + } + } + } + } + + @Override + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger()) { + if (e.isPopupTrigger()) { + Object source = e.getSource(); + if (source instanceof JTree) { + JTree tree = (JTree) source; + TreePath path = tree.getPathForLocation(e + .getX(), e.getY()); + if (path != null + && (path.getLastPathComponent() instanceof Usb_Interface_Descriptor)) { + usbTree.setSelectionPath(path); + testAppPopup.show(tree, e.getX(), e.getY()); + } + } + } + } + } + }); + } + return usbTree; + } + + private void getJTestAppPopup() { + // Create the popup menu. + testAppPopup = new JPopupMenu(); + endpointPopup = new JPopupMenu(); + JMenuItem menuItem = new JMenuItem( + "Start a test application using this interface"); + menuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent e) { + initAndStartTestApp(); + } + + private void initAndStartTestApp() { + JTree tree = (JTree) testAppPopup.getInvoker(); + TreePath path = tree.getSelectionPath(); + TreePath parent = path; + Usb_Endpoint_Descriptor[] endpoints = null; + int altinterface = -1; + int interface_ = -1; + int configuration = -1; + short vendorId = -1; + short productId = -1; + while (parent != null + && !(parent.getLastPathComponent() instanceof Usb_Bus)) { + Object usbObj = parent.getLastPathComponent(); + if (usbObj instanceof Usb_Interface_Descriptor) { + Usb_Interface_Descriptor usbIntDesc = (Usb_Interface_Descriptor) usbObj; + endpoints = usbIntDesc.getEndpoint(); + interface_ = usbIntDesc.getBInterfaceNumber(); + altinterface = usbIntDesc.getBAlternateSetting(); + } else if (usbObj instanceof Usb_Config_Descriptor) { + configuration = ((Usb_Config_Descriptor) usbObj) + .getBConfigurationValue(); + } else if (usbObj instanceof Usb_Device) { + Usb_Device_Descriptor devDesc = ((Usb_Device) usbObj) + .getDescriptor(); + productId = devDesc.getIdProduct(); + vendorId = devDesc.getIdVendor(); + } + parent = parent.getParentPath(); + } + if (parent != null) { + // present a dialog to select in/out endpoint + // TODO: present dialog to select in/out endpoint + Usb_Endpoint_Descriptor[] outEPs = null; + int nofOutEPs = 0; + Usb_Endpoint_Descriptor[] inEPs = null; + int nofInEPs = 0; + + if (endpoints != null) { + outEPs = new Usb_Endpoint_Descriptor[endpoints.length]; + inEPs = new Usb_Endpoint_Descriptor[endpoints.length]; + for (int i = 0; i < endpoints.length; i++) { + int epAddr = endpoints[i].getBEndpointAddress() & 0xFF; + if ((epAddr & 0x80) > 0) { + // is IN endpoint + inEPs[nofInEPs++] = endpoints[i]; + } else { + // is OUT endpoint + outEPs[nofOutEPs++] = endpoints[i]; + } + } + } + // create a new TestDevice + TestDevice testDevice = new TestDevice(); + testDevice.setIdProduct(productId); + testDevice.setIdVendor(vendorId); + testDevice.setAltinterface(altinterface); + testDevice.setConfiguration(configuration); + testDevice.setInterface(interface_); + if (inEPs != null) { + for (int i = 0; i < nofInEPs; i++) { + int type = inEPs[i].getBmAttributes() & 0x03; + switch (type) { + case Usb_Endpoint_Descriptor.USB_ENDPOINT_TYPE_BULK: + testDevice.setInEPBulk(inEPs[i] + .getBEndpointAddress() & 0xff); + testDevice.setInMode(TransferMode.Bulk); + break; + case Usb_Endpoint_Descriptor.USB_ENDPOINT_TYPE_INTERRUPT: + testDevice.setInEPInt(inEPs[i] + .getBEndpointAddress() & 0xff); + testDevice.setInMode(TransferMode.Interrupt); + break; + default: + break; + } + } + } + if (outEPs != null) { + for (int i = 0; i < nofOutEPs; i++) { + int type = outEPs[i].getBmAttributes() & 0x03; + switch (type) { + case Usb_Endpoint_Descriptor.USB_ENDPOINT_TYPE_BULK: + testDevice.setOutEPBulk(outEPs[i] + .getBEndpointAddress() & 0xff); + testDevice.setOutMode(TransferMode.Bulk); + break; + case Usb_Endpoint_Descriptor.USB_ENDPOINT_TYPE_INTERRUPT: + testDevice.setOutEPInt(outEPs[i] + .getBEndpointAddress() & 0xff); + testDevice.setOutMode(TransferMode.Interrupt); + break; + default: + break; + } + } + } + // open a new testApp + TestApp app = new TestApp(testDevice); + app.setVisible(true); + } else { + System.out.println("error, could not find device node"); + // TODO: handle error + } + } + }); + testAppPopup.add(menuItem); + } + + /** + * This method initializes jSplitPane + * + * @return javax.swing.JSplitPane + */ + private JSplitPane getJSplitPane() { + if (jSplitPane == null) { + jSplitPane = new JSplitPane(); + jSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); + jSplitPane.setContinuousLayout(true); + jSplitPane.setDividerLocation(APP_HIGHT / 2); + jSplitPane + .setBottomComponent(createScrollPane(getJPropertiesArea())); + jSplitPane.setTopComponent(createScrollPane(getUsbTree())); + } + return jSplitPane; + } + + /** + * This method initializes jPropertiesArea + * + * @return javax.swing.JTextArea + */ + private JTextArea getJPropertiesArea() { + if (jPropertiesArea == null) { + jPropertiesArea = new JTextArea(); + } + return jPropertiesArea; + } + + private JScrollPane createScrollPane(Component view) { + JScrollPane scrollPane = new JScrollPane(view); + return scrollPane; + } + + /** + * Launches this application + */ + public static void main(String[] args) { + UsbView application = new UsbView(); + application.setVisible(true); + } + + void expandAll(JTree tree) { + for (int row = 0; row < tree.getRowCount(); row++) { + tree.expandRow(row); + } + } +} diff --git a/src/main/java/ch/ntb/usb.r273/usbView/package.html b/src/main/java/ch/ntb/usb.r273/usbView/package.html new file mode 100644 index 0000000..2a64b06 --- /dev/null +++ b/src/main/java/ch/ntb/usb.r273/usbView/package.html @@ -0,0 +1,17 @@ + + + + + +Displays the bus and device information of the currently attached +devices in a tree (based on Swing). + +

Related Resources

+ +For more information about this project visit +http://libusbjava.sourceforge.net +. + + +