1 /***************************************************************************
3 * Copyright (C) 2009 by Cahya Wirawan <cahya@gmx.at> *
4 * Based on opendous driver by Vladimir Fonov *
6 * Copyright (C) 2009 by Vladimir Fonov <vladimir.fonov@gmai.com> *
7 * Based on J-link driver by Juergen Stuber *
9 * Copyright (C) 2007 by Juergen Stuber <juergen@jstuber.net> *
10 * based on Dominic Rath's and Benedikt Sauter's usbprog.c *
12 * Copyright (C) 2008 by Spencer Oliver *
13 * spen@spen-soft.co.uk *
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
20 * This program is distributed in the hope that it will be useful, *
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
23 * GNU General Public License for more details. *
25 * You should have received a copy of the GNU General Public License *
26 * along with this program; if not, write to the *
27 * Free Software Foundation, Inc., *
28 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
29 ***************************************************************************/
35 #include <jtag/interface.h>
36 #include <jtag/commands.h>
37 #include "libusb_common.h"
39 #include <sys/timeb.h>
42 #define ESTICK_VID 0x1781
43 #define ESTICK_PID 0xC0C0
45 #define OPENDOUS_VID 0x03EB
46 #define OPENDOUS_PID 0x204F
48 /* pid could be specified at runtime */
49 static uint16_t vids
[] = { OPENDOUS_VID
, ESTICK_VID
, 0 };
50 static uint16_t pids
[] = { OPENDOUS_PID
, ESTICK_PID
, 0 };
52 #define OPENDOUS_WRITE_ENDPOINT 0x02
53 #define OPENDOUS_READ_ENDPOINT 0x81
55 static unsigned int opendous_hw_jtag_version
= 1;
57 #define OPENDOUS_USB_TIMEOUT 1000
59 #define OPENDOUS_USB_BUFFER_SIZE 360
60 #define OPENDOUS_IN_BUFFER_SIZE (OPENDOUS_USB_BUFFER_SIZE)
61 #define OPENDOUS_OUT_BUFFER_SIZE (OPENDOUS_USB_BUFFER_SIZE)
63 /* Global USB buffers */
64 static uint8_t usb_in_buffer
[OPENDOUS_IN_BUFFER_SIZE
];
65 static uint8_t usb_out_buffer
[OPENDOUS_OUT_BUFFER_SIZE
];
67 /* Constants for OPENDOUS command */
69 #define OPENDOUS_MAX_SPEED 66
70 #define OPENDOUS_MAX_TAP_TRANSMIT 350 /* even number is easier to handle */
71 #define OPENDOUS_MAX_INPUT_DATA (OPENDOUS_MAX_TAP_TRANSMIT*4)
73 #define OPENDOUS_TAP_BUFFER_SIZE 65536
75 #define MAX_PENDING_SCAN_RESULTS (OPENDOUS_MAX_INPUT_DATA)
77 /* JTAG usb commands */
78 #define JTAG_CMD_TAP_OUTPUT 0x0
79 #define JTAG_CMD_SET_TRST 0x1
80 #define JTAG_CMD_SET_SRST 0x2
81 #define JTAG_CMD_READ_INPUT 0x3
82 #define JTAG_CMD_TAP_OUTPUT_EMU 0x4
83 #define JTAG_CMD_SET_DELAY 0x5
84 #define JTAG_CMD_SET_SRST_TRST 0x6
85 #define JTAG_CMD_READ_CONFIG 0x7
87 /* External interface functions */
88 static int opendous_execute_queue(void);
89 static int opendous_init(void);
90 static int opendous_quit(void);
92 /* Queue command functions */
93 static void opendous_end_state(tap_state_t state
);
94 static void opendous_state_move(void);
95 static void opendous_path_move(int num_states
, tap_state_t
*path
);
96 static void opendous_runtest(int num_cycles
);
97 static void opendous_scan(int ir_scan
, enum scan_type type
, uint8_t *buffer
,
98 int scan_size
, struct scan_command
*command
);
99 static void opendous_reset(int trst
, int srst
);
100 static void opendous_simple_command(uint8_t command
, uint8_t _data
);
101 static int opendous_get_status(void);
103 /* opendous tap buffer functions */
104 static void opendous_tap_init(void);
105 static int opendous_tap_execute(void);
106 static void opendous_tap_ensure_space(int scans
, int bits
);
107 static void opendous_tap_append_step(int tms
, int tdi
);
108 static void opendous_tap_append_scan(int length
, uint8_t *buffer
, struct scan_command
*command
);
110 /* opendous lowlevel functions */
111 struct opendous_jtag
{
112 struct jtag_libusb_device_handle
*usb_handle
;
115 static struct opendous_jtag
*opendous_usb_open(void);
116 static void opendous_usb_close(struct opendous_jtag
*opendous_jtag
);
117 static int opendous_usb_message(struct opendous_jtag
*opendous_jtag
, int out_length
, int in_length
);
118 static int opendous_usb_write(struct opendous_jtag
*opendous_jtag
, int out_length
);
119 static int opendous_usb_read(struct opendous_jtag
*opendous_jtag
);
121 /* helper functions */
122 int opendous_get_version_info(void);
124 #ifdef _DEBUG_USB_COMMS_
126 static void opendous_debug_buffer(uint8_t *buffer
, int length
);
127 char *opendous_get_time(char *);
130 static struct opendous_jtag
*opendous_jtag_handle
;
132 /***************************************************************************/
133 /* External interface implementation */
135 COMMAND_HANDLER(opendous_handle_opendous_info_command
)
137 if (opendous_get_version_info() == ERROR_OK
) {
138 /* attempt to get status */
139 opendous_get_status();
145 COMMAND_HANDLER(opendous_handle_opendous_hw_jtag_command
)
149 command_print(CMD_CTX
, "opendous hw jtag %i", opendous_hw_jtag_version
);
153 int request_version
= atoi(CMD_ARGV
[0]);
154 switch (request_version
) {
157 opendous_hw_jtag_version
= request_version
;
161 return ERROR_COMMAND_SYNTAX_ERROR
;
167 return ERROR_COMMAND_SYNTAX_ERROR
;
173 static const struct command_registration opendous_command_handlers
[] = {
175 .name
= "opendous_info",
176 .handler
= &opendous_handle_opendous_info_command
,
177 .mode
= COMMAND_EXEC
,
178 .help
= "show opendous info",
181 .name
= "opendous_hw_jtag",
182 .handler
= &opendous_handle_opendous_hw_jtag_command
,
183 .mode
= COMMAND_EXEC
,
184 .help
= "access opendous HW JTAG command version",
187 COMMAND_REGISTRATION_DONE
190 struct jtag_interface opendous_interface
= {
192 .commands
= opendous_command_handlers
,
193 .execute_queue
= opendous_execute_queue
,
194 .init
= opendous_init
,
195 .quit
= opendous_quit
,
198 static int opendous_execute_queue(void)
200 struct jtag_command
*cmd
= jtag_command_queue
;
205 while (cmd
!= NULL
) {
208 DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd
->cmd
.runtest
->num_cycles
, \
209 cmd
->cmd
.runtest
->end_state
);
211 if (cmd
->cmd
.runtest
->end_state
!= -1)
212 opendous_end_state(cmd
->cmd
.runtest
->end_state
);
213 opendous_runtest(cmd
->cmd
.runtest
->num_cycles
);
217 DEBUG_JTAG_IO("statemove end in %i", cmd
->cmd
.statemove
->end_state
);
219 if (cmd
->cmd
.statemove
->end_state
!= -1)
220 opendous_end_state(cmd
->cmd
.statemove
->end_state
);
221 opendous_state_move();
225 DEBUG_JTAG_IO("pathmove: %i states, end in %i", \
226 cmd
->cmd
.pathmove
->num_states
, \
227 cmd
->cmd
.pathmove
->path
[cmd
->cmd
.pathmove
->num_states
- 1]);
229 opendous_path_move(cmd
->cmd
.pathmove
->num_states
, cmd
->cmd
.pathmove
->path
);
233 DEBUG_JTAG_IO("scan end in %i", cmd
->cmd
.scan
->end_state
);
235 if (cmd
->cmd
.scan
->end_state
!= -1)
236 opendous_end_state(cmd
->cmd
.scan
->end_state
);
238 scan_size
= jtag_build_buffer(cmd
->cmd
.scan
, &buffer
);
239 DEBUG_JTAG_IO("scan input, length = %d", scan_size
);
241 #ifdef _DEBUG_USB_COMMS_
242 opendous_debug_buffer(buffer
, (scan_size
+ 7) / 8);
244 type
= jtag_scan_type(cmd
->cmd
.scan
);
245 opendous_scan(cmd
->cmd
.scan
->ir_scan
, type
, buffer
, scan_size
, cmd
->cmd
.scan
);
249 DEBUG_JTAG_IO("reset trst: %i srst %i", cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
251 opendous_tap_execute();
253 if (cmd
->cmd
.reset
->trst
== 1)
254 tap_set_state(TAP_RESET
);
255 opendous_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
259 DEBUG_JTAG_IO("sleep %i", cmd
->cmd
.sleep
->us
);
260 opendous_tap_execute();
261 jtag_sleep(cmd
->cmd
.sleep
->us
);
265 LOG_ERROR("BUG: unknown JTAG command type encountered");
270 return opendous_tap_execute();
273 static int opendous_init(void)
277 opendous_jtag_handle
= opendous_usb_open();
279 if (opendous_jtag_handle
== 0) {
280 LOG_ERROR("Cannot find opendous Interface! Please check connection and permissions.");
281 return ERROR_JTAG_INIT_FAILED
;
285 while (check_cnt
< 3) {
286 if (opendous_get_version_info() == ERROR_OK
) {
287 /* attempt to get status */
288 opendous_get_status();
295 LOG_INFO("opendous JTAG Interface ready");
297 opendous_reset(0, 0);
303 static int opendous_quit(void)
305 opendous_usb_close(opendous_jtag_handle
);
309 /***************************************************************************/
310 /* Queue command implementations */
312 void opendous_end_state(tap_state_t state
)
314 if (tap_is_state_stable(state
))
315 tap_set_end_state(state
);
317 LOG_ERROR("BUG: %i is not a valid end state", state
);
322 /* Goes to the end state. */
323 void opendous_state_move(void)
327 uint8_t tms_scan
= tap_get_tms_path(tap_get_state(), tap_get_end_state());
328 uint8_t tms_scan_bits
= tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
330 for (i
= 0; i
< tms_scan_bits
; i
++) {
331 tms
= (tms_scan
>> i
) & 1;
332 opendous_tap_append_step(tms
, 0);
335 tap_set_state(tap_get_end_state());
338 void opendous_path_move(int num_states
, tap_state_t
*path
)
342 for (i
= 0; i
< num_states
; i
++) {
343 if (path
[i
] == tap_state_transition(tap_get_state(), false))
344 opendous_tap_append_step(0, 0);
345 else if (path
[i
] == tap_state_transition(tap_get_state(), true))
346 opendous_tap_append_step(1, 0);
348 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
349 tap_state_name(tap_get_state()), tap_state_name(path
[i
]));
353 tap_set_state(path
[i
]);
356 tap_set_end_state(tap_get_state());
359 void opendous_runtest(int num_cycles
)
363 tap_state_t saved_end_state
= tap_get_end_state();
365 /* only do a state_move when we're not already in IDLE */
366 if (tap_get_state() != TAP_IDLE
) {
367 opendous_end_state(TAP_IDLE
);
368 opendous_state_move();
371 /* execute num_cycles */
372 for (i
= 0; i
< num_cycles
; i
++)
373 opendous_tap_append_step(0, 0);
375 /* finish in end_state */
376 opendous_end_state(saved_end_state
);
377 if (tap_get_state() != tap_get_end_state())
378 opendous_state_move();
381 void opendous_scan(int ir_scan
, enum scan_type type
, uint8_t *buffer
, int scan_size
, struct scan_command
*command
)
383 tap_state_t saved_end_state
;
385 opendous_tap_ensure_space(1, scan_size
+ 8);
387 saved_end_state
= tap_get_end_state();
389 /* Move to appropriate scan state */
390 opendous_end_state(ir_scan
? TAP_IRSHIFT
: TAP_DRSHIFT
);
392 if (tap_get_state() != tap_get_end_state())
393 opendous_state_move();
395 opendous_end_state(saved_end_state
);
398 opendous_tap_append_scan(scan_size
, buffer
, command
);
400 /* We are in Exit1, go to Pause */
401 opendous_tap_append_step(0, 0);
403 tap_set_state(ir_scan
? TAP_IRPAUSE
: TAP_DRPAUSE
);
405 if (tap_get_state() != tap_get_end_state())
406 opendous_state_move();
409 void opendous_reset(int trst
, int srst
)
411 LOG_DEBUG("trst: %i, srst: %i", trst
, srst
);
413 /* Signals are active low */
416 opendous_simple_command(JTAG_CMD_SET_SRST
, 1);
418 opendous_simple_command(JTAG_CMD_SET_SRST
, 0);
421 opendous_simple_command(JTAG_CMD_SET_TRST
, 1);
423 opendous_simple_command(JTAG_CMD_SET_TRST
, 0);
428 opendous_simple_command(JTAG_CMD_SET_SRST_TRST
, srst
| trst
);
431 void opendous_simple_command(uint8_t command
, uint8_t _data
)
435 DEBUG_JTAG_IO("0x%02x 0x%02x", command
, _data
);
437 usb_out_buffer
[0] = 2;
438 usb_out_buffer
[1] = 0;
439 usb_out_buffer
[2] = command
;
440 usb_out_buffer
[3] = _data
;
442 result
= opendous_usb_message(opendous_jtag_handle
, 4, 1);
444 LOG_ERROR("opendous command 0x%02x failed (%d)", command
, result
);
447 int opendous_get_status(void)
452 int opendous_get_version_info(void)
457 /***************************************************************************/
458 /* Estick tap functions */
460 static int tap_length
;
461 static uint8_t tms_buffer
[OPENDOUS_TAP_BUFFER_SIZE
];
462 static uint8_t tdo_buffer
[OPENDOUS_TAP_BUFFER_SIZE
];
464 struct pending_scan_result
{
465 int first
; /* First bit position in tdo_buffer to read */
466 int length
; /* Number of bits to read */
467 struct scan_command
*command
; /* Corresponding scan command */
471 static int pending_scan_results_length
;
472 static struct pending_scan_result pending_scan_results_buffer
[MAX_PENDING_SCAN_RESULTS
];
476 void opendous_tap_init(void)
479 pending_scan_results_length
= 0;
482 void opendous_tap_ensure_space(int scans
, int bits
)
484 int available_scans
= MAX_PENDING_SCAN_RESULTS
- pending_scan_results_length
;
486 if (scans
> available_scans
)
487 opendous_tap_execute();
490 void opendous_tap_append_step(int tms
, int tdi
)
493 unsigned char _tms
= tms
? 1 : 0;
494 unsigned char _tdi
= tdi
? 1 : 0;
496 int tap_index
= tap_length
/ 4;
497 int bits
= (tap_length
% 4) * 2;
499 if (tap_length
< OPENDOUS_TAP_BUFFER_SIZE
) {
501 tms_buffer
[tap_index
] = 0;
503 tms_buffer
[tap_index
] |= (_tdi
<< bits
)|(_tms
<< (bits
+ 1)) ;
506 LOG_ERROR("opendous_tap_append_step, overflow");
509 void opendous_tap_append_scan(int length
, uint8_t *buffer
, struct scan_command
*command
)
511 DEBUG_JTAG_IO("append scan, length = %d", length
);
513 struct pending_scan_result
*pending_scan_result
= &pending_scan_results_buffer
[pending_scan_results_length
];
516 pending_scan_result
->first
= tap_length
;
517 pending_scan_result
->length
= length
;
518 pending_scan_result
->command
= command
;
519 pending_scan_result
->buffer
= buffer
;
521 for (i
= 0; i
< length
; i
++)
522 opendous_tap_append_step((i
< length
-1 ? 0 : 1), (buffer
[i
/ 8] >> (i
% 8)) & 1);
523 pending_scan_results_length
++;
526 /* Pad and send a tap sequence to the device, and receive the answer.
527 * For the purpose of padding we assume that we are in idle or pause state. */
528 int opendous_tap_execute(void)
534 #ifdef _DEBUG_USB_COMMS_
538 if (tap_length
> 0) {
540 /* memset(tdo_buffer,0,OPENDOUS_TAP_BUFFER_SIZE); */
541 /* LOG_INFO("OPENDOUS tap execute %d",tap_length); */
542 byte_length
= (tap_length
+ 3) / 4;
544 #ifdef _DEBUG_USB_COMMS_
545 byte_length_out
= (tap_length
+ 7) / 8;
546 LOG_DEBUG("opendous is sending %d bytes", byte_length
);
549 for (j
= 0, i
= 0; j
< byte_length
;) {
552 int transmit
= byte_length
- j
;
553 if (transmit
> OPENDOUS_MAX_TAP_TRANSMIT
) {
554 transmit
= OPENDOUS_MAX_TAP_TRANSMIT
;
555 receive
= (OPENDOUS_MAX_TAP_TRANSMIT
) / 2;
556 usb_out_buffer
[2] = JTAG_CMD_TAP_OUTPUT
;
558 usb_out_buffer
[2] = JTAG_CMD_TAP_OUTPUT
| ((tap_length
% 4) << 4);
559 receive
= (transmit
+ 1) / 2;
561 usb_out_buffer
[0] = (transmit
+ 1) & 0xff;
562 usb_out_buffer
[1] = ((transmit
+ 1) >> 8) & 0xff;
564 memmove(usb_out_buffer
+ 3, tms_buffer
+ j
, transmit
);
565 result
= opendous_usb_message(opendous_jtag_handle
, 3 + transmit
, receive
);
566 if (result
!= receive
) {
567 LOG_ERROR("opendous_tap_execute, wrong result %d, expected %d", result
, receive
);
568 return ERROR_JTAG_QUEUE_FAILED
;
571 memmove(tdo_buffer
+ i
, usb_in_buffer
, receive
);
576 #ifdef _DEBUG_USB_COMMS_
577 LOG_DEBUG("opendous tap result %d", byte_length_out
);
578 opendous_debug_buffer(tdo_buffer
, byte_length_out
);
581 /* LOG_INFO("eStick tap execute %d",tap_length); */
582 for (i
= 0; i
< pending_scan_results_length
; i
++) {
584 struct pending_scan_result
*pending_scan_result
= &pending_scan_results_buffer
[i
];
585 uint8_t *buffer
= pending_scan_result
->buffer
;
586 int length
= pending_scan_result
->length
;
587 int first
= pending_scan_result
->first
;
588 struct scan_command
*command
= pending_scan_result
->command
;
591 buf_set_buf(tdo_buffer
, first
, buffer
, 0, length
);
593 DEBUG_JTAG_IO("pending scan result, length = %d", length
);
595 #ifdef _DEBUG_USB_COMMS_
596 opendous_debug_buffer(buffer
, byte_length_out
);
599 if (jtag_read_buffer(buffer
, command
) != ERROR_OK
) {
601 return ERROR_JTAG_QUEUE_FAILED
;
604 if (pending_scan_result
->buffer
!= NULL
)
605 free(pending_scan_result
->buffer
);
614 /*****************************************************************************/
615 /* Estick USB low-level functions */
617 struct opendous_jtag
*opendous_usb_open(void)
619 struct opendous_jtag
*result
;
621 struct jtag_libusb_device_handle
*devh
;
622 if (jtag_libusb_open(vids
, pids
, &devh
) != ERROR_OK
)
625 jtag_libusb_set_configuration(devh
, 0);
626 jtag_libusb_claim_interface(devh
, 0);
628 result
= (struct opendous_jtag
*) malloc(sizeof(struct opendous_jtag
));
629 result
->usb_handle
= devh
;
633 void opendous_usb_close(struct opendous_jtag
*opendous_jtag
)
635 jtag_libusb_close(opendous_jtag
->usb_handle
);
639 /* Send a message and receive the reply. */
640 int opendous_usb_message(struct opendous_jtag
*opendous_jtag
, int out_length
, int in_length
)
644 result
= opendous_usb_write(opendous_jtag
, out_length
);
645 if (result
== out_length
) {
646 result
= opendous_usb_read(opendous_jtag
);
647 if (result
== in_length
)
650 LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)", in_length
, result
);
654 LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)", out_length
, result
);
659 /* Write data from out_buffer to USB. */
660 int opendous_usb_write(struct opendous_jtag
*opendous_jtag
, int out_length
)
664 if (out_length
> OPENDOUS_OUT_BUFFER_SIZE
) {
665 LOG_ERROR("opendous_jtag_write illegal out_length=%d (max=%d)", out_length
, OPENDOUS_OUT_BUFFER_SIZE
);
669 #ifdef _DEBUG_USB_COMMS_
670 LOG_DEBUG("%s: USB write begin", opendous_get_time(time_str
));
672 result
= jtag_libusb_bulk_write(opendous_jtag
->usb_handle
, OPENDOUS_WRITE_ENDPOINT
, \
673 (char *)usb_out_buffer
, out_length
, OPENDOUS_USB_TIMEOUT
);
674 #ifdef _DEBUG_USB_COMMS_
675 LOG_DEBUG("%s: USB write end: %d bytes", opendous_get_time(time_str
), result
);
678 DEBUG_JTAG_IO("opendous_usb_write, out_length = %d, result = %d", out_length
, result
);
680 #ifdef _DEBUG_USB_COMMS_
681 opendous_debug_buffer(usb_out_buffer
, out_length
);
686 /* Read data from USB into in_buffer. */
687 int opendous_usb_read(struct opendous_jtag
*opendous_jtag
)
689 #ifdef _DEBUG_USB_COMMS_
690 LOG_DEBUG("%s: USB read begin", opendous_get_time(time_str
));
692 int result
= jtag_libusb_bulk_read(opendous_jtag
->usb_handle
, OPENDOUS_READ_ENDPOINT
,
693 (char *)usb_in_buffer
, OPENDOUS_IN_BUFFER_SIZE
, OPENDOUS_USB_TIMEOUT
);
694 #ifdef _DEBUG_USB_COMMS_
695 LOG_DEBUG("%s: USB read end: %d bytes", opendous_get_time(time_str
), result
);
697 DEBUG_JTAG_IO("opendous_usb_read, result = %d", result
);
699 #ifdef _DEBUG_USB_COMMS_
700 opendous_debug_buffer(usb_in_buffer
, result
);
705 #ifdef _DEBUG_USB_COMMS_
706 #define BYTES_PER_LINE 16
708 void opendous_debug_buffer(uint8_t *buffer
, int length
)
715 for (i
= 0; i
< length
; i
+= BYTES_PER_LINE
) {
716 snprintf(line
, 5, "%04x", i
);
717 for (j
= i
; j
< i
+ BYTES_PER_LINE
&& j
< length
; j
++) {
718 snprintf(s
, 4, " %02x", buffer
[j
]);
721 LOG_DEBUG("%s", line
);
725 char *opendous_get_time(char *str
)
727 struct timeb timebuffer
;
731 timeline
= ctime(&(timebuffer
.time
));
732 snprintf(str
, 49, "%.8s.%hu", &timeline
[11], timebuffer
.millitm
);
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)