diff --git a/mcdp/src/ch/ntb/mcdp/usb/USBDevice.java b/mcdp/src/ch/ntb/mcdp/usb/USBDevice.java index bc67b90..af526cb 100644 --- a/mcdp/src/ch/ntb/mcdp/usb/USBDevice.java +++ b/mcdp/src/ch/ntb/mcdp/usb/USBDevice.java @@ -32,6 +32,8 @@ public class USBDevice { static { dev = USB.getDevice(IdVendor, IdProduct); + dev.setReopenOnTimeout(true); + dev.setResetOnFirstOpen(true); } public static void open() throws USBException { diff --git a/mcdp/src/ch/ntb/usb/Device.java b/mcdp/src/ch/ntb/usb/Device.java index 14b5f5f..2a65a6a 100644 --- a/mcdp/src/ch/ntb/usb/Device.java +++ b/mcdp/src/ch/ntb/usb/Device.java @@ -24,7 +24,13 @@ public class Device { private int usb_dev_handle; + private boolean reopenOnTimeout, reopenDone, resetOnFirstOpen, resetDone; + protected Device(short idVendor, short idProduct) { + reopenOnTimeout = false; + reopenDone = false; + resetOnFirstOpen = false; + resetDone = false; maxPacketSize = -1; this.idVendor = idVendor; this.idProduct = idProduct; @@ -94,7 +100,8 @@ public class Device { for (int k = 0; k < intDesc.length; k++) { Usb_Endpoint_Descriptor[] epDesc = intDesc[k].endpoint; for (int l = 0; l < epDesc.length; l++) { - maxPacketSize = Math.max(epDesc[l].wMaxPacketSize, + maxPacketSize = Math.max( + epDesc[l].wMaxPacketSize, maxPacketSize); } } @@ -117,8 +124,19 @@ public class Device { + Integer.toHexString(idProduct & 0xFFFF) + " not found"); } claim_interface(usb_dev_handle, configuration, interface_, altinterface); + if (resetOnFirstOpen & !resetDone) { + logger.info("reset on first open"); + resetDone = true; + reset(); + open(configuration, interface_, altinterface); + } } + /** + * Release the claimed interface and close the opened device. + * + * @throws USBException + */ public void close() throws USBException { if (usb_dev_handle <= 0) { throw new USBException("invalid device handle"); @@ -154,6 +172,7 @@ public class Device { /** * Write data to the device using a bulk transfer.
+ * If reopenOnTimeout is set to true, it may take * * @param out_ep_address * endpoint address to write to @@ -182,6 +201,15 @@ public class Device { out_ep_address, data, length, timeout); if (lenWritten < 0) { if (lenWritten == TIMEOUT_ERROR_CODE) { + // try to reopen the device and send the data again + if (reopenOnTimeout & !reopenDone) { + logger.info("try to reopen"); + reset(); + open(configuration, interface_, altinterface); + reopenDone = true; + return bulkwrite(out_ep_address, data, length, timeout); + } + reopenDone = false; throw new USBTimeoutException("LibusbWin.usb_bulk_write: " + LibusbWin.usb_strerror()); } @@ -229,6 +257,19 @@ public class Device { data, size, timeout); if (lenRead < 0) { if (lenRead == TIMEOUT_ERROR_CODE) { + if (lenRead == TIMEOUT_ERROR_CODE) { + // try to reopen the device and send the data again + if (reopenOnTimeout & !reopenDone) { + logger.info("try to reopen"); + reset(); + open(configuration, interface_, altinterface); + reopenDone = true; + return bulkwrite(in_ep_address, data, size, timeout); + } + reopenDone = false; + throw new USBTimeoutException("LibusbWin.usb_bulk_write: " + + LibusbWin.usb_strerror()); + } throw new USBTimeoutException("LibusbWin.usb_bulk_read: " + LibusbWin.usb_strerror()); } @@ -356,4 +397,26 @@ public class Device { return maxPacketSize; } + /** + * Before a timeout exception is thrown (after issuing a read or write + * command), the device will try to open the connection and send or receive + * the data again.
+ * The default value is false. + * + * @param enable + */ + public void setReopenOnTimeout(boolean enable) { + reopenOnTimeout = enable; + } + + /** + * If enabled, the device is reset when first opened. This will only happen + * once. + * + * @param enable + */ + public void setResetOnFirstOpen(boolean enable) { + resetOnFirstOpen = enable; + } + }