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@3:4189a10038e6, 2013-11-21 (annotated)
- 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?
User | Revision | Line number | New 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 | } |