lua2rtt.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*
  2. * @File: lua2rtt.c
  3. * @Author: liu2guang
  4. * @Date: 2018-05-06 09:16:56
  5. *
  6. * @LICENSE: https://github.com/liu2guang/lua2rtt/blob/master/LICENSE.
  7. *
  8. * Change Logs:
  9. * Date Author Notes
  10. * 2018-05-06 liu2guang The first version.
  11. */
  12. #include "lua2rtt.h"
  13. #include "shell.h"
  14. #if defined(RT_USING_POSIX)
  15. #include <stdio.h>
  16. #endif
  17. static struct lua2rtt handle = {0};
  18. static rt_uint8_t lua2rtt_getc(void)
  19. {
  20. rt_uint8_t ch = 0;
  21. while(rt_device_read(handle.device, (-1), &ch, 1) != 1)
  22. {
  23. rt_sem_take(&(handle.rx_sem), RT_WAITING_FOREVER);
  24. }
  25. return ch;
  26. }
  27. static rt_err_t lua2rtt_rxcb(rt_device_t dev, rt_size_t size)
  28. {
  29. return rt_sem_release(&(handle.rx_sem));
  30. }
  31. static rt_bool_t lua2rtt_handle_history(const char *prompt)
  32. {
  33. rt_kprintf("\033[2K\r");
  34. rt_kprintf("%s%s", prompt, handle.line);
  35. return RT_FALSE;
  36. }
  37. static void lua2rtt_push_history(void)
  38. {
  39. if(handle.line_position > 0)
  40. {
  41. if(handle.history_count >= LUA2RTT_HISTORY_LINES)
  42. {
  43. if(rt_memcmp(&handle.lua_history[LUA2RTT_HISTORY_LINES-1], handle.line, LUA2RTT_CMD_SIZE))
  44. {
  45. int index;
  46. for(index = 0; index < FINSH_HISTORY_LINES - 1; index ++)
  47. {
  48. rt_memcpy(&handle.lua_history[index][0], &handle.lua_history[index+1][0], LUA2RTT_CMD_SIZE);
  49. }
  50. rt_memset(&handle.lua_history[index][0], 0, LUA2RTT_CMD_SIZE);
  51. rt_memcpy(&handle.lua_history[index][0], handle.line, handle.line_position);
  52. handle.history_count = LUA2RTT_HISTORY_LINES;
  53. }
  54. }
  55. else
  56. {
  57. if(handle.history_count == 0 || rt_memcmp(&handle.lua_history[handle.history_count-1], handle.line, LUA2RTT_CMD_SIZE))
  58. {
  59. handle.history_current = handle.history_count;
  60. rt_memset(&handle.lua_history[handle.history_count][0], 0, LUA2RTT_CMD_SIZE);
  61. rt_memcpy(&handle.lua_history[handle.history_count][0], handle.line, handle.line_position);
  62. handle.history_count++;
  63. }
  64. }
  65. }
  66. handle.history_current = handle.history_count;
  67. }
  68. /* Lua回调函数 */
  69. int lua2rtt_readline(const char *prompt, char *buffer, int buffer_size)
  70. {
  71. rt_uint8_t ch;
  72. start:
  73. rt_kprintf(prompt);
  74. while(1)
  75. {
  76. ch = lua2rtt_getc();
  77. /* 处理方向键: 方向键为3个字节: 0x1B 0x5B 0x41/42/43/44 */
  78. if(ch == 0x1b)
  79. {
  80. handle.stat = LUA2RTT_WAIT_SPEC_KEY;
  81. continue;
  82. }
  83. else if(handle.stat == LUA2RTT_WAIT_SPEC_KEY)
  84. {
  85. if(ch == 0x5b)
  86. {
  87. handle.stat = LUA2RTT_WAIT_FUNC_KEY;
  88. continue;
  89. }
  90. handle.stat = LUA2RTT_WAIT_NORMAL;
  91. }
  92. else if(handle.stat == LUA2RTT_WAIT_FUNC_KEY)
  93. {
  94. handle.stat = LUA2RTT_WAIT_NORMAL;
  95. if(ch == 0x41) /* 键盘UP键 */
  96. {
  97. if(handle.history_current > 0)
  98. {
  99. handle.history_current--;
  100. }
  101. else
  102. {
  103. handle.history_current = 0;
  104. continue;
  105. }
  106. /* copy the history command */
  107. rt_memcpy(handle.line, &handle.lua_history[handle.history_current][0], LUA2RTT_CMD_SIZE);
  108. handle.line_curpos = handle.line_position = rt_strlen(handle.line);
  109. lua2rtt_handle_history(prompt);
  110. continue;
  111. }
  112. else if(ch == 0x42) /* 键盘DOWN键 */
  113. {
  114. if(handle.history_current < (handle.history_count-1))
  115. {
  116. handle.history_current++;
  117. }
  118. else
  119. {
  120. /* set to the end of history */
  121. if(handle.history_count != 0)
  122. {
  123. handle.history_current = handle.history_count-1;
  124. }
  125. else
  126. {
  127. continue;
  128. }
  129. }
  130. rt_memcpy(handle.line, &handle.lua_history[handle.history_current][0], LUA2RTT_CMD_SIZE);
  131. handle.line_curpos = handle.line_position = rt_strlen(handle.line);
  132. lua2rtt_handle_history(prompt);
  133. continue;
  134. }
  135. else if(ch == 0x44) /* 键盘LEFT键 */
  136. {
  137. if(handle.line_curpos)
  138. {
  139. rt_kprintf("\b");
  140. handle.line_curpos--;
  141. }
  142. continue;
  143. }
  144. else if(ch == 0x43) /* 键盘RIGHT键 */
  145. {
  146. if(handle.line_curpos < handle.line_position)
  147. {
  148. rt_kprintf("%c", handle.line[handle.line_curpos]);
  149. handle.line_curpos++;
  150. }
  151. continue;
  152. }
  153. }
  154. /* 处理空字符和错误 */
  155. if(ch == '\0' || ch == 0xFF)
  156. {
  157. continue;
  158. }
  159. /* 处理方向键删除键 */
  160. else if(ch == 0x7f || ch == 0x08)
  161. {
  162. /* 输入的命令字符串为空, 不对字符串进行删除处理 */
  163. if(handle.line_curpos == 0)
  164. {
  165. continue;
  166. }
  167. handle.line_curpos--;
  168. handle.line_position--;
  169. if(handle.line_position > handle.line_curpos)
  170. {
  171. /* 删除当前光标所在处的字符 */
  172. rt_memmove(&handle.line[handle.line_curpos], &handle.line[handle.line_curpos+1],
  173. handle.line_position-handle.line_curpos);
  174. handle.line[handle.line_position] = 0;
  175. /* 重新打印移动后的字符串 */
  176. rt_kprintf("\b%s \b", &handle.line[handle.line_curpos]);
  177. int index;
  178. for(index = (handle.line_curpos); index <= (handle.line_position); index++)
  179. {
  180. rt_kprintf("\b");
  181. }
  182. }
  183. else
  184. {
  185. rt_kprintf("\b \b");
  186. handle.line[handle.line_position] = 0;
  187. }
  188. continue;
  189. }
  190. /* 处理回车键 */
  191. else if(ch == '\r' || ch == '\n')
  192. {
  193. /* 存入历史记录 */
  194. lua2rtt_push_history();
  195. rt_kprintf("\n");
  196. if(handle.line_position == 0)
  197. {
  198. goto start;
  199. }
  200. else
  201. {
  202. rt_uint8_t temp = handle.line_position;
  203. /* 拷贝输入命令 */
  204. rt_strncpy(buffer, handle.line, handle.line_position);
  205. rt_memset(handle.line, 0x00, sizeof(handle.line));
  206. buffer[handle.line_position] = 0;
  207. handle.line_curpos = handle.line_position = 0;
  208. return temp;
  209. }
  210. }
  211. /* 处理ctrl+D退出键 */
  212. else if(ch == 0x04)
  213. {
  214. if(handle.line_position == 0)
  215. {
  216. return 0;
  217. }
  218. else
  219. {
  220. continue;
  221. }
  222. }
  223. /* 处理Tab按键 */
  224. else if(ch == '\t')
  225. {
  226. continue;
  227. }
  228. /* 处理其他控制字符 */
  229. else if(ch < 0x20 || ch >= 0x80)
  230. {
  231. continue;
  232. }
  233. /* 判断输出命令是否过长, 过长后不处理字符, 默认128Byte字符 */
  234. if(handle.line_position >= LUA2RTT_CMD_SIZE)
  235. {
  236. continue;
  237. }
  238. /* 处理普通字符, 将普通字符添加到缓存中 */
  239. if(handle.line_curpos < handle.line_position)
  240. {
  241. rt_memmove(&handle.line[handle.line_curpos+1], &handle.line[handle.line_curpos],
  242. handle.line_position-handle.line_curpos);
  243. handle.line[handle.line_curpos] = ch;
  244. rt_kprintf("%s", &handle.line[handle.line_curpos]);
  245. int index;
  246. for(index = (handle.line_curpos); index < (handle.line_position); index++)
  247. {
  248. rt_kprintf("\b");
  249. }
  250. }
  251. else
  252. {
  253. handle.line[handle.line_position] = ch;
  254. rt_kprintf("%c", ch);
  255. }
  256. ch = 0;
  257. handle.line_curpos++;
  258. handle.line_position++;
  259. }
  260. }
  261. static void lua2rtt_run(void *p)
  262. {
  263. const char *device_name = RT_CONSOLE_DEVICE_NAME;
  264. handle.device = rt_device_find(device_name);
  265. if(handle.device == RT_NULL)
  266. {
  267. LUA2RTT_DBG("The msh device find failed.\n");
  268. return;
  269. }
  270. /* 缓存msh使用的串口回调函数 */
  271. handle.rx_indicate = handle.device->rx_indicate;
  272. /* 设置Lua2RTT的串口回调函数 */
  273. rt_device_set_rx_indicate(handle.device, lua2rtt_rxcb);
  274. /* 阻塞式运行lua解析器 */
  275. extern int lua_main(int argc, char **argv);
  276. lua_main(handle.argc, handle.argv);
  277. /* 释放参数分配内存 */
  278. if(handle.argc > 1)
  279. {
  280. rt_free(handle.argv[1]);
  281. }
  282. /* 退出Lua2RTT解析器时恢复msh对串口的控制权 */
  283. rt_device_set_rx_indicate(handle.device, handle.rx_indicate);
  284. }
  285. /* MSH Lua解析器启动命令 */
  286. static int lua2rtt(int argc, char **argv)
  287. {
  288. static rt_bool_t history_init = RT_FALSE;
  289. /* 初始化Lua2RTT句柄, 但是不初始化重复初始化历史记录 */
  290. if(history_init == RT_FALSE)
  291. {
  292. rt_memset(&handle, 0x00, sizeof(struct lua2rtt));
  293. history_init = RT_TRUE;
  294. }
  295. else
  296. {
  297. handle.thread = RT_NULL;
  298. handle.stat = LUA2RTT_WAIT_NORMAL;
  299. handle.argc = 0;
  300. handle.argv[0] = RT_NULL;
  301. handle.argv[1] = RT_NULL;
  302. handle.argv[2] = RT_NULL;
  303. rt_memset(handle.line, 0x00, LUA2RTT_CMD_SIZE);
  304. handle.line_position = 0;
  305. handle.line_curpos = 0;
  306. handle.device = RT_NULL;
  307. handle.rx_indicate = RT_NULL;
  308. }
  309. /* 初始化Lua2RTT串口数据接收信号量 */
  310. rt_sem_init(&(handle.rx_sem), "lua2rtt_rxsem", 0, RT_IPC_FLAG_FIFO);
  311. /* 处理输出参数 */
  312. handle.argc = argc;
  313. handle.argv[0] = "lua";
  314. handle.argv[1] = RT_NULL;
  315. handle.argv[2] = RT_NULL;
  316. if(argc > 1)
  317. {
  318. rt_size_t len = rt_strlen(argv[1]);
  319. handle.argv[1] = (char *)rt_malloc(len + 1);
  320. rt_memset(handle.argv[1], 0x00, len + 1);
  321. rt_strncpy(handle.argv[1], argv[1], len);
  322. }
  323. /* 创建Lua2RTT解析器线程 */
  324. rt_uint8_t prio = rt_thread_self()->current_priority+1;
  325. handle.thread = rt_thread_create("lua2rtt_run", lua2rtt_run, RT_NULL,
  326. LUA2RTT_THREAD_STACK_SIZE, prio, 10);
  327. if(handle.thread == RT_NULL)
  328. {
  329. LUA2RTT_DBG("The Lua interpreter thread create failed.\n");
  330. return RT_ERROR;
  331. }
  332. rt_thread_startup(handle.thread);
  333. return RT_EOK;
  334. }
  335. MSH_CMD_EXPORT_ALIAS(lua2rtt, lua, The lua5.1.4 shell cmd.);