PN532 customized

Fork of PN532 by Components

Committer:
stanvn
Date:
Thu Feb 11 11:56:00 2016 +0000
Revision:
10:2fcf2448d199
Parent:
7:a26fa6ef10eb
Working code for reading type-a and type-b cards

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 3:4189a10038e6 1 #include "MifareClassic.h"
yihui 3:4189a10038e6 2 #include "PN532_debug.h"
yihui 3:4189a10038e6 3
yihui 3:4189a10038e6 4 #define BLOCK_SIZE 16
yihui 3:4189a10038e6 5 #define LONG_TLV_SIZE 4
yihui 3:4189a10038e6 6 #define SHORT_TLV_SIZE 2
yihui 3:4189a10038e6 7
yihui 3:4189a10038e6 8 #define MIFARE_CLASSIC ("Mifare Classic")
stanvn 7:a26fa6ef10eb 9 #define TAG_TYPE_MIFARE_MINI (0)
stanvn 7:a26fa6ef10eb 10 #define TAG_TYPE_MIFARE_1K (1)
stanvn 7:a26fa6ef10eb 11 #define TAG_TYPE_MIFARE_4K (2)
stanvn 7:a26fa6ef10eb 12 #define TAG_TYPE_MIFARE_UL (3)
stanvn 7:a26fa6ef10eb 13 #define TAG_TYPE_MIFARE_PLUS_2K (4)
stanvn 7:a26fa6ef10eb 14 #define TAG_TYPE_MIFARE_PLUS_4K (5)
stanvn 7:a26fa6ef10eb 15 #define TAG_TYPE_14443 (6)
yihui 3:4189a10038e6 16
stanvn 7:a26fa6ef10eb 17
stanvn 7:a26fa6ef10eb 18 MifareClassic::MifareClassic(PN532& nfcShield, uint8_t tag_type)
yihui 3:4189a10038e6 19 {
yihui 3:4189a10038e6 20 _nfcShield = &nfcShield;
stanvn 7:a26fa6ef10eb 21 if(tag_type == TAG_TYPE_MIFARE_MINI)
stanvn 7:a26fa6ef10eb 22 type = "Mifare Classic Mini";
stanvn 7:a26fa6ef10eb 23 else if(tag_type == TAG_TYPE_MIFARE_1K)
stanvn 7:a26fa6ef10eb 24 type = "Mifare Classic 1K";
stanvn 7:a26fa6ef10eb 25 else if(tag_type == TAG_TYPE_MIFARE_4K)
stanvn 7:a26fa6ef10eb 26 type = "Mifare Classic 4K";
stanvn 7:a26fa6ef10eb 27 else if(tag_type == TAG_TYPE_MIFARE_PLUS_2K)
stanvn 7:a26fa6ef10eb 28 type = "Mifare plus 2K";
stanvn 7:a26fa6ef10eb 29 else if(tag_type == TAG_TYPE_MIFARE_PLUS_4K)
stanvn 7:a26fa6ef10eb 30 type = "Mifare plus 4K";
stanvn 7:a26fa6ef10eb 31 else
stanvn 7:a26fa6ef10eb 32 type = "Unknown";
yihui 3:4189a10038e6 33 }
yihui 3:4189a10038e6 34
yihui 3:4189a10038e6 35 MifareClassic::~MifareClassic()
yihui 3:4189a10038e6 36 {
yihui 3:4189a10038e6 37 }
yihui 3:4189a10038e6 38
yihui 3:4189a10038e6 39 NfcTag MifareClassic::read(uint8_t *uid, unsigned int uidLength)
yihui 3:4189a10038e6 40 {
yihui 3:4189a10038e6 41 uint8_t key[6] = { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 };
yihui 3:4189a10038e6 42 int currentBlock = 4;
yihui 3:4189a10038e6 43 int messageStartIndex = 0;
yihui 3:4189a10038e6 44 int messageLength = 0;
yihui 3:4189a10038e6 45 uint8_t data[BLOCK_SIZE];
yihui 3:4189a10038e6 46
yihui 3:4189a10038e6 47 // read first block to get message length
yihui 3:4189a10038e6 48 int success = _nfcShield->mifareclassic_AuthenticateBlock(uid, uidLength, currentBlock, 0, key);
yihui 3:4189a10038e6 49 if (success)
yihui 3:4189a10038e6 50 {
yihui 3:4189a10038e6 51 success = _nfcShield->mifareclassic_ReadDataBlock(currentBlock, data);
yihui 3:4189a10038e6 52 if (success)
yihui 3:4189a10038e6 53 {
yihui 3:4189a10038e6 54 if (!decodeTlv(data, messageLength, messageStartIndex)) {
yihui 3:4189a10038e6 55 return NfcTag(uid, uidLength, "ERROR"); // TODO should the error message go in NfcTag?
yihui 3:4189a10038e6 56 }
yihui 3:4189a10038e6 57 }
yihui 3:4189a10038e6 58 else
yihui 3:4189a10038e6 59 {
yihui 3:4189a10038e6 60 DMSG("Error. Failed read block ");
yihui 3:4189a10038e6 61 DMSG_INT(currentBlock);
stanvn 7:a26fa6ef10eb 62 return NfcTag(uid, uidLength, type);
yihui 3:4189a10038e6 63 }
yihui 3:4189a10038e6 64 }
yihui 3:4189a10038e6 65 else
yihui 3:4189a10038e6 66 {
yihui 3:4189a10038e6 67 DMSG("Tag is not NDEF formatted.");
yihui 3:4189a10038e6 68 // TODO set tag.isFormatted = false
stanvn 7:a26fa6ef10eb 69 return NfcTag(uid, uidLength, type);
yihui 3:4189a10038e6 70 }
yihui 3:4189a10038e6 71
yihui 3:4189a10038e6 72 // this should be nested in the message length loop
yihui 3:4189a10038e6 73 int index = 0;
yihui 3:4189a10038e6 74 int bufferSize = getBufferSize(messageLength);
yihui 3:4189a10038e6 75 uint8_t buffer[bufferSize];
yihui 3:4189a10038e6 76
yihui 3:4189a10038e6 77 #ifdef MIFARE_CLASSIC_DEBUG
yihui 3:4189a10038e6 78 DMSG("Message Length ");
yihui 3:4189a10038e6 79 DMSG_INT(messageLength);
yihui 3:4189a10038e6 80 DMSG("Buffer Size ");
yihui 3:4189a10038e6 81 DMSG_INT(bufferSize);
yihui 3:4189a10038e6 82 #endif
yihui 3:4189a10038e6 83
yihui 3:4189a10038e6 84 while (index < bufferSize)
yihui 3:4189a10038e6 85 {
yihui 3:4189a10038e6 86
yihui 3:4189a10038e6 87 // authenticate on every sector
yihui 3:4189a10038e6 88 if (_nfcShield->mifareclassic_IsFirstBlock(currentBlock))
yihui 3:4189a10038e6 89 {
yihui 3:4189a10038e6 90 success = _nfcShield->mifareclassic_AuthenticateBlock(uid, uidLength, currentBlock, 0, key);
yihui 3:4189a10038e6 91 if (!success)
yihui 3:4189a10038e6 92 {
yihui 3:4189a10038e6 93 DMSG("Error. Block Authentication failed for ");
yihui 3:4189a10038e6 94 DMSG_INT(currentBlock);
yihui 3:4189a10038e6 95 // TODO error handling
yihui 3:4189a10038e6 96 }
yihui 3:4189a10038e6 97 }
yihui 3:4189a10038e6 98
yihui 3:4189a10038e6 99 // read the data
yihui 3:4189a10038e6 100 success = _nfcShield->mifareclassic_ReadDataBlock(currentBlock, &buffer[index]);
yihui 3:4189a10038e6 101 if (success)
yihui 3:4189a10038e6 102 {
yihui 3:4189a10038e6 103 #ifdef MIFARE_CLASSIC_DEBUG
yihui 3:4189a10038e6 104 DMSG("Block ");
yihui 3:4189a10038e6 105 DMSG_INT(currentBlock);
yihui 3:4189a10038e6 106 _nfcShield->PrintHexChar(&buffer[index], BLOCK_SIZE);
yihui 3:4189a10038e6 107 #endif
yihui 3:4189a10038e6 108 }
yihui 3:4189a10038e6 109 else
yihui 3:4189a10038e6 110 {
yihui 3:4189a10038e6 111 DMSG("Read failed ");
yihui 3:4189a10038e6 112 DMSG_INT(currentBlock);
yihui 3:4189a10038e6 113 // TODO handle errors here
yihui 3:4189a10038e6 114 }
yihui 3:4189a10038e6 115
yihui 3:4189a10038e6 116 index += BLOCK_SIZE;
yihui 3:4189a10038e6 117 currentBlock++;
yihui 3:4189a10038e6 118
yihui 3:4189a10038e6 119 // skip the trailer block
yihui 3:4189a10038e6 120 if (_nfcShield->mifareclassic_IsTrailerBlock(currentBlock))
yihui 3:4189a10038e6 121 {
yihui 3:4189a10038e6 122 #ifdef MIFARE_CLASSIC_DEBUG
yihui 3:4189a10038e6 123 DMSG("Skipping block ");
yihui 3:4189a10038e6 124 DMSG_INT(currentBlock);
yihui 3:4189a10038e6 125 #endif
yihui 3:4189a10038e6 126 currentBlock++;
yihui 3:4189a10038e6 127 }
yihui 3:4189a10038e6 128 }
yihui 3:4189a10038e6 129
stanvn 7:a26fa6ef10eb 130 return NfcTag(uid, uidLength, type, &buffer[messageStartIndex], messageLength);
yihui 3:4189a10038e6 131 }
yihui 3:4189a10038e6 132
yihui 3:4189a10038e6 133 int MifareClassic::getBufferSize(int messageLength)
yihui 3:4189a10038e6 134 {
yihui 3:4189a10038e6 135
yihui 3:4189a10038e6 136 int bufferSize = messageLength;
yihui 3:4189a10038e6 137
yihui 3:4189a10038e6 138 // TLV header is 2 or 4 uint8_ts, TLV terminator is 1 uint8_t.
yihui 3:4189a10038e6 139 if (messageLength < 0xFF)
yihui 3:4189a10038e6 140 {
yihui 3:4189a10038e6 141 bufferSize += SHORT_TLV_SIZE + 1;
yihui 3:4189a10038e6 142 }
yihui 3:4189a10038e6 143 else
yihui 3:4189a10038e6 144 {
yihui 3:4189a10038e6 145 bufferSize += LONG_TLV_SIZE + 1;
yihui 3:4189a10038e6 146 }
yihui 3:4189a10038e6 147
yihui 3:4189a10038e6 148 // bufferSize needs to be a multiple of BLOCK_SIZE
yihui 3:4189a10038e6 149 if (bufferSize % BLOCK_SIZE != 0)
yihui 3:4189a10038e6 150 {
yihui 3:4189a10038e6 151 bufferSize = ((bufferSize / BLOCK_SIZE) + 1) * BLOCK_SIZE;
yihui 3:4189a10038e6 152 }
yihui 3:4189a10038e6 153
yihui 3:4189a10038e6 154 return bufferSize;
yihui 3:4189a10038e6 155 }
yihui 3:4189a10038e6 156
yihui 3:4189a10038e6 157 // skip null tlvs (0x0) before the real message
yihui 3:4189a10038e6 158 // technically unlimited null tlvs, but we assume
yihui 3:4189a10038e6 159 // T & L of TLV in the first block we read
yihui 3:4189a10038e6 160 int MifareClassic::getNdefStartIndex(uint8_t *data)
yihui 3:4189a10038e6 161 {
yihui 3:4189a10038e6 162
yihui 3:4189a10038e6 163 for (int i = 0; i < BLOCK_SIZE; i++)
yihui 3:4189a10038e6 164 {
yihui 3:4189a10038e6 165 if (data[i] == 0x0)
yihui 3:4189a10038e6 166 {
yihui 3:4189a10038e6 167 // do nothing, skip
yihui 3:4189a10038e6 168 }
yihui 3:4189a10038e6 169 else if (data[i] == 0x3)
yihui 3:4189a10038e6 170 {
yihui 3:4189a10038e6 171 return i;
yihui 3:4189a10038e6 172 }
yihui 3:4189a10038e6 173 else
yihui 3:4189a10038e6 174 {
yihui 3:4189a10038e6 175 DMSG("Unknown TLV ");
yihui 3:4189a10038e6 176 DMSG_HEX(data[i]);
yihui 3:4189a10038e6 177 return -2;
yihui 3:4189a10038e6 178 }
yihui 3:4189a10038e6 179 }
yihui 3:4189a10038e6 180
yihui 3:4189a10038e6 181 return -1;
yihui 3:4189a10038e6 182 }
yihui 3:4189a10038e6 183
yihui 3:4189a10038e6 184 // Decode the NDEF data length from the Mifare TLV
yihui 3:4189a10038e6 185 // Leading null TLVs (0x0) are skipped
yihui 3:4189a10038e6 186 // Assuming T & L of TLV will be in the first block
yihui 3:4189a10038e6 187 // messageLength and messageStartIndex written to the parameters
yihui 3:4189a10038e6 188 // success or failure status is returned
yihui 3:4189a10038e6 189 //
yihui 3:4189a10038e6 190 // { 0x3, LENGTH }
yihui 3:4189a10038e6 191 // { 0x3, 0xFF, LENGTH, LENGTH }
yihui 3:4189a10038e6 192 bool MifareClassic::decodeTlv(uint8_t *data, int &messageLength, int &messageStartIndex)
yihui 3:4189a10038e6 193 {
yihui 3:4189a10038e6 194 int i = getNdefStartIndex(data);
yihui 3:4189a10038e6 195
yihui 3:4189a10038e6 196 if (i < 0 || data[i] != 0x3)
yihui 3:4189a10038e6 197 {
yihui 3:4189a10038e6 198 DMSG("Error. Can't decode message length.");
yihui 3:4189a10038e6 199 return false;
yihui 3:4189a10038e6 200 }
yihui 3:4189a10038e6 201 else
yihui 3:4189a10038e6 202 {
yihui 3:4189a10038e6 203 if (data[i+1] == 0xFF)
yihui 3:4189a10038e6 204 {
yihui 3:4189a10038e6 205 messageLength = ((0xFF & data[i+2]) << 8) | (0xFF & data[i+3]);
yihui 3:4189a10038e6 206 messageStartIndex = i + LONG_TLV_SIZE;
yihui 3:4189a10038e6 207 }
yihui 3:4189a10038e6 208 else
yihui 3:4189a10038e6 209 {
yihui 3:4189a10038e6 210 messageLength = data[i+1];
yihui 3:4189a10038e6 211 messageStartIndex = i + SHORT_TLV_SIZE;
yihui 3:4189a10038e6 212 }
yihui 3:4189a10038e6 213 }
yihui 3:4189a10038e6 214
yihui 3:4189a10038e6 215 return true;
yihui 3:4189a10038e6 216 }
yihui 3:4189a10038e6 217
yihui 3:4189a10038e6 218 bool MifareClassic::write(NdefMessage& m, uint8_t * uid, unsigned int uidLength)
yihui 3:4189a10038e6 219 {
yihui 3:4189a10038e6 220
yihui 3:4189a10038e6 221 uint8_t encoded[m.getEncodedSize()];
yihui 3:4189a10038e6 222 m.encode(encoded);
yihui 3:4189a10038e6 223
yihui 3:4189a10038e6 224 uint8_t buffer[getBufferSize(sizeof(encoded))];
yihui 3:4189a10038e6 225 memset(buffer, 0, sizeof(buffer));
yihui 3:4189a10038e6 226
yihui 3:4189a10038e6 227 #ifdef MIFARE_CLASSIC_DEBUG
yihui 3:4189a10038e6 228 DMSG("sizeof(encoded) "));DMSG(sizeof(encoded);
yihui 3:4189a10038e6 229 DMSG("sizeof(buffer) "));DMSG(sizeof(buffer);
yihui 3:4189a10038e6 230 #endif
yihui 3:4189a10038e6 231
yihui 3:4189a10038e6 232 if (sizeof(encoded) < 0xFF)
yihui 3:4189a10038e6 233 {
yihui 3:4189a10038e6 234 buffer[0] = 0x3;
yihui 3:4189a10038e6 235 buffer[1] = sizeof(encoded);
yihui 3:4189a10038e6 236 memcpy(&buffer[2], encoded, sizeof(encoded));
yihui 3:4189a10038e6 237 buffer[2+sizeof(encoded)] = 0xFE; // terminator
yihui 3:4189a10038e6 238 }
yihui 3:4189a10038e6 239 else
yihui 3:4189a10038e6 240 {
yihui 3:4189a10038e6 241 buffer[0] = 0x3;
yihui 3:4189a10038e6 242 buffer[1] = 0xFF;
yihui 3:4189a10038e6 243 buffer[2] = ((sizeof(encoded) >> 8) & 0xFF);
yihui 3:4189a10038e6 244 buffer[3] = (sizeof(encoded) & 0xFF);
yihui 3:4189a10038e6 245 memcpy(&buffer[4], encoded, sizeof(encoded));
yihui 3:4189a10038e6 246 buffer[4+sizeof(encoded)] = 0xFE; // terminator
yihui 3:4189a10038e6 247 }
yihui 3:4189a10038e6 248
yihui 3:4189a10038e6 249 // Write to tag
yihui 3:4189a10038e6 250 int index = 0;
yihui 3:4189a10038e6 251 int currentBlock = 4;
yihui 3:4189a10038e6 252 uint8_t key[6] = { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 }; // this is Sector 1 - 15 key
yihui 3:4189a10038e6 253
yihui 3:4189a10038e6 254 while (index < sizeof(buffer))
yihui 3:4189a10038e6 255 {
yihui 3:4189a10038e6 256
yihui 3:4189a10038e6 257 if (_nfcShield->mifareclassic_IsFirstBlock(currentBlock))
yihui 3:4189a10038e6 258 {
yihui 3:4189a10038e6 259 int success = _nfcShield->mifareclassic_AuthenticateBlock(uid, uidLength, currentBlock, 0, key);
yihui 3:4189a10038e6 260 if (!success)
yihui 3:4189a10038e6 261 {
yihui 3:4189a10038e6 262 DMSG("Error. Block Authentication failed for ");DMSG_INT(currentBlock);
yihui 3:4189a10038e6 263 return false;
yihui 3:4189a10038e6 264 }
yihui 3:4189a10038e6 265 }
yihui 3:4189a10038e6 266
yihui 3:4189a10038e6 267 int write_success = _nfcShield->mifareclassic_WriteDataBlock (currentBlock, &buffer[index]);
yihui 3:4189a10038e6 268 if (write_success)
yihui 3:4189a10038e6 269 {
yihui 3:4189a10038e6 270 #ifdef MIFARE_CLASSIC_DEBUG
yihui 3:4189a10038e6 271 DMSG("Wrote block ");Serial.print(currentBlock);DMSG(" - ");
yihui 3:4189a10038e6 272 _nfcShield->PrintHexChar(&buffer[index], BLOCK_SIZE);
yihui 3:4189a10038e6 273 #endif
yihui 3:4189a10038e6 274 }
yihui 3:4189a10038e6 275 else
yihui 3:4189a10038e6 276 {
yihui 3:4189a10038e6 277 DMSG("Write failed ");DMSG_INT(currentBlock);
yihui 3:4189a10038e6 278 return false;
yihui 3:4189a10038e6 279 }
yihui 3:4189a10038e6 280 index += BLOCK_SIZE;
yihui 3:4189a10038e6 281 currentBlock++;
yihui 3:4189a10038e6 282
yihui 3:4189a10038e6 283 if (_nfcShield->mifareclassic_IsTrailerBlock(currentBlock))
yihui 3:4189a10038e6 284 {
yihui 3:4189a10038e6 285 // can't write to trailer block
yihui 3:4189a10038e6 286 #ifdef MIFARE_CLASSIC_DEBUG
yihui 3:4189a10038e6 287 DMSG("Skipping block ");DMSG(currentBlock);
yihui 3:4189a10038e6 288 #endif
yihui 3:4189a10038e6 289 currentBlock++;
yihui 3:4189a10038e6 290 }
yihui 3:4189a10038e6 291
yihui 3:4189a10038e6 292 }
yihui 3:4189a10038e6 293
yihui 3:4189a10038e6 294 return true;
yihui 3:4189a10038e6 295 }