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();
+	}
+}