NfcTag MifareUltralight::read(byte * uid, unsigned int uidLength) { if (isUnformatted()) { Serial.println(F("WARNING: Tag is not formatted.")); return NfcTag(uid, uidLength, NFC_FORUM_TAG_TYPE_2); } readCapabilityContainer(); // meta info for tag findNdefMessage(); calculateBufferSize(); if (messageLength == 0) { // data is 0x44 0x03 0x00 0xFE NdefMessage message = NdefMessage(); message.addEmptyRecord(); return NfcTag(uid, uidLength, NFC_FORUM_TAG_TYPE_2, message); } boolean success; uint8_t page; uint8_t index = 0; byte buffer[bufferSize]; for (page = ULTRALIGHT_DATA_START_PAGE; page < ULTRALIGHT_MAX_PAGE; page++) { // read the data success = nfc->mifareultralight_ReadPage(page, &buffer[index]); if (success) { #ifdef MIFARE_ULTRALIGHT_DEBUG Serial.print(F("Page ")); Serial.print(page); Serial.print(" "); nfc->PrintHexChar(&buffer[index], ULTRALIGHT_PAGE_SIZE); #endif } else { Serial.print(F("Read failed ")); Serial.println(page); // TODO error handling messageLength = 0; break; } if (index >= (messageLength + ndefStartIndex)) { break; } index += ULTRALIGHT_PAGE_SIZE; } NdefMessage ndefMessage = NdefMessage(&buffer[ndefStartIndex], messageLength); return NfcTag(uid, uidLength, NFC_FORUM_TAG_TYPE_2, ndefMessage); }
NfcTag NfcAdapter::read() { uint8_t type = guessTagType(); // TODO need an abstraction of Driver if (type == TAG_TYPE_MIFARE_CLASSIC) { #ifdef NDEF_DEBUG DMSG("Reading Mifare Classic"); #endif MifareClassic mifareClassic = MifareClassic(*shield); return mifareClassic.read(uid, uidLength); } else if (type == TAG_TYPE_2) { #ifdef NDEF_DEBUG DMSG("Reading Mifare Ultralight"); #endif MifareUltralight ultralight = MifareUltralight(*shield); return ultralight.read(uid, uidLength); } else if (type == TAG_TYPE_UNKNOWN) { DMSG("Can not determine tag type"); //DMSG("Can not determine tag type for ATQA 0x"); //Serial.print(atqa, HEX);DMSG(" SAK 0x");DMSG(sak, HEX); return NfcTag(uid, uidLength); } else { DMSG("No driver for card type "); DMSG_INT(type); // TODO should set type here return NfcTag(uid, uidLength); } }
NfcTag MifareClassic::read(byte *uid, unsigned int uidLength) { uint8_t key[6] = { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 }; int currentBlock = 4; int messageLength = 0; byte data[BLOCK_SIZE]; // read first block to get message length int success = _nfcShield->mifareclassic_AuthenticateBlock(uid, uidLength, currentBlock, 0, key); if (success) { success = _nfcShield->mifareclassic_ReadDataBlock(currentBlock, data); if (success) { messageLength = getNdefLength(data); if (messageLength < 1) { return NfcTag(uid, uidLength, "ERROR"); // TODO should the error message go in NfcTag? } } else { // TODO why is an unformatted tag ending up here? Authentication should have failed. Serial.print(F("Error. Failed read block "));Serial.println(currentBlock); return NfcTag(uid, uidLength, MIFARE_CLASSIC); } } else { Serial.print(F("Error. Block Authentication failed for "));Serial.println(currentBlock); // TODO unformatted tags should be ending up here // TODO set tag.isFormatted = false return NfcTag(uid, uidLength, MIFARE_CLASSIC); } // this should be nested in the message length loop int index = 0; int bufferSize = getBufferSize(messageLength); uint8_t buffer[bufferSize]; #ifdef MIFARE_CLASSIC_DEBUG Serial.print(F("Message Length "));Serial.println(messageLength); Serial.print(F("Buffer Size "));Serial.println(bufferSize); #endif while (index < bufferSize) { // authenticate on every sector if (_nfcShield->mifareclassic_IsFirstBlock(currentBlock)) { success = _nfcShield->mifareclassic_AuthenticateBlock(uid, uidLength, currentBlock, 0, key); if (!success) { Serial.print(F("Error. Block Authentication failed for "));Serial.println(currentBlock); // TODO error handling } } // read the data success = _nfcShield->mifareclassic_ReadDataBlock(currentBlock, &buffer[index]); if (success) { #ifdef MIFARE_CLASSIC_DEBUG Serial.print(F("Block "));Serial.print(currentBlock);Serial.print(" "); _nfcShield->PrintHexChar(&buffer[index], BLOCK_SIZE); #endif } else { Serial.print(F("Read failed "));Serial.println(currentBlock); // TODO handle errors here } index += BLOCK_SIZE; currentBlock++; // skip the trailer block if (_nfcShield->mifareclassic_IsTrailerBlock(currentBlock)) { #ifdef MIFARE_CLASSIC_DEBUG Serial.print(F("Skipping block "));Serial.println(currentBlock); #endif currentBlock++; } } // NdefMessage ndefMessage = NdefMessage(&buffer[4], messageLength); // NfcTag tag = NfcTag(uid, uidLength, "Mifare Classic", ndefMessage); // return tag; return NfcTag(uid, uidLength, MIFARE_CLASSIC, &buffer[4], messageLength); }