FreeCalypso > hg > fc-sim-sniff
diff sw/sniff-dec/atr.c @ 41:118a12e9483b
simtrace3-sniff-dec started
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 31 Aug 2023 08:46:23 +0000 |
parents | |
children | 74330513121e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sw/sniff-dec/atr.c Thu Aug 31 08:46:23 2023 +0000 @@ -0,0 +1,175 @@ +/* + * Here we implement ATR decoding. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include "state.h" + +extern char linebuf[]; +extern int lineno; +extern unsigned rx_byte; +extern int state; + +#define MAX_ATR_BYTES 33 + +#define SUBST_TS 0 +#define SUBST_T0 1 +#define SUBST_TAn 2 +#define SUBST_TBn 3 +#define SUBST_TCn 4 +#define SUBST_TDn 5 +#define SUBST_HIST 6 +#define SUBST_TCK 7 + +static char atr_start_timestamp[18]; +static int atr_start_line; +static int substate; +static u_char atr_bytes[MAX_ATR_BYTES]; +static unsigned byte_count; +static u_char latch_y, latch_k, have_tck; + +void +atr_begin() +{ + strcpy(atr_start_timestamp, linebuf); + atr_start_line = lineno; + substate = SUBST_TS; + byte_count = 0; +} + +static int +advance_state() +{ + if (substate == SUBST_TAn) { + if (latch_y & 0x10) + return 0; + substate = SUBST_TBn; + } + if (substate == SUBST_TBn) { + if (latch_y & 0x20) + return 0; + substate = SUBST_TCn; + } + if (substate == SUBST_TCn) { + if (latch_y & 0x40) + return 0; + substate = SUBST_TDn; + } + if (substate == SUBST_TDn) { + if (latch_y & 0x80) + return 0; + substate = SUBST_HIST; + } + if (substate == SUBST_HIST) { + if (latch_k) + return 0; + substate = SUBST_TCK; + } + if (substate == SUBST_TCK) { + if (have_tck) + return 0; + return 1; + } + fprintf(stderr, "BUG in ATR decoder: bad state in advance_state()\n"); + abort(); +} + +static void +check_tck() +{ + unsigned n, xor; + + xor = 0; + for (n = 1; n < byte_count; n++) + xor ^= atr_bytes[n]; + printf(" TCK is %s\n", xor ? "bad!" : "correct"); +} + +static void +atr_finish() +{ + unsigned n; + + printf("%s line %d: ATR\n", atr_start_timestamp, atr_start_line); + for (n = 0; n < byte_count; n++) + printf(" %02X", atr_bytes[n]); + putchar('\n'); + if (have_tck) + check_tck(); + state = STATE_READY_FOR_CMD; +} + +void +atr_byte_in() +{ + atr_bytes[byte_count++] = rx_byte; + switch (substate) { + case SUBST_TS: + substate = SUBST_T0; + return; + case SUBST_T0: + latch_y = rx_byte & 0xF0; + latch_k = rx_byte & 0x0F; + have_tck = 0; + substate = SUBST_TAn; + if (advance_state()) { + atr_finish(); + return; + } + return; + case SUBST_TAn: + substate = SUBST_TBn; + if (advance_state()) { + atr_finish(); + return; + } + break; + case SUBST_TBn: + substate = SUBST_TCn; + if (advance_state()) { + atr_finish(); + return; + } + break; + case SUBST_TCn: + substate = SUBST_TDn; + if (advance_state()) { + atr_finish(); + return; + } + break; + case SUBST_TDn: + latch_y = rx_byte & 0xF0; + if (rx_byte & 0x0F) + have_tck = 1; + substate = SUBST_TAn; + if (advance_state()) { + atr_finish(); + return; + } + break; + case SUBST_HIST: + latch_k--; + if (advance_state()) { + atr_finish(); + return; + } + break; + case SUBST_TCK: + atr_finish(); + return; + default: + fprintf(stderr, + "BUG in ATR decoder: bad state in atr_byte_in()\n"); + abort(); + } + if (byte_count < MAX_ATR_BYTES) + return; + printf("%s line %d: ERROR: ATR is too long\n", atr_start_timestamp, + atr_start_line); + state = STATE_ERROR; +}