main.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*
  2. * Copyright (c) 2019 - 2024 Stefan Strobel <stefan.strobel@shimatta.net>
  3. *
  4. * This Source Code Form is subject to the terms of the Mozilla Public
  5. * License, v. 2.0. If a copy of the MPL was not distributed with this
  6. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
  7. */
  8. /**
  9. * @file main.c
  10. * @brief main module to demonstrate use of the shellmatta.
  11. * @author Stefan Strobel <stefan.strobel@shimatta.net>
  12. */
  13. #include "shellmatta.h"
  14. #include <stdint.h>
  15. #include <stdio.h>
  16. #include <stdbool.h>
  17. #include <fcntl.h>
  18. #include <unistd.h>
  19. #include <string.h>
  20. #include <errno.h>
  21. static bool exitRequest = false;
  22. int f;
  23. shellmatta_handle_t handle;
  24. static shellmatta_retCode_t doSomething(shellmatta_handle_t handle, const char *arguments, uint32_t length)
  25. {
  26. shellmatta_printf(handle, "%s - length: %u", arguments, length);
  27. return SHELLMATTA_OK;
  28. }
  29. shellmatta_cmd_t doSomethingCmd = {"doSomething", "do", "Function does something", "use me, please", doSomething, NULL, NULL};
  30. static shellmatta_retCode_t doSome(shellmatta_handle_t handle, const char *arguments, uint32_t length)
  31. {
  32. shellmatta_write(handle, "blubb\r\n", 7u);
  33. shellmatta_configure(handle, SHELLMATTA_MODE_INSERT, false, '\r');
  34. (void)arguments;
  35. (void)length;
  36. return SHELLMATTA_OK;
  37. }
  38. shellmatta_cmd_t doSomeCmd = {"adoSome2", "adof2", "Function does something", "use me, please", doSome, NULL, NULL};
  39. static shellmatta_retCode_t removeCmdFct(shellmatta_handle_t handle, const char *arguments, uint32_t length)
  40. {
  41. shellmatta_printf(handle, "removing command: %s\r\n", doSomeCmd.cmd);
  42. shellmatta_removeCmd(handle, &doSomeCmd);
  43. (void)arguments;
  44. (void)length;
  45. return SHELLMATTA_OK;
  46. }
  47. shellmatta_cmd_t removeCommand = {"remove", "r", "Function removes a command", "", removeCmdFct, NULL, NULL};
  48. static shellmatta_retCode_t quit(shellmatta_handle_t handle, const char *arguments, uint32_t length)
  49. {
  50. exitRequest = true;
  51. (void)handle;
  52. (void)arguments;
  53. (void)length;
  54. return SHELLMATTA_OK;
  55. }
  56. shellmatta_cmd_t quitCommand = {"quit", "q", "Function quits the shell", "", quit, NULL, NULL};
  57. static shellmatta_retCode_t empty(shellmatta_handle_t handle, const char *arguments, uint32_t length)
  58. {
  59. (void)arguments;
  60. (void)length;
  61. shellmatta_printf(handle, "empty function called\r\n");
  62. shellmatta_configure(handle, SHELLMATTA_MODE_OVERWRITE, true, '\r');
  63. return SHELLMATTA_OK;
  64. }
  65. shellmatta_cmd_t emptyCommand = {"empty", NULL, NULL, NULL, empty, NULL, NULL};
  66. static shellmatta_retCode_t reset(shellmatta_handle_t handle, const char *arguments, uint32_t length)
  67. {
  68. shellmatta_retCode_t ret;
  69. (void)arguments;
  70. (void)length;
  71. char option;
  72. char *argument;
  73. uint32_t argLen;
  74. bool printPrompt = false;
  75. static const shellmatta_opt_long_t options[] =
  76. {
  77. {"prompt", 'p', SHELLMATTA_OPT_ARG_REQUIRED},
  78. {NULL, '\0', SHELLMATTA_OPT_ARG_NONE}
  79. };
  80. ret = shellmatta_opt_long(handle, options, &option, &argument, &argLen);
  81. while(SHELLMATTA_OK == ret)
  82. {
  83. switch(option)
  84. {
  85. case 'p':
  86. if(NULL != argument)
  87. {
  88. if(0 == strncmp("true", argument, 4u))
  89. {
  90. printPrompt = true;
  91. }
  92. }
  93. break;
  94. default:
  95. shellmatta_printf(handle, "Unknown option: %c\r\n", option);
  96. break;
  97. }
  98. ret = shellmatta_opt_long(handle, options, &option, &argument, &argLen);
  99. }
  100. shellmatta_resetShell(handle, printPrompt);
  101. shellmatta_configure(handle, SHELLMATTA_MODE_INSERT, true, '\r');
  102. return SHELLMATTA_OK;
  103. }
  104. shellmatta_cmd_t resetCommand = {"reset", NULL, "resets the shellmatta instance", "reset [--prompt true/false]", reset, NULL, NULL};
  105. static shellmatta_retCode_t continuous(shellmatta_handle_t handle, const char *arguments, uint32_t length)
  106. {
  107. (void)arguments;
  108. (void)length;
  109. shellmatta_retCode_t ret = SHELLMATTA_CONTINUE;
  110. uint32_t stdinLength;
  111. char *stdinData;
  112. shellmatta_read(handle, &stdinData, &stdinLength);
  113. if(NULL != stdinData)
  114. {
  115. if('x' == stdinData[0u])
  116. {
  117. ret = SHELLMATTA_OK;
  118. }
  119. stdinData[0u] ++;
  120. shellmatta_write(handle, stdinData, stdinLength);
  121. }
  122. return ret;
  123. }
  124. shellmatta_cmd_t continuousCommand = {"continuous", "cont", "prints continously all input bytes", "continuous", continuous, NULL, NULL};
  125. static shellmatta_retCode_t busy(shellmatta_handle_t handle, const char *arguments, uint32_t length)
  126. {
  127. (void)arguments;
  128. (void)length;
  129. static uint32_t callCnt = 0u;
  130. shellmatta_retCode_t ret = SHELLMATTA_BUSY;
  131. if(callCnt < 10u)
  132. {
  133. callCnt ++;
  134. shellmatta_printf(handle, "%s - length %u - callCnt %u\r\n", arguments, length, callCnt);
  135. }
  136. else
  137. {
  138. callCnt = 0u;
  139. ret = SHELLMATTA_OK;
  140. }
  141. return ret;
  142. }
  143. shellmatta_cmd_t busyCommand = {"busy", NULL, NULL, NULL, busy, NULL, NULL};
  144. shellmatta_retCode_t ret = SHELLMATTA_OK;
  145. void ymodemCallbackCancel() {
  146. return;
  147. }
  148. void ymodemCallbackReceiveHeader(uint32_t fileSize, char* fileName) {
  149. printf("Received Packet Header: %u %s\n", fileSize, fileName);
  150. return;
  151. }
  152. void ymodemCallbackReceivePacket(uint8_t *data, uint32_t packetSize, uint32_t packetNum)
  153. {
  154. uint32_t i;
  155. printf("Received Packet: %u %u\n", packetNum, packetSize);
  156. for(i = 0u; i < packetSize; i ++)
  157. {
  158. printf("0x%02x ", data[i]);
  159. if(15u == (i % 16))
  160. {
  161. printf("\n");
  162. }
  163. }
  164. printf("\n");
  165. return;
  166. }
  167. void ymodemCallbackTransmissionComplete(shellmatta_retCode_t result) {
  168. ret = SHELLMATTA_OK;
  169. printf("\nTransmission complete: %s\n", result == SHELLMATTA_OK ? "success" : "error");
  170. return;
  171. }
  172. uint8_t ymodemBuffer[1024u] = {0};
  173. static shellmatta_retCode_t ymodem(shellmatta_handle_t handle, const char *arguments, uint32_t length)
  174. {
  175. (void)arguments;
  176. (void)length;
  177. shellmatta_printf(handle, "Starting ymodem session\r\n");
  178. shellmatta_ymodem_init(handle,
  179. ymodemBuffer,
  180. ymodemCallbackCancel,
  181. ymodemCallbackReceiveHeader,
  182. ymodemCallbackReceivePacket,
  183. ymodemCallbackTransmissionComplete);
  184. return SHELLMATTA_OK;
  185. }
  186. shellmatta_cmd_t ymodemCommand = {"ymodem", NULL, NULL, NULL, ymodem, NULL, NULL};
  187. shellmatta_retCode_t writeFct(const char* data, uint32_t length)
  188. {
  189. write(f, data, length);
  190. return SHELLMATTA_OK;
  191. }
  192. int main(int argc, char **argv)
  193. {
  194. static char buffer[1024];
  195. static char historyBuffer[4096];
  196. static shellmatta_instance_t instance;
  197. if(2 != argc)
  198. {
  199. printf("%s <serial device>\n", argv[0u]);
  200. return -1;
  201. }
  202. f = open(argv[1u], O_RDWR | O_SYNC);
  203. if (f < 0)
  204. {
  205. printf("failure opening device %s %d\n", argv[1u], errno);
  206. return f;
  207. }
  208. printf("Starting Shellmatta\n");
  209. shellmatta_doInit( &instance,
  210. &handle,
  211. buffer,
  212. sizeof(buffer),
  213. historyBuffer,
  214. sizeof(historyBuffer),
  215. "shellmatta->",
  216. NULL,
  217. writeFct);
  218. shellmatta_addCmd(handle, &doSomethingCmd);
  219. shellmatta_addCmd(handle, &doSomeCmd);
  220. shellmatta_addCmd(handle, &quitCommand);
  221. shellmatta_addCmd(handle, &removeCommand);
  222. shellmatta_addCmd(handle, &emptyCommand);
  223. shellmatta_addCmd(handle, &resetCommand);
  224. shellmatta_addCmd(handle, &continuousCommand);
  225. shellmatta_addCmd(handle, &busyCommand);
  226. shellmatta_addCmd(handle, &ymodemCommand);
  227. shellmatta_auth_user_t userList[] = {
  228. {1, false, "shimatta", "12345678"},
  229. {2, false, "not_shimatta", "87654321"}
  230. };
  231. uint32_t doSomeCmdPerms[] = {1, 2};
  232. uint32_t removeCommandPerms[] = {1};
  233. shellmatta_auth_perm_t permList[] = {
  234. {"adoSome2", doSomeCmdPerms, sizeof(doSomeCmdPerms)/sizeof(doSomeCmdPerms[0])},
  235. {"remove", removeCommandPerms, sizeof(removeCommandPerms)/sizeof(removeCommandPerms[0])}
  236. };
  237. shellmatta_auth_init(handle, userList, 2, permList, 2, false, NULL, NULL);
  238. int i = 0;
  239. while(exitRequest == false)
  240. {
  241. char c;
  242. shellmatta_retCode_t ret;
  243. int flags = fcntl(f, F_GETFL, 0);
  244. fcntl(f, F_SETFL, flags | O_NONBLOCK);
  245. int res = 0;
  246. res = read (f, &c, 1);
  247. if (res == -1)
  248. {
  249. i = (i + 1) % 10000;
  250. usleep(1);
  251. if (i != 0)
  252. {
  253. continue;
  254. }
  255. }
  256. do
  257. {
  258. res = res > 0 ? res : 0;
  259. ret = shellmatta_processData(handle, &c, res);
  260. if(SHELLMATTA_BUSY == ret)
  261. {
  262. sleep(1);
  263. }
  264. } while(SHELLMATTA_BUSY == ret);
  265. }
  266. close(f);
  267. return 0;
  268. }