update files to correct FSF address
[fw/openocd] / 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  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
18  ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <string.h>
25
26 #include "../versaloon_include.h"
27 #include "../versaloon.h"
28 #include "../versaloon_internal.h"
29 #include "usbtoxxx.h"
30 #include "usbtoxxx_internal.h"
31
32 #define N_A "n/a"
33
34 const char *types_name[96] = {
35         "usbtousart", "usbtospi", "usbtoi2c", "usbtogpio", "usbtocan", "usbtopwm",
36         "usbtoadc", "usbtodac",
37         "usbtomicrowire", "usbtoswim", "usbtodusi", N_A, N_A, N_A, "usbtopower", "usbtodelay",
38         N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
39         N_A, N_A, N_A, N_A, N_A, N_A, N_A,
40         "usbtojtagll", "usbtojtaghl", "usbtoissp", "usbtoc2", "usbtosbw",
41         "usbtolpcicp", "usbtoswd", "usbtojtagraw",
42         "usbtobdm", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
43         N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
44         "usbtomsp430jtag", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
45         "usbtopower", "usbtodelay", "usbtopoll", N_A, N_A, N_A, N_A, N_A,
46         N_A, N_A, N_A, N_A, N_A, N_A, N_A, "usbtoall"
47 };
48
49 uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN];
50
51 #define usbtoxxx_get_type_name(type)    \
52         types_name[((type) - VERSALOON_USB_TO_XXX_CMD_START) \
53                    % (sizeof(types_name) / sizeof(types_name[0]))]
54
55 static uint8_t type_pre;
56 static uint16_t usbtoxxx_buffer_index;
57 static uint16_t usbtoxxx_current_cmd_index;
58 static uint8_t *usbtoxxx_buffer;
59
60 uint16_t collect_index;
61 uint8_t collect_cmd;
62 static uint8_t poll_nesting;
63
64 struct usbtoxxx_context_t {
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                 /* not the first command */
95                 if (NULL == usbtoxxx_buffer) {
96                         LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(usbtoxxx_buffer));
97                         return ERRCODE_INVALID_BUFFER;
98                 }
99
100                 usbtoxxx_buffer[0] = type_pre;
101                 SET_LE_U16(&usbtoxxx_buffer[1], usbtoxxx_current_cmd_index);
102
103                 usbtoxxx_buffer_index += usbtoxxx_current_cmd_index;
104         } else {
105                 /* first command */
106                 usbtoxxx_buffer_index = 3;
107         }
108
109         /* prepare for next command */
110         usbtoxxx_current_cmd_index = 3;
111         usbtoxxx_buffer = versaloon_buf + usbtoxxx_buffer_index;
112
113         collect_index = 0;
114         collect_cmd = 0;
115
116         return ERROR_OK;
117 }
118
119 RESULT usbtoxxx_execute_command(void)
120 {
121         uint16_t i;
122         uint16_t inlen;
123         RESULT result = ERROR_OK;
124
125         if (poll_nesting) {
126                 LOG_BUG(ERRMSG_INVALID_USAGE, "USB_TO_POLL");
127                 versaloon_free_want_pos();
128                 return ERROR_FAIL;
129         }
130
131         if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
132                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
133                 versaloon_free_want_pos();
134                 return ERRCODE_FAILURE_OPERATION;
135         }
136         if (3 == usbtoxxx_buffer_index) {
137                 versaloon_free_want_pos();
138                 return ERROR_OK;
139         }
140
141         versaloon_buf[0] = USB_TO_ALL;
142         SET_LE_U16(&versaloon_buf[1], usbtoxxx_buffer_index);
143
144         if (ERROR_OK != versaloon_send_command(usbtoxxx_buffer_index, &inlen)) {
145                 versaloon_free_want_pos();
146                 return ERROR_FAIL;
147         }
148
149         /* process return data */
150         usbtoxxx_buffer_index = 0;
151         for (i = 0; i < versaloon_pending_idx; i++) {
152                 /* check result */
153                 if ((0 == i) || !((versaloon_pending[i].collect)
154                                   && (versaloon_pending[i - 1].collect)
155                                   && (versaloon_pending[i].cmd
156                                       == versaloon_pending[i - 1].cmd))) {
157                         if (USB_TO_XXX_CMD_NOT_SUPPORT
158                                         == versaloon_buf[usbtoxxx_buffer_index]) {
159                                 LOG_ERROR(ERRMSG_NOT_SUPPORT_BY,
160                                         usbtoxxx_get_type_name(versaloon_pending[i].type),
161                                         "current dongle");
162                                 result = ERROR_FAIL;
163                                 break;
164                         } else if (USB_TO_XXX_OK != versaloon_buf[usbtoxxx_buffer_index]) {
165                                 LOG_ERROR("%s command 0x%02x failed with 0x%02x",
166                                         usbtoxxx_get_type_name(versaloon_pending[i].type),
167                                         versaloon_pending[i].cmd,
168                                         versaloon_buf[usbtoxxx_buffer_index]);
169                                 result = ERROR_FAIL;
170                                 break;
171                         }
172                         usbtoxxx_buffer_index++;
173                 }
174
175                 /* get result data */
176                 if (versaloon_pending[i].pos != NULL) {
177                         uint8_t processed = 0;
178
179                         if (versaloon_pending[i].callback != NULL) {
180                                 versaloon_pending[i].callback(&versaloon_pending[i],
181                                         versaloon_buf + usbtoxxx_buffer_index, &processed);
182                         }
183                         if (!processed) {
184                                 struct versaloon_want_pos_t *tmp;
185
186                                 tmp = versaloon_pending[i].pos;
187                                 while (tmp != NULL) {
188                                         if ((tmp->buff != NULL) && (tmp->size > 0)) {
189                                                 memcpy(tmp->buff,
190                                                         versaloon_buf + usbtoxxx_buffer_index
191                                                         + tmp->offset,
192                                                         tmp->size);
193                                         }
194                                         struct versaloon_want_pos_t *free_tmp;
195                                         free_tmp = tmp;
196                                         tmp = tmp->next;
197                                         free(free_tmp);
198                                 }
199                                 versaloon_pending[i].pos = NULL;
200                         }
201                 } else if ((versaloon_pending[i].want_data_size > 0)
202                                 && (versaloon_pending[i].data_buffer != NULL)) {
203                         uint8_t processed = 0;
204
205                         if (versaloon_pending[i].callback != NULL) {
206                                 versaloon_pending[i].callback(&versaloon_pending[i],
207                                         versaloon_buf + usbtoxxx_buffer_index, &processed);
208                         }
209                         if (!processed) {
210                                 memcpy(versaloon_pending[i].data_buffer,
211                                         versaloon_buf + usbtoxxx_buffer_index
212                                         + versaloon_pending[i].want_data_pos,
213                                         versaloon_pending[i].want_data_size);
214                         }
215                 }
216                 usbtoxxx_buffer_index += versaloon_pending[i].actual_data_size;
217                 if (usbtoxxx_buffer_index > inlen) {
218                         LOG_BUG("%s command 0x%02x process error",
219                                 usbtoxxx_get_type_name(versaloon_pending[i].type),
220                                 versaloon_pending[i].cmd);
221                         result = ERROR_FAIL;
222                         break;
223                 }
224         }
225
226         /* data is not the right size */
227         if (inlen != usbtoxxx_buffer_index) {
228                 LOG_ERROR(ERRMSG_INVALID_TARGET, "length of return data");
229                 result = ERROR_FAIL;
230         }
231
232         if (versaloon_pending_idx > 0)
233                 versaloon_pending_idx = 0;
234         else {
235                 /* no receive data, avoid collision */
236                 sleep_ms(10);
237         }
238
239         type_pre = 0;
240         collect_cmd = 0;
241         collect_index = 0;
242         versaloon_free_want_pos();
243         return result;
244 }
245
246 RESULT usbtoxxx_init(void)
247 {
248         versaloon_pending_idx = 0;
249
250         if ((ERROR_OK != usbtoinfo_get_abilities(usbtoxxx_abilities)) ||
251                         (ERROR_OK != usbtoxxx_execute_command()))
252                 return ERROR_FAIL;
253         LOG_INFO("USB_TO_XXX abilities: 0x%08X:0x%08X:0x%08X",
254                 GET_LE_U32(&usbtoxxx_abilities[0]),
255                 GET_LE_U32(&usbtoxxx_abilities[4]),
256                 GET_LE_U32(&usbtoxxx_abilities[8]));
257         return ERROR_OK;
258 }
259
260 RESULT usbtoxxx_fini(void)
261 {
262         usbtoxxx_buffer = NULL;
263         type_pre = 0;
264         return ERROR_OK;
265 }
266
267 bool usbtoxxx_interface_supported(uint8_t cmd)
268 {
269         if ((cmd < VERSALOON_USB_TO_XXX_CMD_START) ||
270                         (cmd > VERSALOON_USB_TO_XXX_CMD_END))
271                 return false;
272
273         cmd -= VERSALOON_USB_TO_XXX_CMD_START;
274         return (usbtoxxx_abilities[cmd  / 8] & (1 << (cmd % 8))) > 0;
275 }
276
277 RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen)
278 {
279         /* check free space, commit if not enough */
280         if (((usbtoxxx_buffer_index + usbtoxxx_current_cmd_index + cmdlen)
281                         >= versaloon_buf_size)
282                         || (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER)) {
283                 struct usbtoxxx_context_t context_tmp;
284                 uint8_t poll_nesting_tmp = 0;
285
286                 memset(&context_tmp, 0, sizeof(context_tmp));
287                 if (poll_nesting) {
288                         if (0 == poll_context.type_pre) {
289                                 LOG_BUG("USB_TO_POLL toooooo long");
290                                 return ERROR_OK;
291                         }
292
293                         usbtoxxx_save_context(&context_tmp);
294                         usbtoxxx_pop_context(&poll_context);
295                         poll_nesting_tmp = poll_nesting;
296                         poll_nesting = 0;
297                 }
298
299                 if (usbtoxxx_execute_command() != ERROR_OK)
300                         return ERROR_FAIL;
301
302                 if (poll_nesting_tmp) {
303                         uint16_t newlen, oldlen;
304
305                         newlen = context_tmp.versaloon_pending_idx
306                                 - poll_context.versaloon_pending_idx;
307                         memcpy(&versaloon_pending[0],
308                                 &versaloon_pending[poll_context.versaloon_pending_idx],
309                                 sizeof(versaloon_pending[0]) * newlen);
310                         context_tmp.versaloon_pending_idx = newlen;
311                         oldlen = poll_context.usbtoxxx_buffer_index
312                                 + poll_context.usbtoxxx_current_cmd_index;
313                         newlen = context_tmp.usbtoxxx_buffer_index
314                                 + context_tmp.usbtoxxx_current_cmd_index;
315                         memcpy(versaloon_buf + 3, versaloon_buf + oldlen, newlen - oldlen);
316                         oldlen -= 3;
317                         context_tmp.usbtoxxx_buffer -= oldlen;
318                         context_tmp.usbtoxxx_buffer_index -= oldlen;
319                         usbtoxxx_pop_context(&context_tmp);
320                         poll_nesting = poll_nesting_tmp;
321                 }
322         }
323         return ERROR_OK;
324 }
325
326 RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf,
327         uint16_t cmdlen, uint16_t retlen, uint8_t *wantbuf,
328         uint16_t wantpos, uint16_t wantlen, uint8_t collect)
329 {
330         uint16_t len_tmp;
331
332         /* 3 more bytes by usbtoxxx_validate_current_command_type */
333         /* 3 more bytes when ((0 == collect_index) || (collect_cmd != cmd)) */
334         if (ERROR_OK != usbtoxxx_ensure_buffer_size(cmdlen + 6))
335                 return ERROR_FAIL;
336
337         if ((type_pre != type) || (NULL == usbtoxxx_buffer)) {
338                 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
339                         LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
340                         return ERRCODE_FAILURE_OPERATION;
341                 }
342                 type_pre = type;
343         }
344
345         if ((0 == collect_index) || (collect_cmd != cmd)) {
346                 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = cmd;
347
348                 if (collect) {
349                         collect_index = usbtoxxx_current_cmd_index;
350                         collect_cmd = cmd;
351                 } else {
352                         collect_index = 0;
353                         collect_cmd = 0;
354                 }
355                 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], cmdlen);
356                 usbtoxxx_current_cmd_index += 2;
357         } else {
358                 len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen;
359                 SET_LE_U16(&usbtoxxx_buffer[collect_index], len_tmp);
360         }
361
362         if (cmdbuf != NULL) {
363                 memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen);
364                 usbtoxxx_current_cmd_index += cmdlen;
365         }
366
367         return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen,
368                 wantbuf, collect);
369 }
370
371 RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN])
372 {
373         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3))
374                 return ERROR_FAIL;
375
376         if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
377                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
378                 return ERRCODE_FAILURE_OPERATION;
379         }
380         type_pre = USB_TO_INFO;
381
382         return versaloon_add_pending(USB_TO_INFO, 0, USB_TO_XXX_ABILITIES_LEN, 0,
383                 USB_TO_XXX_ABILITIES_LEN, abilities, 0);
384 }
385
386 RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us)
387 {
388         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5))
389                 return ERROR_FAIL;
390         if (!poll_nesting)
391                 usbtoxxx_save_context(&poll_context);
392
393         if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
394                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
395                 return ERRCODE_FAILURE_OPERATION;
396         }
397         poll_nesting++;
398         type_pre = USB_TO_POLL;
399
400         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_START;
401         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], retry_cnt);
402         usbtoxxx_current_cmd_index += 2;
403         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], interval_us);
404         usbtoxxx_current_cmd_index += 2;
405
406         return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
407 }
408
409 RESULT usbtopoll_end(void)
410 {
411         if (!poll_nesting) {
412                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
413                 return ERRCODE_FAILURE_OPERATION;
414         }
415         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 1))
416                 return ERROR_FAIL;
417
418         if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
419                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
420                 return ERRCODE_FAILURE_OPERATION;
421         }
422
423         poll_nesting--;
424         type_pre = USB_TO_POLL;
425
426         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_END;
427
428         return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
429 }
430
431 RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size,
432         uint32_t mask, uint32_t value)
433 {
434         uint8_t i;
435
436         if (size > 4) {
437                 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
438                 return ERRCODE_INVALID_PARAMETER;
439         }
440         if (!poll_nesting) {
441                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
442                 return ERRCODE_FAILURE_OPERATION;
443         }
444         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
445                 return ERROR_FAIL;
446
447         if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
448                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
449                 return ERRCODE_FAILURE_OPERATION;
450         }
451
452         type_pre = USB_TO_POLL;
453
454         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKOK;
455         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
456         usbtoxxx_current_cmd_index += 2;
457         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
458         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
459         for (i = 0; i < size; i++)
460                 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
461         for (i = 0; i < size; i++)
462                 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
463
464         return ERROR_OK;
465 }
466
467 RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size,
468         uint32_t mask, uint32_t value)
469 {
470         uint8_t i;
471
472         if (size > 4) {
473                 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
474                 return ERRCODE_INVALID_PARAMETER;
475         }
476         if (!poll_nesting) {
477                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
478                 return ERRCODE_FAILURE_OPERATION;
479         }
480         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
481                 return ERROR_FAIL;
482
483         if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
484                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
485                 return ERRCODE_FAILURE_OPERATION;
486         }
487
488         type_pre = USB_TO_POLL;
489
490         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKFAIL;
491         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
492         usbtoxxx_current_cmd_index += 2;
493         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
494         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
495         for (i = 0; i < size; i++)
496                 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
497         for (i = 0; i < size; i++)
498                 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
499
500         return ERROR_OK;
501 }
502
503 RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff)
504 {
505         if (!poll_nesting) {
506                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
507                 return ERRCODE_FAILURE_OPERATION;
508         }
509         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5 + size))
510                 return ERROR_FAIL;
511
512         if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
513                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
514                 return ERRCODE_FAILURE_OPERATION;
515         }
516
517         type_pre = USB_TO_POLL;
518
519         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_VERIFYBUFF;
520         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
521         usbtoxxx_current_cmd_index += 2;
522         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], size);
523         usbtoxxx_current_cmd_index += 2;
524         memcpy(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], buff, size);
525         usbtoxxx_current_cmd_index += size;
526
527         return ERROR_OK;
528 }
529
530 RESULT usbtodelay_delay(uint16_t dly)
531 {
532         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 2))
533                 return ERROR_FAIL;
534
535         if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
536                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
537                 return ERRCODE_FAILURE_OPERATION;
538         }
539         type_pre = USB_TO_DELAY;
540
541         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], dly);
542         usbtoxxx_current_cmd_index += 2;
543
544         return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0);
545 }
546
547 RESULT usbtodelay_delayms(uint16_t ms)
548 {
549         return usbtodelay_delay(ms | 0x8000);
550 }
551
552 RESULT usbtodelay_delayus(uint16_t us)
553 {
554         return usbtodelay_delay(us & 0x7FFF);
555 }