* improve scanning support:
authorlaforge <laforge@e0336214-984f-0b4b-a45f-81c69e1f0ede>
Sun, 27 Jan 2008 02:15:48 +0000 (02:15 +0000)
committerlaforge <laforge@e0336214-984f-0b4b-a45f-81c69e1f0ede>
Sun, 27 Jan 2008 02:15:48 +0000 (02:15 +0000)
** 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
include/librfid/rfid_reader.h
src/rfid_asic_rc632.c
src/rfid_layer2_iso14443a.c
src/rfid_reader_cm5121.c
src/rfid_reader_openpcd.c
src/rfid_reader_spidev.c
utils/librfid-tool.c

index 3aebd1f..ccc4f20 100644 (file)
@@ -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,
index 296c66f..64ad862 100644 (file)
@@ -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);
index 61af0ac..b8d8db3 100644 (file)
@@ -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,
index 9bdd25a..148960d 100644 (file)
@@ -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;
index 383fba2..053b953 100644 (file)
@@ -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) |
index 67b73b6..88c55ee 100644 (file)
@@ -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,
index e546380..b0676eb 100644 (file)
@@ -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) |
index 74f6128..dab7db3 100644 (file)
@@ -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':