From ebd46e23b3822abe29658eb02bce8e56afd7c356 Mon Sep 17 00:00:00 2001 From: ntfreak Date: Mon, 13 Jul 2009 06:36:51 +0000 Subject: [PATCH] Gary Carlson Spencer Oliver - fix jlink win32/linux/darwin startup issues - see https://lists.berlios.de/pipermail/openocd-development/2009-July/009438.html git-svn-id: svn://svn.berlios.de/openocd/trunk@2513 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/jtag/jlink.c | 135 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 92 insertions(+), 43 deletions(-) diff --git a/src/jtag/jlink.c b/src/jtag/jlink.c index aff1a6cae7..d8bfb0f391 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; } } -- 2.30.2