diff --git a/src/jtag/jlink.c b/src/jtag/jlink.c
index aff1a6cae7aa3dd4a511b0786e7d15ff95b96d38..d8bfb0f391162b0e9f461ba855b4e851d4789a67 100644
--- a/src/jtag/jlink.c
+++ b/src/jtag/jlink.c
@@ -835,13 +835,37 @@ static int jlink_tap_execute(void)
 	return ERROR_OK;
 }
 
+static struct usb_device* find_jlink_device(void)
+{
+	struct usb_bus *busses;
+	struct usb_bus *bus;
+	struct usb_device *dev;
+
+	usb_find_busses();
+	usb_find_devices();
+
+	busses = usb_get_busses();
+
+	/* find jlink_jtag device in usb bus */
+
+	for (bus = busses; bus; bus = bus->next)
+	{
+		for (dev = bus->devices; dev; dev = dev->next)
+		{
+			if ((dev->descriptor.idVendor == VID) && (dev->descriptor.idProduct == PID)) {
+				return dev;
+			}
+		}
+	}
+
+	return NULL;
+}
+
 /*****************************************************************************/
 /* JLink USB low-level functions */
 
 static jlink_jtag_t* jlink_usb_open()
 {
-	struct usb_bus *busses;
-	struct usb_bus *bus;
 	struct usb_device *dev;
 
 	jlink_jtag_t *result;
@@ -849,56 +873,81 @@ static jlink_jtag_t* jlink_usb_open()
 	result = (jlink_jtag_t*) malloc(sizeof(jlink_jtag_t));
 
 	usb_init();
-	usb_find_busses();
-	usb_find_devices();
 
-	busses = usb_get_busses();
+	if ((dev = find_jlink_device()) == NULL) {
+		free(result);
+		return NULL;
+	}
 
-	/* find jlink_jtag device in usb bus */
+	result->usb_handle = usb_open(dev);
 
-	for (bus = busses; bus; bus = bus->next)
+	if (result->usb_handle)
 	{
-		for (dev = bus->devices; dev; dev = dev->next)
+	
+		/* 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)
 		{
-			if ((dev->descriptor.idVendor == VID) && (dev->descriptor.idProduct == PID))
-			{
-				result->usb_handle = usb_open(dev);
-				
-				/*
-				 *	Some j-link dongles experience intermittent communication issues at startup to varying degrees
-				 *	depending on the host operating system.  Troubleshooting this problem all the way back to libusb
-				 *	revealed that without a usb reset, the hardware can start in an uncertain state causing a litany
-				 *	of annoying problems.  The next step was added to the original code to address this problem.
-				 */
-				
-				usb_reset(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);
+			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);
 
 #if 0
-				/*
-				 * This makes problems under Mac OS X. And is not needed
-				 * under Windows. Hopefully this will not break a linux build
-				 */
-				usb_set_altinterface(result->usb_handle, 0);
+			/*
+			 * This makes problems under Mac OS X. And is not needed
+			 * under Windows. Hopefully this will not break a linux build
+			 */
+			usb_set_altinterface(result->usb_handle, 0);
 #endif
-				struct usb_interface *iface = dev->config->interface;
-				struct usb_interface_descriptor *desc = iface->altsetting;
-				for (int i = 0; i < desc->bNumEndpoints; i++)
-				{
-					uint8_t epnum = desc->endpoint[i].bEndpointAddress;
-					bool is_input = epnum & 0x80;
-					LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum);
-					if (is_input)
-						jlink_read_ep = epnum;
-					else
-						jlink_write_ep = epnum;
-				}
-
-				return result;
+			struct usb_interface *iface = dev->config->interface;
+			struct usb_interface_descriptor *desc = iface->altsetting;
+			for (int i = 0; i < desc->bNumEndpoints; i++)
+			{
+				uint8_t epnum = desc->endpoint[i].bEndpointAddress;
+				bool is_input = epnum & 0x80;
+				LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum);
+				if (is_input)
+					jlink_read_ep = epnum;
+				else
+					jlink_write_ep = epnum;
 			}
+
+			return result;
 		}
 	}