Skip to content

Commit

Permalink
erase(), format(), clean()
Browse files Browse the repository at this point in the history
erase - erases tag by writing an empty NDEF record
format - format tag as NDEF (Mifare Classic only)
clean - reset a tag to factory state (or close to factory state)

Mifare Classic format now adds an empty NDEF record
  • Loading branch information
don committed Aug 25, 2014
1 parent 56a4461 commit c2da758
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 21 deletions.
18 changes: 16 additions & 2 deletions MifareClassic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,12 @@ bool MifareClassic::decodeTlv(byte *data, int &messageLength, int &messageStartI
return true;
}

// Intialized NDEF tag contains one empty NDEF TLV 03 00 FE - AN1304 6.3.1
// We are formatting in read/write mode with a NDEF TLV 03 03 and an empty NDEF record D0 00 00 FE - AN1304 6.3.2
boolean MifareClassic::formatNDEF(byte * uid, unsigned int uidLength)
{
uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
uint8_t emptyNdefMesg[16] = {0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t sectorbuffer0[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t sectorbuffer4[16] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

Expand All @@ -207,10 +210,21 @@ boolean MifareClassic::formatNDEF(byte * uid, unsigned int uidLength)
{
for (int i=4; i<64; i+=4) {
success = _nfcShield->mifareclassic_AuthenticateBlock (uid, uidLength, i, 0, keya);

if (success) {
if (!(_nfcShield->mifareclassic_WriteDataBlock (i, sectorbuffer0)))
if (i == 4) // special handling for block 4
{
if (!(_nfcShield->mifareclassic_WriteDataBlock (i, emptyNdefMesg)))
{
Serial.print(F("Unable to write block "));Serial.println(i);
}
}
else
{
Serial.print(F("Unable to write block "));Serial.println(i);
if (!(_nfcShield->mifareclassic_WriteDataBlock (i, sectorbuffer0)))
{
Serial.print(F("Unable to write block "));Serial.println(i);
}
}
if (!(_nfcShield->mifareclassic_WriteDataBlock (i+1, sectorbuffer0)))
{
Expand Down
43 changes: 33 additions & 10 deletions MifareUltralight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,25 +170,25 @@ boolean MifareUltralight::write(NdefMessage& m, byte * uid, unsigned int uidLeng
return false;
}
readCapabilityContainer(); // meta info for tag

messageLength = m.getEncodedSize();
ndefStartIndex = messageLength < 0xFF ? 2 : 4;
calculateBufferSize();

if(bufferSize>tagCapacity) {
#ifdef MIFARE_ULTRALIGHT_DEBUG
Serial.print(F("Encoded Message length exceeded tag Capacity "));Serial.println(tagCapacity);
#endif
return false;
}

uint8_t encoded[bufferSize];
uint8_t * src = encoded;
unsigned int position = 0;
uint8_t page = ULTRALIGHT_DATA_START_PAGE;

// Set message size. With ultralight should always be less than 0xFF but who knows?

encoded[0] = 0x3;
if (messageLength < 0xFF)
{
Expand All @@ -200,24 +200,24 @@ boolean MifareUltralight::write(NdefMessage& m, byte * uid, unsigned int uidLeng
encoded[2] = ((messageLength >> 8) & 0xFF);
encoded[3] = (messageLength & 0xFF);
}

m.encode(encoded+ndefStartIndex);
// this is always at least 1 byte copy because of terminator.
memset(encoded+ndefStartIndex+messageLength,0,bufferSize-ndefStartIndex-messageLength);
memset(encoded+ndefStartIndex+messageLength,0,bufferSize-ndefStartIndex-messageLength);
encoded[ndefStartIndex+messageLength] = 0xFE; // terminator

#ifdef MIFARE_ULTRALIGHT_DEBUG
Serial.print(F("messageLength "));Serial.println(messageLength);
Serial.print(F("Tag Capacity "));Serial.println(tagCapacity);
nfc->PrintHex(encoded,bufferSize);
#endif

while (position < bufferSize){ //bufferSize is always times pagesize so no "last chunk" check
// write page
if (!nfc->mifareultralight_WritePage(page, src))
return false;
#ifdef MIFARE_ULTRALIGHT_DEBUG
Serial.print(F("Written page "));Serial.print(page);Serial.print(F(" - "));
Serial.print(F("Wrote page "));Serial.print(page);Serial.print(F(" - "));
nfc->PrintHex(src,ULTRALIGHT_PAGE_SIZE);
#endif
page++;
Expand All @@ -226,3 +226,26 @@ boolean MifareUltralight::write(NdefMessage& m, byte * uid, unsigned int uidLeng
}
return true;
}

// Mifare Ultralight can't be reset to factory state
// zero out tag data like the NXP Tag Write Android application
boolean MifareUltralight::clean()
{
readCapabilityContainer(); // meta info for tag

uint8_t pages = (tagCapacity / ULTRALIGHT_PAGE_SIZE) + ULTRALIGHT_DATA_START_PAGE;

// factory tags have 0xFF, but OTP-CC blocks have already been set so we use 0x00
uint8_t data[4] = { 0x00, 0x00, 0x00, 0x00 };

for (int i = ULTRALIGHT_DATA_START_PAGE; i < pages; i++) {
#ifdef MIFARE_ULTRALIGHT_DEBUG
Serial.print(F("Wrote page "));Serial.print(i);Serial.print(F(" - "));
nfc->PrintHex(data, ULTRALIGHT_PAGE_SIZE);
#endif
if (!nfc->mifareultralight_WritePage(i, data)) {
return false;
}
}
return true;
}
1 change: 1 addition & 0 deletions MifareUltralight.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class MifareUltralight
~MifareUltralight();
NfcTag read(byte *uid, unsigned int uidLength);
boolean write(NdefMessage& ndefMessage, byte *uid, unsigned int uidLength);
boolean clean();
private:
PN532* nfc;
unsigned int tagCapacity;
Expand Down
35 changes: 28 additions & 7 deletions NfcAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ boolean NfcAdapter::tagPresent(unsigned long timeout)
return success;
}

boolean NfcAdapter::erase()
{
boolean success;
NdefMessage message = NdefMessage();
message.addEmptyRecord();
return write(message);
}

boolean NfcAdapter::format()
{
boolean success;
Expand All @@ -64,22 +72,35 @@ boolean NfcAdapter::format()
return success;
}

boolean NfcAdapter::erase()
boolean NfcAdapter::clean()
{
boolean success;
if (uidLength == 4)
uint8_t type = guessTagType();

if (type == TAG_TYPE_MIFARE_CLASSIC)
{
#ifdef NDEF_DEBUG
Serial.println(F("Cleaning Mifare Classic"));
#endif
MifareClassic mifareClassic = MifareClassic(*shield);
success = mifareClassic.formatMifare(uid, uidLength);
return mifareClassic.formatMifare(uid, uidLength);
}
else if (type == TAG_TYPE_2)
{
#ifdef NDEF_DEBUG
Serial.println(F("Cleaning Mifare Ultralight"));
#endif
MifareUltralight ultralight = MifareUltralight(*shield);
return ultralight.clean();
}
else
{
Serial.print(F("Unsupported Tag. Length is "));Serial.println(uidLength);
success = false;
Serial.print(F("No driver for card type "));Serial.println(type);
return false;
}
return success;

}


NfcTag NfcAdapter::read()
{
uint8_t type = guessTagType();
Expand Down
8 changes: 6 additions & 2 deletions NfcAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ class NfcAdapter {
boolean tagPresent(unsigned long timeout=0); // tagAvailable
NfcTag read();
boolean write(NdefMessage& ndefMessage);
boolean erase(); // brings MifareClassic at original state
boolean format(); // format MifareClassic to NDEF
// erase tag by writing an empty NDEF record
boolean erase();
// format a tag as NDEF
boolean format();
// reset tag back to factory state
boolean clean();
private:
PN532* shield;
byte uid[7]; // Buffer to store the returned UID
Expand Down

0 comments on commit c2da758

Please sign in to comment.