This is an automated email from Gerrit.

"Erhan Kurubas <erhan.kuru...@espressif.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7079

-- gerrit

commit d3b717bb6a5b6eb932cecdc38c15d51e1ae3aa34
Author: Erhan Kurubas <erhan.kuru...@espressif.com>
Date:   Tue Jul 5 00:14:09 2022 +0300

    esp_usb_jtag: device reinit after bulk write error
    
    Reinit sequence(reset + init) will be needed when external reset
    is asserted or when the usb cable is unplugged/replugged.
    
    Signed-off-by: Erhan Kurubas <erhan.kuru...@espressif.com>
    Change-Id: I20e66bf186939afe4098f80a62ad6c1b9f88f5fe

diff --git a/src/jtag/drivers/esp_usb_jtag.c b/src/jtag/drivers/esp_usb_jtag.c
index a73984a3a1..78d361eb77 100644
--- a/src/jtag/drivers/esp_usb_jtag.c
+++ b/src/jtag/drivers/esp_usb_jtag.c
@@ -197,7 +197,14 @@ struct jtag_proto_caps_speed_apb {
  *to be read, we have multiple buffers to store those before the bitq 
interface reads them out. */
 #define IN_BUF_CT 8
 
-#define ESP_USB_INTERFACE       1
+/*
+ * comment from libusb:
+ * As per the USB 3.0 specs, the current maximum limit for the depth is 7.
+ */
+#define MAX_USB_PORTS                   7
+#define ESP_USB_JTAG_RST_DELAY          100000 /* us */
+
+#define ESP_USB_INTERFACE               1
 
 /* Private data */
 struct esp_usb_jtag {
@@ -231,6 +238,7 @@ struct esp_usb_jtag {
  * OpenOCD supports multiple JTAG adapters anyway. */
 static struct esp_usb_jtag esp_usb_jtag_priv;
 static struct esp_usb_jtag *priv = &esp_usb_jtag_priv;
+static const char *esp_usb_jtag_serial;
 
 static int esp_usb_vid;
 static int esp_usb_pid;
@@ -240,13 +248,99 @@ static int esp_usb_target_chip_id;
 static int esp_usb_jtag_init(void);
 static int esp_usb_jtag_quit(void);
 
+static bool esp_usb_jtag_libusb_location_equal(libusb_device *dev1, 
libusb_device *dev2)
+{
+       if (libusb_get_bus_number(dev1) != libusb_get_bus_number(dev2))
+               return false;
+
+#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
+       uint8_t port_path1[MAX_USB_PORTS], port_path2[MAX_USB_PORTS];
+
+       int path_len1 = libusb_get_port_numbers(dev1, port_path1, 
MAX_USB_PORTS);
+       if (path_len1 == LIBUSB_ERROR_OVERFLOW) {
+               LOG_WARNING("cannot determine path to usb device! (more than %i 
ports in path)\n",
+                       MAX_USB_PORTS);
+               return false;
+       }
+
+       int path_len2 = libusb_get_port_numbers(dev2, port_path2, 
MAX_USB_PORTS);
+       if (path_len2 == LIBUSB_ERROR_OVERFLOW) {
+               LOG_WARNING("cannot determine path to usb device! (more than %i 
ports in path)\n",
+                       MAX_USB_PORTS);
+               return false;
+       }
+
+       if (path_len1 != path_len2)
+               return false;
+
+       for (int i = 0; i < path_len1; i++) {
+               if (port_path1[i] != port_path2[i])
+                       return false;
+       }
+#endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */
+
+       if (libusb_get_device_address(dev1) != libusb_get_device_address(dev2))
+               return false;
+       return true;
+}
+
+static int esp_usb_jtag_reinit_device(struct libusb_device_handle *usb_device)
+{
+       const uint16_t vids[] = { esp_usb_vid, 0 };             /* must be null 
terminated */
+       const uint16_t pids[] = { esp_usb_pid, 0 };             /* must be null 
terminated */
+       libusb_device *cur_dev = libusb_get_device(usb_device);
+       libusb_device *new_dev = NULL;
+       int ret, tries = 5;
+
+       while (tries-- >= 0) {
+               new_dev = jtag_libusb_find_device(vids, pids, 
esp_usb_jtag_serial);
+               if (new_dev) {
+                       if (esp_usb_jtag_libusb_location_equal(cur_dev, 
new_dev)) {
+                               /* device is still at the same location on bus 
and with the same address, try to reset it */
+                               int rc = libusb_reset_device(usb_device);
+                               if (rc == LIBUSB_ERROR_NOT_FOUND || rc == 
LIBUSB_ERROR_NO_DEVICE) {
+                                       /* re-enumeration is necessary */
+                                       break;
+                               }
+                               libusb_unref_device(new_dev);
+                               return rc == 0 ? ERROR_OK : ERROR_WAIT;
+                       }
+                       break;
+               }
+               jtag_sleep(ESP_USB_JTAG_RST_DELAY);
+       }
+       if (!new_dev) {
+               LOG_ERROR("esp_usb_jtag: device not found!");
+               return ERROR_FAIL;
+       }
+       libusb_unref_device(new_dev);
+       ret = esp_usb_jtag_quit();
+       if (ret != ERROR_OK) {
+               LOG_ERROR("esp_usb_jtag: failed to deinit (%d)", ret);
+               return ret;
+       }
+       tries = 5;
+       while (tries-- >= 0) {
+               ret = esp_usb_jtag_init();
+               if (ret == ERROR_OK)
+                       break;
+               jtag_sleep(ESP_USB_JTAG_RST_DELAY);
+       }
+       if (ret != ERROR_OK) {
+               LOG_ERROR("esp_usb_jtag: failed to init (%d)", ret);
+               return ret;
+       }
+       return ERROR_OK;
+}
+
 /* Try to receive from USB endpoint into the current priv->in_buf */
 static int esp_usb_jtag_recv_buf(void)
 {
-       if (priv->in_buf_size_bits[priv->cur_in_buf_wr] != 0)
+       if (priv->in_buf_size_bits[priv->cur_in_buf_wr] != 0) {
                LOG_ERROR("esp_usb_jtag: IN buffer overflow! (%d, size %d)",
                        priv->cur_in_buf_wr,
                        priv->in_buf_size_bits[priv->cur_in_buf_wr]);
+       }
 
        unsigned int recvd = 0, ct = (priv->pending_in_bits + 7) / 8;
        if (ct > IN_BUF_SZ)
@@ -313,8 +407,12 @@ static int esp_usb_jtag_send_buf(void)
                                written + tr,
                                ct);
                }
-               if (ret != ERROR_OK)
+               if (ret != ERROR_OK) {
+                       int reset_ret = 
esp_usb_jtag_reinit_device(priv->usb_device);
+                       if (reset_ret != ERROR_OK)
+                               LOG_ERROR("esp_usb_jtag: failed to reinit USB 
device!");
                        return ret;
+               }
                written += tr;
        }
        priv->out_buf_pos_nibbles = 0;
@@ -507,6 +605,19 @@ static int esp_usb_jtag_init(void)
                goto out;
        }
 
+       /* serial number may have been set by `adapter serial` command */
+       if (adapter_get_required_serial()) {
+               free((void *)esp_usb_jtag_serial);
+               esp_usb_jtag_serial = strdup(adapter_get_required_serial());
+       }
+
+       if (!esp_usb_jtag_serial) {
+               r = jtag_libusb_get_serial(priv->usb_device, 
&esp_usb_jtag_serial);
+               if (r != ERROR_OK)
+                       goto out;
+       }
+       LOG_INFO("esp_usb_jtag: serial (%s)", esp_usb_jtag_serial);
+
        jtag_libusb_set_configuration(priv->usb_device, USB_CONFIGURATION);
 
        r = jtag_libusb_choose_interface(priv->usb_device, &priv->read_ep, 
&priv->write_ep,
@@ -599,6 +710,8 @@ static int esp_usb_jtag_init(void)
        return ERROR_OK;
 
 out:
+       free((void *)esp_usb_jtag_serial);
+       esp_usb_jtag_serial = NULL;
        if (priv->usb_device)
                jtag_libusb_close(priv->usb_device);
        bitq_interface = NULL;
@@ -608,6 +721,8 @@ out:
 
 static int esp_usb_jtag_quit(void)
 {
+       free((void *)esp_usb_jtag_serial);
+       esp_usb_jtag_serial = NULL;
        if (!priv->usb_device)
                return ERROR_OK;
        jtag_libusb_close(priv->usb_device);

-- 

Reply via email to