Hi,

Between hardware revision 5 and 11, the USB endpoint ids of the J-Links
were changed. The old driver was hardcoded to specific endpoint ids. As
a result, newer J-Links simply did not work.

This patch dynamically searches for the correct endpoints. After that,
newer J-Links should work as expected. The code for this was mostly
copied from libjaylink's transport_usb.c.

I verified operation with a J-Link EDU Hardware Rev. 11.0 and a J-Link
EDU Hardware Rev. 5.

Additionally, the USB timeout value was copied from libjaylink. The
timeout was increased from 100ms to 1000ms.

Thanks
Stephan
From d448ffae2926c6c701da5968cd002d2be83824f1 Mon Sep 17 00:00:00 2001
From: Stephan Brunner <s.brun...@stephan-brunner.net>
Date: Sun, 26 Jul 2020 17:26:49 +0200
Subject: [PATCH] Cable/J-Link: Dynamically search for usb endpoints

Between hardware revision 5 and 11, the USB endpoint ids were changed.
The old driver was hardcoded to specific endpoint ids. As a result,
newer J-Links simply did not work.

This patch dynamically searches for the correct endpoints. After that,
newer J-Links should work as expected.
The code for this was mostly copied from libjaylink's transport_usb.c

Signed-off-by: Stephan Brunner <s.brun...@stephan-brunner.net>
---
 urjtag/src/tap/cable/jlink.c | 89 +++++++++++++++++++++++++++++++++---
 1 file changed, 83 insertions(+), 6 deletions(-)

diff --git a/urjtag/src/tap/cable/jlink.c b/urjtag/src/tap/cable/jlink.c
index d991b809..8af32b70 100644
--- a/urjtag/src/tap/cable/jlink.c
+++ b/urjtag/src/tap/cable/jlink.c
@@ -47,10 +47,7 @@
 
 #include "usbconn/libusb.h"
 
-#define JLINK_WRITE_ENDPOINT 0x02
-#define JLINK_READ_ENDPOINT  (0x01 | LIBUSB_ENDPOINT_IN)
-
-#define JLINK_USB_TIMEOUT 100
+#define JLINK_USB_TIMEOUT 1000
 
 #define JLINK_IN_BUFFER_SIZE  2064
 #define JLINK_OUT_BUFFER_SIZE 2064
@@ -64,6 +61,10 @@ typedef struct
     unsigned char usb_in_buffer[JLINK_IN_BUFFER_SIZE];
     unsigned char usb_out_buffer[JLINK_OUT_BUFFER_SIZE];
 
+    uint8_t interface_number;
+    uint8_t endpoint_in;
+    uint8_t endpoint_out;
+
     int tap_length;
     uint8_t tms_buffer[JLINK_TAP_BUFFER_SIZE];
     uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE];
@@ -357,7 +358,7 @@ jlink_usb_write (urj_usbconn_libusb_param_t *params, unsigned int out_length)
     }
 
     result = libusb_bulk_transfer (params->handle,
-                                   JLINK_WRITE_ENDPOINT,
+                                   data->endpoint_out,
                                    data->usb_out_buffer,
                                    out_length, &actual,
                                    JLINK_USB_TIMEOUT);
@@ -381,7 +382,7 @@ jlink_usb_read (urj_usbconn_libusb_param_t *params)
     int result, actual;
 
     result = libusb_bulk_transfer (params->handle,
-                                   JLINK_READ_ENDPOINT,
+                                   data->endpoint_in,
                                    data->usb_in_buffer,
                                    JLINK_IN_BUFFER_SIZE,
                                    &actual,
@@ -420,6 +421,76 @@ jlink_debug_buffer (unsigned char *buffer, int length)
 
 /* ---------------------------------------------------------------------- */
 
+// Mostly copied by libjaylink's transport_usb.c
+static int
+jlink_find_endpoints (urj_usbconn_libusb_param_t *params)
+{
+    int ret;
+    struct libusb_config_descriptor *config;
+    const struct libusb_interface *interface;
+    const struct libusb_interface_descriptor *desc;
+    const struct libusb_endpoint_descriptor *epdesc;
+    jlink_usbconn_data_t *data = params->data;
+
+    ret = libusb_get_active_config_descriptor (params->dev, &config);
+
+    if (ret != LIBUSB_SUCCESS)
+    {
+        return -1;
+    }
+
+    uint8_t found_interface = 0;
+
+    for (uint8_t i = 0; i < config->bNumInterfaces; i++)
+    {
+        interface = &config->interface[i];
+        desc = &interface->altsetting[0];
+
+        if (desc->bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC)
+            continue;
+
+        if (desc->bInterfaceSubClass != LIBUSB_CLASS_VENDOR_SPEC)
+            continue;
+
+        if (desc->bNumEndpoints < 2)
+            continue;
+
+        found_interface = 1;
+        data->interface_number = i;
+        break;
+    }
+
+    if (!found_interface)
+    {
+        libusb_free_config_descriptor (config);
+        return URJ_STATUS_FAIL;
+    }
+
+    uint8_t found_endpoint_in = 0;
+    uint8_t found_endpoint_out = 0;
+
+    for (uint8_t i = 0; i < desc->bNumEndpoints; i++) {
+        epdesc = &desc->endpoint[i];
+
+        if (epdesc->bEndpointAddress & LIBUSB_ENDPOINT_IN)
+        {
+            data->endpoint_in = epdesc->bEndpointAddress;
+            found_endpoint_in = 1;
+        }
+        else
+        {
+            data->endpoint_out = epdesc->bEndpointAddress;
+            found_endpoint_out = 1;
+        }
+    }
+
+    libusb_free_config_descriptor (config);
+
+    return found_endpoint_out && found_endpoint_in ? URJ_STATUS_OK : URJ_STATUS_FAIL;
+}
+
+/* ---------------------------------------------------------------------- */
+
 static int
 jlink_init (urj_cable_t *cable)
 {
@@ -440,6 +511,12 @@ jlink_init (urj_cable_t *cable)
     if (urj_tap_usbconn_open (cable->link.usb) != URJ_STATUS_OK)
         return URJ_STATUS_FAIL;
 
+    if (jlink_find_endpoints(params) != URJ_STATUS_OK)
+    {
+        urj_error_set (URJ_ERROR_USB, "Failed to find usb endpoints.");
+        return URJ_STATUS_FAIL;
+    }
+
     jlink_tap_init (data);
 
     result = jlink_usb_read (params);
-- 
2.27.0

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
UrJTAG-development mailing list
UrJTAG-development@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/urjtag-development

Reply via email to