X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Frfid_proto_tcl.c;h=cfde04b29f688c6b8a8ff42d2c961b7f7ec716f6;hb=d7a9101e32415b5686431e48358738127f1c611b;hp=64f28b3dd66f3ae3153ffee886834b4f3594c2c6;hpb=5685d0b215152de2d05d599a421e77c6fe62ab8d;p=librfid diff --git a/src/rfid_proto_tcl.c b/src/rfid_proto_tcl.c index 64f28b3..cfde04b 100644 --- a/src/rfid_proto_tcl.c +++ b/src/rfid_proto_tcl.c @@ -1,6 +1,6 @@ /* ISO 14443-4 (T=CL) implementation, PCD side. * - * (C) 2005 by Harald Welte + * (C) 2005-2006 by Harald Welte * */ @@ -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 @@ -38,6 +38,10 @@ #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, }, };