update files to correct FSF address
[openocd.git] / src / jtag / drivers / versaloon / usbtoxxx / usbtoxxx.c
blob65e54e4e6400d8c96ef6f559ef0dcd80355330b9
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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
18 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <string.h>
26 #include "../versaloon_include.h"
27 #include "../versaloon.h"
28 #include "../versaloon_internal.h"
29 #include "usbtoxxx.h"
30 #include "usbtoxxx_internal.h"
32 #define N_A "n/a"
34 const char *types_name[96] = {
35 "usbtousart", "usbtospi", "usbtoi2c", "usbtogpio", "usbtocan", "usbtopwm",
36 "usbtoadc", "usbtodac",
37 "usbtomicrowire", "usbtoswim", "usbtodusi", N_A, N_A, N_A, "usbtopower", "usbtodelay",
38 N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
39 N_A, N_A, N_A, N_A, N_A, N_A, N_A,
40 "usbtojtagll", "usbtojtaghl", "usbtoissp", "usbtoc2", "usbtosbw",
41 "usbtolpcicp", "usbtoswd", "usbtojtagraw",
42 "usbtobdm", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
43 N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
44 "usbtomsp430jtag", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
45 "usbtopower", "usbtodelay", "usbtopoll", N_A, N_A, N_A, N_A, N_A,
46 N_A, N_A, N_A, N_A, N_A, N_A, N_A, "usbtoall"
49 uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN];
51 #define usbtoxxx_get_type_name(type) \
52 types_name[((type) - VERSALOON_USB_TO_XXX_CMD_START) \
53 % (sizeof(types_name) / sizeof(types_name[0]))]
55 static uint8_t type_pre;
56 static uint16_t usbtoxxx_buffer_index;
57 static uint16_t usbtoxxx_current_cmd_index;
58 static uint8_t *usbtoxxx_buffer;
60 uint16_t collect_index;
61 uint8_t collect_cmd;
62 static uint8_t poll_nesting;
64 struct usbtoxxx_context_t {
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;
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)
93 if (type_pre > 0) {
94 /* not the first command */
95 if (NULL == usbtoxxx_buffer) {
96 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(usbtoxxx_buffer));
97 return ERRCODE_INVALID_BUFFER;
100 usbtoxxx_buffer[0] = type_pre;
101 SET_LE_U16(&usbtoxxx_buffer[1], usbtoxxx_current_cmd_index);
103 usbtoxxx_buffer_index += usbtoxxx_current_cmd_index;
104 } else {
105 /* first command */
106 usbtoxxx_buffer_index = 3;
109 /* prepare for next command */
110 usbtoxxx_current_cmd_index = 3;
111 usbtoxxx_buffer = versaloon_buf + usbtoxxx_buffer_index;
113 collect_index = 0;
114 collect_cmd = 0;
116 return ERROR_OK;
119 RESULT usbtoxxx_execute_command(void)
121 uint16_t i;
122 uint16_t inlen;
123 RESULT result = ERROR_OK;
125 if (poll_nesting) {
126 LOG_BUG(ERRMSG_INVALID_USAGE, "USB_TO_POLL");
127 versaloon_free_want_pos();
128 return ERROR_FAIL;
131 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
132 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
133 versaloon_free_want_pos();
134 return ERRCODE_FAILURE_OPERATION;
136 if (3 == usbtoxxx_buffer_index) {
137 versaloon_free_want_pos();
138 return ERROR_OK;
141 versaloon_buf[0] = USB_TO_ALL;
142 SET_LE_U16(&versaloon_buf[1], usbtoxxx_buffer_index);
144 if (ERROR_OK != versaloon_send_command(usbtoxxx_buffer_index, &inlen)) {
145 versaloon_free_want_pos();
146 return ERROR_FAIL;
149 /* process return data */
150 usbtoxxx_buffer_index = 0;
151 for (i = 0; i < versaloon_pending_idx; i++) {
152 /* check result */
153 if ((0 == i) || !((versaloon_pending[i].collect)
154 && (versaloon_pending[i - 1].collect)
155 && (versaloon_pending[i].cmd
156 == versaloon_pending[i - 1].cmd))) {
157 if (USB_TO_XXX_CMD_NOT_SUPPORT
158 == versaloon_buf[usbtoxxx_buffer_index]) {
159 LOG_ERROR(ERRMSG_NOT_SUPPORT_BY,
160 usbtoxxx_get_type_name(versaloon_pending[i].type),
161 "current dongle");
162 result = ERROR_FAIL;
163 break;
164 } else if (USB_TO_XXX_OK != versaloon_buf[usbtoxxx_buffer_index]) {
165 LOG_ERROR("%s command 0x%02x failed with 0x%02x",
166 usbtoxxx_get_type_name(versaloon_pending[i].type),
167 versaloon_pending[i].cmd,
168 versaloon_buf[usbtoxxx_buffer_index]);
169 result = ERROR_FAIL;
170 break;
172 usbtoxxx_buffer_index++;
175 /* get result data */
176 if (versaloon_pending[i].pos != NULL) {
177 uint8_t processed = 0;
179 if (versaloon_pending[i].callback != NULL) {
180 versaloon_pending[i].callback(&versaloon_pending[i],
181 versaloon_buf + usbtoxxx_buffer_index, &processed);
183 if (!processed) {
184 struct versaloon_want_pos_t *tmp;
186 tmp = versaloon_pending[i].pos;
187 while (tmp != NULL) {
188 if ((tmp->buff != NULL) && (tmp->size > 0)) {
189 memcpy(tmp->buff,
190 versaloon_buf + usbtoxxx_buffer_index
191 + tmp->offset,
192 tmp->size);
194 struct versaloon_want_pos_t *free_tmp;
195 free_tmp = tmp;
196 tmp = tmp->next;
197 free(free_tmp);
199 versaloon_pending[i].pos = NULL;
201 } else if ((versaloon_pending[i].want_data_size > 0)
202 && (versaloon_pending[i].data_buffer != NULL)) {
203 uint8_t processed = 0;
205 if (versaloon_pending[i].callback != NULL) {
206 versaloon_pending[i].callback(&versaloon_pending[i],
207 versaloon_buf + usbtoxxx_buffer_index, &processed);
209 if (!processed) {
210 memcpy(versaloon_pending[i].data_buffer,
211 versaloon_buf + usbtoxxx_buffer_index
212 + versaloon_pending[i].want_data_pos,
213 versaloon_pending[i].want_data_size);
216 usbtoxxx_buffer_index += versaloon_pending[i].actual_data_size;
217 if (usbtoxxx_buffer_index > inlen) {
218 LOG_BUG("%s command 0x%02x process error",
219 usbtoxxx_get_type_name(versaloon_pending[i].type),
220 versaloon_pending[i].cmd);
221 result = ERROR_FAIL;
222 break;
226 /* data is not the right size */
227 if (inlen != usbtoxxx_buffer_index) {
228 LOG_ERROR(ERRMSG_INVALID_TARGET, "length of return data");
229 result = ERROR_FAIL;
232 if (versaloon_pending_idx > 0)
233 versaloon_pending_idx = 0;
234 else {
235 /* no receive data, avoid collision */
236 sleep_ms(10);
239 type_pre = 0;
240 collect_cmd = 0;
241 collect_index = 0;
242 versaloon_free_want_pos();
243 return result;
246 RESULT usbtoxxx_init(void)
248 versaloon_pending_idx = 0;
250 if ((ERROR_OK != usbtoinfo_get_abilities(usbtoxxx_abilities)) ||
251 (ERROR_OK != usbtoxxx_execute_command()))
252 return ERROR_FAIL;
253 LOG_INFO("USB_TO_XXX abilities: 0x%08X:0x%08X:0x%08X",
254 GET_LE_U32(&usbtoxxx_abilities[0]),
255 GET_LE_U32(&usbtoxxx_abilities[4]),
256 GET_LE_U32(&usbtoxxx_abilities[8]));
257 return ERROR_OK;
260 RESULT usbtoxxx_fini(void)
262 usbtoxxx_buffer = NULL;
263 type_pre = 0;
264 return ERROR_OK;
267 bool usbtoxxx_interface_supported(uint8_t cmd)
269 if ((cmd < VERSALOON_USB_TO_XXX_CMD_START) ||
270 (cmd > VERSALOON_USB_TO_XXX_CMD_END))
271 return false;
273 cmd -= VERSALOON_USB_TO_XXX_CMD_START;
274 return (usbtoxxx_abilities[cmd / 8] & (1 << (cmd % 8))) > 0;
277 RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen)
279 /* check free space, commit if not enough */
280 if (((usbtoxxx_buffer_index + usbtoxxx_current_cmd_index + cmdlen)
281 >= versaloon_buf_size)
282 || (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER)) {
283 struct usbtoxxx_context_t context_tmp;
284 uint8_t poll_nesting_tmp = 0;
286 memset(&context_tmp, 0, sizeof(context_tmp));
287 if (poll_nesting) {
288 if (0 == poll_context.type_pre) {
289 LOG_BUG("USB_TO_POLL toooooo long");
290 return ERROR_OK;
293 usbtoxxx_save_context(&context_tmp);
294 usbtoxxx_pop_context(&poll_context);
295 poll_nesting_tmp = poll_nesting;
296 poll_nesting = 0;
299 if (usbtoxxx_execute_command() != ERROR_OK)
300 return ERROR_FAIL;
302 if (poll_nesting_tmp) {
303 uint16_t newlen, oldlen;
305 newlen = context_tmp.versaloon_pending_idx
306 - poll_context.versaloon_pending_idx;
307 memcpy(&versaloon_pending[0],
308 &versaloon_pending[poll_context.versaloon_pending_idx],
309 sizeof(versaloon_pending[0]) * newlen);
310 context_tmp.versaloon_pending_idx = newlen;
311 oldlen = poll_context.usbtoxxx_buffer_index
312 + poll_context.usbtoxxx_current_cmd_index;
313 newlen = context_tmp.usbtoxxx_buffer_index
314 + context_tmp.usbtoxxx_current_cmd_index;
315 memcpy(versaloon_buf + 3, versaloon_buf + oldlen, newlen - oldlen);
316 oldlen -= 3;
317 context_tmp.usbtoxxx_buffer -= oldlen;
318 context_tmp.usbtoxxx_buffer_index -= oldlen;
319 usbtoxxx_pop_context(&context_tmp);
320 poll_nesting = poll_nesting_tmp;
323 return ERROR_OK;
326 RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf,
327 uint16_t cmdlen, uint16_t retlen, uint8_t *wantbuf,
328 uint16_t wantpos, uint16_t wantlen, uint8_t collect)
330 uint16_t len_tmp;
332 /* 3 more bytes by usbtoxxx_validate_current_command_type */
333 /* 3 more bytes when ((0 == collect_index) || (collect_cmd != cmd)) */
334 if (ERROR_OK != usbtoxxx_ensure_buffer_size(cmdlen + 6))
335 return ERROR_FAIL;
337 if ((type_pre != type) || (NULL == usbtoxxx_buffer)) {
338 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
339 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
340 return ERRCODE_FAILURE_OPERATION;
342 type_pre = type;
345 if ((0 == collect_index) || (collect_cmd != cmd)) {
346 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = cmd;
348 if (collect) {
349 collect_index = usbtoxxx_current_cmd_index;
350 collect_cmd = cmd;
351 } else {
352 collect_index = 0;
353 collect_cmd = 0;
355 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], cmdlen);
356 usbtoxxx_current_cmd_index += 2;
357 } else {
358 len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen;
359 SET_LE_U16(&usbtoxxx_buffer[collect_index], len_tmp);
362 if (cmdbuf != NULL) {
363 memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen);
364 usbtoxxx_current_cmd_index += cmdlen;
367 return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen,
368 wantbuf, collect);
371 RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN])
373 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3))
374 return ERROR_FAIL;
376 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
377 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
378 return ERRCODE_FAILURE_OPERATION;
380 type_pre = USB_TO_INFO;
382 return versaloon_add_pending(USB_TO_INFO, 0, USB_TO_XXX_ABILITIES_LEN, 0,
383 USB_TO_XXX_ABILITIES_LEN, abilities, 0);
386 RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us)
388 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5))
389 return ERROR_FAIL;
390 if (!poll_nesting)
391 usbtoxxx_save_context(&poll_context);
393 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
394 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
395 return ERRCODE_FAILURE_OPERATION;
397 poll_nesting++;
398 type_pre = USB_TO_POLL;
400 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_START;
401 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], retry_cnt);
402 usbtoxxx_current_cmd_index += 2;
403 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], interval_us);
404 usbtoxxx_current_cmd_index += 2;
406 return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
409 RESULT usbtopoll_end(void)
411 if (!poll_nesting) {
412 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
413 return ERRCODE_FAILURE_OPERATION;
415 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 1))
416 return ERROR_FAIL;
418 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
419 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
420 return ERRCODE_FAILURE_OPERATION;
423 poll_nesting--;
424 type_pre = USB_TO_POLL;
426 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_END;
428 return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
431 RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size,
432 uint32_t mask, uint32_t value)
434 uint8_t i;
436 if (size > 4) {
437 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
438 return ERRCODE_INVALID_PARAMETER;
440 if (!poll_nesting) {
441 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
442 return ERRCODE_FAILURE_OPERATION;
444 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
445 return ERROR_FAIL;
447 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
448 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
449 return ERRCODE_FAILURE_OPERATION;
452 type_pre = USB_TO_POLL;
454 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKOK;
455 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
456 usbtoxxx_current_cmd_index += 2;
457 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
458 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
459 for (i = 0; i < size; i++)
460 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
461 for (i = 0; i < size; i++)
462 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
464 return ERROR_OK;
467 RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size,
468 uint32_t mask, uint32_t value)
470 uint8_t i;
472 if (size > 4) {
473 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
474 return ERRCODE_INVALID_PARAMETER;
476 if (!poll_nesting) {
477 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
478 return ERRCODE_FAILURE_OPERATION;
480 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
481 return ERROR_FAIL;
483 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
484 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
485 return ERRCODE_FAILURE_OPERATION;
488 type_pre = USB_TO_POLL;
490 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKFAIL;
491 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
492 usbtoxxx_current_cmd_index += 2;
493 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
494 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
495 for (i = 0; i < size; i++)
496 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
497 for (i = 0; i < size; i++)
498 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
500 return ERROR_OK;
503 RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff)
505 if (!poll_nesting) {
506 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
507 return ERRCODE_FAILURE_OPERATION;
509 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5 + size))
510 return ERROR_FAIL;
512 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
513 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
514 return ERRCODE_FAILURE_OPERATION;
517 type_pre = USB_TO_POLL;
519 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_VERIFYBUFF;
520 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
521 usbtoxxx_current_cmd_index += 2;
522 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], size);
523 usbtoxxx_current_cmd_index += 2;
524 memcpy(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], buff, size);
525 usbtoxxx_current_cmd_index += size;
527 return ERROR_OK;
530 RESULT usbtodelay_delay(uint16_t dly)
532 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 2))
533 return ERROR_FAIL;
535 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
536 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
537 return ERRCODE_FAILURE_OPERATION;
539 type_pre = USB_TO_DELAY;
541 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], dly);
542 usbtoxxx_current_cmd_index += 2;
544 return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0);
547 RESULT usbtodelay_delayms(uint16_t ms)
549 return usbtodelay_delay(ms | 0x8000);
552 RESULT usbtodelay_delayus(uint16_t us)
554 return usbtodelay_delay(us & 0x7FFF);