cliface.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /**
  2. * \file cli.c
  3. *
  4. * This file implements command line interface (CLI) framework.
  5. */
  6. /*
  7. * Copyright (C) 2017. Mindtree Ltd.
  8. * All rights reserved.
  9. */
  10. /* --------------------------------------------- Header File Inclusion */
  11. #include "cliface.h"
  12. //#ifdef HAVE_CLI
  13. /* --------------------------------------------- Global Definitions */
  14. /* --------------------------------------------- Function */
  15. /**
  16. * \fn CLI_init
  17. *
  18. * \brief Initialize CLI
  19. *
  20. * \Description
  21. * This routine intializes CLI.
  22. *
  23. * \return EM_SUCCESS or an error code indicating reason for failure
  24. *
  25. */
  26. uint16_t CLI_init
  27. (
  28. void
  29. )
  30. {
  31. return 0;
  32. }
  33. /**
  34. * \brief Process a command line instruction
  35. *
  36. * \Description
  37. * This routine processes a command line instruction.
  38. *
  39. * \param [in] buffer Buffer containing a command
  40. * \param [in] buffer_len Length of command in buffer
  41. * \param [in] cmd_list Command List
  42. * \param [in] cmd_count Number of command in the list
  43. *
  44. * \return EM_SUCCESS or an error code indicating reason for failure
  45. */
  46. uint16_t CLI_process_line
  47. (
  48. /* IN */ uint8_t * buffer,
  49. /* IN */ uint32_t buffer_len,
  50. /* IN */ CLI_COMMAND * cmd_list,
  51. /* IN */ uint32_t cmd_count
  52. )
  53. {
  54. uint32_t argc;
  55. uint8_t * argv[CLI_MAX_ARGS];
  56. uint8_t * cmd;
  57. uint32_t index;
  58. /* TBD: Parameter Validation */
  59. CLI_NULL_CHECK(buffer);
  60. /* Skip initial white spaces */
  61. for (; CLI_IS_WHITE_SPACE(*buffer) && (0 != buffer_len); buffer++, buffer_len--);
  62. /* Check this is not an empty command line */
  63. if (0 == buffer_len)
  64. {
  65. CLI_ERR(
  66. "[CLI] Empty command line\n");
  67. return 0xffff;
  68. }
  69. /**
  70. * Got the initial command.
  71. * Parse the remaining command line to get the arguments.
  72. */
  73. argc = 0;
  74. for (cmd = buffer + 1; cmd < (buffer + buffer_len); cmd++)
  75. {
  76. /**
  77. * If command argument separator is detected, replace with '\0'
  78. * to create each as separate strings.
  79. */
  80. if (CLI_IS_CMD_SEPARATOR(*cmd))
  81. {
  82. #ifdef AT_CMD
  83. if(('\r' == *cmd) && ('\n' == *(cmd+1))) // support '\r\n' for some uart tools in windows.
  84. {
  85. *cmd = '\0';
  86. //cmd++;
  87. break;
  88. }
  89. if(' ' == *cmd)
  90. {
  91. *cmd = '\0';
  92. break;
  93. }
  94. #endif //end AT_CMD
  95. *cmd = '\0';
  96. }
  97. /* Check if this is start of a new argument */
  98. else if ('\0' == (*(cmd - 1)))
  99. {
  100. argv[argc++] = cmd;
  101. }
  102. else
  103. {
  104. /* Nothing to do */
  105. }
  106. }
  107. CLI_TRC(
  108. "[CLI] Command %s, Number of arguments %d\n", buffer, argc);
  109. {
  110. uint8_t ai;
  111. for (ai = 0; ai < argc; ai++)
  112. {
  113. CLI_TRC(
  114. "Arg [%02X] %s\n", ai, argv[ai]);
  115. }
  116. }
  117. /* Identified command name */
  118. cmd = buffer;
  119. /* Search command and call associated callback */
  120. for (index = 0; index < cmd_count; index++)
  121. {
  122. if (0 == CLI_STR_COMPARE(buffer, cmd_list[index].cmd))
  123. {
  124. cmd_list[index].cmd_hdlr(argc, argv);
  125. break;
  126. }
  127. }
  128. return 0;
  129. }
  130. /* TODO: Create a separe utility module or move to a common utility module */
  131. /* Supporting Macros */
  132. #define IS_SPACE(c) ((' ' == (c)) || ('\t' == (c)))
  133. #define IS_DIGIT(c) (('0' <= (c)) && ('9' >= (c)))
  134. #define IS_UPPER(c) (('A' <= (c)) && ('F' >= (c)))
  135. #define IS_LOWER(c) (('a' <= (c)) && ('f' >= (c)))
  136. #define IS_ALPHA(c) IS_LOWER(c) || IS_UPPER(c)
  137. /* Convert string to Integer */
  138. int32_t CLI_strtoi
  139. (
  140. /* IN */ uint8_t *data,
  141. /* IN */ uint16_t data_length,
  142. /* IN */ uint8_t base
  143. )
  144. {
  145. int32_t value;
  146. uint16_t index;
  147. int8_t sign_adj;
  148. uint8_t c;
  149. c = 0;
  150. /* Skip Whitespaces */
  151. for (index = 0; index < data_length; index++)
  152. {
  153. c = data[index];
  154. if (IS_SPACE(c))
  155. {
  156. continue;
  157. }
  158. else
  159. {
  160. break;
  161. }
  162. }
  163. value = 0;
  164. sign_adj = 1;
  165. /* Check Sign */
  166. if ('-' == c)
  167. {
  168. sign_adj = (int8_t)-1;
  169. index++;
  170. }
  171. /* Not handling spaces after '-' or '0x' etc. */
  172. for (; index < data_length; index++)
  173. {
  174. c = data[index];
  175. /* Check if Digit */
  176. if (IS_DIGIT(c))
  177. {
  178. value *= base;
  179. value += (c - '0');
  180. }
  181. else if (IS_LOWER(c))
  182. {
  183. value *= base;
  184. value += (c - 'a' + 10);
  185. }
  186. else if (IS_UPPER(c))
  187. {
  188. value *= base;
  189. value += (c - 'A' + 10);
  190. }
  191. else
  192. {
  193. break;
  194. }
  195. }
  196. return (sign_adj * value);
  197. }
  198. /* Convert string to Integer Array */
  199. uint16_t CLI_strtoarray
  200. (
  201. /* IN */ uint8_t * data,
  202. /* IN */ uint16_t data_length,
  203. /* OUT */ uint8_t * output_array,
  204. /* IN */ uint16_t output_array_len
  205. )
  206. {
  207. int32_t index;
  208. uint8_t c0, c1;
  209. uint8_t base;
  210. uint16_t output_index;
  211. /* HEX */
  212. base = 16;
  213. c0 = 0;
  214. c1 = 0;
  215. /* Fill with Zeros */
  216. memset(output_array, 0, output_array_len);
  217. /* Check the length */
  218. if (data_length > (2 * output_array_len))
  219. {
  220. return 0xFFFF;
  221. }
  222. /* Process from end */
  223. output_index = output_array_len - 1;
  224. for (index = data_length - 1; index >= 0; index -= 2)
  225. {
  226. if (0 != index)
  227. {
  228. c1 = data[index];
  229. c0 = data[index - 1];
  230. }
  231. else
  232. {
  233. c1 = data[index];
  234. c0 = '0';
  235. }
  236. /* Check if Digit */
  237. if (IS_DIGIT(c0))
  238. {
  239. c0 = (c0 - '0');
  240. }
  241. else if (IS_LOWER(c0))
  242. {
  243. c0 = (c0 - 'a' + 10);
  244. }
  245. else if (IS_UPPER(c0))
  246. {
  247. c0 = (c0 - 'A' + 10);
  248. }
  249. else
  250. {
  251. return 0xFFFF;
  252. }
  253. /* Check if Digit */
  254. if (IS_DIGIT(c1))
  255. {
  256. c1 = (c1 - '0');
  257. }
  258. else if (IS_LOWER(c1))
  259. {
  260. c1 = (c1 - 'a' + 10);
  261. }
  262. else if (IS_UPPER(c1))
  263. {
  264. c1 = (c1 - 'A' + 10);
  265. }
  266. else
  267. {
  268. return 0xFFFF;
  269. }
  270. output_array[output_index] = c0 * base + c1;
  271. output_index--;
  272. }
  273. return 0;
  274. }
  275. /* Convert string to Integer Array in Little Endian Packing */
  276. uint16_t CLI_strtoarray_le
  277. (
  278. /* IN */ uint8_t * data,
  279. /* IN */ uint16_t data_length,
  280. /* OUT */ uint8_t * output_array,
  281. /* IN */ uint16_t output_array_len
  282. )
  283. {
  284. int32_t index;
  285. uint8_t c0, c1;
  286. uint8_t base;
  287. uint16_t output_index;
  288. /* HEX */
  289. base = 16;
  290. c0 = 0;
  291. c1 = 0;
  292. /* Fill with Zeros */
  293. memset(output_array, 0, output_array_len);
  294. /* Check the length */
  295. if (data_length > (2 * output_array_len))
  296. {
  297. return 0xFFFF;
  298. }
  299. /* Process from end */
  300. output_index = 0;
  301. for (index = data_length - 1; index >= 0; index -= 2)
  302. {
  303. if (0 != index)
  304. {
  305. c1 = data[index];
  306. c0 = data[index - 1];
  307. }
  308. else
  309. {
  310. c1 = data[index];
  311. c0 = '0';
  312. }
  313. /* Check if Digit */
  314. if (IS_DIGIT(c0))
  315. {
  316. c0 = (c0 - '0');
  317. }
  318. else if (IS_LOWER(c0))
  319. {
  320. c0 = (c0 - 'a' + 10);
  321. }
  322. else if (IS_UPPER(c0))
  323. {
  324. c0 = (c0 - 'A' + 10);
  325. }
  326. else
  327. {
  328. return 0xFFFF;
  329. }
  330. /* Check if Digit */
  331. if (IS_DIGIT(c1))
  332. {
  333. c1 = (c1 - '0');
  334. }
  335. else if (IS_LOWER(c1))
  336. {
  337. c1 = (c1 - 'a' + 10);
  338. }
  339. else if (IS_UPPER(c1))
  340. {
  341. c1 = (c1 - 'A' + 10);
  342. }
  343. else
  344. {
  345. return 0xFFFF;
  346. }
  347. output_array[output_index] = c0 * base + c1;
  348. output_index++;
  349. }
  350. return 0;
  351. }
  352. //#endif /* HAVE_CLI */