From 05c7e304271bcf88901da3782fcd3f28a0c7c9cf Mon Sep 17 00:00:00 2001 From: laforge Date: Tue, 8 Nov 2005 08:34:15 +0000 Subject: use autoconf/automake git-svn-id: https://svn.gnumonks.org/trunk/librfid@1658 e0336214-984f-0b4b-a45f-81c69e1f0ede --- rfid_proto_tcl.c | 694 ------------------------------------------------------- 1 file changed, 694 deletions(-) delete mode 100644 rfid_proto_tcl.c (limited to 'rfid_proto_tcl.c') diff --git a/rfid_proto_tcl.c b/rfid_proto_tcl.c deleted file mode 100644 index f070614..0000000 --- a/rfid_proto_tcl.c +++ /dev/null @@ -1,694 +0,0 @@ -/* ISO 14443-4 (T=CL) implementation, PCD side. - * - * (C) 2005 by Harald Welte - * - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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 - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "rfid_iso14443_common.h" - -#if 1 -#ifdef DEBUGP -#undef DEBUGP -#define DEBUGP(x, ...) -#define DEBUGPC(x, ...) -#endif -#endif - -static enum rfid_frametype l2_to_frame(unsigned int layer2) -{ - switch (layer2) { - case RFID_LAYER2_ISO14443A: - return RFID_14443A_FRAME_REGULAR; - break; - case RFID_LAYER2_ISO14443B: - return RFID_14443B_FRAME_REGULAR; - break; - } - return 0; -} - -static unsigned int sfgi_to_sfgt(struct rfid_protocol_handle *h, - unsigned char 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) -{ - 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; -} - -/* 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 -tcl_parse_ats(struct rfid_protocol_handle *h, - unsigned char *ats, unsigned int size) -{ - unsigned char len = ats[0]; - unsigned char t0; - unsigned char *cur; - - if (len == 0 || size == 0) - return -1; - - 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 = 0x80; /* 0x80 (same d for both dirs) */ - h->priv.tcl.sfgt = sfgi_to_sfgt(h, 0); - 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 */ - /* Value is assigned in tcl_connect() */ - /* This function is never called for Type B, since it has no (R)ATS */ - } - return 0; - } - - /* guarateed to be at least 2 bytes in size */ - - t0 = ats[1]; - cur = &ats[2]; - - iso14443_fsdi_to_fsd(&h->priv.tcl.fsc, t0 & 0x0f); - - if (t0 & (1 << 4)) { - /* TA is transmitted */ - h->priv.tcl.ta = *cur++; - } - - if (t0 & (1 << 5)) { - /* TB is transmitted */ - h->priv.tcl.sfgt = sfgi_to_sfgt(h, *cur & 0x0f); - h->priv.tcl.fwt = fwi_to_fwt(h, (*cur & 0xf0) >> 4); - cur++; - } - - if (t0 & (1 << 6)) { - /* TC is transmitted */ - if (*cur & 0x01) - h->priv.tcl.flags |= TCL_HANDLE_F_NAD_SUPPORTED; - if (*cur & 0x02) - h->priv.tcl.flags |= TCL_HANDLE_F_CID_SUPPORTED; - cur++; - } - - h->priv.tcl.historical_len = (ats+len) - cur; - h->priv.tcl.historical_bytes = cur; - - return 0; -} - - -/* request an ATS from the PICC */ -static int -tcl_request_ats(struct rfid_protocol_handle *h) -{ - int ret; - unsigned char rats[2]; - unsigned char fsdi; - - if (h->priv.tcl.state != TCL_STATE_INITIAL) - return -1; - - ret = iso14443_fsd_to_fsdi(&fsdi, h->priv.tcl.fsd); - if (ret < 0) { - DEBUGP("unable to encode FSD of %u as FSDI\n", h->priv.tcl.fsd); - return ret; - } - - rats[0] = 0xe0; - rats[1] = (h->priv.tcl.cid & 0x0f) | ((fsdi << 4) & 0xf0); - - /* transcieve (with CRC) */ - 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) { - DEBUGP("transcieve of rats failed\n"); - h->priv.tcl.state = TCL_STATE_RATS_SENT; - /* FIXME: retransmit */ - return ret; - } - h->priv.tcl.state = TCL_STATE_ATS_RCVD; - - ret = tcl_parse_ats(h, h->priv.tcl.ats, h->priv.tcl.ats_len); - if (ret < 0) { - DEBUGP("parsing of ats failed\n"); - return ret; - } - - 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_pps(struct rfid_protocol_handle *h) -{ -#if 0 - int ret; - unsigned char ppss[3]; - 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; - - /* FIXME: deal with different speed for each direction */ - DrI = d_to_di(h, Dr); - DsI = d_to_di(h, Ds); - - 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; -} - - -static int -tcl_build_prologue2(struct tcl_handle *th, - unsigned char *prlg, unsigned int *prlg_len, - unsigned char pcb) -{ - *prlg_len = 1; - - *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 (th->flags & TCL_HANDLE_F_CID_USED) { - /* ISO 14443-4:2000(E) Section 7.1.1.2 */ - *prlg |= TCL_PCB_CID_FOLLOWING; - (*prlg_len)++; - prlg[*prlg_len] = th->cid & 0x0f; - } - - /* nad only for I-block (0xc0 == 00) */ - if ((th->flags & TCL_HANDLE_F_NAD_USED) && - ((pcb & 0xc0) == 0x00)) { - /* ISO 14443-4:2000(E) Section 7.1.1.3 */ - /* FIXME: in case of chaining only for first frame */ - *prlg |= TCL_PCB_NAD_FOLLOWING; - prlg[*prlg_len] = th->nad; - (*prlg_len)++; - } - - return 0; -} - -static int -tcl_build_prologue_i(struct tcl_handle *th, - unsigned char *prlg, unsigned int *prlg_len) -{ - /* ISO 14443-4:2000(E) Section 7.1.1.1 */ - return tcl_build_prologue2(th, prlg, prlg_len, 0x02); -} - -static int -tcl_build_prologue_r(struct tcl_handle *th, - unsigned char *prlg, unsigned int *prlg_len, - unsigned int nak) -{ - unsigned char pcb = 0xa2; - /* ISO 14443-4:2000(E) Section 7.1.1.1 */ - - if (nak) - pcb |= 0x10; - - return tcl_build_prologue2(th, prlg, prlg_len, pcb); -} - -static int -tcl_build_prologue_s(struct tcl_handle *th, - unsigned char *prlg, unsigned int *prlg_len) -{ - /* ISO 14443-4:2000(E) Section 7.1.1.1 */ - - /* the only S-block from PCD->PICC is DESELECT, - * well, actually there is the S(WTX) response. */ - return tcl_build_prologue2(th, prlg, prlg_len, 0xc2); -} - -/* FIXME: WTXM implementation */ - -static int tcl_prlg_len(struct tcl_handle *th) -{ - int prlg_len = 1; - - if (th->flags & TCL_HANDLE_F_CID_USED) - prlg_len++; - - if (th->flags & TCL_HANDLE_F_NAD_USED) - prlg_len++; - - return prlg_len; -} - -#define max_net_tx_framesize(x) (x->fsc - tcl_prlg_len(x)) - -static int -tcl_connect(struct rfid_protocol_handle *h) -{ - int ret; - - if (h->priv.tcl.state != TCL_STATE_DESELECTED && - h->priv.tcl.state != TCL_STATE_INITIAL) - return -1; - - switch (h->l2h->l2->id) { - case RFID_LAYER2_ISO14443A: - /* Start Type A T=CL Activation Sequence */ - ret = tcl_request_ats(h); - if (ret < 0) - return ret; - - /* Only do PPS if any non-default divisors supported */ - if (h->priv.tcl.ta & 0x77) { - ret = tcl_do_pps(h); - if (ret < 0) - return ret; - } - break; - case RFID_LAYER2_ISO14443B: - /* initialized T=CL state from Type B Activation Data */ - h->priv.tcl.cid = h->l2h->priv.iso14443b.cid; - h->priv.tcl.fsc = h->l2h->priv.iso14443b.fsc; - h->priv.tcl.fsd = h->l2h->priv.iso14443b.fsd; - h->priv.tcl.fwt = h->l2h->priv.iso14443b.fwt; - - /* what about ta? sfgt? */ - - if (h->l2h->priv.iso14443b.flags & ISO14443B_CID_SUPPORTED) - h->priv.tcl.flags |= TCL_HANDLE_F_CID_SUPPORTED; - if (h->l2h->priv.iso14443b.flags & ISO14443B_NAD_SUPPORTED) - h->priv.tcl.flags |= TCL_HANDLE_F_NAD_SUPPORTED; - - switch (h->l2h->priv.iso14443b.state) { - case ISO14443B_STATE_SELECTED: - h->priv.tcl.state = TCL_STATE_ATS_RCVD; - break; - case ISO14443B_STATE_ATTRIB_SENT: - h->priv.tcl.state = TCL_STATE_RATS_SENT; - break; - } - - /* PUPI will be presented as ATS/historical bytes */ - memcpy(h->priv.tcl.ats, h->l2h->uid, 4); - h->priv.tcl.ats_len = 4; - h->priv.tcl.historical_bytes = h->priv.tcl.ats; - - break; - default: - DEBUGP("unsupported l2: %u\n", h->l2h->l2->id); - return -1; - break; - } - - return 0; -} - -static int -tcl_deselect(struct rfid_protocol_handle *h) -{ - /* ISO 14443-4:2000(E) Section 8 */ - int ret; - unsigned char frame[3]; /* 3 bytes prologue, no information */ - unsigned char rx[3]; - unsigned int rx_len = sizeof(rx); - unsigned int prlg_len; - struct tcl_handle *th = &h->priv.tcl; - - if (th->state != TCL_STATE_ESTABLISHED) { - /* FIXME: not sure whether deselect is possible here, - * probably better send a HLTA? */ - } - - /* build DESELECT S-block */ - ret = tcl_build_prologue_s(th, frame, &prlg_len); - if (ret < 0) - return ret; - - 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) { - /* FIXME: retransmit, HLT(A|B) */ - return ret; - } - - th->state = TCL_STATE_DESELECTED; - - 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) - -static int -tcl_transcieve(struct rfid_protocol_handle *h, - const unsigned char *tx_data, unsigned int tx_len, - unsigned char *rx_data, unsigned int *rx_len, - unsigned int timeout, unsigned int flags) -{ - int ret; - unsigned char *tx_buf, *rx_buf; - unsigned char *_rx_data = rx_data; - unsigned int _rx_len; - unsigned int max_rx_len = *rx_len; /* maximum number of payoload that - caller has requested */ - unsigned int prlg_len; - struct tcl_handle *th = &h->priv.tcl; - - 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 */ - return -1; - } - - tx_buf = malloc(tcl_prlg_len(th) + tx_len); - if (!tx_buf) { - ret = -ENOMEM; - goto out; - } - rx_buf = malloc(tcl_prlg_len(th) + *rx_len); - if (!rx_buf) { - ret = -ENOMEM; - goto out_txb; - } - - if (tcl_build_prologue_i(th, tx_buf, &prlg_len) < 0) { - ret = -1; - goto out_rxb; - } - memcpy(tx_buf + prlg_len, tx_data, tx_len); - - /* intialize to data-to-be-transferred */ - _tx = tx_buf; - _tx_len = tx_len+prlg_len; - _timeout = th->fwt; - _rx_len = *rx_len; - *rx_len = 0; - -do_tx: - ret = h->l2h->l2->fn.transcieve(h->l2h, l2_to_frame(h->l2h->l2->id), - _tx, _tx_len, - rx_buf, &_rx_len, _timeout, 0); - DEBUGP("l2 transcieve finished\n"); - if (ret < 0) - goto out_rxb; - - if ((*rx_buf & 0x01) != h->priv.tcl.toggle) { - DEBUGP("response with wrong toggle bit\n"); - goto out_rxb; - } - - 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) { - DEBUGP("CID %u is not valid\n", *(rx_buf)+1); - goto out_rxb; - } - } - /* set up parameters for next frame in chain */ - if (txed < tx_len) { - /* move tx pointer by the amount of bytes transferred - * in last frame */ - _tx += _tx_len; - _tx_len = (tx_len - txed); - if (_tx_len > max_net_tx_framesize(th)) { - /* not last frame in chain */ - _tx_len = max_net_tx_framesize(th); - } else { - /* last frame in chain */ - } - goto do_tx; - } else { - DEBUGP("Received ACK in response to last frame in " - "chain?!? Expected I-frame.\n"); - ret = -1; - goto out_rxb; - } - } else if (is_s_block(*rx_buf)) { - 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) { - DEBUGP("S-Block with CID but short len\n"); - ret = -1; - goto out_rxb; - } - if (*(rx_buf+1) != h->priv.tcl.cid) { - DEBUGP("CID %u is not valid\n", *(rx_buf)+1); - goto out_rxb; - } - inf = *(rx_buf+2); - } else - inf = *(rx_buf+1); - - if ((*rx_buf & 0x30) != 0x30) { - DEBUGP("S-Block but not WTX?\n"); - ret = -1; - goto out_rxb; - } - inf &= 0x3f; /* only lower 6 bits code WTXM */ - if (inf == 0 || (inf >= 60 && inf <= 63)) { - DEBUGP("WTXM %u is RFU!\n", inf); - ret = -1; - goto out_rxb; - } - - /* Acknowledge WTXM */ - tcl_build_prologue_s(&h->priv.tcl, wtx_resp, &prlg_len); - /* set two bits that make this block a wtx */ - wtx_resp[0] |= 0x30; - wtx_resp[prlg_len] = inf; - _tx = wtx_resp; - _tx_len = prlg_len+1; - _timeout = th->fwt * inf; - - /* start over with next transcieve */ - goto do_tx; /* FIXME: do transcieve locally since we use - totally different buffer */ - - } else if (is_i_block(*rx_buf)) { - unsigned char *inf = rx_buf+1; - unsigned int net_payload_len; - /* we're actually receiving payload data */ - - DEBUGP("I-Block: "); - if (*rx_buf & TCL_PCB_CID_FOLLOWING) { - if (*(rx_buf+1) != h->priv.tcl.cid) { - DEBUGPC("CID %u is not valid\n", *(rx_buf)+1); - goto out_rxb; - } - inf++; - } - if (*rx_buf & TCL_PCB_NAD_FOLLOWING) { - inf++; - } - net_payload_len = _rx_len - (inf - rx_buf); - DEBUGPC("%u bytes\n", net_payload_len); - memcpy(_rx_data, inf, net_payload_len); - /* increment the number of payload bytes that we actually received */ - *rx_len += net_payload_len; - _rx_data += net_payload_len; - - if (*rx_buf & 0x10) { - /* 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; - } - } - -out_rxb: - free(rx_buf); -out_txb: - free(tx_buf); -out: - return ret; -} - -static struct rfid_protocol_handle * -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); - 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); - - /* maximum received ats length equals mru of asic/reader */ - th->priv.tcl.state = TCL_STATE_INITIAL; - th->priv.tcl.ats_len = mru; - th->priv.tcl.toggle = 1; - - th->priv.tcl.fsd = iso14443_fsd_approx(mru); - - return th; -} - -static int -tcl_fini(struct rfid_protocol_handle *ph) -{ - free(ph); - return 0; -} - -struct rfid_protocol rfid_protocol_tcl = { - .id = RFID_PROTOCOL_TCL, - .name = "ISO 14443-4 / T=CL", - .fn = { - .init = &tcl_init, - .open = &tcl_connect, - .transcieve = &tcl_transcieve, - .close = &tcl_deselect, - .fini = &tcl_fini, - }, -}; -- cgit v1.2.3