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