1 /*
2  * Copyright 2021-2023 NXP
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 
17 #if (NXP_NFC_RECOVERY == TRUE)
18 
19 #include "phNxpNciHal_Recovery.h"
20 
21 #include <phDnldNfc.h>
22 #include <phNfcStatus.h>
23 #include <phNfcTypes.h>
24 #include <phNxpLog.h>
25 #include <phNxpNciHal.h>
26 #include <phNxpNciHal_Dnld.h>
27 #include <phNxpNciHal_ext.h>
28 #include <phOsalNfc_Timer.h>
29 #include <phTmlNfc.h>
30 #undef property_set
31 #undef PROPERTY_VALUE_MAX
32 #undef property_get
33 #include <cutils/properties.h>
34 #define MAX_CORE_RESET 3
35 
36 extern phNxpNciProfile_Control_t nxpprofile_ctrl;
37 extern phNxpNciHal_Control_t nxpncihal_ctrl;
38 extern phTmlNfc_Context_t* gpphTmlNfc_Context;
39 extern void* phNxpNciHal_client_thread(void* arg);
40 
41 static void phnxpNciHal_partialClose();
42 static NFCSTATUS phnxpNciHal_partialOpen();
43 
44 // property name for storing boot time init status
45 const char* halInitProperty = "vendor.nfc.min_firmware";
46 
47 /******************************************************************************
48  * Function         getHalInitStatus
49  *
50  * Description      Get property whether it is boot init/not
51  *
52  * Parameters       Parameter to return the hal status is boot init/not.
53  *
54  * Returns          None
55  *
56  ******************************************************************************/
getHalInitStatus(char * halInitStatus)57 static void getHalInitStatus(char* halInitStatus) {
58   NXPLOG_NCIHAL_D("Enter : %s", __func__);
59   if (property_get(halInitProperty, halInitStatus, "Boot-time") != 0) {
60     NXPLOG_NCIHAL_E("Error in property_get : %s", __func__);
61   }
62 }
63 
64 /******************************************************************************
65  * Function         setHalInitStatus
66  *
67  * Description      To set property as per input whether it is boot init/not
68  *
69  * Parameters       status to be updated in property
70  *
71  * Returns          void
72  *
73  ******************************************************************************/
setHalInitStatus(const char * status)74 static void setHalInitStatus(const char* status) {
75   NXPLOG_NCIHAL_E("Enter : %s", __func__);
76   if (property_set(halInitProperty, status) != 0) {
77     NXPLOG_NCIHAL_E("Error in property_set : %s", __func__);
78   }
79 }
80 
81 /******************************************************************************
82  * Function         phNxpNciHal_read_callback
83  *
84  * Description      Callback function for read request to tml reader thread
85  *
86  * Parameters       pContext - context value passed while callback register
87  *                  pInfo    - Information which contains status and response
88  *                             buffers.
89  *
90  * Returns          void
91  *
92  ******************************************************************************/
phNxpNciHal_read_callback(void * pContext,phTmlNfc_TransactInfo_t * pInfo)93 static void phNxpNciHal_read_callback(void* pContext,
94                                       phTmlNfc_TransactInfo_t* pInfo) {
95   UNUSED_PROP(pContext);
96   if (pInfo != NULL) {
97     NXPLOG_NCIHAL_E("%s Status %d", __func__, pInfo->wStatus);
98     if (pInfo->wStatus == NFCSTATUS_SUCCESS) {
99       nxpncihal_ctrl.p_rx_data = pInfo->pBuff;
100       nxpncihal_ctrl.rx_data_len = pInfo->wLength;
101     }
102     nxpncihal_ctrl.ext_cb_data.status = pInfo->wStatus;
103   } else {
104     nxpncihal_ctrl.ext_cb_data.status = NFCSTATUS_FAILED;
105   }
106   SEM_POST(&(nxpncihal_ctrl.ext_cb_data));
107 }
108 
109 /******************************************************************************
110  * Function         phNxpNciHal_write_callback
111  *
112  * Description      Callback function for write request to tml writer thread
113  *
114  * Parameters       pContext - context value passed while callback register
115  *                  pInfo    - Information which contains status and response
116  *                             buffers.
117  *
118  * Returns          void
119  *
120  ******************************************************************************/
phNxpNciHal_write_callback(void * pContext,phTmlNfc_TransactInfo_t * pInfo)121 static void phNxpNciHal_write_callback(void* pContext,
122                                        phTmlNfc_TransactInfo_t* pInfo) {
123   UNUSED_PROP(pContext);
124   if (pInfo != NULL) {
125     if (pInfo->wStatus != NFCSTATUS_SUCCESS) {
126       NXPLOG_NCIHAL_E("write error status = 0x%x", pInfo->wStatus);
127     }
128     nxpncihal_ctrl.ext_cb_data.status = pInfo->wStatus;
129   } else {
130     nxpncihal_ctrl.ext_cb_data.status = NFCSTATUS_FAILED;
131   }
132   SEM_POST(&(nxpncihal_ctrl.ext_cb_data));
133 }
134 
135 /******************************************************************************
136  * Function         phNxpNciHal_semWaitTimeout
137  *
138  * Description      Helper function for global sem wait with timeout value
139  *
140  * Parameters       timeout - wait timeout in nanoseconds
141  *
142  * Returns          NFCSTATUS
143  *
144  ******************************************************************************/
phNxpNciHal_semWaitTimeout(long timeout)145 static NFCSTATUS phNxpNciHal_semWaitTimeout(long timeout) {
146   NFCSTATUS status = NFCSTATUS_FAILED;
147   int retVal = 0;
148   struct timespec ts;
149   clock_gettime(CLOCK_MONOTONIC, &ts);
150   ts.tv_nsec += timeout;
151   ts.tv_sec += ts.tv_nsec / 1000000000;
152   ts.tv_nsec %= 1000000000;
153   while ((retVal = sem_timedwait_monotonic_np(&nxpncihal_ctrl.ext_cb_data.sem, &ts)) == -1 &&
154          errno == EINTR) {
155     continue; /* Restart if interrupted by handler */
156   }
157   if (retVal == -1 && errno != ETIMEDOUT) {
158     NXPLOG_NCIHAL_E("%s : sem_timedwait failed : errno = 0x%x", __func__,
159                     errno);
160   }
161   if (retVal != -1) {
162     status = nxpncihal_ctrl.ext_cb_data.status;
163   } else if (errno == ETIMEDOUT && retVal == -1) {
164     NXPLOG_NCIHAL_E("%s :timed out errno = 0x%x", __func__, errno);
165   }
166   return status;
167 }
168 
169 /******************************************************************************
170  * Function         phNxpNciHal_writeCmd
171  *
172  * Description      Helper function to write command to NFCC
173  *
174  * Parameters       timeout - wait timeout in nanoseconds
175  *
176  * Returns          NFCSTATUS
177  *
178  ******************************************************************************/
phNxpNciHal_writeCmd(uint16_t data_len,const uint8_t * p_data,long timeout)179 static NFCSTATUS phNxpNciHal_writeCmd(uint16_t data_len, const uint8_t* p_data,
180                                       long timeout) {
181   NFCSTATUS status = NFCSTATUS_FAILED;
182   const char context[] = "RecoveryWrite";
183 
184   if (p_data == NULL) {
185     NXPLOG_NCIHAL_E("Invalid Command Buffer");
186     return NFCSTATUS_INVALID_PARAMETER;
187   }
188   /* Create local copy of cmd_data */
189   memcpy(nxpncihal_ctrl.p_cmd_data, p_data, data_len);
190   nxpncihal_ctrl.cmd_len = data_len;
191   status = phTmlNfc_Write(
192       (uint8_t*)nxpncihal_ctrl.p_cmd_data, (uint16_t)nxpncihal_ctrl.cmd_len,
193       (pphTmlNfc_TransactCompletionCb_t)&phNxpNciHal_write_callback,
194       (void*)context);
195   if (status == NFCSTATUS_PENDING) {
196     return phNxpNciHal_semWaitTimeout(timeout);
197   }
198   NXPLOG_NCIHAL_E("tml write request failed");
199   return status;
200 }
201 
202 /******************************************************************************
203  * Function         phNxpNciHal_ReadResponse
204  *
205  * Description      Helper function to read response from NFCC
206  *
207  * Parameters       len - response buffer len
208  *                  rsp_buffer - Ptr to the response buffer
209  *                  timeout - wait timeout in nanoseconds
210  *
211  * Returns          NFCSTATUS
212  *
213  ******************************************************************************/
phNxpNciHal_ReadResponse(uint16_t * len,uint8_t ** rsp_buffer,long timeout)214 static NFCSTATUS phNxpNciHal_ReadResponse(uint16_t* len, uint8_t** rsp_buffer,
215                                           long timeout) {
216   NFCSTATUS status = NFCSTATUS_FAILED;
217   const char context[] = "RecoveryRead";
218 
219   if (len == NULL) {
220     NXPLOG_NCIHAL_E("%s Invalid Parameters", __func__);
221     return NFCSTATUS_INVALID_PARAMETER;
222   }
223   status = phTmlNfc_Read(
224       nxpncihal_ctrl.p_rsp_data, NCI_MAX_DATA_LEN,
225       (pphTmlNfc_TransactCompletionCb_t)&phNxpNciHal_read_callback,
226       (void*)context);
227   if (phNxpNciHal_semWaitTimeout(timeout) == NFCSTATUS_SUCCESS) {
228     if (nxpncihal_ctrl.p_rx_data != NULL && nxpncihal_ctrl.rx_data_len > 0) {
229       *rsp_buffer = nxpncihal_ctrl.p_rx_data;
230       *len = nxpncihal_ctrl.rx_data_len;
231       status = NFCSTATUS_SUCCESS;
232     } else
233       status = NFCSTATUS_FAILED;
234   }
235   return status;
236 }
237 
238 /******************************************************************************
239  * Function         phNxpNciHal_readNFCCClockCfgValues
240  *
241  * Description      Helper function to read clock configuration from
242  *                  nfcc configuration file and stores value in global strcture
243  *
244  * Returns          void
245  *
246  ******************************************************************************/
phNxpNciHal_readNFCCClockCfgValues(void)247 static void phNxpNciHal_readNFCCClockCfgValues(void) {
248   unsigned long num = 0;
249   int isfound = 0;
250 
251   isfound = GetNxpNumValue(NAME_NXP_SYS_CLK_SRC_SEL, &num, sizeof(num));
252   if (isfound > 0) nxpprofile_ctrl.bClkSrcVal = num;
253   num = 0;
254   isfound = 0;
255   isfound = GetNxpNumValue(NAME_NXP_SYS_CLK_FREQ_SEL, &num, sizeof(num));
256   if (isfound > 0) nxpprofile_ctrl.bClkFreqVal = num;
257 }
258 
259 /******************************************************************************
260  * Function         phNxpNciHal_determineChipType
261  *
262  * Description      Helper function to determine the chip info in nci mode
263  *                  from NCI command and stores value in global strcture
264  *
265  * Returns          bool
266  *
267  ******************************************************************************/
phNxpNciHal_determineChipType(void)268 static bool phNxpNciHal_determineChipType(void) {
269   const uint8_t cmd_reset_nci[] = {0x20, 0x00, 0x01, 0x00};
270   uint8_t* rsp_buffer = NULL;
271   uint16_t rsp_len = 0;
272   uint8_t retry = 0;
273   bool status = false;
274 
275   do {
276     if ((phNxpNciHal_writeCmd(sizeof(cmd_reset_nci), cmd_reset_nci,
277                               WRITE_TIMEOUT_NS) != NFCSTATUS_SUCCESS)) {
278       NXPLOG_NCIHAL_E("NCI_CORE_RESET Write Failure ");
279       break;
280     }
281     // 10ms delay  for first core reset response to avoid nfcc standby
282     usleep(NCI_RESET_RESP_READ_DELAY_US);
283     if ((phNxpNciHal_ReadResponse(&rsp_len, &rsp_buffer,
284                                   RESPONSE_READ_TIMEOUT_NS) !=
285          NFCSTATUS_SUCCESS) ||
286         (rsp_buffer == NULL)) {
287       NXPLOG_NCIHAL_E("NCI_CORE_RESET read response failed");
288       break;
289     }
290     if (rsp_buffer[NCI_RSP_IDX] == NCI_MSG_RSP) {
291       if ((phNxpNciHal_ReadResponse(&rsp_len, &rsp_buffer,
292                                     RESPONSE_READ_TIMEOUT_NS) !=
293            NFCSTATUS_SUCCESS) ||
294           (rsp_buffer == NULL)) {
295         NXPLOG_NCIHAL_E("NCI_CORE_RESET NTF read failed");
296         break;
297       }
298       if (rsp_buffer[NCI_RSP_IDX] == NCI_MSG_NTF) {
299         phNxpNciHal_configFeatureList(rsp_buffer, rsp_len);
300         status = true;
301         break;
302       }
303     } else {
304       NXPLOG_NCIHAL_E("NCI_CORE_RESPONSE Wrong Status");
305     }
306   } while (retry++ < MAX_CORE_RESET);
307   return status;
308 }
309 
310 /******************************************************************************
311  * Function         phNxpNciHal_isSessionClosed
312  *
313  * Description      Helper function to determine download session state
314  *
315  * Returns          true means session closed
316  *
317  ******************************************************************************/
phNxpNciHal_isSessionClosed(void)318 bool phNxpNciHal_isSessionClosed(void) {
319   const uint8_t get_session_cmd[] = {0x00, 0x04, 0xF2, 0x00,
320                                      0x00, 0x00, 0xF5, 0x33};
321   uint8_t* rsp_buffer = NULL;
322   uint16_t rsp_len = 0;
323 
324   if ((phNxpNciHal_writeCmd(sizeof(get_session_cmd), get_session_cmd,
325                             WRITE_TIMEOUT_NS) == NFCSTATUS_SUCCESS)) {
326     if ((phNxpNciHal_ReadResponse(&rsp_len, &rsp_buffer,
327                                   RESPONSE_READ_TIMEOUT_NS) !=
328          NFCSTATUS_SUCCESS) ||
329         (rsp_buffer == NULL)) {
330       NXPLOG_NCIHAL_E("Get Session read response failed");
331     } else if (rsp_buffer[DL_RSP_STAT_IDX] == DL_MSG_STAT_RSP &&
332                rsp_buffer[DL_RSP_IDX] == DL_MSG_RSP) {
333       if (rsp_buffer[DL_RSP_SESS_IDX] == DL_SESSION_CLOSE_TAG) {
334         return true;
335       }
336     }
337   }
338   return false;
339 }
340 
341 /******************************************************************************
342  * Function         phNxpNciHal_determineChipTypeDlMode
343  *
344  * Description      Helper function to determine the chip info in download mode
345  *                  from get version command and stores value in global strcture
346  *
347  * Returns          bool
348  *
349  ******************************************************************************/
phNxpNciHal_determineChipTypeDlMode(void)350 static bool phNxpNciHal_determineChipTypeDlMode(void) {
351   const uint8_t get_version_cmd[] = {0x00, 0x04, 0xF1, 0x00,
352                                      0x00, 0x00, 0x6E, 0xEF};
353   uint8_t* rsp_buffer = NULL;
354   uint16_t rsp_len = 0;
355 
356   if ((phNxpNciHal_writeCmd(sizeof(get_version_cmd), get_version_cmd,
357                             WRITE_TIMEOUT_NS) == NFCSTATUS_SUCCESS)) {
358     if ((phNxpNciHal_ReadResponse(&rsp_len, &rsp_buffer,
359                                   RESPONSE_READ_TIMEOUT_NS) !=
360          NFCSTATUS_SUCCESS) ||
361         (rsp_buffer == NULL)) {
362       NXPLOG_NCIHAL_E("Get Version read response failed");
363     } else if (rsp_buffer[DL_RSP_STAT_IDX] == DL_MSG_STAT_RSP &&
364                rsp_buffer[DL_RSP_IDX] == DL_MSG_RSP) {
365       phNxpNciHal_configFeatureList(rsp_buffer, rsp_len);
366       return true;
367     }
368   }
369   return false;
370 }
371 
372 /******************************************************************************
373  * Function        phNxpNciHal_RecoverFWTearDown
374  *
375  * Description     Function to determine the NFCC state and recovery using
376  *                 minimal fw download.
377  *
378  * Parameters      None
379  *
380  * Returns         SUCCESS if recovery is successful else FAIL.
381  *
382  ******************************************************************************/
phNxpNciHal_RecoverFWTearDown(void)383 void phNxpNciHal_RecoverFWTearDown(void) {
384   uint8_t nfcc_recovery_support = 0x00;
385   // status post boot completed
386   const char* status = "Boot-completed";
387   char halInitStatus[PROPERTY_VALUE_MAX] = {0};
388 
389   NXPLOG_NCIHAL_D("phNxpNciHal_RecoverFWTearDown(): enter \n");
390   if (!GetNxpNumValue(NAME_NXP_NFCC_RECOVERY_SUPPORT, &nfcc_recovery_support,
391                       sizeof(nfcc_recovery_support))) {
392     NXPLOG_NCIHAL_E("Failed to read NXP_NFC_RECOVERY_SUPPORT config :");
393   }
394   if (nfcc_recovery_support == 0x00) {
395     NXPLOG_NCIHAL_D("NFCC Recovery not supported");
396     return;
397   }
398 
399   // If this is not boot time invocation return
400   getHalInitStatus(halInitStatus);
401   if (strncmp(halInitStatus, status, PROPERTY_VALUE_MAX) == 0) {
402     NXPLOG_NCIHAL_D("Not boot time, skip minimal FW download");
403     return;
404   } else {
405     NXPLOG_NCIHAL_D("boot time, check minimal FW download required");
406   }
407 
408   if (phnxpNciHal_partialOpen() != NFCSTATUS_SUCCESS) {
409     NXPLOG_NCIHAL_E("Failed to Initialize Partial HAL for NFCC recovery \n");
410     return;
411   }
412   if (phTmlNfc_IoCtl(phTmlNfc_e_PowerReset) != NFCSTATUS_SUCCESS) {
413     NXPLOG_NCIHAL_E("Failed to Perform VEN RESET \n");
414     phnxpNciHal_partialClose();
415     return;
416   }
417   if (phNxpNciHal_determineChipType()) {
418     NXPLOG_NCIHAL_D("Recovery not required \n");
419     phnxpNciHal_partialClose();
420     setHalInitStatus(status);
421     return;
422   }
423   if (phTmlNfc_IoCtl(phTmlNfc_e_EnableDownloadModeWithVenRst) !=
424       NFCSTATUS_SUCCESS) {
425     NXPLOG_NCIHAL_E("Enable Download mode failed");
426     phnxpNciHal_partialClose();
427     setHalInitStatus(status);
428     return;
429   }
430 
431   phTmlNfc_EnableFwDnldMode(true);
432   bool bEnableNormalMode = true;
433   if (!phNxpNciHal_determineChipTypeDlMode()) {
434     NXPLOG_NCIHAL_E("Not able to determine chiptype");
435   } else if (IS_CHIP_TYPE_NE(sn100u)) {
436     NXPLOG_NCIHAL_E("Recovery not supported for chiptype (%d)", nfcFL.chipType);
437   } else if (phNxpNciHal_isSessionClosed()) {
438     NXPLOG_NCIHAL_D("FW Dnld session is closed");
439   } else if (phNxpNciHal_fw_download_seq(nxpprofile_ctrl.bClkSrcVal,
440                                          nxpprofile_ctrl.bClkFreqVal, 0,
441                                          true) != NFCSTATUS_SUCCESS) {
442     NXPLOG_NCIHAL_E("Minimal FW Update failed \n");
443   } else {
444     /* In the success case, the phNxpNciHal_fw_download_seq() will enable normal
445      * mode */
446     bEnableNormalMode = false;
447   }
448   if (bEnableNormalMode) {
449     phTmlNfc_IoCtl(phTmlNfc_e_EnableNormalMode);
450   }
451   phTmlNfc_IoCtl(phTmlNfc_e_PowerReset);
452   phnxpNciHal_partialClose();
453   // Minimal FW not required in this boot session
454   setHalInitStatus(status);
455 }
456 
457 /*******************************************************************************
458  *
459  * Function         phnxpNciHal_partialOpenCleanUp
460  *
461  * Description      Helper function to cleanUp the Memory and flags from
462  *                  phnxpNciHal_partialOpen
463  *
464  * Parameters       nfc_dev_node - dev node to be freed
465  *
466  * Returns          NFCSTATUS
467  *******************************************************************************/
phnxpNciHal_partialOpenCleanUp(char * nfc_dev_node)468 static int phnxpNciHal_partialOpenCleanUp(char* nfc_dev_node) {
469   if (nfc_dev_node != NULL) {
470     free(nfc_dev_node);
471     nfc_dev_node = NULL;
472   }
473   /* Report error status */
474   phNxpNciHal_cleanup_monitor();
475   nxpncihal_ctrl.halStatus = HAL_STATUS_CLOSE;
476   return NFCSTATUS_FAILED;
477 }
478 
479 /*******************************************************************************
480  *
481  * Function         phnxpNciHal_partialOpen
482  *
483  * Description      Initialize the Minimal HAL
484  *
485  * Parameters       none
486  *
487  * Returns          NFCSTATUS
488  *******************************************************************************/
phnxpNciHal_partialOpen(void)489 static NFCSTATUS phnxpNciHal_partialOpen(void) {
490   phOsalNfc_Config_t tOsalConfig;
491   phTmlNfc_Config_t tTmlConfig;
492   char* nfc_dev_node = NULL;
493 
494   NXPLOG_NCIHAL_D("phnxpNciHal_partialOpen(): enter");
495   if (nxpncihal_ctrl.halStatus == HAL_STATUS_MIN_OPEN) {
496     NXPLOG_NCIHAL_D("phNxpNciHal: already open");
497     return NFCSTATUS_SUCCESS;
498   }
499   /* initialize trace level */
500   phNxpLog_InitializeLogLevel();
501   if (phNxpNciHal_init_monitor() == NULL) {
502     NXPLOG_NCIHAL_E("Init monitor failed");
503     return NFCSTATUS_FAILED;
504   }
505   /* Create the local semaphore */
506   if (phNxpNciHal_init_cb_data(&nxpncihal_ctrl.ext_cb_data, NULL) !=
507       NFCSTATUS_SUCCESS) {
508     NXPLOG_NCIHAL_D("Create ext_cb_data failed");
509     return NFCSTATUS_FAILED;
510   }
511   CONCURRENCY_LOCK();
512   memset(&tOsalConfig, 0x00, sizeof(tOsalConfig));
513   memset(&tTmlConfig, 0x00, sizeof(tTmlConfig));
514   memset(&nxpprofile_ctrl, 0, sizeof(phNxpNciProfile_Control_t));
515 
516   /* By default HAL status is HAL_STATUS_OPEN */
517   nxpncihal_ctrl.halStatus = HAL_STATUS_OPEN;
518 
519   /*nci version NCI_VERSION_2_0 version by default for SN100 chip type*/
520   nxpncihal_ctrl.nci_info.nci_version = NCI_VERSION_2_0;
521   /* Read the nfc device node name */
522   nfc_dev_node = (char*)malloc(NXP_MAX_CONFIG_STRING_LEN * sizeof(char));
523   if (nfc_dev_node == NULL) {
524     NXPLOG_NCIHAL_D("malloc of nfc_dev_node failed ");
525     CONCURRENCY_UNLOCK();
526     return phnxpNciHal_partialOpenCleanUp(nfc_dev_node);
527   } else if (!GetNxpStrValue(NAME_NXP_NFC_DEV_NODE, nfc_dev_node,
528                              NXP_MAX_CONFIG_STRING_LEN)) {
529     NXPLOG_NCIHAL_D(
530         "Invalid nfc device node name keeping the default device node "
531         "/dev/pn54x");
532     strlcpy(nfc_dev_node, "/dev/pn54x",
533             (NXP_MAX_CONFIG_STRING_LEN * sizeof(char)));
534   }
535   /* Configure hardware link */
536   nxpncihal_ctrl.gDrvCfg.nClientId = phDal4Nfc_msgget(0, 0600);
537   nxpncihal_ctrl.gDrvCfg.nLinkType = ENUM_LINK_TYPE_I2C; /* For PN54X */
538   tTmlConfig.pDevName = (int8_t*)nfc_dev_node;
539   tOsalConfig.dwCallbackThreadId = (uintptr_t)nxpncihal_ctrl.gDrvCfg.nClientId;
540   tOsalConfig.pLogFile = NULL;
541   tTmlConfig.dwGetMsgThreadId = (uintptr_t)nxpncihal_ctrl.gDrvCfg.nClientId;
542 
543   /* Initialize TML layer */
544   if (phTmlNfc_Init(&tTmlConfig) != NFCSTATUS_SUCCESS) {
545     NXPLOG_NCIHAL_E("phTmlNfc_Init Failed");
546     CONCURRENCY_UNLOCK();
547     return phnxpNciHal_partialOpenCleanUp(nfc_dev_node);
548   } else {
549     if (nfc_dev_node != NULL) {
550       free(nfc_dev_node);
551       nfc_dev_node = NULL;
552     }
553   }
554   /* Create the client thread */
555   if (pthread_create(&nxpncihal_ctrl.client_thread, NULL,
556                      phNxpNciHal_client_thread, &nxpncihal_ctrl) != 0) {
557     NXPLOG_NCIHAL_E("pthread_create failed");
558     if (phTmlNfc_Shutdown_CleanUp() != NFCSTATUS_SUCCESS) {
559       NXPLOG_NCIHAL_E("phTmlNfc_Shutdown_CleanUp: Failed");
560     }
561     CONCURRENCY_UNLOCK();
562     return phnxpNciHal_partialOpenCleanUp(nfc_dev_node);
563   }
564   phNxpNciHal_readNFCCClockCfgValues();
565   CONCURRENCY_UNLOCK();
566   return NFCSTATUS_SUCCESS;
567 }
568 
569 /*******************************************************************************
570  *
571  * Function         phnxpNciHal_partialClose
572  *
573  * Description      close the Minimal HAL
574  *
575  * Parameters       none
576  *
577  * Returns          void
578  *******************************************************************************/
phnxpNciHal_partialClose(void)579 static void phnxpNciHal_partialClose(void) {
580   phLibNfc_Message_t msg;
581   nxpncihal_ctrl.halStatus = HAL_STATUS_CLOSE;
582 
583   if (NULL != gpphTmlNfc_Context->pDevHandle) {
584     msg.eMsgType = NCI_HAL_CLOSE_CPLT_MSG;
585     msg.pMsgData = NULL;
586     msg.Size = 0;
587     phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &msg);
588     /* Abort any pending read and write */
589     phTmlNfc_ReadAbort();
590     phTmlNfc_WriteAbort();
591     phTmlNfc_Shutdown();
592     if (0 != pthread_join(nxpncihal_ctrl.client_thread, (void**)NULL)) {
593       NXPLOG_TML_E("Fail to kill client thread!");
594     }
595     phTmlNfc_CleanUp();
596     phDal4Nfc_msgrelease(nxpncihal_ctrl.gDrvCfg.nClientId);
597     phNxpNciHal_cleanup_cb_data(&nxpncihal_ctrl.ext_cb_data);
598     memset(&nxpncihal_ctrl, 0x00, sizeof(nxpncihal_ctrl));
599     NXPLOG_NCIHAL_D("phnxpNciHal_partialClose - phOsalNfc_DeInit completed");
600   }
601   CONCURRENCY_UNLOCK();
602   phNxpNciHal_cleanup_monitor();
603 }
604 
605 #endif
606