64e31a6552cdf7b9fce81747714e0dce9f344524
[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, *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