NFC library using PN532 to read/write NDEF Messages to NFC tags
Dependents: Seeed_NFC_Shield_write Nucleo_test_nfc
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::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 }
Generated on Tue Jul 12 2022 21:59:39 by 1.7.2