remove autogenerated file
[librfid] / src / rfid_proto_tcl.c
index 64f28b3..cfde04b 100644 (file)
@@ -1,6 +1,6 @@
 /* ISO 14443-4 (T=CL) implementation, PCD side.
  *
- * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2005-2006 by Harald Welte <laforge@gnumonks.org>
  *
  */
 
@@ -16,7 +16,7 @@
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 #include <stdio.h>
 
 #define RFID_MAX_FRAMELEN      256
 
+#define is_s_block(x) ((x & 0xc0) == 0xc0)
+#define is_r_block(x) ((x & 0xc0) == 0x80)
+#define is_i_block(x) ((x & 0xc0) == 0x00)
+
 static enum rfid_frametype l2_to_frame(unsigned int layer2)
 {
        switch (layer2) {
@@ -118,7 +122,8 @@ tcl_parse_ats(struct rfid_protocol_handle *h,
                } else {
                        /* Section 7.2: fwi for type B is always in ATQB */
                        /* Value is assigned in tcl_connect() */
-                       /* This function is never called for Type B, since it has no (R)ATS */
+                       /* This function is never called for Type B, 
+                        * since Type B has no (R)ATS */
                }
                return 0;
        }
@@ -146,15 +151,21 @@ tcl_parse_ats(struct rfid_protocol_handle *h,
 
        if (t0 & (1 << 6)) {
                /* TC is transmitted */
-               if (*cur & 0x01)
+               if (*cur & 0x01) {
                        h->priv.tcl.flags |= TCL_HANDLE_F_NAD_SUPPORTED;
-               if (*cur & 0x02)
+                       DEBUGP("This PICC supports NAD\n");
+               }
+               if (*cur & 0x02) {
                        h->priv.tcl.flags |= TCL_HANDLE_F_CID_SUPPORTED;
+                       DEBUGP("This PICC supports CID\n");
+               }
                cur++;
        }
 
        h->priv.tcl.historical_len = (ats+len) - cur;
        h->priv.tcl.historical_bytes = cur;
+       
+       DEBUGP("ATS parsed: %s\n", rfid_hexdump(ats, size));
 
        return 0;
 }
@@ -251,7 +262,9 @@ tcl_do_pps(struct rfid_protocol_handle *h)
 {
        int ret;
        unsigned char ppss[3];
-       unsigned char pps_response[1];
+       /* FIXME: this stinks like hell. IF we reduce pps_response size to one,
+          we'll get stack corruption! */
+       unsigned char pps_response[10];
        unsigned int rx_len = 1;
        unsigned char Dr, Ds, DrI, DsI;
        unsigned int speed;
@@ -319,13 +332,15 @@ tcl_build_prologue2(struct tcl_handle *th,
 
        *prlg = pcb;
 
-       if (th->toggle) {
-               /* we've sent a toggle bit last time */
-               th->toggle = 0;
-       } else {
-               /* we've not sent a toggle last time: send one */
-               th->toggle = 1;
-               *prlg |= 0x01;
+       if (!is_s_block(pcb)) {
+               if (th->toggle) {
+                       /* we've sent a toggle bit last time */
+                       th->toggle = 0;
+               } else {
+                       /* we've not sent a toggle last time: send one */
+                       th->toggle = 1;
+                       *prlg |= 0x01;
+               }
        }
 
        if (th->flags & TCL_HANDLE_F_CID_USED) {
@@ -335,9 +350,8 @@ tcl_build_prologue2(struct tcl_handle *th,
                prlg[*prlg_len] = th->cid & 0x0f;
        }
 
-       /* nad only for I-block (0xc0 == 00) */
-       if ((th->flags & TCL_HANDLE_F_NAD_USED) &&
-           ((pcb & 0xc0) == 0x00)) {
+       /* nad only for I-block */
+       if ((th->flags & TCL_HANDLE_F_NAD_USED) && is_i_block(pcb)) {
                /* ISO 14443-4:2000(E) Section 7.1.1.3 */
                /* FIXME: in case of chaining only for first frame */
                *prlg |= TCL_PCB_NAD_FOLLOWING;
@@ -496,10 +510,6 @@ tcl_deselect(struct rfid_protocol_handle *h)
        return 0;
 }
 
-#define is_s_block(x) ((x & 0xc0) == 0xc0)
-#define is_r_block(x) ((x & 0xc0) == 0x80)
-#define is_i_block(x) ((x & 0xc0) == 0x00)
-
 struct fr_buff {
        unsigned int frame_len;         /* length of frame */
        unsigned int hdr_len;           /* length of header within frame */
@@ -634,14 +644,14 @@ do_tx:
        if (ret < 0)
                goto out;
 
-       if ((xcvb.rx.data[0] & 0x01) != h->priv.tcl.toggle) {
-               DEBUGP("response with wrong toggle bit\n");
-               goto out;
-       }
-
        if (is_r_block(xcvb.rx.data[0])) {
                DEBUGP("R-Block\n");
 
+               if ((xcvb.rx.data[0] & 0x01) != h->priv.tcl.toggle) {
+                       DEBUGP("response with wrong toggle bit\n");
+                       goto out;
+               }
+
                /* Handle ACK frame in case of chaining */
                if (!check_cid(th, &xcvb))
                        goto out;
@@ -687,6 +697,12 @@ do_tx:
                /* we're actually receiving payload data */
 
                DEBUGP("I-Block: ");
+
+               if ((xcvb.rx.data[0] & 0x01) != h->priv.tcl.toggle) {
+                       DEBUGP("response with wrong toggle bit\n");
+                       goto out;
+               }
+
                xcvb.rx.hdr_len = 1;
 
                if (!check_cid(th, &xcvb))
@@ -724,13 +740,13 @@ tcl_init(struct rfid_layer2_handle *l2h)
        struct rfid_protocol_handle *th;
        unsigned int mru = l2h->rh->ah->mru;
 
-       th = malloc(sizeof(struct rfid_protocol_handle) + mru);
+       th = malloc_protocol_handle(sizeof(struct rfid_protocol_handle));
        if (!th)
                return NULL;
 
        /* FIXME: mru should be attribute of layer2 (in case it adds/removes
         * some overhead */
-       memset(th, 0, sizeof(struct rfid_protocol_handle) + mru);
+       memset(th, 0, sizeof(struct rfid_protocol_handle));
 
        /* maximum received ats length equals mru of asic/reader */
        th->priv.tcl.state = TCL_STATE_INITIAL;
@@ -745,11 +761,50 @@ tcl_init(struct rfid_layer2_handle *l2h)
 static int
 tcl_fini(struct rfid_protocol_handle *ph)
 {
-       free(ph);
+       free_protocol_handle(ph);
        return 0;
 }
 
-struct rfid_protocol rfid_protocol_tcl = {
+int 
+tcl_getopt(struct rfid_protocol_handle *h, int optname, void *optval,
+          unsigned int *optlen)
+{
+       u_int8_t *opt_str = optval;
+
+       switch (optname) {
+       case RFID_OPT_P_TCL_ATS:
+               if (h->priv.tcl.ats_len < *optlen)
+                       *optlen = h->priv.tcl.ats_len;
+               memcpy(opt_str, h->priv.tcl.ats, *optlen);
+               break;
+       case RFID_OPT_P_TCL_ATS_LEN:
+               if (*optlen < sizeof(u_int8_t))
+                       return -E2BIG;
+               *optlen = sizeof(u_int8_t);
+               *opt_str = h->priv.tcl.ats_len & 0xff;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int
+tcl_setopt(struct rfid_protocol_handle *h, int optname, const void *optval,
+          unsigned int optlen)
+{
+       int ret = -EINVAL;
+
+       switch (optname) {
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+const struct rfid_protocol rfid_protocol_tcl = {
        .id     = RFID_PROTOCOL_TCL,
        .name   = "ISO 14443-4 / T=CL",
        .fn     = {
@@ -758,5 +813,7 @@ struct rfid_protocol rfid_protocol_tcl = {
                .transceive = &tcl_transceive,
                .close = &tcl_deselect,
                .fini = &tcl_fini,
+               .getopt = &tcl_getopt,
+               .setopt = &tcl_setopt,
        },
 };