make "frametype" a parameter of transcieve functions
[librfid] / rfid_proto_tcl.c
index a992f70..8590fd4 100644 (file)
 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
@@ -68,17 +91,20 @@ tcl_parse_ats(struct rfid_protocol_handle *h,
        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;
        }
@@ -139,7 +165,8 @@ tcl_request_ats(struct rfid_protocol_handle *h)
        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) {
@@ -158,28 +185,81 @@ tcl_request_ats(struct rfid_protocol_handle *h)
 
        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;
 }
 
 
@@ -287,10 +367,11 @@ tcl_connect(struct rfid_protocol_handle *h)
                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:
@@ -317,7 +398,7 @@ tcl_connect(struct rfid_protocol_handle *h)
                }
 
                /* 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;
 
@@ -352,7 +433,8 @@ tcl_deselect(struct rfid_protocol_handle *h)
        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) {
@@ -383,6 +465,8 @@ tcl_transcieve(struct rfid_protocol_handle *h,
        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 */
@@ -412,8 +496,10 @@ tcl_transcieve(struct rfid_protocol_handle *h,
        _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;
 
@@ -422,11 +508,9 @@ do_tx:
                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) {
@@ -457,6 +541,7 @@ do_tx:
                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) {
@@ -501,6 +586,7 @@ do_tx:
                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);
@@ -514,7 +600,12 @@ do_tx:
                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;
                }
        }
@@ -559,8 +650,6 @@ tcl_init(struct rfid_layer2_handle *l2h)
        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);