summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/rfid.c52
-rw-r--r--src/rfid_layer2.c43
-rw-r--r--src/rfid_layer2_iso14443a.c6
-rw-r--r--src/rfid_layer2_iso14443b.c71
-rw-r--r--src/rfid_reader_cm5121.c10
-rw-r--r--src/rfid_reader_openpcd.c8
-rw-r--r--src/rfid_scan.c113
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
diff --git a/src/rfid.c b/src/rfid.c
index b90043f..ba166a2 100644
--- a/src/rfid.c
+++ b/src/rfid.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;
+}
personal git repositories of Harald Welte. Your mileage may vary