to colorize a colorful pixel with a simple touch using nfc technology

Dependencies:   Chainable_RGB_LED mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MifareUltralight.cpp Source File

MifareUltralight.cpp

00001 #include "MifareUltralight.h"
00002 
00003 #include "PN532_debug.h"
00004 
00005 #define ULTRALIGHT_PAGE_SIZE 4
00006 #define ULTRALIGHT_READ_SIZE 4 // we should be able to read 16 uint8_ts at a time
00007 
00008 #define ULTRALIGHT_DATA_START_PAGE 4
00009 #define ULTRALIGHT_MESSAGE_LENGTH_INDEX 1
00010 #define ULTRALIGHT_DATA_START_INDEX 2
00011 #define ULTRALIGHT_MAX_PAGE 63
00012 
00013 #define NFC_FORUM_TAG_TYPE_2 ("NFC Forum Type 2")
00014 
00015 MifareUltralight::MifareUltralight(PN532& nfcShield)
00016 {
00017     nfc = &nfcShield;
00018     ndefStartIndex = 0;
00019     messageLength = 0;
00020 }
00021 
00022 MifareUltralight::~MifareUltralight()
00023 {
00024 }
00025 
00026 NfcTag MifareUltralight::read(uint8_t * uid, unsigned int uidLength)
00027 {
00028     if (isUnformatted())
00029     {
00030         DMSG("WARNING: Tag is not formatted.");
00031         return NfcTag(uid, uidLength, NFC_FORUM_TAG_TYPE_2);
00032     }
00033 
00034     readCapabilityContainer(); // meta info for tag
00035     findNdefMessage();
00036     calculateBufferSize();
00037 
00038     if (messageLength == 0) { // data is 0x44 0x03 0x00 0xFE
00039         NdefMessage message = NdefMessage();
00040         message.addEmptyRecord();
00041         return NfcTag(uid, uidLength, NFC_FORUM_TAG_TYPE_2, message);
00042     }
00043 
00044     bool success;
00045     uint8_t page;
00046     uint8_t index = 0;
00047     uint8_t buffer[bufferSize];
00048     for (page = ULTRALIGHT_DATA_START_PAGE; page < ULTRALIGHT_MAX_PAGE; page++)
00049     {
00050         // read the data
00051         success = nfc->mifareultralight_ReadPage(page, &buffer[index]);
00052         if (success)
00053         {
00054             #ifdef MIFARE_ULTRALIGHT_DEBUG
00055             DMSG("Page ");Serial.print(page);DMSG(" ");
00056             nfc->PrintHexChar(&buffer[index], ULTRALIGHT_PAGE_SIZE);
00057             #endif
00058         }
00059         else
00060         {
00061             DMSG("Read failed ");DMSG_INT(page);
00062             // TODO error handling
00063             messageLength = 0;
00064             break;
00065         }
00066 
00067         if (index >= (messageLength + ndefStartIndex))
00068         {
00069             break;
00070         }
00071 
00072         index += ULTRALIGHT_PAGE_SIZE;
00073     }
00074 
00075     NdefMessage ndefMessage = NdefMessage(&buffer[ndefStartIndex], messageLength);
00076     return NfcTag(uid, uidLength, NFC_FORUM_TAG_TYPE_2, ndefMessage);
00077 
00078 }
00079 
00080 bool MifareUltralight::isUnformatted()
00081 {
00082     uint8_t page = 4;
00083     uint8_t data[ULTRALIGHT_READ_SIZE];
00084     bool success = nfc->mifareultralight_ReadPage (page, data);
00085     if (success)
00086     {
00087         return (data[0] == 0xFF && data[1] == 0xFF && data[2] == 0xFF && data[3] == 0xFF);
00088     }
00089     else
00090     {
00091         DMSG("Error. Failed read page ");DMSG_INT(page);
00092         return false;
00093     }
00094 }
00095 
00096 // page 3 has tag capabilities
00097 void MifareUltralight::readCapabilityContainer()
00098 {
00099     uint8_t data[ULTRALIGHT_PAGE_SIZE];
00100     int success = nfc->mifareultralight_ReadPage (3, data);
00101     if (success)
00102     {
00103         // See AN1303 - different rules for Mifare Family uint8_t2 = (additional data + 48)/8
00104         tagCapacity = data[2] * 8;
00105         #ifdef MIFARE_ULTRALIGHT_DEBUG
00106         DMSG("Tag capacity "));Serial.print(tagCapacity);DMSG(F(" uint8_ts");
00107         #endif
00108 
00109         // TODO future versions should get lock information
00110     }
00111 }
00112 
00113 // read enough of the message to find the ndef message length
00114 void MifareUltralight::findNdefMessage()
00115 {
00116     int page;
00117     uint8_t data[12]; // 3 pages
00118     uint8_t* data_ptr = &data[0];
00119 
00120     // the nxp read command reads 4 pages, unfortunately adafruit give me one page at a time
00121     bool success = true;
00122     for (page = 4; page < 6; page++)
00123     {
00124         success = success && nfc->mifareultralight_ReadPage(page, data_ptr);
00125         #ifdef MIFARE_ULTRALIGHT_DEBUG
00126         DMSG("Page "));Serial.print(page);Serial.print(F(" - ");
00127         nfc->PrintHexChar(data_ptr, 4);
00128         #endif
00129         data_ptr += ULTRALIGHT_PAGE_SIZE;
00130     }
00131 
00132     if (success)
00133     {
00134         if (data[0] == 0x03)
00135         {
00136             messageLength = data[1];
00137             ndefStartIndex = 2;
00138         }
00139         else if (data[5] == 0x3) // page 5 uint8_t 1
00140         {
00141             // TODO should really read the lock control TLV to ensure uint8_t[5] is correct
00142             messageLength = data[6];
00143             ndefStartIndex = 7;
00144         }
00145     }
00146 
00147     #ifdef MIFARE_ULTRALIGHT_DEBUG
00148     DMSG("messageLength ");DMSG(messageLength);
00149     DMSG("ndefStartIndex ");DMSG(ndefStartIndex);
00150     #endif
00151 }
00152 
00153 // buffer is larger than the message, need to handle some data before and after
00154 // message and need to ensure we read full pages
00155 void MifareUltralight::calculateBufferSize()
00156 {
00157     // TLV terminator 0xFE is 1 uint8_t
00158     bufferSize = messageLength + ndefStartIndex + 1;
00159 
00160     if (bufferSize % ULTRALIGHT_READ_SIZE != 0)
00161     {
00162         // buffer must be an increment of page size
00163         bufferSize = ((bufferSize / ULTRALIGHT_READ_SIZE) + 1) * ULTRALIGHT_READ_SIZE;
00164     }
00165 }