- /* usb_set_configuration required under win32 */
- usb_set_configuration(result->usb_handle, dev->config[0].bConfigurationValue);
- usb_claim_interface(result->usb_handle, 0);
+static struct jlink* jlink_usb_open()
+{
+ struct usb_device *dev;
+
+ struct jlink *result;
+
+ result = (struct jlink*) malloc(sizeof(struct jlink));
+
+ usb_init();
+
+ if ((dev = find_jlink_device()) == NULL) {
+ free(result);
+ return NULL;
+ }
+
+ result->usb_handle = usb_open(dev);
+
+ if (result->usb_handle)
+ {
+
+ /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS AREA!!!!!!!!!!!
+ * The behavior of libusb is not completely consistent across Windows, Linux, and Mac OS X platforms. The actions taken
+ * in the following compiler conditionals may not agree with published documentation for libusb, but were found
+ * to be necessary through trials and tribulations. Even little tweaks can break one or more platforms, so if you do make changes
+ * test them carefully on all platforms before committing them!
+ */
+
+#if IS_WIN32 == 0
+
+ usb_reset(result->usb_handle);
+
+#if IS_DARWIN == 0
+
+ int timeout = 5;
+
+ /* reopen jlink after usb_reset
+ * on win32 this may take a second or two to re-enumerate */
+ while ((dev = find_jlink_device()) == NULL)
+ {
+ usleep(1000);
+ timeout--;
+ if (!timeout) {
+ break;
+ }
+ }
+
+ if (dev == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ result->usb_handle = usb_open(dev);
+#endif
+
+#endif
+
+ if (result->usb_handle)
+ {
+ /* usb_set_configuration required under win32 */
+ usb_set_configuration(result->usb_handle, dev->config[0].bConfigurationValue);
+ usb_claim_interface(result->usb_handle, 0);