Change in osmo-ccid-firmware[master]: setparameters/PPS works

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Hoernchen gerrit-no-reply at lists.osmocom.org
Tue Nov 26 18:39:11 UTC 2019


Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/16237 )


Change subject: setparameters/PPS works
......................................................................

setparameters/PPS works

Change-Id: I2e226b0033f8a147fad60a33a63cc45ee9adc756
---
M ccid_common/ccid_device.c
M ccid_common/ccid_device.h
M ccid_common/ccid_slot_fsm.c
M ccid_common/cuart.h
R ccid_common/iso7816_3.c
R ccid_common/iso7816_3.h
M ccid_common/iso7816_fsm.c
M ccid_common/iso7816_fsm.h
M sysmoOCTSIM/cuart_driver_asf4_usart_async.c
M sysmoOCTSIM/gcc/Makefile
M sysmoOCTSIM/ncn8025.c
M sysmoOCTSIM/ncn8025.h
12 files changed, 370 insertions(+), 29 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/37/16237/1

diff --git a/ccid_common/ccid_device.c b/ccid_common/ccid_device.c
index 8183b16..ba36988 100644
--- a/ccid_common/ccid_device.c
+++ b/ccid_common/ccid_device.c
@@ -24,8 +24,10 @@
 static int decode_ccid_pars_t0(struct ccid_pars_decoded *out, const struct ccid_proto_data_t0 *in)
 {
 	/* input validation: only 0x00 and 0x02 permitted for bmTCCKST0 */
-	if (in->bmTCCKST0 & 0xFD)
-		return -11;
+//	if (in->bmTCCKST0 & 0xFD)
+//		return -11;
+// 6.1.7 says: "Note: the CCID ignores this bit", placeholder for GETparameters
+
 	/* input validation: only 0x00 to 0x03 permitted for bClockSTop */
 	if (in->bClockStop & 0xFC)
 		return -14;
@@ -254,7 +256,7 @@
 	}
 	return msg;
 }
-static struct msgb *ccid_gen_parameters_t0(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
+struct msgb *ccid_gen_parameters_t0(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
 					   enum ccid_error_code err)
 {
 	return ccid_gen_parameters_t0_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, &cs->pars);
@@ -276,7 +278,7 @@
 	}
 	return msg;
 }
-static struct msgb *ccid_gen_parameters_t1(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
+struct msgb *ccid_gen_parameters_t1(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
 					   enum ccid_error_code err)
 {
 	return ccid_gen_parameters_t1_nr(cs->slot_nr, get_icc_status(cs), seq, cmd_sts, err, &cs->pars);
@@ -465,7 +467,7 @@
 
 	/* copy default parameters from somewhere */
 	/* FIXME: T=1 */
-	cs->ci->slot_ops->set_params(cs, CCID_PROTOCOL_NUM_T0, cs->default_pars);
+	cs->ci->slot_ops->set_params(cs, seq, CCID_PROTOCOL_NUM_T0, cs->default_pars);
 	cs->pars = *cs->default_pars;
 
 	resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_OK, 0);
@@ -502,14 +504,16 @@
 		goto out;
 	}
 
+	cs->proposed_pars = pars_dec;
+
 	/* validate parameters; abort if they are not supported */
-	rc = cs->ci->slot_ops->set_params(cs, spar->bProtocolNum, &pars_dec);
+	rc = cs->ci->slot_ops->set_params(cs, seq, spar->bProtocolNum, &pars_dec);
 	if (rc < 0) {
 		resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_FAILED, -rc);
-	} else {
-		cs->pars = pars_dec;
-		resp = ccid_gen_parameters_t0(cs, seq, CCID_CMD_STATUS_OK, 0);
+		goto out;
 	}
+	/* busy, tdpu like callback */
+	return 1;
 out:
 	return ccid_slot_send_unbusy(cs, resp);
 }
diff --git a/ccid_common/ccid_device.h b/ccid_common/ccid_device.h
index ae3ab5b..8390783 100644
--- a/ccid_common/ccid_device.h
+++ b/ccid_common/ccid_device.h
@@ -53,6 +53,8 @@
 	bool cmd_busy;
 	/* decided CCID parameters */
 	struct ccid_pars_decoded pars;
+	/* proposed CCID parameters */
+	struct ccid_pars_decoded proposed_pars;
 	/* default parameters; applied on ResetParameters */
 	const struct ccid_pars_decoded *default_pars;
 };
@@ -80,7 +82,7 @@
 				const struct ccid_pc_to_rdr_xfr_block *xfb);
 	void (*set_power)(struct ccid_slot *cs, bool enable);
 	void (*set_clock)(struct ccid_slot *cs, enum ccid_clock_command cmd);
-	int (*set_params)(struct ccid_slot *cs, enum ccid_protocol_num proto,
+	int (*set_params)(struct ccid_slot *cs, uint8_t seq, enum ccid_protocol_num proto,
 			  const struct ccid_pars_decoded *pars_dec);
 	int (*set_rate_and_clock)(struct ccid_slot *cs, uint32_t freq_hz, uint32_t rate_bps);
 };
@@ -118,6 +120,10 @@
 			const uint32_t *data_rates, const uint32_t *clock_freqs,
 			const char *name, void *priv);
 int ccid_handle_out(struct ccid_instance *ci, struct msgb *msg);
+struct msgb *ccid_gen_parameters_t0(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
+					   enum ccid_error_code err);
+struct msgb *ccid_gen_parameters_t1(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
+					   enum ccid_error_code err);
 
 /* Invalid request received: Please return STALL */
 #define CCID_CTRL_RET_INVALID	-1
diff --git a/ccid_common/ccid_slot_fsm.c b/ccid_common/ccid_slot_fsm.c
index 870cf35..8bdcfd5 100644
--- a/ccid_common/ccid_slot_fsm.c
+++ b/ccid_common/ccid_slot_fsm.c
@@ -13,6 +13,7 @@
 #include "ccid_device.h"
 #include "cuart.h"
 #include "iso7816_fsm.h"
+#include "iso7816_3.h"
 
 struct iso_fsm_slot {
 	/* CCID slot above us */
@@ -112,6 +113,33 @@
 		ccid_slot_send_unbusy(cs, resp);
 		msgb_free(tpdu);
 		break;
+	case ISO7816_E_PPS_DONE_IND:
+		tpdu = data;
+		/* pps was successful, so we know these values are fine */
+		uint16_t F = iso7816_3_fi_table[cs->proposed_pars.fi];
+		uint8_t D = iso7816_3_di_table[cs->proposed_pars.di];
+		uint32_t fmax = iso7816_3_fmax_table[cs->proposed_pars.fi];
+
+		card_uart_ctrl(ss->cuart, CUART_CTL_CLOCK_FREQ, fmax);
+		card_uart_ctrl(ss->cuart, CUART_CTL_FD, F/D);
+		card_uart_ctrl(ss->cuart, CUART_CTL_WTIME, cs->proposed_pars.t0.waiting_integer);
+
+		cs->pars = cs->proposed_pars;
+		resp = ccid_gen_parameters_t0(cs, ss->seq, CCID_CMD_STATUS_OK, 0);
+
+		ccid_slot_send_unbusy(cs, resp);
+
+		/* this frees the pps req from the host, pps resp buffer stays with the pps fsm */
+		msgb_free(tpdu);
+		break;
+	case ISO7816_E_PPS_FAILED_IND:
+		tpdu = data;
+		/* failed fi/di */
+		resp = ccid_gen_parameters_t0(cs, ss->seq, CCID_CMD_STATUS_FAILED, 10);
+		ccid_slot_send_unbusy(cs, resp);
+		/* this frees the pps req from the host, pps resp buffer stays with the pps fsm */
+		msgb_free(tpdu);
+		break;
 	default:
 		LOGPCS(cs, LOGL_NOTICE, "%s(event=%d, cause=%d, data=%p) unhandled\n",
 			__func__, event, cause, data);
@@ -175,10 +203,36 @@
 	}
 }
 
-static int iso_fsm_slot_set_params(struct ccid_slot *cs, enum ccid_protocol_num proto,
+static int iso_fsm_slot_set_params(struct ccid_slot *cs, uint8_t seq, enum ccid_protocol_num proto,
 				const struct ccid_pars_decoded *pars_dec)
 {
-	/* we always acknowledge all parameters */
+	struct iso_fsm_slot *ss = ccid_slot2iso_fsm_slot(cs);
+	struct msgb *tpdu;
+
+	/* see 6.1.7 for error offsets */
+	if(proto != CCID_PROTOCOL_NUM_T0)
+		return -7;
+
+	if(pars_dec->t0.guard_time_etu != 0)
+		return -12;
+
+	if(pars_dec->clock_stop != CCID_CLOCK_STOP_NOTALLOWED)
+		return -14;
+
+	ss->seq = seq;
+
+	/* Hardware does not support SPU, so no PPS2, and PPS3 is reserved anyway */
+	tpdu = msgb_alloc(6, "PPSRQ");
+	OSMO_ASSERT(tpdu);
+	msgb_put_u8(tpdu, 0xff);
+	msgb_put_u8(tpdu, (1 << 4)); /* only PPS1, T=0 */
+	msgb_put_u8(tpdu, (pars_dec->fi << 4 | pars_dec->di));
+	msgb_put_u8(tpdu, 0xff ^ (1 << 4) ^ (pars_dec->fi << 4 | pars_dec->di));
+
+
+	LOGPCS(cs, LOGL_DEBUG, "scheduling PPS transfer: %s\n", msgb_hexdump(tpdu));
+	osmo_fsm_inst_dispatch(ss->fi, ISO7816_E_XCEIVE_PPS_CMD, tpdu);
+	/* continues in iso_fsm_clot_user_cb once response/error/timeout is received */
 	return 0;
 }
 
diff --git a/ccid_common/cuart.h b/ccid_common/cuart.h
index 5e397ab..9c93b7e 100644
--- a/ccid_common/cuart.h
+++ b/ccid_common/cuart.h
@@ -25,8 +25,10 @@
 	CUART_CTL_RX,		/* enable/disable receiver */
 	CUART_CTL_POWER,	/* enable/disable ICC power */
 	CUART_CTL_CLOCK,	/* enable/disable ICC clock */
+	CUART_CTL_CLOCK_FREQ, /* set ICC clock frequency (hz)*/
 	CUART_CTL_RST,		/* enable/disable ICC reset */
 	CUART_CTL_WTIME,	/* set the waiting time (in etu) */
+	CUART_CTL_FD,
 };
 
 struct card_uart;
@@ -74,6 +76,7 @@
 	uint32_t wtime_etu;
 	struct osmo_timer_list wtime_tmr;
 
+
 	/* driver-specific private data */
 	union {
 		struct {
@@ -95,6 +98,8 @@
 		struct {
 			struct usart_async_descriptor *usa_pd;
 			uint8_t slot_nr;
+			/* in us, required, no delay breaks _rx_ */
+			uint32_t extrawait_after_rx;
 		} asf4;
 	} u;
 };
diff --git a/sysmoOCTSIM/iso7816_3.c b/ccid_common/iso7816_3.c
similarity index 100%
rename from sysmoOCTSIM/iso7816_3.c
rename to ccid_common/iso7816_3.c
diff --git a/sysmoOCTSIM/iso7816_3.h b/ccid_common/iso7816_3.h
similarity index 100%
rename from sysmoOCTSIM/iso7816_3.h
rename to ccid_common/iso7816_3.h
diff --git a/ccid_common/iso7816_fsm.c b/ccid_common/iso7816_fsm.c
index beda7ab..c675ece 100644
--- a/ccid_common/iso7816_fsm.c
+++ b/ccid_common/iso7816_fsm.c
@@ -69,6 +69,7 @@
  *  @note defined in ISO/IEC 7816-3:2006(E) section 9
  */
 enum pps_state {
+	PPS_S_TX_PPS_REQ,  /*!< tx pps request */
 	PPS_S_WAIT_PPSS, /*!< initial byte */
 	PPS_S_WAIT_PPS0, /*!< format byte */
 	PPS_S_WAIT_PPS1, /*!< first parameter byte */
@@ -221,7 +222,7 @@
 
 	/* go back to initial state in child FSMs */
 	osmo_fsm_inst_state_chg(ip->atr_fi, ATR_S_WAIT_TS, 0, 0);
-	//osmo_fsm_inst_state_chg(ip->pps_fi, PPS_S_WAIT_PPSS, 0, 0);
+	osmo_fsm_inst_state_chg(ip->pps_fi, PPS_S_TX_PPS_REQ, 0, 0);
 	osmo_fsm_inst_state_chg(ip->tpdu_fi, TPDU_S_INIT, 0, 0);
 }
 
@@ -311,6 +312,12 @@
 		/* pass on to sub-fsm */
 		osmo_fsm_inst_dispatch(ip->tpdu_fi, event, data);
 		break;
+	case ISO7816_E_XCEIVE_PPS_CMD:
+//		osmo_fsm_inst_state_chg(fi, ISO7816_S_IN_PPS_REQ, 0, 0);
+		osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_PPS_RSP, 0, 0);
+		osmo_fsm_inst_state_chg(ip->pps_fi, PPS_S_TX_PPS_REQ, 0, 0);
+		osmo_fsm_inst_dispatch(ip->pps_fi, event, data);
+		break;
 	default:
 		OSMO_ASSERT(0);
 	}
@@ -369,6 +376,65 @@
 	}
 }
 
+static void iso7816_3_in_pps_req_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	struct iso7816_3_priv *tfp = get_iso7816_3_priv(fi);
+//	struct osmo_fsm_inst *parent_fi = fi->proc.parent;
+//	struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
+
+	switch (event) {
+	case ISO7816_E_XCEIVE_PPS_CMD:
+		osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_PPS_RSP, 0, 0);
+//		card_uart_tx(tfp->uart, msgb_data(data), msgb_length(data), true);
+		break;
+	default:
+		OSMO_ASSERT(0);
+	}
+}
+
+
+static void iso7816_3_s_wait_pps_rsp_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
+	switch (event) {
+	case ISO7816_E_TX_COMPL:
+		/* Rx of single byte is already enabled by previous card_uart_tx() call */
+		osmo_fsm_inst_state_chg(fi, ISO7816_S_IN_PPS_RSP, 0, 0);
+		break;
+	default:
+		OSMO_ASSERT(0);
+	}
+}
+
+static void iso7816_3_s_ins_pps_rsp_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
+	struct msgb *ppsrsp;
+	OSMO_ASSERT(fi->fsm == &iso7816_3_fsm);
+
+	switch (event) {
+	case ISO7816_E_RX_SINGLE:
+	case ISO7816_E_WTIME_EXP:
+		/* simply pass this through to the child FSM for the ATR */
+		osmo_fsm_inst_dispatch(ip->pps_fi, event, data);
+		break;
+	case ISO7816_E_PPS_DONE_IND:
+	case ISO7816_E_PPS_FAILED_IND:
+		ppsrsp = data;
+		osmo_fsm_inst_state_chg(fi, ISO7816_S_WAIT_TPDU, 0, 0);
+		/* notify user about PPS result */
+		ip->user_cb(fi, event, 0, ppsrsp);
+		break;
+	case ISO7816_E_RX_ERR_IND:
+		ppsrsp = data;
+		osmo_fsm_inst_state_chg(fi, ISO7816_S_RESET, 0, 0);
+		ip->user_cb(fi, event, 0, ppsrsp);
+		break;
+	default:
+		OSMO_ASSERT(0);
+	}
+}
+
 static const struct osmo_fsm_state iso7816_3_states[] = {
 	[ISO7816_S_RESET] = {
 		.name = "RESET",
@@ -400,11 +466,13 @@
 	},
 	[ISO7816_S_WAIT_TPDU] = {
 		.name = "WAIT_TPDU",
-		.in_event_mask =	S(ISO7816_E_XCEIVE_TPDU_CMD),
+		.in_event_mask =	S(ISO7816_E_XCEIVE_TPDU_CMD) |
+							S(ISO7816_E_XCEIVE_PPS_CMD),
 		.out_state_mask =	S(ISO7816_S_RESET) |
 					S(ISO7816_S_WAIT_TPDU) |
 					S(ISO7816_S_IN_TPDU) |
-					S(ISO7816_S_IN_PPS_REQ),
+					S(ISO7816_S_IN_PPS_REQ) |
+					S(ISO7816_S_WAIT_PPS_RSP),
 		.action = iso7816_3_wait_tpdu_action,
 		.onenter = iso7816_3_wait_tpdu_onenter,
 	},
@@ -424,26 +492,36 @@
 	},
 	[ISO7816_S_IN_PPS_REQ] = {
 		.name = "IN_PPS_REQ",
-		.in_event_mask =	0, /* FIXME */
+		.in_event_mask =	S(ISO7816_E_XCEIVE_TPDU_CMD),
 		.out_state_mask =	S(ISO7816_S_RESET) |
 					S(ISO7816_S_WAIT_TPDU) |
 					S(ISO7816_S_IN_PPS_REQ) |
 					S(ISO7816_S_WAIT_PPS_RSP),
+		.action = iso7816_3_in_pps_req_action,
 	},
 	[ISO7816_S_WAIT_PPS_RSP] = {
 		.name = "WAIT_PPS_RESP",
-		.in_event_mask =	0, /* FIXME */
+		.in_event_mask =	S(ISO7816_E_TX_COMPL) |
+					S(ISO7816_E_TX_ERR_IND) |
+					S(ISO7816_E_WTIME_EXP),
 		.out_state_mask =	S(ISO7816_S_RESET) |
 					S(ISO7816_S_WAIT_TPDU) |
 					S(ISO7816_S_WAIT_PPS_RSP) |
 					S(ISO7816_S_IN_PPS_RSP),
+		.action = iso7816_3_s_wait_pps_rsp_action,
 	},
 	[ISO7816_S_IN_PPS_RSP] = {
 		.name = "IN_PPS_RESP",
-		.in_event_mask =	0, /* FIXME */
+		.in_event_mask =	S(ISO7816_E_RX_SINGLE) |
+					S(ISO7816_E_RX_COMPL) |
+					S(ISO7816_E_RX_ERR_IND) |
+					S(ISO7816_E_PPS_DONE_IND) |
+					S(ISO7816_E_PPS_FAILED_IND) |
+					S(ISO7816_E_WTIME_EXP),
 		.out_state_mask =	S(ISO7816_S_RESET) |
 					S(ISO7816_S_WAIT_TPDU) |
 					S(ISO7816_S_IN_PPS_RSP),
+		.action = iso7816_3_s_ins_pps_rsp_action,
 	},
 };
 static struct osmo_fsm iso7816_3_fsm = {
@@ -796,28 +874,188 @@
 /***********************************************************************
  * PPS FSM
  ***********************************************************************/
+struct pps_fsm_priv {
+	struct msgb* tx_cmd;
+	struct msgb* rx_cmd;
+	uint8_t pps0_recv;
+};
+
+static void pps_s_wait_ppss_onenter(struct osmo_fsm_inst *fi, uint32_t old_state)
+{
+	struct pps_fsm_priv *atp = fi->priv;
+
+	if (!atp->rx_cmd)
+		atp->rx_cmd = msgb_alloc_c(fi, 6, "ATR"); /* TS + 32 chars */
+	else
+		msgb_reset(atp->rx_cmd);
+}
+
+static void pps_s_tx_pps_req_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	struct pps_fsm_priv *atp = fi->priv;
+	atp->tx_cmd = data;
+	struct osmo_fsm_inst *parent_fi = fi->proc.parent;
+	struct iso7816_3_priv *ip = get_iso7816_3_priv(parent_fi);
+
+	switch (event) {
+	case ISO7816_E_XCEIVE_PPS_CMD:
+		osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPSS, 0, 0);
+		card_uart_tx(ip->uart, msgb_data(data), msgb_length(data), true);
+		break;
+	default:
+		OSMO_ASSERT(0);
+	}
+}
+
+static void pps_wait_pX_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	struct pps_fsm_priv *atp = fi->priv;
+//	uint32_t guard_time_ms = atr_fi_gt_ms(fi);
+	uint8_t byte;
+
+	switch (event) {
+	case ISO7816_E_RX_SINGLE:
+		byte = get_rx_byte_evt(fi->proc.parent, data);
+		LOGPFSML(fi, LOGL_DEBUG, "RX byte '%02x'\n", byte);
+		msgb_put_u8(atp->rx_cmd, byte);
+		switch (fi->state) {
+		case PPS_S_WAIT_PPSS:
+			if (byte == 0xff)
+				osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS0, 0, 0);
+			break;
+		case PPS_S_WAIT_PPS0:
+			atp->pps0_recv = byte;
+			if(atp->pps0_recv & (1 << 4)) {
+				osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS1, 0, 0);
+				break;
+			} else if (atp->pps0_recv & (1 << 5)) {
+				osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS2, 0, 0);
+				break;
+			} else if (atp->pps0_recv & (1 << 6)) {
+				osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS3, 0, 0);
+				break;
+			}
+			osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PCK, 0, 0);
+			break;
+		case PPS_S_WAIT_PPS1:
+			if (atp->pps0_recv & (1 << 5)) {
+				osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS2, 0, 0);
+				break;
+			} else if (atp->pps0_recv & (1 << 6)) {
+				osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS3, 0, 0);
+				break;
+			}
+			osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PCK, 0, 0);
+			break;
+		case PPS_S_WAIT_PPS2:
+			if (atp->pps0_recv & (1 << 6)) {
+				osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PPS3, 0, 0);
+				break;
+			}
+			osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PCK, 0, 0);
+			break;
+		case PPS_S_WAIT_PPS3:
+			osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_PCK, 0, 0);
+			break;
+		case PPS_S_WAIT_PCK:
+			/* verify checksum if present */
+			if (fi->state == PPS_S_WAIT_PCK) {
+				uint8_t *pps_received = msgb_data(atp->rx_cmd);
+				uint8_t *pps_sent = msgb_data(atp->tx_cmd);
+
+				osmo_fsm_inst_state_chg(fi, PPS_S_WAIT_END, 0, 0);
+
+				/* pps was successful if response equals request
+				 * rx buffer stays with the fsm, tx buffer gets handed back and freed
+				 * by the cb */
+				if (msgb_length(atp->rx_cmd) == msgb_length(atp->tx_cmd) &&
+					!memcmp(pps_received, pps_sent, msgb_length(atp->rx_cmd))) {
+					osmo_fsm_inst_dispatch(fi->proc.parent,
+							ISO7816_E_PPS_DONE_IND, atp->tx_cmd);
+				} else {
+					osmo_fsm_inst_dispatch(fi->proc.parent,
+							ISO7816_E_PPS_FAILED_IND, atp->tx_cmd);
+				}
+			}
+			break;
+		default:
+			OSMO_ASSERT(0);
+		}
+		break;
+	case ISO7816_E_WTIME_EXP:
+		/* FIXME: timeout handling if no pps supported ? */
+		osmo_fsm_inst_dispatch(fi->proc.parent, ISO7816_E_RX_ERR_IND, NULL);
+		break;
+	default:
+		OSMO_ASSERT(0);
+	}
+}
+
 
 static const struct osmo_fsm_state pps_states[] = {
+	[PPS_S_TX_PPS_REQ] = {
+		.name = "TX_PPS_REQ",
+		.in_event_mask =	S(ISO7816_E_XCEIVE_PPS_CMD) |
+							S(ISO7816_E_WTIME_EXP),
+		.out_state_mask =	S(PPS_S_TX_PPS_REQ) |
+							S(PPS_S_WAIT_PPSS),
+		.action = pps_s_tx_pps_req_action,
+		.onenter = pps_s_wait_ppss_onenter,
+	},
 	[PPS_S_WAIT_PPSS] = {
 		.name = "WAIT_PPSS",
+		.in_event_mask =	S(ISO7816_E_RX_SINGLE) |
+							S(ISO7816_E_WTIME_EXP),
+		.out_state_mask =	S(PPS_S_WAIT_PPS0) |
+							S(PPS_S_WAIT_PPSS),
+		.action = pps_wait_pX_action,
 	},
 	[PPS_S_WAIT_PPS0] = {
 		.name = "WAIT_PPS0",
+		.in_event_mask =	S(ISO7816_E_RX_SINGLE) |
+							S(ISO7816_E_WTIME_EXP),
+		.out_state_mask =	S(PPS_S_WAIT_PPS1) |
+							S(PPS_S_WAIT_PPS2) |
+							S(PPS_S_WAIT_PPS3) |
+							S(PPS_S_WAIT_PCK),
+		.action = pps_wait_pX_action,
 	},
 	[PPS_S_WAIT_PPS1] = {
 		.name = "WAIT_PPS1",
+		.in_event_mask =	S(ISO7816_E_RX_SINGLE) |
+							S(ISO7816_E_WTIME_EXP),
+		.out_state_mask =	S(PPS_S_WAIT_PPS2) |
+							S(PPS_S_WAIT_PPS3) |
+							S(PPS_S_WAIT_PCK),
+		.action = pps_wait_pX_action,
 	},
 	[PPS_S_WAIT_PPS2] = {
 		.name = "WAIT_PPS2",
+		.in_event_mask =	S(ISO7816_E_RX_SINGLE) |
+							S(ISO7816_E_WTIME_EXP),
+		.out_state_mask =	S(PPS_S_WAIT_PPS3) |
+							S(PPS_S_WAIT_PCK),
+		.action = pps_wait_pX_action,
 	},
 	[PPS_S_WAIT_PPS3] = {
 		.name = "WAIT_PPS3",
+		.in_event_mask =	S(ISO7816_E_RX_SINGLE) |
+							S(ISO7816_E_WTIME_EXP),
+		.out_state_mask =	S(PPS_S_WAIT_PCK),
+		.action = pps_wait_pX_action,
 	},
 	[PPS_S_WAIT_PCK] = {
 		.name = "WAIT_PCK",
+		.in_event_mask =	S(ISO7816_E_RX_SINGLE) |
+							S(ISO7816_E_WTIME_EXP),
+		.out_state_mask =	S(PPS_S_WAIT_END),
+		.action = pps_wait_pX_action,
 	},
 	[PPS_S_WAIT_END] = {
 		.name = "WAIT_END",
+		.in_event_mask =	0,
+		.out_state_mask =	S(PPS_S_TX_PPS_REQ) |
+							S(PPS_S_WAIT_PPSS),
 	},
 };
 
@@ -1223,7 +1461,7 @@
 	if (!ip->tpdu_fi->priv)
 		goto out_tpdu;
 
-#if 0
+#if 1
 	ip->pps_fi = osmo_fsm_inst_alloc_child(&pps_fsm, fi, ISO7816_E_SW_ERR_IND);
 	if (!ip->pps_fi)
 		goto out_tpdu;
@@ -1237,7 +1475,7 @@
 
 	return fi;
 
-#if 0
+#if 1
 out_pps:
 	osmo_fsm_inst_free(ip->pps_fi);
 #endif
diff --git a/ccid_common/iso7816_fsm.h b/ccid_common/iso7816_fsm.h
index f2c7483..f512709 100644
--- a/ccid_common/iso7816_fsm.h
+++ b/ccid_common/iso7816_fsm.h
@@ -21,6 +21,9 @@
 	ISO7816_E_RESET_ACT_IND,	/*!< Reset activated */
 	ISO7816_E_ABORT_REQ,		/*!< Abort request (e.g. from CCID) */
 	/* TODO: PPS request */
+	ISO7816_E_XCEIVE_PPS_CMD,
+	ISO7816_E_PPS_DONE_IND,
+	ISO7816_E_PPS_FAILED_IND,
 	/* TODO: Clock stop request */
 	/* TODO: Rx FIFO overrun */
 	/* TODO: Rx buffer overrun */
diff --git a/sysmoOCTSIM/cuart_driver_asf4_usart_async.c b/sysmoOCTSIM/cuart_driver_asf4_usart_async.c
index f9856f3..a8f8044 100644
--- a/sysmoOCTSIM/cuart_driver_asf4_usart_async.c
+++ b/sysmoOCTSIM/cuart_driver_asf4_usart_async.c
@@ -289,6 +289,8 @@
 	cuart->u.asf4.usa_pd = usa_pd;
 	cuart->u.asf4.slot_nr = slot_nr;
 
+	/* in us, 20Mhz with default ncn8025 divider 8, F=372, D=1*/
+	cuart->u.asf4.extrawait_after_rx = 1./(20./8/372);
 
 	usart_async_register_callback(usa_pd, USART_ASYNC_RXC_CB, SIM_rx_cb[slot_nr]);
 	usart_async_register_callback(usa_pd, USART_ASYNC_TXC_CB, SIM_tx_cb[slot_nr]);
@@ -338,6 +340,8 @@
 	return io_read(&usa_pd->io, data, len);
 }
 
+#include "ccid_device.h"
+#include "iso7816_3.h"
 static int asf4_usart_ctrl(struct card_uart *cuart, enum card_uart_ctl ctl, int arg)
 {
 	struct ncn8025_settings settings;
@@ -349,7 +353,7 @@
 			sercom->USART.CTRLB.bit.RXEN = 1;
 			sercom->USART.CTRLB.bit.TXEN = 0;
 		} else {
-			delay_us(100);
+			delay_us(cuart->u.asf4.extrawait_after_rx);
 			sercom->USART.CTRLB.bit.RXEN = 0;
 			sercom->USART.CTRLB.bit.TXEN = 1;
 		}
@@ -361,22 +365,47 @@
 		usart_async_flush_rx_buffer(cuart->u.asf4.usa_pd);
 		break;
 	case CUART_CTL_POWER:
-		ncn8025_get(cuart->u.asf4.slot_nr, &settings);
-		settings.cmdvcc = arg ? true : false;
-		settings.led = arg ? true : false;
-		settings.vsel = SIM_VOLT_5V0;
+		/* in us, 20Mhz with default ncn8025 divider 8, F=372, D=1*/
+		cuart->u.asf4.extrawait_after_rx = 1./(20./8/372);
 
 		// set USART baud rate to match the interface (f = 2.5 MHz) and card default settings (Fd = 372, Dd = 1)
 		if(arg)
 			slot_set_isorate(cuart->u.asf4.slot_nr, SIM_CLKDIV_8, ISO7816_3_DEFAULT_FD, ISO7816_3_DEFAULT_DD);
 
+		ncn8025_get(cuart->u.asf4.slot_nr, &settings);
+		settings.cmdvcc = arg ? true : false;
+		settings.led = arg ? true : false;
+		settings.vsel = SIM_VOLT_5V0;
 		ncn8025_set(cuart->u.asf4.slot_nr, &settings);
+
 		break;
 	case CUART_CTL_WTIME:
 		/* no driver-specific handling of this */
 		break;
 	case CUART_CTL_CLOCK:
-		/* FIXME */
+		/* no clock stop support */
+		break;
+	case CUART_CTL_CLOCK_FREQ:
+		ncn8025_get(cuart->u.asf4.slot_nr, &settings);
+
+		/* 2,5/5/10/20 supported by dividers */
+		enum ncn8025_sim_clkdiv clkdiv = SIM_CLKDIV_1;
+		if(arg < 20000000)
+			clkdiv = SIM_CLKDIV_2;
+		if(arg < 10000000)
+			clkdiv = SIM_CLKDIV_4;
+		if(arg < 5000000)
+			clkdiv = SIM_CLKDIV_8;
+		settings.clkdiv = clkdiv;
+		ncn8025_set(cuart->u.asf4.slot_nr, &settings);
+		break;
+	case CUART_CTL_FD:
+		ncn8025_get(cuart->u.asf4.slot_nr, &settings);
+		uint8_t divider = ncn8025_div_val[settings.clkdiv];
+		uint32_t baudrate = (20e6/divider)/arg;
+		cuart->u.asf4.extrawait_after_rx = 1./baudrate * 1000 * 1000;
+		slot_set_baudrate(cuart->u.asf4.slot_nr, baudrate);
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/sysmoOCTSIM/gcc/Makefile b/sysmoOCTSIM/gcc/Makefile
index 9873159..41f5d10 100644
--- a/sysmoOCTSIM/gcc/Makefile
+++ b/sysmoOCTSIM/gcc/Makefile
@@ -84,6 +84,7 @@
 	ccid_common/ccid_proto.o \
 	ccid_common/ccid_device.o \
 	ccid_common/iso7816_fsm.o \
+	ccid_common/iso7816_3.o \
 	ccid_common/cuart.o \
 	ccid_common/ccid_slot_fsm.o \
 	cuart_driver_asf4_usart_async.o \
@@ -123,7 +124,6 @@
 	hpl/sercom/hpl_sercom.o \
 	hpl/usb/hpl_usb.o \
 	i2c_bitbang.o \
-	iso7816_3.o \
 	libosmo_emb.o \
 	main.o \
 	manual_test.o \
diff --git a/sysmoOCTSIM/ncn8025.c b/sysmoOCTSIM/ncn8025.c
index 540b166..74d3b39 100644
--- a/sysmoOCTSIM/ncn8025.c
+++ b/sysmoOCTSIM/ncn8025.c
@@ -159,7 +159,7 @@
 	[SIM_VOLT_1V8] = "1.8",
 };
 
-static const unsigned int div_val[] = {
+const unsigned int ncn8025_div_val[] = {
 	[SIM_CLKDIV_1] = 1,
 	[SIM_CLKDIV_2] = 2,
 	[SIM_CLKDIV_4] = 4,
@@ -168,7 +168,7 @@
 
 void ncn8025_dump(const struct ncn8025_settings *set)
 {
-	printf("VOLT=%s, CLKDIV=%u", volt_str[set->vsel], div_val[set->clkdiv]);
+	printf("VOLT=%s, CLKDIV=%u", volt_str[set->vsel], ncn8025_div_val[set->clkdiv]);
 	if (set->rstin)
 		printf(", RST");
 	if (set->cmdvcc)
diff --git a/sysmoOCTSIM/ncn8025.h b/sysmoOCTSIM/ncn8025.h
index 2e774a7..01ddc97 100644
--- a/sysmoOCTSIM/ncn8025.h
+++ b/sysmoOCTSIM/ncn8025.h
@@ -14,6 +14,8 @@
 	SIM_CLKDIV_8 = 0,
 };
 
+extern const unsigned int ncn8025_div_val[];
+
 struct ncn8025_settings {
 	bool rstin;	/* Reset signal (true: asserted low) */
 	bool cmdvcc;	/* Command VCC pin. Activation sequence Enable (true: active low) */

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-ccid-firmware/+/16237
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ccid-firmware
Gerrit-Branch: master
Gerrit-Change-Id: I2e226b0033f8a147fad60a33a63cc45ee9adc756
Gerrit-Change-Number: 16237
Gerrit-PatchSet: 1
Gerrit-Owner: Hoernchen <ewild at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20191126/43f15728/attachment.htm>


More information about the gerrit-log mailing list