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