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 <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19
20 #include "lz_hardware.h"
21 #include "ndef.h"
22 #include "nfcForum.h"
23 #include "NT3H.h"
24
25 /* NFC使用i2c的总线ID */
26 static unsigned int NFC_I2C_PORT = 2;
27
28 /* i2c配置 */
29 static I2cBusIo m_i2c2m0 = {
30 .scl = {
31 .gpio = GPIO0_PD6,
32 .func = MUX_FUNC1,
33 .type = PULL_NONE,
34 .drv = DRIVE_KEEP,
35 .dir = LZGPIO_DIR_KEEP,
36 .val = LZGPIO_LEVEL_KEEP
37 },
38 .sda = {
39 .gpio = GPIO0_PD5,
40 .func = MUX_FUNC1,
41 .type = PULL_NONE,
42 .drv = DRIVE_KEEP,
43 .dir = LZGPIO_DIR_KEEP,
44 .val = LZGPIO_LEVEL_KEEP
45 },
46 .id = FUNC_ID_I2C2,
47 .mode = FUNC_MODE_M0,
48 };
49 /* i2c的时钟频率 */
50 static unsigned int m_i2c2_freq = 400000;
51
52 uint8_t nfcPageBuffer[NFC_PAGE_SIZE];
53 NT3HerrNo errNo;
54 // due to the nature of the NT3H a timeout is required to
55 // protectd 2 consecutive I2C access
56
get_last_ncf_page(void)57 inline const uint8_t* get_last_ncf_page(void)
58 {
59 return nfcPageBuffer;
60 }
61
writeTimeout(uint8_t * data,uint8_t dataSend)62 static bool writeTimeout( uint8_t *data, uint8_t dataSend)
63 {
64 uint32_t timeout_usec = 300000;
65 uint32_t status = 0;
66
67 status = LzI2cWrite(NFC_I2C_PORT, NT3H1X_SLAVE_ADDRESS, data, dataSend);
68 if (status != LZ_HARDWARE_SUCCESS) {
69 printf("===== Error: I2C write status1 = 0x%x! =====\r\n", status);
70 return 0;
71 }
72 usleep(timeout_usec);
73
74 return 1;
75 }
76
readTimeout(uint8_t address,uint8_t * block_data)77 static bool readTimeout(uint8_t address, uint8_t *block_data)
78 {
79 uint32_t status = 0;
80 uint8_t buffer[1] = {address};
81
82 status = LzI2cWrite(NFC_I2C_PORT, NT3H1X_SLAVE_ADDRESS, &buffer[0], 1);
83 if (status != LZ_HARDWARE_SUCCESS) {
84 printf("===== Error: I2C write status1 = 0x%x! =====\r\n", status);
85 return 0;
86 }
87
88 status = LzI2cRead(NFC_I2C_PORT, NT3H1X_SLAVE_ADDRESS, block_data, NFC_PAGE_SIZE);
89 if (status != 0) {
90 printf("===== Error: I2C write status = 0x%x! =====\r\n", status);
91 return 0;
92 }
93
94 return 1;
95 }
96
NT3HI2cInit(void)97 unsigned int NT3HI2cInit(void)
98 {
99 uint32_t *pGrf = (uint32_t *)0x41050000U;
100 uint32_t reg_offset = 7;
101 uint32_t reg_bit_i2c = 0x7;
102 uint32_t regbit_offset_h = 8;
103 uint32_t regbit_offset_l = 4;
104 uint32_t regmask = 0xFFFF;
105 uing32_t regmask_offset = 16;
106 uint32_t ulValue;
107
108 ulValue = pGrf[reg_offset];
109 ulValue &= ~((reg_bit_i2c << regbit_offset_h) | (reg_bit_i2c << regbit_offset_l));
110 ulValue |= ((0x1 << regbit_offset_h) | (0x1 << regbit_offset_l));
111 pGrf[reg_offset] = ulValue | (regmask << regmask_offset);
112
113 if (I2cIoInit(m_i2c2m0) != LZ_HARDWARE_SUCCESS) {
114 printf("%s, %s, %d: I2cIoInit failed!\n", __FILE__, __func__, __LINE__);
115 return __LINE__;
116 }
117 if (LzI2cInit(NFC_I2C_PORT, m_i2c2_freq) != LZ_HARDWARE_SUCCESS) {
118 printf("%s, %s, %d: LzI2cInit failed!\n", __FILE__, __func__, __LINE__);
119 return __LINE__;
120 }
121
122 return 0;
123 }
124
NT3HI2cDeInit(void)125 unsigned int NT3HI2cDeInit(void)
126 {
127 LzI2cDeinit(NFC_I2C_PORT);
128 }
129
NT3HReadHeaderNfc(uint8_t * endRecordsPtr,uint8_t * ndefHeader)130 bool NT3HReadHeaderNfc(uint8_t *endRecordsPtr, uint8_t *ndefHeader)
131 {
132 #define STRING_OFFSET_NDEF_START 0
133 #define STRING_OFFSET_NEND_RECORD 1
134 #define STRING_OFFSET_NTAG_ERASED 2
135 bool ret = NT3HReadUserData(0);
136 *endRecordsPtr = 0;
137
138 // read the first page to see where is the end of the Records.
139 if (ret == true) {
140 // if the first byte is equals to NDEF_START_BYTE there are some records
141 // store theend of that
142 if ((NDEF_START_BYTE == nfcPageBuffer[STRING_OFFSET_NDEF_START])
143 && (NTAG_ERASED != nfcPageBuffer[STRING_OFFSET_NTAG_ERASED])) {
144 *endRecordsPtr = nfcPageBuffer[STRING_OFFSET_NEND_RECORD];
145 *ndefHeader = nfcPageBuffer[STRING_OFFSET_NTAG_ERASED];
146 }
147 return true;
148 } else {
149 errNo = NT3HERROR_READ_HEADER;
150 }
151
152 return ret;
153 }
154
155
NT3HWriteHeaderNfc(uint8_t endRecordsPtr,uint8_t ndefHeader)156 bool NT3HWriteHeaderNfc(uint8_t endRecordsPtr, uint8_t ndefHeader)
157 {
158 uint32_t offset_record_ptr = 1;
159 uint32_t offset_header = 2;
160
161 /* read the first page to see where is the end of the Records. */
162 bool ret = NT3HReadUserData(0);
163 if (ret == true) {
164 nfcPageBuffer[offset_record_ptr] = endRecordsPtr;
165 nfcPageBuffer[offset_header] = ndefHeader;
166 ret = NT3HWriteUserData(0, nfcPageBuffer);
167 if (ret == false) {
168 errNo = NT3HERROR_WRITE_HEADER;
169 }
170 } else {
171 errNo = NT3HERROR_READ_HEADER;
172 }
173
174 return ret;
175 }
176
NT3HEraseAllTag(void)177 bool NT3HEraseAllTag(void)
178 {
179 bool ret = true;
180 uint8_t erase[NFC_PAGE_SIZE + 1] = {USER_START_REG, 0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE};
181
182 ret = writeTimeout(erase, sizeof(erase));
183 if (ret == false) {
184 errNo = NT3HERROR_ERASE_USER_MEMORY_PAGE;
185 }
186 return ret;
187 }
188
NT3HReaddManufactoringData(uint8_t * manuf)189 bool NT3HReaddManufactoringData(uint8_t *manuf)
190 {
191 return readTimeout(MANUFACTORING_DATA_REG, manuf);
192 }
193
NT3HReadConfiguration(uint8_t * configuration)194 bool NT3HReadConfiguration(uint8_t *configuration)
195 {
196 return readTimeout(CONFIG_REG, configuration);
197 }
198
getSessionReg(void)199 bool getSessionReg(void)
200 {
201 return readTimeout(SESSION_REG, nfcPageBuffer);
202 }
203
NT3HReadUserData(uint8_t page)204 bool NT3HReadUserData(uint8_t page)
205 {
206 uint8_t reg = USER_START_REG + page;
207 bool ret;
208
209 // if the requested page is out of the register exit with error
210 if (reg > USER_END_REG) {
211 errNo = NT3HERROR_INVALID_USER_MEMORY_PAGE;
212 return false;
213 }
214
215 ret = readTimeout(reg, nfcPageBuffer);
216 if (ret == false) {
217 errNo = NT3HERROR_READ_USER_MEMORY_PAGE;
218 }
219
220 return ret;
221 }
222
223
NT3HWriteUserData(uint8_t page,const uint8_t * data)224 bool NT3HWriteUserData(uint8_t page, const uint8_t* data)
225 {
226 bool ret = true;
227 uint8_t dataSend[NFC_PAGE_SIZE + 1]; // data plus register
228 uint8_t reg = USER_START_REG + page;
229
230 /* if the requested page is out of the register exit with error */
231 if (reg > USER_END_REG) {
232 errNo = NT3HERROR_INVALID_USER_MEMORY_PAGE;
233 ret = false;
234 return ret;
235 }
236
237 dataSend[0] = reg; // store the register
238 memcpy(&dataSend[1], data, NFC_PAGE_SIZE);
239 ret = writeTimeout(dataSend, sizeof(dataSend));
240 if (ret == false) {
241 errNo = NT3HERROR_WRITE_USER_MEMORY_PAGE;
242 return ret;
243 }
244
245 return ret;
246 }
247
248
NT3HReadSram(void)249 bool NT3HReadSram(void)
250 {
251 bool ret = false;
252 for (int i = SRAM_START_REG, j = 0; i <= SRAM_END_REG; i++, j++) {
253 ret = readTimeout(i, nfcPageBuffer);
254 if (ret == false) {
255 return ret;
256 }
257 }
258 return ret;
259 }
260
261
NT3HGetNxpSerialNumber(char * buffer)262 void NT3HGetNxpSerialNumber(char* buffer)
263 {
264 #define MANUF_BUFFER_MAXSIZE 6
265 uint8_t manuf[16];
266
267 if (NT3HReaddManufactoringData(manuf)) {
268 for (int i = 0; i < MANUF_BUFFER_MAXSIZE; i++) {
269 buffer[i] = manuf[i];
270 }
271 }
272 }
273