/* ISO 14443-3 B anticollision implementation
*
- * (C) 2005 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2005-2006 by Harald Welte <laforge@gnumonks.org>
*
*/
*
* 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 <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <errno.h>
-#include <rfid/rfid.h>
-#include <rfid/rfid_layer2.h>
-#include <rfid/rfid_reader.h>
-#include <rfid/rfid_layer2_iso14443b.h>
+#include <librfid/rfid.h>
+#include <librfid/rfid_layer2.h>
+#include <librfid/rfid_reader.h>
+#include <librfid/rfid_layer2_iso14443b.h>
+#include <librfid/rfid_protocol.h>
#include "rfid_iso14443_common.h"
#define ATQB_TIMEOUT ((256*10e6/ISO14443_FREQ_SUBCARRIER) \
+(200*10e6/ISO14443_FREQ_SUBCARRIER))
+#undef ATQB_TIMEOUT
+#define ATQB_TIMEOUT 1
+
static inline int
fwi_to_fwt(struct rfid_layer2_handle *h, unsigned int *fwt, unsigned int fwi)
{
if (atqb->protocol_info.protocol_type == 0x1) {
DEBUGP("we have a T=CL compliant PICC\n");
h->priv.iso14443b.tcl_capable = 1;
+ h->proto_supported = (1 << RFID_PROTOCOL_TCL);
} else {
DEBUGP("we have a T!=CL PICC\n");
h->priv.iso14443b.tcl_capable = 0;
+ /* FIXME: what protocols do we support? */
}
iso14443_fsdi_to_fsd(&h->priv.iso14443b.fsc,
if (is_wup)
reqb[2] |= 0x08;
- ret = h->rh->reader->transcieve(h->rh, RFID_14443B_FRAME_REGULAR,
+ ret = h->rh->reader->transceive(h->rh, RFID_14443B_FRAME_REGULAR,
reqb, sizeof(reqb),
(unsigned char *)&atqb,
&atqb_len, ATQB_TIMEOUT, 0);
h->priv.iso14443b.state = ISO14443B_STATE_REQB_SENT;
if (ret < 0) {
- DEBUGP("error during transcieve of REQB/WUBP\n");
+ DEBUGP("error during transceive of REQB/WUBP\n");
continue;
}
}
static int
-transcieve_attrib(struct rfid_layer2_handle *h, const unsigned char *inf,
+transceive_attrib(struct rfid_layer2_handle *h, const unsigned char *inf,
unsigned int inf_len, unsigned char *rx_data, unsigned int *rx_len)
{
- struct iso14443b_attrib_hdr *attrib;
- unsigned int attrib_size = sizeof(*attrib) + inf_len;
- unsigned char *rx_buf;
+ struct {
+ struct iso14443b_attrib_hdr attrib;
+ char buf[256-3];
+ } _attrib_buf;
+
+ struct iso14443b_attrib_hdr *attrib = &_attrib_buf.attrib;
+ unsigned char rx_buf[256];
unsigned char fsdi;
int ret = 0;
DEBUGP("fsd is %u\n", h->priv.iso14443b.fsd);
- attrib = malloc(attrib_size);
- if (!attrib) {
- perror("attrib_alloc");
- return -1;
- }
-
- DEBUGP("fsd is %u\n", h->priv.iso14443b.fsd);
- rx_buf = malloc(*rx_len+1);
- if (!rx_buf) {
- perror("rx_buf malloc");
- ret = -1;
- goto out_attrib;
- }
+ if (rx_len >= rx_len-1)
+ return -EINVAL;
/* initialize attrib frame */
- memset(attrib, 0, attrib_size);
+ memset(&_attrib_buf, 0, sizeof(_attrib_buf));
if (inf_len)
memcpy((unsigned char *)attrib+sizeof(*attrib), inf, inf_len);
if (h->priv.iso14443b.tcl_capable == 1)
attrib->param3.protocol_type = 0x1;
+ attrib->param4.cid = h->priv.iso14443b.cid & 0xf;
+
*rx_len = *rx_len + 1;
- ret = h->rh->reader->transcieve(h->rh, RFID_14443B_FRAME_REGULAR,
+ ret = h->rh->reader->transceive(h->rh, RFID_14443B_FRAME_REGULAR,
(unsigned char *) attrib,
sizeof(*attrib)+inf_len,
rx_buf, rx_len, h->priv.iso14443b.fwt,
0);
h->priv.iso14443b.state = ISO14443B_STATE_ATTRIB_SENT;
if (ret < 0) {
- DEBUGP("transcieve problem\n");
+ DEBUGP("transceive problem\n");
goto out_rx;
}
if ((rx_buf[0] & 0x0f) != h->priv.iso14443b.cid) {
- DEBUGP("ATTRIB response with invalid CID %u\n",
- rx_buf[0] & 0x0f);
+ DEBUGP("ATTRIB response with invalid CID %u (should be %u)\n",
+ rx_buf[0] & 0x0f, h->priv.iso14443b.cid);
ret = -1;
goto out_rx;
}
memcpy(rx_data, rx_buf+1, *rx_len);
out_rx:
- free(rx_buf);
out_attrib:
- free(attrib);
return ret;
}
hltb[0] = 0x50;
memcpy(hltb+1, h->uid, 4);
- ret = h->rh->reader->transcieve(h->rh, RFID_14443B_FRAME_REGULAR,
+ ret = h->rh->reader->transceive(h->rh, RFID_14443B_FRAME_REGULAR,
hltb, 5,
hltb_resp, &hltb_len,
h->priv.iso14443b.fwt, 0);
h->priv.iso14443b.state = ISO14443B_STATE_HLTB_SENT;
if (ret < 0) {
- DEBUGP("transcieve problem\n");
+ DEBUGP("transceive problem\n");
return ret;
}
if (ret < 0)
return ret;
- ret = transcieve_attrib(handle, NULL, 0, buf, &buf_len);
+ ret = transceive_attrib(handle, NULL, 0, buf, &buf_len);
if (ret < 0)
return ret;
iso14443b_init(struct rfid_reader_handle *rh)
{
int ret;
- struct rfid_layer2_handle *h = malloc(sizeof(*h));
+ struct rfid_layer2_handle *h = malloc_layer2_handle(sizeof(*h));
if (!h)
return NULL;
h->rh = rh;
h->priv.iso14443b.state = ISO14443B_STATE_NONE;
+ /* FIXME: if we want to support multiple PICC's, we need some
+ * fancy allocation scheme for CID's */
+ h->priv.iso14443b.cid = 0;
+
h->priv.iso14443b.fsd = iso14443_fsd_approx(rh->ah->mru);
DEBUGP("fsd is %u\n", h->priv.iso14443b.fsd);
h->priv.iso14443b.tr0 = (256/ISO14443_FREQ_SUBCARRIER)*10e6;
h->priv.iso14443b.tr1 = (200/ISO14443_FREQ_SUBCARRIER)*10e6;
- ret = h->rh->reader->iso14443b.init(h->rh);
+ ret = h->rh->reader->init(h->rh, RFID_LAYER2_ISO14443B);
if (ret < 0) {
DEBUGP("error during reader 14443b init\n");
- free(h);
+ free_layer2_handle(h);
return NULL;
}
static int
iso14443b_fini(struct rfid_layer2_handle *handle)
{
- free(handle);
+ free_layer2_handle(handle);
return 0;
}
static int
-iso14443b_transcieve(struct rfid_layer2_handle *handle,
+iso14443b_transceive(struct rfid_layer2_handle *handle,
enum rfid_frametype frametype,
const unsigned char *tx_buf, unsigned int tx_len,
unsigned char *rx_buf, unsigned int *rx_len,
u_int64_t timeout, unsigned int flags)
{
DEBUGP("transcieving %u bytes, expecting max %u\n", tx_len, *rx_len);
- return handle->rh->reader->transcieve(handle->rh, frametype,
+ return handle->rh->reader->transceive(handle->rh, frametype,
tx_buf, tx_len,
rx_buf, rx_len, timeout, flags);
}
-struct rfid_layer2 rfid_layer2_iso14443b = {
+static int
+iso14443b_getopt(struct rfid_layer2_handle *handle,
+ int optname, void *optval, unsigned int *optlen)
+{
+ unsigned int *opt_ui = optval;
+
+ switch (optname) {
+ case RFID_OPT_14443B_CID:
+ *opt_ui = handle->priv.iso14443b.cid;
+ break;
+ case RFID_OPT_14443B_FSC:
+ *opt_ui = handle->priv.iso14443b.fsc;
+ break;
+ case RFID_OPT_14443B_FSD:
+ *opt_ui = handle->priv.iso14443b.fsd;
+ break;
+ case RFID_OPT_14443B_FWT:
+ *opt_ui = handle->priv.iso14443b.fwt;
+ break;
+ case RFID_OPT_14443B_TR0:
+ *opt_ui = handle->priv.iso14443b.tr0;
+ break;
+ case RFID_OPT_14443B_TR1:
+ *opt_ui = handle->priv.iso14443b.tr1;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ return 0;
+}
+
+static int
+iso14443b_setopt(struct rfid_layer2_handle *handle,
+ int optname, const void *optval, unsigned int optlen)
+{
+ const unsigned int *opt_ui = optval;
+
+ switch (optname) {
+ case RFID_OPT_14443B_CID:
+ handle->priv.iso14443b.cid = (*opt_ui & 0xf);
+ break;
+ defaukt:
+ return -EINVAL;
+ break;
+ }
+ return 0;
+}
+
+
+const struct rfid_layer2 rfid_layer2_iso14443b = {
.id = RFID_LAYER2_ISO14443B,
.name = "ISO 14443-3 B",
.fn = {
.init = &iso14443b_init,
.open = &iso14443b_anticol,
- .transcieve = &iso14443b_transcieve,
+ .transceive = &iso14443b_transceive,
.close = &iso14443b_hltb,
.fini = &iso14443b_fini,
+ .getopt = &iso14443b_getopt,
+ .setopt = &iso14443b_setopt,
},
};