From c203de04bd740e324b06615b98932ac9fa734ed2 Mon Sep 17 00:00:00 2001 From: laforge Date: Sun, 27 Jan 2008 02:15:48 +0000 Subject: * improve scanning support: ** first try REQA/HLTA/REQA/HLTA until no more tags found ** then power off the field and start from the beginning again * add proper RF field on/off switching support to all readers * reduce timer to actual value, don't multiply by 10 * detect collisions during transceive_sf (ATQA) * make UID length depend on cascade level, not ATQA git-svn-id: https://svn.gnumonks.org/trunk/librfid@2056 e0336214-984f-0b4b-a45f-81c69e1f0ede --- include/librfid/rfid_asic_rc632.h | 3 +-- include/librfid/rfid_reader.h | 1 + src/rfid_asic_rc632.c | 47 ++++++++++++++++++++++++++------------- src/rfid_layer2_iso14443a.c | 10 ++++----- src/rfid_reader_cm5121.c | 7 ++++++ src/rfid_reader_openpcd.c | 7 ++++++ src/rfid_reader_spidev.c | 6 +++++ utils/librfid-tool.c | 37 ++++++++++++++++++++++++++---- 8 files changed, 91 insertions(+), 27 deletions(-) diff --git a/include/librfid/rfid_asic_rc632.h b/include/librfid/rfid_asic_rc632.h index 3aebd1f..ccc4f20 100644 --- a/include/librfid/rfid_asic_rc632.h +++ b/include/librfid/rfid_asic_rc632.h @@ -33,8 +33,7 @@ struct rfid_asic_rc632 { struct { int (*power_up)(struct rfid_asic_handle *h); int (*power_down)(struct rfid_asic_handle *h); - int (*turn_on_rf)(struct rfid_asic_handle *h); - int (*turn_off_rf)(struct rfid_asic_handle *h); + int (*rf_power)(struct rfid_asic_handle *h, int on); int (*transceive)(struct rfid_asic_handle *h, enum rfid_frametype, const u_int8_t *tx_buf, diff --git a/include/librfid/rfid_reader.h b/include/librfid/rfid_reader.h index 296c66f..64ad862 100644 --- a/include/librfid/rfid_reader.h +++ b/include/librfid/rfid_reader.h @@ -35,6 +35,7 @@ struct rfid_reader { u_int64_t timeout, unsigned int flags); struct rfid_reader_handle * (*open)(void *data); void (*close)(struct rfid_reader_handle *h); + int (*rf_power)(struct rfid_reader_handle *h, int on); struct rfid_14443a_reader { int (*init)(struct rfid_reader_handle *h); diff --git a/src/rfid_asic_rc632.c b/src/rfid_asic_rc632.c index 61af0ac..b8d8db3 100644 --- a/src/rfid_asic_rc632.c +++ b/src/rfid_asic_rc632.c @@ -139,17 +139,17 @@ rc632_clear_bits(struct rfid_asic_handle *handle, } static int -rc632_turn_on_rf(struct rfid_asic_handle *handle) +rc632_rf_power(struct rfid_asic_handle *handle, int on) { ENTER(); - return rc632_set_bits(handle, RC632_REG_TX_CONTROL, 0x03); -} - -static int -rc632_turn_off_rf(struct rfid_asic_handle *handle) -{ - ENTER(); - return rc632_clear_bits(handle, RC632_REG_TX_CONTROL, 0x03); + if (on) + return rc632_set_bits(handle, RC632_REG_TX_CONTROL, + RC632_TXCTRL_TX1_RF_EN| + RC632_TXCTRL_TX2_RF_EN); + else + return rc632_clear_bits(handle, RC632_REG_TX_CONTROL, + RC632_TXCTRL_TX1_RF_EN| + RC632_TXCTRL_TX2_RF_EN); } static int @@ -375,7 +375,7 @@ rc632_transceive(struct rfid_asic_handle *handle, else cur_tx_len = tx_len; - ret = rc632_timer_set(handle, timer*10); + ret = rc632_timer_set(handle, timer); if (ret < 0) return ret; @@ -566,14 +566,14 @@ rc632_init(struct rfid_asic_handle *ah) return ret; /* switch off rf */ - ret = rc632_turn_off_rf(ah); + ret = rc632_rf_power(ah, 0); if (ret < 0) return ret; usleep(100000); /* switch on rf */ - ret = rc632_turn_on_rf(ah); + ret = rc632_rf_power(ah, 1); if (ret < 0) return ret; @@ -586,7 +586,7 @@ rc632_fini(struct rfid_asic_handle *ah) int ret; /* switch off rf */ - ret = rc632_turn_off_rf(ah); + ret = rc632_rf_power(ah, 0); if (ret < 0) return ret; @@ -746,7 +746,7 @@ rc632_iso14443a_fini(struct iso14443a_handle *handle_14443) { #if 0 - ret = rc632_turn_off_rf(handle); + ret = rc632_rf_power(handle, 0); if (ret < 0) return ret; #endif @@ -765,6 +765,7 @@ rc632_iso14443a_transceive_sf(struct rfid_asic_handle *handle, int ret; u_int8_t tx_buf[1]; u_int8_t rx_len = 2; + u_int8_t error_flag; memset(atqa, 0, sizeof(*atqa)); @@ -805,6 +806,21 @@ rc632_iso14443a_transceive_sf(struct rfid_asic_handle *handle, if (ret < 0) return ret; + /* determine whether there was a collission */ + ret = rc632_reg_read(handle, RC632_REG_ERROR_FLAG, &error_flag); + if (ret < 0) + return ret; + + if (error_flag & RC632_ERR_FLAG_COL_ERR) { + u_int8_t boc; + /* retrieve bit of collission */ + ret = rc632_reg_read(handle, RC632_REG_COLL_POS, &boc); + if (ret < 0) + return ret; + DEBUGP("collision detected in xcv_sf: bit_of_col=%u\n", boc); + /* FIXME: how to signal this up the stack */ + } + if (rx_len != 2) { DEBUGP("rx_len(%d) != 2\n", rx_len); return -1; @@ -1617,8 +1633,7 @@ const struct rfid_asic rc632 = { .fn = { .power_up = &rc632_power_up, .power_down = &rc632_power_down, - .turn_on_rf = &rc632_turn_on_rf, - .turn_off_rf = &rc632_turn_off_rf, + .rf_power = &rc632_rf_power, .transceive = &rc632_iso14443ab_transceive, .iso14443a = { .init = &rc632_iso14443a_init, diff --git a/src/rfid_layer2_iso14443a.c b/src/rfid_layer2_iso14443a.c index 9bdd25a..148960d 100644 --- a/src/rfid_layer2_iso14443a.c +++ b/src/rfid_layer2_iso14443a.c @@ -237,13 +237,10 @@ cascade: } } - h->level = ISO14443A_LEVEL_NONE; - h->state = ISO14443A_STATE_SELECTED; - { - if (uid_size == 1) + if (h->level == ISO14443A_LEVEL_CL1) handle->uid_len = 4; - else if (uid_size == 2) + else if (h->level == ISO14443A_LEVEL_CL2) handle->uid_len = 7; else handle->uid_len = 10; @@ -251,6 +248,9 @@ cascade: DEBUGP("UID %s\n", rfid_hexdump(handle->uid, handle->uid_len)); } + h->level = ISO14443A_LEVEL_NONE; + h->state = ISO14443A_STATE_SELECTED; + if (sak[0] & 0x20) { DEBUGP("we have a T=CL compliant PICC\n"); handle->proto_supported = 1 << RFID_PROTOCOL_TCL; diff --git a/src/rfid_reader_cm5121.c b/src/rfid_reader_cm5121.c index 383fba2..053b953 100644 --- a/src/rfid_reader_cm5121.c +++ b/src/rfid_reader_cm5121.c @@ -288,6 +288,12 @@ cm5121_mifare_auth(struct rfid_reader_handle *rh, u_int8_t cmd, cmd, serno, block); } +static int +cm5121_rf_power(struct rfid_reader_handle *rh, int on) +{ + return rh->ah->asic->priv.rc632.fn.rf_power(rh->ah, on); +} + struct rfid_asic_transport cm5121_ccid = { .name = "CM5121 OpenCT", .priv.rc632 = { @@ -364,6 +370,7 @@ const struct rfid_reader rfid_reader_cm5121 = { .name = "Omnikey CardMan 5121 RFID", .open = &cm5121_open, .close = &cm5121_close, + .rf_power = &cm5121_rf_power, .transceive = &cm5121_transceive, .l2_supported = (1 << RFID_LAYER2_ISO14443A) | (1 << RFID_LAYER2_ISO14443B) | diff --git a/src/rfid_reader_openpcd.c b/src/rfid_reader_openpcd.c index 67b73b6..88c55ee 100644 --- a/src/rfid_reader_openpcd.c +++ b/src/rfid_reader_openpcd.c @@ -438,6 +438,12 @@ openpcd_mifare_auth(struct rfid_reader_handle *rh, u_int8_t cmd, cmd, serno, block); } +static void +openpcd_rf_power(struct rfid_reader_handle *rh, int on) +{ + return rh->ah->asic->priv.rc632.fn.rf_power(rh->ah, on); +} + static struct rfid_reader_handle * openpcd_open(void *data) { @@ -527,6 +533,7 @@ const struct rfid_reader rfid_reader_openpcd = { .id = RFID_READER_OPENPCD, .open = &openpcd_open, .close = &openpcd_close, + .rf_power = &openpcd_rf_power, #ifndef LIBRFID_FIRMWARE .get_api_version = &openpcd_get_api_version, diff --git a/src/rfid_reader_spidev.c b/src/rfid_reader_spidev.c index e546380..b0676eb 100644 --- a/src/rfid_reader_spidev.c +++ b/src/rfid_reader_spidev.c @@ -274,6 +274,11 @@ spidev_mifare_auth(struct rfid_reader_handle *rh, u_int8_t cmd, cmd, serno, block); } +static int +spidev_rf_power(struct rfid_reader_handle *rh, int on) +{ + return rh->ah->asic->priv.rc632.fn.rf_power(rh->ah, on); +} static struct rfid_reader_handle *spidev_open(void *data) { @@ -363,6 +368,7 @@ struct rfid_reader rfid_reader_spidev = { .id = RFID_READER_SPIDEV, .open = &spidev_open, .close = &spidev_close, + .rf_power = &spidev_rf_power, .transceive = &spidev_transceive, .l2_supported = (1 << RFID_LAYER2_ISO14443A) | (1 << RFID_LAYER2_ISO14443B) | diff --git a/utils/librfid-tool.c b/utils/librfid-tool.c index 74f6128..dab7db3 100644 --- a/utils/librfid-tool.c +++ b/utils/librfid-tool.c @@ -260,12 +260,17 @@ static int l2_by_name(const char *name) return -1; } -static void do_scan(void) +static int do_scan(int first) { int rc; unsigned int size; unsigned int size_len = sizeof(size); + if (first) { + rh->reader->rf_power(rh, 0); + usleep(10*1000); + rh->reader->rf_power(rh, 1); + } printf("scanning for RFID token...\n"); rc = rfid_scan(rh, &l2h, &ph); if (rc >= 2) { @@ -283,6 +288,31 @@ static void do_scan(void) &size, &size_len) == 0) printf("Size: %u bytes\n", size); } + + return rc; +} + +static void do_endless_scan() +{ + int rc; + int first = 1; + + while (1) { + if (first) + putc('\n', stdout); + printf("==> doing %s scan\n", first ? "first" : "successive"); + rc = do_scan(first); + if (rc >= 3) { + printf("closing proto\n"); + rfid_protocol_close(ph); + } + if (rc >= 2) { + printf("closing layer2\n"); + rfid_layer2_close(l2h); + first = 0; + } else + first = 1; + } } #define OPTION_OFFSET 256 @@ -399,14 +429,13 @@ int main(int argc, char **argv) case 's': if (reader_init() < 0) exit(1); - do_scan(); + do_scan(0); exit(0); break; case 'S': if (reader_init() < 0) exit(1); - while (1) - do_scan(); + do_endless_scan(); exit(0); break; case 'p': -- cgit v1.2.3