FreeCalypso > hg > fc-sim-sniff
view sw/sniff-dec/atr.c @ 57:eb4274e7f4da
simsniff-dec: decode SELECT file IDs
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 04 Oct 2023 03:54:00 +0000 |
parents | 74330513121e |
children |
line wrap: on
line source
/* * 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() { 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: strcpy(atr_start_timestamp, linebuf); atr_start_line = lineno; 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; }