diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/rfid.c | 52 | ||||
-rw-r--r-- | src/rfid_layer2.c | 43 | ||||
-rw-r--r-- | src/rfid_layer2_iso14443a.c | 6 | ||||
-rw-r--r-- | src/rfid_layer2_iso14443b.c | 71 | ||||
-rw-r--r-- | src/rfid_reader_cm5121.c | 10 | ||||
-rw-r--r-- | src/rfid_reader_openpcd.c | 8 | ||||
-rw-r--r-- | src/rfid_scan.c | 113 |
8 files changed, 289 insertions, 16 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 04d17d4..c0cbfbe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,7 +5,7 @@ AM_CFLAGS = -std=gnu99 lib_LTLIBRARIES = librfid.la -CORE=rfid.c rfid_layer2.c rfid_protocol.c rfid_reader.c +CORE=rfid.c rfid_layer2.c rfid_protocol.c rfid_reader.c rfid_scan.c L2=rfid_layer2_iso14443a.c rfid_layer2_iso14443b.c rfid_layer2_iso15693.c rfid_iso14443_common.c PROTO=rfid_proto_tcl.c rfid_proto_mifare_ul.c rfid_proto_mifare_classic.c READER=rfid_reader_cm5121.c rfid_asic_rc632.c rfid_reader_openpcd.c @@ -1,4 +1,6 @@ -/* +/* librfid core + * (C) 2005-2006 by Harald Welte <laforge@gnumonks.org> + * * 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 @@ -40,6 +42,54 @@ rfid_hexdump(const void *data, unsigned int len) return string; } +#if 0 +int rfid_setopt(struct rfid_handle *rh, unsigned int level, + unsigned int optname, + const void *opt, unsigned int *optlen) +{ + switch (level) { + case RFID_LEVEL_ASIC: + case RFID_LEVEL_READER: + return -EINVAL; + break; + case RFID_LEVEL_LAYER2: + return rfid_layer2_setopt(optname, opt, optlen); + break; + case RFID_LEVEL_LAYER3: + return rfid_layer3_setopt(optname, opt, optlen); + break; + default: + return -EINVAL; + break; + } + + return 0; +} + +int rfid_getopt(struct rfid_handle *rh, unsigned int level, + unsigned int optname, + void *opt, unsigned int *optlen) +{ + switch (level) { + case RFID_LEVEL_ASIC: + case RFID_LEVEL_READER: + return -EINVAL; + break; + case RFID_LEVEL_LAYER2: + return rfid_layer2_getopt(optname, opt, optlen); + break; + case RFID_LEVEL_LAYER3: + return rfid_layer3_getopt(optname, opt, optlen); + break; + default: + return -EINVAL; + break; + } + + return 0; +} +#endif + int rfid_init() { rfid_reader_register(&rfid_reader_cm5121); diff --git a/src/rfid_layer2.c b/src/rfid_layer2.c index eef0560..7461d87 100644 --- a/src/rfid_layer2.c +++ b/src/rfid_layer2.c @@ -1,5 +1,5 @@ /* librfid - layer 2 protocol handler - * (C) 2005 by Harald Welte <laforge@gnumonks.org> + * (C) 2005-2006 by Harald Welte <laforge@gnumonks.org> */ /* @@ -92,18 +92,43 @@ int rfid_layer2_getopt(struct rfid_layer2_handle *ph, int optname, void *optval, unsigned int *optlen) { - if (!ph->l2->fn.getopt) - return -EINVAL; - - return ph->l2->fn.getopt(ph, optname, optval, optlen); + if (optname >> 16 == 0) { + unsigned char *optchar = optval; + + switch (optname) { + case RFID_OPT_LAYER2_UID: + if (ph->uid_len < *optlen) + *optlen = ph->uid_len; + memcpy(optchar, ph->uid, *optlen); + break; + default: + return -EINVAL; + break; + } + } else { + if (!ph->l2->fn.getopt) + return -EINVAL; + + return ph->l2->fn.getopt(ph, optname, optval, optlen); + } + return 0; } int rfid_layer2_setopt(struct rfid_layer2_handle *ph, int optname, const void *optval, unsigned int optlen) { - if (!ph->l2->fn.setopt) - return -EINVAL; - - return ph->l2->fn.setopt(ph, optname, optval, optlen); + if (optname >> 16 == 0) { + switch (optname) { + default: + return -EINVAL; + break; + } + } else { + if (!ph->l2->fn.setopt) + return -EINVAL; + + return ph->l2->fn.setopt(ph, optname, optval, optlen); + } + return 0; } diff --git a/src/rfid_layer2_iso14443a.c b/src/rfid_layer2_iso14443a.c index a83c71a..7ebc240 100644 --- a/src/rfid_layer2_iso14443a.c +++ b/src/rfid_layer2_iso14443a.c @@ -1,6 +1,6 @@ /* ISO 14443-3 A anticollision implementation * - * (C) 2005 by Harald Welte <laforge@gnumonks.org> + * (C) 2005-2006 by Harald Welte <laforge@gnumonks.org> * */ @@ -28,6 +28,7 @@ #include <librfid/rfid_layer2.h> #include <librfid/rfid_reader.h> #include <librfid/rfid_layer2_iso14443a.h> +#include <librfid/rfid_protocol.h> #define TIMEOUT 1236 @@ -225,9 +226,12 @@ cascade: if (sak[0] & 0x20) { DEBUGP("we have a T=CL compliant PICC\n"); + handle->proto_supported = 1 << RFID_PROTOCOL_TCL; h->tcl_capable = 1; } else { DEBUGP("we have a T!=CL PICC\n"); + handle->proto_supported = (1 << RFID_PROTOCOL_MIFARE_UL)| + (1 << RFID_PROTOCOL_MIFARE_CLASSIC); h->tcl_capable = 0; } diff --git a/src/rfid_layer2_iso14443b.c b/src/rfid_layer2_iso14443b.c index 454df0a..8227a32 100644 --- a/src/rfid_layer2_iso14443b.c +++ b/src/rfid_layer2_iso14443b.c @@ -1,6 +1,6 @@ /* ISO 14443-3 B anticollision implementation * - * (C) 2005 by Harald Welte <laforge@gnumonks.org> + * (C) 2005-2006 by Harald Welte <laforge@gnumonks.org> * */ @@ -22,17 +22,22 @@ #include <stdlib.h> #include <unistd.h> #include <string.h> +#include <errno.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) { @@ -79,9 +84,11 @@ parse_atqb(struct rfid_layer2_handle *h, struct iso14443b_atqb *atqb) 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, @@ -199,6 +206,8 @@ transceive_attrib(struct rfid_layer2_handle *h, const unsigned char *inf, 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->transceive(h->rh, RFID_14443B_FRAME_REGULAR, (unsigned char *) attrib, @@ -212,8 +221,8 @@ transceive_attrib(struct rfid_layer2_handle *h, const unsigned char *inf, } 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; } @@ -294,6 +303,10 @@ iso14443b_init(struct rfid_reader_handle *rh) 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); @@ -331,6 +344,56 @@ iso14443b_transceive(struct rfid_layer2_handle *handle, rx_buf, rx_len, timeout, flags); } +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; +} + + struct rfid_layer2 rfid_layer2_iso14443b = { .id = RFID_LAYER2_ISO14443B, .name = "ISO 14443-3 B", @@ -340,5 +403,7 @@ struct rfid_layer2 rfid_layer2_iso14443b = { .transceive = &iso14443b_transceive, .close = &iso14443b_hltb, .fini = &iso14443b_fini, + .getopt = &iso14443b_getopt, + .setopt = &iso14443b_setopt, }, }; diff --git a/src/rfid_reader_cm5121.c b/src/rfid_reader_cm5121.c index ab1e701..a9907ad 100644 --- a/src/rfid_reader_cm5121.c +++ b/src/rfid_reader_cm5121.c @@ -1,6 +1,6 @@ /* Omnikey CardMan 5121 specific RC632 transport layer * - * (C) 2005 by Harald Welte <laforge@gnumonks.org> + * (C) 2005-2006 by Harald Welte <laforge@gnumonks.org> * * The 5121 is an Atmel AT89C5122 based USB CCID reader (probably the same * design like the 3121). It's CL RC632 is connected via address/data bus, @@ -37,6 +37,8 @@ #include <librfid/rfid_asic.h> #include <librfid/rfid_asic_rc632.h> #include <librfid/rfid_reader_cm5121.h> +#include <librfid/rfid_layer2.h> +#include <librfid/rfid_protocol.h> #include "cm5121_source.h" @@ -360,6 +362,12 @@ struct rfid_reader rfid_reader_cm5121 = { .open = &cm5121_open, .close = &cm5121_close, .transceive = &cm5121_transceive, + .l2_supported = (1 << RFID_LAYER2_ISO14443A) | + (1 << RFID_LAYER2_ISO14443B) | + (1 << RFID_LAYER2_ISO15693), + .proto_supported = (1 << RFID_PROTOCOL_TCL) | + (1 << RFID_PROTOCOL_MIFARE_UL) | + (1 << RFID_PROTOCOL_MIFARE_CLASSIC), .iso14443a = { .init = &cm5121_14443a_init, .transceive_sf = &cm5121_transceive_sf, diff --git a/src/rfid_reader_openpcd.c b/src/rfid_reader_openpcd.c index 51852f0..053a711 100644 --- a/src/rfid_reader_openpcd.c +++ b/src/rfid_reader_openpcd.c @@ -39,6 +39,8 @@ #include <librfid/rfid_asic.h> #include <librfid/rfid_asic_rc632.h> #include <librfid/rfid_reader_openpcd.h> +#include <librfid/rfid_layer2.h> +#include <librfid/rfid_protocol.h> /* FIXME */ #include "rc632.h" @@ -391,6 +393,12 @@ struct rfid_reader rfid_reader_openpcd = { .open = &openpcd_open, .close = &openpcd_close, .transceive = &openpcd_transceive, + .l2_supported = (1 << RFID_LAYER2_ISO14443A) | + (1 << RFID_LAYER2_ISO14443B) | + (1 << RFID_LAYER2_ISO15693), + .proto_supported = (1 << RFID_PROTOCOL_TCL) | + (1 << RFID_PROTOCOL_MIFARE_UL) | + (1 << RFID_PROTOCOL_MIFARE_CLASSIC), .iso14443a = { .init = &openpcd_14443a_init, .transceive_sf = &openpcd_transceive_sf, diff --git a/src/rfid_scan.c b/src/rfid_scan.c new file mode 100644 index 0000000..1abb4df --- /dev/null +++ b/src/rfid_scan.c @@ -0,0 +1,113 @@ +/* RFID scanning implementation + * + * (C) 2006 by Harald Welte <laforge@gnumonks.org> + * + */ + +/* + * 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 <librfid/rfid.h> +#include <librfid/rfid_layer2.h> +#include <librfid/rfid_reader.h> +#include <librfid/rfid_protocol.h> + +static struct rfid_layer2_handle * +rfid_layer2_scan1(struct rfid_reader_handle *rh, int l2) +{ + struct rfid_layer2_handle *l2h; + + if (rh->reader->l2_supported & (1 << l2)) { + l2h = rfid_layer2_init(rh, l2); + if (!l2h) + return NULL; + if (rfid_layer2_open(l2h) < 0) { + rfid_layer2_fini(l2h); + return NULL; + } else + return l2h; + } + + return NULL; +} + +static struct rfid_layer2_handle * +rfid_layer2_scan(struct rfid_reader_handle *rh) +{ + struct rfid_layer2_handle *l2h; + int i; + +#define RFID_LAYER2_MAX 16 + for (i = 0; i < RFID_LAYER2_MAX; i++) { + l2h = rfid_layer2_scan1(rh, i); + if (l2h) + return l2h; + } + + return NULL; +} + +static struct rfid_protocol_handle * +rfid_protocol_scan1(struct rfid_layer2_handle *l2h, int proto) +{ + struct rfid_protocol_handle *ph; + + if (l2h->rh->reader->proto_supported & (1 << proto) && + l2h->proto_supported & (1 << proto)) { + ph = rfid_protocol_init(l2h, proto); + if (!ph) + return NULL; + if (rfid_protocol_open(ph) < 0) { + rfid_protocol_fini(ph); + return NULL; + } else + return ph; + } + + return NULL; +} + +static struct rfid_protocol_handle * +rfid_protocol_scan(struct rfid_layer2_handle *l2h) +{ + struct rfid_protocol_handle *ph; + int i; + +#define RFID_PROTOCOL_MAX 16 + for (i = 0; i < RFID_PROTOCOL_MAX; i++) { + ph = rfid_protocol_scan1(l2h, i); + if (ph) + return ph; + } + + return NULL; +} + +/* Scan for any RFID transponder within range of the given reader. + * Abort after the first successfully found transponder. */ +int rfid_scan(struct rfid_reader_handle *rh, + struct rfid_layer2_handle **l2h, + struct rfid_protocol_handle **ph) +{ + *l2h = rfid_layer2_scan(rh); + if (!*l2h) + return 0; + + *ph = rfid_protocol_scan(l2h); + if (!*ph) + return 2; + + return 3; +} |