blob: 7a2f46d3fda69105ebf83fb7d7865d06b17b9d21 [file] [log] [blame]
nxp72763946fc382019-11-29 17:30:41 +05301/******************************************************************************
2 *
anil.hiranniaha6c13282021-12-17 17:27:18 +05303 * Copyright 2019-2021 NXP
nxp72763946fc382019-11-29 17:30:41 +05304 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
George Changf21544f2021-05-13 05:38:02 +000018#include "NxpMfcReader.h"
nxp72763946fc382019-11-29 17:30:41 +053019#include <phNfcCompId.h>
20#include <phNxpLog.h>
21#include <phNxpNciHal_Adaptation.h>
22#include <phNxpNciHal_ext.h>
anil.hiranniahf05c3982021-03-27 10:33:22 +053023#include "phNxpNciHal.h"
nxp72763946fc382019-11-29 17:30:41 +053024
25extern bool sendRspToUpperLayer;
anil.hiranniaha6c13282021-12-17 17:27:18 +053026extern bool bEnableMfcExtns;
27extern bool bDisableLegacyMfcExtns;
nxp72763946fc382019-11-29 17:30:41 +053028
anil.hiranniahf05c3982021-03-27 10:33:22 +053029NxpMfcReader& NxpMfcReader::getInstance() {
nxp72763946fc382019-11-29 17:30:41 +053030 static NxpMfcReader msNxpMfcReader;
31 return msNxpMfcReader;
32}
33
34/*******************************************************************************
35**
36** Function Write
37**
38** Description Wrapper API to handle Mifare Transceive to TAG_CMD interface
39** RAW read write.
40**
41** Returns It returns number of bytes successfully written to NFCC.
42**
43*******************************************************************************/
anil.hiranniahf05c3982021-03-27 10:33:22 +053044int NxpMfcReader::Write(uint16_t mfcDataLen, const uint8_t* pMfcData) {
nxp72763946fc382019-11-29 17:30:41 +053045 uint16_t mfcTagCmdBuffLen = 0;
46 uint8_t mfcTagCmdBuff[MAX_MFC_BUFF_SIZE] = {0};
47
anil.hiranniaha6c13282021-12-17 17:27:18 +053048 if (mfcDataLen > MAX_MFC_BUFF_SIZE) {
49 android_errorWriteLog(0x534e4554, "169259605");
50 mfcDataLen = MAX_MFC_BUFF_SIZE;
51 }
nxp72763946fc382019-11-29 17:30:41 +053052 memcpy(mfcTagCmdBuff, pMfcData, mfcDataLen);
anil.hiranniahf05c3982021-03-27 10:33:22 +053053 if (mfcDataLen >= 3) mfcTagCmdBuffLen = mfcDataLen - NCI_HEADER_SIZE;
nxp72763946fc382019-11-29 17:30:41 +053054 BuildMfcCmd(&mfcTagCmdBuff[3], &mfcTagCmdBuffLen);
55
56 mfcTagCmdBuff[2] = mfcTagCmdBuffLen;
anil.hiranniaha6c13282021-12-17 17:27:18 +053057
58 if (checkIsMFCIncDecRestore(pMfcData[3])) {
59 if (sem_init(&mNacksem, 0, 0) != 0) {
60 NXPLOG_NCIHAL_E("%s : sem_init failed", __func__);
61 return 0;
62 }
63 }
Alisher Alikhodjaev8f88d642023-01-31 17:58:00 -080064 int writtenDataLen = phNxpNciHal_write_internal(
65 mfcTagCmdBuffLen + NCI_HEADER_SIZE, mfcTagCmdBuff);
nxp72763946fc382019-11-29 17:30:41 +053066
67 /* send TAG_CMD part 2 for Mifare increment ,decrement and restore commands */
anil.hiranniaha6c13282021-12-17 17:27:18 +053068 if (checkIsMFCIncDecRestore(pMfcData[3])) {
69 MfcWaitForAck();
70 if (isAck) {
71 NXPLOG_NCIHAL_D("part 1 command Acked");
Alisher Alikhodjaev8f88d642023-01-31 17:58:00 -080072 SendIncDecRestoreCmdPart2(mfcDataLen, pMfcData);
anil.hiranniaha6c13282021-12-17 17:27:18 +053073 } else {
74 NXPLOG_NCIHAL_E("part 1 command NACK");
75 }
76 sem_destroy(&mNacksem);
nxp72763946fc382019-11-29 17:30:41 +053077 }
78 return writtenDataLen;
79}
80
81/*******************************************************************************
82**
83** Function BuildMfcCmd
84**
85** Description builds the TAG CMD for Mifare Classic Tag.
86**
87** Returns None
88**
89*******************************************************************************/
anil.hiranniahf05c3982021-03-27 10:33:22 +053090void NxpMfcReader::BuildMfcCmd(uint8_t* pData, uint16_t* pLength) {
nxp72763946fc382019-11-29 17:30:41 +053091 uint16_t cmdBuffLen = *pLength;
92 memcpy(mMfcTagCmdIntfData.sendBuf, pData, cmdBuffLen);
93 mMfcTagCmdIntfData.sendBufLen = cmdBuffLen;
94
95 switch (pData[0]) {
anil.hiranniahf05c3982021-03-27 10:33:22 +053096 case eMifareAuthentA:
97 case eMifareAuthentB:
98 BuildAuthCmd();
99 break;
100 case eMifareRead16:
101 BuildReadCmd();
102 break;
103 case eMifareWrite16:
104 AuthForWrite();
105 BuildWrite16Cmd();
106 break;
107 case eMifareInc:
108 case eMifareDec:
109 BuildIncDecCmd();
110 break;
111 default:
112 BuildRawCmd();
113 break;
nxp72763946fc382019-11-29 17:30:41 +0530114 }
115
116 memcpy(pData, mMfcTagCmdIntfData.sendBuf, (mMfcTagCmdIntfData.sendBufLen));
117 *pLength = (mMfcTagCmdIntfData.sendBufLen);
118 return;
119}
120
121/*******************************************************************************
122**
123** Function BuildAuthCmd
124**
125** Description builds the TAG CMD for Mifare Auth.
126**
127** Returns None
128**
129*******************************************************************************/
130void NxpMfcReader::BuildAuthCmd() {
131 uint8_t byKey = 0x00, noOfKeys = 0x00;
132 bool isPreloadedKey = false;
133
134 if (mMfcTagCmdIntfData.sendBuf[0] == eMifareAuthentB) {
135 byKey |= MFC_ENABLE_KEY_B;
136 }
137 uint8_t aMfckeys[MFC_NUM_OF_KEYS][MFC_KEY_SIZE] = MFC_KEYS;
138 noOfKeys = sizeof(aMfckeys) / MFC_KEY_SIZE;
139 for (uint8_t byIndex = 0; byIndex < noOfKeys; byIndex++) {
140 if ((memcmp(aMfckeys[byIndex], &mMfcTagCmdIntfData.sendBuf[6],
141 MFC_AUTHKEYLEN) == 0x00)) {
142 byKey = byKey | byIndex;
143 isPreloadedKey = true;
144 break;
145 }
146 }
147 CalcSectorAddress();
148 mMfcTagCmdIntfData.sendBufLen = 0x03;
149 if (!isPreloadedKey) {
150 byKey |= MFC_EMBEDDED_KEY;
Anil Hiranniahbf307e52020-02-20 10:06:38 +0530151 memmove(&mMfcTagCmdIntfData.sendBuf[3], &mMfcTagCmdIntfData.sendBuf[6],
anil.hiranniahf05c3982021-03-27 10:33:22 +0530152 MFC_AUTHKEYLEN);
nxp72763946fc382019-11-29 17:30:41 +0530153 mMfcTagCmdIntfData.sendBufLen += MFC_AUTHKEYLEN;
154 }
155
156 mMfcTagCmdIntfData.sendBuf[0] = eMfcAuthReq;
157 mMfcTagCmdIntfData.sendBuf[1] = mMfcTagCmdIntfData.byAddr;
158 mMfcTagCmdIntfData.sendBuf[2] = byKey;
159 return;
160}
161
162/*******************************************************************************
163**
164** Function CalcSectorAddress
165**
166** Description This function update the sector address for Mifare classic
167**
168** Returns None
169**
170*******************************************************************************/
171void NxpMfcReader::CalcSectorAddress() {
172 uint8_t BlockNumber = mMfcTagCmdIntfData.sendBuf[1];
173 if (BlockNumber >= MFC_4K_BLK128) {
174 mMfcTagCmdIntfData.byAddr =
175 (uint8_t)(MFC_SECTOR_NO32 +
176 ((BlockNumber - MFC_4K_BLK128) / MFC_BYTES_PER_BLOCK));
177 } else {
178 mMfcTagCmdIntfData.byAddr = BlockNumber / MFC_BLKS_PER_SECTOR;
179 }
180
181 return;
182}
183
184/*******************************************************************************
185**
186** Function BuildReadCmd
187**
188** Description builds the TAG CMD for Mifare Read.
189**
190** Returns None
191**
192*******************************************************************************/
193void NxpMfcReader::BuildReadCmd() { BuildRawCmd(); }
194
195/*******************************************************************************
196**
anil.hiranniaha6c13282021-12-17 17:27:18 +0530197** Function checkIsMFCIncDecRestore
198**
199** Description Check command is MF Increment/Decrement or Restore.
200**
201** Returns True/False
202**
203*******************************************************************************/
204bool NxpMfcReader::checkIsMFCIncDecRestore(uint8_t cmdInst) {
205 return (cmdInst == eMifareDec || cmdInst == eMifareInc ||
206 cmdInst == eMifareRestore);
207}
208
209/*******************************************************************************
210**
nxp72763946fc382019-11-29 17:30:41 +0530211** Function BuildWrite16Cmd
212**
213** Description builds the TAG CMD for Mifare write part 2.
214**
215** Returns None
216**
217*******************************************************************************/
218void NxpMfcReader::BuildWrite16Cmd() {
219 mMfcTagCmdIntfData.sendBuf[0] = eMfRawDataXchgHdr;
220 mMfcTagCmdIntfData.sendBufLen = mMfcTagCmdIntfData.sendBufLen - 1;
anil.hiranniaha6c13282021-12-17 17:27:18 +0530221 uint8_t buff[mMfcTagCmdIntfData.sendBufLen];
222 memset(buff, 0, mMfcTagCmdIntfData.sendBufLen);
223 memcpy(buff, mMfcTagCmdIntfData.sendBuf + 2, mMfcTagCmdIntfData.sendBufLen);
224 memcpy(mMfcTagCmdIntfData.sendBuf + 1, buff, mMfcTagCmdIntfData.sendBufLen);
nxp72763946fc382019-11-29 17:30:41 +0530225}
226
227/*******************************************************************************
228**
229** Function BuildRawCmd
230**
231** Description builds the TAG CMD for Raw transceive.
232**
233** Returns None
234**
235*******************************************************************************/
236void NxpMfcReader::BuildRawCmd() {
237 mMfcTagCmdIntfData.sendBufLen = mMfcTagCmdIntfData.sendBufLen + 1;
anil.hiranniahf05c3982021-03-27 10:33:22 +0530238 uint8_t buff[mMfcTagCmdIntfData.sendBufLen];
239 memset(buff, 0, mMfcTagCmdIntfData.sendBufLen);
240 memcpy(buff, mMfcTagCmdIntfData.sendBuf, mMfcTagCmdIntfData.sendBufLen);
241 memcpy(mMfcTagCmdIntfData.sendBuf + 1, buff, mMfcTagCmdIntfData.sendBufLen);
nxp72763946fc382019-11-29 17:30:41 +0530242 mMfcTagCmdIntfData.sendBuf[0] = eMfRawDataXchgHdr;
243}
244
245/*******************************************************************************
246**
247** Function BuildIncDecCmd
248**
249** Description builds the TAG CMD for Mifare Inc/Dec.
250**
251** Returns None
252**
253*******************************************************************************/
254void NxpMfcReader::BuildIncDecCmd() {
anil.hiranniahf05c3982021-03-27 10:33:22 +0530255 mMfcTagCmdIntfData.sendBufLen = 0x03; // eMfRawDataXchgHdr + cmd +
256 // blockaddress
257 uint8_t buff[mMfcTagCmdIntfData.sendBufLen];
258 memset(buff, 0, mMfcTagCmdIntfData.sendBufLen);
259 memcpy(buff, mMfcTagCmdIntfData.sendBuf, mMfcTagCmdIntfData.sendBufLen);
260 memcpy(mMfcTagCmdIntfData.sendBuf + 1, buff, mMfcTagCmdIntfData.sendBufLen);
nxp72763946fc382019-11-29 17:30:41 +0530261 mMfcTagCmdIntfData.sendBuf[0] = eMfRawDataXchgHdr;
262}
263
264/*******************************************************************************
265**
266** Function AuthForWrite
267**
268** Description send Mifare write Part 1.
269**
270** Returns None
271**
272*******************************************************************************/
273void NxpMfcReader::AuthForWrite() {
274 sendRspToUpperLayer = false;
275 NFCSTATUS status = NFCSTATUS_FAILED;
276 uint8_t authForWriteBuff[] = {0x00,
277 0x00,
278 0x03,
279 (uint8_t)eMfRawDataXchgHdr,
280 (uint8_t)mMfcTagCmdIntfData.sendBuf[0],
281 (uint8_t)mMfcTagCmdIntfData.sendBuf[1]};
282
283 status = phNxpNciHal_send_ext_cmd(
284 sizeof(authForWriteBuff) / sizeof(authForWriteBuff[0]), authForWriteBuff);
285 if (status != NFCSTATUS_SUCCESS) {
286 NXPLOG_NCIHAL_E("Mifare Auth for Transceive failed");
287 }
288 return;
289}
290
291/*******************************************************************************
292**
293** Function SendIncDecRestoreCmdPart2
294**
295** Description send Mifare Inc/Dec/Restore Command Part 2.
296**
297** Returns None
298**
299*******************************************************************************/
Alisher Alikhodjaev8f88d642023-01-31 17:58:00 -0800300void NxpMfcReader::SendIncDecRestoreCmdPart2(uint16_t mfcDataLen,
301 const uint8_t* mfcData) {
nxp72763946fc382019-11-29 17:30:41 +0530302 NFCSTATUS status = NFCSTATUS_SUCCESS;
303 /* Build TAG_CMD part 2 for Mifare increment ,decrement and restore commands*/
304 uint8_t incDecRestorePart2[] = {0x00, 0x00, 0x05, (uint8_t)eMfRawDataXchgHdr,
305 0x00, 0x00, 0x00, 0x00};
306 uint8_t incDecRestorePart2Size =
307 (sizeof(incDecRestorePart2) / sizeof(incDecRestorePart2[0]));
308 if (mfcData[3] == eMifareInc || mfcData[3] == eMifareDec) {
Alisher Alikhodjaev8f88d642023-01-31 17:58:00 -0800309 if (incDecRestorePart2Size >= mfcDataLen) {
310 incDecRestorePart2Size = mfcDataLen - 1;
311 android_errorWriteLog(0x534e4554, "238177877");
312 }
nxp72763946fc382019-11-29 17:30:41 +0530313 for (int i = 4; i < incDecRestorePart2Size; i++) {
314 incDecRestorePart2[i] = mfcData[i + 1];
315 }
316 }
317 sendRspToUpperLayer = false;
318 status = phNxpNciHal_send_ext_cmd(incDecRestorePart2Size, incDecRestorePart2);
319 if (status != NFCSTATUS_SUCCESS) {
320 NXPLOG_NCIHAL_E("Mifare Cmd for inc/dec/Restore part 2 failed");
321 }
322 return;
323}
324
325/*******************************************************************************
326**
327** Function AnalyzeMfcResp
328**
329** Description Analyze type of MFC response and build MFC response from
330** Tag cmd Intf response?
331**
332** Returns NFCSTATUS_SUCCESS - Data Reception is successful
333** NFCSTATUS_FAILED - Data Reception failed
334**
335*******************************************************************************/
anil.hiranniahf05c3982021-03-27 10:33:22 +0530336NFCSTATUS NxpMfcReader::AnalyzeMfcResp(uint8_t* pBuff, uint16_t* pBufflen) {
nxp72763946fc382019-11-29 17:30:41 +0530337 NFCSTATUS status = NFCSTATUS_SUCCESS;
338 uint16_t wPldDataSize = 0;
339 MfcRespId_t RecvdExtnRspId = eInvalidRsp;
340
341 if (0 == (*pBufflen)) {
342 status = NFCSTATUS_FAILED;
343 } else {
344 RecvdExtnRspId = (MfcRespId_t)pBuff[0];
345 NXPLOG_NCIHAL_E("%s: RecvdExtnRspId=%d", __func__, RecvdExtnRspId);
346 switch (RecvdExtnRspId) {
anil.hiranniahf05c3982021-03-27 10:33:22 +0530347 case eMfXchgDataRsp: {
348 NFCSTATUS writeRespStatus = NFCSTATUS_SUCCESS;
349 /* check the status byte */
350 if (*pBufflen == 3) {
351 if ((pBuff[0] == 0x10) && (pBuff[1] != 0x0A)) {
352 NXPLOG_NCIHAL_E("Mifare Error in payload response");
353 *pBufflen = 0x1;
354 pBuff[0] = NFCSTATUS_FAILED;
355 return NFCSTATUS_FAILED;
356 } else {
357 pBuff[0] = NFCSTATUS_SUCCESS;
358 return NFCSTATUS_SUCCESS;
359 }
nxp72763946fc382019-11-29 17:30:41 +0530360 }
anil.hiranniahf05c3982021-03-27 10:33:22 +0530361 writeRespStatus = pBuff[*pBufflen - 1];
nxp72763946fc382019-11-29 17:30:41 +0530362
anil.hiranniahf05c3982021-03-27 10:33:22 +0530363 if (NFCSTATUS_SUCCESS == writeRespStatus) {
364 status = NFCSTATUS_SUCCESS;
365 uint16_t wRecvDataSz = 0;
George Changf21544f2021-05-13 05:38:02 +0000366
anil.hiranniahf05c3982021-03-27 10:33:22 +0530367 wPldDataSize =
368 ((*pBufflen) - (MFC_EXTN_ID_SIZE + MFC_EXTN_STATUS_SIZE));
369 wRecvDataSz = MAX_MFC_BUFF_SIZE;
370 if ((wPldDataSize) <= wRecvDataSz) {
371 /* Extract the data part from pBuff[2] & fill it to be sent to
372 * upper layer */
373 memcpy(&(pBuff[0]), &(pBuff[1]), wPldDataSize);
374 /* update the number of bytes received from lower layer,excluding
375 * the status byte */
376 *pBufflen = wPldDataSize;
377 } else {
378 status = NFCSTATUS_FAILED;
379 }
anil.hiranniah5c4c40d2021-03-27 10:33:22 +0530380 } else {
anil.hiranniah5c4c40d2021-03-27 10:33:22 +0530381 status = NFCSTATUS_FAILED;
382 }
anil.hiranniahf05c3982021-03-27 10:33:22 +0530383 } break;
George Changf21544f2021-05-13 05:38:02 +0000384
anil.hiranniahf05c3982021-03-27 10:33:22 +0530385 case eMfcAuthRsp: {
Alisher Alikhodjaev10a70012023-03-01 13:00:03 -0800386 if (*pBufflen < 2) {
387 status = NFCSTATUS_FAILED;
388 break;
389 }
anil.hiranniahf05c3982021-03-27 10:33:22 +0530390 /* check the status byte */
391 if (NFCSTATUS_SUCCESS == pBuff[1]) {
392 status = NFCSTATUS_SUCCESS;
393 /* DataLen = TotalRecvdLen - (sizeof(RspId) + sizeof(Status)) */
394 wPldDataSize =
395 ((*pBufflen) - (MFC_EXTN_ID_SIZE + MFC_EXTN_STATUS_SIZE));
396 /* Extract the data part from pBuff[2] & fill it to be sent to upper
397 * layer */
398 pBuff[0] = pBuff[1];
399 /* update the number of bytes received from lower layer,excluding
400 * the status byte */
401 *pBufflen = wPldDataSize + 1;
402 } else {
403 pBuff[0] = pBuff[1];
404 *pBufflen = 1;
405 status = NFCSTATUS_FAILED;
406 }
407 } break;
408 default: {
George Changf21544f2021-05-13 05:38:02 +0000409 status = NFCSTATUS_FAILED;
anil.hiranniahf05c3982021-03-27 10:33:22 +0530410 } break;
nxp72763946fc382019-11-29 17:30:41 +0530411 }
412 }
413 return status;
414}
415
416/*******************************************************************************
417**
418** Function CheckMfcResponse
419**
420** Description This function is called to check if it's a valid Mfc
421** response data
422**
423** Returns NFCSTATUS_SUCCESS
424** NFCSTATUS_FAILED
425**
426*******************************************************************************/
anil.hiranniahf05c3982021-03-27 10:33:22 +0530427NFCSTATUS NxpMfcReader::CheckMfcResponse(uint8_t* pTransceiveData,
nxp72763946fc382019-11-29 17:30:41 +0530428 uint16_t transceiveDataLen) {
429 NFCSTATUS status = NFCSTATUS_SUCCESS;
430
431 if (transceiveDataLen == 3) {
432 if ((pTransceiveData)[0] == 0x10 && (pTransceiveData)[1] != 0x0A) {
433 NXPLOG_NCIHAL_E("Mifare Error in payload response");
434 transceiveDataLen = 0x1;
435 pTransceiveData += 1;
436 return NFCSTATUS_FAILED;
437 }
438 }
439 if ((pTransceiveData)[0] == 0x40) {
440 pTransceiveData += 1;
441 transceiveDataLen = 0x01;
442 if ((pTransceiveData)[0] == 0x03) {
443 transceiveDataLen = 0x00;
444 status = NFCSTATUS_FAILED;
445 }
446 } else if ((pTransceiveData)[0] == 0x10) {
447 pTransceiveData += 1;
448 transceiveDataLen = 0x10;
449 }
450 return status;
451}
anil.hiranniaha6c13282021-12-17 17:27:18 +0530452
453/*******************************************************************************
454**
455** Function MfcAckReceived
456**
457** Description This function is called to notify that MFC
458** response data is received
459**
460** Returns NFCSTATUS_SUCCESS
461** NFCSTATUS_FAILED
462**
463*******************************************************************************/
464void NxpMfcReader::MfcNotifyOnAckReceived(uint8_t* buff) {
465 const uint8_t NCI_RF_CONN_ID = 0;
466 /*
467 * If Mifare Activated & received RF data packet
468 */
469 if (bEnableMfcExtns && bDisableLegacyMfcExtns &&
470 (buff[0] == NCI_RF_CONN_ID)) {
471 int sem_val;
472 isAck = (buff[3] == NFCSTATUS_SUCCESS);
473 sem_getvalue(&mNacksem, &sem_val);
474 if (sem_val == 0) {
475 if (sem_post(&mNacksem) == -1) {
476 NXPLOG_NCIHAL_E("%s : sem_post failed", __func__);
477 }
478 }
479 }
480}
481
482/*******************************************************************************
483**
484** Function MfcWaitForAck
485**
486** Description This function is called to wait for MFC NACK
487**
488** Returns NFCSTATUS_SUCCESS
489** NFCSTATUS_FAILED
490**
491*******************************************************************************/
492NFCSTATUS NxpMfcReader::MfcWaitForAck() {
493 NFCSTATUS status = NFCSTATUS_FAILED;
494 int sem_timedout = 2, s;
495 struct timespec ts;
496 isAck = false;
Keith Mok783e0e52022-01-25 18:50:02 +0000497 clock_gettime(CLOCK_MONOTONIC, &ts);
anil.hiranniaha6c13282021-12-17 17:27:18 +0530498 ts.tv_sec += sem_timedout;
Keith Mok783e0e52022-01-25 18:50:02 +0000499 while ((s = sem_timedwait_monotonic_np(&mNacksem, &ts)) == -1 && errno == EINTR) {
anil.hiranniaha6c13282021-12-17 17:27:18 +0530500 continue; /* Restart if interrupted by handler */
501 }
502 if (s != -1) {
503 status = NFCSTATUS_SUCCESS;
504 }
505 return status;
506}