/* 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>
*
*/
#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) {
} 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;
}
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;
}
{
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;
*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) {
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;
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 */
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;
/* 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))
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;
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 = {
.transceive = &tcl_transceive,
.close = &tcl_deselect,
.fini = &tcl_fini,
+ .getopt = &tcl_getopt,
+ .setopt = &tcl_setopt,
},
};