Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forked from updates by the-real-orca, added class for NTAG support #35

Open
wants to merge 39 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
80fc999
compiles with -Wall -Werror -std=c++11
ccreutzig Mar 10, 2015
6a4e283
fix indenting
ccreutzig Mar 10, 2015
3d31069
make use of Serial optional
ccreutzig Mar 10, 2015
f231e10
disable Mifare Classic, to save space
ccreutzig Mar 10, 2015
1699127
further limit Serial
ccreutzig Mar 12, 2015
3b471e0
Added method to create an Android Application Record (AAR) for launch…
abcd-ca Sep 16, 2015
b80bb78
Copying from Arduino library and adding some other functions, see lin…
Oct 5, 2015
a6907c5
Removing definition of NULL
Oct 10, 2015
89dea94
Adding functionality to add unknown records
Dec 22, 2015
6a24d57
- Fixing stuff for Arduino Due and Arduino 1.6.6
Jan 15, 2016
2813a46
Adding option to show debug info
Jan 15, 2016
700e159
Return empty message when read failed
Jan 15, 2016
4fabc9b
Merge remote-tracking branch 'remotes/ccreutzig/master'
the-real-orca Jan 21, 2017
41a46a7
Merge remote-tracking branch 'remotes/LieBtrau/master'
the-real-orca Jan 21, 2017
0ef4c09
Merge remote-tracking branch 'remotes/abcd-ca/master'
the-real-orca Jan 21, 2017
68e9862
fix #ifdef #endif
the-real-orca Jan 28, 2017
c5083e0
make Mifare Classic or Mifare Ultra selectable
the-real-orca Jan 28, 2017
a100c7d
use ENUM for tag type instead of C++ String -> reduce memory size by …
the-real-orca Jan 28, 2017
191f260
switch to global buffer
the-real-orca Jan 28, 2017
2e8680f
replace C++ String with char*
the-real-orca Jan 28, 2017
9e78272
addExternalRecord()
the-real-orca Jan 28, 2017
0ef1bbf
Update readme with note on fork purpose
eecharlie Apr 5, 2017
17651e0
Import ntag class from LieBtrau/arduino-ntag. No edits; will not build.
Apr 5, 2017
842eee2
Add no-payload option to NdefRecord.
Apr 5, 2017
7576d7f
Implement functions to get NDEF header from NdefMessage
Apr 5, 2017
c71592c
Update unit tests. Some memory tests fail.
Apr 9, 2017
92a4116
Updates (untested) to ntag class.
Apr 9, 2017
10754d7
Memory leak troubleshooting in progress.
Apr 10, 2017
09c0698
Apply unit test fixes so that all tests now pass.
Apr 10, 2017
b957b98
Implement NDEF TLV header creation and sketch of packaging function. …
Apr 10, 2017
286a995
Implement some unit tests for ntag interface class (requires real har…
Apr 10, 2017
d505bd4
Implement and test packaging of NDEF message and writing to NTAG. All…
Apr 10, 2017
dec314d
Add test of complete NDEF encoding and writing to NTAG, and fix bug w…
Apr 10, 2017
0b59f8f
Find and fix several errors caused by 8-bit index variables that shou…
Apr 11, 2017
399f4f1
Clobber 'master' with 'find-memory-leak', burying some dumb ideas tha…
Apr 11, 2017
c2a24d4
Implement and test calculation of record payload offsets in packaged …
Apr 11, 2017
64e00ba
Update readme, back to stock.
eecharlie Apr 11, 2017
b039379
Add function to read startup & session config registers.
Jun 1, 2017
7b04600
Add record header getter functions. All tests pass.
Jul 10, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions Due.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@
#ifndef Due_h
#define Due_h

#if defined(__SAM3X8E__)
#define PROGMEM
#define pgm_read_byte(x) (*((char *)x))
// #define pgm_read_word(x) (*((short *)(x & 0xfffffffe)))
#define pgm_read_word(x) ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
#define pgm_read_byte_near(x) (*((char *)x))
#define pgm_read_byte_far(x) (*((char *)x))
// #define pgm_read_word_near(x) (*((short *)(x & 0xfffffffe))
// #define pgm_read_word_far(x) (*((short *)(x & 0xfffffffe)))
#define pgm_read_word_near(x) ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
#define pgm_read_word_far(x) ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x))))
#define PSTR(x) x
#if defined F
#undef F
#endif
#define F(X) (X)
#endif
//#if defined(__SAM3X8E__)
// #define PROGMEM
// #define pgm_read_byte(x) (*((char *)x))
//// #define pgm_read_word(x) (*((short *)(x & 0xfffffffe)))
// #define pgm_read_word(x) ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
// #define pgm_read_byte_near(x) (*((char *)x))
// #define pgm_read_byte_far(x) (*((char *)x))
//// #define pgm_read_word_near(x) (*((short *)(x & 0xfffffffe))
//// #define pgm_read_word_far(x) (*((short *)(x & 0xfffffffe)))
// #define pgm_read_word_near(x) ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x)))
// #define pgm_read_word_far(x) ( ((*((unsigned char *)x + 1)) << 8) + (*((unsigned char *)x))))
// #define PSTR(x) x
// #if defined F
// #undef F
// #endif
// #define F(X) (X)
//#endif

#endif
#endif
121 changes: 97 additions & 24 deletions MifareClassic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
#define LONG_TLV_SIZE 4
#define SHORT_TLV_SIZE 2

#define MIFARE_CLASSIC ("Mifare Classic")

MifareClassic::MifareClassic(PN532& nfcShield)
MifareClassic::MifareClassic(PN532& nfcShield, uint8_t *staticBuf, unsigned int staticBufSize)
{
_nfcShield = &nfcShield;
_nfcShield = &nfcShield;
_staticBufSize = staticBufSize;
_staticBuf = staticBuf;
}

MifareClassic::~MifareClassic()
Expand All @@ -31,26 +31,39 @@ NfcTag MifareClassic::read(byte *uid, unsigned int uidLength)
if (success)
{
if (!decodeTlv(data, messageLength, messageStartIndex)) {
return NfcTag(uid, uidLength, "ERROR"); // TODO should the error message go in NfcTag?
return NfcTag(uid, uidLength, NfcTag::UNKNOWN); // TODO should the error message go in NfcTag?
}
}
else
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Error. Failed read block "));Serial.println(currentBlock);
return NfcTag(uid, uidLength, MIFARE_CLASSIC);
#endif
return NfcTag(uid, uidLength, NfcTag::MIFARE_CLASSIC);
}
}
else
{
#ifdef NDEF_USE_SERIAL
Serial.println(F("Tag is not NDEF formatted."));
#endif
// TODO set tag.isFormatted = false
return NfcTag(uid, uidLength, MIFARE_CLASSIC);
return NfcTag(uid, uidLength, NfcTag::MIFARE_CLASSIC);
}

// this should be nested in the message length loop
int index = 0;
int bufferSize = getBufferSize(messageLength);
uint8_t buffer[bufferSize];
// use shared static buffer
if ( _staticBufSize < bufferSize )
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Error. Static buffer to small. is: "));Serial.print(_staticBufSize);
Serial.print(F("required: "));Serial.print(bufferSize);
#endif
return NfcTag(uid, uidLength, NfcTag::MIFARE_CLASSIC);
}
uint8_t *buffer = _staticBuf;

#ifdef MIFARE_CLASSIC_DEBUG
Serial.print(F("Message Length "));Serial.println(messageLength);
Expand All @@ -66,7 +79,9 @@ NfcTag MifareClassic::read(byte *uid, unsigned int uidLength)
success = _nfcShield->mifareclassic_AuthenticateBlock(uid, uidLength, currentBlock, 0, key);
if (!success)
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Error. Block Authentication failed for "));Serial.println(currentBlock);
#endif
// TODO error handling
}
}
Expand All @@ -82,7 +97,9 @@ NfcTag MifareClassic::read(byte *uid, unsigned int uidLength)
}
else
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Read failed "));Serial.println(currentBlock);
#endif
// TODO handle errors here
}

Expand All @@ -99,7 +116,7 @@ NfcTag MifareClassic::read(byte *uid, unsigned int uidLength)
}
}

return NfcTag(uid, uidLength, MIFARE_CLASSIC, &buffer[messageStartIndex], messageLength);
return NfcTag(uid, uidLength, NfcTag::MIFARE_CLASSIC, &buffer[messageStartIndex], messageLength);
}

int MifareClassic::getBufferSize(int messageLength)
Expand Down Expand Up @@ -144,7 +161,9 @@ int MifareClassic::getNdefStartIndex(byte *data)
}
else
{
#ifdef NDEF_USE_SERIAL
Serial.print("Unknown TLV ");Serial.println(data[i], HEX);
#endif
return -2;
}
}
Expand All @@ -166,7 +185,9 @@ bool MifareClassic::decodeTlv(byte *data, int &messageLength, int &messageStartI

if (i < 0 || data[i] != 0x3)
{
#ifdef NDEF_USE_SERIAL
Serial.println(F("Error. Can't decode message length."));
#endif
return false;
}
else
Expand Down Expand Up @@ -198,13 +219,17 @@ boolean MifareClassic::formatNDEF(byte * uid, unsigned int uidLength)
boolean success = _nfcShield->mifareclassic_AuthenticateBlock (uid, uidLength, 0, 0, keya);
if (!success)
{
#ifdef NDEF_USE_SERIAL
Serial.println(F("Unable to authenticate block 0 to enable card formatting!"));
#endif
return false;
}
success = _nfcShield->mifareclassic_FormatNDEF();
if (!success)
{
#ifdef NDEF_USE_SERIAL
Serial.println(F("Unable to format the card for NDEF"));
#endif
}
else
{
Expand All @@ -216,31 +241,43 @@ boolean MifareClassic::formatNDEF(byte * uid, unsigned int uidLength)
{
if (!(_nfcShield->mifareclassic_WriteDataBlock (i, emptyNdefMesg)))
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Unable to write block "));Serial.println(i);
#endif
}
}
else
{
if (!(_nfcShield->mifareclassic_WriteDataBlock (i, sectorbuffer0)))
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Unable to write block "));Serial.println(i);
#endif
}
}
if (!(_nfcShield->mifareclassic_WriteDataBlock (i+1, sectorbuffer0)))
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Unable to write block "));Serial.println(i+1);
#endif
}
if (!(_nfcShield->mifareclassic_WriteDataBlock (i+2, sectorbuffer0)))
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Unable to write block "));Serial.println(i+2);
#endif
}
if (!(_nfcShield->mifareclassic_WriteDataBlock (i+3, sectorbuffer4)))
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Unable to write block "));Serial.println(i+3);
#endif
}
} else {
unsigned int iii=uidLength;
#ifdef NDEF_USE_SERIAL
Serial.print(F("Unable to authenticate block "));Serial.println(i);
#endif
_nfcShield->readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, (uint8_t*)&iii);
}
}
Expand Down Expand Up @@ -276,7 +313,9 @@ boolean MifareClassic::formatMifare(byte * uid, unsigned int uidLength)
success = _nfcShield->mifareclassic_AuthenticateBlock (uid, uidLength, BLOCK_NUMBER_OF_SECTOR_TRAILER(idx), 1, (uint8_t *)KEY_DEFAULT_KEYAB);
if (!success)
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Authentication failed for sector ")); Serial.println(idx);
#endif
return false;
}

Expand All @@ -286,7 +325,9 @@ boolean MifareClassic::formatMifare(byte * uid, unsigned int uidLength)
memset(blockBuffer, 0, sizeof(blockBuffer));
if (!(_nfcShield->mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, blockBuffer)))
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Unable to write to sector ")); Serial.println(idx);
#endif
}
}
else
Expand All @@ -295,19 +336,25 @@ boolean MifareClassic::formatMifare(byte * uid, unsigned int uidLength)
// this block has not to be overwritten for block 0. It contains Tag id and other unique data.
if (!(_nfcShield->mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 3, blockBuffer)))
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Unable to write to sector ")); Serial.println(idx);
#endif
}
if (!(_nfcShield->mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 2, blockBuffer)))
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Unable to write to sector ")); Serial.println(idx);
#endif
}
}

memset(blockBuffer, 0, sizeof(blockBuffer));

if (!(_nfcShield->mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)) - 1, blockBuffer)))
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Unable to write to sector ")); Serial.println(idx);
#endif
}

// Step 3: Reset both keys to 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
Expand All @@ -319,7 +366,9 @@ boolean MifareClassic::formatMifare(byte * uid, unsigned int uidLength)
// Step 4: Write the trailer block
if (!(_nfcShield->mifareclassic_WriteDataBlock((BLOCK_NUMBER_OF_SECTOR_TRAILER(idx)), blockBuffer)))
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Unable to write trailer block of sector ")); Serial.println(idx);
#endif
}
}
return true;
Expand All @@ -328,48 +377,70 @@ boolean MifareClassic::formatMifare(byte * uid, unsigned int uidLength)
boolean MifareClassic::write(NdefMessage& m, byte * uid, unsigned int uidLength)
{

uint8_t encoded[m.getEncodedSize()];
int encodedSize = m.getEncodedSize();
// use shared static buffer
if ( _staticBufSize < encodedSize *2 )
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Error. Static buffer to small. is: "));Serial.print(_staticBufSize);
Serial.print(F("required: "));Serial.print(encodedSize *2);
#endif
return false;
}
uint8_t *encoded = _staticBuf;
m.encode(encoded);

uint8_t buffer[getBufferSize(sizeof(encoded))];
memset(buffer, 0, sizeof(buffer));
int bufferSize = getBufferSize(encodedSize);
// use shared static buffer
if ( _staticBufSize < encodedSize + bufferSize )
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Error. Static buffer to small. is: "));Serial.print(_staticBufSize);
Serial.print(F("required: "));Serial.print(encodedSize + bufferSize);
#endif
return false;
}
uint8_t *buffer = _staticBuf + encodedSize;
memset(buffer, 0, bufferSize);

#ifdef MIFARE_CLASSIC_DEBUG
Serial.print(F("sizeof(encoded) "));Serial.println(sizeof(encoded));
Serial.print(F("sizeof(buffer) "));Serial.println(sizeof(buffer));
Serial.print(F("sizeof(encoded) "));Serial.println(encodedSize);
Serial.print(F("sizeof(buffer) "));Serial.println(bufferSize);
#endif

if (sizeof(encoded) < 0xFF)
if (encodedSize < 0xFF)
{
buffer[0] = 0x3;
buffer[1] = sizeof(encoded);
memcpy(&buffer[2], encoded, sizeof(encoded));
buffer[2+sizeof(encoded)] = 0xFE; // terminator
buffer[1] = encodedSize;
memcpy(&buffer[2], encoded, encodedSize);
buffer[2+encodedSize] = 0xFE; // terminator
}
else
{
buffer[0] = 0x3;
buffer[1] = 0xFF;
buffer[2] = ((sizeof(encoded) >> 8) & 0xFF);
buffer[3] = (sizeof(encoded) & 0xFF);
memcpy(&buffer[4], encoded, sizeof(encoded));
buffer[4+sizeof(encoded)] = 0xFE; // terminator
buffer[2] = ((encodedSize >> 8) & 0xFF);
buffer[3] = (encodedSize & 0xFF);
memcpy(&buffer[4], encoded, encodedSize);
buffer[4+encodedSize] = 0xFE; // terminator
}

// Write to tag
int index = 0;
unsigned int index = 0;
int currentBlock = 4;
uint8_t key[6] = { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7 }; // this is Sector 1 - 15 key

while (index < sizeof(buffer))
while (index < bufferSize)
{

if (_nfcShield->mifareclassic_IsFirstBlock(currentBlock))
{
int success = _nfcShield->mifareclassic_AuthenticateBlock(uid, uidLength, currentBlock, 0, key);
if (!success)
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Error. Block Authentication failed for "));Serial.println(currentBlock);
#endif
return false;
}
}
Expand All @@ -384,7 +455,9 @@ boolean MifareClassic::write(NdefMessage& m, byte * uid, unsigned int uidLength)
}
else
{
#ifdef NDEF_USE_SERIAL
Serial.print(F("Write failed "));Serial.println(currentBlock);
#endif
return false;
}
index += BLOCK_SIZE;
Expand Down
4 changes: 3 additions & 1 deletion MifareClassic.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@
class MifareClassic
{
public:
MifareClassic(PN532& nfcShield);
MifareClassic(PN532& nfcShield, uint8_t *staticBuf, unsigned int staticBufSize);
~MifareClassic();
NfcTag read(byte *uid, unsigned int uidLength);
boolean write(NdefMessage& ndefMessage, byte *uid, unsigned int uidLength);
boolean formatNDEF(byte * uid, unsigned int uidLength);
boolean formatMifare(byte * uid, unsigned int uidLength);
private:
PN532* _nfcShield;
unsigned int _staticBufSize;
uint8_t *_staticBuf;
int getBufferSize(int messageLength);
int getNdefStartIndex(byte *data);
bool decodeTlv(byte *data, int &messageLength, int &messageStartIndex);
Expand Down
Loading