simpleserial.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. // simpleserial.c
  2. #include "simpleserial.h"
  3. #include <stdint.h>
  4. #include "hal.h"
  5. #define MAX_SS_CMDS 16
  6. static int num_commands = 0;
  7. #define MAX_SS_LEN 192
  8. //#define SS_VER_1_0 0
  9. //#define SS_VER_1_1 1
  10. //#define SS_VER_2_0 2
  11. // 0xA6 formerly
  12. #define CW_CRC 0x4D
  13. uint8_t ss_crc(uint8_t *buf, uint8_t len)
  14. {
  15. unsigned int k = 0;
  16. uint8_t crc = 0x00;
  17. while (len--) {
  18. crc ^= *buf++;
  19. for (k = 0; k < 8; k++) {
  20. crc = crc & 0x80 ? (crc << 1) ^ CW_CRC: crc << 1;
  21. }
  22. }
  23. return crc;
  24. }
  25. // [B_STUFF, CMD, SCMD, LEN, B_STUFF, DATA..., CRC, TERM]
  26. //#define SS_VER SS_VER_2_0
  27. #if SS_VER == SS_VER_2_0
  28. #error "SS_VER_2_0 is deprecated! Use SS_VER_2_1 instead."
  29. #elif SS_VER == SS_VER_2_1
  30. typedef struct ss_cmd
  31. {
  32. char c;
  33. unsigned int len;
  34. uint8_t (*fp)(uint8_t, uint8_t, uint8_t, uint8_t *);
  35. } ss_cmd;
  36. static ss_cmd commands[MAX_SS_CMDS];
  37. void ss_puts(char *x)
  38. {
  39. do {
  40. putch(*x);
  41. } while (*++x);
  42. }
  43. #define FRAME_BYTE 0x00
  44. uint8_t check_version(uint8_t cmd, uint8_t scmd, uint8_t len, uint8_t *data)
  45. {
  46. uint8_t ver = SS_VER;
  47. simpleserial_put('r', 1, &ver);
  48. return SS_ERR_OK;
  49. }
  50. uint8_t ss_get_commands(uint8_t cmd, uint8_t scmd, uint8_t len, uint8_t *data)
  51. {
  52. uint8_t cmd_chars[MAX_SS_CMDS];
  53. for (uint8_t i = 0; i < (num_commands & 0xFF); i++) {
  54. cmd_chars[i] = commands[i].c;
  55. }
  56. simpleserial_put('r', num_commands & 0xFF, (void *)cmd_chars);
  57. return 0x00;
  58. }
  59. uint8_t stuff_data(uint8_t *buf, uint8_t len)
  60. {
  61. uint8_t i = 1;
  62. uint8_t last = 0;
  63. for (; i < len; i++) {
  64. if (buf[i] == FRAME_BYTE) {
  65. buf[last] = i - last;
  66. last = i;
  67. }
  68. }
  69. return 0x00;
  70. }
  71. uint8_t unstuff_data(uint8_t *buf, uint8_t len)
  72. {
  73. uint8_t next = buf[0];
  74. buf[0] = 0x00;
  75. //len -= 1;
  76. uint8_t tmp = next;
  77. while ((next < len) && tmp != 0) {
  78. tmp = buf[next];
  79. buf[next] = FRAME_BYTE;
  80. next += tmp;
  81. }
  82. return next;
  83. }
  84. // Set up the SimpleSerial module by preparing internal commands
  85. // This just adds the "v" command for now...
  86. void simpleserial_init()
  87. {
  88. simpleserial_addcmd('v', 0, check_version);
  89. simpleserial_addcmd('w', 0, ss_get_commands);
  90. }
  91. int simpleserial_addcmd(char c, unsigned int len, uint8_t (*fp)(uint8_t, uint8_t, uint8_t, uint8_t*))
  92. {
  93. if(num_commands >= MAX_SS_CMDS) {
  94. putch('a');
  95. return 1;
  96. }
  97. if(len >= MAX_SS_LEN) {
  98. putch('b');
  99. return 1;
  100. }
  101. commands[num_commands].c = c;
  102. commands[num_commands].len = len;
  103. commands[num_commands].fp = fp;
  104. num_commands++;
  105. return 0;
  106. }
  107. void simpleserial_get(void)
  108. {
  109. uint8_t data_buf[MAX_SS_LEN];
  110. uint8_t err = 0;
  111. for (int i = 0; i < 4; i++) {
  112. data_buf[i] = getch(); //PTR, cmd, scmd, len
  113. if (data_buf[i] == FRAME_BYTE) {
  114. err = SS_ERR_FRAME_BYTE;
  115. goto ERROR;
  116. }
  117. }
  118. uint8_t next_frame = unstuff_data(data_buf, 4);
  119. // check for valid command
  120. uint8_t c = 0;
  121. for(c = 0; c < num_commands; c++)
  122. {
  123. if(commands[c].c == data_buf[1])
  124. break;
  125. }
  126. if (c == num_commands) {
  127. err = SS_ERR_CMD;
  128. goto ERROR;
  129. }
  130. //check that next frame not beyond end of message
  131. // account for cmd, scmd, len, data, crc, end of frame
  132. if ((data_buf[3] + 5) < next_frame) {
  133. err = SS_ERR_LEN;
  134. goto ERROR;
  135. }
  136. // read in data
  137. // eq to len + crc + frame end
  138. int i = 4;
  139. for (; i < data_buf[3] + 5; i++) {
  140. data_buf[i] = getch();
  141. if (data_buf[i] == FRAME_BYTE) {
  142. err = SS_ERR_FRAME_BYTE;
  143. goto ERROR;
  144. }
  145. }
  146. //check that final byte is the FRAME_BYTE
  147. data_buf[i] = getch();
  148. if (data_buf[i] != FRAME_BYTE) {
  149. err = SS_ERR_LEN;
  150. goto ERROR;
  151. }
  152. //fully unstuff data now
  153. unstuff_data(data_buf + next_frame, i - next_frame + 1);
  154. //calc crc excluding original frame offset and frame end and crc
  155. uint8_t crc = ss_crc(data_buf+1, i-2);
  156. if (crc != data_buf[i-1]) {
  157. err = SS_ERR_CRC;
  158. goto ERROR;
  159. }
  160. err = commands[c].fp(data_buf[1], data_buf[2], data_buf[3], data_buf+4);
  161. ERROR:
  162. simpleserial_put('e', 0x01, &err);
  163. return;
  164. }
  165. void simpleserial_put(char c, uint8_t size, uint8_t* output)
  166. {
  167. uint8_t data_buf[MAX_SS_LEN];
  168. data_buf[0] = 0x00;
  169. data_buf[1] = c;
  170. data_buf[2] = size;
  171. int i = 0;
  172. for (; i < size; i++) {
  173. data_buf[i + 3] = output[i];
  174. }
  175. data_buf[i + 3] = ss_crc(data_buf+1, size+2);
  176. data_buf[i + 4] = 0x00;
  177. stuff_data(data_buf, i + 5);
  178. for (int i = 0; i < size + 5; i++) {
  179. putch(data_buf[i]);
  180. }
  181. }
  182. #else
  183. typedef struct ss_cmd
  184. {
  185. char c;
  186. unsigned int len;
  187. uint8_t (*fp)(uint8_t*, uint8_t);
  188. uint8_t flags;
  189. } ss_cmd;
  190. static ss_cmd commands[MAX_SS_CMDS];
  191. // Callback function for "v" command.
  192. // This can exist in v1.0 as long as we don't actually send back an ack ("z")
  193. uint8_t check_version(uint8_t *v, uint8_t len)
  194. {
  195. return SS_VER;
  196. }
  197. uint8_t ss_num_commands(uint8_t *x, uint8_t len)
  198. {
  199. uint8_t ncmds = num_commands & 0xFF;
  200. simpleserial_put('r', 0x01, &ncmds);
  201. return 0x00;
  202. }
  203. typedef struct ss_cmd_repr {
  204. uint8_t c;
  205. uint8_t len;
  206. uint8_t flags;
  207. } ss_cmd_repr;
  208. uint8_t ss_get_commands(uint8_t *x, uint8_t len)
  209. {
  210. ss_cmd_repr repr_cmd_buf[MAX_SS_CMDS];
  211. for (uint8_t i = 0; i < (num_commands & 0xFF); i++) {
  212. repr_cmd_buf[i].c = commands[i].c;
  213. repr_cmd_buf[i].len = commands[i].len;
  214. repr_cmd_buf[i].flags = commands[i].flags;
  215. }
  216. simpleserial_put('r', num_commands * 0x03, (void *) repr_cmd_buf);
  217. return 0x00;
  218. }
  219. static char hex_lookup[16] =
  220. {
  221. '0', '1', '2', '3', '4', '5', '6', '7',
  222. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
  223. };
  224. int hex_decode(int len, char* ascii_buf, uint8_t* data_buf)
  225. {
  226. for(int i = 0; i < len; i++)
  227. {
  228. char n_hi = ascii_buf[2*i];
  229. char n_lo = ascii_buf[2*i+1];
  230. if(n_lo >= '0' && n_lo <= '9')
  231. data_buf[i] = n_lo - '0';
  232. else if(n_lo >= 'A' && n_lo <= 'F')
  233. data_buf[i] = n_lo - 'A' + 10;
  234. else if(n_lo >= 'a' && n_lo <= 'f')
  235. data_buf[i] = n_lo - 'a' + 10;
  236. else
  237. return 1;
  238. if(n_hi >= '0' && n_hi <= '9')
  239. data_buf[i] |= (n_hi - '0') << 4;
  240. else if(n_hi >= 'A' && n_hi <= 'F')
  241. data_buf[i] |= (n_hi - 'A' + 10) << 4;
  242. else if(n_hi >= 'a' && n_hi <= 'f')
  243. data_buf[i] |= (n_hi - 'a' + 10) << 4;
  244. else
  245. return 1;
  246. }
  247. return 0;
  248. }
  249. // Set up the SimpleSerial module by preparing internal commands
  250. // This just adds the "v" command for now...
  251. void simpleserial_init()
  252. {
  253. simpleserial_addcmd('v', 0, check_version);
  254. simpleserial_addcmd('w', 0, ss_get_commands);
  255. simpleserial_addcmd('y', 0, ss_num_commands);
  256. }
  257. int simpleserial_addcmd(char c, unsigned int len, uint8_t (*fp)(uint8_t*, uint8_t))
  258. {
  259. return simpleserial_addcmd_flags(c, len, fp, CMD_FLAG_NONE);
  260. }
  261. int simpleserial_addcmd_flags(char c, unsigned int len, uint8_t (*fp)(uint8_t*, uint8_t), uint8_t fl)
  262. {
  263. if(num_commands >= MAX_SS_CMDS)
  264. return 1;
  265. if(len >= MAX_SS_LEN)
  266. return 1;
  267. commands[num_commands].c = c;
  268. commands[num_commands].len = len;
  269. commands[num_commands].fp = fp;
  270. commands[num_commands].flags = fl;
  271. num_commands++;
  272. return 0;
  273. }
  274. void simpleserial_get(void)
  275. {
  276. char ascii_buf[2*MAX_SS_LEN];
  277. uint8_t data_buf[MAX_SS_LEN];
  278. char c;
  279. // Find which command we're receiving
  280. c = getch();
  281. int cmd;
  282. for(cmd = 0; cmd < num_commands; cmd++)
  283. {
  284. if(commands[cmd].c == c)
  285. break;
  286. }
  287. // If we didn't find a match, give up right away
  288. if(cmd == num_commands)
  289. return;
  290. // If flag CMD_FLAG_LEN is set, the next byte indicates the sent length
  291. if ((commands[cmd].flags & CMD_FLAG_LEN) != 0)
  292. {
  293. uint8_t l = 0;
  294. char buff[2];
  295. buff[0] = getch();
  296. buff[1] = getch();
  297. if (hex_decode(1, buff, &l))
  298. return;
  299. commands[cmd].len = l;
  300. }
  301. // Receive characters until we fill the ASCII buffer
  302. for(int i = 0; i < 2*commands[cmd].len; i++)
  303. {
  304. c = getch();
  305. // Check for early \n
  306. if(c == '\n' || c == '\r')
  307. return;
  308. ascii_buf[i] = c;
  309. }
  310. // Assert that last character is \n or \r
  311. c = getch();
  312. if(c != '\n' && c != '\r')
  313. return;
  314. // ASCII buffer is full: convert to bytes
  315. // Check for illegal characters here
  316. if(hex_decode(commands[cmd].len, ascii_buf, data_buf))
  317. return;
  318. // Callback
  319. uint8_t ret[1];
  320. ret[0] = commands[cmd].fp(data_buf, commands[cmd].len);
  321. // Acknowledge (if version is 1.1)
  322. #if SS_VER == SS_VER_1_1
  323. simpleserial_put('z', 1, ret);
  324. #endif
  325. }
  326. void simpleserial_put(char c, uint8_t size, uint8_t* output)
  327. {
  328. // Write first character
  329. putch(c);
  330. // Write each byte as two nibbles
  331. for(int i = 0; i < size; i++)
  332. {
  333. putch(hex_lookup[output[i] >> 4 ]);
  334. putch(hex_lookup[output[i] & 0xF]);
  335. }
  336. // Write trailing '\n'
  337. putch('\n');
  338. }
  339. #endif