PN532 NFC library for Seeed Studio's NFC Shield

Fork of PN532 by Yihui Xiong

Committer:
yihui
Date:
Thu Nov 21 04:30:49 2013 +0000
Revision:
3:4189a10038e6
Child:
5:51f820fbd18a
sync with https://github.com/Seeed-Studio/PN532/releases/tag/v0.9.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 3:4189a10038e6 1 #include "MifareUltralight.h"
yihui 3:4189a10038e6 2
yihui 3:4189a10038e6 3 #include "PN532_debug.h"
yihui 3:4189a10038e6 4
yihui 3:4189a10038e6 5 #define ULTRALIGHT_PAGE_SIZE 4
yihui 3:4189a10038e6 6 #define ULTRALIGHT_READ_SIZE 4 // we should be able to read 16 uint8_ts at a time
yihui 3:4189a10038e6 7
yihui 3:4189a10038e6 8 #define ULTRALIGHT_DATA_START_PAGE 4
yihui 3:4189a10038e6 9 #define ULTRALIGHT_MESSAGE_LENGTH_INDEX 1
yihui 3:4189a10038e6 10 #define ULTRALIGHT_DATA_START_INDEX 2
yihui 3:4189a10038e6 11 #define ULTRALIGHT_MAX_PAGE 63
yihui 3:4189a10038e6 12
yihui 3:4189a10038e6 13 #define NFC_FORUM_TAG_TYPE_2 ("NFC Forum Type 2")
yihui 3:4189a10038e6 14
yihui 3:4189a10038e6 15 MifareUltralight::MifareUltralight(PN532& nfcShield)
yihui 3:4189a10038e6 16 {
yihui 3:4189a10038e6 17 nfc = &nfcShield;
yihui 3:4189a10038e6 18 ndefStartIndex = 0;
yihui 3:4189a10038e6 19 messageLength = 0;
yihui 3:4189a10038e6 20 }
yihui 3:4189a10038e6 21
yihui 3:4189a10038e6 22 MifareUltralight::~MifareUltralight()
yihui 3:4189a10038e6 23 {
yihui 3:4189a10038e6 24 }
yihui 3:4189a10038e6 25
yihui 3:4189a10038e6 26 NfcTag MifareUltralight::read(uint8_t * uid, unsigned int uidLength)
yihui 3:4189a10038e6 27 {
yihui 3:4189a10038e6 28 if (isUnformatted())
yihui 3:4189a10038e6 29 {
yihui 3:4189a10038e6 30 DMSG("WARNING: Tag is not formatted.");
yihui 3:4189a10038e6 31 return NfcTag(uid, uidLength, NFC_FORUM_TAG_TYPE_2);
yihui 3:4189a10038e6 32 }
yihui 3:4189a10038e6 33
yihui 3:4189a10038e6 34 readCapabilityContainer(); // meta info for tag
yihui 3:4189a10038e6 35 findNdefMessage();
yihui 3:4189a10038e6 36 calculateBufferSize();
yihui 3:4189a10038e6 37
yihui 3:4189a10038e6 38 if (messageLength == 0) { // data is 0x44 0x03 0x00 0xFE
yihui 3:4189a10038e6 39 NdefMessage message = NdefMessage();
yihui 3:4189a10038e6 40 message.addEmptyRecord();
yihui 3:4189a10038e6 41 return NfcTag(uid, uidLength, NFC_FORUM_TAG_TYPE_2, message);
yihui 3:4189a10038e6 42 }
yihui 3:4189a10038e6 43
yihui 3:4189a10038e6 44 bool success;
yihui 3:4189a10038e6 45 uint8_t page;
yihui 3:4189a10038e6 46 uint8_t index = 0;
yihui 3:4189a10038e6 47 uint8_t buffer[bufferSize];
yihui 3:4189a10038e6 48 for (page = ULTRALIGHT_DATA_START_PAGE; page < ULTRALIGHT_MAX_PAGE; page++)
yihui 3:4189a10038e6 49 {
yihui 3:4189a10038e6 50 // read the data
yihui 3:4189a10038e6 51 success = nfc->mifareultralight_ReadPage(page, &buffer[index]);
yihui 3:4189a10038e6 52 if (success)
yihui 3:4189a10038e6 53 {
yihui 3:4189a10038e6 54 #ifdef MIFARE_ULTRALIGHT_DEBUG
yihui 3:4189a10038e6 55 DMSG("Page ");Serial.print(page);DMSG(" ");
yihui 3:4189a10038e6 56 nfc->PrintHexChar(&buffer[index], ULTRALIGHT_PAGE_SIZE);
yihui 3:4189a10038e6 57 #endif
yihui 3:4189a10038e6 58 }
yihui 3:4189a10038e6 59 else
yihui 3:4189a10038e6 60 {
yihui 3:4189a10038e6 61 DMSG("Read failed ");DMSG_INT(page);
yihui 3:4189a10038e6 62 // TODO error handling
yihui 3:4189a10038e6 63 messageLength = 0;
yihui 3:4189a10038e6 64 break;
yihui 3:4189a10038e6 65 }
yihui 3:4189a10038e6 66
yihui 3:4189a10038e6 67 if (index >= (messageLength + ndefStartIndex))
yihui 3:4189a10038e6 68 {
yihui 3:4189a10038e6 69 break;
yihui 3:4189a10038e6 70 }
yihui 3:4189a10038e6 71
yihui 3:4189a10038e6 72 index += ULTRALIGHT_PAGE_SIZE;
yihui 3:4189a10038e6 73 }
yihui 3:4189a10038e6 74
yihui 3:4189a10038e6 75 NdefMessage ndefMessage = NdefMessage(&buffer[ndefStartIndex], messageLength);
yihui 3:4189a10038e6 76 return NfcTag(uid, uidLength, NFC_FORUM_TAG_TYPE_2, ndefMessage);
yihui 3:4189a10038e6 77
yihui 3:4189a10038e6 78 }
yihui 3:4189a10038e6 79
yihui 3:4189a10038e6 80 bool MifareUltralight::isUnformatted()
yihui 3:4189a10038e6 81 {
yihui 3:4189a10038e6 82 uint8_t page = 4;
yihui 3:4189a10038e6 83 uint8_t data[ULTRALIGHT_READ_SIZE];
yihui 3:4189a10038e6 84 bool success = nfc->mifareultralight_ReadPage (page, data);
yihui 3:4189a10038e6 85 if (success)
yihui 3:4189a10038e6 86 {
yihui 3:4189a10038e6 87 return (data[0] == 0xFF && data[1] == 0xFF && data[2] == 0xFF && data[3] == 0xFF);
yihui 3:4189a10038e6 88 }
yihui 3:4189a10038e6 89 else
yihui 3:4189a10038e6 90 {
yihui 3:4189a10038e6 91 DMSG("Error. Failed read page ");DMSG_INT(page);
yihui 3:4189a10038e6 92 return false;
yihui 3:4189a10038e6 93 }
yihui 3:4189a10038e6 94 }
yihui 3:4189a10038e6 95
yihui 3:4189a10038e6 96 // page 3 has tag capabilities
yihui 3:4189a10038e6 97 void MifareUltralight::readCapabilityContainer()
yihui 3:4189a10038e6 98 {
yihui 3:4189a10038e6 99 uint8_t data[ULTRALIGHT_PAGE_SIZE];
yihui 3:4189a10038e6 100 int success = nfc->mifareultralight_ReadPage (3, data);
yihui 3:4189a10038e6 101 if (success)
yihui 3:4189a10038e6 102 {
yihui 3:4189a10038e6 103 // See AN1303 - different rules for Mifare Family uint8_t2 = (additional data + 48)/8
yihui 3:4189a10038e6 104 tagCapacity = data[2] * 8;
yihui 3:4189a10038e6 105 #ifdef MIFARE_ULTRALIGHT_DEBUG
yihui 3:4189a10038e6 106 DMSG("Tag capacity "));Serial.print(tagCapacity);DMSG(F(" uint8_ts");
yihui 3:4189a10038e6 107 #endif
yihui 3:4189a10038e6 108
yihui 3:4189a10038e6 109 // TODO future versions should get lock information
yihui 3:4189a10038e6 110 }
yihui 3:4189a10038e6 111 }
yihui 3:4189a10038e6 112
yihui 3:4189a10038e6 113 // read enough of the message to find the ndef message length
yihui 3:4189a10038e6 114 void MifareUltralight::findNdefMessage()
yihui 3:4189a10038e6 115 {
yihui 3:4189a10038e6 116 int page;
yihui 3:4189a10038e6 117 uint8_t data[12]; // 3 pages
yihui 3:4189a10038e6 118 uint8_t* data_ptr = &data[0];
yihui 3:4189a10038e6 119
yihui 3:4189a10038e6 120 // the nxp read command reads 4 pages, unfortunately adafruit give me one page at a time
yihui 3:4189a10038e6 121 bool success = true;
yihui 3:4189a10038e6 122 for (page = 4; page < 6; page++)
yihui 3:4189a10038e6 123 {
yihui 3:4189a10038e6 124 success = success && nfc->mifareultralight_ReadPage(page, data_ptr);
yihui 3:4189a10038e6 125 #ifdef MIFARE_ULTRALIGHT_DEBUG
yihui 3:4189a10038e6 126 DMSG("Page "));Serial.print(page);Serial.print(F(" - ");
yihui 3:4189a10038e6 127 nfc->PrintHexChar(data_ptr, 4);
yihui 3:4189a10038e6 128 #endif
yihui 3:4189a10038e6 129 data_ptr += ULTRALIGHT_PAGE_SIZE;
yihui 3:4189a10038e6 130 }
yihui 3:4189a10038e6 131
yihui 3:4189a10038e6 132 if (success)
yihui 3:4189a10038e6 133 {
yihui 3:4189a10038e6 134 if (data[0] == 0x03)
yihui 3:4189a10038e6 135 {
yihui 3:4189a10038e6 136 messageLength = data[1];
yihui 3:4189a10038e6 137 ndefStartIndex = 2;
yihui 3:4189a10038e6 138 }
yihui 3:4189a10038e6 139 else if (data[5] == 0x3) // page 5 uint8_t 1
yihui 3:4189a10038e6 140 {
yihui 3:4189a10038e6 141 // TODO should really read the lock control TLV to ensure uint8_t[5] is correct
yihui 3:4189a10038e6 142 messageLength = data[6];
yihui 3:4189a10038e6 143 ndefStartIndex = 7;
yihui 3:4189a10038e6 144 }
yihui 3:4189a10038e6 145 }
yihui 3:4189a10038e6 146
yihui 3:4189a10038e6 147 #ifdef MIFARE_ULTRALIGHT_DEBUG
yihui 3:4189a10038e6 148 DMSG("messageLength ");DMSG(messageLength);
yihui 3:4189a10038e6 149 DMSG("ndefStartIndex ");DMSG(ndefStartIndex);
yihui 3:4189a10038e6 150 #endif
yihui 3:4189a10038e6 151 }
yihui 3:4189a10038e6 152
yihui 3:4189a10038e6 153 // buffer is larger than the message, need to handle some data before and after
yihui 3:4189a10038e6 154 // message and need to ensure we read full pages
yihui 3:4189a10038e6 155 void MifareUltralight::calculateBufferSize()
yihui 3:4189a10038e6 156 {
yihui 3:4189a10038e6 157 // TLV terminator 0xFE is 1 uint8_t
yihui 3:4189a10038e6 158 bufferSize = messageLength + ndefStartIndex + 1;
yihui 3:4189a10038e6 159
yihui 3:4189a10038e6 160 if (bufferSize % ULTRALIGHT_READ_SIZE != 0)
yihui 3:4189a10038e6 161 {
yihui 3:4189a10038e6 162 // buffer must be an increment of page size
yihui 3:4189a10038e6 163 bufferSize = ((bufferSize / ULTRALIGHT_READ_SIZE) + 1) * ULTRALIGHT_READ_SIZE;
yihui 3:4189a10038e6 164 }
yihui 3:4189a10038e6 165 }