• 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 <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