From f0a3a3f8c4f39dfacf2d370bd23b27cd5b3358bf Mon Sep 17 00:00:00 2001 From: laforge Date: Fri, 1 Dec 2006 13:29:00 +0000 Subject: - add size detection for mifare classic / ultralight - add possibility to obtain ATQA via getopt - fix default -EINVAL return of tcl getopt git-svn-id: https://svn.gnumonks.org/trunk/librfid@1930 e0336214-984f-0b4b-a45f-81c69e1f0ede --- include/librfid/rfid_layer2_iso14443a.h | 2 ++ include/librfid/rfid_protocol.h | 1 + include/librfid/rfid_protocol_mifare_classic.h | 4 +++ src/rfid_layer2_iso14443a.c | 35 ++++++++++++++++++++------ src/rfid_proto_mifare_classic.c | 30 ++++++++++++++++++++++ src/rfid_proto_mifare_ul.c | 28 +++++++++++++++++++++ src/rfid_proto_tcl.c | 2 ++ src/rfid_protocol.c | 1 - utils/librfid-tool.c | 7 ++++++ 9 files changed, 101 insertions(+), 9 deletions(-) diff --git a/include/librfid/rfid_layer2_iso14443a.h b/include/librfid/rfid_layer2_iso14443a.h index 283e6b6..b9ef954 100644 --- a/include/librfid/rfid_layer2_iso14443a.h +++ b/include/librfid/rfid_layer2_iso14443a.h @@ -4,6 +4,7 @@ enum rfid_14443a_opt { RFID_OPT_14443A_SPEED_RX = 0x00010001, RFID_OPT_14443A_SPEED_TX = 0x00010002, + RFID_OPT_14443A_ATQA = 0x00010003, }; enum rfid_14443_opt_speed { @@ -56,6 +57,7 @@ struct iso14443a_handle { unsigned int state; unsigned int level; unsigned int tcl_capable; + struct iso14443a_atqa atqa; }; enum iso14443a_level { diff --git a/include/librfid/rfid_protocol.h b/include/librfid/rfid_protocol.h index fd649ef..06f704f 100644 --- a/include/librfid/rfid_protocol.h +++ b/include/librfid/rfid_protocol.h @@ -45,6 +45,7 @@ enum rfid_protocol_id { enum rfid_protocol_opt { RFID_OPT_PROTO_ID, + RFID_OPT_PROTO_SIZE = 0x10000001, }; #ifdef __LIBRFID__ diff --git a/include/librfid/rfid_protocol_mifare_classic.h b/include/librfid/rfid_protocol_mifare_classic.h index 99c447d..b20a028 100644 --- a/include/librfid/rfid_protocol_mifare_classic.h +++ b/include/librfid/rfid_protocol_mifare_classic.h @@ -17,6 +17,10 @@ #define RFID_CMD_MIFARE_AUTH1A 0x60 #define RFID_CMD_MIFARE_AUTH1B 0x61 +enum rfid_proto_mfcl_opt { + RFID_OPT_P_MFCL_SIZE = 0x10000001, +}; + #ifdef __LIBRFID__ extern const struct rfid_protocol rfid_protocol_mfcl; diff --git a/src/rfid_layer2_iso14443a.c b/src/rfid_layer2_iso14443a.c index 2ee7eb0..429577c 100644 --- a/src/rfid_layer2_iso14443a.c +++ b/src/rfid_layer2_iso14443a.c @@ -100,22 +100,22 @@ iso14443a_anticol(struct rfid_layer2_handle *handle) int ret; unsigned int uid_size; struct iso14443a_handle *h = &handle->priv.iso14443a; - struct iso14443a_atqa atqa; + struct iso14443a_atqa *atqa = &h->atqa; struct iso14443a_anticol_cmd acf; unsigned int bit_of_col; unsigned char sak[3]; unsigned int rx_len = sizeof(sak); - char *aqptr = (char *) &atqa; + char *aqptr = (char *) atqa; memset(handle->uid, 0, sizeof(handle->uid)); memset(sak, 0, sizeof(sak)); - memset(&atqa, 0, sizeof(atqa)); + memset(atqa, 0, sizeof(&atqa)); memset(&acf, 0, sizeof(acf)); if (handle->flags & RFID_OPT_LAYER2_WUP) - ret = iso14443a_transceive_sf(handle, ISO14443A_SF_CMD_WUPA, &atqa); + ret = iso14443a_transceive_sf(handle, ISO14443A_SF_CMD_WUPA, atqa); else - ret = iso14443a_transceive_sf(handle, ISO14443A_SF_CMD_REQA, &atqa); + ret = iso14443a_transceive_sf(handle, ISO14443A_SF_CMD_REQA, atqa); if (ret < 0) { h->state = ISO14443A_STATE_REQA_SENT; DEBUGP("error during transceive_sf: %d\n", ret); @@ -125,15 +125,15 @@ iso14443a_anticol(struct rfid_layer2_handle *handle) DEBUGP("ATQA: 0x%02x 0x%02x\n", *aqptr, *(aqptr+1)); - if (!atqa.bf_anticol) { + if (!atqa->bf_anticol) { h->state = ISO14443A_STATE_NO_BITFRAME_ANTICOL; DEBUGP("no bitframe anticollission bits set, aborting\n"); return -1; } - if (atqa.uid_size == 2 || atqa.uid_size == 3) + if (atqa->uid_size == 2 || atqa->uid_size == 3) uid_size = 3; - else if (atqa.uid_size == 1) + else if (atqa->uid_size == 1) uid_size = 2; else uid_size = 1; @@ -285,6 +285,24 @@ iso14443a_setopt(struct rfid_layer2_handle *handle, int optname, return ret; } +static int +iso14443a_getopt(struct rfid_layer2_handle *handle, int optname, + void *optval, unsigned int optlen) +{ + int ret = -EINVAL; + struct iso14443a_handle *h = &handle->priv.iso14443a; + struct iso14443a_atqa *atqa = optval; + + switch (optname) { + case RFID_OPT_14443A_ATQA: + *atqa = h->atqa; + ret = 0; + break; + }; + + return ret; +} + static struct rfid_layer2_handle * iso14443a_init(struct rfid_reader_handle *rh) @@ -328,6 +346,7 @@ const struct rfid_layer2 rfid_layer2_iso14443a = { .close = &iso14443a_hlta, .fini = &iso14443a_fini, .setopt = &iso14443a_setopt, + .getopt = &iso14443a_getopt, }, }; diff --git a/src/rfid_proto_mifare_classic.c b/src/rfid_proto_mifare_classic.c index 4032b80..c2020b0 100644 --- a/src/rfid_proto_mifare_classic.c +++ b/src/rfid_proto_mifare_classic.c @@ -140,6 +140,35 @@ mfcl_write(struct rfid_protocol_handle *ph, unsigned int page, return ret; } +static int +mfcl_getopt(struct rfid_protocol_handle *ph, int optname, void *optval, + unsigned int *optlen) +{ + int ret = -EINVAL; + u_int16_t atqa; + unsigned int atqa_size = sizeof(atqa); + unsigned int *size = optval; + + switch (optname) { + case RFID_OPT_PROTO_SIZE: + if (*optlen < sizeof(*size)) + return -EINVAL; + *optlen = sizeof(*size); + ret = 0; + rfid_layer2_getopt(ph->l2h, RFID_OPT_14443A_ATQA, + (void *) &atqa, &atqa_size); + if (atqa == 0x0004) + *size = 1024; + else if (atqa == 0x0002) + *size = 4096; + else + ret = -EIO; + break; + } + + return ret; +} + static struct rfid_protocol_handle * mfcl_init(struct rfid_layer2_handle *l2h) { @@ -169,6 +198,7 @@ const struct rfid_protocol rfid_protocol_mfcl = { .read = &mfcl_read, .write = &mfcl_write, .fini = &mfcl_fini, + .getopt = &mfcl_getopt, }, }; diff --git a/src/rfid_proto_mifare_ul.c b/src/rfid_proto_mifare_ul.c index 8981b5e..65347b1 100644 --- a/src/rfid_proto_mifare_ul.c +++ b/src/rfid_proto_mifare_ul.c @@ -108,14 +108,41 @@ mful_transceive(struct rfid_protocol_handle *ph, return -EINVAL; } +static int +mful_getopt(struct rfid_protocol_handle *ph, int optname, void *optval, + unsigned int optlen) +{ + int ret = -EINVAL; + u_int16_t atqa; + unsigned int *size = optval; + + switch (optname) { + case RFID_OPT_PROTO_SIZE: + ret = 0; + *size = 512; + break; + } + + return ret; +} + + static struct rfid_protocol_handle * mful_init(struct rfid_layer2_handle *l2h) { struct rfid_protocol_handle *ph; + u_int16_t atqa; + unsigned int atqa_len = sizeof(atqa); if (l2h->l2->id != RFID_LAYER2_ISO14443A) return NULL; + /* According to "Type Identification Procedure Rev. 1.3" */ + rfid_layer2_getopt(l2h, RFID_OPT_14443A_ATQA, + &atqa, atqa_len); + if (atqa != 0x0044) + return NULL; + /* according to "Functional Specification Rev. 3.0 */ if (l2h->uid_len != 7) return NULL; @@ -138,6 +165,7 @@ const struct rfid_protocol rfid_protocol_mful = { .read = &mful_read, .write = &mful_write, .fini = &mful_fini, + .getopt = &mful_getopt, }, }; diff --git a/src/rfid_proto_tcl.c b/src/rfid_proto_tcl.c index af626c6..70259e6 100644 --- a/src/rfid_proto_tcl.c +++ b/src/rfid_proto_tcl.c @@ -781,6 +781,8 @@ tcl_getopt(struct rfid_protocol_handle *h, int optname, void *optval, *optlen = sizeof(u_int8_t); *opt_str = h->priv.tcl.ats_len & 0xff; break; + default: + return -EINVAL; } return 0; diff --git a/src/rfid_protocol.c b/src/rfid_protocol.c index 99fc8b1..3cbe8af 100644 --- a/src/rfid_protocol.c +++ b/src/rfid_protocol.c @@ -114,7 +114,6 @@ rfid_protocol_getopt(struct rfid_protocol_handle *ph, int optname, unsigned char *optchar = optval; switch (optname) { - break; default: return -EINVAL; break; diff --git a/utils/librfid-tool.c b/utils/librfid-tool.c index 37efadc..be6e843 100644 --- a/utils/librfid-tool.c +++ b/utils/librfid-tool.c @@ -260,6 +260,9 @@ static int l2_by_name(const char *name) static void do_scan(void) { int rc; + unsigned int size; + unsigned int size_len = sizeof(size); + printf("scanning for RFID token...\n"); rc = rfid_scan(rh, &l2h, &ph); if (rc >= 2) { @@ -272,6 +275,10 @@ static void do_scan(void) } if (rc >= 3) { printf("Protocol success (%s)\n", rfid_protocol_name(ph)); + + if (rfid_protocol_getopt(ph, RFID_OPT_PROTO_SIZE, + &size, &size_len) == 0) + printf("Size: %u bytes\n", size); } } -- cgit v1.2.3