- added support for error handlers to JTAG scan commands (jtag_[plain_][ir|dr]_scan)
[openocd.git] / src / jtag / ft2232.c
index 096111bc8e0fbcc123c41db7c7a93d290089d466..75faf38d052ebe75d2aaf050af01ea69563de831 100644 (file)
 
 /* enable this to debug io latency
  */
-#if 1
+#if 0
 #define _DEBUG_USB_IO_
 #endif
 
 /* enable this to debug communication
  */
-#if 1
+#if 0
 #define _DEBUG_USB_COMMS_
 #endif
 
@@ -77,8 +77,11 @@ int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd,
 char *ft2232_device_desc = NULL;
 char *ft2232_serial = NULL;
 char *ft2232_layout = NULL;
-u16 ft2232_vid = 0x0403;
-u16 ft2232_pid = 0x6010;
+
+#define MAX_USB_IDS    8
+/* vid = pid = 0 marks the end of the list */
+static u16 ft2232_vid[MAX_USB_IDS+1] = { 0x0403, 0 };
+static u16 ft2232_pid[MAX_USB_IDS+1] = { 0x6010, 0 };
 
 typedef struct ft2232_layout_s
 {
@@ -93,15 +96,18 @@ int usbjtag_init(void);
 int jtagkey_init(void);
 int olimex_jtag_init(void);
 int m5960_init(void);
+int turtle_init(void);
 
 /* reset procedures for supported layouts */
 void usbjtag_reset(int trst, int srst);
 void jtagkey_reset(int trst, int srst);
 void olimex_jtag_reset(int trst, int srst);
 void m5960_reset(int trst, int srst);
+void turtle_reset(int trst, int srst);
 
 /* blink procedures for layouts that support a blinking led */
 void olimex_jtag_blink(void);
+void turtle_jtag_blink(void);
 
 ft2232_layout_t ft2232_layouts[] =
 {
@@ -113,6 +119,7 @@ ft2232_layout_t ft2232_layouts[] =
        {"evb_lm3s811", usbjtag_init, usbjtag_reset, NULL},
        {"olimex-jtag", olimex_jtag_init, olimex_jtag_reset, olimex_jtag_blink},
        {"m5960", m5960_init, m5960_reset, NULL},
+        {"turtelizer2", turtle_init, turtle_reset, turtle_jtag_blink},
        {NULL, NULL, NULL},
 };
 
@@ -161,7 +168,7 @@ int ft2232_write(u8 *buf, int size, u32* bytes_written)
        if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK)
        {
                *bytes_written = dw_bytes_written;
-               ERROR("FT_Write returned: %i", status);
+               ERROR("FT_Write returned: %lu", status);
                return ERROR_JTAG_DEVICE_ERROR;
        }
        else
@@ -198,7 +205,7 @@ int ft2232_read(u8* buf, int size, u32* bytes_read)
                if ((status = FT_Read(ftdih, buf, size, &dw_bytes_read)) != FT_OK)
                {
                        *bytes_read = 0; 
-                       ERROR("FT_Read returned: %i", status);
+                       ERROR("FT_Read returned: %lu", status);
                        return ERROR_JTAG_DEVICE_ERROR;
                }
                *bytes_read += dw_bytes_read; 
@@ -395,7 +402,12 @@ int ft2232_send_and_recv(jtag_command_t *first, jtag_command_t *last)
 
        ft2232_expect_read = 0;
        ft2232_read_pointer = 0;
-
+       
+       /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
+        * that wasn't handled by a caller-provided error handler
+        */ 
+       retval = ERROR_OK;
+       
        cmd = first;
        while (cmd != last)
        {
@@ -408,7 +420,8 @@ int ft2232_send_and_recv(jtag_command_t *first, jtag_command_t *last)
                                        scan_size = jtag_scan_size(cmd->cmd.scan);
                                        buffer = calloc(CEIL(scan_size, 8), 1);
                                        ft2232_read_scan(type, buffer, scan_size);
-                                       jtag_read_buffer(buffer, cmd->cmd.scan);
+                                       if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
                                        free(buffer);
                                }
                                break;
@@ -420,7 +433,7 @@ int ft2232_send_and_recv(jtag_command_t *first, jtag_command_t *last)
        
        ft2232_buffer_size = 0;
 
-       return ERROR_OK;
+       return retval;
 }
 
 void ft2232_add_pathmove(pathmove_command_t *cmd)
@@ -1002,6 +1015,26 @@ void m5960_reset(int trst, int srst)
     DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);
 }
 
+void turtle_reset(int trst, int srst)
+{
+  trst = trst;
+  
+       if (srst == 1)
+       {
+       low_output |= nSRST;
+       }
+       else if (srst == 0)
+       {
+               low_output &= ~nSRST;
+       }
+       
+       /* command "set data bits high byte" */
+       BUFFER_ADD = 0x80;
+       BUFFER_ADD = low_output;
+       BUFFER_ADD = low_direction;
+       DEBUG("srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", srst, low_output, low_direction);
+}
+
 int ft2232_execute_queue()
 {
        jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
@@ -1012,6 +1045,12 @@ int ft2232_execute_queue()
        int i;
        int predicted_size = 0;
        int require_send = 0;
+       int retval;
+       
+       /* return ERROR_OK, unless ft2232_send_and_recv reports a failed check
+        * that wasn't handled by a caller-provided error handler
+        */ 
+       retval = ERROR_OK;
 
        ft2232_buffer_size = 0;
        ft2232_expect_read = 0;
@@ -1033,7 +1072,8 @@ int ft2232_execute_queue()
                                predicted_size = 3;
                                if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
                                {
-                                       ft2232_send_and_recv(first_unsent, cmd);
+                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
                                        require_send = 0;
                                        first_unsent = cmd;
                                }
@@ -1057,7 +1097,8 @@ int ft2232_execute_queue()
                                        predicted_size += 3;
                                if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
                                {
-                                       ft2232_send_and_recv(first_unsent, cmd);
+                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
                                        require_send = 0;
                                        first_unsent = cmd;
                                }
@@ -1108,7 +1149,8 @@ int ft2232_execute_queue()
                                predicted_size = 3;
                                if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
                                {
-                                       ft2232_send_and_recv(first_unsent, cmd);
+                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
                                        require_send = 0;
                                        first_unsent = cmd;
                                }
@@ -1132,7 +1174,8 @@ int ft2232_execute_queue()
                                predicted_size = 3 * CEIL(cmd->cmd.pathmove->num_states, 7);
                                if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
                                {
-                                       ft2232_send_and_recv(first_unsent, cmd);
+                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
                                        require_send = 0;
                                        first_unsent = cmd;
                                }
@@ -1151,7 +1194,8 @@ int ft2232_execute_queue()
                                        DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)");
                                        /* unsent commands before this */
                                        if (first_unsent != cmd)
-                                               ft2232_send_and_recv(first_unsent, cmd);
+                                               if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                                       retval = ERROR_JTAG_QUEUE_FAILED;
                                        
                                        /* current command */
                                        if (cmd->cmd.scan->end_state != -1)
@@ -1165,8 +1209,9 @@ int ft2232_execute_queue()
                                }
                                else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
                                {
-                                       DEBUG("ft2232 buffer size reached, sending queued commands (first_unsent: %x, cmd: %x)", first_unsent, cmd);
-                                       ft2232_send_and_recv(first_unsent, cmd);
+                                       DEBUG("ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p)", first_unsent, cmd);
+                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
                                        require_send = 0;
                                        first_unsent = cmd;
                                }
@@ -1183,7 +1228,8 @@ int ft2232_execute_queue()
 #endif
                                break;
                        case JTAG_SLEEP:
-                               ft2232_send_and_recv(first_unsent, cmd);
+                               if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                       retval = ERROR_JTAG_QUEUE_FAILED;
                                first_unsent = cmd->next;
                                jtag_sleep(cmd->cmd.sleep->us);
 #ifdef _DEBUG_JTAG_IO_                         
@@ -1198,60 +1244,29 @@ int ft2232_execute_queue()
        }
 
        if (require_send > 0)
-               ft2232_send_and_recv(first_unsent, cmd);
+               if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                       retval = ERROR_JTAG_QUEUE_FAILED;
 
-       return ERROR_OK;
+       return retval;
 }
 
-int ft2232_init(void)
-{
-       u8 latency_timer;
-       u8 buf[1];
-       int retval;
-       u32 bytes_written;
-       
 #if BUILD_FT2232_FTD2XX == 1
+static int ft2232_init_ftd2xx(u16 vid, u16 pid, int more, int *try_more)
+{
        FT_STATUS status;
        DWORD openex_flags = 0;
        char *openex_string = NULL;
-#endif
+       u8 latency_timer;
 
-       ft2232_layout_t *cur_layout = ft2232_layouts;
-       
-       if ((ft2232_layout == NULL) || (ft2232_layout[0] == 0))
-       {
-               ft2232_layout = "usbjtag";
-               WARNING("No ft2232 layout specified, using default 'usbjtag'");
-       }
-       
-       while (cur_layout->name)
-       {
-               if (strcmp(cur_layout->name, ft2232_layout) == 0)
-               {
-                       layout = cur_layout;
-                       break;
-               }
-               cur_layout++;
-       }
+       DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)",
+           ft2232_layout, vid, pid);
 
-       if (!layout)
-       {
-               ERROR("No matching layout found for %s", ft2232_layout);
-               return ERROR_JTAG_INIT_FAILED;
-       }
-       
-#if BUILD_FT2232_FTD2XX == 1
-       DEBUG("'ft2232' interface using FTD2XX with '%s' layout", ft2232_layout);
-#elif BUILD_FT2232_LIBFTDI == 1
-       DEBUG("'ft2232' interface using libftdi with '%s' layout", ft2232_layout);
-#endif
-
-#if BUILD_FT2232_FTD2XX == 1
 #if IS_WIN32 == 0
        /* Add non-standard Vid/Pid to the linux driver */
-       if ((status = FT_SetVIDPID(ft2232_vid, ft2232_pid)) != FT_OK)
+       if ((status = FT_SetVIDPID(vid, pid)) != FT_OK)
        {
-               WARNING("couldn't add %4.4x:%4.4x", ft2232_vid, ft2232_pid);
+               WARNING("couldn't add %4.4x:%4.4x",
+                   vid, pid);
        }
 #endif
 
@@ -1283,7 +1298,13 @@ int ft2232_init(void)
        {
                DWORD num_devices;
                
-               ERROR("unable to open ftdi device: %i", status);
+               if (more) {
+                       WARNING("unable to open ftdi device (trying more): %lu",
+                           status);
+                       *try_more = 1;
+                       return ERROR_JTAG_INIT_FAILED;
+               }
+               ERROR("unable to open ftdi device: %lu", status);
                status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY);
                if (status == FT_OK)
                {
@@ -1298,7 +1319,7 @@ int ft2232_init(void)
 
                        if (status == FT_OK)
                        {
-                               ERROR("ListDevices: %d\n", num_devices);
+                               ERROR("ListDevices: %lu\n", num_devices);
                                for (i = 0; i < num_devices; i++)
                                        ERROR("%i: %s", i, desc_array[i]);
                        }
@@ -1316,13 +1337,13 @@ int ft2232_init(void)
 
        if ((status = FT_SetLatencyTimer(ftdih, 2)) != FT_OK)
        {
-               ERROR("unable to set latency timer: %i", status);
+               ERROR("unable to set latency timer: %lu", status);
                return ERROR_JTAG_INIT_FAILED;
        }
        
        if ((status = FT_GetLatencyTimer(ftdih, &latency_timer)) != FT_OK)
        {
-               ERROR("unable to get latency timer: %i", status);
+               ERROR("unable to get latency timer: %lu", status);
                return ERROR_JTAG_INIT_FAILED;
        }
        else
@@ -1332,23 +1353,59 @@ int ft2232_init(void)
        
        if ((status = FT_SetTimeouts(ftdih, 5000, 5000)) != FT_OK)
        {
-               ERROR("unable to set timeouts: %i", status);
+               ERROR("unable to set timeouts: %lu", status);
                return ERROR_JTAG_INIT_FAILED;
        }
 
        if ((status = FT_SetBitMode(ftdih, 0x0b, 2)) != FT_OK)
        {
-               ERROR("unable to enable bit i/o mode: %i", status);
+               ERROR("unable to enable bit i/o mode: %lu", status);
                return ERROR_JTAG_INIT_FAILED;
        }
-#elif BUILD_FT2232_LIBFTDI == 1
+
+       return ERROR_OK;
+}
+
+static int ft2232_purge_ftd2xx(void)
+{
+       FT_STATUS status;
+
+       if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)
+       {
+               ERROR("error purging ftd2xx device: %lu", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ERROR_OK;
+}
+#endif /* BUILD_FT2232_FTD2XX == 1 */
+
+#if BUILD_FT2232_LIBFTDI == 1
+static int ft2232_init_libftdi(u16 vid, u16 pid, int more, int *try_more)
+{
+       u8 latency_timer;
+
+       DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)",
+           ft2232_layout, vid, pid);
+
        if (ftdi_init(&ftdic) < 0)
                return ERROR_JTAG_INIT_FAILED;
 
        /* context, vendor id, product id */
-       if (ftdi_usb_open(&ftdic, ft2232_vid, ft2232_pid) < 0)
+       if (ftdi_usb_open_desc(&ftdic, vid, pid, ft2232_device_desc,
+           ft2232_serial) < 0) {
+               if (more)
+                       WARNING("unable to open ftdi device (trying more): %s",
+                            ftdic.error_str);
+               else
+                       ERROR("unable to open ftdi device: %s", ftdic.error_str);
+               *try_more = 1;
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if (ftdi_set_interface(&ftdic, INTERFACE_A) < 0)
        {
-               ERROR("unable to open ftdi device: %s", ftdic.error_str);
+               ERROR("unable to select FT2232 channel A: %s", ftdic.error_str);
                return ERROR_JTAG_INIT_FAILED;
        }
 
@@ -1374,12 +1431,78 @@ int ft2232_init(void)
                DEBUG("current latency timer: %i", latency_timer);
        }
 
-       ftdic.bitbang_mode = 0; /* Reset controller */
-       ftdi_enable_bitbang(&ftdic, 0x0b); /* ctx, JTAG I/O mask */
+       ftdi_set_bitmode(&ftdic, 0x0b, 2); /* ctx, JTAG I/O mask */
+
+       return ERROR_OK;
+}
+
+static int ft2232_purge_libftdi(void)
+{
+       if (ftdi_usb_purge_buffers(&ftdic) < 0)
+       {
+               ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ERROR_OK;
+}
+#endif /* BUILD_FT2232_LIBFTDI == 1 */
 
-       ftdic.bitbang_mode = 2; /* MPSSE mode */
-       ftdi_enable_bitbang(&ftdic, 0x0b); /* ctx, JTAG I/O mask */
+int ft2232_init(void)
+{
+       u8 buf[1];
+       int retval;
+       u32 bytes_written;
+       ft2232_layout_t *cur_layout = ft2232_layouts;
+       int i;
+       
+       if ((ft2232_layout == NULL) || (ft2232_layout[0] == 0))
+       {
+               ft2232_layout = "usbjtag";
+               WARNING("No ft2232 layout specified, using default 'usbjtag'");
+       }
+       
+       while (cur_layout->name)
+       {
+               if (strcmp(cur_layout->name, ft2232_layout) == 0)
+               {
+                       layout = cur_layout;
+                       break;
+               }
+               cur_layout++;
+       }
+
+       if (!layout)
+       {
+               ERROR("No matching layout found for %s", ft2232_layout);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       for (i = 0; 1; i++) {
+               /*
+                * "more indicates that there are more IDs to try, so we should
+                * not print an error for an ID mismatch (but for anything
+                * else, we should).
+                *
+                * try_more indicates that the error code returned indicates an
+                * ID mismatch (and nothing else) and that we should proceeed
+                * with the next ID pair.
+                */
+               int more = ft2232_vid[i+1] || ft2232_pid[i+1];
+               int try_more = 0;
+
+#if BUILD_FT2232_FTD2XX == 1
+               retval = ft2232_init_ftd2xx(ft2232_vid[i], ft2232_pid[i],
+                   more, &try_more);
+#elif BUILD_FT2232_LIBFTDI == 1
+               retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i],
+                   more, &try_more);
 #endif 
+               if (retval >= 0)
+                       break;
+               if (!more || !try_more)
+                       return retval;
+       }
 
        ft2232_buffer_size = 0;
        ft2232_buffer = malloc(FT2232_BUFFER_SIZE);
@@ -1397,17 +1520,9 @@ int ft2232_init(void)
        }
 
 #if BUILD_FT2232_FTD2XX == 1
-       if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)
-       {
-               ERROR("error purging ftd2xx device: %i", status);
-               return ERROR_JTAG_INIT_FAILED;
-       }
+       return ft2232_purge_ftd2xx();
 #elif BUILD_FT2232_LIBFTDI == 1
-       if (ftdi_usb_purge_buffers(&ftdic) < 0)
-       {
-               ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
-               return ERROR_JTAG_INIT_FAILED;
-       }
+       return ft2232_purge_libftdi();
 #endif 
 
        return ERROR_OK;
@@ -1680,6 +1795,46 @@ int m5960_init(void)
        return ERROR_OK;
 }
 
+int turtle_init(void)
+{
+       u8 buf[3];
+       u32 bytes_written;
+       
+       low_output = 0x08;
+       low_direction = 0x5b;
+       
+       /* initialize low byte for jtag */
+       buf[0] = 0x80; /* command "set data bits low byte" */
+       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
+       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+  nSRST = 0x40;
+       
+       high_output = 0x00;
+       high_direction = 0x0C;
+       
+       /* initialize high port */
+       buf[0] = 0x82; /* command "set data bits high byte" */
+       buf[1] = high_output;
+       buf[2] = high_direction;
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       return ERROR_OK;
+}
+
 void olimex_jtag_blink(void)
 {
        /* Olimex ARM-USB-OCD has a LED connected to ACBUS3
@@ -1701,6 +1856,26 @@ void olimex_jtag_blink(void)
        BUFFER_ADD = high_direction;
 }
 
+void turtle_jtag_blink(void)
+{
+       /* 
+   * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3
+        */
+       if (high_output & 0x08)
+       {
+               high_output = 0x04;
+       }
+       else
+       {
+               high_output = 0x08;
+       }
+       
+       BUFFER_ADD = 0x82;
+       BUFFER_ADD = high_output;
+       BUFFER_ADD = high_direction;
+}
+
+
 int ft2232_quit(void)
 {
 #if BUILD_FT2232_FTD2XX == 1
@@ -1761,15 +1936,29 @@ int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, c
 
 int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       if (argc >= 2)
-       {
-               ft2232_vid = strtol(args[0], NULL, 0);
-               ft2232_pid = strtol(args[1], NULL, 0);
+       int i;
+
+       if (argc > MAX_USB_IDS*2) {
+               WARNING("ignoring extra IDs in ft2232_vid_pid "
+                   "(maximum is %d pairs)", MAX_USB_IDS);
+               argc = MAX_USB_IDS*2;
        }
-       else
+       if (argc < 2 || (argc & 1))
        {
                WARNING("incomplete ft2232_vid_pid configuration directive");
+               if (argc < 2)
+                       return ERROR_OK;
        }
-       
+
+       for (i = 0; i+1 < argc; i += 2) {
+               ft2232_vid[i >> 1] = strtol(args[i], NULL, 0);
+               ft2232_pid[i >> 1] = strtol(args[i+1], NULL, 0);
+       }
+       /*
+        * Explicitly terminate, in case there are multiples instances of
+        * ft2232_vid_pid.
+        */
+       ft2232_vid[i >> 1] = ft2232_pid[i >> 1] = 0;
+
        return ERROR_OK;
 }

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)