jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / jtag / drivers / versaloon / usbtoxxx / usbtoxxx.c
blob070f68c1ed09962eff2dcd297993dc703a95b79a
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
5 ***************************************************************************/
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
11 #include <string.h>
13 #include "../versaloon_include.h"
14 #include "../versaloon.h"
15 #include "../versaloon_internal.h"
16 #include "usbtoxxx.h"
17 #include "usbtoxxx_internal.h"
19 #define N_A "n/a"
21 static const char *types_name[96] = {
22 "usbtousart", "usbtospi", "usbtoi2c", "usbtogpio", "usbtocan", "usbtopwm",
23 "usbtoadc", "usbtodac",
24 "usbtomicrowire", "usbtoswim", "usbtodusi", N_A, N_A, N_A, "usbtopower", "usbtodelay",
25 N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
26 N_A, N_A, N_A, N_A, N_A, N_A, N_A,
27 "usbtojtagll", "usbtojtaghl", "usbtoissp", "usbtoc2", "usbtosbw",
28 "usbtolpcicp", "usbtoswd", "usbtojtagraw",
29 "usbtobdm", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
30 N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
31 "usbtomsp430jtag", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
32 "usbtopower", "usbtodelay", "usbtopoll", N_A, N_A, N_A, N_A, N_A,
33 N_A, N_A, N_A, N_A, N_A, N_A, N_A, "usbtoall"
36 uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN];
38 #define usbtoxxx_get_type_name(type) \
39 types_name[((type) - VERSALOON_USB_TO_XXX_CMD_START) \
40 % ARRAY_SIZE(types_name)]
42 static uint8_t type_pre;
43 static uint16_t usbtoxxx_buffer_index;
44 static uint16_t usbtoxxx_current_cmd_index;
45 static uint8_t *usbtoxxx_buffer;
47 static uint16_t collect_index;
48 static uint8_t collect_cmd;
49 static uint8_t poll_nesting;
51 struct usbtoxxx_context_t {
52 uint8_t type_pre;
53 uint8_t *usbtoxxx_buffer;
54 uint16_t usbtoxxx_current_cmd_index;
55 uint16_t usbtoxxx_buffer_index;
56 uint16_t versaloon_pending_idx;
58 static struct usbtoxxx_context_t poll_context;
60 static void usbtoxxx_save_context(struct usbtoxxx_context_t *c)
62 c->type_pre = type_pre;
63 c->usbtoxxx_buffer = usbtoxxx_buffer;
64 c->usbtoxxx_buffer_index = usbtoxxx_buffer_index;
65 c->usbtoxxx_current_cmd_index = usbtoxxx_current_cmd_index;
66 c->versaloon_pending_idx = versaloon_pending_idx;
69 static void usbtoxxx_pop_context(struct usbtoxxx_context_t *c)
71 type_pre = c->type_pre;
72 usbtoxxx_buffer = c->usbtoxxx_buffer;
73 usbtoxxx_buffer_index = c->usbtoxxx_buffer_index;
74 usbtoxxx_current_cmd_index = c->usbtoxxx_current_cmd_index;
75 versaloon_pending_idx = c->versaloon_pending_idx;
78 static RESULT usbtoxxx_validate_current_command_type(void)
80 if (type_pre > 0) {
81 /* not the first command */
82 if (!usbtoxxx_buffer) {
83 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(usbtoxxx_buffer));
84 return ERRCODE_INVALID_BUFFER;
87 usbtoxxx_buffer[0] = type_pre;
88 SET_LE_U16(&usbtoxxx_buffer[1], usbtoxxx_current_cmd_index);
90 usbtoxxx_buffer_index += usbtoxxx_current_cmd_index;
91 } else {
92 /* first command */
93 usbtoxxx_buffer_index = 3;
96 /* prepare for next command */
97 usbtoxxx_current_cmd_index = 3;
98 usbtoxxx_buffer = versaloon_buf + usbtoxxx_buffer_index;
100 collect_index = 0;
101 collect_cmd = 0;
103 return ERROR_OK;
106 RESULT usbtoxxx_execute_command(void)
108 uint16_t i;
109 uint16_t inlen;
110 RESULT result = ERROR_OK;
112 if (poll_nesting) {
113 LOG_BUG(ERRMSG_INVALID_USAGE, "USB_TO_POLL");
114 versaloon_free_want_pos();
115 return ERROR_FAIL;
118 if (usbtoxxx_validate_current_command_type() != ERROR_OK) {
119 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
120 versaloon_free_want_pos();
121 return ERRCODE_FAILURE_OPERATION;
123 if (usbtoxxx_buffer_index == 3) {
124 versaloon_free_want_pos();
125 return ERROR_OK;
128 versaloon_buf[0] = USB_TO_ALL;
129 SET_LE_U16(&versaloon_buf[1], usbtoxxx_buffer_index);
131 if (versaloon_send_command(usbtoxxx_buffer_index, &inlen) != ERROR_OK) {
132 versaloon_free_want_pos();
133 return ERROR_FAIL;
136 /* process return data */
137 usbtoxxx_buffer_index = 0;
138 for (i = 0; i < versaloon_pending_idx; i++) {
139 /* check result */
140 if ((i == 0) || !((versaloon_pending[i].collect)
141 && (versaloon_pending[i - 1].collect)
142 && (versaloon_pending[i].cmd
143 == versaloon_pending[i - 1].cmd))) {
144 if (USB_TO_XXX_CMD_NOT_SUPPORT
145 == versaloon_buf[usbtoxxx_buffer_index]) {
146 LOG_ERROR(ERRMSG_NOT_SUPPORT_BY,
147 usbtoxxx_get_type_name(versaloon_pending[i].type),
148 "current dongle");
149 result = ERROR_FAIL;
150 break;
151 } else if (versaloon_buf[usbtoxxx_buffer_index] != USB_TO_XXX_OK) {
152 LOG_ERROR("%s command 0x%02x failed with 0x%02x",
153 usbtoxxx_get_type_name(versaloon_pending[i].type),
154 versaloon_pending[i].cmd,
155 versaloon_buf[usbtoxxx_buffer_index]);
156 result = ERROR_FAIL;
157 break;
159 usbtoxxx_buffer_index++;
162 /* get result data */
163 if (versaloon_pending[i].pos) {
164 uint8_t processed = 0;
166 if (versaloon_pending[i].callback) {
167 versaloon_pending[i].callback(&versaloon_pending[i],
168 versaloon_buf + usbtoxxx_buffer_index, &processed);
170 if (!processed) {
171 struct versaloon_want_pos_t *tmp;
173 tmp = versaloon_pending[i].pos;
174 while (tmp) {
175 if ((tmp->buff) && (tmp->size > 0)) {
176 memcpy(tmp->buff,
177 versaloon_buf + usbtoxxx_buffer_index
178 + tmp->offset,
179 tmp->size);
181 struct versaloon_want_pos_t *free_tmp;
182 free_tmp = tmp;
183 tmp = tmp->next;
184 free(free_tmp);
186 versaloon_pending[i].pos = NULL;
188 } else if ((versaloon_pending[i].want_data_size > 0)
189 && (versaloon_pending[i].data_buffer)) {
190 uint8_t processed = 0;
192 if (versaloon_pending[i].callback) {
193 versaloon_pending[i].callback(&versaloon_pending[i],
194 versaloon_buf + usbtoxxx_buffer_index, &processed);
196 if (!processed) {
197 memcpy(versaloon_pending[i].data_buffer,
198 versaloon_buf + usbtoxxx_buffer_index
199 + versaloon_pending[i].want_data_pos,
200 versaloon_pending[i].want_data_size);
203 usbtoxxx_buffer_index += versaloon_pending[i].actual_data_size;
204 if (usbtoxxx_buffer_index > inlen) {
205 LOG_BUG("%s command 0x%02x process error",
206 usbtoxxx_get_type_name(versaloon_pending[i].type),
207 versaloon_pending[i].cmd);
208 result = ERROR_FAIL;
209 break;
213 /* data is not the right size */
214 if (inlen != usbtoxxx_buffer_index) {
215 LOG_ERROR(ERRMSG_INVALID_TARGET, "length of return data");
216 result = ERROR_FAIL;
219 if (versaloon_pending_idx > 0)
220 versaloon_pending_idx = 0;
221 else {
222 /* no receive data, avoid collision */
223 sleep_ms(10);
226 type_pre = 0;
227 collect_cmd = 0;
228 collect_index = 0;
229 versaloon_free_want_pos();
230 return result;
233 RESULT usbtoxxx_init(void)
235 versaloon_pending_idx = 0;
237 if ((usbtoinfo_get_abilities(usbtoxxx_abilities) != ERROR_OK) ||
238 (usbtoxxx_execute_command() != ERROR_OK))
239 return ERROR_FAIL;
240 LOG_INFO("USB_TO_XXX abilities: 0x%08X:0x%08X:0x%08X",
241 GET_LE_U32(&usbtoxxx_abilities[0]),
242 GET_LE_U32(&usbtoxxx_abilities[4]),
243 GET_LE_U32(&usbtoxxx_abilities[8]));
244 return ERROR_OK;
247 RESULT usbtoxxx_fini(void)
249 usbtoxxx_buffer = NULL;
250 type_pre = 0;
251 return ERROR_OK;
254 bool usbtoxxx_interface_supported(uint8_t cmd)
256 if ((cmd < VERSALOON_USB_TO_XXX_CMD_START) ||
257 (cmd > VERSALOON_USB_TO_XXX_CMD_END))
258 return false;
260 cmd -= VERSALOON_USB_TO_XXX_CMD_START;
261 return (usbtoxxx_abilities[cmd / 8] & (1 << (cmd % 8))) > 0;
264 static RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen)
266 /* check free space, commit if not enough */
267 if (((usbtoxxx_buffer_index + usbtoxxx_current_cmd_index + cmdlen)
268 >= versaloon_buf_size)
269 || (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER)) {
270 struct usbtoxxx_context_t context_tmp;
271 uint8_t poll_nesting_tmp = 0;
273 memset(&context_tmp, 0, sizeof(context_tmp));
274 if (poll_nesting) {
275 if (poll_context.type_pre == 0) {
276 LOG_BUG("USB_TO_POLL toooooo long");
277 return ERROR_OK;
280 usbtoxxx_save_context(&context_tmp);
281 usbtoxxx_pop_context(&poll_context);
282 poll_nesting_tmp = poll_nesting;
283 poll_nesting = 0;
286 if (usbtoxxx_execute_command() != ERROR_OK)
287 return ERROR_FAIL;
289 if (poll_nesting_tmp) {
290 uint16_t newlen, oldlen;
292 newlen = context_tmp.versaloon_pending_idx
293 - poll_context.versaloon_pending_idx;
294 memcpy(&versaloon_pending[0],
295 &versaloon_pending[poll_context.versaloon_pending_idx],
296 sizeof(versaloon_pending[0]) * newlen);
297 context_tmp.versaloon_pending_idx = newlen;
298 oldlen = poll_context.usbtoxxx_buffer_index
299 + poll_context.usbtoxxx_current_cmd_index;
300 newlen = context_tmp.usbtoxxx_buffer_index
301 + context_tmp.usbtoxxx_current_cmd_index;
302 memcpy(versaloon_buf + 3, versaloon_buf + oldlen, newlen - oldlen);
303 oldlen -= 3;
304 context_tmp.usbtoxxx_buffer -= oldlen;
305 context_tmp.usbtoxxx_buffer_index -= oldlen;
306 usbtoxxx_pop_context(&context_tmp);
307 poll_nesting = poll_nesting_tmp;
310 return ERROR_OK;
313 RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf,
314 uint16_t cmdlen, uint16_t retlen, uint8_t *wantbuf,
315 uint16_t wantpos, uint16_t wantlen, uint8_t collect)
317 uint16_t len_tmp;
319 /* 3 more bytes by usbtoxxx_validate_current_command_type */
320 /* 3 more bytes when ((0 == collect_index) || (collect_cmd != cmd)) */
321 if (usbtoxxx_ensure_buffer_size(cmdlen + 6) != ERROR_OK)
322 return ERROR_FAIL;
324 if ((type_pre != type) || (!usbtoxxx_buffer)) {
325 if (usbtoxxx_validate_current_command_type() != ERROR_OK) {
326 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
327 return ERRCODE_FAILURE_OPERATION;
329 type_pre = type;
332 if ((collect_index == 0) || (collect_cmd != cmd)) {
333 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = cmd;
335 if (collect) {
336 collect_index = usbtoxxx_current_cmd_index;
337 collect_cmd = cmd;
338 } else {
339 collect_index = 0;
340 collect_cmd = 0;
342 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], cmdlen);
343 usbtoxxx_current_cmd_index += 2;
344 } else {
345 len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen;
346 SET_LE_U16(&usbtoxxx_buffer[collect_index], len_tmp);
349 if (cmdbuf) {
350 memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen);
351 usbtoxxx_current_cmd_index += cmdlen;
354 return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen,
355 wantbuf, collect);
358 RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN])
360 if (usbtoxxx_ensure_buffer_size(3) != ERROR_OK)
361 return ERROR_FAIL;
363 if (usbtoxxx_validate_current_command_type() != ERROR_OK) {
364 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
365 return ERRCODE_FAILURE_OPERATION;
367 type_pre = USB_TO_INFO;
369 return versaloon_add_pending(USB_TO_INFO, 0, USB_TO_XXX_ABILITIES_LEN, 0,
370 USB_TO_XXX_ABILITIES_LEN, abilities, 0);
373 RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us)
375 if (usbtoxxx_ensure_buffer_size(3 + 5) != ERROR_OK)
376 return ERROR_FAIL;
377 if (!poll_nesting)
378 usbtoxxx_save_context(&poll_context);
380 if (usbtoxxx_validate_current_command_type() != ERROR_OK) {
381 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
382 return ERRCODE_FAILURE_OPERATION;
384 poll_nesting++;
385 type_pre = USB_TO_POLL;
387 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_START;
388 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], retry_cnt);
389 usbtoxxx_current_cmd_index += 2;
390 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], interval_us);
391 usbtoxxx_current_cmd_index += 2;
393 return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
396 RESULT usbtopoll_end(void)
398 if (!poll_nesting) {
399 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
400 return ERRCODE_FAILURE_OPERATION;
402 if (usbtoxxx_ensure_buffer_size(3 + 1) != ERROR_OK)
403 return ERROR_FAIL;
405 if (usbtoxxx_validate_current_command_type() != ERROR_OK) {
406 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
407 return ERRCODE_FAILURE_OPERATION;
410 poll_nesting--;
411 type_pre = USB_TO_POLL;
413 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_END;
415 return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
418 RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size,
419 uint32_t mask, uint32_t value)
421 uint8_t i;
423 if (size > 4) {
424 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
425 return ERRCODE_INVALID_PARAMETER;
427 if (!poll_nesting) {
428 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
429 return ERRCODE_FAILURE_OPERATION;
431 if (usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size) != ERROR_OK)
432 return ERROR_FAIL;
434 if (usbtoxxx_validate_current_command_type() != ERROR_OK) {
435 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
436 return ERRCODE_FAILURE_OPERATION;
439 type_pre = USB_TO_POLL;
441 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKOK;
442 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
443 usbtoxxx_current_cmd_index += 2;
444 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
445 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
446 for (i = 0; i < size; i++)
447 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
448 for (i = 0; i < size; i++)
449 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
451 return ERROR_OK;
454 RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size,
455 uint32_t mask, uint32_t value)
457 uint8_t i;
459 if (size > 4) {
460 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
461 return ERRCODE_INVALID_PARAMETER;
463 if (!poll_nesting) {
464 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
465 return ERRCODE_FAILURE_OPERATION;
467 if (usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size) != ERROR_OK)
468 return ERROR_FAIL;
470 if (usbtoxxx_validate_current_command_type() != ERROR_OK) {
471 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
472 return ERRCODE_FAILURE_OPERATION;
475 type_pre = USB_TO_POLL;
477 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKFAIL;
478 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
479 usbtoxxx_current_cmd_index += 2;
480 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
481 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
482 for (i = 0; i < size; i++)
483 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
484 for (i = 0; i < size; i++)
485 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
487 return ERROR_OK;
490 RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff)
492 if (!poll_nesting) {
493 LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
494 return ERRCODE_FAILURE_OPERATION;
496 if (usbtoxxx_ensure_buffer_size(3 + 5 + size) != ERROR_OK)
497 return ERROR_FAIL;
499 if (usbtoxxx_validate_current_command_type() != ERROR_OK) {
500 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
501 return ERRCODE_FAILURE_OPERATION;
504 type_pre = USB_TO_POLL;
506 usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_VERIFYBUFF;
507 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
508 usbtoxxx_current_cmd_index += 2;
509 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], size);
510 usbtoxxx_current_cmd_index += 2;
511 memcpy(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], buff, size);
512 usbtoxxx_current_cmd_index += size;
514 return ERROR_OK;
517 RESULT usbtodelay_delay(uint16_t dly)
519 if (usbtoxxx_ensure_buffer_size(3 + 2) != ERROR_OK)
520 return ERROR_FAIL;
522 if (usbtoxxx_validate_current_command_type() != ERROR_OK) {
523 LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
524 return ERRCODE_FAILURE_OPERATION;
526 type_pre = USB_TO_DELAY;
528 SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], dly);
529 usbtoxxx_current_cmd_index += 2;
531 return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0);
534 RESULT usbtodelay_delayms(uint16_t ms)
536 return usbtodelay_delay(ms | 0x8000);
539 RESULT usbtodelay_delayus(uint16_t us)
541 return usbtodelay_delay(us & 0x7FFF);