1/*
2 * Copyright (C) 2012-2014 NXP Semiconductors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <phDal4Nfc_messageQueueLib.h>
17#include <phNxpConfig.h>
18#include <phNxpLog.h>
19#include <phNxpNciHal.h>
20#include <phNxpNciHal_NfcDepSWPrio.h>
21#include <phNxpNciHal_ext.h>
22#include <phTmlNfc.h>
23
24/* Timeout value to wait for response from PN548AD */
25#define HAL_EXTNS_WRITE_RSP_TIMEOUT (1000)
26
27#undef P2P_PRIO_LOGIC_HAL_IMP
28
29/******************* Global variables *****************************************/
30extern phNxpNciHal_Control_t nxpncihal_ctrl;
31extern phNxpNciProfile_Control_t nxpprofile_ctrl;
32
33extern uint32_t cleanup_timer;
34uint8_t icode_detected = 0x00;
35uint8_t icode_send_eof = 0x00;
36#if (NFC_NXP_CHIP_TYPE == PN548C2)
37uint8_t nfcdep_detected = 0x00;
38#endif
39static uint8_t ee_disc_done = 0x00;
40uint8_t EnableP2P_PrioLogic = false;
41static uint32_t RfDiscID = 1;
42static uint32_t RfProtocolType = 4;
43/* NFCEE Set mode */
44static uint8_t setEEModeDone = 0x00;
45static uint8_t cmd_nfcee_setmode_enable[] = {0x22, 0x01, 0x02, 0x01, 0x01};
46
47/* External global variable to get FW version from NCI response*/
48extern uint32_t wFwVerRsp;
49/* External global variable to get FW version from FW file*/
50extern uint16_t wFwVer;
51
52uint16_t fw_maj_ver;
53uint16_t rom_version;
54/* local buffer to store CORE_INIT response */
55static uint32_t bCoreInitRsp[40];
56static uint32_t iCoreInitRspLen;
57
58extern uint32_t timeoutTimerId;
59
60extern NFCSTATUS read_retry();
61
62/************** HAL extension functions ***************************************/
63static void hal_extns_write_rsp_timeout_cb(uint32_t TimerId, void* pContext);
64
65/*Proprietary cmd sent to HAL to send reader mode flag
66 * Last byte of 4 byte proprietary cmd data contains ReaderMode flag
67 * If this flag is enabled, NFC-DEP protocol is modified to T3T protocol
68 * if FrameRF interface is selected. This needs to be done as the FW
69 * always sends Ntf for FrameRF with NFC-DEP even though FrameRF with T3T is
70 * previously selected with DISCOVER_SELECT_CMD
71 */
72#define PROPRIETARY_CMD_FELICA_READER_MODE 0xFE
73static uint8_t gFelicaReaderMode;
74
75static NFCSTATUS phNxpNciHal_ext_process_nfc_init_rsp(uint8_t* p_ntf,
76                                                      uint16_t* p_len);
77/*******************************************************************************
78**
79** Function         phNxpNciHal_ext_init
80**
81** Description      initialize extension function
82**
83*******************************************************************************/
84void phNxpNciHal_ext_init(void) {
85  icode_detected = 0x00;
86  icode_send_eof = 0x00;
87  setEEModeDone = 0x00;
88  EnableP2P_PrioLogic = false;
89}
90
91/*******************************************************************************
92**
93** Function         phNxpNciHal_process_ext_rsp
94**
95** Description      Process extension function response
96**
97** Returns          NFCSTATUS_SUCCESS if success
98**
99*******************************************************************************/
100NFCSTATUS phNxpNciHal_process_ext_rsp(uint8_t* p_ntf, uint16_t* p_len) {
101  NFCSTATUS status = NFCSTATUS_SUCCESS;
102  uint16_t rf_technology_length_param = 0;
103
104  if (p_ntf[0] == 0x61 && p_ntf[1] == 0x05 && p_ntf[4] == 0x03 &&
105      p_ntf[5] == 0x05 && nxpprofile_ctrl.profile_type == EMV_CO_PROFILE) {
106    p_ntf[4] = 0xFF;
107    p_ntf[5] = 0xFF;
108    p_ntf[6] = 0xFF;
109    NXPLOG_NCIHAL_D("Nfc-Dep Detect in EmvCo profile - Restart polling");
110  }
111
112  if (p_ntf[0] == 0x61 && p_ntf[1] == 0x05 && p_ntf[4] == 0x01 &&
113      p_ntf[5] == 0x05 && p_ntf[6] == 0x02 && gFelicaReaderMode) {
114    /*If FelicaReaderMode is enabled,Change Protocol to T3T from NFC-DEP
115         * when FrameRF interface is selected*/
116    p_ntf[5] = 0x03;
117    NXPLOG_NCIHAL_D("FelicaReaderMode:Activity 1.1");
118  }
119
120#ifdef P2P_PRIO_LOGIC_HAL_IMP
121  if (p_ntf[0] == 0x61 && p_ntf[1] == 0x05 && p_ntf[4] == 0x02 &&
122      p_ntf[5] == 0x04 && nxpprofile_ctrl.profile_type == NFC_FORUM_PROFILE) {
123    EnableP2P_PrioLogic = true;
124  }
125
126  NXPLOG_NCIHAL_D("Is EnableP2P_PrioLogic: 0x0%X", EnableP2P_PrioLogic);
127  if (phNxpDta_IsEnable() == false) {
128    if ((icode_detected != 1) && (EnableP2P_PrioLogic == true)) {
129      if (phNxpNciHal_NfcDep_comapre_ntf(p_ntf, *p_len) == NFCSTATUS_FAILED) {
130        status = phNxpNciHal_NfcDep_rsp_ext(p_ntf, p_len);
131        if (status != NFCSTATUS_INVALID_PARAMETER) {
132          return status;
133        }
134      }
135    }
136  }
137#endif
138
139  status = NFCSTATUS_SUCCESS;
140
141  if (p_ntf[0] == 0x61 && p_ntf[1] == 0x05) {
142#if (NFC_NXP_CHIP_TYPE == PN548C2)
143    if (nfcdep_detected) {
144      nfcdep_detected = 0x00;
145    }
146#endif
147
148    switch (p_ntf[4]) {
149      case 0x00:
150        NXPLOG_NCIHAL_D("NxpNci: RF Interface = NFCEE Direct RF");
151        break;
152      case 0x01:
153        NXPLOG_NCIHAL_D("NxpNci: RF Interface = Frame RF");
154        break;
155      case 0x02:
156        NXPLOG_NCIHAL_D("NxpNci: RF Interface = ISO-DEP");
157        break;
158      case 0x03:
159        NXPLOG_NCIHAL_D("NxpNci: RF Interface = NFC-DEP");
160#if (NFC_NXP_CHIP_TYPE == PN548C2)
161        nfcdep_detected = 0x01;
162#endif
163        break;
164      case 0x80:
165        NXPLOG_NCIHAL_D("NxpNci: RF Interface = MIFARE");
166        break;
167      default:
168        NXPLOG_NCIHAL_D("NxpNci: RF Interface = Unknown");
169        break;
170    }
171
172    switch (p_ntf[5]) {
173      case 0x01:
174        NXPLOG_NCIHAL_D("NxpNci: Protocol = T1T");
175        phNxpDta_T1TEnable();
176        break;
177      case 0x02:
178        NXPLOG_NCIHAL_D("NxpNci: Protocol = T2T");
179        break;
180      case 0x03:
181        NXPLOG_NCIHAL_D("NxpNci: Protocol = T3T");
182        break;
183      case 0x04:
184        NXPLOG_NCIHAL_D("NxpNci: Protocol = ISO-DEP");
185        break;
186      case 0x05:
187        NXPLOG_NCIHAL_D("NxpNci: Protocol = NFC-DEP");
188        break;
189      case 0x06:
190        NXPLOG_NCIHAL_D("NxpNci: Protocol = 15693");
191        break;
192      case 0x80:
193        NXPLOG_NCIHAL_D("NxpNci: Protocol = MIFARE");
194        break;
195#if (NFC_NXP_CHIP_TYPE != PN547C2)
196      case 0x81:
197#else
198      case 0x8A:
199#endif
200        NXPLOG_NCIHAL_D("NxpNci: Protocol = Kovio");
201        break;
202      default:
203        NXPLOG_NCIHAL_D("NxpNci: Protocol = Unknown");
204        break;
205    }
206
207    switch (p_ntf[6]) {
208      case 0x00:
209        NXPLOG_NCIHAL_D("NxpNci: Mode = A Passive Poll");
210        break;
211      case 0x01:
212        NXPLOG_NCIHAL_D("NxpNci: Mode = B Passive Poll");
213        break;
214      case 0x02:
215        NXPLOG_NCIHAL_D("NxpNci: Mode = F Passive Poll");
216        break;
217      case 0x03:
218        NXPLOG_NCIHAL_D("NxpNci: Mode = A Active Poll");
219        break;
220      case 0x05:
221        NXPLOG_NCIHAL_D("NxpNci: Mode = F Active Poll");
222        break;
223      case 0x06:
224        NXPLOG_NCIHAL_D("NxpNci: Mode = 15693 Passive Poll");
225        break;
226#if (NFC_NXP_CHIP_TYPE != PN547C2)
227      case 0x70:
228#else
229      case 0x77:
230#endif
231        NXPLOG_NCIHAL_D("NxpNci: Mode = Kovio");
232        break;
233      case 0x80:
234        NXPLOG_NCIHAL_D("NxpNci: Mode = A Passive Listen");
235        break;
236      case 0x81:
237        NXPLOG_NCIHAL_D("NxpNci: Mode = B Passive Listen");
238        break;
239      case 0x82:
240        NXPLOG_NCIHAL_D("NxpNci: Mode = F Passive Listen");
241        break;
242      case 0x83:
243        NXPLOG_NCIHAL_D("NxpNci: Mode = A Active Listen");
244        break;
245      case 0x85:
246        NXPLOG_NCIHAL_D("NxpNci: Mode = F Active Listen");
247        break;
248      case 0x86:
249        NXPLOG_NCIHAL_D("NxpNci: Mode = 15693 Passive Listen");
250        break;
251      default:
252        NXPLOG_NCIHAL_D("NxpNci: Mode = Unknown");
253        break;
254    }
255  }
256  phNxpNciHal_ext_process_nfc_init_rsp(p_ntf, p_len);
257
258  if (p_ntf[0] == 0x61 && p_ntf[1] == 0x05 && p_ntf[2] == 0x15 &&
259      p_ntf[4] == 0x01 && p_ntf[5] == 0x06 && p_ntf[6] == 0x06) {
260    NXPLOG_NCIHAL_D("> Going through workaround - notification of ISO 15693");
261    icode_detected = 0x01;
262    p_ntf[21] = 0x01;
263    p_ntf[22] = 0x01;
264  } else if (icode_detected == 1 && icode_send_eof == 2) {
265    icode_send_eof = 3;
266  } else if (p_ntf[0] == 0x00 && p_ntf[1] == 0x00 && icode_detected == 1) {
267    if (icode_send_eof == 3) {
268      icode_send_eof = 0;
269    }
270    if (nxpncihal_ctrl.nci_info.nci_version != NCI_VERSION_2_0) {
271      if (p_ntf[p_ntf[2] + 2] == 0x00) {
272        NXPLOG_NCIHAL_D("> Going through workaround - data of ISO 15693");
273        p_ntf[2]--;
274        (*p_len)--;
275      } else {
276        p_ntf[p_ntf[2] + 2] |= 0x01;
277      }
278    }
279  } else if (p_ntf[2] == 0x02 && p_ntf[1] == 0x00 && icode_detected == 1) {
280    NXPLOG_NCIHAL_D("> ICODE EOF response do not send to upper layer");
281  } else if (p_ntf[0] == 0x61 && p_ntf[1] == 0x06 && icode_detected == 1) {
282    NXPLOG_NCIHAL_D("> Polling Loop Re-Started");
283    icode_detected = 0;
284    icode_send_eof = 0;
285  } else if (*p_len == 4 && p_ntf[0] == 0x40 && p_ntf[1] == 0x02 &&
286             p_ntf[2] == 0x01 && p_ntf[3] == 0x06) {
287    NXPLOG_NCIHAL_D("> Deinit workaround for LLCP set_config 0x%x 0x%x 0x%x",
288                    p_ntf[21], p_ntf[22], p_ntf[23]);
289    p_ntf[0] = 0x40;
290    p_ntf[1] = 0x02;
291    p_ntf[2] = 0x02;
292    p_ntf[3] = 0x00;
293    p_ntf[4] = 0x00;
294    *p_len = 5;
295  }
296  // 4200 02 00 01
297  else if (p_ntf[0] == 0x42 && p_ntf[1] == 0x00 && ee_disc_done == 0x01) {
298    NXPLOG_NCIHAL_D("Going through workaround - NFCEE_DISCOVER_RSP");
299    if (p_ntf[4] == 0x01) {
300      p_ntf[4] = 0x00;
301
302      ee_disc_done = 0x00;
303    }
304    NXPLOG_NCIHAL_D("Going through workaround - NFCEE_DISCOVER_RSP - END");
305
306  } else if (p_ntf[0] == 0x61 && p_ntf[1] == 0x03 /*&& cleanup_timer!=0*/) {
307    if (cleanup_timer != 0) {
308      /* if RF Notification Type of RF_DISCOVER_NTF is Last Notification */
309      if (0 == (*(p_ntf + 2 + (*(p_ntf + 2))))) {
310        phNxpNciHal_select_RF_Discovery(RfDiscID, RfProtocolType);
311        status = NFCSTATUS_FAILED;
312        return status;
313      } else {
314        RfDiscID = p_ntf[3];
315        RfProtocolType = p_ntf[4];
316      }
317      status = NFCSTATUS_FAILED;
318      return status;
319    }
320  } else if (p_ntf[0] == 0x41 && p_ntf[1] == 0x04 && cleanup_timer != 0) {
321    status = NFCSTATUS_FAILED;
322    return status;
323  }
324#if (NFC_NXP_CHIP_TYPE == PN547C2)
325  else if (p_ntf[0] == 0x61 && p_ntf[1] == 0x05 && p_ntf[4] == 0x02 &&
326           p_ntf[5] == 0x80 && p_ntf[6] == 0x00) {
327    NXPLOG_NCIHAL_D(
328        "Going through workaround - iso-dep  interface  mifare protocol with "
329        "sak value not equal to 0x20");
330    rf_technology_length_param = p_ntf[9];
331    if ((p_ntf[9 + rf_technology_length_param] & 0x20) != 0x20) {
332      p_ntf[4] = 0x80;
333    }
334  }
335#endif
336  else if (*p_len == 4 && p_ntf[0] == 0x4F && p_ntf[1] == 0x11 &&
337           p_ntf[2] == 0x01) {
338    if (p_ntf[3] == 0x00) {
339      NXPLOG_NCIHAL_D(
340          ">  Workaround for ISO-DEP Presence Check, ignore response and wait "
341          "for notification");
342      p_ntf[0] = 0x60;
343      p_ntf[1] = 0x06;
344      p_ntf[2] = 0x03;
345      p_ntf[3] = 0x01;
346      p_ntf[4] = 0x00;
347      p_ntf[5] = 0x01;
348      *p_len = 6;
349    } else {
350      NXPLOG_NCIHAL_D(
351          ">  Workaround for ISO-DEP Presence Check, presence check return "
352          "failed");
353      p_ntf[0] = 0x60;
354      p_ntf[1] = 0x08;
355      p_ntf[2] = 0x02;
356      p_ntf[3] = 0xB2;
357      p_ntf[4] = 0x00;
358      *p_len = 5;
359    }
360  } else if (*p_len == 4 && p_ntf[0] == 0x6F && p_ntf[1] == 0x11 &&
361             p_ntf[2] == 0x01) {
362    if (p_ntf[3] == 0x01) {
363      NXPLOG_NCIHAL_D(
364          ">  Workaround for ISO-DEP Presence Check - Card still in field");
365      p_ntf[0] = 0x00;
366      p_ntf[1] = 0x00;
367      p_ntf[2] = 0x01;
368      p_ntf[3] = 0x7E;
369    } else {
370      NXPLOG_NCIHAL_D(
371          ">  Workaround for ISO-DEP Presence Check - Card not in field");
372      p_ntf[0] = 0x60;
373      p_ntf[1] = 0x08;
374      p_ntf[2] = 0x02;
375      p_ntf[3] = 0xB2;
376      p_ntf[4] = 0x00;
377      *p_len = 5;
378    }
379  }
380  /*
381  else if(p_ntf[0] == 0x61 && p_ntf[1] == 0x05 && p_ntf[4] == 0x01 && p_ntf[5]
382  == 0x00 && p_ntf[6] == 0x01)
383  {
384      NXPLOG_NCIHAL_D("Picopass type 3-B with undefined protocol is not
385  supported, disabling");
386      p_ntf[4] = 0xFF;
387      p_ntf[5] = 0xFF;
388      p_ntf[6] = 0xFF;
389  }*/
390
391  return status;
392}
393
394/******************************************************************************
395 * Function         phNxpNciHal_ext_process_nfc_init_rsp
396 *
397 * Description      This function is used to process the HAL NFC core reset rsp
398 *                  and ntf and core init rsp of NCI 1.0 or NCI2.0 and update
399 *                  NCI version.
400 *                  It also handles error response such as core_reset_ntf with
401 *                  error status in both NCI2.0 and NCI1.0.
402 *
403 * Returns          Returns NFCSTATUS_SUCCESS if parsing response is successful
404 *                  or returns failure.
405 *
406 *******************************************************************************/
407static NFCSTATUS phNxpNciHal_ext_process_nfc_init_rsp(uint8_t* p_ntf,
408                                                      uint16_t* p_len) {
409  NFCSTATUS status = NFCSTATUS_SUCCESS;
410  /* Parsing CORE_RESET_RSP and CORE_RESET_NTF to update NCI version.*/
411  if (p_ntf == NULL || *p_len == 0x00) {
412    return NFCSTATUS_FAILED;
413  }
414  if (p_ntf[0] == NCI_MT_RSP &&
415      ((p_ntf[1] & NCI_OID_MASK) == NCI_MSG_CORE_RESET)) {
416    if (p_ntf[2] == 0x01 && p_ntf[3] == 0x00) {
417      NXPLOG_NCIHAL_D("CORE_RESET_RSP NCI2.0");
418      if (nxpncihal_ctrl.hal_ext_enabled == TRUE) {
419        nxpncihal_ctrl.nci_info.wait_for_ntf = TRUE;
420      }
421    } else if (p_ntf[2] == 0x03 && p_ntf[3] == 0x00) {
422      NXPLOG_NCIHAL_D("CORE_RESET_RSP NCI1.0");
423      nxpncihal_ctrl.nci_info.nci_version = p_ntf[4];
424    }
425  } else if (p_ntf[0] == NCI_MT_NTF &&
426             ((p_ntf[1] & NCI_OID_MASK) == NCI_MSG_CORE_RESET)) {
427    if (p_ntf[3] == CORE_RESET_TRIGGER_TYPE_CORE_RESET_CMD_RECEIVED ||
428        p_ntf[3] == CORE_RESET_TRIGGER_TYPE_POWERED_ON) {
429      NXPLOG_NCIHAL_D("CORE_RESET_NTF NCI2.0 reason CORE_RESET_CMD received !");
430      nxpncihal_ctrl.nci_info.nci_version = p_ntf[5];
431      int len = p_ntf[2] + 2; /*include 2 byte header*/
432      wFwVerRsp = (((uint32_t)p_ntf[len - 2]) << 16U) |
433                  (((uint32_t)p_ntf[len - 1]) << 8U) | p_ntf[len];
434      NXPLOG_NCIHAL_D("NxpNci> FW Version: %x.%x.%x", p_ntf[len - 2],
435                      p_ntf[len - 1], p_ntf[len]);
436    } else {
437#if (NFC_NXP_CHIP_TYPE == PN548C2)
438      if (nfcdep_detected &&
439          !(p_ntf[2] == 0x06 && p_ntf[3] == 0xA0 && p_ntf[4] == 0x00 &&
440            ((p_ntf[5] == 0xC9 && p_ntf[6] == 0x95 && p_ntf[7] == 0x00 &&
441              p_ntf[8] == 0x00) ||
442             (p_ntf[5] == 0x07 && p_ntf[6] == 0x39 && p_ntf[7] == 0xF2 &&
443              p_ntf[8] == 0x00)))) {
444        nfcdep_detected = 0x00;
445      }
446#endif
447      phNxpNciHal_emergency_recovery();
448      status = NFCSTATUS_FAILED;
449    } /* Parsing CORE_INIT_RSP*/
450  } else if (p_ntf[0] == NCI_MT_RSP &&
451             ((p_ntf[1] & NCI_OID_MASK) == NCI_MSG_CORE_INIT)) {
452    if (nxpncihal_ctrl.nci_info.nci_version == NCI_VERSION_2_0) {
453      NXPLOG_NCIHAL_D("CORE_INIT_RSP NCI2.0 received !");
454    } else {
455      NXPLOG_NCIHAL_D("CORE_INIT_RSP NCI1.0 received !");
456      int len = p_ntf[2] + 2; /*include 2 byte header*/
457      wFwVerRsp = (((uint32_t)p_ntf[len - 2]) << 16U) |
458                  (((uint32_t)p_ntf[len - 1]) << 8U) | p_ntf[len];
459      if (wFwVerRsp == 0) status = NFCSTATUS_FAILED;
460      iCoreInitRspLen = *p_len;
461      memcpy(bCoreInitRsp, p_ntf, *p_len);
462      NXPLOG_NCIHAL_D("NxpNci> FW Version: %x.%x.%x", p_ntf[len - 2],
463                      p_ntf[len - 1], p_ntf[len]);
464      fw_maj_ver = p_ntf[len - 1];
465      rom_version = p_ntf[len - 2];
466    }
467  }
468  return status;
469}
470
471/******************************************************************************
472 * Function         phNxpNciHal_process_ext_cmd_rsp
473 *
474 * Description      This function process the extension command response. It
475 *                  also checks the received response to expected response.
476 *
477 * Returns          returns NFCSTATUS_SUCCESS if response is as expected else
478 *                  returns failure.
479 *
480 ******************************************************************************/
481static NFCSTATUS phNxpNciHal_process_ext_cmd_rsp(uint16_t cmd_len,
482                                                 uint8_t* p_cmd) {
483  NFCSTATUS status = NFCSTATUS_FAILED;
484  uint16_t data_written = 0;
485
486  /* Create the local semaphore */
487  if (phNxpNciHal_init_cb_data(&nxpncihal_ctrl.ext_cb_data, NULL) !=
488      NFCSTATUS_SUCCESS) {
489    NXPLOG_NCIHAL_D("Create ext_cb_data failed");
490    return NFCSTATUS_FAILED;
491  }
492
493  nxpncihal_ctrl.ext_cb_data.status = NFCSTATUS_SUCCESS;
494
495  /* Send ext command */
496  data_written = phNxpNciHal_write_unlocked(cmd_len, p_cmd);
497  if (data_written != cmd_len) {
498    NXPLOG_NCIHAL_D("phNxpNciHal_write failed for hal ext");
499    goto clean_and_return;
500  }
501
502  /* Start timer */
503  status = phOsalNfc_Timer_Start(timeoutTimerId, HAL_EXTNS_WRITE_RSP_TIMEOUT,
504                                 &hal_extns_write_rsp_timeout_cb, NULL);
505  if (NFCSTATUS_SUCCESS == status) {
506    NXPLOG_NCIHAL_D("Response timer started");
507  } else {
508    NXPLOG_NCIHAL_E("Response timer not started!!!");
509    status = NFCSTATUS_FAILED;
510    goto clean_and_return;
511  }
512
513  /* Wait for rsp */
514  NXPLOG_NCIHAL_D("Waiting after ext cmd sent");
515  if (SEM_WAIT(nxpncihal_ctrl.ext_cb_data)) {
516    NXPLOG_NCIHAL_E("p_hal_ext->ext_cb_data.sem semaphore error");
517    goto clean_and_return;
518  }
519
520  /* Stop Timer */
521  status = phOsalNfc_Timer_Stop(timeoutTimerId);
522  if (NFCSTATUS_SUCCESS == status) {
523    NXPLOG_NCIHAL_D("Response timer stopped");
524  } else {
525    NXPLOG_NCIHAL_E("Response timer stop ERROR!!!");
526    status = NFCSTATUS_FAILED;
527    goto clean_and_return;
528  }
529  /* Start timer to wait for NTF*/
530  if (nxpncihal_ctrl.nci_info.wait_for_ntf == TRUE) {
531    status = phOsalNfc_Timer_Start(timeoutTimerId, HAL_EXTNS_WRITE_RSP_TIMEOUT,
532                                   &hal_extns_write_rsp_timeout_cb, NULL);
533    if (NFCSTATUS_SUCCESS == status) {
534      NXPLOG_NCIHAL_D("Response timer started");
535    } else {
536      NXPLOG_NCIHAL_E("Response timer not started!!!");
537      status = NFCSTATUS_FAILED;
538      goto clean_and_return;
539    }
540    if (SEM_WAIT(nxpncihal_ctrl.ext_cb_data)) {
541      NXPLOG_NCIHAL_E("p_hal_ext->ext_cb_data.sem semaphore error");
542      /* Stop Timer */
543      status = phOsalNfc_Timer_Stop(timeoutTimerId);
544      goto clean_and_return;
545    }
546    status = phOsalNfc_Timer_Stop(timeoutTimerId);
547    if (NFCSTATUS_SUCCESS == status) {
548      NXPLOG_NCIHAL_D("Response timer stopped");
549    } else {
550      NXPLOG_NCIHAL_E("Response timer stop ERROR!!!");
551      status = NFCSTATUS_FAILED;
552      goto clean_and_return;
553    }
554  }
555
556  if (nxpncihal_ctrl.ext_cb_data.status != NFCSTATUS_SUCCESS) {
557    NXPLOG_NCIHAL_E(
558        "Callback Status is failed!! Timer Expired!! Couldn't read it! 0x%x",
559        nxpncihal_ctrl.ext_cb_data.status);
560    status = NFCSTATUS_FAILED;
561    goto clean_and_return;
562  }
563
564  NXPLOG_NCIHAL_D("Checking response");
565  status = NFCSTATUS_SUCCESS;
566
567clean_and_return:
568  phNxpNciHal_cleanup_cb_data(&nxpncihal_ctrl.ext_cb_data);
569  nxpncihal_ctrl.nci_info.wait_for_ntf = FALSE;
570  return status;
571}
572
573/******************************************************************************
574 * Function         phNxpNciHal_write_ext
575 *
576 * Description      This function inform the status of phNxpNciHal_open
577 *                  function to libnfc-nci.
578 *
579 * Returns          It return NFCSTATUS_SUCCESS then continue with send else
580 *                  sends NFCSTATUS_FAILED direct response is prepared and
581 *                  do not send anything to NFCC.
582 *
583 ******************************************************************************/
584
585NFCSTATUS phNxpNciHal_write_ext(uint16_t* cmd_len, uint8_t* p_cmd_data,
586                                uint16_t* rsp_len, uint8_t* p_rsp_data) {
587  NFCSTATUS status = NFCSTATUS_SUCCESS;
588
589  unsigned long retval = 0;
590  int isfound =
591      GetNxpNumValue(NAME_MIFARE_READER_ENABLE, &retval, sizeof(unsigned long));
592
593  phNxpNciHal_NfcDep_cmd_ext(p_cmd_data, cmd_len);
594
595  if (phNxpDta_IsEnable() == true) {
596    status = phNxpNHal_DtaUpdate(cmd_len, p_cmd_data, rsp_len, p_rsp_data);
597  }
598
599  if (p_cmd_data[0] == PROPRIETARY_CMD_FELICA_READER_MODE &&
600      p_cmd_data[1] == PROPRIETARY_CMD_FELICA_READER_MODE &&
601      p_cmd_data[2] == PROPRIETARY_CMD_FELICA_READER_MODE) {
602    NXPLOG_NCIHAL_D("Received proprietary command to set Felica Reader mode:%d",
603                    p_cmd_data[3]);
604    gFelicaReaderMode = p_cmd_data[3];
605    /* frame the dummy response */
606    *rsp_len = 4;
607    p_rsp_data[0] = 0x00;
608    p_rsp_data[1] = 0x00;
609    p_rsp_data[2] = 0x00;
610    p_rsp_data[3] = 0x00;
611    status = NFCSTATUS_FAILED;
612  } else if (p_cmd_data[0] == 0x20 && p_cmd_data[1] == 0x02 &&
613             p_cmd_data[2] == 0x05 && p_cmd_data[3] == 0x01 &&
614             p_cmd_data[4] == 0xA0 && p_cmd_data[5] == 0x44 &&
615             p_cmd_data[6] == 0x01 && p_cmd_data[7] == 0x01) {
616    nxpprofile_ctrl.profile_type = EMV_CO_PROFILE;
617    NXPLOG_NCIHAL_D("EMV_CO_PROFILE mode - Enabled");
618    status = NFCSTATUS_SUCCESS;
619  } else if (p_cmd_data[0] == 0x20 && p_cmd_data[1] == 0x02 &&
620             p_cmd_data[2] == 0x05 && p_cmd_data[3] == 0x01 &&
621             p_cmd_data[4] == 0xA0 && p_cmd_data[5] == 0x44 &&
622             p_cmd_data[6] == 0x01 && p_cmd_data[7] == 0x00) {
623    NXPLOG_NCIHAL_D("NFC_FORUM_PROFILE mode - Enabled");
624    nxpprofile_ctrl.profile_type = NFC_FORUM_PROFILE;
625    status = NFCSTATUS_SUCCESS;
626  }
627
628  if (nxpprofile_ctrl.profile_type == EMV_CO_PROFILE) {
629    if (p_cmd_data[0] == 0x21 && p_cmd_data[1] == 0x06 &&
630        p_cmd_data[2] == 0x01 && p_cmd_data[3] == 0x03) {
631#if 0
632            //Needs clarification whether to keep it or not
633            NXPLOG_NCIHAL_D ("EmvCo Poll mode - RF Deactivate discard");
634            phNxpNciHal_print_packet("SEND", p_cmd_data, *cmd_len);
635            *rsp_len = 4;
636            p_rsp_data[0] = 0x41;
637            p_rsp_data[1] = 0x06;
638            p_rsp_data[2] = 0x01;
639            p_rsp_data[3] = 0x00;
640            phNxpNciHal_print_packet("RECV", p_rsp_data, 4);
641            status = NFCSTATUS_FAILED;
642#endif
643    } else if (p_cmd_data[0] == 0x21 && p_cmd_data[1] == 0x03) {
644      NXPLOG_NCIHAL_D("EmvCo Poll mode - Discover map only for A and B");
645      p_cmd_data[2] = 0x05;
646      p_cmd_data[3] = 0x02;
647      p_cmd_data[4] = 0x00;
648      p_cmd_data[5] = 0x01;
649      p_cmd_data[6] = 0x01;
650      p_cmd_data[7] = 0x01;
651      *cmd_len = 8;
652    }
653  }
654
655  if (retval == 0x01 && p_cmd_data[0] == 0x21 && p_cmd_data[1] == 0x00) {
656    NXPLOG_NCIHAL_D("Going through extns - Adding Mifare in RF Discovery");
657    p_cmd_data[2] += 3;
658    p_cmd_data[3] += 1;
659    p_cmd_data[*cmd_len] = 0x80;
660    p_cmd_data[*cmd_len + 1] = 0x01;
661    p_cmd_data[*cmd_len + 2] = 0x80;
662    *cmd_len += 3;
663    status = NFCSTATUS_SUCCESS;
664    NXPLOG_NCIHAL_D(
665        "Going through extns - Adding Mifare in RF Discovery - END");
666  } else if (p_cmd_data[3] == 0x81 && p_cmd_data[4] == 0x01 &&
667             p_cmd_data[5] == 0x03) {
668    NXPLOG_NCIHAL_D("> Going through workaround - set host list");
669
670#if (NFC_NXP_CHIP_TYPE != PN547C2)
671    *cmd_len = 8;
672
673    p_cmd_data[2] = 0x05;
674    p_cmd_data[6] = 0x02;
675    p_cmd_data[7] = 0xC0;
676#else
677    *cmd_len = 7;
678
679    p_cmd_data[2] = 0x04;
680    p_cmd_data[6] = 0xC0;
681#endif
682
683    NXPLOG_NCIHAL_D("> Going through workaround - set host list - END");
684    status = NFCSTATUS_SUCCESS;
685  } else if (icode_detected) {
686    if ((p_cmd_data[3] & 0x40) == 0x40 &&
687        (p_cmd_data[4] == 0x21 || p_cmd_data[4] == 0x22 ||
688         p_cmd_data[4] == 0x24 || p_cmd_data[4] == 0x27 ||
689         p_cmd_data[4] == 0x28 || p_cmd_data[4] == 0x29 ||
690         p_cmd_data[4] == 0x2a)) {
691      NXPLOG_NCIHAL_D("> Send EOF set");
692      icode_send_eof = 1;
693    }
694
695    if (p_cmd_data[3] == 0x20 || p_cmd_data[3] == 0x24 ||
696        p_cmd_data[3] == 0x60) {
697      NXPLOG_NCIHAL_D("> NFC ISO_15693 Proprietary CMD ");
698      p_cmd_data[3] += 0x02;
699    }
700  } else if (p_cmd_data[0] == 0x21 && p_cmd_data[1] == 0x03) {
701    NXPLOG_NCIHAL_D("> Polling Loop Started");
702    icode_detected = 0;
703    icode_send_eof = 0;
704#if (NFC_NXP_CHIP_TYPE == PN548C2)
705    // Cache discovery cmd for recovery
706    phNxpNciHal_discovery_cmd_ext(p_cmd_data, *cmd_len);
707#endif
708  }
709  // 22000100
710  else if (p_cmd_data[0] == 0x22 && p_cmd_data[1] == 0x00 &&
711           p_cmd_data[2] == 0x01 && p_cmd_data[3] == 0x00) {
712    // ee_disc_done = 0x01;//Reader Over SWP event getting
713    *rsp_len = 0x05;
714    p_rsp_data[0] = 0x42;
715    p_rsp_data[1] = 0x00;
716    p_rsp_data[2] = 0x02;
717    p_rsp_data[3] = 0x00;
718    p_rsp_data[4] = 0x00;
719    phNxpNciHal_print_packet("RECV", p_rsp_data, 5);
720    status = NFCSTATUS_FAILED;
721  }
722  // 2002 0904 3000 3100 3200 5000
723  else if ((p_cmd_data[0] == 0x20 && p_cmd_data[1] == 0x02) &&
724           ((p_cmd_data[2] == 0x09 && p_cmd_data[3] == 0x04) /*||
725            (p_cmd_data[2] == 0x0D && p_cmd_data[3] == 0x04)*/
726            )) {
727    *cmd_len += 0x01;
728    p_cmd_data[2] += 0x01;
729    p_cmd_data[9] = 0x01;
730    p_cmd_data[10] = 0x40;
731    p_cmd_data[11] = 0x50;
732    p_cmd_data[12] = 0x00;
733
734    NXPLOG_NCIHAL_D("> Going through workaround - Dirty Set Config ");
735    //        phNxpNciHal_print_packet("SEND", p_cmd_data, *cmd_len);
736    NXPLOG_NCIHAL_D("> Going through workaround - Dirty Set Config - End ");
737  }
738  //    20020703300031003200
739  //    2002 0301 3200
740  else if ((p_cmd_data[0] == 0x20 && p_cmd_data[1] == 0x02) &&
741           ((p_cmd_data[2] == 0x07 && p_cmd_data[3] == 0x03) ||
742            (p_cmd_data[2] == 0x03 && p_cmd_data[3] == 0x01 &&
743             p_cmd_data[4] == 0x32))) {
744    NXPLOG_NCIHAL_D("> Going through workaround - Dirty Set Config ");
745    phNxpNciHal_print_packet("SEND", p_cmd_data, *cmd_len);
746    *rsp_len = 5;
747    p_rsp_data[0] = 0x40;
748    p_rsp_data[1] = 0x02;
749    p_rsp_data[2] = 0x02;
750    p_rsp_data[3] = 0x00;
751    p_rsp_data[4] = 0x00;
752
753    phNxpNciHal_print_packet("RECV", p_rsp_data, 5);
754    status = NFCSTATUS_FAILED;
755    NXPLOG_NCIHAL_D("> Going through workaround - Dirty Set Config - End ");
756  }
757
758  // 2002 0D04 300104 310100 320100 500100
759  // 2002 0401 320100
760  else if ((p_cmd_data[0] == 0x20 && p_cmd_data[1] == 0x02) &&
761           (
762               /*(p_cmd_data[2] == 0x0D && p_cmd_data[3] == 0x04)*/
763               (p_cmd_data[2] == 0x04 && p_cmd_data[3] == 0x01 &&
764                p_cmd_data[4] == 0x32 && p_cmd_data[5] == 0x00))) {
765    //        p_cmd_data[12] = 0x40;
766
767    NXPLOG_NCIHAL_D("> Going through workaround - Dirty Set Config ");
768    phNxpNciHal_print_packet("SEND", p_cmd_data, *cmd_len);
769    p_cmd_data[6] = 0x60;
770
771    phNxpNciHal_print_packet("RECV", p_rsp_data, 5);
772    //        status = NFCSTATUS_FAILED;
773    NXPLOG_NCIHAL_D("> Going through workaround - Dirty Set Config - End ");
774  } else if (p_cmd_data[0] == 0x21 && p_cmd_data[1] == 0x00) {
775    NXPLOG_NCIHAL_D(
776        "> Going through workaround - Add Mifare Classic in Discovery Map");
777    p_cmd_data[*cmd_len] = 0x80;
778    p_cmd_data[*cmd_len + 1] = 0x01;
779    p_cmd_data[*cmd_len + 2] = 0x80;
780    p_cmd_data[5] = 0x01;
781    p_cmd_data[6] = 0x01;
782    p_cmd_data[2] += 3;
783    p_cmd_data[3] += 1;
784    *cmd_len += 3;
785  } else if (*cmd_len == 3 && p_cmd_data[0] == 0x00 && p_cmd_data[1] == 0x00 &&
786             p_cmd_data[2] == 0x00) {
787    NXPLOG_NCIHAL_D("> Going through workaround - ISO-DEP Presence Check ");
788    p_cmd_data[0] = 0x2F;
789    p_cmd_data[1] = 0x11;
790    p_cmd_data[2] = 0x00;
791    status = NFCSTATUS_SUCCESS;
792    NXPLOG_NCIHAL_D(
793        "> Going through workaround - ISO-DEP Presence Check - End");
794  }
795#if 0
796    else if ( (p_cmd_data[0] == 0x20 && p_cmd_data[1] == 0x02 ) &&
797                 ((p_cmd_data[2] == 0x09 && p_cmd_data[3] == 0x04) ||
798                     (p_cmd_data[2] == 0x0B && p_cmd_data[3] == 0x05) ||
799                     (p_cmd_data[2] == 0x07 && p_cmd_data[3] == 0x02) ||
800                     (p_cmd_data[2] == 0x0A && p_cmd_data[3] == 0x03) ||
801                     (p_cmd_data[2] == 0x0A && p_cmd_data[3] == 0x04) ||
802                     (p_cmd_data[2] == 0x05 && p_cmd_data[3] == 0x02))
803             )
804    {
805        NXPLOG_NCIHAL_D ("> Going through workaround - Dirty Set Config ");
806        phNxpNciHal_print_packet("SEND", p_cmd_data, *cmd_len);
807        *rsp_len = 5;
808        p_rsp_data[0] = 0x40;
809        p_rsp_data[1] = 0x02;
810        p_rsp_data[2] = 0x02;
811        p_rsp_data[3] = 0x00;
812        p_rsp_data[4] = 0x00;
813
814        phNxpNciHal_print_packet("RECV", p_rsp_data, 5);
815        status = NFCSTATUS_FAILED;
816        NXPLOG_NCIHAL_D ("> Going through workaround - Dirty Set Config - End ");
817    }
818
819    else if((p_cmd_data[0] == 0x20 && p_cmd_data[1] == 0x02) &&
820           ((p_cmd_data[3] == 0x00) ||
821           ((*cmd_len >= 0x06) && (p_cmd_data[5] == 0x00)))) /*If the length of the first param id is zero don't allow*/
822    {
823        NXPLOG_NCIHAL_D ("> Going through workaround - Dirty Set Config ");
824        phNxpNciHal_print_packet("SEND", p_cmd_data, *cmd_len);
825        *rsp_len = 5;
826        p_rsp_data[0] = 0x40;
827        p_rsp_data[1] = 0x02;
828        p_rsp_data[2] = 0x02;
829        p_rsp_data[3] = 0x00;
830        p_rsp_data[4] = 0x00;
831
832        phNxpNciHal_print_packet("RECV", p_rsp_data, 5);
833        status = NFCSTATUS_FAILED;
834        NXPLOG_NCIHAL_D ("> Going through workaround - Dirty Set Config - End ");
835    }
836#endif
837  else if ((wFwVerRsp & 0x0000FFFF) == wFwVer) {
838    /* skip CORE_RESET and CORE_INIT from Brcm */
839    if (p_cmd_data[0] == 0x20 && p_cmd_data[1] == 0x00 &&
840        p_cmd_data[2] == 0x01 && p_cmd_data[3] == 0x01) {
841      //            *rsp_len = 6;
842      //
843      //            NXPLOG_NCIHAL_D("> Going - core reset optimization");
844      //
845      //            p_rsp_data[0] = 0x40;
846      //            p_rsp_data[1] = 0x00;
847      //            p_rsp_data[2] = 0x03;
848      //            p_rsp_data[3] = 0x00;
849      //            p_rsp_data[4] = 0x10;
850      //            p_rsp_data[5] = 0x01;
851      //
852      //            status = NFCSTATUS_FAILED;
853      //            NXPLOG_NCIHAL_D("> Going - core reset optimization - END");
854    }
855    /* CORE_INIT */
856    else if (p_cmd_data[0] == 0x20 && p_cmd_data[1] == 0x01 &&
857             p_cmd_data[2] == 0x00) {
858      //            NXPLOG_NCIHAL_D("> Going - core init optimization");
859      //            *rsp_len = iCoreInitRspLen;
860      //            memcpy(p_rsp_data, bCoreInitRsp, iCoreInitRspLen);
861      //            status = NFCSTATUS_FAILED;
862      //            NXPLOG_NCIHAL_D("> Going - core init optimization - END");
863    }
864  }
865
866#if (NFC_NXP_CHIP_TYPE == PN548C2)
867  if (p_cmd_data[0] == 0x20 && p_cmd_data[1] == 0x02) {
868    uint8_t temp;
869    uint8_t* p = p_cmd_data + 4;
870    uint8_t* end = p_cmd_data + *cmd_len;
871    while (p < end) {
872      if (*p == 0x53)  // LF_T3T_FLAGS
873      {
874        NXPLOG_NCIHAL_D("> Going through workaround - LF_T3T_FLAGS swap");
875        temp = *(p + 3);
876        *(p + 3) = *(p + 2);
877        *(p + 2) = temp;
878        NXPLOG_NCIHAL_D("> Going through workaround - LF_T3T_FLAGS - End");
879        status = NFCSTATUS_SUCCESS;
880        break;
881      }
882      if (*p == 0xA0) {
883        p += *(p + 2) + 3;
884      } else {
885        p += *(p + 1) + 2;
886      }
887    }
888  }
889#endif
890
891  return status;
892}
893
894/******************************************************************************
895 * Function         phNxpNciHal_send_ext_cmd
896 *
897 * Description      This function send the extension command to NFCC. No
898 *                  response is checked by this function but it waits for
899 *                  the response to come.
900 *
901 * Returns          Returns NFCSTATUS_SUCCESS if sending cmd is successful and
902 *                  response is received.
903 *
904 ******************************************************************************/
905NFCSTATUS phNxpNciHal_send_ext_cmd(uint16_t cmd_len, uint8_t* p_cmd) {
906  NFCSTATUS status = NFCSTATUS_FAILED;
907
908  HAL_ENABLE_EXT();
909  nxpncihal_ctrl.cmd_len = cmd_len;
910  memcpy(nxpncihal_ctrl.p_cmd_data, p_cmd, cmd_len);
911  status = phNxpNciHal_process_ext_cmd_rsp(nxpncihal_ctrl.cmd_len,
912                                           nxpncihal_ctrl.p_cmd_data);
913  HAL_DISABLE_EXT();
914
915  return status;
916}
917
918/******************************************************************************
919 * Function         hal_extns_write_rsp_timeout_cb
920 *
921 * Description      Timer call back function
922 *
923 * Returns          None
924 *
925 ******************************************************************************/
926static void hal_extns_write_rsp_timeout_cb(uint32_t timerId, void* pContext) {
927  UNUSED(timerId);
928  UNUSED(pContext);
929  NXPLOG_NCIHAL_E("hal_extns_write_rsp_timeout_cb - write timeout!!!");
930  nxpncihal_ctrl.ext_cb_data.status = NFCSTATUS_FAILED;
931  usleep(1);
932  SEM_POST(&(nxpncihal_ctrl.ext_cb_data));
933
934  return;
935}
936