• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <string.h>
3 #include <unistd.h>
4 
5 #include "iot_i2c.h"
6 #include "iot_i2c_ex.h"
7 
8 #include "nfc.h"
9 #include "nfcForum.h"
10 #include "NT3H.h"
11 
12 /**
13  * @brief Defines I2C data transmission attributes.
14  */
15 typedef struct {
16     /** Pointer to the buffer storing data to send */
17     unsigned char *sendBuf;
18     /** Length of data to send */
19     unsigned int  sendLen;
20     /** Pointer to the buffer for storing data to receive */
21     unsigned char *receiveBuf;
22     /** Length of data received */
23     unsigned int  receiveLen;
24 } WifiIotI2cData;
25 
26 uint8_t     nfcPageBuffer[NFC_PAGE_SIZE];
27 NT3HerrNo   errNo;
28 // due to the nature of the NT3H a timeout is required to
29 // protectd 2 consecutive I2C access
30 
get_last_ncf_page(void)31 inline const uint8_t *get_last_ncf_page(void)
32 {
33     return nfcPageBuffer;
34 }
35 
writeTimeout(uint8_t * data,uint8_t dataSend)36 static bool writeTimeout(uint8_t *data, uint8_t dataSend)
37 {
38     uint32_t status = 0;
39 
40     status = IoTI2cWrite(1, (NT3H1X_ADDRESS << 1) | 0x00, data, dataSend);
41     if (status != 0) {
42         printf("===== Error: I2C write status = 0x%x! =====\r\n", status);
43         return 0;
44     }
45     usleep(NT3H1X_WRITE_TIMEOUT_US);
46     return 1;
47 }
48 
readTimeout(uint8_t address,uint8_t * block_data)49 static bool readTimeout(uint8_t address, uint8_t *block_data)
50 {
51     uint32_t status = 0;
52     IotI2cData nt3h1101_i2c_data = { 0 };
53     uint8_t  buffer[1] = { address };
54     nt3h1101_i2c_data.sendBuf = buffer;
55     nt3h1101_i2c_data.sendLen = 1;
56     nt3h1101_i2c_data.receiveBuf = block_data;
57     nt3h1101_i2c_data.receiveLen = NFC_PAGE_SIZE;
58     status = IoTI2cWriteread(1, (NT3H1X_ADDRESS << 1) | 0x00, &nt3h1101_i2c_data);
59     if (status != 0) {
60         printf("===== Error: I2C write status = 0x%x! =====\r\n", status);
61         return 0;
62     }
63     return 1;
64 }
65 
66 
NT3HReadHeaderNfc(uint8_t * endRecordsPtr,uint8_t * ndefHeader)67 bool NT3HReadHeaderNfc(uint8_t *endRecordsPtr, uint8_t *ndefHeader)
68 {
69     *endRecordsPtr = 0;
70     bool ret = NT3HReadUserData(0);
71     // read the first page to see where is the end of the Records.
72     if (ret == true) {
73         // if the first byte is equals to NDEF_START_BYTE there are some records
74         // store theend of that
75         if ((NDEF_START_BYTE == nfcPageBuffer[0]) && (NTAG_ERASED != nfcPageBuffer[NDEFHeader])) {
76             *endRecordsPtr = nfcPageBuffer[EndRecordsPtr];
77             *ndefHeader = nfcPageBuffer[NDEFHeader];
78         }
79         return true;
80     } else {
81         errNo = NT3HERROR_READ_HEADER;
82     }
83 
84     return ret;
85 }
86 
87 
NT3HWriteHeaderNfc(uint8_t endRecordsPtr,uint8_t ndefHeader)88 bool NT3HWriteHeaderNfc(uint8_t endRecordsPtr, uint8_t ndefHeader)
89 {
90 // read the first page to see where is the end of the Records.
91     bool ret = NT3HReadUserData(0);
92     if (ret == true) {
93         nfcPageBuffer[EndRecordsPtr] = endRecordsPtr;
94         nfcPageBuffer[NDEFHeader] = ndefHeader;
95         ret = NT3HWriteUserData(0, nfcPageBuffer);
96         if (ret == false) {
97             errNo = NT3HERROR_WRITE_HEADER;
98         }
99     } else {
100         errNo = NT3HERROR_READ_HEADER;
101     }
102 
103     return ret;
104 }
105 
NT3HEraseAllTag(void)106 bool NT3HEraseAllTag(void)
107 {
108     bool ret = true;
109     uint8_t erase[NFC_PAGE_SIZE + 1] = { USER_START_REG, 0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE };
110     ret = writeTimeout(erase, sizeof(erase));
111     if (ret == false) {
112         errNo = NT3HERROR_ERASE_USER_MEMORY_PAGE;
113     }
114     return ret;
115 }
116 
NT3HReaddManufactoringData(uint8_t * manuf)117 bool NT3HReaddManufactoringData(uint8_t *manuf)
118 {
119     return readTimeout(MANUFACTORING_DATA_REG, manuf);
120 }
121 
NT3HReadConfiguration(uint8_t * configuration)122 bool NT3HReadConfiguration(uint8_t *configuration)
123 {
124     return readTimeout(CONFIG_REG, configuration);
125 }
126 
getSessionReg(void)127 bool getSessionReg(void)
128 {
129     return readTimeout(SESSION_REG, nfcPageBuffer);
130 }
131 
NT3HReadUserData(uint8_t page)132 bool NT3HReadUserData(uint8_t page)
133 {
134     uint8_t reg = USER_START_REG + page;
135     // if the requested page is out of the register exit with error
136     if (reg > USER_END_REG) {
137         errNo = NT3HERROR_INVALID_USER_MEMORY_PAGE;
138         return false;
139     }
140     bool ret = readTimeout(reg, nfcPageBuffer);
141     if (ret == false) {
142         errNo = NT3HERROR_READ_USER_MEMORY_PAGE;
143     }
144 
145     return ret;
146 }
147 
NT3HWriteUserData(uint8_t page,const uint8_t * data)148 bool NT3HWriteUserData(uint8_t page, const uint8_t *data)
149 {
150     bool ret = true;
151     uint8_t dataSend[NFC_PAGE_SIZE + 1]; // data plus register
152     uint8_t reg = USER_START_REG + page;
153 
154     // if the requested page is out of the register exit with error
155     if (reg > USER_END_REG) {
156         errNo = NT3HERROR_INVALID_USER_MEMORY_PAGE;
157         ret = false;
158         return ret;
159     }
160 
161     dataSend[0] = reg; // store the register
162     memcpy_s(&dataSend[1], NFC_PAGE_SIZE, data, NFC_PAGE_SIZE);
163     ret = writeTimeout(dataSend, sizeof(dataSend));
164     if (ret == false) {
165         errNo = NT3HERROR_WRITE_USER_MEMORY_PAGE;
166         return ret;
167     }
168     return ret;
169 }
170 
NT3HReadSram(void)171 bool NT3HReadSram(void)
172 {
173     bool ret = false;
174     for (int i = SRAM_START_REG, j = 0; i <= SRAM_END_REG; i++, j++) {
175         ret = readTimeout(i, nfcPageBuffer);
176         if (ret == false) {
177             return ret;
178         }
179     }
180     return ret;
181 }
182 
NT3HGetNxpSerialNumber(char * buffer)183 void NT3HGetNxpSerialNumber(char *buffer)
184 {
185     uint8_t manuf[16];
186 
187     if (NT3HReaddManufactoringData(manuf)) {
188         for (int i = 0; i < SERIAL_NUM_LEN; i++) {
189             buffer[i] = manuf[i];
190         }
191     }
192 }
193 typedef uint8_t(*composeRtdPtr)(const NDEFDataStr *ndef, NDEFRecordStr *ndefRecord, uint8_t *I2CMsg);
194 static composeRtdPtr composeRtd[] = { composeRtdText, composeRtdUri };
195 
firstRecord(UncompletePageStr * page,const NDEFDataStr * data,RecordPosEnu rtdPosition)196 int16_t firstRecord(UncompletePageStr *page, const NDEFDataStr *data, RecordPosEnu rtdPosition)
197 {
198     NDEFRecordStr record;
199     NDEFHeaderStr header;
200     uint8_t typeFunct = 0;
201     switch (data->rtdType) {
202         case RTD_TEXT:
203             typeFunct = 0;
204             break;
205 
206         case RTD_URI:
207             typeFunct = 1;
208             break;
209 
210         default:
211             return -1;
212             break;
213     }
214 
215     // clear all buffers
216     memset_s(&record, sizeof(NDEFRecordStr), 0, sizeof(NDEFRecordStr));
217     memset_s(nfcPageBuffer, NFC_PAGE_SIZE, 0, NFC_PAGE_SIZE);
218 
219     // this is the first record
220     header.startByte = NDEF_START_BYTE;
221     composeNDEFMBME(true, true, &record);
222 
223     // prepare the NDEF Header and payload
224     uint8_t recordLength = composeRtd[typeFunct](data, &record, &nfcPageBuffer[sizeof(NDEFHeaderStr)]);
225     header.payloadLength = data->rtdPayloadlength + recordLength;
226 
227     // write first record
228     memcpy_s(nfcPageBuffer, sizeof(NDEFHeaderStr), &header, sizeof(NDEFHeaderStr));
229 
230     return sizeof(NDEFHeaderStr) + recordLength;
231 }
232 
233 
addRecord(UncompletePageStr * pageToUse,const NDEFDataStr * data,RecordPosEnu rtdPosition)234 int16_t addRecord(UncompletePageStr *pageToUse, const NDEFDataStr *data, RecordPosEnu rtdPosition)
235 {
236     NDEFRecordStr record;
237     NDEFHeaderStr header = { 0 };
238     uint8_t       newRecordPtr, mbMe;
239     bool          ret = true;
240     uint8_t       tmpBuffer[NFC_PAGE_SIZE];
241 
242     uint8_t typeFunct = 0;
243 
244     switch (data->rtdType) {
245         case RTD_TEXT:
246             typeFunct = 0;
247             break;
248 
249         case RTD_URI:
250             typeFunct = 1;
251             break;
252 
253         default:
254             return -1;
255             break;
256     }
257 
258     // first Change the Header of the first Record
259     NT3HReadHeaderNfc(&newRecordPtr, &mbMe);
260     record.header = mbMe;
261     composeNDEFMBME(true, false, &record); // this is the first record
262     mbMe = record.header;
263 
264     memset_s(&record, sizeof(NDEFRecordStr), 0, sizeof(NDEFRecordStr));
265     memset_s(tmpBuffer, NFC_PAGE_SIZE, 0, NFC_PAGE_SIZE);
266 
267     // prepare second record
268     uint8_t recordLength = composeRtd[typeFunct](data, &record, tmpBuffer);
269 
270     if (rtdPosition == NDEFMiddlePos) {
271         // this is a record in the middle adjust it on the buffet
272         composeNDEFMBME(false, false, &record);
273     } else if (rtdPosition == NDEFLastPos) {
274         // this is the last record adjust it on the buffet
275         composeNDEFMBME(false, true, &record);
276     }
277 
278     tmpBuffer[0] = record.header;
279 
280     header.payloadLength += data->rtdPayloadlength + recordLength;
281 
282     // save the new value of length on the first page
283     NT3HWriteHeaderNfc((newRecordPtr + header.payloadLength), mbMe);
284 
285     // use the last valid page and start to add the new record
286     NT3HReadUserData(pageToUse->page);
287     if (pageToUse->usedBytes + recordLength < NFC_PAGE_SIZE) {
288         memcpy_s(&nfcPageBuffer[pageToUse->usedBytes], recordLength, tmpBuffer, recordLength);
289         return recordLength + pageToUse->usedBytes;
290     } else {
291         uint8_t byteToCopy = NFC_PAGE_SIZE - pageToUse->usedBytes;
292         memcpy_s(&nfcPageBuffer[pageToUse->usedBytes], byteToCopy, tmpBuffer, byteToCopy);
293         NT3HWriteUserData(pageToUse->page, nfcPageBuffer);
294         // update the info with the new page
295         pageToUse->page++;
296         pageToUse->usedBytes = recordLength - byteToCopy;
297         // copy the remain part in the pageBuffer because this is what the caller expect
298         memcpy_s(nfcPageBuffer, pageToUse->usedBytes, &tmpBuffer[byteToCopy], pageToUse->usedBytes);
299         return pageToUse->usedBytes;
300     }
301 }
302 
writeUserPayload(int16_t payloadPtr,const NDEFDataStr * data,UncompletePageStr * addPage)303 static bool writeUserPayload(int16_t payloadPtr, const NDEFDataStr *data, UncompletePageStr *addPage)
304 {
305     uint8_t addedPayload;
306     bool ret = false;
307 
308     uint8_t finish = payloadPtr + data->rtdPayloadlength;
309     bool endRecord = false;
310     uint8_t copyByte = 0;
311 
312     // if the header is less then the NFC_PAGE_SIZE, fill it with the payload
313     if (NFC_PAGE_SIZE > payloadPtr) {
314         if (data->rtdPayloadlength > NFC_PAGE_SIZE - payloadPtr) {
315             copyByte = NFC_PAGE_SIZE - payloadPtr;
316         } else {
317             copyByte = data->rtdPayloadlength;
318         }
319     }
320 
321     // Copy the payload
322     memcpy_s(&nfcPageBuffer[payloadPtr], copyByte, data->rtdPayload, copyByte);
323     addedPayload = copyByte;
324 
325     // if it is sufficient one send add the NDEF_END_BYTE
326     if ((addedPayload >= data->rtdPayloadlength) && ((payloadPtr + copyByte) < NFC_PAGE_SIZE)) {
327         nfcPageBuffer[(payloadPtr + copyByte)] = NDEF_END_BYTE;
328         endRecord = true;
329     }
330 
331     ret = NT3HWriteUserData(addPage->page, nfcPageBuffer);
332 
333     while (!endRecord) {
334         addPage->page++; // move to a new register
335 
336         memset_s(nfcPageBuffer, NFC_PAGE_SIZE, 0, NFC_PAGE_SIZE);
337         // special case just the NDEF_END_BYTE remain out
338         if (addedPayload == data->rtdPayloadlength) {
339             nfcPageBuffer[0] = NDEF_END_BYTE;
340             endRecord = true;
341             if ((ret = NT3HWriteUserData(addPage->page, nfcPageBuffer)) == false) {
342                 errNo = NT3HERROR_WRITE_NDEF_TEXT;
343             }
344             return ret;
345         }
346 
347         if (addedPayload < data->rtdPayloadlength) {
348             // add the NDEF_END_BYTE if there is enough space
349             if ((data->rtdPayloadlength - addedPayload) < NFC_PAGE_SIZE) {
350                 memcpy_s(nfcPageBuffer, (data->rtdPayloadlength - addedPayload),
351                     &data->rtdPayload[addedPayload], (data->rtdPayloadlength - addedPayload));
352                 nfcPageBuffer[(data->rtdPayloadlength - addedPayload)] = NDEF_END_BYTE;
353             } else {
354                 memcpy_s(nfcPageBuffer, NFC_PAGE_SIZE, &data->rtdPayload[addedPayload], NFC_PAGE_SIZE);
355             }
356             addedPayload += NFC_PAGE_SIZE;
357             if ((ret = NT3HWriteUserData(addPage->page, nfcPageBuffer)) == false) {
358                 errNo = NT3HERROR_WRITE_NDEF_TEXT;
359                 return ret;
360             }
361         } else {
362             endRecord = true;
363         }
364     }
365 
366     return ret;
367 }
368 
369 typedef int16_t(*addFunct_T) (UncompletePageStr *page, const NDEFDataStr *data, RecordPosEnu rtdPosition);
370 static addFunct_T addFunct[] = { firstRecord, addRecord, addRecord };
371 
NT3HwriteRecord(const NDEFDataStr * data)372 bool NT3HwriteRecord(const NDEFDataStr *data)
373 {
374     uint8_t recordLength = 0, mbMe;
375     UncompletePageStr addPage;
376     addPage.page = 0;
377 
378     // calculate the last used page
379     if (data->ndefPosition != NDEFFirstPos) {
380         NT3HReadHeaderNfc(&recordLength, &mbMe);
381         addPage.page = (recordLength + sizeof(NDEFHeaderStr) + 1) / NFC_PAGE_SIZE;
382 
383         // remove the NDEF_END_BYTE byte because it will overwrite by the new Record
384         addPage.usedBytes = (recordLength + sizeof(NDEFHeaderStr) + 1) % NFC_PAGE_SIZE - 1;
385     }
386 
387     // call the appropriate function and consider the pointer
388     // within the NFC_PAGE_SIZE that need to be used
389     int16_t payloadPtr = addFunct[data->ndefPosition](&addPage, data, data->ndefPosition);
390     if (payloadPtr == -1) {
391         errNo = NT3HERROR_TYPE_NOT_SUPPORTED;
392         return false;
393     }
394 
395     return  writeUserPayload(payloadPtr, data, &addPage);
396 }