You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

554 lines
16 KiB

  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. ***************************************************************************/
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include <string.h>
  21. #include "../versaloon_include.h"
  22. #include "../versaloon.h"
  23. #include "../versaloon_internal.h"
  24. #include "usbtoxxx.h"
  25. #include "usbtoxxx_internal.h"
  26. #define N_A "n/a"
  27. static const char *types_name[96] = {
  28. "usbtousart", "usbtospi", "usbtoi2c", "usbtogpio", "usbtocan", "usbtopwm",
  29. "usbtoadc", "usbtodac",
  30. "usbtomicrowire", "usbtoswim", "usbtodusi", N_A, N_A, N_A, "usbtopower", "usbtodelay",
  31. N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
  32. N_A, N_A, N_A, N_A, N_A, N_A, N_A,
  33. "usbtojtagll", "usbtojtaghl", "usbtoissp", "usbtoc2", "usbtosbw",
  34. "usbtolpcicp", "usbtoswd", "usbtojtagraw",
  35. "usbtobdm", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
  36. N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A,
  37. "usbtomsp430jtag", N_A, N_A, N_A, N_A, N_A, N_A, N_A,
  38. "usbtopower", "usbtodelay", "usbtopoll", 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, "usbtoall"
  40. };
  41. uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN];
  42. #define usbtoxxx_get_type_name(type) \
  43. types_name[((type) - VERSALOON_USB_TO_XXX_CMD_START) \
  44. % ARRAY_SIZE(types_name)]
  45. static uint8_t type_pre;
  46. static uint16_t usbtoxxx_buffer_index;
  47. static uint16_t usbtoxxx_current_cmd_index;
  48. static uint8_t *usbtoxxx_buffer;
  49. static uint16_t collect_index;
  50. static uint8_t collect_cmd;
  51. static uint8_t poll_nesting;
  52. struct usbtoxxx_context_t {
  53. uint8_t type_pre;
  54. uint8_t *usbtoxxx_buffer;
  55. uint16_t usbtoxxx_current_cmd_index;
  56. uint16_t usbtoxxx_buffer_index;
  57. uint16_t versaloon_pending_idx;
  58. };
  59. static struct usbtoxxx_context_t poll_context;
  60. static void usbtoxxx_save_context(struct usbtoxxx_context_t *c)
  61. {
  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;
  67. }
  68. static void usbtoxxx_pop_context(struct usbtoxxx_context_t *c)
  69. {
  70. type_pre = c->type_pre;
  71. usbtoxxx_buffer = c->usbtoxxx_buffer;
  72. usbtoxxx_buffer_index = c->usbtoxxx_buffer_index;
  73. usbtoxxx_current_cmd_index = c->usbtoxxx_current_cmd_index;
  74. versaloon_pending_idx = c->versaloon_pending_idx;
  75. }
  76. static RESULT usbtoxxx_validate_current_command_type(void)
  77. {
  78. if (type_pre > 0) {
  79. /* not the first command */
  80. if (!usbtoxxx_buffer) {
  81. LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(usbtoxxx_buffer));
  82. return ERRCODE_INVALID_BUFFER;
  83. }
  84. usbtoxxx_buffer[0] = type_pre;
  85. SET_LE_U16(&usbtoxxx_buffer[1], usbtoxxx_current_cmd_index);
  86. usbtoxxx_buffer_index += usbtoxxx_current_cmd_index;
  87. } else {
  88. /* first command */
  89. usbtoxxx_buffer_index = 3;
  90. }
  91. /* prepare for next command */
  92. usbtoxxx_current_cmd_index = 3;
  93. usbtoxxx_buffer = versaloon_buf + usbtoxxx_buffer_index;
  94. collect_index = 0;
  95. collect_cmd = 0;
  96. return ERROR_OK;
  97. }
  98. RESULT usbtoxxx_execute_command(void)
  99. {
  100. uint16_t i;
  101. uint16_t inlen;
  102. RESULT result = ERROR_OK;
  103. if (poll_nesting) {
  104. LOG_BUG(ERRMSG_INVALID_USAGE, "USB_TO_POLL");
  105. versaloon_free_want_pos();
  106. return ERROR_FAIL;
  107. }
  108. if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
  109. LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
  110. versaloon_free_want_pos();
  111. return ERRCODE_FAILURE_OPERATION;
  112. }
  113. if (3 == usbtoxxx_buffer_index) {
  114. versaloon_free_want_pos();
  115. return ERROR_OK;
  116. }
  117. versaloon_buf[0] = USB_TO_ALL;
  118. SET_LE_U16(&versaloon_buf[1], usbtoxxx_buffer_index);
  119. if (ERROR_OK != versaloon_send_command(usbtoxxx_buffer_index, &inlen)) {
  120. versaloon_free_want_pos();
  121. return ERROR_FAIL;
  122. }
  123. /* process return data */
  124. usbtoxxx_buffer_index = 0;
  125. for (i = 0; i < versaloon_pending_idx; i++) {
  126. /* check result */
  127. if ((0 == i) || !((versaloon_pending[i].collect)
  128. && (versaloon_pending[i - 1].collect)
  129. && (versaloon_pending[i].cmd
  130. == versaloon_pending[i - 1].cmd))) {
  131. if (USB_TO_XXX_CMD_NOT_SUPPORT
  132. == versaloon_buf[usbtoxxx_buffer_index]) {
  133. LOG_ERROR(ERRMSG_NOT_SUPPORT_BY,
  134. usbtoxxx_get_type_name(versaloon_pending[i].type),
  135. "current dongle");
  136. result = ERROR_FAIL;
  137. break;
  138. } else if (USB_TO_XXX_OK != versaloon_buf[usbtoxxx_buffer_index]) {
  139. LOG_ERROR("%s command 0x%02x failed with 0x%02x",
  140. usbtoxxx_get_type_name(versaloon_pending[i].type),
  141. versaloon_pending[i].cmd,
  142. versaloon_buf[usbtoxxx_buffer_index]);
  143. result = ERROR_FAIL;
  144. break;
  145. }
  146. usbtoxxx_buffer_index++;
  147. }
  148. /* get result data */
  149. if (versaloon_pending[i].pos) {
  150. uint8_t processed = 0;
  151. if (versaloon_pending[i].callback) {
  152. versaloon_pending[i].callback(&versaloon_pending[i],
  153. versaloon_buf + usbtoxxx_buffer_index, &processed);
  154. }
  155. if (!processed) {
  156. struct versaloon_want_pos_t *tmp;
  157. tmp = versaloon_pending[i].pos;
  158. while (tmp) {
  159. if ((tmp->buff) && (tmp->size > 0)) {
  160. memcpy(tmp->buff,
  161. versaloon_buf + usbtoxxx_buffer_index
  162. + tmp->offset,
  163. tmp->size);
  164. }
  165. struct versaloon_want_pos_t *free_tmp;
  166. free_tmp = tmp;
  167. tmp = tmp->next;
  168. free(free_tmp);
  169. }
  170. versaloon_pending[i].pos = NULL;
  171. }
  172. } else if ((versaloon_pending[i].want_data_size > 0)
  173. && (versaloon_pending[i].data_buffer)) {
  174. uint8_t processed = 0;
  175. if (versaloon_pending[i].callback) {
  176. versaloon_pending[i].callback(&versaloon_pending[i],
  177. versaloon_buf + usbtoxxx_buffer_index, &processed);
  178. }
  179. if (!processed) {
  180. memcpy(versaloon_pending[i].data_buffer,
  181. versaloon_buf + usbtoxxx_buffer_index
  182. + versaloon_pending[i].want_data_pos,
  183. versaloon_pending[i].want_data_size);
  184. }
  185. }
  186. usbtoxxx_buffer_index += versaloon_pending[i].actual_data_size;
  187. if (usbtoxxx_buffer_index > inlen) {
  188. LOG_BUG("%s command 0x%02x process error",
  189. usbtoxxx_get_type_name(versaloon_pending[i].type),
  190. versaloon_pending[i].cmd);
  191. result = ERROR_FAIL;
  192. break;
  193. }
  194. }
  195. /* data is not the right size */
  196. if (inlen != usbtoxxx_buffer_index) {
  197. LOG_ERROR(ERRMSG_INVALID_TARGET, "length of return data");
  198. result = ERROR_FAIL;
  199. }
  200. if (versaloon_pending_idx > 0)
  201. versaloon_pending_idx = 0;
  202. else {
  203. /* no receive data, avoid collision */
  204. sleep_ms(10);
  205. }
  206. type_pre = 0;
  207. collect_cmd = 0;
  208. collect_index = 0;
  209. versaloon_free_want_pos();
  210. return result;
  211. }
  212. RESULT usbtoxxx_init(void)
  213. {
  214. versaloon_pending_idx = 0;
  215. if ((ERROR_OK != usbtoinfo_get_abilities(usbtoxxx_abilities)) ||
  216. (ERROR_OK != usbtoxxx_execute_command()))
  217. return ERROR_FAIL;
  218. LOG_INFO("USB_TO_XXX abilities: 0x%08X:0x%08X:0x%08X",
  219. GET_LE_U32(&usbtoxxx_abilities[0]),
  220. GET_LE_U32(&usbtoxxx_abilities[4]),
  221. GET_LE_U32(&usbtoxxx_abilities[8]));
  222. return ERROR_OK;
  223. }
  224. RESULT usbtoxxx_fini(void)
  225. {
  226. usbtoxxx_buffer = NULL;
  227. type_pre = 0;
  228. return ERROR_OK;
  229. }
  230. bool usbtoxxx_interface_supported(uint8_t cmd)
  231. {
  232. if ((cmd < VERSALOON_USB_TO_XXX_CMD_START) ||
  233. (cmd > VERSALOON_USB_TO_XXX_CMD_END))
  234. return false;
  235. cmd -= VERSALOON_USB_TO_XXX_CMD_START;
  236. return (usbtoxxx_abilities[cmd / 8] & (1 << (cmd % 8))) > 0;
  237. }
  238. static RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen)
  239. {
  240. /* check free space, commit if not enough */
  241. if (((usbtoxxx_buffer_index + usbtoxxx_current_cmd_index + cmdlen)
  242. >= versaloon_buf_size)
  243. || (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER)) {
  244. struct usbtoxxx_context_t context_tmp;
  245. uint8_t poll_nesting_tmp = 0;
  246. memset(&context_tmp, 0, sizeof(context_tmp));
  247. if (poll_nesting) {
  248. if (0 == poll_context.type_pre) {
  249. LOG_BUG("USB_TO_POLL toooooo long");
  250. return ERROR_OK;
  251. }
  252. usbtoxxx_save_context(&context_tmp);
  253. usbtoxxx_pop_context(&poll_context);
  254. poll_nesting_tmp = poll_nesting;
  255. poll_nesting = 0;
  256. }
  257. if (usbtoxxx_execute_command() != ERROR_OK)
  258. return ERROR_FAIL;
  259. if (poll_nesting_tmp) {
  260. uint16_t newlen, oldlen;
  261. newlen = context_tmp.versaloon_pending_idx
  262. - poll_context.versaloon_pending_idx;
  263. memcpy(&versaloon_pending[0],
  264. &versaloon_pending[poll_context.versaloon_pending_idx],
  265. sizeof(versaloon_pending[0]) * newlen);
  266. context_tmp.versaloon_pending_idx = newlen;
  267. oldlen = poll_context.usbtoxxx_buffer_index
  268. + poll_context.usbtoxxx_current_cmd_index;
  269. newlen = context_tmp.usbtoxxx_buffer_index
  270. + context_tmp.usbtoxxx_current_cmd_index;
  271. memcpy(versaloon_buf + 3, versaloon_buf + oldlen, newlen - oldlen);
  272. oldlen -= 3;
  273. context_tmp.usbtoxxx_buffer -= oldlen;
  274. context_tmp.usbtoxxx_buffer_index -= oldlen;
  275. usbtoxxx_pop_context(&context_tmp);
  276. poll_nesting = poll_nesting_tmp;
  277. }
  278. }
  279. return ERROR_OK;
  280. }
  281. RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf,
  282. uint16_t cmdlen, uint16_t retlen, uint8_t *wantbuf,
  283. uint16_t wantpos, uint16_t wantlen, uint8_t collect)
  284. {
  285. uint16_t len_tmp;
  286. /* 3 more bytes by usbtoxxx_validate_current_command_type */
  287. /* 3 more bytes when ((0 == collect_index) || (collect_cmd != cmd)) */
  288. if (ERROR_OK != usbtoxxx_ensure_buffer_size(cmdlen + 6))
  289. return ERROR_FAIL;
  290. if ((type_pre != type) || (!usbtoxxx_buffer)) {
  291. if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
  292. LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
  293. return ERRCODE_FAILURE_OPERATION;
  294. }
  295. type_pre = type;
  296. }
  297. if ((0 == collect_index) || (collect_cmd != cmd)) {
  298. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = cmd;
  299. if (collect) {
  300. collect_index = usbtoxxx_current_cmd_index;
  301. collect_cmd = cmd;
  302. } else {
  303. collect_index = 0;
  304. collect_cmd = 0;
  305. }
  306. SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], cmdlen);
  307. usbtoxxx_current_cmd_index += 2;
  308. } else {
  309. len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen;
  310. SET_LE_U16(&usbtoxxx_buffer[collect_index], len_tmp);
  311. }
  312. if (cmdbuf) {
  313. memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen);
  314. usbtoxxx_current_cmd_index += cmdlen;
  315. }
  316. return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen,
  317. wantbuf, collect);
  318. }
  319. RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN])
  320. {
  321. if (ERROR_OK != usbtoxxx_ensure_buffer_size(3))
  322. return ERROR_FAIL;
  323. if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
  324. LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
  325. return ERRCODE_FAILURE_OPERATION;
  326. }
  327. type_pre = USB_TO_INFO;
  328. return versaloon_add_pending(USB_TO_INFO, 0, USB_TO_XXX_ABILITIES_LEN, 0,
  329. USB_TO_XXX_ABILITIES_LEN, abilities, 0);
  330. }
  331. RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us)
  332. {
  333. if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5))
  334. return ERROR_FAIL;
  335. if (!poll_nesting)
  336. usbtoxxx_save_context(&poll_context);
  337. if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
  338. LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
  339. return ERRCODE_FAILURE_OPERATION;
  340. }
  341. poll_nesting++;
  342. type_pre = USB_TO_POLL;
  343. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_START;
  344. SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], retry_cnt);
  345. usbtoxxx_current_cmd_index += 2;
  346. SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], interval_us);
  347. usbtoxxx_current_cmd_index += 2;
  348. return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
  349. }
  350. RESULT usbtopoll_end(void)
  351. {
  352. if (!poll_nesting) {
  353. LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
  354. return ERRCODE_FAILURE_OPERATION;
  355. }
  356. if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 1))
  357. return ERROR_FAIL;
  358. if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
  359. LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
  360. return ERRCODE_FAILURE_OPERATION;
  361. }
  362. poll_nesting--;
  363. type_pre = USB_TO_POLL;
  364. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_END;
  365. return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0);
  366. }
  367. RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size,
  368. uint32_t mask, uint32_t value)
  369. {
  370. uint8_t i;
  371. if (size > 4) {
  372. LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
  373. return ERRCODE_INVALID_PARAMETER;
  374. }
  375. if (!poll_nesting) {
  376. LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
  377. return ERRCODE_FAILURE_OPERATION;
  378. }
  379. if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
  380. return ERROR_FAIL;
  381. if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
  382. LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
  383. return ERRCODE_FAILURE_OPERATION;
  384. }
  385. type_pre = USB_TO_POLL;
  386. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKOK;
  387. SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
  388. usbtoxxx_current_cmd_index += 2;
  389. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
  390. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
  391. for (i = 0; i < size; i++)
  392. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
  393. for (i = 0; i < size; i++)
  394. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
  395. return ERROR_OK;
  396. }
  397. RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size,
  398. uint32_t mask, uint32_t value)
  399. {
  400. uint8_t i;
  401. if (size > 4) {
  402. LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
  403. return ERRCODE_INVALID_PARAMETER;
  404. }
  405. if (!poll_nesting) {
  406. LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
  407. return ERRCODE_FAILURE_OPERATION;
  408. }
  409. if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size))
  410. return ERROR_FAIL;
  411. if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
  412. LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
  413. return ERRCODE_FAILURE_OPERATION;
  414. }
  415. type_pre = USB_TO_POLL;
  416. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKFAIL;
  417. SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
  418. usbtoxxx_current_cmd_index += 2;
  419. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size;
  420. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ;
  421. for (i = 0; i < size; i++)
  422. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF;
  423. for (i = 0; i < size; i++)
  424. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF;
  425. return ERROR_OK;
  426. }
  427. RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff)
  428. {
  429. if (!poll_nesting) {
  430. LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting");
  431. return ERRCODE_FAILURE_OPERATION;
  432. }
  433. if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5 + size))
  434. return ERROR_FAIL;
  435. if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
  436. LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
  437. return ERRCODE_FAILURE_OPERATION;
  438. }
  439. type_pre = USB_TO_POLL;
  440. usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_VERIFYBUFF;
  441. SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset);
  442. usbtoxxx_current_cmd_index += 2;
  443. SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], size);
  444. usbtoxxx_current_cmd_index += 2;
  445. memcpy(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], buff, size);
  446. usbtoxxx_current_cmd_index += size;
  447. return ERROR_OK;
  448. }
  449. RESULT usbtodelay_delay(uint16_t dly)
  450. {
  451. if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 2))
  452. return ERROR_FAIL;
  453. if (ERROR_OK != usbtoxxx_validate_current_command_type()) {
  454. LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands");
  455. return ERRCODE_FAILURE_OPERATION;
  456. }
  457. type_pre = USB_TO_DELAY;
  458. SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], dly);
  459. usbtoxxx_current_cmd_index += 2;
  460. return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0);
  461. }
  462. RESULT usbtodelay_delayms(uint16_t ms)
  463. {
  464. return usbtodelay_delay(ms | 0x8000);
  465. }
  466. RESULT usbtodelay_delayus(uint16_t us)
  467. {
  468. return usbtodelay_delay(us & 0x7FFF);
  469. }