• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 FuZhou Lockzhiner Electronic Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ndef.h"
17 #include <string.h>
18 #include "nfcForum.h"
19 #include "rtdTypes.h"
20 #include "NT3H.h"
21 
22 typedef uint8_t (*composeRtdPtr)(const NDEFDataStr *ndef, NDEFRecordStr *ndefRecord, uint8_t *I2CMsg);
23 static composeRtdPtr composeRtd[] = {composeRtdText, composeRtdUri};
24 
firstRecord(UncompletePageStr * page,const NDEFDataStr * data,RecordPosEnu rtdPosition)25 static int16_t firstRecord(UncompletePageStr *page, const NDEFDataStr *data, RecordPosEnu rtdPosition)
26 {
27     NDEFRecordStr record;
28     NDEFHeaderStr header;
29     uint8_t typeFunct = 0;
30 
31     switch (data->rtdType) {
32         case RTD_TEXT:
33             typeFunct = TYPE_FUNCT_TEXT;
34             break;
35 
36         case RTD_URI:
37             typeFunct = TYPE_FUNCT_URI;
38             break;
39 
40         default:
41             return TYPE_FUNCT_INVALID;
42             break;
43     }
44 
45     // clear all buffers
46     memset(&record, 0, sizeof(NDEFRecordStr));
47     memset(nfcPageBuffer, 0, NFC_PAGE_SIZE);
48 
49     // this is the first record
50     header.startByte = NDEF_START_BYTE;
51     composeNDEFMBME(true, true, &record);
52 
53     // prepare the NDEF Header and payload
54     uint8_t recordLength = composeRtd[typeFunct](data, &record, &nfcPageBuffer[sizeof(NDEFHeaderStr)]);
55     header.payloadLength = data->rtdPayloadlength + recordLength;
56 
57     // write first record
58     memcpy(nfcPageBuffer, &header, sizeof(NDEFHeaderStr));
59 
60     return sizeof(NDEFHeaderStr) + recordLength;
61 }
62 
63 
addRecord(UncompletePageStr * pageToUse,const NDEFDataStr * data,RecordPosEnu rtdPosition)64 static int16_t addRecord(UncompletePageStr *pageToUse, const NDEFDataStr *data, RecordPosEnu rtdPosition)
65 {
66     NDEFRecordStr record;
67     NDEFHeaderStr header = {0};
68     uint8_t       newRecordPtr, mbMe;
69     bool          ret = true;
70     uint8_t       tmpBuffer[NFC_PAGE_SIZE];
71 
72     uint8_t typeFunct = 0;
73 
74     switch (data->rtdType) {
75         case RTD_TEXT:
76             typeFunct = 0;
77             break;
78 
79         case RTD_URI:
80             typeFunct = 1;
81             break;
82 
83         default:
84             return -1;
85             break;
86     }
87 
88     // first Change the Header of the first Record
89     NT3HReadHeaderNfc(&newRecordPtr, &mbMe);
90     record.header = mbMe;
91     composeNDEFMBME(true, false, &record); // this is the first record
92     mbMe = record.header;
93 
94     memset(&record, 0, sizeof(NDEFRecordStr));
95     memset(tmpBuffer, 0, NFC_PAGE_SIZE);
96 
97     // prepare second record
98     uint8_t recordLength = composeRtd[typeFunct](data, &record, tmpBuffer);
99 
100     if (rtdPosition == NDEFMiddlePos) {
101         // this is a record in the middle adjust it on the buffet
102         composeNDEFMBME(false, false, &record);
103     } else if (rtdPosition == NDEFLastPos) {
104         // this is the last record adjust it on the buffet
105         composeNDEFMBME(false, true, &record);
106     }
107 
108     tmpBuffer[0] = record.header;
109 
110     header.payloadLength += data->rtdPayloadlength + recordLength;
111 
112     // save the new value of length on the first page
113     NT3HWriteHeaderNfc((newRecordPtr + header.payloadLength), mbMe);
114 
115     // use the last valid page and start to add the new record
116     NT3HReadUserData(pageToUse->page);
117     if (pageToUse->usedBytes + recordLength < NFC_PAGE_SIZE) {
118         memcpy(&nfcPageBuffer[pageToUse->usedBytes], tmpBuffer, recordLength);
119         return recordLength + pageToUse->usedBytes;
120     } else {
121         uint8_t byteToCopy = NFC_PAGE_SIZE - pageToUse->usedBytes;
122         memcpy(&nfcPageBuffer[pageToUse->usedBytes], tmpBuffer, byteToCopy);
123         NT3HWriteUserData(pageToUse->page, nfcPageBuffer);
124         // update the info with the new page
125         pageToUse->page++;
126         pageToUse->usedBytes = recordLength - byteToCopy;
127         // copy the remain part in the pageBuffer because this is what the caller expect
128         memcpy(nfcPageBuffer, &tmpBuffer[byteToCopy], pageToUse->usedBytes);
129         return pageToUse->usedBytes;
130     }
131 }
132 
writeUserPayload(int16_t payloadPtr,const NDEFDataStr * data,UncompletePageStr * addPage)133 static bool writeUserPayload(int16_t payloadPtr, const NDEFDataStr *data, UncompletePageStr *addPage)
134 {
135     uint8_t addedPayload;
136     bool ret = false;
137 
138     uint8_t finish = payloadPtr + data->rtdPayloadlength;
139     bool endRecord = false;
140     uint8_t copyByte = 0;
141 
142     // if the header is less then the NFC_PAGE_SIZE, fill it with the payload
143     if (NFC_PAGE_SIZE > payloadPtr) {
144         if (data->rtdPayloadlength > NFC_PAGE_SIZE - payloadPtr) {
145             copyByte = NFC_PAGE_SIZE - payloadPtr;
146         } else {
147             copyByte = data->rtdPayloadlength;
148         }
149     }
150 
151     // Copy the payload
152     memcpy(&nfcPageBuffer[payloadPtr], data->rtdPayload, copyByte);
153     addedPayload = copyByte;
154 
155     // if it is sufficient one send add the NDEF_END_BYTE
156     if ((addedPayload >= data->rtdPayloadlength) && ((payloadPtr + copyByte) < NFC_PAGE_SIZE)) {
157         nfcPageBuffer[(payloadPtr + copyByte)] = NDEF_END_BYTE;
158         endRecord = true;
159     }
160 
161     ret = NT3HWriteUserData(addPage->page, nfcPageBuffer);
162 
163     while (!endRecord) {
164         addPage->page++; // move to a new register
165         memset(nfcPageBuffer, 0, NFC_PAGE_SIZE);
166 
167         // special case just the NDEF_END_BYTE remain out
168         if (addedPayload == data->rtdPayloadlength) {
169             nfcPageBuffer[0] = NDEF_END_BYTE;
170             ret = NT3HWriteUserData(addPage->page, nfcPageBuffer);
171             endRecord = true;
172             if (ret == false) {
173                 errNo = NT3HERROR_WRITE_NDEF_TEXT;
174             }
175             return ret;
176         }
177 
178         if (addedPayload < data->rtdPayloadlength) {
179             // add the NDEF_END_BYTE if there is enough space
180             if ((data->rtdPayloadlength - addedPayload) < NFC_PAGE_SIZE) {
181                 memcpy(nfcPageBuffer, &data->rtdPayload[addedPayload], (data->rtdPayloadlength - addedPayload));
182                 nfcPageBuffer[(data->rtdPayloadlength - addedPayload)] = NDEF_END_BYTE;
183             } else {
184                 memcpy(nfcPageBuffer, &data->rtdPayload[addedPayload], NFC_PAGE_SIZE);
185             }
186 
187             addedPayload += NFC_PAGE_SIZE;
188             ret = NT3HWriteUserData(addPage->page, nfcPageBuffer);
189             if (ret == false) {
190                 errNo = NT3HERROR_WRITE_NDEF_TEXT;
191                 return ret;
192             }
193         } else {
194             endRecord = true;
195         }
196     }
197 
198     return ret;
199 }
200 
201 typedef int16_t (*addFunct_T) (UncompletePageStr *page, const NDEFDataStr *data, RecordPosEnu rtdPosition);
202 static addFunct_T addFunct[] = {firstRecord, addRecord, addRecord};
203 
NT3HwriteRecord(const NDEFDataStr * data)204 bool NT3HwriteRecord(const NDEFDataStr *data)
205 {
206     uint8_t recordLength = 0, mbMe;
207     UncompletePageStr addPage;
208     addPage.page = 0;
209 
210     // calculate the last used page
211     if (data->ndefPosition != NDEFFirstPos) {
212         NT3HReadHeaderNfc(&recordLength, &mbMe);
213         addPage.page  = (recordLength + sizeof(NDEFHeaderStr) + 1) / NFC_PAGE_SIZE;
214 
215         // remove the NDEF_END_BYTE byte because it will overwrite by the new Record
216         addPage.usedBytes = (recordLength + sizeof(NDEFHeaderStr) + 1) % NFC_PAGE_SIZE - 1;
217     }
218 
219     // call the appropriate function and consider the pointer
220     // within the NFC_PAGE_SIZE that need to be used
221     int16_t payloadPtr = addFunct[data->ndefPosition](&addPage, data, data->ndefPosition);
222     if (payloadPtr == -1) {
223         errNo = NT3HERROR_TYPE_NOT_SUPPORTED;
224         return false;
225     }
226 
227     return writeUserPayload(payloadPtr, data, &addPage);
228 }
229 
230