f92f38c9daa3691eb24288c71b68a4b248d83285
[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  *   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;
203                                 
204                                 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                                         struct versaloon_want_pos_t *free_tmp;
213                                         free_tmp = tmp;
214                                         tmp = tmp->next;
215                                         free(free_tmp);
216                                 }
217                                 versaloon_pending[i].pos = NULL;
218                         }
219                 }
220                 else if ((versaloon_pending[i].want_data_size > 0)
221                         && (versaloon_pending[i].data_buffer != NULL))
222                 {
223                         uint8_t processed = 0;
224                         
225                         if (versaloon_pending[i].callback != NULL)
226                         {
227                                 versaloon_pending[i].callback(&versaloon_pending[i],
228                                                         versaloon_buf + usbtoxxx_buffer_index, &processed);
229                         }
230                         if (!processed)
231                         {
232                                 memcpy(versaloon_pending[i].data_buffer,
233                                            versaloon_buf + usbtoxxx_buffer_index
234                                                         + versaloon_pending[i].want_data_pos,
235                                            versaloon_pending[i].want_data_size);
236                         }
237                 }
238                 usbtoxxx_buffer_index += versaloon_pending[i].actual_data_size;
239                 if (usbtoxxx_buffer_index > inlen)
240                 {
241                         LOG_BUG("%s command 0x%02x process error",
242                                         usbtoxxx_get_type_name(versaloon_pending[i].type),
243                                         versaloon_pending[i].cmd);
244                         result = ERROR_FAIL;
245                         break;
246                 }
247         }
248         
249         // data is not the right size
250         if (inlen != usbtoxxx_buffer_index)
251         {
252                 LOG_ERROR(ERRMSG_INVALID_TARGET, "length of return data");
253                 result = ERROR_FAIL;
254         }
255         
256         if (versaloon_pending_idx > 0)
257         {
258                 versaloon_pending_idx = 0;
259         }
260         else
261         {
262                 // no receive data, avoid collision
263                 sleep_ms(10);
264         }
265         
266         type_pre = 0;
267         collect_cmd = 0;
268         collect_index = 0;
269         versaloon_free_want_pos();
270         return result;
271 }
272
273 RESULT usbtoxxx_init(void)
274 {
275         versaloon_pending_idx = 0;
276         
277         if ((ERROR_OK != usbtoinfo_get_abilities(usbtoxxx_abilities)) ||
278                 (ERROR_OK != usbtoxxx_execute_command()))
279         {
280                 return ERROR_FAIL;
281         }
282         LOG_INFO("USB_TO_XXX abilities: 0x%08X:0x%08X:0x%08X",
283                 GET_LE_U32(&usbtoxxx_abilities[0]),
284                 GET_LE_U32(&usbtoxxx_abilities[4]),
285                 GET_LE_U32(&usbtoxxx_abilities[8]));
286         return ERROR_OK;
287 }
288
289 RESULT usbtoxxx_fini(void)
290 {
291         usbtoxxx_buffer = NULL;
292         type_pre = 0;
293         return ERROR_OK;
294 }
295
296 bool usbtoxxx_interface_supported(uint8_t cmd)
297 {
298         if ((cmd < VERSALOON_USB_TO_XXX_CMD_START) ||
299                 (cmd > VERSALOON_USB_TO_XXX_CMD_END))
300         {
301                 return false;
302         }
303         
304         cmd -= VERSALOON_USB_TO_XXX_CMD_START;
305         return (usbtoxxx_abilities[cmd  / 8] & (1 << (cmd % 8))) > 0;
306 }
307
308
309
310 RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen)
311 {
312         // check free space, commit if not enough
313         if (((usbtoxxx_buffer_index + usbtoxxx_current_cmd_index + cmdlen)
314                         >= versaloon_buf_size)
315                 || (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER))
316         {
317                 struct usbtoxxx_context_t context_tmp;
318                 uint8_t poll_nesting_tmp = 0;
319                 
320                 memset(&context_tmp, 0, sizeof(context_tmp));
321                 if (poll_nesting)
322                 {
323                         if (0 == poll_context.type_pre)
324                         {
325                                 LOG_BUG("USB_TO_POLL toooooo long");
326                                 return ERROR_OK;
327                         }
328                         
329                         usbtoxxx_save_context(&context_tmp);
330                         usbtoxxx_pop_context(&poll_context);
331                         poll_nesting_tmp = poll_nesting;
332                         poll_nesting = 0;
333                 }
334                 
335                 if (usbtoxxx_execute_command() != ERROR_OK)
336                 {
337                         return ERROR_FAIL;
338                 }
339                 
340                 if (poll_nesting_tmp)
341                 {
342                         uint16_t newlen, oldlen;
343                         
344                         newlen = context_tmp.versaloon_pending_idx
345                                                                         - poll_context.versaloon_pending_idx;
346                         memcpy(&versaloon_pending[0],
347                                         &versaloon_pending[poll_context.versaloon_pending_idx],
348                                         sizeof(versaloon_pending[0]) * newlen);
349                         context_tmp.versaloon_pending_idx = newlen;
350                         oldlen = poll_context.usbtoxxx_buffer_index
351                                                                         + poll_context.usbtoxxx_current_cmd_index;
352                         newlen = context_tmp.usbtoxxx_buffer_index
353                                                                         + context_tmp.usbtoxxx_current_cmd_index;
354                         memcpy(versaloon_buf + 3, versaloon_buf + oldlen, newlen - oldlen);
355                         oldlen -= 3;
356                         context_tmp.usbtoxxx_buffer -= oldlen;
357                         context_tmp.usbtoxxx_buffer_index -= oldlen;
358                         usbtoxxx_pop_context(&context_tmp);
359                         poll_nesting = poll_nesting_tmp;
360                 }
361         }
362         return ERROR_OK;
363 }
364
365 RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf,
366                                                         uint16_t cmdlen, uint16_t retlen, uint8_t *wantbuf,
367                                                         uint16_t wantpos, uint16_t wantlen, uint8_t collect)
368 {
369         uint16_t len_tmp;
370         
371         // 3 more bytes by usbtoxxx_validate_current_command_type
372         // 3 more bytes when ((0 == collect_index) || (collect_cmd != cmd))
373         if (ERROR_OK != usbtoxxx_ensure_buffer_size(cmdlen + 6))
374         {
375                 return ERROR_FAIL;
376         }
377         
378         if ((type_pre != type) || (NULL == usbtoxxx_buffer))
379         {
380                 if (ERROR_OK != usbtoxxx_validate_current_command_type())
381                 {
382                         LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
383                         return ERRCODE_FAILURE_OPERATION;
384                 }
385                 type_pre = type;
386         }
387         
388         if ((0 == collect_index) || (collect_cmd != cmd))
389         {
390                 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = cmd;
391                 
392                 if (collect)
393                 {
394                         collect_index = usbtoxxx_current_cmd_index;
395                         collect_cmd = cmd;
396                 }
397                 else
398                 {
399                         collect_index = 0;
400                         collect_cmd = 0;
401                 }
402                 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], cmdlen);
403                 usbtoxxx_current_cmd_index += 2;
404         }
405         else
406         {
407                 len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen;
408                 SET_LE_U16(&usbtoxxx_buffer[collect_index], len_tmp);
409         }
410         
411         if (cmdbuf != NULL)
412         {
413                 memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen);
414                 usbtoxxx_current_cmd_index += cmdlen;
415         }
416         
417         return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen,
418                                                                  wantbuf, collect);
419 }
420
421
422
423
424
425 RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN])
426 {
427         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3))
428         {
429                 return ERROR_FAIL;
430         }
431         
432         if (ERROR_OK != usbtoxxx_validate_current_command_type())
433         {
434                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
435                 return ERRCODE_FAILURE_OPERATION;
436         }
437         type_pre = USB_TO_INFO;
438         
439         return versaloon_add_pending(USB_TO_INFO, 0, USB_TO_XXX_ABILITIES_LEN, 0,
440                                                                         USB_TO_XXX_ABILITIES_LEN, abilities, 0);
441 }
442
443
444
445
446 RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us)
447 {
448         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5))
449         {
450                 return ERROR_FAIL;
451         }
452         if (!poll_nesting)
453         {
454                 usbtoxxx_save_context(&poll_context);
455         }
456         
457         if (ERROR_OK != usbtoxxx_validate_current_command_type())
458         {
459                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
460                 return ERRCODE_FAILURE_OPERATION;
461         }
462         poll_nesting++;
463         type_pre = USB_TO_POLL;
464         
465         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_START;
466         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], retry_cnt);
467         usbtoxxx_current_cmd_index += 2;
468         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], interval_us);
469         usbtoxxx_current_cmd_index += 2;
470         
471         return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
472 }
473
474 RESULT usbtopoll_end(void)
475 {
476         if (!poll_nesting)
477         {
478                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
479                 return ERRCODE_FAILURE_OPERATION;
480         }
481         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 1))
482         {
483                 return ERROR_FAIL;
484         }
485         
486         if (ERROR_OK != usbtoxxx_validate_current_command_type())
487         {
488                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
489                 return ERRCODE_FAILURE_OPERATION;
490         }
491         
492         poll_nesting--;
493         type_pre = USB_TO_POLL;
494         
495         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_END;
496         
497         return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
498 }
499
500 RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size,
501                                                         uint32_t mask, uint32_t value)
502 {
503         uint8_t i;
504         
505         if (size > 4)
506         {
507                 LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__);
508                 return ERRCODE_INVALID_PARAMETER;
509         }
510         if (!poll_nesting)
511         {
512                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
513                 return ERRCODE_FAILURE_OPERATION;
514         }
515         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
516         {
517                 return ERROR_FAIL;
518         }
519         
520         if (ERROR_OK != usbtoxxx_validate_current_command_type())
521         {
522                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
523                 return ERRCODE_FAILURE_OPERATION;
524         }
525         
526         type_pre = USB_TO_POLL;
527         
528         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKOK;
529         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
530         usbtoxxx_current_cmd_index += 2;
531         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
532         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
533         for (i =0; i < size; i++)
534         {
535                 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
536         }
537         for (i =0; i < size; i++)
538         {
539                 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
540         }
541         
542         return ERROR_OK;
543 }
544
545 RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size,
546                                                         uint32_t mask, uint32_t value)
547 {
548         uint8_t i;
549         
550         if (size > 4)
551         {
552                 LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__);
553                 return ERRCODE_INVALID_PARAMETER;
554         }
555         if (!poll_nesting)
556         {
557                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
558                 return ERRCODE_FAILURE_OPERATION;
559         }
560         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
561         {
562                 return ERROR_FAIL;
563         }
564         
565         if (ERROR_OK != usbtoxxx_validate_current_command_type())
566         {
567                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
568                 return ERRCODE_FAILURE_OPERATION;
569         }
570         
571         type_pre = USB_TO_POLL;
572         
573         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKFAIL;
574         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
575         usbtoxxx_current_cmd_index += 2;
576         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
577         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
578         for (i =0; i < size; i++)
579         {
580                 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
581         }
582         for (i =0; i < size; i++)
583         {
584                 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
585         }
586         
587         return ERROR_OK;
588 }
589
590 RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff)
591 {
592         if (!poll_nesting)
593         {
594                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
595                 return ERRCODE_FAILURE_OPERATION;
596         }
597         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5 + size))
598         {
599                 return ERROR_FAIL;
600         }
601         
602         if (ERROR_OK != usbtoxxx_validate_current_command_type())
603         {
604                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
605                 return ERRCODE_FAILURE_OPERATION;
606         }
607         
608         type_pre = USB_TO_POLL;
609         
610         usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_VERIFYBUFF;
611         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
612         usbtoxxx_current_cmd_index += 2;
613         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], size);
614         usbtoxxx_current_cmd_index += 2;
615         memcpy(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], buff, size);
616         usbtoxxx_current_cmd_index += size;
617         
618         return ERROR_OK;
619 }
620
621
622
623
624 RESULT usbtodelay_delay(uint16_t dly)
625 {
626         if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 2))
627         {
628                 return ERROR_FAIL;
629         }
630         
631         if (ERROR_OK != usbtoxxx_validate_current_command_type())
632         {
633                 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
634                 return ERRCODE_FAILURE_OPERATION;
635         }
636         type_pre = USB_TO_DELAY;
637         
638         SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], dly);
639         usbtoxxx_current_cmd_index += 2;
640         
641         return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0);
642 }
643
644 RESULT usbtodelay_delayms(uint16_t ms)
645 {
646         return usbtodelay_delay(ms | 0x8000);
647 }
648
649 RESULT usbtodelay_delayus(uint16_t us)
650 {
651         return usbtodelay_delay(us & 0x7FFF);
652 }
653