Remove FSF address from GPL notices
[openocd.git] / src / jtag / drivers / versaloon / usbtoxxx / usbtoxxx.c
blob53a7e989b333db29befd7f2357407815f96752d7
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, see <http://www.gnu.org/licenses/>. *
16 ***************************************************************************/
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
22 #include <string.h>
24 #include "../versaloon_include.h"
25 #include "../versaloon.h"
26 #include "../versaloon_internal.h"
27 #include "usbtoxxx.h"
28 #include "usbtoxxx_internal.h"
30 #define N_A "n/a"
32 const char *types_name[96] = {
33 "usbtousart", "usbtospi", "usbtoi2c", "usbtogpio", "usbtocan", "usbtopwm",
34 "usbtoadc", "usbtodac",
35 "usbtomicrowire", "usbtoswim", "usbtodusi", N_A, N_A, N_A, "usbtopower", "usbtodelay",
36 N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
37 N_A, N_A, N_A, N_A, N_A, N_A, N_A,
38 "usbtojtagll", "usbtojtaghl", "usbtoissp", "usbtoc2", "usbtosbw",
39 "usbtolpcicp", "usbtoswd", "usbtojtagraw",
40 "usbtobdm", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
41 N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
42 "usbtomsp430jtag", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
43 "usbtopower", "usbtodelay", "usbtopoll", N_A, N_A, N_A, N_A, N_A,
44 N_A, N_A, N_A, N_A, N_A, N_A, N_A, "usbtoall"
47 uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN];
49 #define usbtoxxx_get_type_name(type) \
50 types_name[((type) - VERSALOON_USB_TO_XXX_CMD_START) \
51 % (sizeof(types_name) / sizeof(types_name[0]))]
53 static uint8_t type_pre;
54 static uint16_t usbtoxxx_buffer_index;
55 static uint16_t usbtoxxx_current_cmd_index;
56 static uint8_t *usbtoxxx_buffer;
58 uint16_t collect_index;
59 uint8_t collect_cmd;
60 static uint8_t poll_nesting;
62 struct usbtoxxx_context_t {
63 uint8_t type_pre;
64 uint8_t *usbtoxxx_buffer;
65 uint16_t usbtoxxx_current_cmd_index;
66 uint16_t usbtoxxx_buffer_index;
67 uint16_t versaloon_pending_idx;
69 static struct usbtoxxx_context_t poll_context;
71 static void usbtoxxx_save_context(struct usbtoxxx_context_t *c)
73 c->type_pre = type_pre;
74 c->usbtoxxx_buffer = usbtoxxx_buffer;
75 c->usbtoxxx_buffer_index = usbtoxxx_buffer_index;
76 c->usbtoxxx_current_cmd_index = usbtoxxx_current_cmd_index;
77 c->versaloon_pending_idx = versaloon_pending_idx;
80 static void usbtoxxx_pop_context(struct usbtoxxx_context_t *c)
82 type_pre = c->type_pre;
83 usbtoxxx_buffer = c->usbtoxxx_buffer;
84 usbtoxxx_buffer_index = c->usbtoxxx_buffer_index;
85 usbtoxxx_current_cmd_index = c->usbtoxxx_current_cmd_index;
86 versaloon_pending_idx = c->versaloon_pending_idx;
89 RESULT usbtoxxx_validate_current_command_type(void)
91 if (type_pre > 0) {
92 /* not the first command */
93 if (NULL == usbtoxxx_buffer) {
94 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(usbtoxxx_buffer));
95 return ERRCODE_INVALID_BUFFER;
98 usbtoxxx_buffer[0] = type_pre;
99 SET_LE_U16(&usbtoxxx_buffer[1], usbtoxxx_current_cmd_index);
101 usbtoxxx_buffer_index += usbtoxxx_current_cmd_index;
102 } else {
103 /* first command */
104 usbtoxxx_buffer_index = 3;
107 /* prepare for next command */
108 usbtoxxx_current_cmd_index = 3;
109 usbtoxxx_buffer = versaloon_buf + usbtoxxx_buffer_index;
111 collect_index = 0;
112 collect_cmd = 0;
114 return ERROR_OK;
117 RESULT usbtoxxx_execute_command(void)
119 uint16_t i;
120 uint16_t inlen;
121 RESULT result = ERROR_OK;
123 if (poll_nesting) {
124 LOG_BUG(ERRMSG_INVALID_USAGE, "USB_TO_POLL");
125 versaloon_free_want_pos();
126 return ERROR_FAIL;
129 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
130 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
131 versaloon_free_want_pos();
132 return ERRCODE_FAILURE_OPERATION;
134 if (3 == usbtoxxx_buffer_index) {
135 versaloon_free_want_pos();
136 return ERROR_OK;
139 versaloon_buf[0] = USB_TO_ALL;
140 SET_LE_U16(&versaloon_buf[1], usbtoxxx_buffer_index);
142 if (ERROR_OK != versaloon_send_command(usbtoxxx_buffer_index, &inlen)) {
143 versaloon_free_want_pos();
144 return ERROR_FAIL;
147 /* process return data */
148 usbtoxxx_buffer_index = 0;
149 for (i = 0; i < versaloon_pending_idx; i++) {
150 /* check result */
151 if ((0 == i) || !((versaloon_pending[i].collect)
152 && (versaloon_pending[i - 1].collect)
153 && (versaloon_pending[i].cmd
154 == versaloon_pending[i - 1].cmd))) {
155 if (USB_TO_XXX_CMD_NOT_SUPPORT
156 == versaloon_buf[usbtoxxx_buffer_index]) {
157 LOG_ERROR(ERRMSG_NOT_SUPPORT_BY,
158 usbtoxxx_get_type_name(versaloon_pending[i].type),
159 "current dongle");
160 result = ERROR_FAIL;
161 break;
162 } else if (USB_TO_XXX_OK != versaloon_buf[usbtoxxx_buffer_index]) {
163 LOG_ERROR("%s command 0x%02x failed with 0x%02x",
164 usbtoxxx_get_type_name(versaloon_pending[i].type),
165 versaloon_pending[i].cmd,
166 versaloon_buf[usbtoxxx_buffer_index]);
167 result = ERROR_FAIL;
168 break;
170 usbtoxxx_buffer_index++;
173 /* get result data */
174 if (versaloon_pending[i].pos != NULL) {
175 uint8_t processed = 0;
177 if (versaloon_pending[i].callback != NULL) {
178 versaloon_pending[i].callback(&versaloon_pending[i],
179 versaloon_buf + usbtoxxx_buffer_index, &processed);
181 if (!processed) {
182 struct versaloon_want_pos_t *tmp;
184 tmp = versaloon_pending[i].pos;
185 while (tmp != NULL) {
186 if ((tmp->buff != NULL) && (tmp->size > 0)) {
187 memcpy(tmp->buff,
188 versaloon_buf + usbtoxxx_buffer_index
189 + tmp->offset,
190 tmp->size);
192 struct versaloon_want_pos_t *free_tmp;
193 free_tmp = tmp;
194 tmp = tmp->next;
195 free(free_tmp);
197 versaloon_pending[i].pos = NULL;
199 } else if ((versaloon_pending[i].want_data_size > 0)
200 && (versaloon_pending[i].data_buffer != NULL)) {
201 uint8_t processed = 0;
203 if (versaloon_pending[i].callback != NULL) {
204 versaloon_pending[i].callback(&versaloon_pending[i],
205 versaloon_buf + usbtoxxx_buffer_index, &processed);
207 if (!processed) {
208 memcpy(versaloon_pending[i].data_buffer,
209 versaloon_buf + usbtoxxx_buffer_index
210 + versaloon_pending[i].want_data_pos,
211 versaloon_pending[i].want_data_size);
214 usbtoxxx_buffer_index += versaloon_pending[i].actual_data_size;
215 if (usbtoxxx_buffer_index > inlen) {
216 LOG_BUG("%s command 0x%02x process error",
217 usbtoxxx_get_type_name(versaloon_pending[i].type),
218 versaloon_pending[i].cmd);
219 result = ERROR_FAIL;
220 break;
224 /* data is not the right size */
225 if (inlen != usbtoxxx_buffer_index) {
226 LOG_ERROR(ERRMSG_INVALID_TARGET, "length of return data");
227 result = ERROR_FAIL;
230 if (versaloon_pending_idx > 0)
231 versaloon_pending_idx = 0;
232 else {
233 /* no receive data, avoid collision */
234 sleep_ms(10);
237 type_pre = 0;
238 collect_cmd = 0;
239 collect_index = 0;
240 versaloon_free_want_pos();
241 return result;
244 RESULT usbtoxxx_init(void)
246 versaloon_pending_idx = 0;
248 if ((ERROR_OK != usbtoinfo_get_abilities(usbtoxxx_abilities)) ||
249 (ERROR_OK != usbtoxxx_execute_command()))
250 return ERROR_FAIL;
251 LOG_INFO("USB_TO_XXX abilities: 0x%08X:0x%08X:0x%08X",
252 GET_LE_U32(&usbtoxxx_abilities[0]),
253 GET_LE_U32(&usbtoxxx_abilities[4]),
254 GET_LE_U32(&usbtoxxx_abilities[8]));
255 return ERROR_OK;
258 RESULT usbtoxxx_fini(void)
260 usbtoxxx_buffer = NULL;
261 type_pre = 0;
262 return ERROR_OK;
265 bool usbtoxxx_interface_supported(uint8_t cmd)
267 if ((cmd < VERSALOON_USB_TO_XXX_CMD_START) ||
268 (cmd > VERSALOON_USB_TO_XXX_CMD_END))
269 return false;
271 cmd -= VERSALOON_USB_TO_XXX_CMD_START;
272 return (usbtoxxx_abilities[cmd / 8] & (1 << (cmd % 8))) > 0;
275 RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen)
277 /* check free space, commit if not enough */
278 if (((usbtoxxx_buffer_index + usbtoxxx_current_cmd_index + cmdlen)
279 >= versaloon_buf_size)
280 || (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER)) {
281 struct usbtoxxx_context_t context_tmp;
282 uint8_t poll_nesting_tmp = 0;
284 memset(&context_tmp, 0, sizeof(context_tmp));
285 if (poll_nesting) {
286 if (0 == poll_context.type_pre) {
287 LOG_BUG("USB_TO_POLL toooooo long");
288 return ERROR_OK;
291 usbtoxxx_save_context(&context_tmp);
292 usbtoxxx_pop_context(&poll_context);
293 poll_nesting_tmp = poll_nesting;
294 poll_nesting = 0;
297 if (usbtoxxx_execute_command() != ERROR_OK)
298 return ERROR_FAIL;
300 if (poll_nesting_tmp) {
301 uint16_t newlen, oldlen;
303 newlen = context_tmp.versaloon_pending_idx
304 - poll_context.versaloon_pending_idx;
305 memcpy(&versaloon_pending[0],
306 &versaloon_pending[poll_context.versaloon_pending_idx],
307 sizeof(versaloon_pending[0]) * newlen);
308 context_tmp.versaloon_pending_idx = newlen;
309 oldlen = poll_context.usbtoxxx_buffer_index
310 + poll_context.usbtoxxx_current_cmd_index;
311 newlen = context_tmp.usbtoxxx_buffer_index
312 + context_tmp.usbtoxxx_current_cmd_index;
313 memcpy(versaloon_buf + 3, versaloon_buf + oldlen, newlen - oldlen);
314 oldlen -= 3;
315 context_tmp.usbtoxxx_buffer -= oldlen;
316 context_tmp.usbtoxxx_buffer_index -= oldlen;
317 usbtoxxx_pop_context(&context_tmp);
318 poll_nesting = poll_nesting_tmp;
321 return ERROR_OK;
324 RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf,
325 uint16_t cmdlen, uint16_t retlen, uint8_t *wantbuf,
326 uint16_t wantpos, uint16_t wantlen, uint8_t collect)
328 uint16_t len_tmp;
330 /* 3 more bytes by usbtoxxx_validate_current_command_type */
331 /* 3 more bytes when ((0 == collect_index) || (collect_cmd != cmd)) */
332 if (ERROR_OK != usbtoxxx_ensure_buffer_size(cmdlen + 6))
333 return ERROR_FAIL;
335 if ((type_pre != type) || (NULL == usbtoxxx_buffer)) {
336 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
337 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
338 return ERRCODE_FAILURE_OPERATION;
340 type_pre = type;
343 if ((0 == collect_index) || (collect_cmd != cmd)) {
344 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = cmd;
346 if (collect) {
347 collect_index = usbtoxxx_current_cmd_index;
348 collect_cmd = cmd;
349 } else {
350 collect_index = 0;
351 collect_cmd = 0;
353 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], cmdlen);
354 usbtoxxx_current_cmd_index += 2;
355 } else {
356 len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen;
357 SET_LE_U16(&usbtoxxx_buffer[collect_index], len_tmp);
360 if (cmdbuf != NULL) {
361 memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen);
362 usbtoxxx_current_cmd_index += cmdlen;
365 return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen,
366 wantbuf, collect);
369 RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN])
371 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3))
372 return ERROR_FAIL;
374 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
375 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
376 return ERRCODE_FAILURE_OPERATION;
378 type_pre = USB_TO_INFO;
380 return versaloon_add_pending(USB_TO_INFO, 0, USB_TO_XXX_ABILITIES_LEN, 0,
381 USB_TO_XXX_ABILITIES_LEN, abilities, 0);
384 RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us)
386 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5))
387 return ERROR_FAIL;
388 if (!poll_nesting)
389 usbtoxxx_save_context(&poll_context);
391 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
392 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
393 return ERRCODE_FAILURE_OPERATION;
395 poll_nesting++;
396 type_pre = USB_TO_POLL;
398 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_START;
399 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], retry_cnt);
400 usbtoxxx_current_cmd_index += 2;
401 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], interval_us);
402 usbtoxxx_current_cmd_index += 2;
404 return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
407 RESULT usbtopoll_end(void)
409 if (!poll_nesting) {
410 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
411 return ERRCODE_FAILURE_OPERATION;
413 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 1))
414 return ERROR_FAIL;
416 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
417 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
418 return ERRCODE_FAILURE_OPERATION;
421 poll_nesting--;
422 type_pre = USB_TO_POLL;
424 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_END;
426 return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
429 RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size,
430 uint32_t mask, uint32_t value)
432 uint8_t i;
434 if (size > 4) {
435 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
436 return ERRCODE_INVALID_PARAMETER;
438 if (!poll_nesting) {
439 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
440 return ERRCODE_FAILURE_OPERATION;
442 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
443 return ERROR_FAIL;
445 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
446 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
447 return ERRCODE_FAILURE_OPERATION;
450 type_pre = USB_TO_POLL;
452 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKOK;
453 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
454 usbtoxxx_current_cmd_index += 2;
455 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
456 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
457 for (i = 0; i < size; i++)
458 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
459 for (i = 0; i < size; i++)
460 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
462 return ERROR_OK;
465 RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size,
466 uint32_t mask, uint32_t value)
468 uint8_t i;
470 if (size > 4) {
471 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
472 return ERRCODE_INVALID_PARAMETER;
474 if (!poll_nesting) {
475 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
476 return ERRCODE_FAILURE_OPERATION;
478 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
479 return ERROR_FAIL;
481 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
482 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
483 return ERRCODE_FAILURE_OPERATION;
486 type_pre = USB_TO_POLL;
488 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKFAIL;
489 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
490 usbtoxxx_current_cmd_index += 2;
491 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
492 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
493 for (i = 0; i < size; i++)
494 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
495 for (i = 0; i < size; i++)
496 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
498 return ERROR_OK;
501 RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff)
503 if (!poll_nesting) {
504 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
505 return ERRCODE_FAILURE_OPERATION;
507 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5 + size))
508 return ERROR_FAIL;
510 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
511 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
512 return ERRCODE_FAILURE_OPERATION;
515 type_pre = USB_TO_POLL;
517 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_VERIFYBUFF;
518 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
519 usbtoxxx_current_cmd_index += 2;
520 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], size);
521 usbtoxxx_current_cmd_index += 2;
522 memcpy(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], buff, size);
523 usbtoxxx_current_cmd_index += size;
525 return ERROR_OK;
528 RESULT usbtodelay_delay(uint16_t dly)
530 if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 2))
531 return ERROR_FAIL;
533 if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
534 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
535 return ERRCODE_FAILURE_OPERATION;
537 type_pre = USB_TO_DELAY;
539 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], dly);
540 usbtoxxx_current_cmd_index += 2;
542 return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0);
545 RESULT usbtodelay_delayms(uint16_t ms)
547 return usbtodelay_delay(ms | 0x8000);
550 RESULT usbtodelay_delayus(uint16_t us)
552 return usbtodelay_delay(us & 0x7FFF);