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);