libusb: require pkg-config support
[openocd.git] / src / helper / list.h
1 #ifndef _LINUX_LIST_H
2 #define _LINUX_LIST_H
3
4 /* begin local changes */
5 #include <helper/types.h>
6
7 #define prefetch(x) ((void)x)
8 #define LIST_POISON1 NULL
9 #define LIST_POISON2 NULL
10
11 struct list_head {
12 struct list_head *next, *prev;
13 };
14 struct hlist_head {
15 struct hlist_node *first;
16 };
17 struct hlist_node {
18 struct hlist_node *next, **pprev;
19 };
20 /* end local changes */
21
22 /*
23 * Simple doubly linked list implementation.
24 *
25 * Some of the internal functions ("__xxx") are useful when
26 * manipulating whole lists rather than single entries, as
27 * sometimes we already know the next/prev entries and we can
28 * generate better code by using them directly rather than
29 * using the generic single-entry routines.
30 */
31
32 #define LIST_HEAD_INIT(name) { &(name), &(name) }
33
34 #define LIST_HEAD(name) \
35 struct list_head name = LIST_HEAD_INIT(name)
36
37 static inline void INIT_LIST_HEAD(struct list_head *list)
38 {
39 list->next = list;
40 list->prev = list;
41 }
42
43 /*
44 * Insert a new entry between two known consecutive entries.
45 *
46 * This is only for internal list manipulation where we know
47 * the prev/next entries already!
48 */
49 #ifndef CONFIG_DEBUG_LIST
50 static inline void __list_add(struct list_head *new,
51 struct list_head *prev,
52 struct list_head *next)
53 {
54 next->prev = new;
55 new->next = next;
56 new->prev = prev;
57 prev->next = new;
58 }
59 #else
60 extern void __list_add(struct list_head *new,
61 struct list_head *prev,
62 struct list_head *next);
63 #endif
64
65 /**
66 * list_add - add a new entry
67 * @new: new entry to be added
68 * @head: list head to add it after
69 *
70 * Insert a new entry after the specified head.
71 * This is good for implementing stacks.
72 */
73 static inline void list_add(struct list_head *new, struct list_head *head)
74 {
75 __list_add(new, head, head->next);
76 }
77
78
79 /**
80 * list_add_tail - add a new entry
81 * @new: new entry to be added
82 * @head: list head to add it before
83 *
84 * Insert a new entry before the specified head.
85 * This is useful for implementing queues.
86 */
87 static inline void list_add_tail(struct list_head *new, struct list_head *head)
88 {
89 __list_add(new, head->prev, head);
90 }
91
92 /*
93 * Delete a list entry by making the prev/next entries
94 * point to each other.
95 *
96 * This is only for internal list manipulation where we know
97 * the prev/next entries already!
98 */
99 static inline void __list_del(struct list_head *prev, struct list_head *next)
100 {
101 next->prev = prev;
102 prev->next = next;
103 }
104
105 /**
106 * list_del - deletes entry from list.
107 * @entry: the element to delete from the list.
108 * Note: list_empty() on entry does not return true after this, the entry is
109 * in an undefined state.
110 */
111 #ifndef CONFIG_DEBUG_LIST
112 static inline void __list_del_entry(struct list_head *entry)
113 {
114 __list_del(entry->prev, entry->next);
115 }
116
117 static inline void list_del(struct list_head *entry)
118 {
119 __list_del(entry->prev, entry->next);
120 entry->next = LIST_POISON1;
121 entry->prev = LIST_POISON2;
122 }
123 #else
124 extern void __list_del_entry(struct list_head *entry);
125 extern void list_del(struct list_head *entry);
126 #endif
127
128 /**
129 * list_replace - replace old entry by new one
130 * @old : the element to be replaced
131 * @new : the new element to insert
132 *
133 * If @old was empty, it will be overwritten.
134 */
135 static inline void list_replace(struct list_head *old,
136 struct list_head *new)
137 {
138 new->next = old->next;
139 new->next->prev = new;
140 new->prev = old->prev;
141 new->prev->next = new;
142 }
143
144 static inline void list_replace_init(struct list_head *old,
145 struct list_head *new)
146 {
147 list_replace(old, new);
148 INIT_LIST_HEAD(old);
149 }
150
151 /**
152 * list_del_init - deletes entry from list and reinitialize it.
153 * @entry: the element to delete from the list.
154 */
155 static inline void list_del_init(struct list_head *entry)
156 {
157 __list_del_entry(entry);
158 INIT_LIST_HEAD(entry);
159 }
160
161 /**
162 * list_move - delete from one list and add as another's head
163 * @list: the entry to move
164 * @head: the head that will precede our entry
165 */
166 static inline void list_move(struct list_head *list, struct list_head *head)
167 {
168 __list_del_entry(list);
169 list_add(list, head);
170 }
171
172 /**
173 * list_move_tail - delete from one list and add as another's tail
174 * @list: the entry to move
175 * @head: the head that will follow our entry
176 */
177 static inline void list_move_tail(struct list_head *list,
178 struct list_head *head)
179 {
180 __list_del_entry(list);
181 list_add_tail(list, head);
182 }
183
184 /**
185 * list_is_last - tests whether @list is the last entry in list @head
186 * @list: the entry to test
187 * @head: the head of the list
188 */
189 static inline int list_is_last(const struct list_head *list,
190 const struct list_head *head)
191 {
192 return list->next == head;
193 }
194
195 /**
196 * list_empty - tests whether a list is empty
197 * @head: the list to test.
198 */
199 static inline int list_empty(const struct list_head *head)
200 {
201 return head->next == head;
202 }
203
204 /**
205 * list_empty_careful - tests whether a list is empty and not being modified
206 * @head: the list to test
207 *
208 * Description:
209 * tests whether a list is empty _and_ checks that no other CPU might be
210 * in the process of modifying either member (next or prev)
211 *
212 * NOTE: using list_empty_careful() without synchronization
213 * can only be safe if the only activity that can happen
214 * to the list entry is list_del_init(). Eg. it cannot be used
215 * if another CPU could re-list_add() it.
216 */
217 static inline int list_empty_careful(const struct list_head *head)
218 {
219 struct list_head *next = head->next;
220 return (next == head) && (next == head->prev);
221 }
222
223 /**
224 * list_rotate_left - rotate the list to the left
225 * @head: the head of the list
226 */
227 static inline void list_rotate_left(struct list_head *head)
228 {
229 struct list_head *first;
230
231 if (!list_empty(head)) {
232 first = head->next;
233 list_move_tail(first, head);
234 }
235 }
236
237 /**
238 * list_is_singular - tests whether a list has just one entry.
239 * @head: the list to test.
240 */
241 static inline int list_is_singular(const struct list_head *head)
242 {
243 return !list_empty(head) && (head->next == head->prev);
244 }
245
246 static inline void __list_cut_position(struct list_head *list,
247 struct list_head *head, struct list_head *entry)
248 {
249 struct list_head *new_first = entry->next;
250 list->next = head->next;
251 list->next->prev = list;
252 list->prev = entry;
253 entry->next = list;
254 head->next = new_first;
255 new_first->prev = head;
256 }
257
258 /**
259 * list_cut_position - cut a list into two
260 * @list: a new list to add all removed entries
261 * @head: a list with entries
262 * @entry: an entry within head, could be the head itself
263 * and if so we won't cut the list
264 *
265 * This helper moves the initial part of @head, up to and
266 * including @entry, from @head to @list. You should
267 * pass on @entry an element you know is on @head. @list
268 * should be an empty list or a list you do not care about
269 * losing its data.
270 *
271 */
272 static inline void list_cut_position(struct list_head *list,
273 struct list_head *head, struct list_head *entry)
274 {
275 if (list_empty(head))
276 return;
277 if (list_is_singular(head) &&
278 (head->next != entry && head != entry))
279 return;
280 if (entry == head)
281 INIT_LIST_HEAD(list);
282 else
283 __list_cut_position(list, head, entry);
284 }
285
286 static inline void __list_splice(const struct list_head *list,
287 struct list_head *prev,
288 struct list_head *next)
289 {
290 struct list_head *first = list->next;
291 struct list_head *last = list->prev;
292
293 first->prev = prev;
294 prev->next = first;
295
296 last->next = next;
297 next->prev = last;
298 }
299
300 /**
301 * list_splice - join two lists, this is designed for stacks
302 * @list: the new list to add.
303 * @head: the place to add it in the first list.
304 */
305 static inline void list_splice(const struct list_head *list,
306 struct list_head *head)
307 {
308 if (!list_empty(list))
309 __list_splice(list, head, head->next);
310 }
311
312 /**
313 * list_splice_tail - join two lists, each list being a queue
314 * @list: the new list to add.
315 * @head: the place to add it in the first list.
316 */
317 static inline void list_splice_tail(struct list_head *list,
318 struct list_head *head)
319 {
320 if (!list_empty(list))
321 __list_splice(list, head->prev, head);
322 }
323
324 /**
325 * list_splice_init - join two lists and reinitialise the emptied list.
326 * @list: the new list to add.
327 * @head: the place to add it in the first list.
328 *
329 * The list at @list is reinitialised
330 */
331 static inline void list_splice_init(struct list_head *list,
332 struct list_head *head)
333 {
334 if (!list_empty(list)) {
335 __list_splice(list, head, head->next);
336 INIT_LIST_HEAD(list);
337 }
338 }
339
340 /**
341 * list_splice_tail_init - join two lists and reinitialise the emptied list
342 * @list: the new list to add.
343 * @head: the place to add it in the first list.
344 *
345 * Each of the lists is a queue.
346 * The list at @list is reinitialised
347 */
348 static inline void list_splice_tail_init(struct list_head *list,
349 struct list_head *head)
350 {
351 if (!list_empty(list)) {
352 __list_splice(list, head->prev, head);
353 INIT_LIST_HEAD(list);
354 }
355 }
356
357 /**
358 * list_entry - get the struct for this entry
359 * @ptr: the &struct list_head pointer.
360 * @type: the type of the struct this is embedded in.
361 * @member: the name of the list_struct within the struct.
362 */
363 #define list_entry(ptr, type, member) \
364 container_of(ptr, type, member)
365
366 /**
367 * list_first_entry - get the first element from a list
368 * @ptr: the list head to take the element from.
369 * @type: the type of the struct this is embedded in.
370 * @member: the name of the list_struct within the struct.
371 *
372 * Note, that list is expected to be not empty.
373 */
374 #define list_first_entry(ptr, type, member) \
375 list_entry((ptr)->next, type, member)
376
377 /**
378 * list_for_each - iterate over a list
379 * @pos: the &struct list_head to use as a loop cursor.
380 * @head: the head for your list.
381 */
382 #define list_for_each(pos, head) \
383 for (pos = (head)->next; prefetch(pos->next), pos != (head); \
384 pos = pos->next)
385
386 /**
387 * __list_for_each - iterate over a list
388 * @pos: the &struct list_head to use as a loop cursor.
389 * @head: the head for your list.
390 *
391 * This variant differs from list_for_each() in that it's the
392 * simplest possible list iteration code, no prefetching is done.
393 * Use this for code that knows the list to be very short (empty
394 * or 1 entry) most of the time.
395 */
396 #define __list_for_each(pos, head) \
397 for (pos = (head)->next; pos != (head); pos = pos->next)
398
399 /**
400 * list_for_each_prev - iterate over a list backwards
401 * @pos: the &struct list_head to use as a loop cursor.
402 * @head: the head for your list.
403 */
404 #define list_for_each_prev(pos, head) \
405 for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
406 pos = pos->prev)
407
408 /**
409 * list_for_each_safe - iterate over a list safe against removal of list entry
410 * @pos: the &struct list_head to use as a loop cursor.
411 * @n: another &struct list_head to use as temporary storage
412 * @head: the head for your list.
413 */
414 #define list_for_each_safe(pos, n, head) \
415 for (pos = (head)->next, n = pos->next; pos != (head); \
416 pos = n, n = pos->next)
417
418 /**
419 * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
420 * @pos: the &struct list_head to use as a loop cursor.
421 * @n: another &struct list_head to use as temporary storage
422 * @head: the head for your list.
423 */
424 #define list_for_each_prev_safe(pos, n, head) \
425 for (pos = (head)->prev, n = pos->prev; \
426 prefetch(pos->prev), pos != (head); \
427 pos = n, n = pos->prev)
428
429 /**
430 * list_for_each_entry - iterate over list of given type
431 * @pos: the type * to use as a loop cursor.
432 * @head: the head for your list.
433 * @member: the name of the list_struct within the struct.
434 */
435 #define list_for_each_entry(pos, head, member) \
436 for (pos = list_entry((head)->next, typeof(*pos), member); \
437 prefetch(pos->member.next), &pos->member != (head); \
438 pos = list_entry(pos->member.next, typeof(*pos), member))
439
440 /**
441 * list_for_each_entry_reverse - iterate backwards over list of given type.
442 * @pos: the type * to use as a loop cursor.
443 * @head: the head for your list.
444 * @member: the name of the list_struct within the struct.
445 */
446 #define list_for_each_entry_reverse(pos, head, member) \
447 for (pos = list_entry((head)->prev, typeof(*pos), member); \
448 prefetch(pos->member.prev), &pos->member != (head); \
449 pos = list_entry(pos->member.prev, typeof(*pos), member))
450
451 /**
452 * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
453 * @pos: the type * to use as a start point
454 * @head: the head of the list
455 * @member: the name of the list_struct within the struct.
456 *
457 * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
458 */
459 #define list_prepare_entry(pos, head, member) \
460 ((pos) ? : list_entry(head, typeof(*pos), member))
461
462 /**
463 * list_for_each_entry_continue - continue iteration over list of given type
464 * @pos: the type * to use as a loop cursor.
465 * @head: the head for your list.
466 * @member: the name of the list_struct within the struct.
467 *
468 * Continue to iterate over list of given type, continuing after
469 * the current position.
470 */
471 #define list_for_each_entry_continue(pos, head, member) \
472 for (pos = list_entry(pos->member.next, typeof(*pos), member); \
473 prefetch(pos->member.next), &pos->member != (head); \
474 pos = list_entry(pos->member.next, typeof(*pos), member))
475
476 /**
477 * list_for_each_entry_continue_reverse - iterate backwards from the given point
478 * @pos: the type * to use as a loop cursor.
479 * @head: the head for your list.
480 * @member: the name of the list_struct within the struct.
481 *
482 * Start to iterate over list of given type backwards, continuing after
483 * the current position.
484 */
485 #define list_for_each_entry_continue_reverse(pos, head, member) \
486 for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
487 prefetch(pos->member.prev), &pos->member != (head); \
488 pos = list_entry(pos->member.prev, typeof(*pos), member))
489
490 /**
491 * list_for_each_entry_from - iterate over list of given type from the current point
492 * @pos: the type * to use as a loop cursor.
493 * @head: the head for your list.
494 * @member: the name of the list_struct within the struct.
495 *
496 * Iterate over list of given type, continuing from current position.
497 */
498 #define list_for_each_entry_from(pos, head, member) \
499 for (; prefetch(pos->member.next), &pos->member != (head); \
500 pos = list_entry(pos->member.next, typeof(*pos), member))
501
502 /**
503 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
504 * @pos: the type * to use as a loop cursor.
505 * @n: another type * to use as temporary storage
506 * @head: the head for your list.
507 * @member: the name of the list_struct within the struct.
508 */
509 #define list_for_each_entry_safe(pos, n, head, member) \
510 for (pos = list_entry((head)->next, typeof(*pos), member), \
511 n = list_entry(pos->member.next, typeof(*pos), member); \
512 &pos->member != (head); \
513 pos = n, n = list_entry(n->member.next, typeof(*n), member))
514
515 /**
516 * list_for_each_entry_safe_continue - continue list iteration safe against removal
517 * @pos: the type * to use as a loop cursor.
518 * @n: another type * to use as temporary storage
519 * @head: the head for your list.
520 * @member: the name of the list_struct within the struct.
521 *
522 * Iterate over list of given type, continuing after current point,
523 * safe against removal of list entry.
524 */
525 #define list_for_each_entry_safe_continue(pos, n, head, member) \
526 for (pos = list_entry(pos->member.next, typeof(*pos), member), \
527 n = list_entry(pos->member.next, typeof(*pos), member); \
528 &pos->member != (head); \
529 pos = n, n = list_entry(n->member.next, typeof(*n), member))
530
531 /**
532 * list_for_each_entry_safe_from - iterate over list from current point safe against removal
533 * @pos: the type * to use as a loop cursor.
534 * @n: another type * to use as temporary storage
535 * @head: the head for your list.
536 * @member: the name of the list_struct within the struct.
537 *
538 * Iterate over list of given type from current point, safe against
539 * removal of list entry.
540 */
541 #define list_for_each_entry_safe_from(pos, n, head, member) \
542 for (n = list_entry(pos->member.next, typeof(*pos), member); \
543 &pos->member != (head); \
544 pos = n, n = list_entry(n->member.next, typeof(*n), member))
545
546 /**
547 * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
548 * @pos: the type * to use as a loop cursor.
549 * @n: another type * to use as temporary storage
550 * @head: the head for your list.
551 * @member: the name of the list_struct within the struct.
552 *
553 * Iterate backwards over list of given type, safe against removal
554 * of list entry.
555 */
556 #define list_for_each_entry_safe_reverse(pos, n, head, member) \
557 for (pos = list_entry((head)->prev, typeof(*pos), member), \
558 n = list_entry(pos->member.prev, typeof(*pos), member); \
559 &pos->member != (head); \
560 pos = n, n = list_entry(n->member.prev, typeof(*n), member))
561
562 /**
563 * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
564 * @pos: the loop cursor used in the list_for_each_entry_safe loop
565 * @n: temporary storage used in list_for_each_entry_safe
566 * @member: the name of the list_struct within the struct.
567 *
568 * list_safe_reset_next is not safe to use in general if the list may be
569 * modified concurrently (eg. the lock is dropped in the loop body). An
570 * exception to this is if the cursor element (pos) is pinned in the list,
571 * and list_safe_reset_next is called after re-taking the lock and before
572 * completing the current iteration of the loop body.
573 */
574 #define list_safe_reset_next(pos, n, member) \
575 n = list_entry(pos->member.next, typeof(*pos), member)
576
577 /*
578 * Double linked lists with a single pointer list head.
579 * Mostly useful for hash tables where the two pointer list head is
580 * too wasteful.
581 * You lose the ability to access the tail in O(1).
582 */
583
584 #define HLIST_HEAD_INIT { .first = NULL }
585 #define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
586 #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
587 static inline void INIT_HLIST_NODE(struct hlist_node *h)
588 {
589 h->next = NULL;
590 h->pprev = NULL;
591 }
592
593 static inline int hlist_unhashed(const struct hlist_node *h)
594 {
595 return !h->pprev;
596 }
597
598 static inline int hlist_empty(const struct hlist_head *h)
599 {
600 return !h->first;
601 }
602
603 static inline void __hlist_del(struct hlist_node *n)
604 {
605 struct hlist_node *next = n->next;
606 struct hlist_node **pprev = n->pprev;
607 *pprev = next;
608 if (next)
609 next->pprev = pprev;
610 }
611
612 static inline void hlist_del(struct hlist_node *n)
613 {
614 __hlist_del(n);
615 n->next = LIST_POISON1;
616 n->pprev = LIST_POISON2;
617 }
618
619 static inline void hlist_del_init(struct hlist_node *n)
620 {
621 if (!hlist_unhashed(n)) {
622 __hlist_del(n);
623 INIT_HLIST_NODE(n);
624 }
625 }
626
627 static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
628 {
629 struct hlist_node *first = h->first;
630 n->next = first;
631 if (first)
632 first->pprev = &n->next;
633 h->first = n;
634 n->pprev = &h->first;
635 }
636
637 /* next must be != NULL */
638 static inline void hlist_add_before(struct hlist_node *n,
639 struct hlist_node *next)
640 {
641 n->pprev = next->pprev;
642 n->next = next;
643 next->pprev = &n->next;
644 *(n->pprev) = n;
645 }
646
647 static inline void hlist_add_after(struct hlist_node *n,
648 struct hlist_node *next)
649 {
650 next->next = n->next;
651 n->next = next;
652 next->pprev = &n->next;
653
654 if (next->next)
655 next->next->pprev = &next->next;
656 }
657
658 /* after that we'll appear to be on some hlist and hlist_del will work */
659 static inline void hlist_add_fake(struct hlist_node *n)
660 {
661 n->pprev = &n->next;
662 }
663
664 /*
665 * Move a list from one list head to another. Fixup the pprev
666 * reference of the first entry if it exists.
667 */
668 static inline void hlist_move_list(struct hlist_head *old,
669 struct hlist_head *new)
670 {
671 new->first = old->first;
672 if (new->first)
673 new->first->pprev = &new->first;
674 old->first = NULL;
675 }
676
677 #define hlist_entry(ptr, type, member) container_of(ptr, type, member)
678
679 #define hlist_for_each(pos, head) \
680 for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
681 pos = pos->next)
682
683 #define hlist_for_each_safe(pos, n, head) \
684 for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
685 pos = n)
686
687 /**
688 * hlist_for_each_entry - iterate over list of given type
689 * @tpos: the type * to use as a loop cursor.
690 * @pos: the &struct hlist_node to use as a loop cursor.
691 * @head: the head for your list.
692 * @member: the name of the hlist_node within the struct.
693 */
694 #define hlist_for_each_entry(tpos, pos, head, member) \
695 for (pos = (head)->first; \
696 pos && ({ prefetch(pos->next); 1; }) && \
697 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
698 pos = pos->next)
699
700 /**
701 * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
702 * @tpos: the type * to use as a loop cursor.
703 * @pos: the &struct hlist_node to use as a loop cursor.
704 * @member: the name of the hlist_node within the struct.
705 */
706 #define hlist_for_each_entry_continue(tpos, pos, member) \
707 for (pos = (pos)->next; \
708 pos && ({ prefetch(pos->next); 1; }) && \
709 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
710 pos = pos->next)
711
712 /**
713 * hlist_for_each_entry_from - iterate over a hlist continuing from current point
714 * @tpos: the type * to use as a loop cursor.
715 * @pos: the &struct hlist_node to use as a loop cursor.
716 * @member: the name of the hlist_node within the struct.
717 */
718 #define hlist_for_each_entry_from(tpos, pos, member) \
719 for (; pos && ({ prefetch(pos->next); 1; }) && \
720 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
721 pos = pos->next)
722
723 /**
724 * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
725 * @tpos: the type * to use as a loop cursor.
726 * @pos: the &struct hlist_node to use as a loop cursor.
727 * @n: another &struct hlist_node to use as temporary storage
728 * @head: the head for your list.
729 * @member: the name of the hlist_node within the struct.
730 */
731 #define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
732 for (pos = (head)->first; \
733 pos && ({ n = pos->next; 1; }) && \
734 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
735 pos = n)
736
737 #endif

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)