• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }