FreeCalypso > hg > fc-sim-sniff
diff sw/sniff-dec/dispatch.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/dispatch.c Thu Aug 31 08:46:23 2023 +0000 @@ -0,0 +1,150 @@ +/* + * 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 begin\n", + linebuf, lineno); + state = STATE_ATR_TS; + atr_begin(); + } else { + printf(PREFIX "RST low, card session end\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; + default: + fprintf(stderr, "BUG in top state machine: invalid state\n"); + abort(); + } +}