static unsigned int sfgi_to_sfgt(struct rfid_protocol_handle *h,
unsigned char sfgi)
{
- /* ISO 14443-4:2000(E) Section 5.2.5. */
- return (256 * 16 / h->l2h->rh->ah->fc) * (2 ^ sfgi);
+ unsigned int multiplier;
+ unsigned int tmp;
+
+ if (sfgi > 14)
+ sfgi = 14;
+
+ multiplier = 1 << sfgi; /* 2 to the power of sfgi */
+
+ /* ISO 14443-4:2000(E) Section 5.2.5:
+ * (256 * 16 / h->l2h->rh->ah->fc) * (2 ^ sfgi) */
+ tmp = (unsigned int) 1000000 * 256 * 16;
+
+ return (tmp / h->l2h->rh->ah->fc) * multiplier;
}
static unsigned int fwi_to_fwt(struct rfid_protocol_handle *h,
unsigned char fwi)
{
- /* ISO 14443-4:2000(E) Section 7.2. */
- return (256*16 / h->l2h->rh->ah->fc) * (2 ^ fwi);
+ unsigned int multiplier, tmp;
+
+ if (fwi > 14)
+ fwi = 14;
+
+ multiplier = 1 << fwi; /* 2 to the power of fwi */
+
+ /* ISO 14443-4:2000(E) Section 7.2.:
+ * (256*16 / h->l2h->rh->ah->fc) * (2 ^ fwi) */
+
+ tmp = (unsigned int) 1000000 * 256 * 16;
+
+ return (tmp / h->l2h->rh->ah->fc) * multiplier;
}
-#define activation_fwt(x) (65536 / x->l2h->rh->ah->fc)
+/* 4.9seconds as microseconds (4.9 billion seconds) exceeds 2^32 */
+#define activation_fwt(x) (((u_int64_t)1000000 * 65536 / x->l2h->rh->ah->fc))
#define deactivation_fwt(x) activation_fwt(x)
static int
if (size < len)
len = size;
+ h->priv.tcl.ta = 0;
+
if (len == 1) {
/* FIXME: assume some default values */
h->priv.tcl.fsc = 32;
- h->priv.tcl.ta = 0;
+ h->priv.tcl.ta = 0x80; /* 0x80 (same d for both dirs) */
h->priv.tcl.sfgt = sfgi_to_sfgt(h, 0);
- if (1 /* FIXME: is_iso14443a */) {
+ if (h->l2h->l2->id == RFID_LAYER2_ISO14443A) {
/* Section 7.2: fwi default for type A is 4 */
h->priv.tcl.fwt = fwi_to_fwt(h, 4);
} else {
/* Section 7.2: fwi for type B is always in ATQB */
- /* FIXME */
+ /* Value is assigned in tcl_connect() */
+ /* This function is never called for Type B, since it has no (R)ATS */
}
return 0;
}
rats[1] = (h->priv.tcl.cid & 0x0f) | ((fsdi << 4) & 0xf0);
/* transcieve (with CRC) */
- ret = h->l2h->l2->fn.transcieve(h->l2h, rats, 2, h->priv.tcl.ats,
+ ret = h->l2h->l2->fn.transcieve(h->l2h, RFID_14443A_FRAME_REGULAR,
+ rats, 2, h->priv.tcl.ats,
&h->priv.tcl.ats_len, activation_fwt(h),
TCL_TRANSP_F_TX_CRC);
if (ret < 0) {
return 0;
}
+
+#define ATS_TA_DIV_2 1
+#define ATS_TA_DIV_4 2
+#define ATS_TA_DIV_8 4
+
+#define PPS_DIV_8 3
+#define PPS_DIV_4 2
+#define PPS_DIV_2 1
+#define PPS_DIV_1 0
+static unsigned char d_to_di(struct rfid_protocol_handle *h, unsigned char D)
+{
+ static char DI;
+ unsigned int speed = h->l2h->rh->reader->iso14443a.speed;
+
+ if ((D & ATS_TA_DIV_8) && (speed & RFID_READER_SPEED_848K))
+ DI = PPS_DIV_8;
+ else if ((D & ATS_TA_DIV_4) && (speed & RFID_READER_SPEED_424K))
+ DI = PPS_DIV_4;
+ else if ((D & ATS_TA_DIV_2) && (speed & RFID_READER_SPEED_212K))
+ DI = PPS_DIV_2;
+ else
+ DI = PPS_DIV_1;
+
+ return DI;
+}
+
+
/* start a PSS run (autimatically configure highest possible speed */
static int
-tcl_do_pss(struct rfid_protocol_handle *h)
+tcl_do_pps(struct rfid_protocol_handle *h)
{
+#if 0
+ int ret;
unsigned char ppss[3];
- //unsigned char pps_response[1];
+ unsigned char pps_response[1];
+ unsigned int rx_len = 1;
+ unsigned char Dr, Ds, DrI, DsI;
if (h->priv.tcl.state != TCL_STATE_ATS_RCVD)
return -1;
+ Dr = h->priv.tcl.ta & 0x07;
+ Ds = h->priv.tcl.ta & 0x70 >> 4;
+
+ if (Dr != Ds && !(h->priv.tcl.ta & 0x80)) {
+ /* device supports different divisors for rx and tx, but not ?!? */
+ DEBUGP("PICC has contradictory TA, aborting PPS\n");
+ return -1;
+ };
+
/* ISO 14443-4:2000(E) Section 5.3. */
ppss[0] = 0xd0 & (h->priv.tcl.cid & 0x0f);
ppss[1] = 0x11;
- //ppss[2] = 0x00 & foo;
+ /* FIXME: deal with different speed for each direction */
+ DrI = d_to_di(h, Dr);
+ DsI = d_to_di(h, Ds);
- // FIXME: finish
-
- return -1;
+ ppss[2] = (ppss[2] & 0xf0) | (DrI | DsI << 2);
+
+ ret = h->l2h->l2->fn.transcieve(h->l2h, ppss, 3, pps_response,
+ &rx_len, h->priv.tcl.fwt,
+ TCL_TRANSP_F_TX_CRC);
+ if (ret < 0)
+ return ret;
+
+ if (pps_response[0] != ppss[0]) {
+ DEBUGP("PPS Response != PPSS\n");
+ return -1;
+ }
h->priv.tcl.state = TCL_STATE_ESTABLISHED;
+#endif
+ return 0;
}
if (ret < 0)
return ret;
- if (0 /* FIXME */) {
- ret = tcl_do_pss(h);
+ /* Only do PPS if any non-default divisors supported */
+ if (h->priv.tcl.ta & 0x77) {
+ ret = tcl_do_pps(h);
if (ret < 0)
- return -1;
+ return ret;
}
break;
case RFID_LAYER2_ISO14443B:
}
/* PUPI will be presented as ATS/historical bytes */
- memcpy(h->priv.tcl.ats, h->l2h->priv.iso14443b.pupi, 4);
+ memcpy(h->priv.tcl.ats, h->l2h->uid, 4);
h->priv.tcl.ats_len = 4;
h->priv.tcl.historical_bytes = h->priv.tcl.ats;
if (ret < 0)
return ret;
- ret = h->l2h->l2->fn.transcieve(h->l2h, frame, prlg_len, rx,
+ ret = h->l2h->l2->fn.transcieve(h->l2h, RFID_14443A_FRAME_REGULAR,
+ frame, prlg_len, rx,
&rx_len, deactivation_fwt(h),
TCL_TRANSP_F_TX_CRC);
if (ret < 0) {
unsigned char *_tx;
unsigned int _tx_len, _timeout;
unsigned char wtx_resp[3];
+ unsigned char ack[10];
+ unsigned int ack_len;
if (tx_len > max_net_tx_framesize(th)) {
/* slow path: we need to use chaining */
_timeout = th->fwt;
do_tx:
- ret = h->l2h->l2->fn.transcieve(h->l2h, _tx, _tx_len,
+ ret = h->l2h->l2->fn.transcieve(h->l2h, RFID_14443A_FRAME_REGULAR,
+ _tx, _tx_len,
rx_buf, rx_len, _timeout, 0);
+ DEBUGP("l2 transcieve finished\n");
if (ret < 0)
goto out_rxb;
goto out_rxb;
}
- //if (*rx_len )
- //
-
if (is_r_block(*rx_buf)) {
unsigned int txed = _tx - tx_buf;
+ DEBUGP("R-Block\n");
/* Handle ACK frame in case of chaining */
if (*rx_buf & TCL_PCB_CID_FOLLOWING) {
if (*(rx_buf+1) != h->priv.tcl.cid) {
unsigned char inf;
unsigned int prlg_len;
+ DEBUGP("S-Block\n");
/* Handle Wait Time Extension */
if (*rx_buf & TCL_PCB_CID_FOLLOWING) {
if (*rx_len < 3) {
unsigned char *inf = rx_buf+1;
/* we're actually receiving payload data */
+ DEBUGP("I-Block\n");
if (*rx_buf & TCL_PCB_CID_FOLLOWING) {
if (*(rx_buf+1) != h->priv.tcl.cid) {
DEBUGP("CID %u is not valid\n", *(rx_buf)+1);
memcpy(rx_data, inf, *rx_len - (inf - rx_buf));
if (*rx_buf & 0x10) {
- /* we're not the last frame in the chain, continue */
+ /* we're not the last frame in the chain, continue rx */
+ DEBUGP("we're not the last frame in the chain, continue\n");
+ ack_len = sizeof(ack);
+ tcl_build_prologue_r(&h->priv.tcl, ack, &ack_len, 0);
+ _tx = ack;
+ _tx_len = ack_len;
goto do_tx;
}
}
th->priv.tcl.state = TCL_STATE_INITIAL;
th->priv.tcl.ats_len = mru;
th->priv.tcl.toggle = 1;
- th->l2h = l2h;
- th->proto = &rfid_protocol_tcl;
th->priv.tcl.fsd = iso14443_fsd_approx(mru);