FreeCalypso > hg > fc-sim-sniff
view sw/sniff-dec/dispatch.c @ 56:966a54303d68
simsniff-dec: factor out high-level decoding
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 04 Oct 2023 01:18:50 +0000 |
parents | b0524d1dc6ef |
children |
line wrap: on
line source
/* * Dispatching received FPGA words based on the current state. */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include "state.h" extern char linebuf[]; extern int lineno; extern unsigned fpga_word; extern u_char parity_table[256]; extern u_char inverse_coding_table[256]; int state; int inverse_conv; unsigned rx_byte; #define PREFIX "%s line %d: " static void handle_rst_change() { if (fpga_word & 0x4000) { printf(PREFIX "RST high, card session begins\n", linebuf, lineno); state = STATE_ATR_TS; atr_begin(); } else { printf(PREFIX "RST low, card session ends\n", linebuf, lineno); state = STATE_RSTLOW; } } static int byte_prelim_checks() { if (!(fpga_word & 0x4000)) { printf(PREFIX "ERROR: char Rx with RST low\n", linebuf, lineno); return 1; } if (fpga_word & 0x0200) { printf(PREFIX "ERROR: start bit midpoint sampled high\n", linebuf, lineno); return 1; } if (fpga_word & 0x0400) { printf(PREFIX "ISO 7816-3 section 7.3 error signal\n", linebuf, lineno); return 1; } return 0; } static int check_parity() { unsigned expect_par; expect_par = (parity_table[fpga_word & 0xFF] ^ inverse_conv) << 8; if ((fpga_word & 0x100) != expect_par) { printf(PREFIX "ERROR: bad character parity\n", linebuf, lineno); state = STATE_ERROR; return 1; } return 0; } static void extract_rx_byte() { if (inverse_conv) rx_byte = inverse_coding_table[fpga_word & 0xFF]; else rx_byte = fpga_word & 0xFF; } void process_fpga_word() { if (fpga_word & 0x8000) { handle_rst_change(); return; } if (state == STATE_ERROR) return; if (byte_prelim_checks()) { state = STATE_ERROR; return; } switch (state) { case STATE_UNDEF: printf(PREFIX "ERROR: char Rx without preceding RST high\n", linebuf, lineno); state = STATE_ERROR; return; case STATE_RSTLOW: printf(PREFIX "ERROR: char Rx after RST low\n", linebuf, lineno); state = STATE_ERROR; return; case STATE_ATR_TS: if ((fpga_word & 0x1FF) == 0x13B) { printf(PREFIX "TS sets direct coding convention\n", linebuf, lineno); inverse_conv = 0; rx_byte = 0x3B; atr_byte_in(); state = STATE_ATR_CONT; } else if ((fpga_word & 0x1FF) == 0x103) { printf(PREFIX "TS sets inverse coding convention\n", linebuf, lineno); inverse_conv = 1; rx_byte = 0x3F; atr_byte_in(); state = STATE_ATR_CONT; } else { printf(PREFIX "ERROR: invalid char after RST high\n", linebuf, lineno); state = STATE_ERROR; } return; case STATE_ATR_CONT: if (check_parity()) return; extract_rx_byte(); atr_byte_in(); return; case STATE_READY_FOR_CMD: if (check_parity()) return; extract_rx_byte(); if (rx_byte == 0xFF) start_pps_msg(); else start_cmd_header(); return; case STATE_PPS_MSG: if (check_parity()) return; extract_rx_byte(); pps_byte_in(); return; case STATE_CMD_HDR: if (check_parity()) return; extract_rx_byte(); cmd_hdr_byte_in(); return; case STATE_CMD_PROC: if (check_parity()) return; extract_rx_byte(); cmd_proc_byte_in(); return; case STATE_CMD_DATA: if (check_parity()) return; extract_rx_byte(); cmd_data_byte_in(); return; case STATE_CMD_SW: if (check_parity()) return; extract_rx_byte(); cmd_sw2_byte_in(); return; default: fprintf(stderr, "BUG in top state machine: invalid state\n"); abort(); } }