1 /***************************************************************************
2 * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
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. *
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. *
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 ***************************************************************************/
25 #include "../versaloon_include.h"
26 #include "../versaloon.h"
27 #include "../versaloon_internal.h"
29 #include "usbtoxxx_internal.h"
32 const char* types_name[96] =
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"
48 uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN];
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]))]
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;
59 uint16_t collect_index = 0;
61 static uint8_t poll_nesting = 0;
63 struct usbtoxxx_context_t
66 uint8_t *usbtoxxx_buffer;
67 uint16_t usbtoxxx_current_cmd_index;
68 uint16_t usbtoxxx_buffer_index;
69 uint16_t versaloon_pending_idx;
71 static struct usbtoxxx_context_t poll_context;
73 static void usbtoxxx_save_context(struct usbtoxxx_context_t *c)
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;
82 static void usbtoxxx_pop_context(struct usbtoxxx_context_t *c)
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;
91 RESULT usbtoxxx_validate_current_command_type(void)
95 // not the first command
96 if (NULL == usbtoxxx_buffer)
98 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(usbtoxxx_buffer));
99 return ERRCODE_INVALID_BUFFER;
102 usbtoxxx_buffer[0] = type_pre;
103 SET_LE_U16(&usbtoxxx_buffer[1], usbtoxxx_current_cmd_index);
105 usbtoxxx_buffer_index += usbtoxxx_current_cmd_index;
110 usbtoxxx_buffer_index = 3;
113 // prepare for next command
114 usbtoxxx_current_cmd_index = 3;
115 usbtoxxx_buffer = versaloon_buf + usbtoxxx_buffer_index;
125 RESULT usbtoxxx_execute_command(void)
129 RESULT result = ERROR_OK;
133 LOG_BUG(ERRMSG_INVALID_USAGE, "USB_TO_POLL");
134 versaloon_free_want_pos();
138 if (ERROR_OK != usbtoxxx_validate_current_command_type())
140 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
141 versaloon_free_want_pos();
142 return ERRCODE_FAILURE_OPERATION;
144 if (3 == usbtoxxx_buffer_index)
146 versaloon_free_want_pos();
150 versaloon_buf[0] = USB_TO_ALL;
151 SET_LE_U16(&versaloon_buf[1], usbtoxxx_buffer_index);
153 if (ERROR_OK != versaloon_send_command(usbtoxxx_buffer_index, &inlen))
155 versaloon_free_want_pos();
159 // process return data
160 usbtoxxx_buffer_index = 0;
161 for (i = 0; i < versaloon_pending_idx; i++)
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)))
169 if (USB_TO_XXX_CMD_NOT_SUPPORT
170 == versaloon_buf[usbtoxxx_buffer_index])
172 LOG_ERROR(ERRMSG_NOT_SUPPORT_BY,
173 usbtoxxx_get_type_name(versaloon_pending[i].type),
178 else if (USB_TO_XXX_OK != versaloon_buf[usbtoxxx_buffer_index])
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]);
187 usbtoxxx_buffer_index++;
191 if (versaloon_pending[i].pos != NULL)
193 uint8_t processed = 0;
195 if (versaloon_pending[i].callback != NULL)
197 versaloon_pending[i].callback(&versaloon_pending[i],
198 versaloon_buf + usbtoxxx_buffer_index, &processed);
202 struct versaloon_want_pos_t *tmp, *free_tmp;
204 free_tmp = tmp = versaloon_pending[i].pos;
207 if ((tmp->buff != NULL) && (tmp->size > 0))
209 memcpy(tmp->buff, versaloon_buf + usbtoxxx_buffer_index
210 + tmp->offset, tmp->size);
216 versaloon_pending[i].pos = NULL;
219 else if ((versaloon_pending[i].want_data_size > 0)
220 && (versaloon_pending[i].data_buffer != NULL))
222 uint8_t processed = 0;
224 if (versaloon_pending[i].callback != NULL)
226 versaloon_pending[i].callback(&versaloon_pending[i],
227 versaloon_buf + usbtoxxx_buffer_index, &processed);
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);
237 usbtoxxx_buffer_index += versaloon_pending[i].actual_data_size;
238 if (usbtoxxx_buffer_index > inlen)
240 LOG_BUG("%s command 0x%02x process error",
241 usbtoxxx_get_type_name(versaloon_pending[i].type),
242 versaloon_pending[i].cmd);
248 // data is not the right size
249 if (inlen != usbtoxxx_buffer_index)
251 LOG_ERROR(ERRMSG_INVALID_TARGET, "length of return data");
255 if (versaloon_pending_idx > 0)
257 versaloon_pending_idx = 0;
261 // no receive data, avoid collision
268 versaloon_free_want_pos();
272 RESULT usbtoxxx_init(void)
274 versaloon_pending_idx = 0;
276 if ((ERROR_OK != usbtoinfo_get_abilities(usbtoxxx_abilities)) ||
277 (ERROR_OK != usbtoxxx_execute_command()))
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]));
288 RESULT usbtoxxx_fini(void)
290 usbtoxxx_buffer = NULL;
295 bool usbtoxxx_interface_supported(uint8_t cmd)
297 if ((cmd < VERSALOON_USB_TO_XXX_CMD_START) ||
298 (cmd > VERSALOON_USB_TO_XXX_CMD_END))
303 cmd -= VERSALOON_USB_TO_XXX_CMD_START;
304 return (usbtoxxx_abilities[cmd / 8] & (1 << (cmd % 8))) > 0;
309 RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen)
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))
316 struct usbtoxxx_context_t context_tmp;
317 uint8_t poll_nesting_tmp = 0;
319 memset(&context_tmp, 0, sizeof(context_tmp));
322 if (0 == poll_context.type_pre)
324 LOG_BUG("USB_TO_POLL toooooo long");
328 usbtoxxx_save_context(&context_tmp);
329 usbtoxxx_pop_context(&poll_context);
330 poll_nesting_tmp = poll_nesting;
334 if (usbtoxxx_execute_command() != ERROR_OK)
339 if (poll_nesting_tmp)
341 uint16_t newlen, oldlen;
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);
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;
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)
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))
377 if ((type_pre != type) || (NULL == usbtoxxx_buffer))
379 if (ERROR_OK != usbtoxxx_validate_current_command_type())
381 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
382 return ERRCODE_FAILURE_OPERATION;
387 if ((0 == collect_index) || (collect_cmd != cmd))
389 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = cmd;
393 collect_index = usbtoxxx_current_cmd_index;
401 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], cmdlen);
402 usbtoxxx_current_cmd_index += 2;
406 len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen;
407 SET_LE_U16(&usbtoxxx_buffer[collect_index], len_tmp);
412 memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen);
413 usbtoxxx_current_cmd_index += cmdlen;
416 return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen,
424 RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN])
426 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3))
431 if (ERROR_OK != usbtoxxx_validate_current_command_type())
433 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
434 return ERRCODE_FAILURE_OPERATION;
436 type_pre = USB_TO_INFO;
438 return versaloon_add_pending(USB_TO_INFO, 0, USB_TO_XXX_ABILITIES_LEN, 0,
439 USB_TO_XXX_ABILITIES_LEN, abilities, 0);
445 RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us)
447 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5))
453 usbtoxxx_save_context(&poll_context);
456 if (ERROR_OK != usbtoxxx_validate_current_command_type())
458 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
459 return ERRCODE_FAILURE_OPERATION;
462 type_pre = USB_TO_POLL;
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;
470 return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
473 RESULT usbtopoll_end(void)
477 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
478 return ERRCODE_FAILURE_OPERATION;
480 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 1))
485 if (ERROR_OK != usbtoxxx_validate_current_command_type())
487 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
488 return ERRCODE_FAILURE_OPERATION;
492 type_pre = USB_TO_POLL;
494 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_END;
496 return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
499 RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size,
500 uint32_t mask, uint32_t value)
506 LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__);
507 return ERRCODE_INVALID_PARAMETER;
511 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
512 return ERRCODE_FAILURE_OPERATION;
514 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
519 if (ERROR_OK != usbtoxxx_validate_current_command_type())
521 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
522 return ERRCODE_FAILURE_OPERATION;
525 type_pre = USB_TO_POLL;
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++)
534 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
536 for (i =0; i < size; i++)
538 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
544 RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size,
545 uint32_t mask, uint32_t value)
551 LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__);
552 return ERRCODE_INVALID_PARAMETER;
556 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
557 return ERRCODE_FAILURE_OPERATION;
559 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
564 if (ERROR_OK != usbtoxxx_validate_current_command_type())
566 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
567 return ERRCODE_FAILURE_OPERATION;
570 type_pre = USB_TO_POLL;
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++)
579 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
581 for (i =0; i < size; i++)
583 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
589 RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff)
593 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
594 return ERRCODE_FAILURE_OPERATION;
596 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5 + size))
601 if (ERROR_OK != usbtoxxx_validate_current_command_type())
603 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
604 return ERRCODE_FAILURE_OPERATION;
607 type_pre = USB_TO_POLL;
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;
623 RESULT usbtodelay_delay(uint16_t dly)
625 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 2))
630 if (ERROR_OK != usbtoxxx_validate_current_command_type())
632 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
633 return ERRCODE_FAILURE_OPERATION;
635 type_pre = USB_TO_DELAY;
637 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], dly);
638 usbtoxxx_current_cmd_index += 2;
640 return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0);
643 RESULT usbtodelay_delayms(uint16_t ms)
645 return usbtodelay_delay(ms | 0x8000);
648 RESULT usbtodelay_delayus(uint16_t us)
650 return usbtodelay_delay(us & 0x7FFF);