1 /*
2  * Copyright 2019-2024 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 #include "phNxpNciHal_IoctlOperations.h"
18 
19 #include <android-base/file.h>
20 #include <android-base/parseint.h>
21 #include <android-base/strings.h>
22 
23 #include <map>
24 #include <set>
25 #include <unordered_map>
26 #include <vector>
27 
28 #include "EseAdaptation.h"
29 #include "NfccTransport.h"
30 #include "NfccTransportFactory.h"
31 #include "phDnldNfc_Internal.h"
32 #include "phNfcCommon.h"
33 #include "phNxpNciHal_Adaptation.h"
34 #include "phNxpNciHal_ULPDet.h"
35 #include "phNxpNciHal_ext.h"
36 #include "phNxpNciHal_extOperations.h"
37 #include "phNxpNciHal_utils.h"
38 
39 using android::base::WriteStringToFile;
40 using namespace ::std;
41 using namespace ::android::base;
42 
43 #define TERMINAL_LEN 5
44 /* HAL_NFC_STATUS_REFUSED sent to restart NFC service */
45 #define HAL_NFC_STATUS_RESTART HAL_NFC_STATUS_REFUSED
46 
47 #define GET_RES_STATUS_CHECK(len, data)                           \
48   (((len) < NCI_HEADER_SIZE) ||                                   \
49    ((len) != ((data[NCI_PACKET_LEN_INDEX]) + NCI_HEADER_SIZE)) || \
50    (NFCSTATUS_SUCCESS != (data[NCI_GET_RES_STATUS_INDEX])))
51 
52 typedef enum {
53   UPDATE_DLMA_ID_TX_ENTRY,
54   UPDATE_RF_CM_TX_UNDERSHOOT_CONFIG,
55   UPDATE_MIFARE_NACK_TO_RATS_ENABLE,
56   UPDATE_MIFARE_MUTE_TO_RATS_ENABLE,
57   UPDATE_CHINA_TIANJIN_RF_ENABLED,
58   UPDATE_CN_TRANSIT_CMA_BYPASSMODE_ENABLE,
59   UPDATE_CN_TRANSIT_BLK_NUM_CHECK_ENABLE,
60   UPDATE_ISO_DEP_MERGE_SAK,
61   UPDATE_PHONEOFF_TECH_DISABLE,
62   UPDATE_INITIAL_TX_PHASE,
63   UPDATE_GUARD_TIMEOUT_TX2RX,
64   UPDATE_LPDET_THRESHOLD,
65   UPDATE_NFCLD_THRESHOLD,
66   UPDATE_RF_PATTERN_CHK,
67   UPDATE_UNKNOWN = 0xFF
68 } tNFC_setDynamicRfConfigType;
69 static const std::unordered_map<std::string, uint8_t> tokenMap = {
70     {"UPDATE_DLMA_ID_TX_ENTRY", UPDATE_DLMA_ID_TX_ENTRY},
71     {"UPDATE_RF_CM_TX_UNDERSHOOT_CONFIG", UPDATE_RF_CM_TX_UNDERSHOOT_CONFIG},
72     {"UPDATE_MIFARE_NACK_TO_RATS_ENABLE", UPDATE_MIFARE_NACK_TO_RATS_ENABLE},
73     {"UPDATE_MIFARE_MUTE_TO_RATS_ENABLE", UPDATE_MIFARE_MUTE_TO_RATS_ENABLE},
74     {"UPDATE_CHINA_TIANJIN_RF_ENABLED", UPDATE_CHINA_TIANJIN_RF_ENABLED},
75     {"UPDATE_CN_TRANSIT_CMA_BYPASSMODE_ENABLE",
76      UPDATE_CN_TRANSIT_CMA_BYPASSMODE_ENABLE},
77     {"UPDATE_CN_TRANSIT_BLK_NUM_CHECK_ENABLE",
78      UPDATE_CN_TRANSIT_BLK_NUM_CHECK_ENABLE},
79     {"UPDATE_ISO_DEP_MERGE_SAK", UPDATE_ISO_DEP_MERGE_SAK},
80     {"UPDATE_PHONEOFF_TECH_DISABLE", UPDATE_PHONEOFF_TECH_DISABLE},
81     {"UPDATE_INITIAL_TX_PHASE", UPDATE_INITIAL_TX_PHASE},
82     {"UPDATE_GUARD_TIMEOUT_TX2RX", UPDATE_GUARD_TIMEOUT_TX2RX},
83     {"UPDATE_LPDET_THRESHOLD", UPDATE_LPDET_THRESHOLD},
84     {"UPDATE_NFCLD_THRESHOLD", UPDATE_NFCLD_THRESHOLD},
85     {"UPDATE_RF_PATTERN_CHK", UPDATE_RF_PATTERN_CHK}};
86 
87 static const std::unordered_map<uint8_t, uint8_t> rfReg_A085_Map = {
88     {UPDATE_MIFARE_NACK_TO_RATS_ENABLE, MIFARE_NACK_TO_RATS_ENABLE_BIT_POS},
89     {UPDATE_MIFARE_MUTE_TO_RATS_ENABLE, MIFARE_MUTE_TO_RATS_ENABLE_BIT_POS},
90     {UPDATE_CHINA_TIANJIN_RF_ENABLED, CHINA_TIANJIN_RF_ENABLE_BIT_POS},
91     {UPDATE_CN_TRANSIT_CMA_BYPASSMODE_ENABLE,
92      CN_TRANSIT_CMA_BYPASSMODE_ENABLE_BIT_POS},
93     {UPDATE_CN_TRANSIT_BLK_NUM_CHECK_ENABLE,
94      CN_TRANSIT_BLK_NUM_CHECK_ENABLE_BIT_POS}};
95 /****************************************************************
96  * Global Variables Declaration
97  ***************************************************************/
98 /* External global variable to get FW version from NCI response*/
99 extern uint32_t wFwVerRsp;
100 /* External global variable to get FW version from FW file*/
101 extern uint16_t wFwVer;
102 /* NCI HAL Control structure */
103 extern phNxpNciHal_Control_t nxpncihal_ctrl;
104 extern phNxpNci_getCfg_info_t* mGetCfg_info;
105 extern EseAdaptation* gpEseAdapt;
106 extern nfc_stack_callback_t* p_nfc_stack_cback_backup;
107 #ifndef FW_DWNLD_FLAG
108 extern uint8_t fw_dwnld_flag;
109 #endif
110 
111 /* TML Context */
112 extern phTmlNfc_Context_t* gpphTmlNfc_Context;
113 extern bool nfc_debug_enabled;
114 extern NFCSTATUS phNxpLog_EnableDisableLogLevel(uint8_t enable);
115 extern phNxpNciClock_t phNxpNciClock;
116 extern NfcHalThreadMutex sHalFnLock;
117 
118 /*******************************************************************************
119  **
120  ** Function:        property_get_intf()
121  **
122  ** Description:     Gets property value for the input property name
123  **
124  ** Parameters       propName:   Name of the property whichs value need to get
125  **                  valueStr:   output value of the property.
126  **                  defaultStr: default value of the property if value is not
127  **                              there this will be set to output value.
128  **
129  ** Returns:         actual length of the property value
130  **
131  ********************************************************************************/
property_get_intf(const char * propName,char * valueStr,const char * defaultStr)132 int property_get_intf(const char* propName, char* valueStr,
133                       const char* defaultStr) {
134   string propValue;
135   string propValueDefault = defaultStr;
136   int len = 0;
137 
138   propValue = phNxpNciHal_getSystemProperty(propName);
139   if (propValue.length() > 0) {
140     NXPLOG_NCIHAL_D("property_get_intf , key[%s], propValue[%s], length[%zu]",
141                     propName, propValue.c_str(), propValue.length());
142     len = propValue.length();
143     strlcpy(valueStr, propValue.c_str(), PROPERTY_VALUE_MAX);
144   } else {
145     if (propValueDefault.length() > 0) {
146       len = propValueDefault.length();
147       strlcpy(valueStr, propValueDefault.c_str(), PROPERTY_VALUE_MAX);
148     }
149   }
150 
151   return len;
152 }
153 
154 /*******************************************************************************
155  **
156  ** Function:        property_set_intf()
157  **
158  ** Description:     Sets property value for the input property name
159  **
160  ** Parameters       propName:   Name of the property whichs value need to set
161  **                  valueStr:   value of the property.
162  **
163  ** Returns:        returns 0 on success, < 0 on failure
164  **
165  ********************************************************************************/
property_set_intf(const char * propName,const char * valueStr)166 int property_set_intf(const char* propName, const char* valueStr) {
167   NXPLOG_NCIHAL_D("property_set_intf, key[%s], value[%s]", propName, valueStr);
168   if (phNxpNciHal_setSystemProperty(propName, valueStr))
169     return NFCSTATUS_SUCCESS;
170   else
171     return NFCSTATUS_FAILED;
172 }
173 
174 extern size_t readConfigFile(const char* fileName, uint8_t** p_data);
175 extern NFCSTATUS phNxpNciHal_ext_send_sram_config_to_flash();
176 static bool phNxpNciHal_checkUpdateRfTransitConfig(const char* config);
177 static string phNxpNciHal_parseBytesString(string in);
178 static bool phNxpNciHal_parseValueFromString(string& in);
179 static bool phNxpNciHal_CheckKeyNeeded(string key);
180 static string phNxpNciHal_UpdatePwrStateConfigs(string& config);
181 static bool phNxpNciHal_IsAutonmousModeSet(string config);
182 static string phNxpNciHal_extractConfig(string& config);
183 static void phNxpNciHal_getFilteredConfig(string& config);
184 
185 typedef std::map<std::string, std::string> systemProperty;
186 systemProperty gsystemProperty = {
187     {"nfc.nxp_log_level_global", ""},
188     {"nfc.nxp_log_level_extns", ""},
189     {"nfc.nxp_log_level_hal", ""},
190     {"nfc.nxp_log_level_nci", ""},
191     {"nfc.nxp_log_level_dnld", ""},
192     {"nfc.nxp_log_level_tml", ""},
193     {"nfc.fw.dfl", ""},
194     {"nfc.fw.downloadmode_force", ""},
195     {"nfc.debug_enabled", ""},
196     {"nfc.product.support.ese", ""},
197     {"nfc.product.support.uicc", ""},
198     {"nfc.product.support.uicc2", ""},
199     {"nfc.fw.rfreg_ver", ""},
200     {"nfc.fw.rfreg_display_ver", ""},
201     {"nfc.fw.dfl_areacode", ""},
202     {"nfc.cover.cover_id", ""},
203     {"nfc.cover.state", ""},
204     {"ro.factory.factory_binary", ""},
205 };
206 const char default_nxp_config_path[] = "/vendor/etc/libnfc-nxp.conf";
207 std::set<string> gNciConfigs = {"NXP_SE_COLD_TEMP_ERROR_DELAY",
208                                 "NXP_SWP_RD_TAG_OP_TIMEOUT",
209                                 "NXP_DUAL_UICC_ENABLE",
210                                 "DEFAULT_AID_ROUTE",
211                                 "DEFAULT_MIFARE_CLT_ROUTE",
212                                 "DEFAULT_FELICA_CLT_ROUTE",
213                                 "DEFAULT_AID_PWR_STATE",
214                                 "DEFAULT_DESFIRE_PWR_STATE",
215                                 "DEFAULT_MIFARE_CLT_PWR_STATE",
216                                 "DEFAULT_FELICA_CLT_PWR_STATE",
217                                 "HOST_LISTEN_TECH_MASK",
218                                 "FORWARD_FUNCTIONALITY_ENABLE",
219                                 "DEFAULT_GSMA_PWR_STATE",
220                                 "NXP_DEFAULT_UICC2_SELECT",
221                                 "NXP_SMB_TRANSCEIVE_TIMEOUT",
222                                 "NXP_SMB_ERROR_RETRY",
223                                 "NXP_CHECK_DEFAULT_PROTO_SE_ID",
224                                 "NXPLOG_NCIHAL_LOGLEVEL",
225                                 "NXPLOG_EXTNS_LOGLEVEL",
226                                 "NXPLOG_TML_LOGLEVEL",
227                                 "NXPLOG_FWDNLD_LOGLEVEL",
228                                 "NXPLOG_NCIX_LOGLEVEL",
229                                 "NXPLOG_NCIR_LOGLEVEL",
230                                 "NXP_NFC_SE_TERMINAL_NUM",
231                                 "NXP_POLL_FOR_EFD_TIMEDELAY",
232                                 "NXP_NFCC_MERGE_SAK_ENABLE",
233                                 "NXP_STAG_TIMEOUT_CFG",
234                                 "DEFAULT_T4TNFCEE_AID_POWER_STATE",
235                                 "RF_STORAGE",
236                                 "FW_STORAGE",
237                                 "NXP_CORE_CONF",
238                                 "NXP_RF_FILE_VERSION_INFO",
239                                 "NXP_AUTONOMOUS_ENABLE",
240                                 "NXP_PROP_RESET_EMVCO_CMD",
241                                 "NFA_CONFIG_FORMAT",
242                                 "NXP_T4T_NFCEE_ENABLE",
243                                 "NXP_DISCONNECT_TAG_IN_SCRN_OFF",
244                                 "NXP_CE_PRIORITY_ENABLED",
245                                 "NXP_RDR_REQ_GUARD_TIME",
246                                 "NXP_ENABLE_DISABLE_LOGS",
247                                 "NXP_RDR_DISABLE_ENABLE_LPCD",
248                                 "NXP_SUPPORT_NON_STD_CARD",
249                                 "NXP_GET_HW_INFO_LOG",
250                                 "NXP_WLC_MODE",
251                                 "NXP_T4T_NDEF_NFCEE_AID",
252                                 "NXP_NON_STD_CARD_TIMEDIFF",
253                                 "NXP_SRD_TIMEOUT",
254                                 "NXP_UICC_ETSI_SUPPORT",
255                                 "NXP_MINIMAL_FW_VERSION",
256                                 "NXP_RESTART_RF_FOR_NFCEE_RECOVERY",
257                                 "NXP_NFCC_RECOVERY_SUPPORT",
258                                 "NXP_AGC_DEBUG_ENABLE",
259                                 "NXP_EXTENDED_FIELD_DETECT_MODE",
260                                 "NXP_SE_SMB_TERMINAL_TYPE"};
261 
262 /****************************************************************
263  * Local Functions
264  ***************************************************************/
265 
266 /******************************************************************************
267  ** Function         phNxpNciHal_ioctlIf
268  **
269  ** Description      This function shall be called from HAL when libnfc-nci
270  **                  calls phNxpNciHal_ioctl() to perform any IOCTL operation
271  **
272  ** Returns          return 0 on success and -1 on fail,
273  ******************************************************************************/
phNxpNciHal_ioctlIf(long arg,void * p_data)274 int phNxpNciHal_ioctlIf(long arg, void* p_data) {
275   NXPLOG_NCIHAL_D("%s : enter - arg = %ld", __func__, arg);
276   ese_nxp_IoctlInOutData_t* pInpOutData = (ese_nxp_IoctlInOutData_t*)p_data;
277   int ret = -1;
278 
279   switch (arg) {
280     case HAL_ESE_IOCTL_NFC_JCOP_DWNLD:
281       if (pInpOutData == NULL) {
282         NXPLOG_NCIHAL_E("%s : received invalid param", __func__);
283         break;
284       }
285 
286       if (gpEseAdapt == NULL) {
287         gpEseAdapt = &EseAdaptation::GetInstance();
288         if (gpEseAdapt == NULL) {
289           NXPLOG_NCIHAL_E("%s :invalid gpEseAdapt param", __func__);
290           break;
291         }
292         gpEseAdapt->Initialize();
293       }
294 
295       NXPLOG_NCIHAL_D("HAL_ESE_IOCTL_NFC_JCOP_DWNLD Enter value is %d: \n",
296                       pInpOutData->inp.data.nxpCmd.p_cmd[0]);
297 
298       gpEseAdapt->HalIoctl(HAL_ESE_IOCTL_NFC_JCOP_DWNLD, pInpOutData);
299       ret = 0;
300       break;
301     default:
302       NXPLOG_NCIHAL_E("%s : Wrong arg = %ld", __func__, arg);
303       break;
304   }
305   NXPLOG_NCIHAL_D("%s : exit - ret = %d", __func__, ret);
306   return ret;
307 }
308 
309 /*******************************************************************************
310  **
311  ** Function         phNxpNciHal_getSystemProperty
312  **
313  ** Description      It shall be used to get property value of the given Key
314  **
315  ** Parameters       string key
316  **
317  ** Returns          If Key is found, returns the respective property values
318  **                  else returns the null/empty string
319  *******************************************************************************/
phNxpNciHal_getSystemProperty(string key)320 string phNxpNciHal_getSystemProperty(string key) {
321   string propValue;
322   std::map<std::string, std::string>::iterator prop;
323 
324   if (key == "libnfc-nxp.conf") {
325     return phNxpNciHal_getNxpConfigIf();
326   } else {
327     prop = gsystemProperty.find(key);
328     if (prop != gsystemProperty.end()) {
329       propValue = prop->second;
330     } else {
331       /* else Pass a null string */
332     }
333   }
334   return propValue;
335 }
336 /*******************************************************************************
337  **
338  ** Function         phNxpNciHal_setSystemProperty
339  **
340  ** Description      It shall be used to save/change value to system property
341  **                  based on provided key.
342  **
343  ** Parameters       string key, string value
344  **
345  ** Returns          true if success, false if fail
346  *******************************************************************************/
phNxpNciHal_setSystemProperty(string key,string value)347 bool phNxpNciHal_setSystemProperty(string key, string value) {
348   bool stat = true;
349   if (strcmp(key.c_str(), "nfc.debug_enabled") != 0)
350     NXPLOG_NCIHAL_D("%s : Enter Key = %s, value = %s", __func__, key.c_str(),
351                     value.c_str());
352 
353   unsigned tmp = 0;
354   if (strcmp(key.c_str(), "nfc.debug_enabled") == 0) {
355     if (ParseUint(value.c_str(), &tmp)) {
356       if (phNxpLog_EnableDisableLogLevel((uint8_t)tmp) != NFCSTATUS_SUCCESS) {
357         stat = false;
358       }
359     } else {
360       NXPLOG_NCIHAL_W(
361           "%s : Failed to parse the string to uint. "
362           "nfc.debug_enabled string : %s",
363           __func__, value.c_str());
364     }
365   } else if (strcmp(key.c_str(), "nfc.cover.state") == 0) {
366     unsigned cid, cstate;
367     string strtmp;
368     if (ParseUint(value.c_str(), &cstate)) {
369       strtmp = phNxpNciHal_getSystemProperty("nfc.cover.cover_id");
370       if (ParseUint(strtmp.c_str(), &cid)) {
371         if (fpPropConfCover != NULL) {
372           stat = (fpPropConfCover(cstate, cid) == NFCSTATUS_SUCCESS) ? true
373                                                                      : false;
374         }
375       } else {
376         NXPLOG_NCIHAL_W(
377             "%s : Failed to parse the string to uint. "
378             "nfc.cover.cover_id string : %s",
379             __func__, value.c_str());
380       }
381     } else {
382       NXPLOG_NCIHAL_W(
383           "%s : Failed to parse the string to uint. "
384           "nfc.cover.state string : %s",
385           __func__, value.c_str());
386     }
387   } else if (strcmp(key.c_str(), "nfc.cmd_timeout") == 0) {
388     NXPLOG_NCIHAL_E("%s : nci_timeout, sem post", __func__);
389     sem_post(&(nxpncihal_ctrl.syncSpiNfc));
390   }
391   gsystemProperty[key] = std::move(value);
392   return stat;
393 }
394 
395 /*******************************************************************************
396 **
397 ** Function         phNxpNciHal_getNxpConfig
398 **
399 ** Description      It shall be used to read config values from the
400 *libnfc-nxp.conf
401 **
402 ** Parameters       nxpConfigs config
403 **
404 ** Returns          void
405 *******************************************************************************/
phNxpNciHal_getNxpConfigIf()406 string phNxpNciHal_getNxpConfigIf() {
407   std::string config;
408   uint8_t* p_config = nullptr;
409   size_t config_size = readConfigFile(default_nxp_config_path, &p_config);
410   if (config_size) {
411     config.assign((char*)p_config, config_size);
412     free(p_config);
413     phNxpNciHal_getFilteredConfig(config);
414   }
415   return config;
416 }
417 
418 /*******************************************************************************
419 **
420 ** Function         phNxpNciHal_getFilteredConfig
421 **
422 ** Description      It reads only configs needed for libnfc from
423 *                   libnfc-nxp.conf
424 **
425 ** Parameters       string config
426 **
427 ** Returns          void
428 *******************************************************************************/
phNxpNciHal_getFilteredConfig(string & config)429 static void phNxpNciHal_getFilteredConfig(string& config) {
430   config = phNxpNciHal_extractConfig(config);
431   if (phNxpNciHal_IsAutonmousModeSet(config)) {
432     config = phNxpNciHal_UpdatePwrStateConfigs(config);
433   }
434 }
435 
436 /*******************************************************************************
437 **
438 ** Function         phNxpNciHal_extractConfig
439 **
440 ** Description      It parses complete config file and extracts only
441 *                   enabled options ignores comments etc.
442 **
443 ** Parameters       string config
444 **
445 ** Returns          Resultant string
446 *******************************************************************************/
phNxpNciHal_extractConfig(string & config)447 static string phNxpNciHal_extractConfig(string& config) {
448   stringstream ss(config);
449   string line;
450   string result;
451   bool apduGate = false;
452   while (getline(ss, line)) {
453     line = Trim(line);
454     if (line.empty()) continue;
455     if (line.at(0) == '#') continue;
456     if (line.at(0) == 0) continue;
457 
458     auto search = line.find('=');
459     if (search == string::npos) continue;
460 
461     string key(Trim(line.substr(0, search)));
462     if (!phNxpNciHal_CheckKeyNeeded(key)) continue;
463     if (key == "NXP_NFC_SE_TERMINAL_NUM" && !apduGate) {
464       line = "NXP_SE_APDU_GATE_SUPPORT=0x01\n";
465       result += line;
466       apduGate = true;
467       continue;
468     }
469     string value_string(Trim(line.substr(search + 1, string::npos)));
470 
471     if (value_string[0] == '{' &&
472         value_string[value_string.length() - 1] != '}') {
473       string line_append;
474 
475       do {
476         getline(ss, line_append);
477         if (line_append.empty()) break;
478         if (line_append.at(0) == '#') break;
479         if (line_append.at(0) == 0) break;
480         line_append = Trim(line_append);
481         value_string.append(line_append);
482       } while (line_append[line_append.length() - 1] != '}');
483     }
484 
485     if (!phNxpNciHal_parseValueFromString(value_string)) continue;
486 
487     line = key + "=" + value_string + "\n";
488     result += line;
489     if (key == "NXP_GET_HW_INFO_LOG" &&
490         (value_string == "1" || value_string == "0x01")) {
491       if (!apduGate) {
492         line = "NXP_SE_APDU_GATE_SUPPORT=0x01\n";
493         result += line;
494         apduGate = true;
495       }
496     }
497   }
498 
499   return result;
500 }
501 
502 /*******************************************************************************
503 **
504 ** Function         phNxpNciHal_IsAutonmousModeSet
505 **
506 ** Description      It check whether autonomous mode is enabled
507 *                   in config file
508 **
509 ** Parameters       string config
510 **
511 ** Returns          boolean(TRUE/FALSE)
512 *******************************************************************************/
phNxpNciHal_IsAutonmousModeSet(string config)513 static bool phNxpNciHal_IsAutonmousModeSet(string config) {
514   stringstream ss(config);
515   string line;
516   unsigned tmp = 0;
517   while (getline(ss, line)) {
518     auto search = line.find('=');
519     if (search == string::npos) continue;
520 
521     string key(Trim(line.substr(0, search)));
522     if (key == "NXP_AUTONOMOUS_ENABLE") {
523       string value(Trim(line.substr(search + 1, string::npos)));
524       if (ParseUint(value.c_str(), &tmp)) {
525         if (tmp == 1) {
526           return true;
527         } else {
528           NXPLOG_NCIHAL_D("Autonomous flag disabled");
529           return false;
530         }
531       }
532     } else {
533       continue;
534     }
535   }
536   NXPLOG_NCIHAL_D("Autonomous flag disabled");
537   return false;
538 }
539 
540 /*******************************************************************************
541 **
542 ** Function         phNxpNciHal_UpdatePwrStateConfigs
543 **
544 ** Description      Updates default pwr state accordingly if autonomous mode
545 *                   is enabled
546 **
547 ** Parameters       string config
548 **
549 ** Returns          Resultant string
550 *******************************************************************************/
phNxpNciHal_UpdatePwrStateConfigs(string & config)551 static string phNxpNciHal_UpdatePwrStateConfigs(string& config) {
552   stringstream ss(config);
553   string line;
554   string result;
555   unsigned tmp = 0;
556   while (getline(ss, line)) {
557     auto search = line.find('=');
558     if (search == string::npos) continue;
559 
560     string key(Trim(line.substr(0, search)));
561     if ((key == "DEFAULT_AID_PWR_STATE" || key == "DEFAULT_DESFIRE_PWR_STATE" ||
562          key == "DEFAULT_MIFARE_CLT_PWR_STATE" ||
563          key == "DEFAULT_FELICA_CLT_PWR_STATE")) {
564       string value(Trim(line.substr(search + 1, string::npos)));
565       if (ParseUint(value.c_str(), &tmp)) {
566         tmp = phNxpNciHal_updateAutonomousPwrState(tmp);
567         value = to_string(tmp);
568         line = key + "=" + value + "\n";
569         result += line;
570       }
571     } else {
572       result += (line + "\n");
573       continue;
574     }
575   }
576   return result;
577 }
578 
579 /*******************************************************************************
580 **
581 ** Function         phNxpNciHal_CheckKeyNeeded
582 **
583 ** Description      Check if the config needed for libnfc as per gNciConfigs
584 *                   list
585 **
586 ** Parameters       string config
587 **
588 ** Returns          bool(true/false)
589 *******************************************************************************/
phNxpNciHal_CheckKeyNeeded(string key)590 static bool phNxpNciHal_CheckKeyNeeded(string key) {
591   return ((gNciConfigs.find(key) != gNciConfigs.end()) ? true : false);
592 }
593 
594 /*******************************************************************************
595 **
596 ** Function         phNxpNciHal_parseValueFromString
597 **
598 ** Description      Parse value determine data type of config option
599 **
600 ** Parameters       string config
601 **
602 ** Returns          bool(true/false)
603 *******************************************************************************/
phNxpNciHal_parseValueFromString(string & in)604 static bool phNxpNciHal_parseValueFromString(string& in) {
605   unsigned tmp = 0;
606   bool stat = false;
607   if (in.length() >= 1) {
608     switch (in[0]) {
609       case '"':
610         if (in[in.length() - 1] == '"' && in.length() > 2) stat = true;
611         break;
612       case '{':
613         if (in[in.length() - 1] == '}' && in.length() >= 3) {
614           in = phNxpNciHal_parseBytesString(in);
615           stat = true;
616         }
617         break;
618       default:
619         if (ParseUint(in.c_str(), &tmp)) stat = true;
620         break;
621     }
622   } else {
623     NXPLOG_NCIHAL_E("%s : Invalid config string ", __func__);
624   }
625   return stat;
626 }
627 
628 /*******************************************************************************
629 **
630 ** Function         phNxpNciHal_parseBytesString
631 **
632 ** Description      Parse bytes from string
633 **
634 ** Parameters       string config
635 **
636 ** Returns          Resultant string
637 *******************************************************************************/
phNxpNciHal_parseBytesString(string in)638 static string phNxpNciHal_parseBytesString(string in) {
639   size_t pos;
640   in.erase(remove(in.begin(), in.end(), ' '), in.end());
641   pos = in.find(",");
642   while (pos != string::npos) {
643     in = in.replace(pos, 1, ":");
644     pos = in.find(",", pos);
645   }
646   return in;
647 }
648 
649 /*******************************************************************************
650 **
651 ** Function         phNxpNciHal_resetEse
652 **
653 ** Description      It shall be used to reset eSE by proprietary command.
654 **
655 ** Parameters
656 **
657 ** Returns          status of eSE reset response
658 *******************************************************************************/
phNxpNciHal_resetEse(uint64_t resetType)659 NFCSTATUS phNxpNciHal_resetEse(uint64_t resetType) {
660   NFCSTATUS status = NFCSTATUS_FAILED;
661 
662   {
663     NfcHalAutoThreadMutex a(sHalFnLock);
664     if (nxpncihal_ctrl.halStatus == HAL_STATUS_CLOSE) {
665       if (NFCSTATUS_SUCCESS != phNxpNciHal_MinOpen()) {
666         return NFCSTATUS_FAILED;
667       }
668     }
669   }
670 
671   CONCURRENCY_LOCK();
672   status = gpTransportObj->EseReset(gpphTmlNfc_Context->pDevHandle,
673                                     (EseResetType)resetType);
674   CONCURRENCY_UNLOCK();
675   if (status != NFCSTATUS_SUCCESS) {
676     NXPLOG_NCIHAL_E("EsePowerCycle failed");
677   }
678 
679   if (nxpncihal_ctrl.halStatus == HAL_STATUS_MIN_OPEN) {
680     phNxpNciHal_close(false);
681   }
682 
683   return status;
684 }
685 
686 /*******************************************************************************
687  **
688  ** Function:        phNxpNciHal_GetNfcGpiosStatus()
689  **
690  ** Description:     Sets the gpios status flag byte
691  **
692  ** Parameters       gpiostatus: flag byte
693  **
694  ** Returns:        returns 0 on success, < 0 on failure
695  **
696  ********************************************************************************/
phNxpNciHal_GetNfcGpiosStatus(uint32_t * gpiosstatus)697 NFCSTATUS phNxpNciHal_GetNfcGpiosStatus(uint32_t* gpiosstatus) {
698   NFCSTATUS status = NFCSTATUS_FAILED;
699   status = gpTransportObj->NfcGetGpioStatus(gpphTmlNfc_Context->pDevHandle,
700                                             gpiosstatus);
701   return status;
702 }
703 /******************************************************************************
704  * Function         phNxpNciHal_setNxpTransitConfig
705  *
706  * Description      This function overwrite libnfc-nxpTransit.conf file
707  *                  with transitConfValue.
708  *
709  * Returns          bool.
710  *
711  ******************************************************************************/
phNxpNciHal_setNxpTransitConfig(char * transitConfValue)712 bool phNxpNciHal_setNxpTransitConfig(char* transitConfValue) {
713   bool status = true;
714   NXPLOG_NCIHAL_D("%s : Enter", __func__);
715   std::string transitConfFileName = "/data/vendor/nfc/libnfc-nxpTransit.conf";
716   long transitConfValueLen = strlen(transitConfValue) + 1;
717 
718   if (transitConfValueLen > 1) {
719     if (strncmp(transitConfValue, "UPDATE_", 7) == 0) {
720       if (IS_CHIP_TYPE_GE(sn220u) &&
721           phNxpNciHal_checkUpdateRfTransitConfig(transitConfValue)) {
722         NXPLOG_NCIHAL_D("%s :RfTransit values updated", __func__);
723       } else {
724         NXPLOG_NCIHAL_E("Failed to update RfTransit values");
725         status = false;
726       }
727     } else {
728       if (!WriteStringToFile(transitConfValue, transitConfFileName)) {
729         NXPLOG_NCIHAL_E("WriteStringToFile: Failed");
730         status = false;
731       }
732     }
733   } else {
734     if (!WriteStringToFile("", transitConfFileName)) {
735       NXPLOG_NCIHAL_E("WriteStringToFile: Failed");
736       status = false;
737     }
738     if (remove(transitConfFileName.c_str())) {
739       NXPLOG_NCIHAL_E("Unable to remove file");
740       status = false;
741     }
742   }
743   NXPLOG_NCIHAL_D("%s : Exit", __func__);
744   return status;
745 }
746 
747 /******************************************************************************
748 ** Function         phNxpNciHal_Abort
749 **
750 ** Description      This function shall be used to trigger the abort in libnfc
751 **
752 ** Parameters       None
753 **
754 ** Returns          bool.
755 **
756 *******************************************************************************/
phNxpNciHal_Abort()757 bool phNxpNciHal_Abort() {
758   bool ret = true;
759 
760   NXPLOG_NCIHAL_D("phNxpNciHal_Abort aborting. \n");
761   /* When JCOP download is triggered phNxpNciHal_open is blocked, in this case
762      only we need to abort the libnfc , this can be done only by check the
763      p_nfc_stack_cback_backup pointer which is assigned before the JCOP
764      download.*/
765   if (p_nfc_stack_cback_backup != NULL) {
766     (*p_nfc_stack_cback_backup)(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_RESTART);
767   } else {
768     ret = false;
769     NXPLOG_NCIHAL_D("phNxpNciHal_Abort not triggered\n");
770   }
771   return ret;
772 }
773 
774 /*******************************************************************************
775  **
776  ** Function:        phNxpNciHal_CheckFwRegFlashRequired()
777  **
778  ** Description:     Updates FW and Reg configurations if required
779  **
780  ** Returns:         status
781  **
782  ********************************************************************************/
phNxpNciHal_CheckFwRegFlashRequired(uint8_t * fw_update_req,uint8_t * rf_update_req,uint8_t skipEEPROMRead)783 int phNxpNciHal_CheckFwRegFlashRequired(uint8_t* fw_update_req,
784                                         uint8_t* rf_update_req,
785                                         uint8_t skipEEPROMRead) {
786   NXPLOG_NCIHAL_D("phNxpNciHal_CheckFwRegFlashRequired() : enter");
787   int status = NFCSTATUS_OK;
788   long option;
789   if (fpRegRfFwDndl != NULL) {
790     status = fpRegRfFwDndl(fw_update_req, rf_update_req, skipEEPROMRead);
791   } else {
792     status = phDnldNfc_InitImgInfo();
793     NXPLOG_NCIHAL_D("FW version from the binary(.so/bin) = 0x%x", wFwVer);
794     NXPLOG_NCIHAL_D("FW version found on the device = 0x%x", wFwVerRsp);
795 
796     if (!GetNxpNumValue(NAME_NXP_FLASH_CONFIG, &option,
797                         sizeof(unsigned long))) {
798       NXPLOG_NCIHAL_D("Flash option not found; giving default value");
799       option = 1;
800     }
801     switch (option) {
802       case FLASH_UPPER_VERSION:
803         wFwUpdateReq = (utf8_t)wFwVer > (utf8_t)wFwVerRsp ? true : false;
804         break;
805       case FLASH_DIFFERENT_VERSION:
806         wFwUpdateReq = ((wFwVerRsp & 0x0000FFFF) != wFwVer) ? true : false;
807         break;
808       case FLASH_ALWAYS:
809         wFwUpdateReq = true;
810         break;
811       default:
812         NXPLOG_NCIHAL_D("Invalid flash option selected");
813         status = NFCSTATUS_INVALID_PARAMETER;
814         break;
815     }
816   }
817   *fw_update_req = wFwUpdateReq;
818 
819   if (false == wFwUpdateReq) {
820     NXPLOG_NCIHAL_D("FW update not required");
821     phDnldNfc_ReSetHwDevHandle();
822   } else {
823     property_set("nfc.fw.downloadmode_force", "1");
824   }
825 
826   NXPLOG_NCIHAL_D(
827       "phNxpNciHal_CheckFwRegFlashRequired() : exit - status = %x "
828       "wFwUpdateReq=%u, wRfUpdateReq=%u",
829       status, *fw_update_req, *rf_update_req);
830   return status;
831 }
832 
833 /******************************************************************************
834  * Function         phNxpNciHal_txNfccClockSetCmd
835  *
836  * Description      This function is called after successful download
837  *                  to apply the clock setting provided in config file
838  *
839  * Returns          void.
840  *
841  ******************************************************************************/
phNxpNciHal_txNfccClockSetCmd(void)842 void phNxpNciHal_txNfccClockSetCmd(void) {
843   NFCSTATUS status = NFCSTATUS_FAILED;
844 
845   uint8_t set_clock_cmd[] = {0x20, 0x02, 0x05, 0x01, 0xA0, 0x03, 0x01, 0x08};
846   uint8_t setClkCmdLen = sizeof(set_clock_cmd);
847   unsigned long clockSource = 0;
848   unsigned long frequency = 0;
849   uint32_t pllSetRetryCount = 3, dpllSetRetryCount = 3,
850            setClockCmdWriteRetryCnt = 0;
851   uint8_t* pCmd4PllSetting = NULL;
852   uint8_t* pCmd4DpllSetting = NULL;
853   uint32_t pllCmdLen = 0, dpllCmdLen = 0;
854   int srcCfgFound = 0, freqCfgFound = 0;
855 
856   srcCfgFound = (GetNxpNumValue(NAME_NXP_SYS_CLK_SRC_SEL, &clockSource,
857                                 sizeof(clockSource)) > 0);
858 
859   freqCfgFound = (GetNxpNumValue(NAME_NXP_SYS_CLK_FREQ_SEL, &frequency,
860                                  sizeof(frequency)) > 0);
861 
862   NXPLOG_NCIHAL_D("%s : clock source = %lu, frequency = %lu", __FUNCTION__,
863                   clockSource, frequency);
864 
865   if (srcCfgFound && freqCfgFound && (clockSource == CLK_SRC_PLL)) {
866     phNxpNciClock.isClockSet = TRUE;
867 
868     switch (frequency) {
869       case CLK_FREQ_13MHZ: {
870         NXPLOG_NCIHAL_D("PLL setting for CLK_FREQ_13MHZ");
871         pCmd4PllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_PLL_13MHZ;
872         pllCmdLen = sizeof(PN557_SET_CONFIG_CMD_PLL_13MHZ);
873         pCmd4DpllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_DPLL_13MHZ;
874         dpllCmdLen = sizeof(PN557_SET_CONFIG_CMD_DPLL_13MHZ);
875         break;
876       }
877       case CLK_FREQ_19_2MHZ: {
878         NXPLOG_NCIHAL_D("PLL setting for CLK_FREQ_19_2MHZ");
879         pCmd4PllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_PLL_19_2MHZ;
880         pllCmdLen = sizeof(PN557_SET_CONFIG_CMD_PLL_19_2MHZ);
881         pCmd4DpllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_DPLL_19_2MHZ;
882         dpllCmdLen = sizeof(PN557_SET_CONFIG_CMD_DPLL_19_2MHZ);
883         break;
884       }
885       case CLK_FREQ_24MHZ: {
886         NXPLOG_NCIHAL_D("PLL setting for CLK_FREQ_24MHZ");
887         pCmd4PllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_PLL_24MHZ;
888         pllCmdLen = sizeof(PN557_SET_CONFIG_CMD_PLL_24MHZ);
889         pCmd4DpllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_DPLL_24MHZ;
890         dpllCmdLen = sizeof(PN557_SET_CONFIG_CMD_DPLL_24MHZ);
891         break;
892       }
893       case CLK_FREQ_26MHZ: {
894         NXPLOG_NCIHAL_D("PLL setting for CLK_FREQ_26MHZ");
895         pCmd4PllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_PLL_26MHZ;
896         pllCmdLen = sizeof(PN557_SET_CONFIG_CMD_PLL_26MHZ);
897         pCmd4DpllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_DPLL_26MHZ;
898         dpllCmdLen = sizeof(PN557_SET_CONFIG_CMD_DPLL_26MHZ);
899         break;
900       }
901       case CLK_FREQ_32MHZ: {
902         NXPLOG_NCIHAL_D("PLL setting for CLK_FREQ_32MHZ");
903         pCmd4PllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_PLL_32MHZ;
904         pllCmdLen = sizeof(PN557_SET_CONFIG_CMD_PLL_32MHZ);
905         pCmd4DpllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_DPLL_32MHZ;
906         dpllCmdLen = sizeof(PN557_SET_CONFIG_CMD_DPLL_32MHZ);
907         break;
908       }
909       case CLK_FREQ_38_4MHZ: {
910         NXPLOG_NCIHAL_D("PLL setting for CLK_FREQ_38_4MHZ");
911         pCmd4PllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_PLL_38_4MHZ;
912         pllCmdLen = sizeof(PN557_SET_CONFIG_CMD_PLL_38_4MHZ);
913         pCmd4DpllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_DPLL_38_4MHZ;
914         dpllCmdLen = sizeof(PN557_SET_CONFIG_CMD_DPLL_38_4MHZ);
915         break;
916       }
917       case CLK_FREQ_48MHZ: {
918         NXPLOG_NCIHAL_D("PLL setting for CLK_FREQ_48MHZ");
919         pCmd4PllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_PLL_48MHZ;
920         pllCmdLen = sizeof(PN557_SET_CONFIG_CMD_PLL_48MHZ);
921         pCmd4DpllSetting = (uint8_t*)PN557_SET_CONFIG_CMD_DPLL_48MHZ;
922         dpllCmdLen = sizeof(PN557_SET_CONFIG_CMD_DPLL_48MHZ);
923         break;
924       }
925       default:
926         phNxpNciClock.isClockSet = FALSE;
927         NXPLOG_NCIHAL_E("ERROR: Invalid clock frequency!!");
928         return;
929     }
930   }
931   switch (clockSource) {
932     case CLK_SRC_PLL: {
933       set_clock_cmd[setClkCmdLen - 1] = 0x00;
934       while (status != NFCSTATUS_SUCCESS &&
935              setClockCmdWriteRetryCnt++ < MAX_RETRY_COUNT)
936         status = phNxpNciHal_send_ext_cmd(setClkCmdLen, set_clock_cmd);
937 
938       status = NFCSTATUS_FAILED;
939 
940       while (status != NFCSTATUS_SUCCESS && pllSetRetryCount-- > 0)
941         status = phNxpNciHal_send_ext_cmd(pllCmdLen, pCmd4PllSetting);
942 
943       status = NFCSTATUS_FAILED;
944 
945       while (status != NFCSTATUS_SUCCESS && dpllSetRetryCount-- > 0)
946         status = phNxpNciHal_send_ext_cmd(dpllCmdLen, pCmd4DpllSetting);
947 
948       break;
949     }
950     case CLK_SRC_XTAL: {
951       status = phNxpNciHal_send_ext_cmd(setClkCmdLen, set_clock_cmd);
952       if (status != NFCSTATUS_SUCCESS) {
953         NXPLOG_NCIHAL_E("XTAL clock setting failed !!");
954       }
955       break;
956     }
957     default:
958       NXPLOG_NCIHAL_E("Wrong clock source. Don't apply any modification");
959       return;
960   }
961   phNxpNciClock.isClockSet = FALSE;
962   if (status == NFCSTATUS_SUCCESS &&
963       phNxpNciClock.p_rx_data[3] == NFCSTATUS_SUCCESS) {
964     NXPLOG_NCIHAL_D("PLL and DPLL settings applied successfully");
965   }
966   return;
967 }
968 
969 /*******************************************************************************
970 **
971 ** Function         phNxpNciHal_updateRfSetConfig
972 **
973 ** Description      Update the set RF settings.
974 **
975 ** Parameters       setConfCmd - Update the set config buffer based on getConfig
976 **                  getResData - Response data.
977 ** Returns          True/False
978 *******************************************************************************/
phNxpNciHal_updateRfSetConfig(vector<uint8_t> & setConfCmd,vector<uint8_t> & getResData)979 bool phNxpNciHal_updateRfSetConfig(vector<uint8_t>& setConfCmd,
980                                    vector<uint8_t>& getResData) {
981   uint8_t res_data_packet_len = 0;
982   if ((getResData.size() <= 5) ||
983       (getResData.size() !=
984        (getResData[NCI_PACKET_LEN_INDEX] + NCI_HEADER_SIZE))) {
985     NXPLOG_NCIHAL_E("%s : Invalid res data length", __FUNCTION__);
986     return false;
987   }
988   /*Updating the actual TLV packet length by excluding the status & tlv bytes */
989   res_data_packet_len = getResData[NCI_PACKET_LEN_INDEX] - 2;
990   /*Copying the TLV packet and excluding  NCI header, status & tlv bytes*/
991   setConfCmd.insert(setConfCmd.end(), getResData.begin() + 5, getResData.end());
992   if (setConfCmd.size() >= 0xFF) {
993     if (NFCSTATUS_SUCCESS !=
994         phNxpNciHal_send_ext_cmd((setConfCmd.size() - res_data_packet_len),
995                                  &setConfCmd[0])) {
996       NXPLOG_NCIHAL_E("%s : Set config failed", __FUNCTION__);
997       return false;
998     }
999     // Clear setConf Data expect the last command response.
1000     setConfCmd.erase(setConfCmd.begin() + 4,
1001                      setConfCmd.end() - res_data_packet_len);
1002     // Clear the length and TLV after sending the packet.
1003     setConfCmd[NCI_PACKET_LEN_INDEX] = 0x01;
1004     setConfCmd[NCI_PACKET_TLV_INDEX] = 0x00;
1005   }
1006   setConfCmd[NCI_PACKET_LEN_INDEX] += res_data_packet_len;
1007   setConfCmd[NCI_PACKET_TLV_INDEX] += getResData[NCI_GET_RES_TLV_INDEX];
1008 
1009   return true;
1010 }
1011 /*******************************************************************************
1012 **
1013 ** Function         phNxpNciHal_getUpdatePropRfSetConfig
1014 **
1015 ** Description      Get and update the Prop RF settings.
1016 **
1017 ** Parameters       IndexValue poniting to the vector
1018 **                  NewValue   - To be update at the index position
1019 **                  propCmdresData - Update the prop response buffer based on
1020 **                  prop getConfig response.
1021 ** Returns          bool value true/false
1022 *******************************************************************************/
phNxpNciHal_getUpdatePropRfSetConfig(unsigned newValue,vector<uint8_t> & propCmdresData)1023 bool phNxpNciHal_getUpdatePropRfSetConfig(unsigned newValue,
1024                                           vector<uint8_t>& propCmdresData) {
1025   vector<uint8_t> prop_cmd_get_rftxval{0x2F, 0x14, 0x02, 0x62, 0x32};
1026   uint8_t getPropRfCount = 0;
1027   uint8_t index = 10;  // Index for RF register 6232
1028   do {
1029     if (NFCSTATUS_SUCCESS !=
1030         phNxpNciHal_send_ext_cmd(prop_cmd_get_rftxval.size(),
1031                                  &prop_cmd_get_rftxval[0])) {
1032       NXPLOG_NCIHAL_E("%s : Get config failed for A00D", __FUNCTION__);
1033       return false;
1034     }
1035     if (GET_RES_STATUS_CHECK(nxpncihal_ctrl.rx_data_len,
1036                              nxpncihal_ctrl.p_rx_data)) {
1037       NXPLOG_NCIHAL_E("%s : Get response failed", __FUNCTION__);
1038       return false;
1039     }
1040     if (nxpncihal_ctrl.p_rx_data[RF_CM_TX_UNDERSHOOT_INDEX] == newValue)
1041       return true;
1042 
1043     // Mapping Prop command response to NCI command response.
1044     propCmdresData[index] = (uint8_t)(newValue & BYTE0_SHIFT_MASK);
1045     propCmdresData[index + 1] =
1046         nxpncihal_ctrl.p_rx_data[RF_CM_TX_UNDERSHOOT_INDEX + 1];
1047     propCmdresData[index + 2] =
1048         nxpncihal_ctrl.p_rx_data[RF_CM_TX_UNDERSHOOT_INDEX + 2];
1049     propCmdresData[index + 3] =
1050         nxpncihal_ctrl.p_rx_data[RF_CM_TX_UNDERSHOOT_INDEX + 3];
1051 
1052     getPropRfCount++;
1053     if (getPropRfCount == 1) {
1054       index = 19;  // Index for RF register 6732
1055       prop_cmd_get_rftxval[NCI_PACKET_TLV_INDEX] = 0x67;
1056     }
1057   } while (getPropRfCount < 2);
1058 
1059   return true;
1060 }
1061 
1062 /*******************************************************************************
1063 **
1064 ** Function         phNxpNciHal_checkUpdateRfTransitConfig
1065 **
1066 ** Description      Check and update selected RF settings dynamically.
1067 **
1068 ** Parameters       char config
1069 **
1070 ** Returns          bool value true/false
1071 *******************************************************************************/
phNxpNciHal_checkUpdateRfTransitConfig(const char * config)1072 bool phNxpNciHal_checkUpdateRfTransitConfig(const char* config) {
1073   vector<uint8_t> cmd_get_rfconfval{0x20, 0x03, 0x03, 0x01, 0xA0, 0x85};
1074   vector<uint8_t> cmd_response{};
1075   vector<uint8_t> lpdet_cmd_response{};
1076   vector<uint8_t> get_cmd_response{};
1077   vector<uint8_t> cmd_set_rfconfval{0x20, 0x02, 0x01, 0x00};
1078   vector<uint8_t> prop_Cmd_Response{
1079       /*Preset get config response for A00D register*/
1080       0x40, 0x03, 0x14, 0x00, 0x02, 0xA0, 0x0D, 0x06, 0x62, 0x32, 0xAE, 0x00,
1081       0x7F, 0x00, 0xA0, 0x0D, 0x06, 0x67, 0x32, 0xAE, 0x00, 0x1F, 0x00};
1082   bool is_feature_update_required = false;
1083   bool is_lpdet_threshold_required = false;
1084   uint8_t index_to_value = 0;
1085   uint8_t update_mode = BITWISE;
1086   uint8_t condition = 0;
1087   stringstream key_value_pairs(config);
1088   string single_key_value;
1089   unsigned b_position = 0;
1090   unsigned new_value = 0;
1091   unsigned read_value = 0;
1092   unsigned rf_reg_A085_value = 0;
1093 
1094   NXPLOG_NCIHAL_D("%s : Enter", __FUNCTION__);
1095 
1096   if (NFCSTATUS_SUCCESS != phNxpNciHal_send_ext_cmd(cmd_get_rfconfval.size(),
1097                                                     &cmd_get_rfconfval[0])) {
1098     NXPLOG_NCIHAL_E("%s : Get config failed for A085", __FUNCTION__);
1099     return false;
1100   }
1101   if (GET_RES_STATUS_CHECK(nxpncihal_ctrl.rx_data_len,
1102                            nxpncihal_ctrl.p_rx_data)) {
1103     NXPLOG_NCIHAL_E("%s : Get config failed", __FUNCTION__);
1104     return false;
1105   }
1106   // Updating the A085 get config command response to vector.
1107   cmd_response.insert(
1108       cmd_response.end(), &nxpncihal_ctrl.p_rx_data[0],
1109       (&nxpncihal_ctrl.p_rx_data[0] +
1110        (nxpncihal_ctrl.p_rx_data[NCI_PACKET_LEN_INDEX] + NCI_HEADER_SIZE)));
1111   rf_reg_A085_value = (unsigned)((cmd_response[REG_A085_DATA_INDEX + 3] << 24) |
1112                                  (cmd_response[REG_A085_DATA_INDEX + 2] << 16) |
1113                                  (cmd_response[REG_A085_DATA_INDEX + 1] << 8) |
1114                                  (cmd_response[REG_A085_DATA_INDEX]));
1115 
1116   cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX2] = 0x9E;
1117   if (NFCSTATUS_SUCCESS != phNxpNciHal_send_ext_cmd(cmd_get_rfconfval.size(),
1118                                                     &cmd_get_rfconfval[0])) {
1119     NXPLOG_NCIHAL_E("%s : Get config failed for A09E", __FUNCTION__);
1120     return false;
1121   }
1122   if (GET_RES_STATUS_CHECK(nxpncihal_ctrl.rx_data_len,
1123                            nxpncihal_ctrl.p_rx_data)) {
1124     NXPLOG_NCIHAL_E("%s : Get config failed", __FUNCTION__);
1125     return false;
1126   }
1127   // Updating the A09E get config command response to vector.
1128   lpdet_cmd_response.insert(
1129       lpdet_cmd_response.end(), &nxpncihal_ctrl.p_rx_data[0],
1130       (&nxpncihal_ctrl.p_rx_data[0] +
1131        (nxpncihal_ctrl.p_rx_data[NCI_PACKET_LEN_INDEX] + NCI_HEADER_SIZE)));
1132 
1133   while (getline(key_value_pairs, single_key_value)) {
1134     auto search = single_key_value.find('=');
1135     if (search == string::npos) continue;
1136 
1137     string key(Trim(single_key_value.substr(0, search)));
1138     string value(Trim(single_key_value.substr(search + 1, string::npos)));
1139     ParseUint(value.c_str(), &new_value);
1140     update_mode = BITWISE;
1141     NXPLOG_NCIHAL_D("%s : Update Key = %s Value: %02x", __FUNCTION__,
1142                     key.c_str(), new_value);
1143     auto it = tokenMap.find(key);
1144     if (it != tokenMap.end()) {
1145       condition = it->second;
1146     } else
1147       condition = UPDATE_UNKNOWN;
1148 
1149     switch (condition) {
1150       case UPDATE_DLMA_ID_TX_ENTRY:
1151         cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX1] = 0xA0;
1152         cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX2] = 0x34;
1153         index_to_value = DLMA_ID_TX_ENTRY_INDEX;
1154         break;
1155       case UPDATE_RF_CM_TX_UNDERSHOOT_CONFIG:
1156         if (!phNxpNciHal_getUpdatePropRfSetConfig(new_value, prop_Cmd_Response))
1157           return false;
1158 
1159         if ((nxpncihal_ctrl.rx_data_len > RF_CM_TX_UNDERSHOOT_INDEX) &&
1160             (nxpncihal_ctrl.p_rx_data[RF_CM_TX_UNDERSHOOT_INDEX] !=
1161              new_value)) {
1162           if (!phNxpNciHal_updateRfSetConfig(cmd_set_rfconfval,
1163                                              prop_Cmd_Response))
1164             return false;
1165         }
1166         break;
1167       case UPDATE_INITIAL_TX_PHASE:
1168         cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX1] = 0xA0;
1169         cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX2] = 0x6A;
1170         index_to_value = INITIAL_TX_PHASE_INDEX;
1171         update_mode = BYTEWISE;
1172         break;
1173       case UPDATE_LPDET_THRESHOLD:
1174         read_value = 0;
1175         read_value = lpdet_cmd_response[LPDET_THRESHOLD_INDEX];
1176         read_value |= (lpdet_cmd_response[LPDET_THRESHOLD_INDEX + 1] << 8);
1177         NXPLOG_NCIHAL_D("%s : read_value = %02x Value: %02x", __FUNCTION__,
1178                         read_value, new_value);
1179         if (read_value != new_value) {
1180           lpdet_cmd_response[LPDET_THRESHOLD_INDEX] =
1181               (uint8_t)(new_value & BYTE0_SHIFT_MASK);
1182           lpdet_cmd_response[LPDET_THRESHOLD_INDEX + 1] =
1183               (uint8_t)((new_value & BYTE1_SHIFT_MASK) >> 8);
1184           is_lpdet_threshold_required = true;
1185         }
1186         break;
1187       case UPDATE_NFCLD_THRESHOLD:
1188         read_value = 0;
1189         read_value = lpdet_cmd_response[NFCLD_THRESHOLD_INDEX];
1190         read_value |= (lpdet_cmd_response[NFCLD_THRESHOLD_INDEX + 1] << 8);
1191         NXPLOG_NCIHAL_D("%s : read_value = %02x Value: %02x", __FUNCTION__,
1192                         read_value, new_value);
1193         if (read_value != new_value) {
1194           lpdet_cmd_response[NFCLD_THRESHOLD_INDEX] =
1195               (uint8_t)(new_value & BYTE0_SHIFT_MASK);
1196           lpdet_cmd_response[NFCLD_THRESHOLD_INDEX + 1] =
1197               (uint8_t)((new_value & BYTE1_SHIFT_MASK) >> 8);
1198           is_lpdet_threshold_required = true;
1199         }
1200         break;
1201       case UPDATE_GUARD_TIMEOUT_TX2RX:
1202         cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX1] = 0xA1;
1203         cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX2] = 0x0E;
1204         index_to_value = GUARD_TIMEOUT_TX2RX_INDEX;
1205         break;
1206       case UPDATE_RF_PATTERN_CHK:
1207         cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX1] = 0xA1;
1208         cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX2] = 0x48;
1209         index_to_value = RF_PATTERN_CHK_INDEX;
1210         break;
1211       case UPDATE_MIFARE_NACK_TO_RATS_ENABLE:
1212       case UPDATE_MIFARE_MUTE_TO_RATS_ENABLE:
1213       case UPDATE_CHINA_TIANJIN_RF_ENABLED:
1214       case UPDATE_CN_TRANSIT_CMA_BYPASSMODE_ENABLE:
1215       case UPDATE_CN_TRANSIT_BLK_NUM_CHECK_ENABLE: {
1216         auto itReg = rfReg_A085_Map.find(condition);
1217         if (itReg == rfReg_A085_Map.end()) continue;
1218 
1219         NXPLOG_NCIHAL_D("%s : Reg A085 Update Key = %s and Bit Position: %d",
1220                         __FUNCTION__, key.c_str(), itReg->second);
1221         b_position = (unsigned)(0x01 << itReg->second);
1222         if ((rf_reg_A085_value & b_position) !=
1223             ((new_value & 0x01) << itReg->second)) {
1224           rf_reg_A085_value ^= (1 << itReg->second);
1225           is_feature_update_required = true;
1226         }
1227       } break;
1228       case UPDATE_PHONEOFF_TECH_DISABLE:
1229         cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX1] = 0xA1;
1230         cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX2] = 0x1A;
1231         index_to_value = PHONEOFF_TECH_DISABLE_INDEX;
1232         break;
1233       case UPDATE_ISO_DEP_MERGE_SAK:
1234         cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX1] = 0xA1;
1235         cmd_get_rfconfval[NCI_GET_CMD_TLV_INDEX2] = 0x1B;
1236         index_to_value = ISO_DEP_MERGE_SAK_INDEX;
1237         break;
1238       default:
1239         NXPLOG_NCIHAL_D("%s : default = %x", __FUNCTION__, new_value);
1240         break;
1241     }
1242     if (index_to_value) {
1243       if (NFCSTATUS_SUCCESS !=
1244           phNxpNciHal_send_ext_cmd(cmd_get_rfconfval.size(),
1245                                    &cmd_get_rfconfval[0])) {
1246         NXPLOG_NCIHAL_E("%s : Get config failed for %s", __FUNCTION__,
1247                         key.c_str());
1248         return false;
1249       }
1250       if (GET_RES_STATUS_CHECK(nxpncihal_ctrl.rx_data_len,
1251                                nxpncihal_ctrl.p_rx_data)) {
1252         NXPLOG_NCIHAL_E("%s : Get config response failed ", __FUNCTION__);
1253         return false;
1254       }
1255       read_value = 0;
1256       read_value = nxpncihal_ctrl.p_rx_data[index_to_value];
1257       if (update_mode == BYTEWISE)
1258         read_value |= (nxpncihal_ctrl.p_rx_data[index_to_value + 1] << 8);
1259       if (read_value == new_value) {
1260         index_to_value = 0;
1261         continue;
1262       }
1263       nxpncihal_ctrl.p_rx_data[index_to_value] =
1264           (uint8_t)(new_value & BYTE0_SHIFT_MASK);
1265       if (update_mode == BYTEWISE)
1266         nxpncihal_ctrl.p_rx_data[index_to_value + 1] =
1267             (uint8_t)((new_value & BYTE1_SHIFT_MASK) >> 8);
1268 
1269       // Updating the get config command response to vector.
1270       get_cmd_response.insert(
1271           get_cmd_response.end(), &nxpncihal_ctrl.p_rx_data[0],
1272           (&nxpncihal_ctrl.p_rx_data[0] +
1273            (nxpncihal_ctrl.p_rx_data[NCI_PACKET_LEN_INDEX] + NCI_HEADER_SIZE)));
1274       if (!phNxpNciHal_updateRfSetConfig(cmd_set_rfconfval, get_cmd_response))
1275         return false;
1276 
1277       get_cmd_response.clear();
1278       index_to_value = 0;
1279     }
1280   }
1281   if (is_feature_update_required) {
1282     // Updating the A085 response to set config command.
1283     cmd_response[REG_A085_DATA_INDEX + 3] =
1284         (uint8_t)((rf_reg_A085_value & BYTE3_SHIFT_MASK) >> 24);
1285     cmd_response[REG_A085_DATA_INDEX + 2] =
1286         (uint8_t)((rf_reg_A085_value & BYTE2_SHIFT_MASK) >> 16);
1287     cmd_response[REG_A085_DATA_INDEX + 1] =
1288         (uint8_t)((rf_reg_A085_value & BYTE1_SHIFT_MASK) >> 8);
1289     cmd_response[REG_A085_DATA_INDEX] =
1290         (uint8_t)(rf_reg_A085_value & BYTE0_SHIFT_MASK);
1291     if (!phNxpNciHal_updateRfSetConfig(cmd_set_rfconfval, cmd_response))
1292       return false;
1293   }
1294   if (is_lpdet_threshold_required) {
1295     // Updating the A09E response to set config command.
1296     if (!phNxpNciHal_updateRfSetConfig(cmd_set_rfconfval, lpdet_cmd_response))
1297       return false;
1298   }
1299   if (cmd_set_rfconfval.size() <= NCI_HEADER_SIZE) {
1300     NXPLOG_NCIHAL_E("%s : Invalid NCI Command length = %zu", __FUNCTION__,
1301                     cmd_set_rfconfval.size());
1302     return false;
1303   }
1304   if (cmd_set_rfconfval[NCI_PACKET_TLV_INDEX] != 0x00) {
1305     /*If update require do set-config in NFCC otherwise skip */
1306     if (NFCSTATUS_SUCCESS == phNxpNciHal_send_ext_cmd(cmd_set_rfconfval.size(),
1307                                                       &cmd_set_rfconfval[0])) {
1308       if (is_feature_update_required) {
1309         if (NFCSTATUS_SUCCESS != phNxpNciHal_ext_send_sram_config_to_flash()) {
1310           NXPLOG_NCIHAL_E("%s :Updation of the SRAM contents failed",
1311                           __FUNCTION__);
1312           return false;
1313         }
1314       }
1315     } else {
1316       NXPLOG_NCIHAL_D("Set RF update cmd  is failed..");
1317       return false;
1318     }
1319   }
1320   return true;
1321 }
1322