changeset 774:130c46b83760

simagent: sim-up command fully implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 12 Mar 2021 21:52:09 +0000
parents 6d1b22d4926f
children 6ec781e61e68
files target-utils/simagent/cmdtab.c target-utils/simagent/simup.c
diffstat 2 files changed, 118 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/target-utils/simagent/cmdtab.c	Fri Mar 12 21:20:56 2021 +0000
+++ b/target-utils/simagent/cmdtab.c	Fri Mar 12 21:52:09 2021 +0000
@@ -16,12 +16,14 @@
 extern void abb_init();
 extern void abb_power_off();
 extern void abb_unlock_page2();
+extern void print_atr();
 
 const struct cmdtab cmdtab[] = {
 	{"abbinit", abb_init},
 	{"abbpage2", abb_unlock_page2},
 	{"abbr", cmd_abbr},
 	{"abbw", cmd_abbw},
+	{"atr", print_atr},
 	{"baud", cmd_baud_switch},
 	{"jump", cmd_jump},
 	{"poweroff", abb_power_off},
--- a/target-utils/simagent/simup.c	Fri Mar 12 21:20:56 2021 +0000
+++ b/target-utils/simagent/simup.c	Fri Mar 12 21:52:09 2021 +0000
@@ -3,14 +3,50 @@
 #include "types.h"
 #include "abbdefs.h"
 #include "simregs.h"
+#include "timeout.h"
+
+#define	MAX_ATR_BYTES	33
 
 #define	WAIT_ONE_TDMA	60000
 
 extern u16 abb_reg_read();
 extern void abb_reg_write();
 
+extern const u8 inverse_coding_table[256];
+
 int sim_if_state;
 u16 conf1_reg;
+u8 atr_buf[MAX_ATR_BYTES];
+unsigned atr_length;
+int inverse_coding;
+
+void
+print_atr()
+{
+	unsigned n;
+
+	printf("ATR:");
+	for (n = 0; n < atr_length; n++)
+		printf(" %02X", atr_buf[n]);
+	putchar('\n');
+}
+
+static
+rx_atr_byte()
+{
+	int rc;
+
+	rc = rx_sim_byte(SIM_WAIT_TIMEOUT);
+	if (rc < 0) {
+		printf("ERROR: timeout waiting for subsequent byte of ATR\n");
+		return(-1);
+	}
+	rc &= 0xFF;
+	if (inverse_coding)
+		rc = inverse_coding_table[rc];
+	atr_buf[atr_length++] = rc;
+	return rc;
+}
 
 void
 cmd_sim_up(argbulk)
@@ -18,7 +54,8 @@
 {
 	char *argv[2];
 	u16 abb_sim_reg;
-	unsigned count;
+	unsigned count, y, nhist, have_tck;
+	int rc;
 
 	if (sim_if_state) {
 		printf("ERROR: SIM interface is already up\n");
@@ -89,9 +126,84 @@
 			return;
 		}
 	}
-
-#if 0
 	/* lift the card out of reset! */
 	SIMREGS.conf1 = conf1_reg |= SIM_CONF1_SRSTLEV;
-#endif
+
+	/* first byte of ATR */
+	rc = rx_sim_byte(SIM_WAIT_TIMEOUT);
+	if (rc < 0) {
+		printf("ERROR: timeout waiting for first byte of ATR\n");
+		return;
+	}
+	rc &= 0xFF;
+	if (rc == 0x3B) {
+		/* direct convention */
+		inverse_coding = 0;
+		atr_buf[0] = 0x3B;
+	} else if (rc == 0x03) {
+		/* inverse convention */
+		inverse_coding = 1;
+		atr_buf[0] = 0x3F;
+	} else {
+		printf(
+		    "ERROR: received TS=0x%02X, matches neither convention\n",
+			rc);
+		return;
+	}
+	atr_length = 1;
+
+	/* remainder of ATR, starting with T0 */
+	rc = rx_atr_byte();
+	if (rc < 0)
+		return;
+	nhist = rc & 0xF;
+	y = rc & 0xF0;
+	have_tck = 0;
+	while (y) {
+		if (y & 0x10) {
+			if (atr_length >= MAX_ATR_BYTES) {
+atr_too_long:			printf("ERROR: ATR exceeds 33 byte limit\n");
+				return;
+			}
+			rc = rx_atr_byte();
+			if (rc < 0)
+				return;
+		}
+		if (y & 0x20) {
+			if (atr_length >= MAX_ATR_BYTES)
+				goto atr_too_long;
+			rc = rx_atr_byte();
+			if (rc < 0)
+				return;
+		}
+		if (y & 0x40) {
+			if (atr_length >= MAX_ATR_BYTES)
+				goto atr_too_long;
+			rc = rx_atr_byte();
+			if (rc < 0)
+				return;
+		}
+		if (y & 0x80) {
+			if (atr_length >= MAX_ATR_BYTES)
+				goto atr_too_long;
+			rc = rx_atr_byte();
+			if (rc < 0)
+				return;
+			y = rc & 0xF0;
+			if (rc & 0x0F)
+				have_tck = 1;
+		} else
+			y = 0;
+	}
+	for (count = 0; count < nhist + have_tck; count++) {
+		if (atr_length >= MAX_ATR_BYTES)
+			goto atr_too_long;
+		rc = rx_atr_byte();
+		if (rc < 0)
+			return;
+	}
+
+	/* all good! */
+	sim_if_state = 2;
+	print_atr();
 }