main.c 9.1 KB

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