This is an automated email from Gerrit.

Tarek BOCHKATI ([email protected]) just uploaded a new patch set to 
Gerrit, which you can find at http://openocd.zylin.com/5396

-- gerrit

commit e3bc027a1f4c260a887922aa7d0b50ed73ae6ac6
Author: Tarek BOCHKATI <[email protected]>
Date:   Mon Jan 13 16:24:50 2020 +0100

    jtag/libusb1_common: workarround serial issue with old ST-Link DFU
    
    Old ST-Link DFU returns 12 x 8-bits values as serial, separated by zeros
    which is a wrong unicode encoding, so the serial descriptor length will be 
26
    in that case the useful values are in desc_serial [2], [4] ...
    
    Otherwise compute_stlink_serial will behave like
    libusb_get_string_descriptor_ascii
    
    example for an old ST-LINK/V2 standalone:
      before : 'W?rreWWB g'
      after  : '57FF72067265575742132067'
      => same as the displayed value in STM32CubeProgrammer
    
    note: string_descriptor_equal is kept intentionally
    
    Change-Id: I1213818257663eeb8e76f419087d3127d0524842
    Signed-off-by: Tarek BOCHKATI <[email protected]>

diff --git a/src/jtag/drivers/libusb1_common.c 
b/src/jtag/drivers/libusb1_common.c
index d96ac76..7097600 100644
--- a/src/jtag/drivers/libusb1_common.c
+++ b/src/jtag/drivers/libusb1_common.c
@@ -33,7 +33,7 @@
 static struct libusb_context *jtag_libusb_context; /**< Libusb context **/
 static libusb_device **devs; /**< The usb device list **/
 
-static bool jtag_libusb_match(struct libusb_device_descriptor *dev_desc,
+static bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc,
                const uint16_t vids[], const uint16_t pids[])
 {
        for (unsigned i = 0; vids[i]; i++) {
@@ -98,6 +98,72 @@ static bool string_descriptor_equal(libusb_device_handle 
*device, uint8_t str_in
        return matched;
 }
 
+/*
+ * Compute ST-Link serial number from the device descriptor
+ * "old" ST-Link DFU returns 12 8-bits values, separated by zeros (wrong 
unicode encoding)
+ */
+
+static int stlink_compute_serial(unsigned char *desc_serial, char *serial)
+{
+       int i, len = desc_serial[0];
+
+       if (len == 26) /* work-around for old ST-Links*/
+               for (i = 0; i < 12; i++)
+                       sprintf((char *) &(serial[i*2]), "%02hX", (unsigned 
short) desc_serial[2 * (i+1)]);
+       else if (len == 50)
+               for (i = 0; i < 24; i++)
+                       serial[i] = desc_serial[2 * (i + 1)];
+       else {
+               LOG_ERROR("unexpected serial length (%d) in descriptor", len);
+               return ERROR_FAIL;
+       }
+
+       serial[24] = '\0';
+
+       return ERROR_OK;
+}
+
+/* Returns true if the serial in the descriptor matches the given serial */
+static bool jtag_libusb_match_serial(libusb_device_handle *device,
+               struct libusb_device_descriptor *dev_desc, const char 
*user_serial)
+{
+       int retval;
+       bool matched;
+       char device_serial[256+1]; /* Max size of string descriptor */
+
+       if (dev_desc->iSerialNumber == 0)
+               return false;
+
+       if (dev_desc->idVendor == 0x0483) { /* work around for ST-Link adapter 
*/
+               char device_desc_serial[256+1];
+               retval = libusb_get_string_descriptor(device, 
dev_desc->iSerialNumber, 0x409,
+                                       (unsigned char *)device_desc_serial, 
64);
+               if (retval < 0) {
+                       LOG_ERROR("libusb_get_string_descriptor() failed with 
%d", retval);
+                       return false;
+               }
+               if (stlink_compute_serial((unsigned char *)device_desc_serial, 
device_serial) != ERROR_OK)
+                       return false;
+       } else {
+               retval = libusb_get_string_descriptor_ascii(device, 
dev_desc->iSerialNumber,
+                                       (unsigned char *)device_serial, 
sizeof(device_serial)-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. */
+       device_serial[sizeof(device_serial)-1] = '\0';
+
+       matched = strncmp(user_serial, device_serial, sizeof(device_serial)) == 
0;
+       if (!matched)
+               LOG_DEBUG("Device serial number '%s' doesn't match requested 
serial '%s'",
+                       device_serial, user_serial);
+
+       return matched;
+}
+
 int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
                const char *serial,
                struct jtag_libusb_device_handle **out)
@@ -118,7 +184,7 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t 
pids[],
                if (libusb_get_device_descriptor(devs[idx], &dev_desc) != 0)
                        continue;
 
-               if (!jtag_libusb_match(&dev_desc, vids, pids))
+               if (!jtag_libusb_match_ids(&dev_desc, vids, pids))
                        continue;
 
                if (jtag_usb_get_location() && 
!jtag_libusb_location_equal(devs[idx]))
@@ -133,8 +199,7 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t 
pids[],
                }
 
                /* Device must be open to use 
libusb_get_string_descriptor_ascii. */
-               if (serial != NULL &&
-                               !string_descriptor_equal(libusb_handle, 
dev_desc.iSerialNumber, serial)) {
+               if (serial != NULL && !jtag_libusb_match_serial(libusb_handle, 
&dev_desc, serial)) {
                        serial_mismatch = true;
                        libusb_close(libusb_handle);
                        continue;

-- 


_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to