aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Wild <ewild@sysmocom.de>2020-11-11 21:24:05 +0100
committerlaforge <laforge@osmocom.org>2020-11-20 08:54:19 +0000
commit91f1f18b4864a9ed59b68f9e8350ebdcc8e1d0a3 (patch)
tree2077819eecef1a3584c701e0aa9ef3e9ec5543b3
parent6b1f1c4e95830e80d24e70d33fad140440ed88fd (diff)
7816 fsm/cuart: support inverse condition cards
This does not currently work with "pcsc-lite version 1.8.26." because the inverse conditon cards I know do not support the PPS exchange, which according to spec leads to card deactivation, so the slots needs to be powered up again, which does not happen. osmo-sim-test works after manually disabling the pps exchange code in the firmware. Change-Id: I892e1d883825111cc1e4ea09589c4fdd256da03c
-rw-r--r--ccid_common/ccid_slot_fsm.c14
-rw-r--r--ccid_common/cuart.h1
-rw-r--r--ccid_common/iso7816_fsm.c15
-rw-r--r--sysmoOCTSIM/cuart_driver_asf4_usart_async.c29
4 files changed, 52 insertions, 7 deletions
diff --git a/ccid_common/ccid_slot_fsm.c b/ccid_common/ccid_slot_fsm.c
index a8c4e54..4cf75bc 100644
--- a/ccid_common/ccid_slot_fsm.c
+++ b/ccid_common/ccid_slot_fsm.c
@@ -204,10 +204,16 @@ static int iso_handle_fsm_events(struct ccid_slot *cs, bool enable){
break;
case ISO7816_E_ATR_DONE_IND:
tpdu = data;
- LOGPCS(cs, LOGL_DEBUG, "%s(event=%d, data=%s)\n", __func__, event,
- msgb_hexdump(tpdu));
- resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0,
- msgb_data(tpdu), msgb_length(tpdu));
+
+ /* inverse condition, error interrupt is always disabled during atr and reenabled here after atr */
+ if(*msgb_data(tpdu) == 0x3f) {
+ card_uart_ctrl(ss->cuart, CUART_CTL_ERROR_AND_INV, true);
+ } else {
+ card_uart_ctrl(ss->cuart, CUART_CTL_ERROR_AND_INV, false);
+ }
+
+ LOGPCS(cs, LOGL_DEBUG, "%s(event=%d, data=%s)\n", __func__, event, msgb_hexdump(tpdu));
+ resp = ccid_gen_data_block(cs, ss->seq, CCID_CMD_STATUS_OK, 0, msgb_data(tpdu), msgb_length(tpdu));
ccid_slot_send_unbusy(cs, resp);
cs->event = 0;
break;
diff --git a/ccid_common/cuart.h b/ccid_common/cuart.h
index e5ec501..c0a3a52 100644
--- a/ccid_common/cuart.h
+++ b/ccid_common/cuart.h
@@ -54,6 +54,7 @@ enum card_uart_ctl {
CUART_CTL_SET_FD,
CUART_CTL_GET_BAUDRATE,
CUART_CTL_GET_CLOCK_FREQ,
+ CUART_CTL_ERROR_AND_INV, /* enable error interrupt and maybe inverse signalling according to arg */
};
struct card_uart;
diff --git a/ccid_common/iso7816_fsm.c b/ccid_common/iso7816_fsm.c
index e819e64..8e113b0 100644
--- a/ccid_common/iso7816_fsm.c
+++ b/ccid_common/iso7816_fsm.c
@@ -639,6 +639,15 @@ static uint8_t get_rx_byte_evt(struct osmo_fsm_inst *fi, void *data)
struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
uint8_t byte = *(uint8_t *)data;
+ return byte;
+}
+
+/* obtain the 'byte' (possbily inverted) parameter of an ISO7816_E_RX event */
+static uint8_t get_atr_rx_byte_evt(struct osmo_fsm_inst *fi, void *data)
+{
+ struct iso7816_3_priv *ip = get_iso7816_3_priv(fi);
+ uint8_t byte = *(uint8_t *)data;
+
/* apply inverse convention */
if (ip->convention_convert)
byte = convention_convert_lut[byte];
@@ -689,14 +698,14 @@ static void atr_wait_ts_action(struct osmo_fsm_inst *fi, uint32_t event, void *d
case ISO7816_E_RX_SINGLE:
OSMO_ASSERT(msgb_length(atp->atr) == 0);
restart:
- byte = get_rx_byte_evt(parent_fi, data);
+ byte = get_atr_rx_byte_evt(parent_fi, data);
LOGPFSML(fi, LOGL_DEBUG, "RX byte '%02x'\n", byte);
switch (byte) {
case 0x23:
/* direct convention used, but decoded using inverse
* convention (a parity error should also have occurred) */
/* fall-through */
- case 0x30:
+ case 0x03:
/* inverse convention used, but decoded using direct
* convention (a parity error should also have occurred) */
ip->convention_convert = !ip->convention_convert;
@@ -732,7 +741,7 @@ static void atr_wait_tX_action(struct osmo_fsm_inst *fi, uint32_t event, void *d
switch (event) {
case ISO7816_E_RX_SINGLE:
- byte = get_rx_byte_evt(fi->proc.parent, data);
+ byte = get_atr_rx_byte_evt(fi->proc.parent, data);
LOGPFSML(fi, LOGL_DEBUG, "RX byte '%02x'\n", byte);
atr_append_byte(fi, byte);
switch (fi->state) {
diff --git a/sysmoOCTSIM/cuart_driver_asf4_usart_async.c b/sysmoOCTSIM/cuart_driver_asf4_usart_async.c
index 89cd734..e6d180c 100644
--- a/sysmoOCTSIM/cuart_driver_asf4_usart_async.c
+++ b/sysmoOCTSIM/cuart_driver_asf4_usart_async.c
@@ -159,6 +159,19 @@ static const double sercom_glck_freqs[] = {100E6 / CONF_GCLK_GEN_2_DIV, 100E6 /
*/
static const uint8_t SIM_peripheral_GCLK_ID[] = {SERCOM0_GCLK_ID_CORE, SERCOM1_GCLK_ID_CORE, SERCOM2_GCLK_ID_CORE, SERCOM3_GCLK_ID_CORE, SERCOM4_GCLK_ID_CORE, SERCOM5_GCLK_ID_CORE, SERCOM6_GCLK_ID_CORE, SERCOM7_GCLK_ID_CORE};
+/** inverted signalling as per 7816-3 : inverted bit, inverted bit order
+ */
+static void set_inverted_signalling(void* hw, bool on) {
+
+ hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
+
+ hri_sercomusart_write_CTRLA_DORD_bit(hw, !on); // inverted == msb first
+ hri_sercomusart_write_CTRLA_TXINV_bit(hw, on);
+ hri_sercomusart_write_CTRLA_RXINV_bit(hw, on);
+ hri_sercomusart_write_CTRLB_PMODE_bit(hw, on); // inverted == even parity
+
+ hri_sercomusart_set_CTRLA_ENABLE_bit(hw);
+}
/** change baud rate of card slot
* @param[in] slotnr slot number for which the baud rate should be set
@@ -237,6 +250,7 @@ static bool slot_set_baudrate(struct card_uart *cuart, uint32_t baudrate)
static bool slot_set_isorate(struct card_uart *cuart, enum ncn8025_sim_clkdiv clkdiv, uint16_t f, uint8_t d)
{
uint8_t slotnr = cuart->u.asf4.slot_nr;
+ struct usart_async_descriptor* slot = SIM_peripheral_descriptors[slotnr];
// input checks
ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));
@@ -275,6 +289,12 @@ static bool slot_set_isorate(struct card_uart *cuart, enum ncn8025_sim_clkdiv cl
break;
}
+ /* error interrupt off after reset due to possbile inverted atr and accompanying parity error
+ * this was automatically enabled during error callback registration */
+ hri_sercomusart_write_INTEN_ERROR_bit(slot->device.hw, 0);
+
+ set_inverted_signalling(slot->device.hw, false);
+
// set baud rate
uint32_t baudrate = (freq * d) / f; // calculate actual baud rate
return slot_set_baudrate(cuart, baudrate); // set baud rate
@@ -435,6 +455,15 @@ static int asf4_usart_ctrl(struct card_uart *cuart, enum card_uart_ctl ctl, int
ncn8025_get(cuart->u.asf4.slot_nr, &settings);
return 20e6 / ncn8025_div_val[settings.clkdiv];
break;
+ case CUART_CTL_ERROR_AND_INV:
+ set_inverted_signalling(sercom, arg);
+
+ /* clear pending errors that happened while the interrupt was off (ATR) and enable it*/
+ hri_sercomusart_clear_interrupt_ERROR_bit(sercom);
+ hri_sercomusart_clear_STATUS_reg(sercom, 0xff);
+ volatile uint8_t dummy = hri_sercomusart_read_RXERRCNT_reg(sercom);
+ hri_sercomusart_set_INTEN_ERROR_bit(sercom);
+ break;
default:
return 0;
}