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;
204 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);
212 struct versaloon_want_pos_t *free_tmp;
217 versaloon_pending[i].pos = NULL;
220 else if ((versaloon_pending[i].want_data_size > 0)
221 && (versaloon_pending[i].data_buffer != NULL))
223 uint8_t processed = 0;
225 if (versaloon_pending[i].callback != NULL)
227 versaloon_pending[i].callback(&versaloon_pending[i],
228 versaloon_buf + usbtoxxx_buffer_index, &processed);
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);
238 usbtoxxx_buffer_index += versaloon_pending[i].actual_data_size;
239 if (usbtoxxx_buffer_index > inlen)
241 LOG_BUG("%s command 0x%02x process error",
242 usbtoxxx_get_type_name(versaloon_pending[i].type),
243 versaloon_pending[i].cmd);
249 // data is not the right size
250 if (inlen != usbtoxxx_buffer_index)
252 LOG_ERROR(ERRMSG_INVALID_TARGET, "length of return data");
256 if (versaloon_pending_idx > 0)
258 versaloon_pending_idx = 0;
262 // no receive data, avoid collision
269 versaloon_free_want_pos();
273 RESULT usbtoxxx_init(void)
275 versaloon_pending_idx = 0;
277 if ((ERROR_OK != usbtoinfo_get_abilities(usbtoxxx_abilities)) ||
278 (ERROR_OK != usbtoxxx_execute_command()))
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]));
289 RESULT usbtoxxx_fini(void)
291 usbtoxxx_buffer = NULL;
296 bool usbtoxxx_interface_supported(uint8_t cmd)
298 if ((cmd < VERSALOON_USB_TO_XXX_CMD_START) ||
299 (cmd > VERSALOON_USB_TO_XXX_CMD_END))
304 cmd -= VERSALOON_USB_TO_XXX_CMD_START;
305 return (usbtoxxx_abilities[cmd / 8] & (1 << (cmd % 8))) > 0;
310 RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen)
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))
317 struct usbtoxxx_context_t context_tmp;
318 uint8_t poll_nesting_tmp = 0;
320 memset(&context_tmp, 0, sizeof(context_tmp));
323 if (0 == poll_context.type_pre)
325 LOG_BUG("USB_TO_POLL toooooo long");
329 usbtoxxx_save_context(&context_tmp);
330 usbtoxxx_pop_context(&poll_context);
331 poll_nesting_tmp = poll_nesting;
335 if (usbtoxxx_execute_command() != ERROR_OK)
340 if (poll_nesting_tmp)
342 uint16_t newlen, oldlen;
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);
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;
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)
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))
378 if ((type_pre != type) || (NULL == usbtoxxx_buffer))
380 if (ERROR_OK != usbtoxxx_validate_current_command_type())
382 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
383 return ERRCODE_FAILURE_OPERATION;
388 if ((0 == collect_index) || (collect_cmd != cmd))
390 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = cmd;
394 collect_index = usbtoxxx_current_cmd_index;
402 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], cmdlen);
403 usbtoxxx_current_cmd_index += 2;
407 len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen;
408 SET_LE_U16(&usbtoxxx_buffer[collect_index], len_tmp);
413 memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen);
414 usbtoxxx_current_cmd_index += cmdlen;
417 return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen,
425 RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN])
427 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3))
432 if (ERROR_OK != usbtoxxx_validate_current_command_type())
434 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
435 return ERRCODE_FAILURE_OPERATION;
437 type_pre = USB_TO_INFO;
439 return versaloon_add_pending(USB_TO_INFO, 0, USB_TO_XXX_ABILITIES_LEN, 0,
440 USB_TO_XXX_ABILITIES_LEN, abilities, 0);
446 RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us)
448 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5))
454 usbtoxxx_save_context(&poll_context);
457 if (ERROR_OK != usbtoxxx_validate_current_command_type())
459 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
460 return ERRCODE_FAILURE_OPERATION;
463 type_pre = USB_TO_POLL;
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;
471 return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
474 RESULT usbtopoll_end(void)
478 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
479 return ERRCODE_FAILURE_OPERATION;
481 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 1))
486 if (ERROR_OK != usbtoxxx_validate_current_command_type())
488 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
489 return ERRCODE_FAILURE_OPERATION;
493 type_pre = USB_TO_POLL;
495 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_END;
497 return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
500 RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size,
501 uint32_t mask, uint32_t value)
507 LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__);
508 return ERRCODE_INVALID_PARAMETER;
512 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
513 return ERRCODE_FAILURE_OPERATION;
515 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
520 if (ERROR_OK != usbtoxxx_validate_current_command_type())
522 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
523 return ERRCODE_FAILURE_OPERATION;
526 type_pre = USB_TO_POLL;
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++)
535 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
537 for (i =0; i < size; i++)
539 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
545 RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size,
546 uint32_t mask, uint32_t value)
552 LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__);
553 return ERRCODE_INVALID_PARAMETER;
557 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
558 return ERRCODE_FAILURE_OPERATION;
560 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
565 if (ERROR_OK != usbtoxxx_validate_current_command_type())
567 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
568 return ERRCODE_FAILURE_OPERATION;
571 type_pre = USB_TO_POLL;
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++)
580 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
582 for (i =0; i < size; i++)
584 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
590 RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff)
594 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
595 return ERRCODE_FAILURE_OPERATION;
597 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5 + size))
602 if (ERROR_OK != usbtoxxx_validate_current_command_type())
604 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
605 return ERRCODE_FAILURE_OPERATION;
608 type_pre = USB_TO_POLL;
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;
624 RESULT usbtodelay_delay(uint16_t dly)
626 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 2))
631 if (ERROR_OK != usbtoxxx_validate_current_command_type())
633 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
634 return ERRCODE_FAILURE_OPERATION;
636 type_pre = USB_TO_DELAY;
638 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], dly);
639 usbtoxxx_current_cmd_index += 2;
641 return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0);
644 RESULT usbtodelay_delayms(uint16_t ms)
646 return usbtodelay_delay(ms | 0x8000);
649 RESULT usbtodelay_delayus(uint16_t us)
651 return usbtodelay_delay(us & 0x7FFF);