Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of PN532 by
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::write(NdefMessage& m, uint8_t * uid, unsigned int uidLength) 00081 { 00082 00083 if (isUnformatted()) 00084 { 00085 printf("WARNING: Tag is not formatted.\r\n"); 00086 return false; 00087 } 00088 readCapabilityContainer(); // meta info for tag 00089 00090 messageLength = m.getEncodedSize(); 00091 ndefStartIndex = messageLength < 0xFF ? 2 : 4; 00092 calculateBufferSize(); 00093 00094 if(bufferSize>tagCapacity) { 00095 /* #ifdef MIFARE_ULTRALIGHT_DEBUG 00096 Serial.print(F("Encoded Message length exceeded tag Capacity "));Serial.println(tagCapacity); 00097 #endif*/ 00098 return false; 00099 } 00100 00101 uint8_t encoded[bufferSize]; 00102 uint8_t * src = encoded; 00103 unsigned int position = 0; 00104 uint8_t page = ULTRALIGHT_DATA_START_PAGE; 00105 00106 // Set message size. With ultralight should always be less than 0xFF but who knows? 00107 00108 encoded[0] = 0x3; 00109 if (messageLength < 0xFF) 00110 { 00111 encoded[1] = messageLength; 00112 } 00113 else 00114 { 00115 encoded[1] = 0xFF; 00116 encoded[2] = ((messageLength >> 8) & 0xFF); 00117 encoded[3] = (messageLength & 0xFF); 00118 } 00119 00120 m.encode(encoded+ndefStartIndex); 00121 // this is always at least 1 byte copy because of terminator. 00122 memset(encoded+ndefStartIndex+messageLength,0,bufferSize-ndefStartIndex-messageLength); 00123 encoded[ndefStartIndex+messageLength] = 0xFE; // terminator 00124 00125 while (position < bufferSize){ //bufferSize is always times pagesize so no "last chunk" check 00126 // write page 00127 if (!nfc->mifareultralight_WritePage(page, src)) 00128 return false; 00129 page++; 00130 src+=ULTRALIGHT_PAGE_SIZE; 00131 position+=ULTRALIGHT_PAGE_SIZE; 00132 } 00133 return true; 00134 } 00135 bool MifareUltralight::isUnformatted() 00136 { 00137 uint8_t page = 4; 00138 uint8_t data[ULTRALIGHT_READ_SIZE]; 00139 bool success = nfc->mifareultralight_ReadPage (page, data); 00140 if (success) 00141 { 00142 return (data[0] == 0xFF && data[1] == 0xFF && data[2] == 0xFF && data[3] == 0xFF); 00143 } 00144 else 00145 { 00146 DMSG("Error. Failed read page ");DMSG_INT(page); 00147 return false; 00148 } 00149 } 00150 00151 // page 3 has tag capabilities 00152 void MifareUltralight::readCapabilityContainer() 00153 { 00154 uint8_t data[ULTRALIGHT_PAGE_SIZE]; 00155 int success = nfc->mifareultralight_ReadPage (3, data); 00156 if (success) 00157 { 00158 // See AN1303 - different rules for Mifare Family uint8_t2 = (additional data + 48)/8 00159 tagCapacity = data[2] * 8; 00160 #ifdef MIFARE_ULTRALIGHT_DEBUG 00161 DMSG("Tag capacity "));Serial.print(tagCapacity);DMSG(F(" uint8_ts"); 00162 #endif 00163 00164 // TODO future versions should get lock information 00165 } 00166 } 00167 00168 // read enough of the message to find the ndef message length 00169 void MifareUltralight::findNdefMessage() 00170 { 00171 int page; 00172 uint8_t data[12]; // 3 pages 00173 uint8_t* data_ptr = &data[0]; 00174 00175 // the nxp read command reads 4 pages, unfortunately adafruit give me one page at a time 00176 bool success = true; 00177 for (page = 4; page < 6; page++) 00178 { 00179 success = success && nfc->mifareultralight_ReadPage(page, data_ptr); 00180 #ifdef MIFARE_ULTRALIGHT_DEBUG 00181 DMSG("Page "));Serial.print(page);Serial.print(F(" - "); 00182 nfc->PrintHexChar(data_ptr, 4); 00183 #endif 00184 data_ptr += ULTRALIGHT_PAGE_SIZE; 00185 } 00186 00187 if (success) 00188 { 00189 if (data[0] == 0x03) 00190 { 00191 messageLength = data[1]; 00192 ndefStartIndex = 2; 00193 } 00194 else if (data[5] == 0x3) // page 5 uint8_t 1 00195 { 00196 // TODO should really read the lock control TLV to ensure uint8_t[5] is correct 00197 messageLength = data[6]; 00198 ndefStartIndex = 7; 00199 } 00200 } 00201 00202 #ifdef MIFARE_ULTRALIGHT_DEBUG 00203 DMSG("messageLength ");DMSG(messageLength); 00204 DMSG("ndefStartIndex ");DMSG(ndefStartIndex); 00205 #endif 00206 } 00207 00208 // buffer is larger than the message, need to handle some data before and after 00209 // message and need to ensure we read full pages 00210 void MifareUltralight::calculateBufferSize() 00211 { 00212 // TLV terminator 0xFE is 1 uint8_t 00213 bufferSize = messageLength + ndefStartIndex + 1; 00214 00215 if (bufferSize % ULTRALIGHT_READ_SIZE != 0) 00216 { 00217 // buffer must be an increment of page size 00218 bufferSize = ((bufferSize / ULTRALIGHT_READ_SIZE) + 1) * ULTRALIGHT_READ_SIZE; 00219 } 00220 }
Generated on Tue Jul 12 2022 16:40:03 by
1.7.2
