some additional fixes

Fork of PN532 by Seeed

Committer:
vilesovds
Date:
Thu Jun 02 16:23:37 2016 +0000
Revision:
10:5e24ab94fcc4
Parent:
5:51f820fbd18a
fixed NfcTag::getUid

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
icefeet 5:51f820fbd18a 80 bool MifareUltralight::write(NdefMessage& m, uint8_t * uid, unsigned int uidLength)
icefeet 5:51f820fbd18a 81 {
icefeet 5:51f820fbd18a 82
icefeet 5:51f820fbd18a 83 if (isUnformatted())
icefeet 5:51f820fbd18a 84 {
icefeet 5:51f820fbd18a 85 printf("WARNING: Tag is not formatted.\r\n");
icefeet 5:51f820fbd18a 86 return false;
icefeet 5:51f820fbd18a 87 }
icefeet 5:51f820fbd18a 88 readCapabilityContainer(); // meta info for tag
icefeet 5:51f820fbd18a 89
icefeet 5:51f820fbd18a 90 messageLength = m.getEncodedSize();
icefeet 5:51f820fbd18a 91 ndefStartIndex = messageLength < 0xFF ? 2 : 4;
icefeet 5:51f820fbd18a 92 calculateBufferSize();
icefeet 5:51f820fbd18a 93
icefeet 5:51f820fbd18a 94 if(bufferSize>tagCapacity) {
icefeet 5:51f820fbd18a 95 /* #ifdef MIFARE_ULTRALIGHT_DEBUG
icefeet 5:51f820fbd18a 96 Serial.print(F("Encoded Message length exceeded tag Capacity "));Serial.println(tagCapacity);
icefeet 5:51f820fbd18a 97 #endif*/
icefeet 5:51f820fbd18a 98 return false;
icefeet 5:51f820fbd18a 99 }
icefeet 5:51f820fbd18a 100
icefeet 5:51f820fbd18a 101 uint8_t encoded[bufferSize];
icefeet 5:51f820fbd18a 102 uint8_t * src = encoded;
icefeet 5:51f820fbd18a 103 unsigned int position = 0;
icefeet 5:51f820fbd18a 104 uint8_t page = ULTRALIGHT_DATA_START_PAGE;
icefeet 5:51f820fbd18a 105
icefeet 5:51f820fbd18a 106 // Set message size. With ultralight should always be less than 0xFF but who knows?
icefeet 5:51f820fbd18a 107
icefeet 5:51f820fbd18a 108 encoded[0] = 0x3;
icefeet 5:51f820fbd18a 109 if (messageLength < 0xFF)
icefeet 5:51f820fbd18a 110 {
icefeet 5:51f820fbd18a 111 encoded[1] = messageLength;
icefeet 5:51f820fbd18a 112 }
icefeet 5:51f820fbd18a 113 else
icefeet 5:51f820fbd18a 114 {
icefeet 5:51f820fbd18a 115 encoded[1] = 0xFF;
icefeet 5:51f820fbd18a 116 encoded[2] = ((messageLength >> 8) & 0xFF);
icefeet 5:51f820fbd18a 117 encoded[3] = (messageLength & 0xFF);
icefeet 5:51f820fbd18a 118 }
icefeet 5:51f820fbd18a 119
icefeet 5:51f820fbd18a 120 m.encode(encoded+ndefStartIndex);
icefeet 5:51f820fbd18a 121 // this is always at least 1 byte copy because of terminator.
icefeet 5:51f820fbd18a 122 memset(encoded+ndefStartIndex+messageLength,0,bufferSize-ndefStartIndex-messageLength);
icefeet 5:51f820fbd18a 123 encoded[ndefStartIndex+messageLength] = 0xFE; // terminator
icefeet 5:51f820fbd18a 124
icefeet 5:51f820fbd18a 125 while (position < bufferSize){ //bufferSize is always times pagesize so no "last chunk" check
icefeet 5:51f820fbd18a 126 // write page
icefeet 5:51f820fbd18a 127 if (!nfc->mifareultralight_WritePage(page, src))
icefeet 5:51f820fbd18a 128 return false;
icefeet 5:51f820fbd18a 129 page++;
icefeet 5:51f820fbd18a 130 src+=ULTRALIGHT_PAGE_SIZE;
icefeet 5:51f820fbd18a 131 position+=ULTRALIGHT_PAGE_SIZE;
icefeet 5:51f820fbd18a 132 }
icefeet 5:51f820fbd18a 133 return true;
icefeet 5:51f820fbd18a 134 }
yihui 3:4189a10038e6 135 bool MifareUltralight::isUnformatted()
yihui 3:4189a10038e6 136 {
yihui 3:4189a10038e6 137 uint8_t page = 4;
yihui 3:4189a10038e6 138 uint8_t data[ULTRALIGHT_READ_SIZE];
yihui 3:4189a10038e6 139 bool success = nfc->mifareultralight_ReadPage (page, data);
yihui 3:4189a10038e6 140 if (success)
yihui 3:4189a10038e6 141 {
yihui 3:4189a10038e6 142 return (data[0] == 0xFF && data[1] == 0xFF && data[2] == 0xFF && data[3] == 0xFF);
yihui 3:4189a10038e6 143 }
yihui 3:4189a10038e6 144 else
yihui 3:4189a10038e6 145 {
yihui 3:4189a10038e6 146 DMSG("Error. Failed read page ");DMSG_INT(page);
yihui 3:4189a10038e6 147 return false;
yihui 3:4189a10038e6 148 }
yihui 3:4189a10038e6 149 }
yihui 3:4189a10038e6 150
yihui 3:4189a10038e6 151 // page 3 has tag capabilities
yihui 3:4189a10038e6 152 void MifareUltralight::readCapabilityContainer()
yihui 3:4189a10038e6 153 {
yihui 3:4189a10038e6 154 uint8_t data[ULTRALIGHT_PAGE_SIZE];
yihui 3:4189a10038e6 155 int success = nfc->mifareultralight_ReadPage (3, data);
yihui 3:4189a10038e6 156 if (success)
yihui 3:4189a10038e6 157 {
yihui 3:4189a10038e6 158 // See AN1303 - different rules for Mifare Family uint8_t2 = (additional data + 48)/8
yihui 3:4189a10038e6 159 tagCapacity = data[2] * 8;
yihui 3:4189a10038e6 160 #ifdef MIFARE_ULTRALIGHT_DEBUG
yihui 3:4189a10038e6 161 DMSG("Tag capacity "));Serial.print(tagCapacity);DMSG(F(" uint8_ts");
yihui 3:4189a10038e6 162 #endif
yihui 3:4189a10038e6 163
yihui 3:4189a10038e6 164 // TODO future versions should get lock information
yihui 3:4189a10038e6 165 }
yihui 3:4189a10038e6 166 }
yihui 3:4189a10038e6 167
yihui 3:4189a10038e6 168 // read enough of the message to find the ndef message length
yihui 3:4189a10038e6 169 void MifareUltralight::findNdefMessage()
yihui 3:4189a10038e6 170 {
yihui 3:4189a10038e6 171 int page;
yihui 3:4189a10038e6 172 uint8_t data[12]; // 3 pages
yihui 3:4189a10038e6 173 uint8_t* data_ptr = &data[0];
yihui 3:4189a10038e6 174
yihui 3:4189a10038e6 175 // the nxp read command reads 4 pages, unfortunately adafruit give me one page at a time
yihui 3:4189a10038e6 176 bool success = true;
yihui 3:4189a10038e6 177 for (page = 4; page < 6; page++)
yihui 3:4189a10038e6 178 {
yihui 3:4189a10038e6 179 success = success && nfc->mifareultralight_ReadPage(page, data_ptr);
yihui 3:4189a10038e6 180 #ifdef MIFARE_ULTRALIGHT_DEBUG
yihui 3:4189a10038e6 181 DMSG("Page "));Serial.print(page);Serial.print(F(" - ");
yihui 3:4189a10038e6 182 nfc->PrintHexChar(data_ptr, 4);
yihui 3:4189a10038e6 183 #endif
yihui 3:4189a10038e6 184 data_ptr += ULTRALIGHT_PAGE_SIZE;
yihui 3:4189a10038e6 185 }
yihui 3:4189a10038e6 186
yihui 3:4189a10038e6 187 if (success)
yihui 3:4189a10038e6 188 {
yihui 3:4189a10038e6 189 if (data[0] == 0x03)
yihui 3:4189a10038e6 190 {
yihui 3:4189a10038e6 191 messageLength = data[1];
yihui 3:4189a10038e6 192 ndefStartIndex = 2;
yihui 3:4189a10038e6 193 }
yihui 3:4189a10038e6 194 else if (data[5] == 0x3) // page 5 uint8_t 1
yihui 3:4189a10038e6 195 {
yihui 3:4189a10038e6 196 // TODO should really read the lock control TLV to ensure uint8_t[5] is correct
yihui 3:4189a10038e6 197 messageLength = data[6];
yihui 3:4189a10038e6 198 ndefStartIndex = 7;
yihui 3:4189a10038e6 199 }
yihui 3:4189a10038e6 200 }
yihui 3:4189a10038e6 201
yihui 3:4189a10038e6 202 #ifdef MIFARE_ULTRALIGHT_DEBUG
yihui 3:4189a10038e6 203 DMSG("messageLength ");DMSG(messageLength);
yihui 3:4189a10038e6 204 DMSG("ndefStartIndex ");DMSG(ndefStartIndex);
yihui 3:4189a10038e6 205 #endif
yihui 3:4189a10038e6 206 }
yihui 3:4189a10038e6 207
yihui 3:4189a10038e6 208 // buffer is larger than the message, need to handle some data before and after
yihui 3:4189a10038e6 209 // message and need to ensure we read full pages
yihui 3:4189a10038e6 210 void MifareUltralight::calculateBufferSize()
yihui 3:4189a10038e6 211 {
yihui 3:4189a10038e6 212 // TLV terminator 0xFE is 1 uint8_t
yihui 3:4189a10038e6 213 bufferSize = messageLength + ndefStartIndex + 1;
yihui 3:4189a10038e6 214
yihui 3:4189a10038e6 215 if (bufferSize % ULTRALIGHT_READ_SIZE != 0)
yihui 3:4189a10038e6 216 {
yihui 3:4189a10038e6 217 // buffer must be an increment of page size
yihui 3:4189a10038e6 218 bufferSize = ((bufferSize / ULTRALIGHT_READ_SIZE) + 1) * ULTRALIGHT_READ_SIZE;
yihui 3:4189a10038e6 219 }
yihui 3:4189a10038e6 220 }