Make librfid-tool print out the ATS in case of success with a T=CL card
[librfid] / utils / librfid-tool.c
index 3e833a0..eae9025 100644 (file)
@@ -42,6 +42,7 @@
 #include <librfid/rfid_protocol_mifare_ul.h>
 #include <librfid/rfid_protocol_tagit.h>
 #include <librfid/rfid_protocol_icode.h>
+#include <librfid/rfid_protocol_tcl.h>
 
 #include "librfid-tool.h"
 
@@ -207,15 +208,21 @@ mifare_classic_read_sector(struct rfid_protocol_handle *ph, int sector)
        unsigned char buf[20];
        unsigned int len = sizeof(buf);
        int ret;
-       int block;
+       int block, blocks_per_sector, first_block;
 
-       /* FIXME: make this work for sectors > 31 */
        printf("Reading sector %u\n", sector);
 
-       for (block = sector*4; block < sector*4+4; block++) {
+       first_block = mfcl_sector2block(sector);
+       blocks_per_sector = mfcl_sector_blocks(sector);
+
+       if (first_block < 0 || blocks_per_sector < 0)
+               return -EINVAL;
+
+       for (block = first_block; block < first_block + blocks_per_sector;
+            block++) {
                printf("Reading block %u: ", block);
                ret = rfid_protocol_read(ph, block, buf, &len);
-               if(ret == -ETIMEDOUT)
+               if (ret == -ETIMEDOUT)
                        fprintf(stderr, "TIMEOUT\n");
                if (ret < 0) {
                        printf("Error %d reading\n", ret);
@@ -227,6 +234,59 @@ mifare_classic_read_sector(struct rfid_protocol_handle *ph, int sector)
        return 0;
 }
 
+static int
+mifare_classic_dump(struct rfid_protocol_handle *ph)
+{
+       unsigned int size;
+       unsigned int size_len = sizeof(size);
+       int sector, num_sectors;
+
+       if (rfid_protocol_getopt(ph, RFID_OPT_PROTO_SIZE, 
+                                &size, &size_len) == 0) {
+               printf("Size: %u bytes\n", size);
+       } else {
+               printf("Size: unknown ?!?\n");
+               return -EINVAL;
+       }
+
+       switch (size) {
+       case 320:
+               num_sectors = 5;
+               break;
+       case 1024:
+               num_sectors = 16;
+               break;
+       case 4096:
+               num_sectors = 40;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       for (sector = 0; sector < num_sectors; sector++) {
+               int rc;
+
+               printf("Authenticating sector %u: ", sector);
+               fflush(stdout);
+
+               rc = mfcl_set_key(ph, MIFARE_CL_KEYA_DEFAULT_INFINEON);
+               if (rc < 0) {
+                       printf("key format error\n");
+                       exit(1);
+               }
+
+               rc = mfcl_auth(ph, RFID_CMD_MIFARE_AUTH1A,
+                              mfcl_sector2block(sector));
+               if (rc < 0) {
+                       printf("mifare auth error\n");
+                       exit(1);
+               } else 
+                       printf("mifare auth succeeded!\n");
+
+               mifare_classic_read_sector(ph, sector);
+       }
+}
+
 static char *proto_names[] = {
        [RFID_PROTOCOL_TCL] = "tcl",
        [RFID_PROTOCOL_MIFARE_UL] = "mifare-ultralight",
@@ -273,11 +333,22 @@ static int do_scan(int first)
        int rc;
        unsigned int size;
        unsigned int size_len = sizeof(size);
+       char *data;
+       unsigned int data_len;
 
        if (first) {
-               rh->reader->rf_power(rh, 0);
+               unsigned int opt;
+               unsigned int optlen = sizeof(opt);
+
+               /* turn off RF */
+               opt = 1;
+               rfid_reader_setopt(rh, RFID_OPT_RDR_RF_KILL, &opt, optlen);
+
                usleep(10*1000);
-               rh->reader->rf_power(rh, 1);
+
+               /* turn on RF */
+               opt = 0;
+               rfid_reader_setopt(rh, RFID_OPT_RDR_RF_KILL, &opt, optlen);
        }
        printf("scanning for RFID token...\n");
        rc = rfid_scan(rh, &l2h, &ph);
@@ -295,6 +366,20 @@ static int do_scan(int first)
                if (rfid_protocol_getopt(ph, RFID_OPT_PROTO_SIZE, 
                                         &size, &size_len) == 0)
                        printf("Size: %u bytes\n", size);
+               size_len = sizeof(size);
+               size = 0;
+               if (rfid_protocol_getopt(ph, RFID_OPT_P_TCL_ATS_LEN,
+                                        &size, &size_len) == 0) {
+                       data_len = size + 1;
+                       data = malloc(data_len);
+                       if (data) {
+                               if (rfid_protocol_getopt(ph, RFID_OPT_P_TCL_ATS,
+                                                        data, &data_len) == 0) {
+                                       printf("Got ATS of %u bytes: %s\n", size,
+                                              hexdump(data, data_len));
+                               }
+                       }
+               }
        }
 
        return rc;
@@ -660,26 +745,7 @@ int main(int argc, char **argv)
                break;
        case RFID_PROTOCOL_MIFARE_CLASSIC:
                printf("Protocol Mifare Classic\n");
-               {
-                       int sector;
-                       for (sector = 0; sector < 31; sector++) {
-                               printf("Authenticating sector %u: ", sector);
-                               fflush(stdout);
-                               rc = mfcl_set_key(ph, MIFARE_CL_KEYA_DEFAULT_INFINEON);
-                               if (rc < 0) {
-                                       printf("key format error\n");
-                                       exit(1);
-                               }
-                               rc = mfcl_auth(ph, RFID_CMD_MIFARE_AUTH1A, sector*4);
-                               if (rc < 0) {
-                                       printf("mifare auth error\n");
-                                       exit(1);
-                               } else 
-                                       printf("mifare auth succeeded!\n");
-
-                               mifare_classic_read_sector(ph, sector);
-                       }
-               }
+               mifare_classic_dump(ph);
                break;
        default:
                printf("unknown protocol %u\n", protocol);