diff options
| author | J08nY | 2019-11-21 19:10:50 +0100 |
|---|---|---|
| committer | J08nY | 2019-11-21 19:10:50 +0100 |
| commit | c8d0bff46001bd5636825c5b0bb4c896cb34a4e6 (patch) | |
| tree | 2b3029c6ca37e56e86daa34069ab39da3b1a5400 /pyecsca/codegen/simpleserial/simpleserial.c | |
| download | pyecsca-codegen-c8d0bff46001bd5636825c5b0bb4c896cb34a4e6.tar.gz pyecsca-codegen-c8d0bff46001bd5636825c5b0bb4c896cb34a4e6.tar.zst pyecsca-codegen-c8d0bff46001bd5636825c5b0bb4c896cb34a4e6.zip | |
Initialize.
Diffstat (limited to 'pyecsca/codegen/simpleserial/simpleserial.c')
| -rw-r--r-- | pyecsca/codegen/simpleserial/simpleserial.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/pyecsca/codegen/simpleserial/simpleserial.c b/pyecsca/codegen/simpleserial/simpleserial.c new file mode 100644 index 0000000..8205ed4 --- /dev/null +++ b/pyecsca/codegen/simpleserial/simpleserial.c @@ -0,0 +1,150 @@ +// simpleserial.c + +#include "simpleserial.h" +#include <stdint.h> +#include "hal.h" + +typedef struct ss_cmd +{ + char c; + unsigned int len; + uint8_t (*fp)(uint8_t*, uint16_t); +} ss_cmd; + +#define MAX_SS_CMDS 26 +static ss_cmd commands[MAX_SS_CMDS]; +static int num_commands = 0; + +#define MAX_SS_LEN 256 + +#define SS_VER_1_0 0 +#define SS_VER_1_1 1 + +static char hex_lookup[16] = +{ + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +int hex_decode(int len, char* ascii_buf, uint8_t* data_buf) +{ + for(int i = 0; i < len; i++) + { + char n_hi = ascii_buf[2*i]; + char n_lo = ascii_buf[2*i+1]; + + if(n_lo >= '0' && n_lo <= '9') + data_buf[i] = n_lo - '0'; + else if(n_lo >= 'A' && n_lo <= 'F') + data_buf[i] = n_lo - 'A' + 10; + else if(n_lo >= 'a' && n_lo <= 'f') + data_buf[i] = n_lo - 'a' + 10; + else + return 1; + + if(n_hi >= '0' && n_hi <= '9') + data_buf[i] |= (n_hi - '0') << 4; + else if(n_hi >= 'A' && n_hi <= 'F') + data_buf[i] |= (n_hi - 'A' + 10) << 4; + else if(n_hi >= 'a' && n_hi <= 'f') + data_buf[i] |= (n_hi - 'a' + 10) << 4; + else + return 1; + } + + return 0; +} + +// Callback function for "v" command. +// This can exist in v1.0 as long as we don't actually send back an ack ("z") +uint8_t check_version(uint8_t* v, uint16_t len) +{ + return 0x00; +} + +// Set up the SimpleSerial module by preparing internal commands +// This just adds the "v" command for now... +void simpleserial_init() +{ + simpleserial_addcmd('v', 0, check_version); +} + +int simpleserial_addcmd(char c, unsigned int len, uint8_t (*fp)(uint8_t*, uint16_t)) +{ + if(num_commands >= MAX_SS_CMDS) + return 1; + + if(len > MAX_SS_LEN) + return 1; + + commands[num_commands].c = c; + commands[num_commands].len = len; + commands[num_commands].fp = fp; + num_commands++; + + return 0; +} + +void simpleserial_get(void) +{ + char ascii_buf[2*MAX_SS_LEN]; + uint8_t data_buf[MAX_SS_LEN]; + char c; + + // Find which command we're receiving + c = getch(); + + int cmd; + for(cmd = 0; cmd < num_commands; cmd++) + { + if(commands[cmd].c == c) + break; + } + + // If we didn't find a match, give up right away + if(cmd == num_commands) + return; + + // Receive characters until we fill the ASCII buffer + int i = 0; + for(; i < 2*commands[cmd].len; i++) + { + c = getch(); + + // Check for early \n + if(c == '\n' || c == '\r') + break; + + ascii_buf[i] = c; + } + + // ASCII buffer is full: convert to bytes + // Check for illegal characters here + if(hex_decode(i, ascii_buf, data_buf)) + return; + + // Callback + uint8_t ret[1]; + ret[0] = commands[cmd].fp(data_buf, i); + + // Acknowledge (if version is 1.1) +#if SS_VER == SS_VER_1_1 + simpleserial_put('z', 1, ret); +#endif +} + +void simpleserial_put(char c, int size, uint8_t* output) +{ + // Write first character + putch(c); + + // Write each byte as two nibbles + for(int i = 0; i < size; i++) + { + putch(hex_lookup[output[i] >> 4 ]); + putch(hex_lookup[output[i] & 0xF]); + } + + // Write trailing '\n' + putch('\n'); +} |
