PN532 NFC shield of Adafruit based on PN532 of Seeed.

Fork of PN532 by Seeed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NdefMessage.cpp Source File

NdefMessage.cpp

00001 #include "NdefMessage.h"
00002 #include "PN532_debug.h"
00003 
00004 NdefMessage::NdefMessage(void)
00005 {
00006     _recordCount = 0;
00007 }
00008 
00009 NdefMessage::NdefMessage(const uint8_t * data, const int numuint8_ts)
00010 {
00011     #ifdef NDEF_DEBUG
00012     DMSG("Decoding "));Serial.print(numuint8_ts);DMSG(F(" uint8_ts");
00013     PrintHexChar(data, numuint8_ts);
00014     //DumpHex(data, numuint8_ts, 16);
00015     #endif
00016 
00017     _recordCount = 0;
00018 
00019     int index = 0;
00020 
00021     while (index <= numuint8_ts)
00022     {
00023 
00024         // decode tnf - first uint8_t is tnf with bit flags
00025         // see the NFDEF spec for more info
00026         uint8_t tnf_uint8_t = data[index];
00027         //bool mb = (tnf_uint8_t & 0x80) != 0;
00028         bool me = (tnf_uint8_t & 0x40) != 0;
00029         //bool cf = (tnf_uint8_t & 0x20) != 0;
00030         bool sr = (tnf_uint8_t & 0x10) != 0;
00031         bool il = (tnf_uint8_t & 0x8) != 0;
00032         uint8_t tnf = (tnf_uint8_t & 0x7);
00033 
00034         NdefRecord record = NdefRecord();
00035         record.setTnf(tnf);
00036 
00037         index++;
00038         int typeLength = data[index];
00039 
00040         int payloadLength = 0;
00041         if (sr)
00042         {
00043             index++;
00044             payloadLength = data[index];
00045         }
00046         else
00047         {
00048             payloadLength = ((0xFF & data[++index]) << 24) | ((0xFF & data[++index]) << 26) |
00049             ((0xFF & data[++index]) << 8) | (0xFF & data[++index]);
00050         }
00051 
00052         int idLength = 0;
00053         if (il)
00054         {
00055             index++;
00056             idLength = data[index];
00057         }
00058 
00059         index++;
00060         record.setType(&data[index], typeLength);
00061         index += typeLength;
00062 
00063         if (il)
00064         {
00065             record.setId(&data[index], idLength);
00066             index += idLength;
00067         }
00068 
00069         record.setPayload(&data[index], payloadLength);
00070         index += payloadLength;
00071 
00072         addRecord(record);
00073 
00074         if (me) break; // last message
00075     }
00076 
00077 }
00078 
00079 NdefMessage::NdefMessage(const NdefMessage& rhs)
00080 {
00081 
00082     _recordCount = rhs._recordCount;
00083     for (int i = 0; i < _recordCount; i++)
00084     {
00085         _records[i] = rhs._records[i];
00086     }
00087 
00088 }
00089 
00090 NdefMessage::~NdefMessage()
00091 {
00092 }
00093 
00094 NdefMessage& NdefMessage::operator=(const NdefMessage& rhs)
00095 {
00096 
00097     if (this != &rhs)
00098     {
00099 
00100         // delete existing records
00101         for (int i = 0; i < _recordCount; i++)
00102         {
00103             // TODO Dave: is this the right way to delete existing records?
00104             _records[i] = NdefRecord();
00105         }
00106 
00107         _recordCount = rhs._recordCount;
00108         for (int i = 0; i < _recordCount; i++)
00109         {
00110             _records[i] = rhs._records[i];
00111         }
00112     }
00113     return *this;
00114 }
00115 
00116 unsigned int NdefMessage::getRecordCount()
00117 {
00118     return _recordCount;
00119 }
00120 
00121 int NdefMessage::getEncodedSize()
00122 {
00123     int size = 0;
00124     for (int i = 0; i < _recordCount; i++)
00125     {
00126         size += _records[i].getEncodedSize();
00127     }
00128     return size;
00129 }
00130 
00131 // TODO change this to return uint8_t*
00132 void NdefMessage::encode(uint8_t* data)
00133 {
00134     // assert sizeof(data) >= getEncodedSize()
00135     uint8_t* data_ptr = &data[0];
00136 
00137     for (int i = 0; i < _recordCount; i++)
00138     {
00139         _records[i].encode(data_ptr, i == 0, (i + 1) == _recordCount);
00140         // TODO can NdefRecord.encode return the record size?
00141         data_ptr += _records[i].getEncodedSize();
00142     }
00143 
00144 }
00145 
00146 bool NdefMessage::addRecord(NdefRecord& record)
00147 {
00148 
00149     if (_recordCount < MAX_NDEF_RECORDS)
00150     {
00151         _records[_recordCount] = record;
00152         _recordCount++;
00153         return true;
00154     }
00155     else
00156     {
00157         DMSG("WARNING: Too many records. Increase MAX_NDEF_RECORDS.");
00158         return false;
00159     }
00160 }
00161 
00162 void NdefMessage::addMimeMediaRecord(string mimeType, string payload)
00163 {
00164 
00165     uint8_t payloaduint8_ts[payload.length() + 1];
00166     payload.copy((char*)payloaduint8_ts, sizeof(payloaduint8_ts));
00167 
00168     addMimeMediaRecord(mimeType, payloaduint8_ts, payload.length());
00169 }
00170 
00171 void NdefMessage::addMimeMediaRecord(string mimeType, uint8_t* payload, int payloadLength)
00172 {
00173     NdefRecord r = NdefRecord();
00174     r.setTnf(TNF_MIME_MEDIA);
00175 
00176     uint8_t type[mimeType.length() + 1];
00177     mimeType.copy((char*)type, sizeof(type));
00178     r.setType(type, mimeType.length());
00179 
00180     r.setPayload(payload, payloadLength);
00181 
00182     addRecord(r);
00183 }
00184 
00185 void NdefMessage::addTextRecord(string text)
00186 {
00187     addTextRecord(text, "en");
00188 }
00189 
00190 void NdefMessage::addTextRecord(string text, string encoding)
00191 {
00192     NdefRecord r = NdefRecord();
00193     r.setTnf(TNF_WELL_KNOWN);
00194 
00195     uint8_t RTD_TEXT[1] = { 0x54 }; // TODO this should be a constant or preprocessor
00196     r.setType(RTD_TEXT, sizeof(RTD_TEXT));
00197 
00198     // X is a placeholder for encoding length
00199     // TODO is it more efficient to build w/o string concatenation?
00200     string payloadString = "X" + encoding + text;
00201 
00202     uint8_t payload[payloadString.length() + 1];
00203     payloadString.copy((char*)payload, sizeof(payload));
00204 
00205     // replace X with the real encoding length
00206     payload[0] = encoding.length();
00207 
00208     r.setPayload(payload, payloadString.length());
00209 
00210     addRecord(r);
00211 }
00212 
00213 void NdefMessage::addUriRecord(string uri)
00214 {
00215     NdefRecord* r = new NdefRecord();
00216     r->setTnf(TNF_WELL_KNOWN);
00217 
00218     uint8_t RTD_URI[1] = { 0x55 }; // TODO this should be a constant or preprocessor
00219     r->setType(RTD_URI, sizeof(RTD_URI));
00220 
00221     // X is a placeholder for identifier code
00222     string payloadString = "X" + uri;
00223 
00224     uint8_t payload[payloadString.length() + 1];
00225     payloadString.copy((char*)payload, sizeof(payload));
00226 
00227     // add identifier code 0x0, meaning no prefix substitution
00228     payload[0] = 0x0;
00229 
00230     r->setPayload(payload, payloadString.length());
00231 
00232     addRecord(*r);
00233     delete(r);
00234 }
00235 
00236 void NdefMessage::addEmptyRecord()
00237 {
00238     NdefRecord* r = new NdefRecord();
00239     r->setTnf(TNF_EMPTY);
00240     addRecord(*r);
00241     delete(r);
00242 }
00243 
00244 NdefRecord NdefMessage::getRecord(int index)
00245 {
00246     if (index > -1 && index < _recordCount)
00247     {
00248         return _records[index];
00249     }
00250     else
00251     {
00252         return NdefRecord(); // would rather return NULL
00253     }
00254 }
00255 
00256 NdefRecord NdefMessage::operator[](int index)
00257 {
00258     return getRecord(index);
00259 }
00260 
00261 void NdefMessage::print()
00262 {
00263     DMSG("\nNDEF Message ");
00264     DMSG_INT(_recordCount);
00265     DMSG(" record");
00266     if (_recordCount == 1) {
00267         DMSG(", ");
00268     } else {
00269         DMSG("s, ");
00270     }
00271     DMSG_INT(getEncodedSize());
00272 
00273     int i;
00274     for (i = 0; i < _recordCount; i++)
00275     {
00276          _records[i].print();
00277     }
00278 }