1 /*
2 * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 <unistd.h>
17 #include "ssd1306_oled.h"
18 #include "c081_nfc.h"
19 #include "iot_i2c.h"
20 #include "ohos_init.h"
21 #include "cmsis_os2.h"
22 #include "iot_gpio.h"
23 #include "iot_gpio_ex.h"
24 #include "app_demo_config.h"
25
26 #define NDEF_FILE_LEN (1024)
27 #define TASK_SLEEP_10MS (10)
28 #define TASK_SLEEP_1MS (1)
29 #define FIFO_LC_CMD (2)
30
31 T4T_FILE currentFile;
32
33 unsigned char capabilityContainer[15] = {
34 0x00, 0x0F, // CCLEN
35 0x20, // Mapping Version
36 0x00, 0xF6, // MLe 必须是F6 写成FF超过256字节就会分帧 但是写成F6就不会分帧
37 0x00, 0xF6, // MLc 必须是F6 写成FF超过256字节就会分帧 但是写成F6就不会分帧
38 0x04, // NDEF消息格式 05的话就是私有
39 0x06, // NDEF消息长度
40 0xE1, 0x04, // NDEF FILE ID NDEF的文件标识符
41 0x03, 0x84, // NDEF最大长度
42 0x00, // Read Access 可读
43 0x00 // Write Access 可写
44 };
45 unsigned char ndefFile[NDEF_FILE_LEN] = {
46 /* wechat ndef */
47 #ifdef NFC_TAG_WECHAT
48 0x00, 0x20,
49 0xd4, 0x0f, 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f,
50 0x69, 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x3a, 0x70,
51 0x6b, 0x67, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x65,
52 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x2e, 0x6d, 0x6d,
53 #endif
54 };
55 unsigned char fm327Fifo[NDEF_FILE_LEN];
56 unsigned char irqTxdone = 0;
57 unsigned char rfLen = 0;
58 unsigned char irqRxdone = 0;
59 unsigned char FlagFirstFrame = 0; // 卡片首帧标识
60
SetNdefData(void)61 void SetNdefData(void)
62 {
63 (void)memset_s(ndefFile, sizeof(ndefFile), 0x00, sizeof(ndefFile));
64 }
65
GetNdefData(unsigned char * ndefFileData,unsigned int ndefLen)66 unsigned char GetNdefData(unsigned char *ndefFileData, unsigned int ndefLen)
67 {
68 int ret = 0;
69 ret = memcpy_s(ndefFile, NDEF_FILE_LEN, ndefFileData, ndefLen);
70 if (ret != 0) {
71 return -1;
72 }
73 return 0;
74 }
75
76 /* co8i 写命令: 该接口写eeprom 更改芯片配置 */
C08iNfcI2cWrite(unsigned char regHigh8bitCmd,unsigned char regLow8bitCmd,unsigned char * dataBuff,unsigned char len)77 unsigned char C08iNfcI2cWrite(unsigned char regHigh8bitCmd, unsigned char regLow8bitCmd,
78 unsigned char* dataBuff, unsigned char len)
79 {
80 IotI2cIdx id = IOT_I2C_IDX_0;
81 IotI2cData C081nfcI2cWriteCmdAddr = {0};
82 unsigned char sendUserCmd[64] = {regHigh8bitCmd, regLow8bitCmd};
83
84 C081nfcI2cWriteCmdAddr.sendBuf = sendUserCmd;
85 C081nfcI2cWriteCmdAddr.sendLen = 2 + len; /* 2: send length */
86 for (int i = 0; i < len; i++) {
87 sendUserCmd[2 + i] = *(dataBuff + i); /* 2: send length */
88 }
89 IoTI2cWrite(id,
90 C081_NFC_ADDR& 0xFE,
91 C081nfcI2cWriteCmdAddr.sendBuf,
92 C081nfcI2cWriteCmdAddr.sendLen);
93
94 return 0;
95 }
96
97 /* 写寄存器 */
WriteFifoReg(unsigned char regHigh8bitCmd,unsigned char regLow8bitCmd,unsigned char dataBuff)98 unsigned int WriteFifoReg(unsigned char regHigh8bitCmd,
99 unsigned char regLow8bitCmd, unsigned char dataBuff)
100 {
101 IotI2cIdx id = IOT_I2C_IDX_0;
102 IotI2cData c081nfcI2cWriteCmdAddr = {0};
103 unsigned char sendUserCmd[3] = {regHigh8bitCmd, regLow8bitCmd, dataBuff};
104 c081nfcI2cWriteCmdAddr.sendBuf = sendUserCmd;
105 c081nfcI2cWriteCmdAddr.sendLen = 3; /* 3: send length */
106 IoTI2cWrite(id,
107 C081_NFC_ADDR & 0xFE,
108 c081nfcI2cWriteCmdAddr.sendBuf,
109 c081nfcI2cWriteCmdAddr.sendLen);
110 return 0;
111 }
112
113 /* 写fifo data */
WriteFifoData(unsigned char * dataBuff,unsigned char len)114 unsigned int WriteFifoData(unsigned char* dataBuff, unsigned char len)
115 {
116 unsigned char* writeBuf = dataBuff;
117
118 IotI2cIdx id = IOT_I2C_IDX_0;
119 IotI2cData c081nfcI2cWriteCmdAddr = {0};
120 unsigned char sendUserCmd[128] = {0};
121
122 (void)memset_s(sendUserCmd, sizeof(sendUserCmd), 0x0, sizeof(sendUserCmd));
123 sendUserCmd[0] = 0xff;
124 sendUserCmd[1] = 0xf0;
125 for (int i = 0; i < len; i++) {
126 sendUserCmd[2 + i] = *(writeBuf + i); /* 2: buffer index address */
127 }
128 c081nfcI2cWriteCmdAddr.sendBuf = sendUserCmd;
129 c081nfcI2cWriteCmdAddr.sendLen = 2 + len; /* 2: send length */
130 IoTI2cWrite(id,
131 C081_NFC_ADDR & 0xFE,
132 c081nfcI2cWriteCmdAddr.sendBuf,
133 c081nfcI2cWriteCmdAddr.sendLen);
134 return 0;
135 }
136 #define DELAY_10MS (10000)
137 /* EEPROM page write */
EepWritePage(unsigned char * pBuffer,unsigned short WriteAddr,unsigned char dataLen)138 void EepWritePage(unsigned char *pBuffer, unsigned short WriteAddr, unsigned char dataLen)
139 {
140 C08iNfcI2cWrite((unsigned char)((WriteAddr & 0xFF00) >> 8), /* 8: right move 8 bit */
141 (unsigned char)(WriteAddr & 0x00FF),
142 pBuffer,
143 dataLen);
144 hi_udelay(DELAY_10MS); // 必须延时10ms
145 IoTGpioSetOutputVal(IOT_IO_NAME_GPIO9, IOT_GPIO_VALUE1);
146 printf("----- EepWritePage %d ! -----\r\n\n", __LINE__);
147 }
148
149 /* 写EEPROM */
Fm11WriteEep(unsigned short addr,unsigned int len,unsigned char * wbuf)150 void Fm11WriteEep(unsigned short addr, unsigned int len, unsigned char *wbuf)
151 {
152 unsigned char offset;
153 unsigned short address = addr;
154 unsigned char *writeBuf = wbuf;
155 unsigned int length = len;
156
157 if (address < FM11_E2_USER_ADDR || address >= FM11_E2_MANUF_ADDR) {
158 return;
159 }
160 if (address % FM11_E2_BLOCK_SIZE) {
161 offset = FM11_E2_BLOCK_SIZE - (address % FM11_E2_BLOCK_SIZE);
162 if (length > offset) {
163 EepWritePage(writeBuf, address, offset);
164 address += offset;
165 writeBuf += offset;
166 length -= offset;
167 } else {
168 EepWritePage(writeBuf, address, length);
169 length = 0;
170 }
171 }
172 while (length) {
173 if (length >= FM11_E2_BLOCK_SIZE) {
174 EepWritePage(writeBuf, address, FM11_E2_BLOCK_SIZE);
175 address += FM11_E2_BLOCK_SIZE;
176 writeBuf += FM11_E2_BLOCK_SIZE;
177 length -= FM11_E2_BLOCK_SIZE;
178 } else {
179 EepWritePage(writeBuf, address, length);
180 length = 0;
181 }
182 }
183 }
184
185 /* 读EEPROM */
Fm11ReadEep(unsigned char * dataBuff,unsigned short ReadAddr,unsigned short len)186 unsigned int Fm11ReadEep(unsigned char *dataBuff, unsigned short ReadAddr, unsigned short len)
187 {
188 WriteRead((unsigned char)((ReadAddr & 0xFF00) >> 8), /* 8: right move 8 bit */
189 (unsigned char)(ReadAddr & 0x00FF),
190 dataBuff,
191 2, /* 2: read length */
192 len);
193
194 return 0;
195 }
196
197 /* 读NFC寄存器 */
Fm11ReadReg(unsigned short addr)198 unsigned char Fm11ReadReg(unsigned short addr)
199 {
200 unsigned char pdata[10] = {0};
201 unsigned char a = 0;
202
203 if (Fm11ReadEep(pdata, addr, 1) == 0) { /* 1: read length */
204 a = pdata[0];
205 return a;
206 } else {
207 printf("fm11_read_eep failed \r\n");
208 return -1;
209 }
210 }
211
212 /* 写NFC寄存器 */
Fm11WriteReg(unsigned short addr,unsigned char data)213 unsigned char Fm11WriteReg(unsigned short addr, unsigned char data)
214 {
215 unsigned int status = 0;
216
217 status = WriteFifoReg((unsigned char)((addr & 0xFF00) >> 8), /* 8: right move 8 bit */
218 (unsigned char)(addr & 0x00FF), data);
219 if (status != 0) {
220 return -1;
221 }
222 return 0;
223 }
224
225 /* 读取FIFO */
Fm11ReadFifo(unsigned char NumByteToRead,unsigned char * pbuf)226 unsigned char Fm11ReadFifo(unsigned char NumByteToRead, unsigned char *pbuf)
227 {
228 unsigned char readFifoLen = NumByteToRead;
229
230 if (Fm11ReadEep(pbuf, FM327_FIFO, readFifoLen) == 0) {
231 return 0;
232 } else {
233 return -1;
234 }
235 }
236
237 /* 写FIFO */
Fm11WriteFifo(unsigned char * pbuf,unsigned char len)238 unsigned char Fm11WriteFifo(unsigned char *pbuf, unsigned char len)
239 {
240 unsigned char status;
241
242 if (pbuf == NULL) {
243 return -1;
244 }
245 status = WriteFifoData(pbuf, len);
246 if (status != 0) {
247 return -1;
248 }
249 return 0;
250 }
251
NfcDataRead(unsigned char * sBuf,unsigned int sLen)252 void NfcDataRead(unsigned char *sBuf, unsigned int sLen)
253 {
254 unsigned int sendLen = sLen;
255 unsigned char *sendBuf = sBuf;
256
257 Fm11WriteFifo(sendBuf, 32); // 32: write fifo 先发32字节进fifo
258 Fm11WriteReg(RF_TXEN_REG, 0x55); // 写0x55时触发非接触口回发数据
259
260 sendLen = sendLen - 32; // 32: 待发长度-32
261 sendBuf = sendBuf + 32; // 32: 待发数据指针+32
262
263 while (sendLen > 0) {
264 if ((Fm11ReadReg(FIFO_WORDCNT_REG) & 0x3F) <= 8) { /* 8: read reg below 8 */
265 if (sendLen <= 24) { /* 24: read 24 Byte */
266 Fm11WriteFifo(sendBuf, sendLen); // write fifo 先发32字节进fifo
267 sendLen = 0;
268 } else {
269 Fm11WriteFifo(sendBuf, 24); // 24: write fifo 先发24字节进fifo
270 sendLen = sendLen - 24; // 24: 待发长度-24
271 sendBuf = sendBuf + 24; // 24: 待发数据指针+24
272 }
273 }
274 }
275 irqTxdone = 0;
276 }
277
278 /* 数据回发 */
Fm11DataSend(unsigned int iLen,unsigned char * iBuf)279 void Fm11DataSend(unsigned int iLen, unsigned char *iBuf)
280 {
281 unsigned int sLen;
282 unsigned char *sBuf = NULL;
283 unsigned int inLen = iLen;
284
285 if (iBuf == NULL) {
286 return;
287 }
288 sLen = inLen;
289 sBuf = &iBuf[0];
290
291 if (sLen <= 32) { /* 32: send data length */
292 Fm11WriteFifo(sBuf, sLen); // write fifo 有多少发多少
293 sLen = 0;
294 Fm11WriteReg(RF_TXEN_REG, 0x55); // 写0x55时触发非接触口回发数据
295 } else {
296 NfcDataRead(sBuf, sLen);
297 }
298 }
299
Fm11DataRecvInterrupt(unsigned char * rbuf)300 unsigned int Fm11DataRecvInterrupt(unsigned char *rbuf)
301 {
302 unsigned char irq = 0;
303 unsigned char ret = 0;
304 unsigned char irqDataWl = 0;
305 unsigned char irqDataIn = 0;
306 unsigned int rlen = 0;
307 unsigned int temp = 0;
308
309 while (1) {
310 irqDataWl = 0;
311 irq = Fm11ReadReg(MAIN_IRQ); // 查询中断标志
312 if (irq & MAIN_IRQ_FIFO) {
313 ret = Fm11ReadReg(FIFO_IRQ);
314 if (ret & FIFO_IRQ_WL) {
315 irqDataWl = 1;
316 }
317 }
318 if (irq & MAIN_IRQ_AUX) {
319 Fm11ReadReg(AUX_IRQ);
320 Fm11WriteReg(FIFO_FLUSH, 0xFF);
321 }
322 if (irq & MAIN_IRQ_RX_START) {
323 irqDataIn = 1; /* read reg flag */
324 }
325 if (irqDataIn && irqDataWl) {
326 irqDataWl = 0;
327 Fm11ReadFifo(24, &rbuf[rlen]); // 24: 渐满之后读取24字节
328 rlen += 24; // 24: 渐满之后读取24字节
329 }
330 if (irq & MAIN_IRQ_RX_DONE) {
331 temp = (unsigned int)(Fm11ReadReg(FIFO_WORDCNT) & 0x3F); // 0x3F: 接收完全之后,查fifo有多少字节
332 Fm11ReadFifo(temp, &rbuf[rlen]); // 读最后的数据
333 rlen += temp;
334 irqDataIn = 0;
335 break;
336 }
337 TaskMsleep(TASK_SLEEP_10MS);
338 }
339
340 if (rlen <= 2) { // 2: 字节crc校验
341 return 0;
342 }
343 rlen -= 2; // 2: 字节crc校验
344 return rlen;
345 }
346
347 /* 读取RF数据 */
Fm11DataRecv(unsigned char * rbuf)348 unsigned int Fm11DataRecv(unsigned char *rbuf)
349 {
350 unsigned char irq = 0;
351 unsigned char ret = 0;
352 unsigned char irqDataWl = 0;
353 unsigned char irqDataIn = 0;
354 unsigned int rlen = 0;
355 unsigned int temp = 0;
356
357 /* 查询方式 */
358 while (1) {
359 irqDataWl = 0;
360 irq = Fm11ReadReg(MAIN_IRQ); // 查询中断标志
361 if (irq & MAIN_IRQ_FIFO) {
362 ret = Fm11ReadReg(FIFO_IRQ);
363 if (ret & FIFO_IRQ_WL) {
364 irqDataWl = 1; /* reg read flag */
365 }
366 }
367 if (irq & MAIN_IRQ_AUX) {
368 Fm11ReadReg(AUX_IRQ);
369 Fm11WriteReg(FIFO_FLUSH, 0xFF);
370 }
371 if (irq& MAIN_IRQ_RX_START) {
372 irqDataIn = 1; /* Data read flag */
373 }
374 if (irqDataIn && irqDataWl) {
375 irqDataWl = 0;
376 Fm11ReadFifo(24, &rbuf[rlen]); // 24: 渐满之后读取24字节
377 rlen += 24; // 24: 渐满之后读取24字节
378 }
379 if (irq & MAIN_IRQ_RX_DONE) {
380 temp =(unsigned int)(Fm11ReadReg(FIFO_WORDCNT) & 0x3F); // 0x3F: 接收完全之后,查fifo有多少字节
381 Fm11ReadFifo(temp, &rbuf[rlen]); // 读最后的数据
382 rlen += temp;
383 irqDataIn = 0;
384 break;
385 }
386 TaskMsleep(TASK_SLEEP_10MS);
387 }
388
389 if (rlen <= 2) { // 2: 字节crc校验
390 return 0;
391 }
392 rlen -= 2; // 2: 字节crc校验
393 return rlen;
394 }
395
SetApdu(unsigned char * statusOk,unsigned char * statusWord2,const unsigned char * ndefCapabilityContainer,const unsigned char * ndefId)396 void SetApdu(unsigned char *statusOk, unsigned char *statusWord2,
397 const unsigned char *ndefCapabilityContainer,
398 const unsigned char *ndefId)
399 {
400 if (fm327Fifo[P1] == 0x00) { /* 0x00: FIFO P1 cmd */
401 if ((fm327Fifo[LC] == FIFO_LC_CMD) &&
402 (memcmp(ndefCapabilityContainer, fm327Fifo + DATA, fm327Fifo[LC]) == 0)) {
403 Fm11WriteFifo(statusOk, 3); /* 3: statusOk length */
404 Fm11WriteReg(RF_TXEN_REG, 0x55); /* 0x55: TX reg cmd */
405 currentFile = CC_FILE;
406 } else if ((fm327Fifo[LC] == FIFO_LC_CMD) &&
407 (memcmp(ndefId, fm327Fifo + DATA, fm327Fifo[LC]) == 0)) {
408 Fm11WriteFifo(statusOk, 3); /* 3: statusOk length */
409 Fm11WriteReg(RF_TXEN_REG, 0x55); /* TX reg cmd */
410 currentFile = NDEF_FILE;
411 } else {
412 Fm11WriteFifo(statusWord2, 3); /* 3: statusOk length */
413 Fm11WriteReg(RF_TXEN_REG, 0x55); /* TX reg cmd */
414 currentFile = NONE;
415 }
416 } else if (fm327Fifo[P1] == 0x04) { /* 0x04: FIFO P1 cmd */
417 Fm11WriteFifo(statusOk, 3); /* 3: statusOk length */
418 Fm11WriteReg(RF_TXEN_REG, 0x55); /* 0x55: TX reg cmd */
419 } else {
420 Fm11WriteFifo(statusOk, 3); /* 3: statusOk length */
421 Fm11WriteReg(RF_TXEN_REG, 0x55); /* 0x55: TX reg cmd */
422 }
423 }
424
SelectApdu(unsigned char * statusOk,unsigned char * statusWord,unsigned char * statusWord2,const unsigned char * ndefCapabilityContainer,const unsigned char * ndefId)425 void SelectApdu(unsigned char *statusOk,
426 unsigned char *statusWord,
427 unsigned char *statusWord2,
428 const unsigned char *ndefCapabilityContainer,
429 const unsigned char *ndefId)
430 {
431 unsigned char xlen;
432 unsigned char xbuf[256] = {0};
433
434 if (fm327Fifo[INS] == 0xA4) { /* 0xA4: FIFO INS cmd */
435 SetApdu(statusOk,
436 statusWord2,
437 ndefCapabilityContainer,
438 ndefId);
439 } else if (fm327Fifo[INS] == 0xB0) { /* 0xB0: FIFO INS cmd */
440 if (currentFile == CC_FILE) {
441 Fm11WriteFifo(statusOk, 1); /* 1: statusOk length */
442 Fm11WriteFifo(capabilityContainer + (fm327Fifo[P1] << 8) + fm327Fifo[P2], /* 8: left move 8 bit */
443 fm327Fifo[LC]);
444 Fm11WriteFifo(&statusOk[1], 2); /* 2: statusOk length */
445 Fm11WriteReg(RF_TXEN_REG, 0x55); /* 0x55: TX reg cmd */
446 } else if (currentFile == NDEF_FILE) {
447 (void)memcpy_s(&xbuf[0], NDEF_FILE_LEN, &statusOk[0], 1); /* 1: statusOk length */
448 (void)memcpy_s(&xbuf[1], /* 1: xbuf length */
449 NDEF_FILE_LEN,
450 &ndefFile[0] + (fm327Fifo[P1] << 8) + fm327Fifo[P2], /* 8: left move 8 bit */
451 fm327Fifo[LC]);
452 (void)memcpy_s(&xbuf[0] + fm327Fifo[LC] + 1, /* 1: compy data addr */
453 NDEF_FILE_LEN, statusOk + 1, /* 1: compy data addr */
454 2); /* 2: compy data length */
455 xlen = fm327Fifo[LC] + 3; /* 3: FIFO LC length */
456 Fm11DataSend(xlen, xbuf);
457 } else {
458 Fm11WriteFifo(statusWord, 3); /* 3: statusOk length */
459 Fm11WriteReg(RF_TXEN_REG, 0x55); /* 0x55: TX reg cmd */
460 }
461 } else if (fm327Fifo[INS] == 0xD6) { // UPDATE_BINARY
462 (void)memcpy_s(ndefFile + (fm327Fifo[P1] << 8) + fm327Fifo[P2], /* 8: left move 8 bit */
463 NDEF_FILE_LEN, fm327Fifo + DATA,
464 fm327Fifo[LC]);
465 Fm11WriteFifo(statusOk, 3); /* 3: statusOk length */
466 Fm11WriteReg(RF_TXEN_REG, 0x55); /* 0x55: TX reg cmd */
467 } else {
468 Fm11DataSend(rfLen, fm327Fifo);
469 }
470 }
471
472 /* 写fifo 和 写寄存器 */
Fm11T4t(void)473 void Fm11T4t(void)
474 {
475 unsigned char nakCrcErr = 0x05;
476 unsigned char crcErr = 0;
477 unsigned char statusOk[3] = { 0x02, 0x90, 0x00 };
478 unsigned char statusWord[3] = { 0x02, 0x6A, 0x82 };
479 unsigned char statusWord2[3] = { 0x02, 0x6A, 0x00 };
480 const unsigned char ndefCapabilityContainer[2] = { 0xE1, 0x03 };
481 const unsigned char ndefId[2] = { 0xE1, 0x04 };
482
483 if (crcErr) {
484 Fm11WriteFifo(&nakCrcErr, 1); /* 1: write FiFo length */
485 Fm11WriteReg(RF_TXEN_REG, 0x55); /* 0x55: TX reg cmd */
486 crcErr = 0;
487 } else {
488 statusOk[0] = fm327Fifo[0];
489 statusWord[0] = fm327Fifo[0];
490 statusWord2[0] = fm327Fifo[0];
491 SelectApdu(statusOk, statusWord, statusWord2,
492 ndefCapabilityContainer, ndefId);
493 }
494 }
495
496 /* app nfc demo */
NfcRead(void)497 void NfcRead(void)
498 {
499 #ifdef CHECK
500 while (1) {
501 rfLen = Fm11DataRecv(fm327Fifo); // 读取rf数据(一帧)
502 if (rfLen > 0) {
503 Fm11T4t();
504 }
505 TaskMsleep(TASK_SLEEP_1MS);
506 }
507 #endif
508
509 #ifdef NFC_INTERRUPT
510 while (1) {
511 if (FlagFirstFrame) {
512 rfLen = Fm11DataRecvInterrupt(fm327Fifo); // 读取rf数据(一帧)
513 if (rfLen > 0) {
514 fm11_t4t();
515 }
516 }
517 TaskMsleep(TASK_SLEEP_1MS);
518 }
519 #endif
520 }