mirror of
https://gitea.osmocom.org/sim-card/simtrace2.git
synced 2026-08-16 02:18:45 +03:00
firmware: card_emu: use Di in the waiting time
ISO 7816-3 section 10.2 defines WT = WI x 960 x Fi/f seconds, store as etu, etu = Fi / (D x f) seconds, so the Fi cancels, but the D does not: WT [etu] = WI x 960 x D cemu dropped both (?!) -> WI x 960. The old comment explains why Fi can be dropped, which is right, but what about Di ?! sniffer gets it right (wt_wi * 960UL * wt_d), so the two state machines disagreed here again, by up to a factor of 64???!!?!!? This was fixed in osmo-ccid-firmware in 066489d in 2020 but not ported to st2. Additionally the waiting time was only recalculated at the end of the ATR, where D is still 1 by definition, so a PPS increasing D reprogrammed the baud rate but left the waiting time untouched??! etu duration shrinks with D by the same factor, wall clock WT is independent of D, which is the whole point. The old code decreased the waiting time by a factor of D: after a PPS to D=8 the card emitted its NULL procedure byte at ~0.09s instead of ~0.71s with a reader deadline of ~1.43s, and the inactivity timeout fires 8x too early, which probably led to unexplained wtime_exp errors. Update wt when WI becomes known (end of ATR) and where D changes (after the PPS response) + tests. Change-Id: I4263176d6073029d01f9ff5b11a6311617956af6
This commit is contained in:
@@ -386,6 +386,26 @@ static void emu_update_fidi(struct card_handle *ch)
|
||||
ch->num, rc);
|
||||
}
|
||||
|
||||
/*! Calculate the WT from current WI and D.
|
||||
*
|
||||
* ISO 7816-3 10.2 defines WT = WI x 960 x Fi / f [seconds].
|
||||
* Our waiting time is stored in units of etu = Fi / (D x f) seconds
|
||||
* -> the Fi cancels out, but D does not.
|
||||
*
|
||||
* WT [etu] = WI x 960 x D
|
||||
*
|
||||
* D is the value from ISO 7816-3 Table 8. Only 1..9 are defined,
|
||||
* 0 and RFU range 10..15 have no D -> use D = 1 */
|
||||
static void emu_update_wt(struct card_handle *ch)
|
||||
{
|
||||
uint8_t d = 1;
|
||||
|
||||
if (ch->D_index >= 1 && ch->D_index <= 9)
|
||||
d = iso7816_3_di_table[ch->D_index];
|
||||
|
||||
ch->waiting_time = ch->wi * 960 * d;
|
||||
}
|
||||
|
||||
/* Update the ISO 7816-3 TPDU receiver state */
|
||||
static void card_set_state(struct card_handle *ch,
|
||||
enum iso7816_3_card_state new_state)
|
||||
@@ -505,11 +525,8 @@ static int tx_byte_atr(struct card_handle *ch)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* update waiting time (see ISO 7816-3 10.2). We can drop the Fi
|
||||
* multiplier as we store the waiting time in units of 'etu', and
|
||||
* don't really care what the number of clock cycles or the absolute
|
||||
* wall clock time is */
|
||||
ch->waiting_time = ch->wi * 960;
|
||||
/* update the waiting time now that WI is known (see emu_update_wt) */
|
||||
emu_update_wt(ch);
|
||||
/* go to next state */
|
||||
card_set_state(ch, ISO_S_WAIT_TPDU);
|
||||
return 0;
|
||||
@@ -675,6 +692,9 @@ static int tx_byte_pts(struct card_handle *ch)
|
||||
card_emu_uart_wait_tx_idle(ch->uart_chan);
|
||||
/* update baud rate generator with F/D */
|
||||
emu_update_fidi(ch);
|
||||
/* the waiting time is expressed in etu and scales with D, so it has
|
||||
* to be recomputed whenever D changes */
|
||||
emu_update_wt(ch);
|
||||
/* Wait for the next TPDU */
|
||||
card_set_state(ch, ISO_S_WAIT_TPDU);
|
||||
set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
|
||||
|
||||
Reference in New Issue
Block a user