OpenOCD
usbtoxxx.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
5  ***************************************************************************/
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
11 #include <string.h>
12 
13 #include "../versaloon_include.h"
14 #include "../versaloon.h"
15 #include "../versaloon_internal.h"
16 #include "usbtoxxx.h"
17 #include "usbtoxxx_internal.h"
18 
19 #define N_A "n/a"
20 
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"
34 };
35 
37 
38 #define usbtoxxx_get_type_name(type) \
39  types_name[((type) - VERSALOON_USB_TO_XXX_CMD_START) \
40  % ARRAY_SIZE(types_name)]
41 
42 static uint8_t type_pre;
43 static uint16_t usbtoxxx_buffer_index;
45 static uint8_t *usbtoxxx_buffer;
46 
47 static uint16_t collect_index;
48 static uint8_t collect_cmd;
49 static uint8_t poll_nesting;
50 
52  uint8_t type_pre;
53  uint8_t *usbtoxxx_buffer;
57 };
58 static struct usbtoxxx_context_t poll_context;
59 
61 {
62  c->type_pre = type_pre;
67 }
68 
70 {
71  type_pre = c->type_pre;
76 }
77 
79 {
80  if (type_pre > 0) {
81  /* not the first command */
82  if (!usbtoxxx_buffer) {
85  }
86 
89 
91  } else {
92  /* first command */
94  }
95 
96  /* prepare for next command */
99 
100  collect_index = 0;
101  collect_cmd = 0;
102 
103  return ERROR_OK;
104 }
105 
107 {
108  uint16_t i;
109  uint16_t inlen;
110  RESULT result = ERROR_OK;
111 
112  if (poll_nesting) {
113  LOG_BUG(ERRMSG_INVALID_USAGE, "USB_TO_POLL");
115  return ERROR_FAIL;
116  }
117 
119  LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
122  }
123  if (usbtoxxx_buffer_index == 3) {
125  return ERROR_OK;
126  }
127 
130 
133  return ERROR_FAIL;
134  }
135 
136  /* process return data */
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))) {
148  "current dongle");
149  result = ERROR_FAIL;
150  break;
152  LOG_ERROR("%s command 0x%02x failed with 0x%02x",
156  result = ERROR_FAIL;
157  break;
158  }
160  }
161 
162  /* get result data */
163  if (versaloon_pending[i].pos) {
164  uint8_t processed = 0;
165 
166  if (versaloon_pending[i].callback) {
168  versaloon_buf + usbtoxxx_buffer_index, &processed);
169  }
170  if (!processed) {
171  struct versaloon_want_pos_t *tmp;
172 
173  tmp = versaloon_pending[i].pos;
174  while (tmp) {
175  if ((tmp->buff) && (tmp->size > 0)) {
176  memcpy(tmp->buff,
178  + tmp->offset,
179  tmp->size);
180  }
181  struct versaloon_want_pos_t *free_tmp;
182  free_tmp = tmp;
183  tmp = tmp->next;
184  free(free_tmp);
185  }
187  }
188  } else if ((versaloon_pending[i].want_data_size > 0)
189  && (versaloon_pending[i].data_buffer)) {
190  uint8_t processed = 0;
191 
192  if (versaloon_pending[i].callback) {
194  versaloon_buf + usbtoxxx_buffer_index, &processed);
195  }
196  if (!processed) {
197  memcpy(versaloon_pending[i].data_buffer,
199  + versaloon_pending[i].want_data_pos,
200  versaloon_pending[i].want_data_size);
201  }
202  }
204  if (usbtoxxx_buffer_index > inlen) {
205  LOG_BUG("%s command 0x%02x process error",
208  result = ERROR_FAIL;
209  break;
210  }
211  }
212 
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;
217  }
218 
219  if (versaloon_pending_idx > 0)
221  else {
222  /* no receive data, avoid collision */
223  sleep_ms(10);
224  }
225 
226  type_pre = 0;
227  collect_cmd = 0;
228  collect_index = 0;
230  return result;
231 }
232 
234 {
236 
239  return ERROR_FAIL;
240  LOG_INFO("USB_TO_XXX abilities: 0x%08X:0x%08X:0x%08X",
244  return ERROR_OK;
245 }
246 
248 {
250  type_pre = 0;
251  return ERROR_OK;
252 }
253 
255 {
258  return false;
259 
261  return (usbtoxxx_abilities[cmd / 8] & (1 << (cmd % 8))) > 0;
262 }
263 
264 static RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen)
265 {
266  /* check free space, commit if not enough */
270  struct usbtoxxx_context_t context_tmp;
271  uint8_t poll_nesting_tmp = 0;
272 
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;
278  }
279 
280  usbtoxxx_save_context(&context_tmp);
282  poll_nesting_tmp = poll_nesting;
283  poll_nesting = 0;
284  }
285 
287  return ERROR_FAIL;
288 
289  if (poll_nesting_tmp) {
290  uint16_t newlen, oldlen;
291 
292  newlen = context_tmp.versaloon_pending_idx
294  memcpy(&versaloon_pending[0],
296  sizeof(versaloon_pending[0]) * newlen);
297  context_tmp.versaloon_pending_idx = newlen;
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;
308  }
309  }
310  return ERROR_OK;
311 }
312 
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)
316 {
317  uint16_t len_tmp;
318 
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;
323 
324  if ((type_pre != type) || (!usbtoxxx_buffer)) {
326  LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
328  }
329  type_pre = type;
330  }
331 
332  if ((collect_index == 0) || (collect_cmd != cmd)) {
334 
335  if (collect) {
337  collect_cmd = cmd;
338  } else {
339  collect_index = 0;
340  collect_cmd = 0;
341  }
344  } else {
345  len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen;
347  }
348 
349  if (cmdbuf) {
350  memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen);
351  usbtoxxx_current_cmd_index += cmdlen;
352  }
353 
354  return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen,
355  wantbuf, collect);
356 }
357 
359 {
361  return ERROR_FAIL;
362 
364  LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
366  }
368 
370  USB_TO_XXX_ABILITIES_LEN, abilities, 0);
371 }
372 
373 RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us)
374 {
376  return ERROR_FAIL;
377  if (!poll_nesting)
379 
381  LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
383  }
384  poll_nesting++;
386 
392 
393  return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
394 }
395 
397 {
398  if (!poll_nesting) {
399  LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
401  }
403  return ERROR_FAIL;
404 
406  LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
408  }
409 
410  poll_nesting--;
412 
414 
415  return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
416 }
417 
418 RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size,
419  uint32_t mask, uint32_t value)
420 {
421  uint8_t i;
422 
423  if (size > 4) {
426  }
427  if (!poll_nesting) {
428  LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
430  }
431  if (usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size) != ERROR_OK)
432  return ERROR_FAIL;
433 
435  LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
437  }
438 
440 
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;
450 
451  return ERROR_OK;
452 }
453 
454 RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size,
455  uint32_t mask, uint32_t value)
456 {
457  uint8_t i;
458 
459  if (size > 4) {
462  }
463  if (!poll_nesting) {
464  LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
466  }
467  if (usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size) != ERROR_OK)
468  return ERROR_FAIL;
469 
471  LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
473  }
474 
476 
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;
486 
487  return ERROR_OK;
488 }
489 
490 RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff)
491 {
492  if (!poll_nesting) {
493  LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
495  }
496  if (usbtoxxx_ensure_buffer_size(3 + 5 + size) != ERROR_OK)
497  return ERROR_FAIL;
498 
500  LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
502  }
503 
505 
513 
514  return ERROR_OK;
515 }
516 
518 {
520  return ERROR_FAIL;
521 
523  LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
525  }
527 
530 
531  return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0);
532 }
533 
535 {
536  return usbtodelay_delay(ms | 0x8000);
537 }
538 
540 {
541  return usbtodelay_delay(us & 0x7FFF);
542 }
int mask
Definition: esirisc.c:1741
uint8_t type
Definition: esp_usb_jtag.c:0
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_INFO(expr ...)
Definition: log.h:126
#define ERROR_OK
Definition: log.h:164
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
uint8_t type_pre
Definition: usbtoxxx.c:52
uint16_t usbtoxxx_buffer_index
Definition: usbtoxxx.c:55
uint16_t usbtoxxx_current_cmd_index
Definition: usbtoxxx.c:54
uint8_t * usbtoxxx_buffer
Definition: usbtoxxx.c:53
uint16_t versaloon_pending_idx
Definition: usbtoxxx.c:56
struct versaloon_want_pos_t * pos
versaloon_callback_t callback
struct versaloon_want_pos_t * next
#define NULL
Definition: usb.h:16
RESULT usbtodelay_delayms(uint16_t ms)
Definition: usbtoxxx.c:534
static uint16_t usbtoxxx_current_cmd_index
Definition: usbtoxxx.c:44
RESULT usbtodelay_delayus(uint16_t us)
Definition: usbtoxxx.c:539
bool usbtoxxx_interface_supported(uint8_t cmd)
Definition: usbtoxxx.c:254
RESULT usbtoxxx_init(void)
Definition: usbtoxxx.c:233
#define N_A
Definition: usbtoxxx.c:19
RESULT usbtopoll_end(void)
Definition: usbtoxxx.c:396
static uint16_t usbtoxxx_buffer_index
Definition: usbtoxxx.c:43
static uint8_t poll_nesting
Definition: usbtoxxx.c:49
static void usbtoxxx_save_context(struct usbtoxxx_context_t *c)
Definition: usbtoxxx.c:60
uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN]
Definition: usbtoxxx.c:36
RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size, uint32_t mask, uint32_t value)
Definition: usbtoxxx.c:454
RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf, uint16_t cmdlen, uint16_t retlen, uint8_t *wantbuf, uint16_t wantpos, uint16_t wantlen, uint8_t collect)
Definition: usbtoxxx.c:313
static RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen)
Definition: usbtoxxx.c:264
RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size, uint32_t mask, uint32_t value)
Definition: usbtoxxx.c:418
RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us)
Definition: usbtoxxx.c:373
RESULT usbtodelay_delay(uint16_t dly)
Definition: usbtoxxx.c:517
static RESULT usbtoxxx_validate_current_command_type(void)
Definition: usbtoxxx.c:78
RESULT usbtoxxx_execute_command(void)
Definition: usbtoxxx.c:106
static const char * types_name[96]
Definition: usbtoxxx.c:21
RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff)
Definition: usbtoxxx.c:490
static uint8_t collect_cmd
Definition: usbtoxxx.c:48
static uint8_t * usbtoxxx_buffer
Definition: usbtoxxx.c:45
#define usbtoxxx_get_type_name(type)
Definition: usbtoxxx.c:38
static uint8_t type_pre
Definition: usbtoxxx.c:42
static void usbtoxxx_pop_context(struct usbtoxxx_context_t *c)
Definition: usbtoxxx.c:69
RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN])
Definition: usbtoxxx.c:358
static struct usbtoxxx_context_t poll_context
Definition: usbtoxxx.c:58
static uint16_t collect_index
Definition: usbtoxxx.c:47
RESULT usbtoxxx_fini(void)
Definition: usbtoxxx.c:247
#define USB_TO_XXX_ABILITIES_LEN
Definition: usbtoxxx.h:14
#define USB_TO_INFO
#define USB_TO_POLL_VERIFYBUFF
#define USB_TO_ALL
#define USB_TO_POLL
#define USB_TO_XXX_CMD_NOT_SUPPORT
#define USB_TO_DELAY
#define USB_TO_POLL_CHECKOK
#define USB_TO_POLL_START
#define USB_TO_XXX_OK
#define USB_TO_POLL_END
#define USB_TO_POLL_CHECKFAIL
uint8_t cmd
Definition: vdebug.c:1
uint8_t offset[4]
Definition: vdebug.c:9
void versaloon_free_want_pos(void)
Definition: versaloon.c:102
uint8_t * versaloon_buf
Definition: versaloon.c:21
uint16_t versaloon_pending_idx
Definition: versaloon.c:26
struct versaloon_pending_t versaloon_pending[VERSALOON_MAX_PENDING_NUMBER]
Definition: versaloon.c:25
uint16_t versaloon_buf_size
Definition: versaloon.c:23
RESULT versaloon_add_pending(uint8_t type, uint8_t cmd, uint16_t actual_szie, uint16_t want_pos, uint16_t want_size, uint8_t *buffer, uint8_t collect)
Definition: versaloon.c:153
RESULT versaloon_send_command(uint16_t out_len, uint16_t *inlen)
Definition: versaloon.c:184
#define ERRCODE_INVALID_BUFFER
#define GET_LE_U16(p)
#define ERRMSG_INVALID_TARGET
#define ERRMSG_INVALID_PARAMETER
#define ERRCODE_FAILURE_OPERATION
#define TO_STR(name)
#define RESULT
#define ERRMSG_INVALID_USAGE
#define ERRMSG_NOT_SUPPORT_BY
#define GET_LE_U32(p)
#define ERRCODE_INVALID_PARAMETER
#define sleep_ms(ms)
#define LOG_BUG
#define SET_LE_U16(p, v)
#define ERRMSG_FAILURE_OPERATION
#define ERRMSG_INVALID_BUFFER
#define VERSALOON_USB_TO_XXX_CMD_START
#define VERSALOON_USB_TO_XXX_CMD_END
#define VERSALOON_MAX_PENDING_NUMBER