Use Seeeduino Arch (or Arch Pro) + NFC Shield to read a Mifare Classic tag

Dependencies:   PN532 mbed

Fork of PN532_P2P by Yihui Xiong

Revision:
1:a9df716f8a64
Parent:
0:21ac4fe1ccf8
Child:
2:b238c6772bc4
--- a/main.cpp	Thu Oct 17 07:14:21 2013 +0000
+++ b/main.cpp	Thu Oct 17 07:47:22 2013 +0000
@@ -1,21 +1,13 @@
-/**
- * Seeeduino Arch + NFC Shield write a NDEF record to a NFC tag
- */
-
-
 #include "mbed.h"
 #include "PN532.h"
 
-#if 0
-
+#if 0   // Output debug message or not
 #define LOG(args...)
-
 #else
 #include "USBSerial.h"
-
 #define LOG(args...)        pc.printf(args)
 
-USBSerial pc;
+USBSerial pc;               // Use USB to Serial
 //Serial pc(USBTX, USBRX);
 #endif
 
@@ -24,27 +16,8 @@
 
 DigitalOut led1(LED1);
 
-/*
-    We can encode many different kinds of pointers to the card,
-    from a URL, to an Email address, to a phone number, and many more
-    check the library header .h file to see the large # of supported
-    prefixes!
-*/
-// For a http://www. url:
-const char *url = "seeedstudio.com";
-uint8_t ndefprefix = NDEF_URIPREFIX_HTTP_WWWDOT;
-
-// for an email address
-//const char * url = "mail@example.com";
-//uint8_t ndefprefix = NDEF_URIPREFIX_MAILTO;
-
-// for a phone number
-//const char * url = "+1 212 555 1212";
-//uint8_t ndefprefix = NDEF_URIPREFIX_TEL;
-
 int main()
 {
-
     nfc.begin();
     uint32_t versiondata = nfc.getFirmwareVersion();
     if (! versiondata) {
@@ -60,20 +33,12 @@
 
     nfc.SAMConfig();
 
-
     while (1) {
-        uint8_t success;                          // Flag to check if there was an error with the PN532
-        uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the continueed UID
+        uint8_t success;
+        uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
         uint8_t uidLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
-        bool authenticated = false;               // Flag to indicate if the sector is authenticated
 
-        // Use the default NDEF keys (these would have have set by mifareclassic_formatndef.pde!)
-        uint8_t keya[6] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 };
-        uint8_t keyb[6] = { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 };
-
-        LOG("Place your NDEF formatted Mifare Classic card on the reader to update the NDEF record\r\n");
-
-        // Wait for an ISO14443A type card (Mifare, etc.).  When one is found
+        // Wait for an ISO14443A type cards (Mifare, etc.).  When one is found
         // 'uid' will be populated with the UID, and uidLength will indicate
         // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
         success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 0);
@@ -86,54 +51,76 @@
                 LOG("0x%X ", uid[i]);
             }
 
-            // Make sure this is a Mifare Classic card
-            if (uidLength != 4) {
-                LOG("Ooops ... this doesn't seem to be a Mifare Classic card!\r\n");
-                continue;
-            }
+            if (uidLength == 4) {
+                // We probably have a Mifare Classic card ...
+                LOG("Seems to be a Mifare Classic card (4 byte UID)\r\n");
+
+                // Now we need to try to authenticate it for read/write access
+                // Try with the factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
+                LOG("Trying to authenticate block 4 with default KEYA value\r\n");
+                uint8_t keya[6] = { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 };
+
+                // Start with block 4 (the first block of sector 1) since sector 0
+                // contains the manufacturer data and it's probably better just
+                // to leave it alone unless you know what you're doing
+                success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya);
+
+                if (success) {
+                    LOG("Sector 1 (Blocks 4..7) has been authenticated\r\n");
+                    uint8_t data[16];
 
-            // We probably have a Mifare Classic card ...
-            LOG("Seems to be a Mifare Classic card (4 byte UID)\r\n");
+                    // If you want to write something to block 4 to test with, uncomment
+                    // the following line and this text should be read back in a minute
+                    // data = { 'a', 'd', 'a', 'f', 'r', 'u', 'i', 't', '.', 'c', 'o', 'm', 0, 0, 0, 0};
+                    // success = nfc.mifareclassic_WriteDataBlock (4, data);
+
+                    // Try to read the contents of block 4
+                    success = nfc.mifareclassic_ReadDataBlock(4, data);
 
-            // Check if this is an NDEF card (using first block of sector 1 from mifareclassic_formatndef.pde)
-            // Must authenticate on the first key using 0xD3 0xF7 0xD3 0xF7 0xD3 0xF7
-            success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, 4, 0, keyb);
-            if (!success) {
-                LOG("Unable to authenticate block 4 ... is this card NDEF formatted?\r\n");
-                continue;
+                    if (success) {
+                        // Data seems to have been read ... spit it out
+                        LOG("Reading Block 4:\r\n");
+                        for (int i = 0; i < 16; i++) {
+                            LOG("%2X ", data[i]);
+                        }
+                        LOG("       ");
+                        for (int i = 0; i < 16; i++) {
+                            LOG("%c", (char)data[i]);
+                        }
+                        LOG("\r\n");
+                    } else {
+                        LOG("Ooops ... unable to read the requested block.  Try another key?\r\n");
+                    }
+                } else {
+                    LOG("Ooops ... authentication failed: Try another key?\r\n");
+                }
             }
 
-            LOG("Authentication succeeded (seems to be an NDEF/NFC Forum tag) ...\r\n");
-
-            // Authenticated seems to have worked
-            // Try to write an NDEF record to sector 1
-            // Use 0x01 for the URI Identifier Code to prepend "http://www."
-            // to the url (and save some space).  For information on URI ID Codes
-            // see http://www.ladyada.net/wiki/private/articlestaging/nfc/ndef
-            if (strlen(url) > 38) {
-                // The length is also checked in the WriteNDEFURI function, but lets
-                // warn users here just in case they change the value and it's bigger
-                // than it should be
-                LOG("URI is too long ... must be less than 38 characters!\r\n");
-                continue;
-            }
+            if (uidLength == 7) {
+                // We probably have a Mifare Ultralight card ...
+                LOG("Seems to be a Mifare Ultralight tag (7 byte UID)\r\n");
 
-            LOG("Updating sector 1 with URI as NDEF Message\r\n");
-
-            // URI is within size limits ... write it to the card and report success/failure
-            success = nfc.mifareclassic_WriteNDEFURI(1, ndefprefix, url);
-            if (success) {
-                LOG("NDEF URI Record written to sector 1\r\n");
-                LOG("\r\n");
-            } else {
-                LOG("NDEF Record creation failed! :(\r\n");
+                // Try to read the first general-purpose user page (#4)
+                LOG("Reading page 4\r\n");
+                uint8_t data[32];
+                success = nfc.mifareultralight_ReadPage (4, data);
+                if (success) {
+                    // Data seems to have been read ... spit it out
+                    for (int i = 0; i < 4; i++) {
+                            LOG("%2X ", data[i]);
+                        }
+                        LOG("       ");
+                        for (int i = 0; i < 4; i++) {
+                            LOG("%c", (char)data[i]);
+                        }
+                    LOG("\r\n");
+                } else {
+                    LOG("Ooops ... unable to read the requested page!?\r\n");
+                }
             }
-        } else {
-            LOG("Didn't find a NFC tag\r\n");
         }
-
-        // Wait a bit before trying again
-        LOG("\n\nDone!\r\n");
-        wait(1);
+        
+        wait(3);
     }
 }
+