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