PN532 NFC library for Seeed Studio's NFC Shield

Fork of PN532 by Yihui Xiong

Files at this revision

API Documentation at this revision

Comitter:
yihui
Date:
Wed Oct 08 01:52:33 2014 +0000
Parent:
7:26c1b3b6c192
Parent:
5:51f820fbd18a
Child:
9:85bfede025da
Commit message:
merge

Changed in this revision

PN532.cpp Show annotated file Show diff for this revision Revisions of this file
PN532.h Show annotated file Show diff for this revision Revisions of this file
--- a/MifareClassic.cpp	Tue Mar 25 16:48:10 2014 +0000
+++ b/MifareClassic.cpp	Wed Oct 08 01:52:33 2014 +0000
@@ -243,7 +243,6 @@
                 return false;
             }
         }
-
         int write_success = _nfcShield->mifareclassic_WriteDataBlock (currentBlock, &buffer[index]);
         if (write_success)
         {
--- a/MifareUltralight.cpp	Tue Mar 25 16:48:10 2014 +0000
+++ b/MifareUltralight.cpp	Wed Oct 08 01:52:33 2014 +0000
@@ -77,6 +77,61 @@
 
 }
 
+bool MifareUltralight::write(NdefMessage& m, uint8_t * uid, unsigned int uidLength)
+{
+
+     if (isUnformatted())
+    {
+        printf("WARNING: Tag is not formatted.\r\n");
+        return false;
+    }
+    readCapabilityContainer(); // meta info for tag
+
+    messageLength  = m.getEncodedSize();
+    ndefStartIndex = messageLength < 0xFF ? 2 : 4;
+    calculateBufferSize();
+
+    if(bufferSize>tagCapacity) {
+       /* #ifdef MIFARE_ULTRALIGHT_DEBUG
+        Serial.print(F("Encoded Message length exceeded tag Capacity "));Serial.println(tagCapacity);
+        #endif*/
+        return false;
+    }
+
+    uint8_t encoded[bufferSize];
+    uint8_t *  src = encoded;
+    unsigned int position = 0;
+    uint8_t page = ULTRALIGHT_DATA_START_PAGE;
+
+    // Set message size. With ultralight should always be less than 0xFF but who knows?
+
+    encoded[0] = 0x3;
+    if (messageLength < 0xFF)
+    {
+        encoded[1] = messageLength;
+    }
+    else
+    {
+        encoded[1] = 0xFF;
+        encoded[2] = ((messageLength >> 8) & 0xFF);
+        encoded[3] = (messageLength & 0xFF);
+    }
+
+    m.encode(encoded+ndefStartIndex);
+    // this is always at least 1 byte copy because of terminator.
+    memset(encoded+ndefStartIndex+messageLength,0,bufferSize-ndefStartIndex-messageLength);
+    encoded[ndefStartIndex+messageLength] = 0xFE; // terminator
+
+    while (position < bufferSize){ //bufferSize is always times pagesize so no "last chunk" check
+        // write page
+        if (!nfc->mifareultralight_WritePage(page, src))
+            return false;
+        page++;
+        src+=ULTRALIGHT_PAGE_SIZE;
+        position+=ULTRALIGHT_PAGE_SIZE;
+    }
+    return true;
+}
 bool MifareUltralight::isUnformatted()
 {
     uint8_t page = 4;
--- a/MifareUltralight.h	Tue Mar 25 16:48:10 2014 +0000
+++ b/MifareUltralight.h	Wed Oct 08 01:52:33 2014 +0000
@@ -11,6 +11,7 @@
         MifareUltralight(PN532& nfcShield);
         ~MifareUltralight();
         NfcTag read(uint8_t *uid, unsigned int uidLength);
+        bool write(NdefMessage& ndefMessage, uint8_t *uid, unsigned int uidLength);
     private:
         PN532* nfc;
         unsigned int tagCapacity;
--- a/NfcAdapter.cpp	Tue Mar 25 16:48:10 2014 +0000
+++ b/NfcAdapter.cpp	Wed Oct 08 01:52:33 2014 +0000
@@ -34,7 +34,7 @@
     uidLength = 0;
 
     // TODO is cast of uidLength OK?
-    success = shield->readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, (uint8_t*)&uidLength);
+    success = shield->readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, (uint8_t*)&uidLength,&ATQA,&SAK);
 
     // if (success)
     // {
@@ -90,7 +90,7 @@
 bool NfcAdapter::write(NdefMessage& ndefMessage)
 {
     bool success;
-
+    uint8_t type = guessTagType();
     if (uidLength == 4)
     {
         MifareClassic mifareClassic = MifareClassic(*shield);
@@ -98,8 +98,10 @@
     }
     else
     {
-        DMSG("Unsupported Tag");
-        success = false;
+        DMSG("Ultralight Tag");
+        MifareUltralight mifareUltralight = MifareUltralight(*shield);
+        success= mifareUltralight.write(ndefMessage, uid, uidLength);
+        //success = false;
     }
     return success;
 }
@@ -116,13 +118,21 @@
     //  - ATQA 0x44 && SAK 0x8 - Mifare Classic
     //  - ATQA 0x44 && SAK 0x0 - Mifare Ultralight NFC Forum Type 2
     //  - ATQA 0x344 && SAK 0x20 - NFC Forum Type 4
-
-    if (uidLength == 4)
+    DMSG("Guess type");
+    DMSG("ATQA: 0x");  DMSG_HEX(ATQA);
+    DMSG("SAK: 0x");  DMSG_HEX(SAK);
+    /*if (uidLength == 4)
     {
         return TAG_TYPE_MIFARE_CLASSIC;
     }
     else
     {
         return TAG_TYPE_2;
+    }*/
+    if(ATQA==0x4&&SAK==0x8){
+        return TAG_TYPE_MIFARE_CLASSIC;
+    }
+    if(ATQA==0x44&&SAK==0x0){
+        return TAG_TYPE_2;
     }
 }
--- a/NfcAdapter.h	Tue Mar 25 16:48:10 2014 +0000
+++ b/NfcAdapter.h	Wed Oct 08 01:52:33 2014 +0000
@@ -38,6 +38,8 @@
         uint8_t uid[7];    // Buffer to store the returned UID
         unsigned int uidLength; // Length of the UID (4 or 7 uint8_ts depending on ISO14443A card type)
         unsigned int guessTagType();
+        uint16_t ATQA;
+        uint8_t SAK;
 };
 
 #endif
--- a/PN532.cpp	Tue Mar 25 16:48:10 2014 +0000
+++ b/PN532.cpp	Wed Oct 08 01:52:33 2014 +0000
@@ -287,7 +287,7 @@
     @returns 1 if everything executed properly, 0 for an error
 */
 /**************************************************************************/
-bool PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout)
+bool PN532::readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t *atqa, uint8_t *sak, uint16_t timeout)
 {
     pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
     pn532_packetbuffer[1] = 1;  // max 1 cards at once (we can set this to 2 later)
@@ -321,7 +321,8 @@
     uint16_t sens_res = pn532_packetbuffer[2];
     sens_res <<= 8;
     sens_res |= pn532_packetbuffer[3];
-
+    *atqa = sens_res;
+    *sak = pn532_packetbuffer[4];
     DMSG("ATQA: 0x");  DMSG_HEX(sens_res);
     DMSG("SAK: 0x");  DMSG_HEX(pn532_packetbuffer[4]);
     DMSG("\n");
@@ -496,6 +497,35 @@
     /* Read the response packet */
     return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
 }
+/**************************************************************************/
+/*!
+    Tries to write an entire 4-bytes data block at the specified block
+    address.
+
+    @param  blockNumber   The block number to authenticate.  (0..63 for
+                          1KB cards, and 0..255 for 4KB cards).
+    @param  data          The byte array that contains the data to write.
+
+    @returns 1 if everything executed properly, 0 for an error
+*/
+/**************************************************************************/
+uint8_t PN532::mifareultralight_WritePage (uint8_t blockNumber, uint8_t *data)
+{
+    /* Prepare the first command */
+    pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
+    pn532_packetbuffer[1] = 1;                      /* Card number */
+    pn532_packetbuffer[2] = MIFARE_UL_CMD_WRITE_PAGE;       /* Mifare Write command = 0xA0 */
+    pn532_packetbuffer[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */
+    memcpy (pn532_packetbuffer + 4, data, 4);        /* Data Payload */
+
+    /* Send the command */
+    if (HAL(writeCommand)(pn532_packetbuffer, 8)) {
+        return 0;
+    }
+
+    /* Read the response packet */
+    return (0 < HAL(readResponse)(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
+}
 
 /**************************************************************************/
 /*!
--- a/PN532.h	Tue Mar 25 16:48:10 2014 +0000
+++ b/PN532.h	Wed Oct 08 01:52:33 2014 +0000
@@ -61,7 +61,7 @@
 #define MIFARE_CMD_DECREMENT                (0xC0)
 #define MIFARE_CMD_INCREMENT                (0xC1)
 #define MIFARE_CMD_STORE                    (0xC2)
-
+#define MIFARE_UL_CMD_WRITE_PAGE            (0xA2)
 // Prefixes for NDEF Records (to identify record type)
 #define NDEF_URIPREFIX_NONE                 (0x00)
 #define NDEF_URIPREFIX_HTTP_WWWDOT          (0x01)
@@ -142,7 +142,7 @@
 
     // ISO14443A functions
     bool inListPassiveTarget();
-    bool readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 1000);
+    bool readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t *atqa, uint8_t *sak, uint16_t timeout = 1000);
     bool inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength);
 
     // Mifare Classic functions
@@ -156,7 +156,7 @@
 
     // Mifare Ultralight functions
     uint8_t mifareultralight_ReadPage (uint8_t page, uint8_t *buffer);
-
+    uint8_t mifareultralight_WritePage (uint8_t page, uint8_t *buffer);
     // Help functions to display formatted text
     static void PrintHex(const uint8_t *data, const uint32_t numBytes);
     static void PrintHexChar(const uint8_t *pbtData, const uint32_t numBytes);
--- a/PN532_debug.h	Tue Mar 25 16:48:10 2014 +0000
+++ b/PN532_debug.h	Wed Oct 08 01:52:33 2014 +0000
@@ -8,8 +8,8 @@
 #include <stdio.h>
 
 #define DMSG(args...)   printf(args)
-#define DMSG_STR(str)   printf("%s\n", str)
-#define DMSG_INT(num)   printf("%d\n", num)
+#define DMSG_STR(str)   printf("%s\r\n", str)
+#define DMSG_INT(num)   printf("%d\r\n", num)
 #define DMSG_HEX(num)   printf("%2X ", num)
 
 #else