jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / jtag / drivers / osbdm.c
1 /***************************************************************************
2 * Copyright (C) 2012 by Jan Dakinevich *
3 * jan.dakinevich@gmail.com *
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, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 #endif
21
22 #include <helper/log.h>
23 #include <helper/binarybuffer.h>
24 #include <helper/command.h>
25 #include <jtag/interface.h>
26 #include "libusb_helper.h"
27
28 struct sequence {
29 int len;
30 void *tms;
31 void *tdo;
32 const void *tdi;
33 struct sequence *next;
34 };
35
36 struct queue {
37 struct sequence *head;
38 struct sequence *tail;
39 };
40
41 static struct sequence *queue_add_tail(struct queue *queue, int len)
42 {
43 if (len <= 0) {
44 LOG_ERROR("BUG: sequences with zero length are not allowed");
45 return NULL;
46 }
47
48 struct sequence *next;
49 next = malloc(sizeof(*next));
50 if (next) {
51 next->tms = calloc(1, DIV_ROUND_UP(len, 8));
52 if (next->tms) {
53 next->len = len;
54 next->tdo = NULL;
55 next->tdi = NULL;
56 next->next = NULL;
57
58 if (!queue->head) {
59 /* Queue is empty at the moment */
60 queue->head = next;
61 } else {
62 /* Queue already contains at least one sequence */
63 queue->tail->next = next;
64 }
65
66 queue->tail = next;
67 } else {
68 free(next);
69 next = NULL;
70 }
71 }
72
73 if (!next)
74 LOG_ERROR("Not enough memory");
75
76 return next;
77 }
78
79 static void queue_drop_head(struct queue *queue)
80 {
81 struct sequence *head = queue->head->next; /* New head */
82 free(queue->head->tms);
83 free(queue->head);
84 queue->head = head;
85 }
86
87 static void queue_free(struct queue *queue)
88 {
89 if (queue) {
90 while (queue->head)
91 queue_drop_head(queue);
92
93 free(queue);
94 }
95 }
96
97 static struct queue *queue_alloc(void)
98 {
99 struct queue *queue = malloc(sizeof(*queue));
100 if (queue)
101 queue->head = NULL;
102 else
103 LOG_ERROR("Not enough memory");
104
105 return queue;
106 }
107
108 /* Size of usb communication buffer */
109 #define OSBDM_USB_BUFSIZE 64
110 /* Timeout for USB transfer, ms */
111 #define OSBDM_USB_TIMEOUT 1000
112 /* Write end point */
113 #define OSBDM_USB_EP_WRITE 0x01
114 /* Read end point */
115 #define OSBDM_USB_EP_READ 0x82
116
117 /* Initialize OSBDM device */
118 #define OSBDM_CMD_INIT 0x11
119 /* Execute special, not-BDM command. But only this
120 * command is used for JTAG operation */
121 #define OSBDM_CMD_SPECIAL 0x27
122 /* Execute JTAG swap (tms/tdi -> tdo) */
123 #define OSBDM_CMD_SPECIAL_SWAP 0x05
124 /* Reset control */
125 #define OSBDM_CMD_SPECIAL_SRST 0x01
126 /* Maximum bit-length in one swap */
127 #define OSBDM_SWAP_MAX (((OSBDM_USB_BUFSIZE - 6) / 5) * 16)
128
129 /* Lists of valid VID/PID pairs
130 */
131 static const uint16_t osbdm_vid[] = { 0x15a2, 0x15a2, 0x15a2, 0 };
132 static const uint16_t osbdm_pid[] = { 0x0042, 0x0058, 0x005e, 0 };
133
134 struct osbdm {
135 struct libusb_device_handle *devh; /* USB handle */
136 uint8_t buffer[OSBDM_USB_BUFSIZE]; /* Data to send and receive */
137 int count; /* Count data to send and to read */
138 };
139
140 /* osbdm instance
141 */
142 static struct osbdm osbdm_context;
143
144 static int osbdm_send_and_recv(struct osbdm *osbdm)
145 {
146 /* Send request */
147 int count, ret;
148
149 ret = jtag_libusb_bulk_write(osbdm->devh, OSBDM_USB_EP_WRITE,
150 (char *)osbdm->buffer, osbdm->count,
151 OSBDM_USB_TIMEOUT, &count);
152 if (ret || count != osbdm->count) {
153 LOG_ERROR("OSBDM communication error: can't write");
154 return ERROR_FAIL;
155 }
156
157 /* Save command code for next checking */
158 uint8_t cmd_saved = osbdm->buffer[0];
159
160 /* Reading answer */
161 ret = jtag_libusb_bulk_read(osbdm->devh, OSBDM_USB_EP_READ,
162 (char *)osbdm->buffer, OSBDM_USB_BUFSIZE,
163 OSBDM_USB_TIMEOUT, &osbdm->count);
164 /* Now perform basic checks for data sent by BDM device
165 */
166 if (ret) {
167 LOG_ERROR("OSBDM communication error: can't read");
168 return ERROR_FAIL;
169 }
170
171 if (osbdm->count < 2) {
172 LOG_ERROR("OSBDM communication error: reply too small");
173 return ERROR_FAIL;
174 }
175
176 if (osbdm->count != osbdm->buffer[1]) {
177 LOG_ERROR("OSBDM communication error: reply size mismatch");
178 return ERROR_FAIL;
179 }
180
181 if (cmd_saved != osbdm->buffer[0]) {
182 LOG_ERROR("OSBDM communication error: reply command mismatch");
183 return ERROR_FAIL;
184 }
185
186 return ERROR_OK;
187 }
188
189 static int osbdm_srst(struct osbdm *osbdm, int srst)
190 {
191 osbdm->count = 0;
192 (void)memset(osbdm->buffer, 0, OSBDM_USB_BUFSIZE);
193
194 /* Composing request
195 */
196 osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL; /* Command */
197 osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL_SRST; /* Subcommand */
198 /* Length in bytes - not used */
199 osbdm->buffer[osbdm->count++] = 0;
200 osbdm->buffer[osbdm->count++] = 0;
201 /* SRST state */
202 osbdm->buffer[osbdm->count++] = (srst ? 0 : 0x08);
203
204 /* Sending data
205 */
206 if (osbdm_send_and_recv(osbdm) != ERROR_OK)
207 return ERROR_FAIL;
208
209 return ERROR_OK;
210 }
211
212 static int osbdm_swap(struct osbdm *osbdm, void *tms, void *tdi,
213 void *tdo, int length)
214 {
215 if (length > OSBDM_SWAP_MAX) {
216 LOG_ERROR("BUG: bit sequence too long");
217 return ERROR_FAIL;
218 }
219
220 if (length <= 0) {
221 LOG_ERROR("BUG: bit sequence equal or less than 0");
222 return ERROR_FAIL;
223 }
224
225 int swap_count = DIV_ROUND_UP(length, 16);
226
227 /* cleanup */
228 osbdm->count = 0;
229 (void)memset(osbdm->buffer, 0, OSBDM_USB_BUFSIZE);
230
231 /* Composing request
232 */
233
234 osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL; /* Command */
235 osbdm->buffer[osbdm->count++] = OSBDM_CMD_SPECIAL_SWAP; /* Subcommand */
236 /* Length in bytes - not used */
237 osbdm->buffer[osbdm->count++] = 0;
238 osbdm->buffer[osbdm->count++] = 0;
239 /* Swap count */
240 osbdm->buffer[osbdm->count++] = 0;
241 osbdm->buffer[osbdm->count++] = (uint8_t)swap_count;
242
243 for (int bit_idx = 0; bit_idx < length; ) {
244 /* Bit count in swap */
245 int bit_count = length - bit_idx;
246 if (bit_count > 16)
247 bit_count = 16;
248
249 osbdm->buffer[osbdm->count++] = (uint8_t)bit_count;
250
251 /* Copying TMS and TDI data to output buffer */
252 uint32_t tms_data = buf_get_u32(tms, bit_idx, bit_count);
253 uint32_t tdi_data = buf_get_u32(tdi, bit_idx, bit_count);
254 osbdm->buffer[osbdm->count++] = (uint8_t)(tdi_data >> 8);
255 osbdm->buffer[osbdm->count++] = (uint8_t)tdi_data;
256 osbdm->buffer[osbdm->count++] = (uint8_t)(tms_data >> 8);
257 osbdm->buffer[osbdm->count++] = (uint8_t)tms_data;
258
259 /* Next bit offset */
260 bit_idx += bit_count;
261 }
262
263 assert(osbdm->count <= OSBDM_USB_BUFSIZE);
264
265 /* Sending data
266 */
267 if (osbdm_send_and_recv(osbdm) != ERROR_OK)
268 return ERROR_FAIL;
269
270 /* Extra check
271 */
272 if (((osbdm->buffer[2] << 8) | osbdm->buffer[3]) != 2 * swap_count) {
273 LOG_ERROR("OSBDM communication error: invalid swap command reply");
274 return ERROR_FAIL;
275 }
276
277 /* Copy TDO response
278 */
279 uint8_t *buffer = osbdm->buffer + 4;
280 for (int bit_idx = 0; bit_idx < length; ) {
281 int bit_count = length - bit_idx;
282 if (bit_count > 16)
283 bit_count = 16;
284
285 /* Prepare data */
286 uint32_t tdo_data = 0;
287 tdo_data |= (*buffer++) << 8;
288 tdo_data |= (*buffer++);
289 tdo_data >>= (16 - bit_count);
290
291 /* Copy TDO to return */
292 buf_set_u32(tdo, bit_idx, bit_count, tdo_data);
293
294 bit_idx += bit_count;
295 }
296
297 return ERROR_OK;
298 }
299
300 static int osbdm_flush(struct osbdm *osbdm, struct queue *queue)
301 {
302 uint8_t tms[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
303 uint8_t tdi[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
304 uint8_t tdo[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
305
306 int seq_back_len = 0;
307
308 while (queue->head) {
309 (void)memset(tms, 0, sizeof(tms));
310 (void)memset(tdi, 0, sizeof(tdi));
311 (void)memset(tdo, 0, sizeof(tdo));
312
313 int seq_len;
314 int swap_len;
315 struct sequence *seq;
316
317 /* Copy from queue to tms/tdi streams
318 */
319 seq = queue->head;
320 seq_len = seq_back_len;
321 swap_len = 0;
322
323 while (seq && swap_len != OSBDM_SWAP_MAX) {
324 /* Count bit for copy at this iteration.
325 * len should fit into remaining space
326 * in tms/tdo bitstreams
327 */
328 int len = seq->len - seq_len;
329 if (len > OSBDM_SWAP_MAX - swap_len)
330 len = OSBDM_SWAP_MAX - swap_len;
331
332 /* Set tms data */
333 buf_set_buf(seq->tms, seq_len, tms, swap_len, len);
334
335 /* Set tdi data if they exists */
336 if (seq->tdi)
337 buf_set_buf(seq->tdi, seq_len, tdi, swap_len, len);
338
339 swap_len += len;
340 seq_len += len;
341 if (seq_len == seq->len) {
342 seq = seq->next; /* Move to next sequence */
343 seq_len = 0;
344 }
345 }
346
347 if (osbdm_swap(osbdm, tms, tdi, tdo, swap_len))
348 return ERROR_FAIL;
349
350 /* Copy from tdo stream to queue
351 */
352
353 for (int swap_back_len = 0; swap_back_len < swap_len; ) {
354 int len = queue->head->len - seq_back_len;
355 if (len > swap_len - swap_back_len)
356 len = swap_len - swap_back_len;
357
358 if (queue->head->tdo)
359 buf_set_buf(tdo, swap_back_len, queue->head->tdo, seq_back_len, len);
360
361 swap_back_len += len;
362 seq_back_len += len;
363 if (seq_back_len == queue->head->len) {
364 queue_drop_head(queue);
365 seq_back_len = 0;
366 }
367 }
368 }
369
370 return ERROR_OK;
371 }
372
373 /* Basic operation for opening USB device */
374 static int osbdm_open(struct osbdm *osbdm)
375 {
376 (void)memset(osbdm, 0, sizeof(*osbdm));
377 if (jtag_libusb_open(osbdm_vid, osbdm_pid, &osbdm->devh, NULL) != ERROR_OK)
378 return ERROR_FAIL;
379
380 if (libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
381 return ERROR_FAIL;
382
383 return ERROR_OK;
384 }
385
386 static int osbdm_quit(void)
387 {
388 jtag_libusb_close(osbdm_context.devh);
389 return ERROR_OK;
390 }
391
392 static int osbdm_add_pathmove(
393 struct queue *queue,
394 tap_state_t *path,
395 int num_states)
396 {
397 assert(num_states <= 32);
398
399 struct sequence *next = queue_add_tail(queue, num_states);
400 if (!next) {
401 LOG_ERROR("BUG: can't allocate bit sequence");
402 return ERROR_FAIL;
403 }
404
405 uint32_t tms = 0;
406 for (int i = 0; i < num_states; i++) {
407 if (tap_state_transition(tap_get_state(), 1) == path[i]) {
408 tms |= (1 << i);
409 } else if (tap_state_transition(tap_get_state(), 0) == path[i]) {
410 tms &= ~(1 << i); /* This line not so needed */
411 } else {
412 LOG_ERROR("BUG: %s -> %s isn't a valid TAP state transition",
413 tap_state_name(tap_get_state()),
414 tap_state_name(path[i]));
415 return ERROR_FAIL;
416 }
417
418 tap_set_state(path[i]);
419 }
420
421 buf_set_u32(next->tms, 0, num_states, tms);
422 tap_set_end_state(tap_get_state());
423
424 return ERROR_OK;
425 }
426
427 static int osbdm_add_statemove(
428 struct queue *queue,
429 tap_state_t new_state,
430 int skip_first)
431 {
432 int len = 0;
433 int tms = 0;
434
435 tap_set_end_state(new_state);
436 if (tap_get_end_state() == TAP_RESET) {
437 /* Ignore current state */
438 tms = 0xff;
439 len = 5;
440 } else if (tap_get_state() != tap_get_end_state()) {
441 tms = tap_get_tms_path(tap_get_state(), new_state);
442 len = tap_get_tms_path_len(tap_get_state(), new_state);
443 }
444
445 if (len && skip_first) {
446 len--;
447 tms >>= 1;
448 }
449
450 if (len) {
451 struct sequence *next = queue_add_tail(queue, len);
452 if (!next) {
453 LOG_ERROR("BUG: can't allocate bit sequence");
454 return ERROR_FAIL;
455 }
456 buf_set_u32(next->tms, 0, len, tms);
457 }
458
459 tap_set_state(tap_get_end_state());
460 return ERROR_OK;
461 }
462
463 static int osbdm_add_stableclocks(
464 struct queue *queue,
465 int count)
466 {
467 if (!tap_is_state_stable(tap_get_state())) {
468 LOG_ERROR("BUG: current state (%s) is not stable",
469 tap_state_name(tap_get_state()));
470 return ERROR_FAIL;
471 }
472
473 struct sequence *next = queue_add_tail(queue, count);
474 if (!next) {
475 LOG_ERROR("BUG: can't allocate bit sequence");
476 return ERROR_FAIL;
477 }
478
479 if (tap_get_state() == TAP_RESET)
480 (void)memset(next->tms, 0xff, DIV_ROUND_UP(count, 8));
481
482 return ERROR_OK;
483 }
484
485 static int osbdm_add_tms(
486 struct queue *queue,
487 const uint8_t *tms,
488 int num_bits)
489 {
490 struct sequence *next = queue_add_tail(queue, num_bits);
491 if (!next) {
492 LOG_ERROR("BUG: can't allocate bit sequence");
493 return ERROR_FAIL;
494 }
495 buf_set_buf(tms, 0, next->tms, 0, num_bits);
496
497 return ERROR_OK;
498 }
499
500 static int osbdm_add_scan(
501 struct queue *queue,
502 struct scan_field *fields,
503 int num_fields,
504 tap_state_t end_state,
505 bool ir_scan)
506 {
507 /* Move to desired shift state */
508 if (ir_scan) {
509 if (tap_get_state() != TAP_IRSHIFT) {
510 if (osbdm_add_statemove(queue, TAP_IRSHIFT, 0) != ERROR_OK)
511 return ERROR_FAIL;
512 }
513 } else {
514 if (tap_get_state() != TAP_DRSHIFT) {
515 if (osbdm_add_statemove(queue, TAP_DRSHIFT, 0) != ERROR_OK)
516 return ERROR_FAIL;
517 }
518 }
519
520 /* Add scan */
521 tap_set_end_state(end_state);
522 for (int idx = 0; idx < num_fields; idx++) {
523 struct sequence *next = queue_add_tail(queue, fields[idx].num_bits);
524 if (!next) {
525 LOG_ERROR("Can't allocate bit sequence");
526 return ERROR_FAIL;
527 }
528
529 (void)memset(next->tms, 0, DIV_ROUND_UP(fields[idx].num_bits, 8));
530 next->tdi = fields[idx].out_value;
531 next->tdo = fields[idx].in_value;
532 }
533
534 /* Move to end state
535 */
536 if (tap_get_state() != tap_get_end_state()) {
537 /* Exit from IRSHIFT/DRSHIFT */
538 buf_set_u32(queue->tail->tms, queue->tail->len - 1, 1, 1);
539
540 /* Move with skip_first flag */
541 if (osbdm_add_statemove(queue, tap_get_end_state(), 1) != ERROR_OK)
542 return ERROR_FAIL;
543 }
544
545 return ERROR_OK;
546 }
547
548 static int osbdm_add_runtest(
549 struct queue *queue,
550 int num_cycles,
551 tap_state_t end_state)
552 {
553 if (osbdm_add_statemove(queue, TAP_IDLE, 0) != ERROR_OK)
554 return ERROR_FAIL;
555
556 if (osbdm_add_stableclocks(queue, num_cycles) != ERROR_OK)
557 return ERROR_FAIL;
558
559 if (osbdm_add_statemove(queue, end_state, 0) != ERROR_OK)
560 return ERROR_FAIL;
561
562 return ERROR_OK;
563 }
564
565 static int osbdm_execute_command(
566 struct osbdm *osbdm,
567 struct queue *queue,
568 struct jtag_command *cmd)
569 {
570 int retval = ERROR_OK;
571
572 switch (cmd->type) {
573 case JTAG_RESET:
574 if (cmd->cmd.reset->trst) {
575 LOG_ERROR("BUG: nTRST signal is not supported");
576 retval = ERROR_FAIL;
577 } else {
578 retval = osbdm_flush(osbdm, queue);
579 if (retval == ERROR_OK)
580 retval = osbdm_srst(osbdm, cmd->cmd.reset->srst);
581 }
582 break;
583
584 case JTAG_PATHMOVE:
585 retval = osbdm_add_pathmove(
586 queue,
587 cmd->cmd.pathmove->path,
588 cmd->cmd.pathmove->num_states);
589 break;
590
591 case JTAG_TLR_RESET:
592 retval = osbdm_add_statemove(
593 queue,
594 cmd->cmd.statemove->end_state,
595 0);
596 break;
597
598 case JTAG_STABLECLOCKS:
599 retval = osbdm_add_stableclocks(
600 queue,
601 cmd->cmd.stableclocks->num_cycles);
602 break;
603
604 case JTAG_TMS:
605 retval = osbdm_add_tms(
606 queue,
607 cmd->cmd.tms->bits,
608 cmd->cmd.tms->num_bits);
609 break;
610
611 case JTAG_SCAN:
612 retval = osbdm_add_scan(
613 queue,
614 cmd->cmd.scan->fields,
615 cmd->cmd.scan->num_fields,
616 cmd->cmd.scan->end_state,
617 cmd->cmd.scan->ir_scan);
618 break;
619
620 case JTAG_SLEEP:
621 retval = osbdm_flush(osbdm, queue);
622 if (retval == ERROR_OK)
623 jtag_sleep(cmd->cmd.sleep->us);
624 break;
625
626 case JTAG_RUNTEST:
627 retval = osbdm_add_runtest(
628 queue,
629 cmd->cmd.runtest->num_cycles,
630 cmd->cmd.runtest->end_state);
631 break;
632
633 default:
634 LOG_ERROR("BUG: unknown JTAG command type encountered");
635 retval = ERROR_FAIL;
636 break;
637 }
638
639 return retval;
640 }
641
642 static int osbdm_execute_queue(void)
643 {
644 int retval = ERROR_OK;
645
646 struct queue *queue = queue_alloc();
647 if (!queue) {
648 LOG_ERROR("BUG: can't allocate bit queue");
649 retval = ERROR_FAIL;
650 } else {
651 struct jtag_command *cmd = jtag_command_queue;
652
653 while (retval == ERROR_OK && cmd) {
654 retval = osbdm_execute_command(&osbdm_context, queue, cmd);
655 cmd = cmd->next;
656 }
657
658 if (retval == ERROR_OK)
659 retval = osbdm_flush(&osbdm_context, queue);
660
661 queue_free(queue);
662 }
663
664 if (retval != ERROR_OK) {
665 LOG_ERROR("FATAL: can't execute jtag command");
666 exit(-1);
667 }
668
669 return retval;
670 }
671
672 static int osbdm_init(void)
673 {
674 /* Open device */
675 if (osbdm_open(&osbdm_context) != ERROR_OK) {
676 LOG_ERROR("Can't open OSBDM device");
677 return ERROR_FAIL;
678 } else {
679 /* Device successfully opened */
680 LOG_DEBUG("OSBDM init");
681 }
682
683 /* Perform initialize command */
684 osbdm_context.count = 0;
685 osbdm_context.buffer[osbdm_context.count++] = OSBDM_CMD_INIT;
686 if (osbdm_send_and_recv(&osbdm_context) != ERROR_OK)
687 return ERROR_FAIL;
688
689 return ERROR_OK;
690 }
691
692 static struct jtag_interface osbdm_interface = {
693 .execute_queue = osbdm_execute_queue,
694 };
695
696 struct adapter_driver osbdm_adapter_driver = {
697 .name = "osbdm",
698 .transports = jtag_only,
699
700 .init = osbdm_init,
701 .quit = osbdm_quit,
702
703 .jtag_ops = &osbdm_interface,
704 };

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)