summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am3
-rw-r--r--src/rc632.h10
-rw-r--r--src/rfid_access_mifare_classic.c232
-rw-r--r--src/rfid_asic_rc632.c46
-rw-r--r--src/rfid_layer2_iso15693.c39
-rw-r--r--src/rfid_proto_mifare_classic.c65
-rw-r--r--src/rfid_proto_mifare_ul.c8
7 files changed, 381 insertions, 22 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 86663a4..3e2bf95 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,6 +15,7 @@ L2=rfid_layer2_iso14443a.c rfid_layer2_iso14443b.c rfid_layer2_iso15693.c rfid_i
PROTO=rfid_proto_tcl.c rfid_proto_mifare_ul.c rfid_proto_mifare_classic.c
ASIC=rfid_asic_rc632.c
READER=rfid_reader_openpcd.c
+MISC=rfid_access_mifare_classic.c
if ENABLE_CM5121
READER_CM5121=rfid_reader_cm5121.c
@@ -37,7 +38,7 @@ AM_CFLAGS = -std=gnu99 -D__LIBRFID__ $(AM_CFLAGS_FIRMWARE) $(AM_CFLAGS_STATIC) \
lib_LTLIBRARIES = librfid.la
librfid_la_LDFLAGS = -Wc,-nostartfiles -version-info $(LIBVERSION) -lopenct
-librfid_la_SOURCES = $(CORE) $(L2) $(PROTO) $(ASIC) \
+librfid_la_SOURCES = $(CORE) $(L2) $(PROTO) $(ASIC) $(MISC) \
$(READER) \
$(READER_CM5121) $(READER_LOW_CCID) $(READER_LOW_OPENCT)
diff --git a/src/rc632.h b/src/rc632.h
index ff00df0..c7690ed 100644
--- a/src/rc632.h
+++ b/src/rc632.h
@@ -94,8 +94,12 @@ enum rc632_reg_interrupt {
};
enum rc632_reg_control {
+ RC632_CONTROL_FIFO_FLUSH = 0x01,
+ RC632_CONTROL_TIMER_START = 0x02,
+ RC632_CONTROL_TIMER_STOP = 0x04,
RC632_CONTROL_CRYPTO1_ON = 0x08,
RC632_CONTROL_POWERDOWN = 0x10,
+ RC632_CONTROL_STANDBY = 0x20,
};
enum rc632_reg_error_flag {
@@ -235,3 +239,9 @@ enum rc632_reg_timer_irq {
RC632_IRQ_SET = 0x80,
};
+
+enum rc632_reg_secondary_status {
+ RC632_SEC_ST_TMR_RUNNING = 0x80,
+ RC632_SEC_ST_E2_READY = 0x40,
+ RC632_SEC_ST_CRC_READY = 0x20,
+};
diff --git a/src/rfid_access_mifare_classic.c b/src/rfid_access_mifare_classic.c
new file mode 100644
index 0000000..bd362e1
--- /dev/null
+++ b/src/rfid_access_mifare_classic.c
@@ -0,0 +1,232 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <librfid/rfid.h>
+#include <librfid/rfid_access_mifare_classic.h>
+
+/* parse encoded data structure into c1/c2/c3 */
+int mfcl_compile_access(u_int8_t *encoded,
+ const struct mfcl_access_sect *ac)
+{
+ int b;
+ u_int8_t c1, c2, c3;
+
+ c1 = c2 = c3 = 0;
+
+ for (b = 0; b < 4; b++) {
+ if (ac->block[b] & 0x01)
+ c1 |= (1 << b);
+ if (ac->block[b] & 0x02)
+ c2 |= (1 << b);
+ if (ac->block[b] & 0x04)
+ c3 |= (1 << b);
+ }
+
+ DEBUGP("compile: c1=%u c2=%u c3=%u\n", c1, c2, c3);
+
+ encoded[3] = 0x00;
+ encoded[2] = c2 | (c3 << 4);
+ encoded[1] = (~c3 & 0xf) | (c1 << 4);
+ encoded[0] = (~c1 & 0xf) | ((~c2 & 0xf) << 4);
+
+ return 0;
+}
+
+/* parse mifare classic access conditions from card */
+int mfcl_parse_access(struct mfcl_access_sect *ac, u_int8_t *encoded)
+{
+ int b;
+
+ u_int8_t c1, c2, c3;
+
+ DEBUGP("encoded: %s\n", rfid_hexdump(encoded, 4));
+
+ c1 = encoded[1] >> 4;
+ c2 = encoded[2] & 0xf;
+ c3 = encoded[2] >> 4;
+
+ DEBUGP("c1=0x%x, c2=0x%x, c3=0x%x\n", c1, c2, c3);
+
+ memset(ac, 0, sizeof(*ac));
+ for (b = 0; b < 4; b++) {
+ if (c1 & (1 << b))
+ ac->block[b] = 0x1;
+ if (c2 & (1 << b))
+ ac->block[b] |= 0x2;
+ if (c3 & (1 << b))
+ ac->block[b] |= 0x4;
+ };
+
+ /* FIXME: verify the inverted access bits */
+
+ return 0;
+}
+
+
+/* functions below here are for our own internal decoded (orthogonal)
+ * format of access bits */
+
+/* In the order of the table 3.7.3 in MFCL Product Specification Rev. 5.1 */
+static const struct mfcl_access_exp_block mfcl_exp_data[] = {
+ [0] = {
+ .read = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ .write = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ .inc = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ .dec = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ },
+ [2] = {
+ .read = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ .write = MFCL_ACCESS_NEVER,
+ .inc = MFCL_ACCESS_NEVER,
+ .dec = MFCL_ACCESS_NEVER,
+ },
+ [1] = {
+ .read = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ .write = MFCL_ACCESS_KEY_B,
+ .inc = MFCL_ACCESS_NEVER,
+ .dec = MFCL_ACCESS_NEVER,
+ },
+ [3] = {
+ .read = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ .write = MFCL_ACCESS_KEY_B,
+ .inc = MFCL_ACCESS_KEY_B,
+ .dec = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ },
+ [4] = {
+ .read = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ .write = MFCL_ACCESS_NEVER,
+ .inc = MFCL_ACCESS_NEVER,
+ .dec = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ },
+ [6] = {
+ .read = MFCL_ACCESS_KEY_B,
+ .write = MFCL_ACCESS_KEY_B,
+ .inc = MFCL_ACCESS_NEVER,
+ .dec = MFCL_ACCESS_NEVER,
+ },
+ [5] = {
+ .read = MFCL_ACCESS_KEY_B,
+ .write = MFCL_ACCESS_NEVER,
+ .inc = MFCL_ACCESS_NEVER,
+ .dec = MFCL_ACCESS_NEVER,
+ },
+ [7] = {
+ .read = MFCL_ACCESS_NEVER,
+ .write = MFCL_ACCESS_NEVER,
+ .inc = MFCL_ACCESS_NEVER,
+ .dec = MFCL_ACCESS_NEVER,
+ },
+};
+
+static const struct mfcl_access_exp_acc mfcl_exp_trailer[] = {
+ [0] = {
+ .key_a_rd = MFCL_ACCESS_NEVER,
+ .key_a_wr = MFCL_ACCESS_KEY_A,
+ .acc_rd = MFCL_ACCESS_KEY_A,
+ .acc_wr = MFCL_ACCESS_NEVER,
+ .key_b_rd = MFCL_ACCESS_KEY_A,
+ .key_b_wr = MFCL_ACCESS_KEY_A,
+ },
+ [2] = {
+ .key_a_rd = MFCL_ACCESS_NEVER,
+ .key_a_wr = MFCL_ACCESS_NEVER,
+ .acc_rd = MFCL_ACCESS_KEY_A,
+ .acc_wr = MFCL_ACCESS_NEVER,
+ .key_b_rd = MFCL_ACCESS_KEY_A,
+ .key_b_wr = MFCL_ACCESS_NEVER,
+ },
+ [1] = {
+ .key_a_rd = MFCL_ACCESS_NEVER,
+ .key_a_wr = MFCL_ACCESS_KEY_B,
+ .acc_rd = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ .acc_wr = MFCL_ACCESS_NEVER,
+ .key_b_rd = MFCL_ACCESS_NEVER,
+ .key_b_wr = MFCL_ACCESS_KEY_B,
+ },
+ [3] = {
+ .key_a_rd = MFCL_ACCESS_NEVER,
+ .key_a_wr = MFCL_ACCESS_NEVER,
+ .acc_rd = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ .acc_wr = MFCL_ACCESS_NEVER,
+ .key_b_rd = MFCL_ACCESS_NEVER,
+ .key_b_wr = MFCL_ACCESS_NEVER,
+ },
+ [4] = {
+ .key_a_rd = MFCL_ACCESS_NEVER,
+ .key_a_wr = MFCL_ACCESS_KEY_A,
+ .acc_rd = MFCL_ACCESS_KEY_A,
+ .acc_wr = MFCL_ACCESS_KEY_A,
+ .key_b_rd = MFCL_ACCESS_KEY_A,
+ .key_b_wr = MFCL_ACCESS_KEY_A,
+ },
+ [6] = {
+ .key_a_rd = MFCL_ACCESS_NEVER,
+ .key_a_wr = MFCL_ACCESS_KEY_B,
+ .acc_rd = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ .acc_wr = MFCL_ACCESS_KEY_B,
+ .key_b_rd = MFCL_ACCESS_NEVER,
+ .key_b_wr = MFCL_ACCESS_KEY_B,
+ },
+ [5] = {
+ .key_a_rd = MFCL_ACCESS_NEVER,
+ .key_a_wr = MFCL_ACCESS_NEVER,
+ .acc_rd = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ .acc_wr = MFCL_ACCESS_KEY_B,
+ .key_b_rd = MFCL_ACCESS_NEVER,
+ .key_b_wr = MFCL_ACCESS_NEVER,
+ },
+ [7] = {
+ .key_a_rd = MFCL_ACCESS_NEVER,
+ .key_a_wr = MFCL_ACCESS_NEVER,
+ .acc_rd = MFCL_ACCESS_KEY_A | MFCL_ACCESS_KEY_B,
+ .acc_wr = MFCL_ACCESS_NEVER,
+ .key_b_rd = MFCL_ACCESS_NEVER,
+ .key_b_wr = MFCL_ACCESS_NEVER,
+ },
+};
+
+const char *mfcl_access_str[] = {
+ [MFCL_ACCESS_NEVER] = "NEVER",
+ [MFCL_ACCESS_KEY_A] = "A",
+ [MFCL_ACCESS_KEY_B] = "B",
+ [MFCL_ACCESS_KEY_A|MFCL_ACCESS_KEY_B] = "A|B",
+};
+
+void mfcl_access_to_exp(struct mfcl_access_exp_sect *exp,
+ const struct mfcl_access_sect *sect)
+{
+ int b;
+ for (b = 0; b < 3; b++)
+ exp->block[b] = mfcl_exp_data[sect->block[b]];
+ exp->acc = mfcl_exp_trailer[sect->block[3]];
+}
+
+char *mfcl_access_exp_stringify(const struct mfcl_access_exp_block *exp)
+{
+ static char buf[80];
+
+ sprintf(buf, "READ: %s, WRITE: %s, INC: %s, DEC: %s",
+ mfcl_access_str[exp->read],
+ mfcl_access_str[exp->write],
+ mfcl_access_str[exp->inc],
+ mfcl_access_str[exp->dec]);
+ return buf;
+}
+
+char *mfcl_access_exp_acc_stringify(const struct mfcl_access_exp_acc *acc)
+{
+ static char buf[80];
+
+ sprintf(buf, "KEY_A_RD: %s, KEY_A_WR: %s, ACC_RD: %s, ACC_WR: %s, "
+ "KEY_B_RD: %s, KEY_B_WR: %s",
+ mfcl_access_str[acc->key_a_rd],
+ mfcl_access_str[acc->key_a_wr],
+ mfcl_access_str[acc->acc_rd],
+ mfcl_access_str[acc->acc_wr],
+ mfcl_access_str[acc->key_b_rd],
+ mfcl_access_str[acc->key_b_wr]);
+ return buf;
+}
+
diff --git a/src/rfid_asic_rc632.c b/src/rfid_asic_rc632.c
index b421ca6..2890d6d 100644
--- a/src/rfid_asic_rc632.c
+++ b/src/rfid_asic_rc632.c
@@ -38,7 +38,7 @@
//#include "rc632_14443a.h"
-#define RC632_TMO_AUTH1 14000
+#define RC632_TMO_AUTH1 140
#define ENTER() DEBUGP("entering\n")
const struct rfid_asic rc632;
@@ -566,6 +566,13 @@ rc632_init(struct rfid_asic_handle *ah)
if (ret < 0)
return ret;
+ /* switch off rf */
+ ret = rc632_turn_off_rf(ah);
+ if (ret < 0)
+ return ret;
+
+ usleep(100000);
+
/* switch on rf */
ret = rc632_turn_on_rf(ah);
if (ret < 0)
@@ -639,7 +646,8 @@ rc632_iso14443a_init(struct rfid_asic_handle *handle)
// FIXME: some fifo work (drain fifo?)
/* flush fifo (our way) */
- ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01);
+ ret = rc632_reg_write(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_FIFO_FLUSH);
ret = rc632_reg_write(handle, RC632_REG_TX_CONTROL,
(RC632_TXCTRL_TX1_RF_EN |
@@ -1065,7 +1073,8 @@ static int rc632_iso14443b_init(struct rfid_asic_handle *handle)
// FIXME: some FIFO work
/* flush fifo (our way) */
- ret = rc632_reg_write(handle, RC632_REG_CONTROL, 0x01);
+ ret = rc632_reg_write(handle, RC632_REG_CONTROL,
+ RC632_CONTROL_FIFO_FLUSH);
if (ret < 0)
return ret;
@@ -1453,7 +1462,8 @@ rc632_mifare_set_key(struct rfid_asic_handle *h, const u_int8_t *key)
if (ret < 0)
return ret;
- ret = rc632_fifo_write(h, RFID_MIFARE_KEY_CODED_LEN, coded_key, 0x03);
+ /* Terminate probably running command */
+ ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_IDLE);
if (ret < 0)
return ret;
@@ -1461,6 +1471,10 @@ rc632_mifare_set_key(struct rfid_asic_handle *h, const u_int8_t *key)
if (ret < 0)
return ret;
+ ret = rc632_fifo_write(h, RFID_MIFARE_KEY_CODED_LEN, coded_key, 0x03);
+ if (ret < 0)
+ return ret;
+
ret = rc632_wait_idle(h, RC632_TMO_AUTH1);
if (ret < 0)
return ret;
@@ -1483,8 +1497,10 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno,
struct mifare_authcmd acmd;
u_int8_t reg;
- if (cmd != RFID_CMD_MIFARE_AUTH1A && cmd != RFID_CMD_MIFARE_AUTH1B)
+ if (cmd != RFID_CMD_MIFARE_AUTH1A && cmd != RFID_CMD_MIFARE_AUTH1B) {
+ DEBUGP("invalid auth command\n");
return -EINVAL;
+ }
/* Initialize acmd */
acmd.block_address = block & 0xff;
@@ -1492,9 +1508,16 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno,
//acmd.serno = htonl(serno);
acmd.serno = serno;
+#if 1
/* Clear Rx CRC */
ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY,
RC632_CR_RX_CRC_ENABLE);
+#else
+ /* Clear Rx CRC, Set Tx CRC and Odd Parity */
+ ret = rc632_reg_write(h, RC632_REG_CHANNEL_REDUNDANCY,
+ RC632_CR_TX_CRC_ENABLE | RC632_CR_PARITY_ODD |
+ RC632_CR_PARITY_ENABLE);
+#endif
if (ret < 0)
return ret;
@@ -1504,8 +1527,10 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno,
return ret;
ret = rc632_reg_write(h, RC632_REG_COMMAND, RC632_CMD_AUTHENT1);
- if (ret < 0)
+ if (ret < 0) {
+ DEBUGP("error during AUTHENT1");
return ret;
+ }
/* Wait until transmitter is idle */
ret = rc632_wait_idle(h, RC632_TMO_AUTH1);
@@ -1515,8 +1540,10 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno,
ret = rc632_reg_read(h, RC632_REG_SECONDARY_STATUS, &reg);
if (ret < 0)
return ret;
- if (reg & 0x07)
+ if (reg & 0x07) {
+ DEBUGP("bitframe?");
return -EIO;
+ }
/* Clear Tx CRC */
ret = rc632_clear_bits(h, RC632_REG_CHANNEL_REDUNDANCY,
@@ -1539,11 +1566,12 @@ rc632_mifare_auth(struct rfid_asic_handle *h, u_int8_t cmd, u_int32_t serno,
if (ret < 0)
return ret;
- if (!(reg & RC632_CONTROL_CRYPTO1_ON))
+ if (!(reg & RC632_CONTROL_CRYPTO1_ON)) {
+ DEBUGP("authentication not successful");
return -EACCES;
+ }
return 0;
-
}
/* transceive regular frame */
diff --git a/src/rfid_layer2_iso15693.c b/src/rfid_layer2_iso15693.c
index dab7418..f5da8c2 100644
--- a/src/rfid_layer2_iso15693.c
+++ b/src/rfid_layer2_iso15693.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <errno.h>
#include <librfid/rfid.h>
#include <librfid/rfid_layer2.h>
@@ -92,6 +93,42 @@ iso15693_anticol(struct rfid_layer2_handle *handle)
return -1;
}
+static int
+iso15693_getopt(struct rfid_layer2_handle *handle,
+ int optname, void *optval, unsigned int optlen)
+{
+ switch (optname) {
+ case RFID_OPT_15693_MOD_DEPTH:
+ case RFID_OPT_15693_VCD_CODING:
+ case RFID_OPT_15693_VICC_SUBC:
+ case RFID_OPT_15693_VICC_SPEED:
+ default:
+ return -EINVAL;
+ break;
+ }
+ return 0;
+}
+
+static int
+iso15693_setopt(struct rfid_layer2_handle *handle, int optname,
+ const void *optval, unsigned int optlen)
+{
+ switch (optname) {
+ case RFID_OPT_15693_MOD_DEPTH:
+ case RFID_OPT_15693_VCD_CODING:
+ case RFID_OPT_15693_VICC_SUBC:
+ case RFID_OPT_15693_VICC_SPEED:
+ default:
+ return -EINVAL;
+ break;
+ }
+ return 0;
+}
+
+static int transceive_inventory(struct rfid_layer2_handle *l2h)
+{
+}
+
static struct rfid_layer2_handle *
iso15693_init(struct rfid_reader_handle *rh)
{
@@ -129,6 +166,8 @@ const struct rfid_layer2 rfid_layer2_iso15693 = {
//.transceive = &iso15693_transceive,
//.close = &iso14443a_hlta,
.fini = &iso15693_fini,
+ .setopt = &iso15693_setopt,
+ .getopt = &iso15693_getopt,
},
};
diff --git a/src/rfid_proto_mifare_classic.c b/src/rfid_proto_mifare_classic.c
index d45eefc..4032b80 100644
--- a/src/rfid_proto_mifare_classic.c
+++ b/src/rfid_proto_mifare_classic.c
@@ -85,23 +85,57 @@ mfcl_write(struct rfid_protocol_handle *ph, unsigned int page,
unsigned int rx_len;
int ret;
- if (tx_len != 16 || page > MIFARE_CL_PAGE_MAX)
+ if (page > MIFARE_CL_PAGE_MAX)
return -EINVAL;
- tx[0] = MIFARE_CL_CMD_WRITE16;
- tx[1] = page & 0xff;
+ if (tx_len != 16 && tx_len != 4)
+ return -EINVAL;
+
+ if (tx_len == 16) {
+ tx[0] = MIFARE_CL_CMD_WRITE16;
+ tx[1] = page & 0xff;
- memcpy(tx+2, tx_data, 16);
+ ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx,
+ 2, rx, &rx_len,
+ MIFARE_CL_WRITE_FWT, 0);
+ if (ret < 0)
+ return ret;
- ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx,
- sizeof(tx), rx, &rx_len,
- MIFARE_CL_WRITE_FWT, 0);
-
- if (ret < 0)
- return ret;
+ ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx_data,
+ tx_len, rx, &rx_len,
+ MIFARE_CL_WRITE_FWT, 0);
+ if (ret < 0)
+ return ret;
+
+ if (rx[0] != MIFARE_UL_RESP_ACK)
+ return -EIO;
+
+ ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx,
+ sizeof(tx), rx, &rx_len,
+ MIFARE_CL_WRITE_FWT, 0);
+ if (ret < 0)
+ return ret;
+
+ if (rx[0] != MIFARE_UL_RESP_ACK)
+ return -EIO;
- if (rx[0] != MIFARE_UL_RESP_ACK)
- return -EIO;
+ } else if (tx_len == 4) {
+
+ tx[0] = MIFARE_CL_CMD_WRITE4;
+ tx[1] = page & 0xff;
+
+ memcpy(tx+2, tx_data, 4);
+
+ ret = rfid_layer2_transceive(ph->l2h, RFID_MIFARE_FRAME, tx,
+ 2+4, rx, &rx_len,
+ MIFARE_CL_WRITE_FWT, 0);
+ if (ret < 0)
+ return ret;
+
+ if (rx[0] != MIFARE_UL_RESP_ACK)
+ return -EIO;
+
+ }
return ret;
}
@@ -110,6 +144,13 @@ static struct rfid_protocol_handle *
mfcl_init(struct rfid_layer2_handle *l2h)
{
struct rfid_protocol_handle *ph;
+
+ if (l2h->l2->id != RFID_LAYER2_ISO14443A)
+ return NULL;
+
+ if (l2h->uid_len != 4)
+ return NULL;
+
ph = malloc_protocol_handle(sizeof(struct rfid_protocol_handle));
return ph;
}
diff --git a/src/rfid_proto_mifare_ul.c b/src/rfid_proto_mifare_ul.c
index 0ea55d2..8981b5e 100644
--- a/src/rfid_proto_mifare_ul.c
+++ b/src/rfid_proto_mifare_ul.c
@@ -112,6 +112,14 @@ static struct rfid_protocol_handle *
mful_init(struct rfid_layer2_handle *l2h)
{
struct rfid_protocol_handle *ph;
+
+ if (l2h->l2->id != RFID_LAYER2_ISO14443A)
+ return NULL;
+
+ /* according to "Functional Specification Rev. 3.0 */
+ if (l2h->uid_len != 7)
+ return NULL;
+
ph = malloc_protocol_handle(sizeof(struct rfid_protocol_handle));
return ph;
}
personal git repositories of Harald Welte. Your mileage may vary