| @@ -2,11 +2,27 @@ | |||
| #include <strobe_rng_init.h> | |||
| #include <string.h> | |||
| #include <board.h> | |||
| #include <misc.h> | |||
| #include <radio.h> | |||
| #include <delay.h> | |||
| char * | |||
| findeol(char *pos, size_t len) | |||
| { | |||
| while (len) { | |||
| if (*pos == '\r' || *pos == '\n') | |||
| return pos; | |||
| pos++; | |||
| len--; | |||
| } | |||
| return NULL; | |||
| } | |||
| void | |||
| hexdump(uint8_t *ptr, size_t len) | |||
| { | |||
| @@ -60,6 +76,86 @@ RadioEvents_t revents = { | |||
| .RxError = rxerr, | |||
| }; | |||
| static uint8_t | |||
| hexchartonib(char s) | |||
| { | |||
| switch (s) { | |||
| case '0'...'9': | |||
| return s - '0'; | |||
| case 'a'...'f': | |||
| return s - 'a' + 10; | |||
| case 'A'...'F': | |||
| return s - 'A' + 10; | |||
| default: | |||
| return -1; | |||
| } | |||
| } | |||
| static bool | |||
| hexdecode(char *buf, size_t len, uint8_t *out) | |||
| { | |||
| uint8_t topchr, botchr; | |||
| if (len % 2) | |||
| return -1; | |||
| /* NB: only needed to silence a bad gcc warning */ | |||
| topchr = -1; | |||
| while (len) { | |||
| if (len % 2) { | |||
| /* bottom nibble */ | |||
| botchr = hexchartonib(*buf); | |||
| if (topchr == -1 || botchr == -1) | |||
| return false; | |||
| *out = topchr << 4 | botchr; | |||
| out++; | |||
| } else { | |||
| /* top nibble */ | |||
| topchr = hexchartonib(*buf); | |||
| } | |||
| len--; | |||
| buf++; | |||
| } | |||
| return true; | |||
| } | |||
| static const char pktstart[] = "pkt:"; | |||
| static const size_t pktstartlen = sizeof pktstart - 1; | |||
| static uint8_t pktbuf[128]; | |||
| static void | |||
| process_line(char *start, char *end) | |||
| { | |||
| size_t len; | |||
| /* trim off leading CR/NL */ | |||
| while (start < end && (*start == '\r' || *start == '\n')) | |||
| start++; | |||
| len = end - start; | |||
| if (len >= pktstartlen && memcmp(start, pktstart, sizeof pktstart - 1) == 0) { | |||
| start += pktstartlen; | |||
| len -= pktstartlen; | |||
| if (len % 2) { | |||
| usb_printf("invalid pkt len\r\n"); | |||
| return; | |||
| } | |||
| if (!hexdecode(start, len, pktbuf)) { | |||
| usb_printf("invalid pkt\r\n"); | |||
| return; | |||
| } | |||
| Radio.Send(pktbuf, len / 2); | |||
| return; | |||
| } | |||
| usb_printf("line: %.*s", end - start, start); | |||
| } | |||
| int | |||
| main(void) | |||
| { | |||
| @@ -148,10 +244,70 @@ main(void) | |||
| usb_printf("rx(0)...\r\n"); | |||
| Radio.Rx(0); | |||
| char inpbuf[1024]; | |||
| char *lastcheck; | |||
| char *endchr; | |||
| int inpbufpos = 0; | |||
| int cpylen; | |||
| loop: | |||
| BoardLowPowerHandler(); | |||
| if (Radio.IrqProcess != NULL) | |||
| Radio.IrqProcess(); | |||
| /* while we have data */ | |||
| while (CDC_RX_LEN) { | |||
| /* store last position */ | |||
| lastcheck = &inpbuf[inpbufpos]; | |||
| /* calculate how much space left */ | |||
| cpylen = MIN(sizeof inpbuf - inpbufpos, CDC_RX_LEN); | |||
| /* copy into buffer */ | |||
| memcpy(&inpbuf[inpbufpos], CDC_RX_BUFFER, cpylen); | |||
| /* and point to end of buffer */ | |||
| inpbufpos += cpylen; | |||
| do { | |||
| /* find first end of line characters */ | |||
| endchr = findeol(lastcheck, cpylen); | |||
| if (endchr != NULL) { | |||
| /* if so, process it */ | |||
| process_line(inpbuf, endchr); | |||
| /* skip end of line char */ | |||
| endchr++; | |||
| /* move remaining buffer to the beginning */ | |||
| memmove(inpbuf, endchr, inpbufpos - (endchr - inpbuf)); | |||
| /* and store new length */ | |||
| inpbufpos = inpbufpos - (endchr - inpbuf); | |||
| /* mark begining of stream as last checked */ | |||
| lastcheck = inpbuf; | |||
| /* and try to process another line */ | |||
| continue; | |||
| } else if (inpbufpos == sizeof inpbuf) { | |||
| /* we overflowed the buffer */ | |||
| /* XXX - best way is to throw away this line */ | |||
| inpbufpos = 0; | |||
| } | |||
| } while (0); | |||
| /* if we copied all the data */ | |||
| if (cpylen == CDC_RX_LEN) { | |||
| /* declare that we are ready to receive more data */ | |||
| CDC_RX_LEN = 0; | |||
| USBD_CDC_ReceivePacket(&hUsbDeviceFS); | |||
| } else { | |||
| /* if not, move the remaining to the begining and try again */ | |||
| memmove(CDC_RX_BUFFER, &CDC_RX_BUFFER[cpylen], CDC_RX_LEN - cpylen); | |||
| CDC_RX_LEN -= cpylen; | |||
| } | |||
| } | |||
| goto loop; | |||
| } | |||