versaloon driver update
[openocd.git] / src / jtag / drivers / versaloon / usbtoxxx / usbtoxxx.c
1 /***************************************************************************
2 * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <string.h>
24
25 #include "../versaloon_include.h"
26 #include "../versaloon.h"
27 #include "../versaloon_internal.h"
28 #include "usbtoxxx.h"
29 #include "usbtoxxx_internal.h"
30
31 #define N_A "n/a"
32 const char* types_name[96] =
33 {
34 "usbtousart", "usbtospi", "usbtoi2c", "usbtogpio", "usbtocan", "usbtopwm",
35 "usbtoadc", "usbtodac",
36 "usbtomicrowire", "usbtoswim", "usbtodusi", N_A, N_A, N_A, "usbtopower", "usbtodelay",
37 N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
38 N_A, N_A, N_A, N_A, N_A, N_A, N_A,
39 "usbtojtagll", "usbtojtaghl", "usbtoissp", "usbtoc2", "usbtosbw",
40 "usbtolpcicp", "usbtoswd", "usbtojtagraw",
41 "usbtobdm", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
42 N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
43 "usbtomsp430jtag", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
44 "usbtopower", "usbtodelay", "usbtopoll", N_A, N_A, N_A, N_A, N_A,
45 N_A, N_A, N_A, N_A, N_A, N_A, N_A, "usbtoall"
46 };
47
48 uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN];
49
50 #define usbtoxxx_get_type_name(type) \
51 types_name[((type) - VERSALOON_USB_TO_XXX_CMD_START) \
52 % (sizeof(types_name) / sizeof(types_name[0]))]
53
54 static uint8_t type_pre = 0;
55 static uint16_t usbtoxxx_buffer_index = 0;
56 static uint16_t usbtoxxx_current_cmd_index = 0;
57 static uint8_t *usbtoxxx_buffer = NULL;
58
59 uint16_t collect_index = 0;
60 uint8_t collect_cmd;
61 static uint8_t poll_nesting = 0;
62
63 struct usbtoxxx_context_t
64 {
65 uint8_t type_pre;
66 uint8_t *usbtoxxx_buffer;
67 uint16_t usbtoxxx_current_cmd_index;
68 uint16_t usbtoxxx_buffer_index;
69 uint16_t versaloon_pending_idx;
70 };
71 static struct usbtoxxx_context_t poll_context;
72
73 static void usbtoxxx_save_context(struct usbtoxxx_context_t *c)
74 {
75 c->type_pre = type_pre;
76 c->usbtoxxx_buffer = usbtoxxx_buffer;
77 c->usbtoxxx_buffer_index = usbtoxxx_buffer_index;
78 c->usbtoxxx_current_cmd_index = usbtoxxx_current_cmd_index;
79 c->versaloon_pending_idx = versaloon_pending_idx;
80 }
81
82 static void usbtoxxx_pop_context(struct usbtoxxx_context_t *c)
83 {
84 type_pre = c->type_pre;
85 usbtoxxx_buffer = c->usbtoxxx_buffer;
86 usbtoxxx_buffer_index = c->usbtoxxx_buffer_index;
87 usbtoxxx_current_cmd_index = c->usbtoxxx_current_cmd_index;
88 versaloon_pending_idx = c->versaloon_pending_idx;
89 }
90
91 RESULT usbtoxxx_validate_current_command_type(void)
92 {
93 if (type_pre > 0)
94 {
95 // not the first command
96 if (NULL == usbtoxxx_buffer)
97 {
98 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(usbtoxxx_buffer));
99 return ERRCODE_INVALID_BUFFER;
100 }
101
102 usbtoxxx_buffer[0] = type_pre;
103 SET_LE_U16(&usbtoxxx_buffer[1], usbtoxxx_current_cmd_index);
104
105 usbtoxxx_buffer_index += usbtoxxx_current_cmd_index;
106 }
107 else
108 {
109 // first command
110 usbtoxxx_buffer_index = 3;
111 }
112
113 // prepare for next command
114 usbtoxxx_current_cmd_index = 3;
115 usbtoxxx_buffer = versaloon_buf + usbtoxxx_buffer_index;
116
117 collect_index = 0;
118 collect_cmd = 0;
119
120 return ERROR_OK;
121 }
122
123
124
125 RESULT usbtoxxx_execute_command(void)
126 {
127 uint16_t i;
128 uint16_t inlen;
129 RESULT result = ERROR_OK;
130
131 if (poll_nesting)
132 {
133 LOG_BUG(ERRMSG_INVALID_USAGE, "USB_TO_POLL");
134 versaloon_free_want_pos();
135 return ERROR_FAIL;
136 }
137
138 if (ERROR_OK != usbtoxxx_validate_current_command_type())
139 {
140 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
141 versaloon_free_want_pos();
142 return ERRCODE_FAILURE_OPERATION;
143 }
144 if (3 == usbtoxxx_buffer_index)
145 {
146 versaloon_free_want_pos();
147 return ERROR_OK;
148 }
149
150 versaloon_buf[0] = USB_TO_ALL;
151 SET_LE_U16(&versaloon_buf[1], usbtoxxx_buffer_index);
152
153 if (ERROR_OK != versaloon_send_command(usbtoxxx_buffer_index, &inlen))
154 {
155 versaloon_free_want_pos();
156 return ERROR_FAIL;
157 }
158
159 // process return data
160 usbtoxxx_buffer_index = 0;
161 for (i = 0; i < versaloon_pending_idx; i++)
162 {
163 // check result
164 if ((0 == i) || !((versaloon_pending[i].collect)
165 && (versaloon_pending[i - 1].collect)
166 && (versaloon_pending[i].cmd
167 == versaloon_pending[i - 1].cmd)))
168 {
169 if (USB_TO_XXX_CMD_NOT_SUPPORT
170 == versaloon_buf[usbtoxxx_buffer_index])
171 {
172 LOG_ERROR(ERRMSG_NOT_SUPPORT_BY,
173 usbtoxxx_get_type_name(versaloon_pending[i].type),
174 "current dongle");
175 result = ERROR_FAIL;
176 break;
177 }
178 else if (USB_TO_XXX_OK != versaloon_buf[usbtoxxx_buffer_index])
179 {
180 LOG_ERROR("%s command 0x%02x failed with 0x%02x",
181 usbtoxxx_get_type_name(versaloon_pending[i].type),
182 versaloon_pending[i].cmd,
183 versaloon_buf[usbtoxxx_buffer_index]);
184 result = ERROR_FAIL;
185 break;
186 }
187 usbtoxxx_buffer_index++;
188 }
189
190 // get result data
191 if (versaloon_pending[i].pos != NULL)
192 {
193 uint8_t processed = 0;
194
195 if (versaloon_pending[i].callback != NULL)
196 {
197 versaloon_pending[i].callback(&versaloon_pending[i],
198 versaloon_buf + usbtoxxx_buffer_index, &processed);
199 }
200 if (!processed)
201 {
202 struct versaloon_want_pos_t *tmp, *free_tmp;
203
204 free_tmp = tmp = versaloon_pending[i].pos;
205 while (tmp != NULL)
206 {
207 if ((tmp->buff != NULL) && (tmp->size > 0))
208 {
209 memcpy(tmp->buff, versaloon_buf + usbtoxxx_buffer_index
210 + tmp->offset, tmp->size);
211 }
212 free_tmp = tmp;
213 tmp = tmp->next;
214 free(free_tmp);
215 }
216 versaloon_pending[i].pos = NULL;
217 }
218 }
219 else if ((versaloon_pending[i].want_data_size > 0)
220 && (versaloon_pending[i].data_buffer != NULL))
221 {
222 uint8_t processed = 0;
223
224 if (versaloon_pending[i].callback != NULL)
225 {
226 versaloon_pending[i].callback(&versaloon_pending[i],
227 versaloon_buf + usbtoxxx_buffer_index, &processed);
228 }
229 if (!processed)
230 {
231 memcpy(versaloon_pending[i].data_buffer,
232 versaloon_buf + usbtoxxx_buffer_index
233 + versaloon_pending[i].want_data_pos,
234 versaloon_pending[i].want_data_size);
235 }
236 }
237 usbtoxxx_buffer_index += versaloon_pending[i].actual_data_size;
238 if (usbtoxxx_buffer_index > inlen)
239 {
240 LOG_BUG("%s command 0x%02x process error",
241 usbtoxxx_get_type_name(versaloon_pending[i].type),
242 versaloon_pending[i].cmd);
243 result = ERROR_FAIL;
244 break;
245 }
246 }
247
248 // data is not the right size
249 if (inlen != usbtoxxx_buffer_index)
250 {
251 LOG_ERROR(ERRMSG_INVALID_TARGET, "length of return data");
252 result = ERROR_FAIL;
253 }
254
255 if (versaloon_pending_idx > 0)
256 {
257 versaloon_pending_idx = 0;
258 }
259 else
260 {
261 // no receive data, avoid collision
262 sleep_ms(10);
263 }
264
265 type_pre = 0;
266 collect_cmd = 0;
267 collect_index = 0;
268 versaloon_free_want_pos();
269 return result;
270 }
271
272 RESULT usbtoxxx_init(void)
273 {
274 versaloon_pending_idx = 0;
275
276 if ((ERROR_OK != usbtoinfo_get_abilities(usbtoxxx_abilities)) ||
277 (ERROR_OK != usbtoxxx_execute_command()))
278 {
279 return ERROR_FAIL;
280 }
281 LOG_INFO("USB_TO_XXX abilities: 0x%08X:0x%08X:0x%08X",
282 GET_LE_U32(&usbtoxxx_abilities[0]),
283 GET_LE_U32(&usbtoxxx_abilities[4]),
284 GET_LE_U32(&usbtoxxx_abilities[8]));
285 return ERROR_OK;
286 }
287
288 RESULT usbtoxxx_fini(void)
289 {
290 usbtoxxx_buffer = NULL;
291 type_pre = 0;
292 return ERROR_OK;
293 }
294
295 bool usbtoxxx_interface_supported(uint8_t cmd)
296 {
297 if ((cmd < VERSALOON_USB_TO_XXX_CMD_START) ||
298 (cmd > VERSALOON_USB_TO_XXX_CMD_END))
299 {
300 return false;
301 }
302
303 cmd -= VERSALOON_USB_TO_XXX_CMD_START;
304 return (usbtoxxx_abilities[cmd / 8] & (1 << (cmd % 8))) > 0;
305 }
306
307
308
309 RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen)
310 {
311 // check free space, commit if not enough
312 if (((usbtoxxx_buffer_index + usbtoxxx_current_cmd_index + cmdlen)
313 >= versaloon_buf_size)
314 || (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER))
315 {
316 struct usbtoxxx_context_t context_tmp;
317 uint8_t poll_nesting_tmp = 0;
318
319 memset(&context_tmp, 0, sizeof(context_tmp));
320 if (poll_nesting)
321 {
322 if (0 == poll_context.type_pre)
323 {
324 LOG_BUG("USB_TO_POLL toooooo long");
325 return ERROR_OK;
326 }
327
328 usbtoxxx_save_context(&context_tmp);
329 usbtoxxx_pop_context(&poll_context);
330 poll_nesting_tmp = poll_nesting;
331 poll_nesting = 0;
332 }
333
334 if (usbtoxxx_execute_command() != ERROR_OK)
335 {
336 return ERROR_FAIL;
337 }
338
339 if (poll_nesting_tmp)
340 {
341 uint16_t newlen, oldlen;
342
343 newlen = context_tmp.versaloon_pending_idx
344 - poll_context.versaloon_pending_idx;
345 memcpy(&versaloon_pending[0],
346 &versaloon_pending[poll_context.versaloon_pending_idx],
347 sizeof(versaloon_pending[0]) * newlen);
348 context_tmp.versaloon_pending_idx = newlen;
349 oldlen = poll_context.usbtoxxx_buffer_index
350 + poll_context.usbtoxxx_current_cmd_index;
351 newlen = context_tmp.usbtoxxx_buffer_index
352 + context_tmp.usbtoxxx_current_cmd_index;
353 memcpy(versaloon_buf + 3, versaloon_buf + oldlen, newlen - oldlen);
354 oldlen -= 3;
355 context_tmp.usbtoxxx_buffer -= oldlen;
356 context_tmp.usbtoxxx_buffer_index -= oldlen;
357 usbtoxxx_pop_context(&context_tmp);
358 poll_nesting = poll_nesting_tmp;
359 }
360 }
361 return ERROR_OK;
362 }
363
364 RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf,
365 uint16_t cmdlen, uint16_t retlen, uint8_t *wantbuf,
366 uint16_t wantpos, uint16_t wantlen, uint8_t collect)
367 {
368 uint16_t len_tmp;
369
370 // 3 more bytes by usbtoxxx_validate_current_command_type
371 // 3 more bytes when ((0 == collect_index) || (collect_cmd != cmd))
372 if (ERROR_OK != usbtoxxx_ensure_buffer_size(cmdlen + 6))
373 {
374 return ERROR_FAIL;
375 }
376
377 if ((type_pre != type) || (NULL == usbtoxxx_buffer))
378 {
379 if (ERROR_OK != usbtoxxx_validate_current_command_type())
380 {
381 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
382 return ERRCODE_FAILURE_OPERATION;
383 }
384 type_pre = type;
385 }
386
387 if ((0 == collect_index) || (collect_cmd != cmd))
388 {
389 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = cmd;
390
391 if (collect)
392 {
393 collect_index = usbtoxxx_current_cmd_index;
394 collect_cmd = cmd;
395 }
396 else
397 {
398 collect_index = 0;
399 collect_cmd = 0;
400 }
401 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], cmdlen);
402 usbtoxxx_current_cmd_index += 2;
403 }
404 else
405 {
406 len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen;
407 SET_LE_U16(&usbtoxxx_buffer[collect_index], len_tmp);
408 }
409
410 if (cmdbuf != NULL)
411 {
412 memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen);
413 usbtoxxx_current_cmd_index += cmdlen;
414 }
415
416 return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen,
417 wantbuf, collect);
418 }
419
420
421
422
423
424 RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN])
425 {
426 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3))
427 {
428 return ERROR_FAIL;
429 }
430
431 if (ERROR_OK != usbtoxxx_validate_current_command_type())
432 {
433 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
434 return ERRCODE_FAILURE_OPERATION;
435 }
436 type_pre = USB_TO_INFO;
437
438 return versaloon_add_pending(USB_TO_INFO, 0, USB_TO_XXX_ABILITIES_LEN, 0,
439 USB_TO_XXX_ABILITIES_LEN, abilities, 0);
440 }
441
442
443
444
445 RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us)
446 {
447 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5))
448 {
449 return ERROR_FAIL;
450 }
451 if (!poll_nesting)
452 {
453 usbtoxxx_save_context(&poll_context);
454 }
455
456 if (ERROR_OK != usbtoxxx_validate_current_command_type())
457 {
458 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
459 return ERRCODE_FAILURE_OPERATION;
460 }
461 poll_nesting++;
462 type_pre = USB_TO_POLL;
463
464 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_START;
465 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], retry_cnt);
466 usbtoxxx_current_cmd_index += 2;
467 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], interval_us);
468 usbtoxxx_current_cmd_index += 2;
469
470 return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
471 }
472
473 RESULT usbtopoll_end(void)
474 {
475 if (!poll_nesting)
476 {
477 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
478 return ERRCODE_FAILURE_OPERATION;
479 }
480 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 1))
481 {
482 return ERROR_FAIL;
483 }
484
485 if (ERROR_OK != usbtoxxx_validate_current_command_type())
486 {
487 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
488 return ERRCODE_FAILURE_OPERATION;
489 }
490
491 poll_nesting--;
492 type_pre = USB_TO_POLL;
493
494 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_END;
495
496 return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
497 }
498
499 RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size,
500 uint32_t mask, uint32_t value)
501 {
502 uint8_t i;
503
504 if (size > 4)
505 {
506 LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__);
507 return ERRCODE_INVALID_PARAMETER;
508 }
509 if (!poll_nesting)
510 {
511 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
512 return ERRCODE_FAILURE_OPERATION;
513 }
514 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
515 {
516 return ERROR_FAIL;
517 }
518
519 if (ERROR_OK != usbtoxxx_validate_current_command_type())
520 {
521 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
522 return ERRCODE_FAILURE_OPERATION;
523 }
524
525 type_pre = USB_TO_POLL;
526
527 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKOK;
528 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
529 usbtoxxx_current_cmd_index += 2;
530 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
531 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
532 for (i =0; i < size; i++)
533 {
534 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
535 }
536 for (i =0; i < size; i++)
537 {
538 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
539 }
540
541 return ERROR_OK;
542 }
543
544 RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size,
545 uint32_t mask, uint32_t value)
546 {
547 uint8_t i;
548
549 if (size > 4)
550 {
551 LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__);
552 return ERRCODE_INVALID_PARAMETER;
553 }
554 if (!poll_nesting)
555 {
556 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
557 return ERRCODE_FAILURE_OPERATION;
558 }
559 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
560 {
561 return ERROR_FAIL;
562 }
563
564 if (ERROR_OK != usbtoxxx_validate_current_command_type())
565 {
566 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
567 return ERRCODE_FAILURE_OPERATION;
568 }
569
570 type_pre = USB_TO_POLL;
571
572 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKFAIL;
573 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
574 usbtoxxx_current_cmd_index += 2;
575 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
576 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
577 for (i =0; i < size; i++)
578 {
579 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
580 }
581 for (i =0; i < size; i++)
582 {
583 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
584 }
585
586 return ERROR_OK;
587 }
588
589 RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff)
590 {
591 if (!poll_nesting)
592 {
593 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
594 return ERRCODE_FAILURE_OPERATION;
595 }
596 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5 + size))
597 {
598 return ERROR_FAIL;
599 }
600
601 if (ERROR_OK != usbtoxxx_validate_current_command_type())
602 {
603 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
604 return ERRCODE_FAILURE_OPERATION;
605 }
606
607 type_pre = USB_TO_POLL;
608
609 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_VERIFYBUFF;
610 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
611 usbtoxxx_current_cmd_index += 2;
612 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], size);
613 usbtoxxx_current_cmd_index += 2;
614 memcpy(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], buff, size);
615 usbtoxxx_current_cmd_index += size;
616
617 return ERROR_OK;
618 }
619
620
621
622
623 RESULT usbtodelay_delay(uint16_t dly)
624 {
625 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 2))
626 {
627 return ERROR_FAIL;
628 }
629
630 if (ERROR_OK != usbtoxxx_validate_current_command_type())
631 {
632 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
633 return ERRCODE_FAILURE_OPERATION;
634 }
635 type_pre = USB_TO_DELAY;
636
637 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], dly);
638 usbtoxxx_current_cmd_index += 2;
639
640 return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0);
641 }
642
643 RESULT usbtodelay_delayms(uint16_t ms)
644 {
645 return usbtodelay_delay(ms | 0x8000);
646 }
647
648 RESULT usbtodelay_delayus(uint16_t us)
649 {
650 return usbtodelay_delay(us & 0x7FFF);
651 }
652

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)