arm11: do not use dynamic arrays
[openocd.git] / src / jtag / usbprog.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Benedikt Sauter *
3 * sauter@ixbat.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 /*
22 * This file is based on Dominic Rath's amt_jtagaccel.c.
23 *
24 * usbprog is a free programming adapter. You can easily install
25 * different firmware versions from an "online pool" over USB.
26 * The adapter can be used for programming and debugging AVR and ARM
27 * processors, as USB to RS232 converter, as JTAG interface or as
28 * simple I/O interface (5 lines).
29 *
30 * http://www.embedded-projects.net/usbprog
31 */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include "interface.h"
38 #include "commands.h"
39
40 #include <usb.h>
41
42
43 #define VID 0x1781
44 #define PID 0x0c63
45
46 /* Pins at usbprog */
47 #define TDO_BIT 0
48 #define TDI_BIT 3
49 #define TCK_BIT 2
50 #define TMS_BIT 1
51
52 static void usbprog_end_state(tap_state_t state);
53 static void usbprog_state_move(void);
54 static void usbprog_path_move(struct pathmove_command *cmd);
55 static void usbprog_runtest(int num_cycles);
56 static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size);
57
58 #define UNKOWN_COMMAND 0x00
59 #define PORT_DIRECTION 0x01
60 #define PORT_SET 0x02
61 #define PORT_GET 0x03
62 #define PORT_SETBIT 0x04
63 #define PORT_GETBIT 0x05
64 #define WRITE_TDI 0x06
65 #define READ_TDO 0x07
66 #define WRITE_AND_READ 0x08
67 #define WRITE_TMS 0x09
68 #define WRITE_TMS_CHAIN 0x0A
69
70 struct usbprog_jtag
71 {
72 struct usb_dev_handle* usb_handle;
73 };
74
75 static struct usbprog_jtag * usbprog_jtag_handle;
76
77 static struct usbprog_jtag* usbprog_jtag_open(void);
78 //static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag);
79 static void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag);
80 static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen);
81
82 static void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
83 static void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
84 static void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
85 static void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan);
86
87 static char tms_chain[64];
88 static int tms_chain_index;
89
90 static void usbprog_jtag_tms_collect(char tms_scan);
91 static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag);
92
93 static void usbprog_write(int tck, int tms, int tdi);
94 static void usbprog_reset(int trst, int srst);
95
96 static void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction);
97 static void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value);
98 //static unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag);
99 static void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value);
100 //static int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit);
101
102 static int usbprog_speed(int speed)
103 {
104 return ERROR_OK;
105 }
106
107 static int usbprog_execute_queue(void)
108 {
109 struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
110 int scan_size;
111 enum scan_type type;
112 uint8_t *buffer;
113
114 while (cmd)
115 {
116 switch (cmd->type)
117 {
118 case JTAG_RESET:
119 #ifdef _DEBUG_JTAG_IO_
120 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
121 #endif
122 if (cmd->cmd.reset->trst == 1)
123 {
124 tap_set_state(TAP_RESET);
125 }
126 usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
127 break;
128 case JTAG_RUNTEST:
129 #ifdef _DEBUG_JTAG_IO_
130 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
131 #endif
132 usbprog_end_state(cmd->cmd.runtest->end_state);
133 usbprog_runtest(cmd->cmd.runtest->num_cycles);
134 break;
135 case JTAG_STATEMOVE:
136 #ifdef _DEBUG_JTAG_IO_
137 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
138 #endif
139 usbprog_end_state(cmd->cmd.statemove->end_state);
140 usbprog_state_move();
141 break;
142 case JTAG_PATHMOVE:
143 #ifdef _DEBUG_JTAG_IO_
144 LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
145 cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
146 #endif
147 usbprog_path_move(cmd->cmd.pathmove);
148 break;
149 case JTAG_SCAN:
150 #ifdef _DEBUG_JTAG_IO_
151 LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
152 #endif
153 usbprog_end_state(cmd->cmd.scan->end_state);
154 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
155 type = jtag_scan_type(cmd->cmd.scan);
156 usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
157 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
158 return ERROR_JTAG_QUEUE_FAILED;
159 if (buffer)
160 free(buffer);
161 break;
162 case JTAG_SLEEP:
163 #ifdef _DEBUG_JTAG_IO_
164 LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
165 #endif
166 jtag_sleep(cmd->cmd.sleep->us);
167 break;
168 default:
169 LOG_ERROR("BUG: unknown JTAG command type encountered");
170 exit(-1);
171 }
172
173 cmd = cmd->next;
174 }
175
176 return ERROR_OK;
177 }
178
179 static int usbprog_init(void)
180 {
181 usbprog_jtag_handle = usbprog_jtag_open();
182
183 tms_chain_index = 0;
184 if (usbprog_jtag_handle == 0)
185 {
186 LOG_ERROR("Can't find USB JTAG Interface! Please check connection and permissions.");
187 return ERROR_JTAG_INIT_FAILED;
188 }
189
190 LOG_INFO("USB JTAG Interface ready!");
191
192 usbprog_jtag_init(usbprog_jtag_handle);
193 usbprog_reset(0, 0);
194 usbprog_write(0, 0, 0);
195
196 return ERROR_OK;
197 }
198
199 static int usbprog_quit(void)
200 {
201 return ERROR_OK;
202 }
203
204 /*************** jtag execute commands **********************/
205 static void usbprog_end_state(tap_state_t state)
206 {
207 if (tap_is_state_stable(state))
208 tap_set_end_state(state);
209 else
210 {
211 LOG_ERROR("BUG: %i is not a valid end state", state);
212 exit(-1);
213 }
214 }
215
216 static void usbprog_state_move(void)
217 {
218 int i = 0, tms = 0;
219 uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
220 int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
221
222 usbprog_jtag_write_tms(usbprog_jtag_handle, (char)tms_scan);
223 for (i = 0; i < tms_count; i++)
224 {
225 tms = (tms_scan >> i) & 1;
226 }
227
228 tap_set_state(tap_get_end_state());
229 }
230
231 static void usbprog_path_move(struct pathmove_command *cmd)
232 {
233 int num_states = cmd->num_states;
234 int state_count;
235
236 /* There may be queued transitions, and before following a specified
237 path, we must flush those queued transitions */
238 usbprog_jtag_tms_send(usbprog_jtag_handle);
239
240 state_count = 0;
241 while (num_states)
242 {
243 if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count])
244 {
245 /* LOG_INFO("1"); */
246 usbprog_write(0, 0, 0);
247 usbprog_write(1, 0, 0);
248 }
249 else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count])
250 {
251 /* LOG_INFO("2"); */
252 usbprog_write(0, 1, 0);
253 usbprog_write(1, 1, 0);
254 }
255 else
256 {
257 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count]));
258 exit(-1);
259 }
260
261 tap_set_state(cmd->path[state_count]);
262 state_count++;
263 num_states--;
264 }
265
266 tap_set_end_state(tap_get_state());
267 }
268
269 static void usbprog_runtest(int num_cycles)
270 {
271 int i;
272
273 /* only do a state_move when we're not already in IDLE */
274 if (tap_get_state() != TAP_IDLE)
275 {
276 usbprog_end_state(TAP_IDLE);
277 usbprog_state_move();
278 }
279
280 /* execute num_cycles */
281 if (num_cycles > 0)
282 {
283 usbprog_jtag_tms_send(usbprog_jtag_handle);
284 usbprog_write(0, 0, 0);
285 }
286 else
287 {
288 usbprog_jtag_tms_send(usbprog_jtag_handle);
289 /* LOG_INFO("NUM CYCLES %i",num_cycles); */
290 }
291
292 for (i = 0; i < num_cycles; i++)
293 {
294 usbprog_write(1, 0, 0);
295 usbprog_write(0, 0, 0);
296 }
297
298 #ifdef _DEBUG_JTAG_IO_
299 LOG_DEBUG("runtest: cur_state %s end_state %s", tap_state_name(tap_get_state()), tap_state_name(tap_get_end_state()));
300 #endif
301
302 /* finish in end_state */
303 /*
304 usbprog_end_state(saved_end_state);
305 if (tap_get_state() != tap_get_end_state())
306 usbprog_state_move();
307 */
308 }
309
310 static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
311 {
312 tap_state_t saved_end_state = tap_get_end_state();
313
314 if (ir_scan)
315 usbprog_end_state(TAP_IRSHIFT);
316 else
317 usbprog_end_state(TAP_DRSHIFT);
318
319 /* Only move if we're not already there */
320 if (tap_get_state() != tap_get_end_state())
321 usbprog_state_move();
322
323 usbprog_end_state(saved_end_state);
324
325 usbprog_jtag_tms_send(usbprog_jtag_handle);
326
327 void (*f)(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
328 switch (type) {
329 case SCAN_OUT: f = &usbprog_jtag_write_tdi; break;
330 case SCAN_IN: f = &usbprog_jtag_read_tdo; break;
331 case SCAN_IO: f = &usbprog_jtag_write_and_read; break;
332 default:
333 LOG_ERROR("unknown scan type: %i", type);
334 exit(-1);
335 }
336 f(usbprog_jtag_handle, (char *)buffer, scan_size);
337
338 /* The adapter does the transition to PAUSE internally */
339 if (ir_scan)
340 tap_set_state(TAP_IRPAUSE);
341 else
342 tap_set_state(TAP_DRPAUSE);
343
344 if (tap_get_state() != tap_get_end_state())
345 usbprog_state_move();
346 }
347
348 /*************** jtag wrapper functions *********************/
349
350 static void usbprog_write(int tck, int tms, int tdi)
351 {
352 unsigned char output_value = 0x00;
353
354 if (tms)
355 output_value |= (1 << TMS_BIT);
356 if (tdi)
357 output_value |= (1 << TDI_BIT);
358 if (tck)
359 output_value |= (1 << TCK_BIT);
360
361 usbprog_jtag_write_slice(usbprog_jtag_handle,output_value);
362 }
363
364 /* (1) assert or (0) deassert reset lines */
365 static void usbprog_reset(int trst, int srst)
366 {
367 LOG_DEBUG("trst: %i, srst: %i", trst, srst);
368
369 if (trst)
370 usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 0);
371 else
372 usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 1);
373
374 if (srst)
375 usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 0);
376 else
377 usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 1);
378 }
379
380 /*************** jtag lowlevel functions ********************/
381
382 struct usb_bus *busses;
383
384 struct usbprog_jtag* usbprog_jtag_open(void)
385 {
386 struct usb_bus *bus;
387 struct usb_device *dev;
388
389 struct usbprog_jtag *tmp;
390
391 tmp = (struct usbprog_jtag*)malloc(sizeof(struct usbprog_jtag));
392
393 usb_set_debug(10);
394 usb_init();
395 usb_find_busses();
396 usb_find_devices();
397
398 busses = usb_get_busses();
399
400 /* find usbprog_jtag device in usb bus */
401
402 for (bus = busses; bus; bus = bus->next)
403 {
404 for (dev = bus->devices; dev; dev = dev->next)
405 {
406 /* condition for sucessfully hit (too bad, I only check the vendor id)*/
407 if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID)
408 {
409 tmp->usb_handle = usb_open(dev);
410 usb_set_configuration(tmp->usb_handle, 1);
411 usb_claim_interface(tmp->usb_handle, 0);
412 usb_set_altinterface(tmp->usb_handle, 0);
413 return tmp;
414 }
415 }
416 }
417 free(tmp);
418 return 0;
419 }
420
421 #if 0
422 static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag)
423 {
424 usb_close(usbprog_jtag->usb_handle);
425 free(usbprog_jtag);
426 }
427 #endif
428
429 static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen)
430 {
431 int res = usb_bulk_write(usbprog_jtag->usb_handle, 3, msg,msglen, 100);
432 if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) || \
433 (msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9))
434 return 1;
435 if (res == msglen)
436 {
437 /* LOG_INFO("HALLLLOOO %i",(int)msg[0]); */
438 res = usb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100);
439 if (res > 0)
440 return (unsigned char)msg[1];
441 else
442 return -1;
443 }
444 else
445 return -1;
446 return 0;
447 }
448
449 static void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag)
450 {
451 usbprog_jtag_set_direction(usbprog_jtag, 0xFE);
452 }
453
454 static void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
455 {
456 char tmp[64]; /* fastes packet size for usb controller */
457 int send_bits, bufindex = 0, fillindex = 0, i, loops;
458
459 char swap;
460 /* 61 byte can be transfered (488 bit) */
461
462 while (size > 0)
463 {
464 if (size > 488)
465 {
466 send_bits = 488;
467 size = size - 488;
468 loops = 61;
469 }
470 else
471 {
472 send_bits = size;
473 loops = size / 8;
474 loops++;
475 size = 0;
476 }
477 tmp[0] = WRITE_AND_READ;
478 tmp[1] = (char)(send_bits >> 8); /* high */
479 tmp[2] = (char)(send_bits); /* low */
480 i = 0;
481
482 for (i = 0; i < loops; i++)
483 {
484 tmp[3 + i] = buffer[bufindex];
485 bufindex++;
486 }
487
488 if (usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000) == 64)
489 {
490 /* LOG_INFO("HALLLLOOO2 %i",(int)tmp[0]); */
491 usleep(1);
492 int timeout = 0;
493 while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 1000) < 1)
494 {
495 timeout++;
496 if (timeout > 10)
497 break;
498 }
499
500 for (i = 0; i < loops; i++)
501 {
502 swap = tmp[3 + i];
503 buffer[fillindex++] = swap;
504 }
505 }
506 }
507 }
508
509 static void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
510 {
511 char tmp[64]; /* fastes packet size for usb controller */
512 int send_bits, fillindex = 0, i, loops;
513
514 char swap;
515 /* 61 byte can be transfered (488 bit) */
516
517 while (size > 0)
518 {
519 if (size > 488)
520 {
521 send_bits = 488;
522 size = size - 488;
523 loops = 61;
524 }
525 else
526 {
527 send_bits = size;
528 loops = size / 8;
529 loops++;
530 size = 0;
531 }
532 tmp[0] = WRITE_AND_READ;
533 tmp[1] = (char)(send_bits >> 8); /* high */
534 tmp[2] = (char)(send_bits); /* low */
535
536 usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 3, 1000);
537
538 /* LOG_INFO("HALLLLOOO3 %i",(int)tmp[0]); */
539 int timeout = 0;
540 usleep(1);
541 while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 10) < 1)
542 {
543 timeout++;
544 if (timeout > 10)
545 break;
546 }
547
548 for (i = 0; i < loops; i++)
549 {
550 swap = tmp[3 + i];
551 buffer[fillindex++] = swap;
552 }
553 }
554 }
555
556 static void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
557 {
558 char tmp[64]; /* fastes packet size for usb controller */
559 int send_bits, bufindex = 0, i, loops;
560
561 /* 61 byte can be transfered (488 bit) */
562 while (size > 0)
563 {
564 if (size > 488)
565 {
566 send_bits = 488;
567 size = size - 488;
568 loops = 61;
569 }
570 else
571 {
572 send_bits = size;
573 loops = size/8;
574 /* if (loops == 0) */
575 loops++;
576 size = 0;
577 }
578 tmp[0] = WRITE_TDI;
579 tmp[1] = (char)(send_bits >> 8); /* high */
580 tmp[2] = (char)(send_bits); /* low */
581 i = 0;
582
583 for (i = 0; i < loops; i++)
584 {
585 tmp[3 + i] = buffer[bufindex];
586 bufindex++;
587 }
588 usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000);
589 }
590 }
591
592 static void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan)
593 {
594 usbprog_jtag_tms_collect(tms_scan);
595 }
596
597 static void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction)
598 {
599 char tmp[2];
600 tmp[0] = PORT_DIRECTION;
601 tmp[1] = (char)direction;
602 usbprog_jtag_message(usbprog_jtag, tmp, 2);
603 }
604
605 static void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value)
606 {
607 char tmp[2];
608 tmp[0] = PORT_SET;
609 tmp[1] = (char)value;
610 usbprog_jtag_message(usbprog_jtag, tmp, 2);
611 }
612
613 #if 0
614 static unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag)
615 {
616 char tmp[2];
617 tmp[0] = PORT_GET;
618 tmp[1] = 0x00;
619 return usbprog_jtag_message(usbprog_jtag, tmp, 2);
620 }
621 #endif
622
623 static void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value)
624 {
625 char tmp[3];
626 tmp[0] = PORT_SETBIT;
627 tmp[1] = (char)bit;
628 if (value == 1)
629 tmp[2] = 0x01;
630 else
631 tmp[2] = 0x00;
632 usbprog_jtag_message(usbprog_jtag, tmp, 3);
633 }
634
635 #if 0
636 static int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit)
637 {
638 char tmp[2];
639 tmp[0] = PORT_GETBIT;
640 tmp[1] = (char)bit;
641
642 if (usbprog_jtag_message(usbprog_jtag, tmp, 2) > 0)
643 return 1;
644 else
645 return 0;
646 }
647 #endif
648
649 static void usbprog_jtag_tms_collect(char tms_scan)
650 {
651 tms_chain[tms_chain_index] = tms_scan;
652 tms_chain_index++;
653 }
654
655 static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)
656 {
657 int i;
658 /* LOG_INFO("TMS SEND"); */
659 if (tms_chain_index > 0)
660 {
661 char tmp[tms_chain_index + 2];
662 tmp[0] = WRITE_TMS_CHAIN;
663 tmp[1] = (char)(tms_chain_index);
664 for (i = 0; i < tms_chain_index + 1; i++)
665 tmp[2 + i] = tms_chain[i];
666 usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, tms_chain_index + 2, 1000);
667 tms_chain_index = 0;
668 }
669 }
670
671 struct jtag_interface usbprog_interface = {
672 .name = "usbprog",
673 .execute_queue = &usbprog_execute_queue,
674 .speed = &usbprog_speed,
675 .init = &usbprog_init,
676 .quit = &usbprog_quit
677 };

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)