main.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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(shellmatta_handle_t handle) {
  146. (void)handle;
  147. return;
  148. }
  149. void ymodemCallbackReceiveHeader(shellmatta_handle_t handle, uint32_t fileSize, char* fileName) {
  150. (void)handle;
  151. printf("Received Packet Header: %u %s\n", fileSize, fileName);
  152. return;
  153. }
  154. void ymodemCallbackReceivePacket(shellmatta_handle_t handle, uint8_t *data, uint32_t packetSize, uint32_t packetNum)
  155. {
  156. uint32_t i;
  157. (void)handle;
  158. printf("Received Packet: %u %u\n", packetNum, packetSize);
  159. for(i = 0u; i < packetSize; i ++)
  160. {
  161. printf("0x%02x ", data[i]);
  162. if(15u == (i % 16))
  163. {
  164. printf("\n");
  165. }
  166. }
  167. printf("\n");
  168. return;
  169. }
  170. void ymodemCallbackTransmissionComplete(shellmatta_handle_t handle, shellmatta_retCode_t result) {
  171. (void)handle;
  172. ret = SHELLMATTA_OK;
  173. printf("\nTransmission complete: %s\n", result == SHELLMATTA_OK ? "success" : "error");
  174. return;
  175. }
  176. uint8_t ymodemBuffer[1024u] = {0};
  177. static shellmatta_retCode_t ymodem(shellmatta_handle_t handle, const char *arguments, uint32_t length)
  178. {
  179. (void)arguments;
  180. (void)length;
  181. shellmatta_printf(handle, "Starting ymodem session\r\n");
  182. shellmatta_ymodem_init(handle,
  183. ymodemBuffer,
  184. ymodemCallbackCancel,
  185. ymodemCallbackReceiveHeader,
  186. ymodemCallbackReceivePacket,
  187. ymodemCallbackTransmissionComplete);
  188. return SHELLMATTA_OK;
  189. }
  190. shellmatta_cmd_t ymodemCommand = {"ymodem", NULL, NULL, NULL, ymodem, NULL, NULL};
  191. shellmatta_retCode_t writeFct(const char* data, uint32_t length)
  192. {
  193. write(f, data, length);
  194. return SHELLMATTA_OK;
  195. }
  196. int main(int argc, char **argv)
  197. {
  198. static char buffer[1024];
  199. static char historyBuffer[4096];
  200. static shellmatta_instance_t instance;
  201. if(2 != argc)
  202. {
  203. printf("%s <serial device>\n", argv[0u]);
  204. return -1;
  205. }
  206. f = open(argv[1u], O_RDWR | O_SYNC);
  207. if (f < 0)
  208. {
  209. printf("failure opening device %s %d\n", argv[1u], errno);
  210. return f;
  211. }
  212. printf("Starting Shellmatta\n");
  213. shellmatta_doInit( &instance,
  214. &handle,
  215. buffer,
  216. sizeof(buffer),
  217. historyBuffer,
  218. sizeof(historyBuffer),
  219. "shellmatta->",
  220. NULL,
  221. writeFct);
  222. shellmatta_addCmd(handle, &doSomethingCmd);
  223. shellmatta_addCmd(handle, &doSomeCmd);
  224. shellmatta_addCmd(handle, &quitCommand);
  225. shellmatta_addCmd(handle, &removeCommand);
  226. shellmatta_addCmd(handle, &emptyCommand);
  227. shellmatta_addCmd(handle, &resetCommand);
  228. shellmatta_addCmd(handle, &continuousCommand);
  229. shellmatta_addCmd(handle, &busyCommand);
  230. shellmatta_addCmd(handle, &ymodemCommand);
  231. shellmatta_auth_user_t userList[] = {
  232. {1, false, "shimatta", "12345678"},
  233. {2, false, "not_shimatta", "87654321"}
  234. };
  235. uint32_t doSomeCmdPerms[] = {1, 2};
  236. uint32_t removeCommandPerms[] = {1};
  237. shellmatta_auth_perm_t permList[] = {
  238. {"adoSome2", doSomeCmdPerms, sizeof(doSomeCmdPerms)/sizeof(doSomeCmdPerms[0])},
  239. {"remove", removeCommandPerms, sizeof(removeCommandPerms)/sizeof(removeCommandPerms[0])}
  240. };
  241. shellmatta_auth_init(handle, userList, 2, permList, 2, false, NULL, NULL);
  242. int i = 0;
  243. while(exitRequest == false)
  244. {
  245. char c;
  246. shellmatta_retCode_t ret;
  247. int flags = fcntl(f, F_GETFL, 0);
  248. fcntl(f, F_SETFL, flags | O_NONBLOCK);
  249. int res = 0;
  250. res = read (f, &c, 1);
  251. if (res == -1)
  252. {
  253. i = (i + 1) % 10000;
  254. usleep(1);
  255. if (i != 0)
  256. {
  257. continue;
  258. }
  259. }
  260. do
  261. {
  262. res = res > 0 ? res : 0;
  263. ret = shellmatta_processData(handle, &c, res);
  264. if(SHELLMATTA_BUSY == ret)
  265. {
  266. sleep(1);
  267. }
  268. } while(SHELLMATTA_BUSY == ret);
  269. }
  270. close(f);
  271. return 0;
  272. }