Support hla_serial command for ST-LINK adapters. 98/2198/8
authorAustin Phillips <austin_phillips@hotmail.com>
Thu, 18 Sep 2014 04:39:41 +0000 (14:39 +1000)
committerSpencer Oliver <spen@spen-soft.co.uk>
Mon, 22 Sep 2014 19:36:05 +0000 (19:36 +0000)
The hla_serial command allows for a programming device serial number to be
specified in addition to USB VID/PID.  This allows for multiple ST-LINK/V2
programmers to be attached to a single machine and operated using openocd.

Change-Id: I350654bf676eb26ba3a90450acfa55d2a5d2d791
Signed-off-by: Austin Phillips <austin_phillips@hotmail.com>
Reviewed-on: http://openocd.zylin.com/2198
Tested-by: jenkins
Reviewed-by: Martin Glunz <mg@wunderkis.de>
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
13 files changed:
doc/openocd.texi
src/jtag/aice/aice_usb.c
src/jtag/drivers/jlink.c
src/jtag/drivers/libusb0_common.c
src/jtag/drivers/libusb0_common.h
src/jtag/drivers/libusb1_common.c
src/jtag/drivers/libusb1_common.h
src/jtag/drivers/opendous.c
src/jtag/drivers/osbdm.c
src/jtag/drivers/stlink_usb.c
src/jtag/drivers/usb_blaster/ublast2_access_libusb.c
tcl/interface/stlink-v2-1.cfg
tcl/interface/stlink-v2.cfg

index e51de4de9108a01607e48faa8b6f5211c212eb00..15965dabb6f388055d1e54c271466c46c814e27d 100644 (file)
@@ -3079,13 +3079,17 @@ This type of adapter does not expose some of the lower level api's
 that OpenOCD would normally use to access the target.
 
 Currently supported adapters include the ST STLINK and TI ICDI.
+STLINK firmware version >= V2.J21.S4 recommended due to issues with earlier
+versions of firmware where serial number is reset after first use.  Suggest
+using ST firmware update utility to upgrade STLINK firmware even if current
+version reported is V2.J21.S4.
 
 @deffn {Config Command} {hla_device_desc} description
 Currently Not Supported.
 @end deffn
 
 @deffn {Config Command} {hla_serial} serial
-Currently Not Supported.
+Specifies the serial number of the adapter.
 @end deffn
 
 @deffn {Config Command} {hla_layout} (@option{stlink}|@option{icdi})
index 917d795b075ad4c34050a8c31ba40d231530d229..d933845c50844bfa56267fd066d8bd29f6804ce2 100644 (file)
@@ -2099,7 +2099,7 @@ static int aice_usb_open(struct aice_port_param_s *param)
        const uint16_t pids[] = { param->pid, 0 };
        struct jtag_libusb_device_handle *devh;
 
-       if (jtag_libusb_open(vids, pids, &devh) != ERROR_OK)
+       if (jtag_libusb_open(vids, pids, NULL, &devh) != ERROR_OK)
                return ERROR_FAIL;
 
        /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
@@ -2123,7 +2123,7 @@ static int aice_usb_open(struct aice_port_param_s *param)
        /* reopen jlink after usb_reset
         * on win32 this may take a second or two to re-enumerate */
        int retval;
-       while ((retval = jtag_libusb_open(vids, pids, &devh)) != ERROR_OK) {
+       while ((retval = jtag_libusb_open(vids, pids, NULL, &devh)) != ERROR_OK) {
                usleep(1000);
                timeout--;
                if (!timeout)
index 39be9412697c58ab30646bc7ccbc1831cbaa03dc..55b1e45f9fb54b13cb2f1492710fb620aa0b5bde 100644 (file)
@@ -1699,7 +1699,7 @@ static void jlink_swd_queue_cmd(struct adiv5_dap *dap, uint8_t cmd, uint32_t *ds
 static struct jlink *jlink_usb_open()
 {
        struct jtag_libusb_device_handle *devh;
-       if (jtag_libusb_open(vids, pids, &devh) != ERROR_OK)
+       if (jtag_libusb_open(vids, pids, NULL, &devh) != ERROR_OK)
                return NULL;
 
        /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
@@ -1723,7 +1723,7 @@ static struct jlink *jlink_usb_open()
        /* reopen jlink after usb_reset
         * on win32 this may take a second or two to re-enumerate */
        int retval;
-       while ((retval = jtag_libusb_open(vids, pids, &devh)) != ERROR_OK) {
+       while ((retval = jtag_libusb_open(vids, pids, NULL, &devh)) != ERROR_OK) {
                usleep(1000);
                timeout--;
                if (!timeout)
index 16dd4ecba6323af6f119060cb77effd4eff9ab26..b44b7861b7b70f20747430d453a5eaded02d8764 100644 (file)
@@ -37,9 +37,40 @@ static bool jtag_libusb_match(struct jtag_libusb_device *dev,
        return false;
 }
 
+/* Returns true if the string descriptor indexed by str_index in device matches string */
+static bool string_descriptor_equal(usb_dev_handle *device, uint8_t str_index,
+                                                                       const char *string)
+{
+       int retval;
+       bool matched;
+       char desc_string[256+1]; /* Max size of string descriptor */
+
+       if (str_index == 0)
+               return false;
+
+       retval = usb_get_string_simple(device, str_index,
+                       desc_string, sizeof(desc_string)-1);
+       if (retval < 0) {
+               LOG_ERROR("usb_get_string_simple() failed with %d", retval);
+               return false;
+       }
+
+       /* Null terminate descriptor string in case it needs to be logged. */
+       desc_string[sizeof(desc_string)-1] = '\0';
+
+       matched = strncmp(string, desc_string, sizeof(desc_string)) == 0;
+       if (!matched)
+               LOG_DEBUG("Device serial number '%s' doesn't match requested serial '%s'",
+                       desc_string, string);
+       return matched;
+}
+
 int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
+               const char *serial,
                struct jtag_libusb_device_handle **out)
 {
+       int retval = -ENODEV;
+       struct jtag_libusb_device_handle *libusb_handle;
        usb_init();
 
        usb_find_busses();
@@ -52,13 +83,24 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
                        if (!jtag_libusb_match(dev, vids, pids))
                                continue;
 
-                       *out = usb_open(dev);
-                       if (NULL == *out)
-                               return -errno;
-                       return 0;
+                       libusb_handle = usb_open(dev);
+                       if (NULL == libusb_handle) {
+                               retval = -errno;
+                               continue;
+                       }
+
+                       /* Device must be open to use libusb_get_string_descriptor_ascii. */
+                       if (serial != NULL &&
+                                       !string_descriptor_equal(libusb_handle, dev->descriptor.iSerialNumber, serial)) {
+                               usb_close(libusb_handle);
+                               continue;
+                       }
+                       *out = libusb_handle;
+                       retval = 0;
+                       break;
                }
        }
-       return -ENODEV;
+       return retval;
 }
 
 void jtag_libusb_close(jtag_libusb_device_handle *dev)
index db247ad850d31d873561124ebeee59e051376a00..370954fd377528d3f9a10517355439e5cb5b4370 100644 (file)
@@ -54,6 +54,7 @@ static inline int jtag_libusb_release_interface(jtag_libusb_device_handle *devh,
 }
 
 int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
+               const char *serial,
                struct jtag_libusb_device_handle **out);
 void jtag_libusb_close(jtag_libusb_device_handle *dev);
 int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev,
index 99e0d48268da8f8612e33b75a7eb0860559ed5be..a29b2e9105e56eaf51f645cc2ac515d2f204384f 100644 (file)
 static struct libusb_context *jtag_libusb_context; /**< Libusb context **/
 static libusb_device **devs; /**< The usb device list **/
 
-static bool jtag_libusb_match(struct jtag_libusb_device *dev,
+static bool jtag_libusb_match(struct libusb_device_descriptor *dev_desc,
                const uint16_t vids[], const uint16_t pids[])
 {
-       struct libusb_device_descriptor dev_desc;
-
        for (unsigned i = 0; vids[i]; i++) {
-               if (libusb_get_device_descriptor(dev, &dev_desc) == 0) {
-                       if (dev_desc.idVendor == vids[i] &&
-                               dev_desc.idProduct == pids[i])
-                               return true;
+               if (dev_desc->idVendor == vids[i] &&
+                       dev_desc->idProduct == pids[i]) {
+                       return true;
                }
        }
        return false;
 }
 
+/* Returns true if the string descriptor indexed by str_index in device matches string */
+static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_index,
+                                                                       const char *string)
+{
+       int retval;
+       bool matched;
+       char desc_string[256+1]; /* Max size of string descriptor */
+
+       if (str_index == 0)
+               return false;
+
+       retval = libusb_get_string_descriptor_ascii(device, str_index,
+                       (unsigned char *)desc_string, sizeof(desc_string)-1);
+       if (retval < 0) {
+               LOG_ERROR("libusb_get_string_descriptor_ascii() failed with %d", retval);
+               return false;
+       }
+
+       /* Null terminate descriptor string in case it needs to be logged. */
+       desc_string[sizeof(desc_string)-1] = '\0';
+
+       matched = strncmp(string, desc_string, sizeof(desc_string)) == 0;
+       if (!matched)
+               LOG_DEBUG("Device serial number '%s' doesn't match requested serial '%s'",
+                       desc_string, string);
+       return matched;
+}
+
 int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
+               const char *serial,
                struct jtag_libusb_device_handle **out)
 {
        int cnt, idx, errCode;
+       int retval = -ENODEV;
+       struct jtag_libusb_device_handle *libusb_handle = NULL;
 
        if (libusb_init(&jtag_libusb_context) < 0)
                return -ENODEV;
@@ -54,22 +82,37 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
        cnt = libusb_get_device_list(jtag_libusb_context, &devs);
 
        for (idx = 0; idx < cnt; idx++) {
-               if (!jtag_libusb_match(devs[idx], vids, pids))
+               struct libusb_device_descriptor dev_desc;
+
+               if (libusb_get_device_descriptor(devs[idx], &dev_desc) != 0)
                        continue;
 
-               errCode = libusb_open(devs[idx], out);
+               if (!jtag_libusb_match(&dev_desc, vids, pids))
+                       continue;
 
-               /** Free the device list **/
-               libusb_free_device_list(devs, 1);
+               errCode = libusb_open(devs[idx], &libusb_handle);
 
                if (errCode) {
                        LOG_ERROR("libusb_open() failed with %s",
                                  libusb_error_name(errCode));
-                       return errCode;
+                       continue;
+               }
+
+               /* Device must be open to use libusb_get_string_descriptor_ascii. */
+               if (serial != NULL &&
+                               !string_descriptor_equal(libusb_handle, dev_desc.iSerialNumber, serial)) {
+                       libusb_close(libusb_handle);
+                       continue;
                }
-               return 0;
+
+               /* Success. */
+               *out = libusb_handle;
+               retval = 0;
+               break;
        }
-       return -ENODEV;
+       if (cnt >= 0)
+               libusb_free_device_list(devs, 1);
+       return retval;
 }
 
 void jtag_libusb_close(jtag_libusb_device_handle *dev)
index e33b83ad844c5b986e398875b3c5dbfbf503e572..a4447ca9baec3bb3103af8e421ed9ec9879d2cff 100644 (file)
@@ -48,6 +48,7 @@ static inline int jtag_libusb_release_interface(jtag_libusb_device_handle *devh,
 }
 
 int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
+               const char *serial,
                struct jtag_libusb_device_handle **out);
 void jtag_libusb_close(jtag_libusb_device_handle *dev);
 int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev,
index 8bfaf0d9973a79b1b9899ec3b67636b217acf441..6af3b28f489209fee1aa3420a210c71abbe0288f 100644 (file)
@@ -709,7 +709,7 @@ struct opendous_jtag *opendous_usb_open(void)
        struct opendous_jtag *result;
 
        struct jtag_libusb_device_handle *devh;
-       if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, &devh) != ERROR_OK)
+       if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh) != ERROR_OK)
                return NULL;
 
        jtag_libusb_set_configuration(devh, 0);
index db9c29f245ce337d4c4c04850e6ce6934fa1c13e..d1eeedb3377564907d9d04664d2cd00c32b268c0 100644 (file)
@@ -375,7 +375,7 @@ static int osbdm_flush(struct osbdm *osbdm, struct queue* queue)
 static int osbdm_open(struct osbdm *osbdm)
 {
        (void)memset(osbdm, 0, sizeof(*osbdm));
-       if (jtag_libusb_open(osbdm_vid, osbdm_pid, &osbdm->devh) != ERROR_OK)
+       if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh) != ERROR_OK)
                return ERROR_FAIL;
 
        if (jtag_libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
index bd970ab4e7dc991cfa62706cf809022d7a2fe555..58af0dd59c42e693883ce30a4fa1eae9e9cf1266 100644 (file)
@@ -1600,9 +1600,11 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
 
        const uint16_t vids[] = { param->vid, 0 };
        const uint16_t pids[] = { param->pid, 0 };
+       const char *serial = param->serial;
 
-       LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x", param->transport,
-               param->vid, param->pid);
+       LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s",
+                       param->transport, param->vid, param->pid,
+                       param->serial ? param->serial : "");
 
        /*
          On certain host USB configurations(e.g. MacBook Air)
@@ -1614,7 +1616,7 @@ static int stlink_usb_open(struct hl_interface_param_s *param, void **fd)
          in order to become operational.
         */
        do {
-               if (jtag_libusb_open(vids, pids, &h->fd) != ERROR_OK) {
+               if (jtag_libusb_open(vids, pids, serial, &h->fd) != ERROR_OK) {
                        LOG_ERROR("open failed");
                        goto error_open;
                }
index 437150d752d3b6814ec399329aad6fd5c42435b1..70dab20d58a3561108a33ece50bb597257c366eb 100644 (file)
@@ -186,7 +186,7 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
        bool renumeration = false;
        int ret;
 
-       if (jtag_libusb_open(vids, pids, &temp) == ERROR_OK) {
+       if (jtag_libusb_open(vids, pids, NULL, &temp) == ERROR_OK) {
                LOG_INFO("Altera USB-Blaster II (uninitialized) found");
                LOG_INFO("Loading firmware...");
                ret = load_usb_blaster_firmware(temp, low);
@@ -200,13 +200,13 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
        const uint16_t pids_renum[] = { low->ublast_pid, 0 };
 
        if (renumeration == false) {
-               if (jtag_libusb_open(vids_renum, pids_renum, &low->libusb_dev) != ERROR_OK) {
+               if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK) {
                        LOG_ERROR("Altera USB-Blaster II not found");
                        return ERROR_FAIL;
                }
        } else {
                int retry = 10;
-               while (jtag_libusb_open(vids_renum, pids_renum, &low->libusb_dev) != ERROR_OK && retry--) {
+               while (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK && retry--) {
                        usleep(1000000);
                        LOG_INFO("Waiting for renumerate...");
                }
index e1bccbc26b3d43f8436c6deb0fe20160f374dc9c..093e80177078667dbc03e166ac5d7e997086b4f2 100644 (file)
@@ -7,3 +7,10 @@ hla_layout stlink
 hla_device_desc "ST-LINK/V2-1"
 hla_vid_pid 0x0483 0x374b
 
+# Optionally specify the serial number of ST-LINK/V2 usb device.  ST-LINK/V2
+# devices seem to have serial numbers with unreadable characters.  ST-LINK/V2
+# firmware version >= V2.J21.S4 recommended to avoid issues with adapter serial
+# number reset issues.
+# eg.
+#hla_serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f"
+
index e145d6353f5886727f1e5669d3cba121bfdd9e01..ae545a1187762bbdbb80e24913dbe746421310f5 100644 (file)
@@ -7,3 +7,10 @@ hla_layout stlink
 hla_device_desc "ST-LINK/V2"
 hla_vid_pid 0x0483 0x3748
 
+# Optionally specify the serial number of ST-LINK/V2 usb device.  ST-LINK/V2
+# devices seem to have serial numbers with unreadable characters.  ST-LINK/V2
+# firmware version >= V2.J21.S4 recommended to avoid issues with adapter serial
+# number reset issues.
+# eg.
+#hla_serial "\xaa\xbc\x6e\x06\x50\x75\xff\x55\x17\x42\x19\x3f"
+

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)