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