1 /****************************************************************************** 2 * 3 * Copyright (C) 2011-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 /****************************************************************************** 20 * 21 * The original Work has been changed by NXP Semiconductors. 22 * 23 * Copyright (C) 2013-2014 NXP Semiconductors 24 * 25 * Licensed under the Apache License, Version 2.0 (the "License"); 26 * you may not use this file except in compliance with the License. 27 * You may obtain a copy of the License at 28 * 29 * http://www.apache.org/licenses/LICENSE-2.0 30 * 31 * Unless required by applicable law or agreed to in writing, software 32 * distributed under the License is distributed on an "AS IS" BASIS, 33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 34 * See the License for the specific language governing permissions and 35 * limitations under the License. 36 * 37 ******************************************************************************/ 38 39 #include <stdio.h> 40 #include <sys/stat.h> 41 #include <list> 42 #include <string> 43 #include <vector> 44 45 #include <phNxpConfig.h> 46 #include <phNxpLog.h> 47 #include "sparse_crc32.h" 48 49 #if GENERIC_TARGET 50 const char alternative_config_path[] = "/data/vendor/nfc/"; 51 #else 52 const char alternative_config_path[] = ""; 53 #endif 54 55 #if 1 56 const char* transport_config_paths[] = {"/odm/etc/", "/vendor/etc/", "/etc/"}; 57 #else 58 const char* transport_config_paths[] = {"res/"}; 59 #endif 60 const int transport_config_path_size = 61 (sizeof(transport_config_paths) / sizeof(transport_config_paths[0])); 62 63 #define config_name "libnfc-nxp.conf" 64 #define extra_config_base "libnfc-nxp-" 65 #define extra_config_ext ".conf" 66 #define IsStringValue 0x80000000 67 68 const char config_timestamp_path[] = 69 "/data/vendor/nfc/libnfc-nxpConfigState.bin"; 70 71 namespace { 72 73 size_t readConfigFile(const char* fileName, uint8_t** p_data) { 74 FILE* fd = fopen(fileName, "rb"); 75 if (fd == nullptr) return 0; 76 77 fseek(fd, 0L, SEEK_END); 78 const size_t file_size = ftell(fd); 79 rewind(fd); 80 81 uint8_t* buffer = new uint8_t[file_size]; 82 size_t read = fread(buffer, file_size, 1, fd); 83 fclose(fd); 84 85 if (read == 1) { 86 *p_data = buffer; 87 return file_size; 88 } 89 90 return 0; 91 } 92 93 } // namespace 94 95 using namespace ::std; 96 97 class CNfcParam : public string { 98 public: 99 CNfcParam(); 100 CNfcParam(const char* name, const string& value); 101 CNfcParam(const char* name, unsigned long value); 102 virtual ~CNfcParam(); 103 unsigned long numValue() const { return m_numValue; } 104 const char* str_value() const { return m_str_value.c_str(); } 105 size_t str_len() const { return m_str_value.length(); } 106 107 private: 108 string m_str_value; 109 unsigned long m_numValue; 110 }; 111 112 class CNfcConfig : public vector<const CNfcParam*> { 113 public: 114 virtual ~CNfcConfig(); 115 static CNfcConfig& GetInstance(); 116 friend void readOptionalConfig(const char* optional); 117 bool isModified(); 118 void resetModified(); 119 120 bool getValue(const char* name, char* pValue, size_t len) const; 121 bool getValue(const char* name, unsigned long& rValue) const; 122 bool getValue(const char* name, unsigned short& rValue) const; 123 bool getValue(const char* name, char* pValue, long len, long* readlen) const; 124 const CNfcParam* find(const char* p_name) const; 125 void clean(); 126 127 private: 128 CNfcConfig(); 129 bool readConfig(const char* name, bool bResetContent); 130 void moveFromList(); 131 void moveToList(); 132 void add(const CNfcParam* pParam); 133 list<const CNfcParam*> m_list; 134 bool mValidFile; 135 uint32_t config_crc32_; 136 137 unsigned long state; 138 139 inline bool Is(unsigned long f) { return (state & f) == f; } 140 inline void Set(unsigned long f) { state |= f; } 141 inline void Reset(unsigned long f) { state &= ~f; } 142 }; 143 144 /******************************************************************************* 145 ** 146 ** Function: isPrintable() 147 ** 148 ** Description: determine if 'c' is printable 149 ** 150 ** Returns: 1, if printable, otherwise 0 151 ** 152 *******************************************************************************/ 153 inline bool isPrintable(char c) { 154 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || 155 (c >= '0' && c <= '9') || c == '/' || c == '_' || c == '-' || c == '.'; 156 } 157 158 /******************************************************************************* 159 ** 160 ** Function: isDigit() 161 ** 162 ** Description: determine if 'c' is numeral digit 163 ** 164 ** Returns: true, if numerical digit 165 ** 166 *******************************************************************************/ 167 inline bool isDigit(char c, int base) { 168 if ('0' <= c && c <= '9') return true; 169 if (base == 16) { 170 if (('A' <= c && c <= 'F') || ('a' <= c && c <= 'f')) return true; 171 } 172 return false; 173 } 174 175 /******************************************************************************* 176 ** 177 ** Function: getDigitValue() 178 ** 179 ** Description: return numerical value of a decimal or hex char 180 ** 181 ** Returns: numerical value if decimal or hex char, otherwise 0 182 ** 183 *******************************************************************************/ 184 inline int getDigitValue(char c, int base) { 185 if ('0' <= c && c <= '9') return c - '0'; 186 if (base == 16) { 187 if ('A' <= c && c <= 'F') 188 return c - 'A' + 10; 189 else if ('a' <= c && c <= 'f') 190 return c - 'a' + 10; 191 } 192 return 0; 193 } 194 195 /******************************************************************************* 196 ** 197 ** Function: findConfigFilePathFromTransportConfigPaths() 198 ** 199 ** Description: find a config file path with a given config name from transport 200 ** config paths 201 ** 202 ** Returns: none 203 ** 204 *******************************************************************************/ 205 void findConfigFilePathFromTransportConfigPaths(const string& configName, 206 string& filePath) { 207 for (int i = 0; i < transport_config_path_size - 1; i++) { 208 filePath.assign(transport_config_paths[i]); 209 filePath += configName; 210 struct stat file_stat; 211 if (stat(filePath.c_str(), &file_stat) == 0 && S_ISREG(file_stat.st_mode)) { 212 return; 213 } 214 } 215 filePath.assign(transport_config_paths[transport_config_path_size - 1]); 216 filePath += configName; 217 } 218 219 /******************************************************************************* 220 ** 221 ** Function: CNfcConfig::readConfig() 222 ** 223 ** Description: read Config settings and parse them into a linked list 224 ** move the element from linked list to a array at the end 225 ** 226 ** Returns: 1, if there are any config data, 0 otherwise 227 ** 228 *******************************************************************************/ 229 bool CNfcConfig::readConfig(const char* name, bool bResetContent) { 230 enum { 231 BEGIN_LINE = 1, 232 TOKEN, 233 STR_VALUE, 234 NUM_VALUE, 235 BEGIN_HEX, 236 BEGIN_QUOTE, 237 END_LINE 238 }; 239 240 uint8_t* p_config = nullptr; 241 size_t config_size = readConfigFile(name, &p_config); 242 if (p_config == nullptr) { 243 ALOGE("%s Cannot open config file %s\n", __func__, name); 244 if (bResetContent) { 245 ALOGE("%s Using default value for all settings\n", __func__); 246 mValidFile = false; 247 } 248 return false; 249 } 250 251 string token; 252 string strValue; 253 unsigned long numValue = 0; 254 CNfcParam* pParam = NULL; 255 int i = 0; 256 int base = 0; 257 char c; 258 int bflag = 0; 259 state = BEGIN_LINE; 260 261 config_crc32_ = sparse_crc32(0, p_config, config_size); 262 mValidFile = true; 263 if (size() > 0) { 264 if (bResetContent) 265 clean(); 266 else 267 moveToList(); 268 } 269 270 for (size_t offset = 0; offset != config_size; ++offset) { 271 c = p_config[offset]; 272 switch (state & 0xff) { 273 case BEGIN_LINE: 274 if (c == '#') 275 state = END_LINE; 276 else if (isPrintable(c)) { 277 i = 0; 278 token.erase(); 279 strValue.erase(); 280 state = TOKEN; 281 token.push_back(c); 282 } 283 break; 284 case TOKEN: 285 if (c == '=') { 286 token.push_back('\0'); 287 state = BEGIN_QUOTE; 288 } else if (isPrintable(c)) 289 token.push_back(c); 290 else 291 state = END_LINE; 292 break; 293 case BEGIN_QUOTE: 294 if (c == '"') { 295 state = STR_VALUE; 296 base = 0; 297 } else if (c == '0') 298 state = BEGIN_HEX; 299 else if (isDigit(c, 10)) { 300 state = NUM_VALUE; 301 base = 10; 302 numValue = getDigitValue(c, base); 303 i = 0; 304 } else if (c == '{') { 305 state = NUM_VALUE; 306 bflag = 1; 307 base = 16; 308 i = 0; 309 Set(IsStringValue); 310 } else 311 state = END_LINE; 312 break; 313 case BEGIN_HEX: 314 if (c == 'x' || c == 'X') { 315 state = NUM_VALUE; 316 base = 16; 317 numValue = 0; 318 i = 0; 319 break; 320 } else if (isDigit(c, 10)) { 321 state = NUM_VALUE; 322 base = 10; 323 numValue = getDigitValue(c, base); 324 break; 325 } else if (c != '\n' && c != '\r') { 326 state = END_LINE; 327 break; 328 } 329 // fall through to numValue to handle numValue 330 331 case NUM_VALUE: 332 if (isDigit(c, base)) { 333 numValue *= base; 334 numValue += getDigitValue(c, base); 335 ++i; 336 } else if (bflag == 1 && 337 (c == ' ' || c == '\r' || c == '\n' || c == '\t')) { 338 break; 339 } else if (base == 16 && 340 (c == ',' || c == ':' || c == '-' || c == ' ' || c == '}')) { 341 if (c == '}') { 342 bflag = 0; 343 } 344 if (i > 0) { 345 int n = (i + 1) / 2; 346 while (n-- > 0) { 347 numValue = numValue >> (n * 8); 348 unsigned char c = (numValue)&0xFF; 349 strValue.push_back(c); 350 } 351 } 352 353 Set(IsStringValue); 354 numValue = 0; 355 i = 0; 356 } else { 357 if (c == '\n' || c == '\r') { 358 if (bflag == 0) { 359 state = BEGIN_LINE; 360 } 361 } else { 362 if (bflag == 0) { 363 state = END_LINE; 364 } 365 } 366 if (Is(IsStringValue) && base == 16 && i > 0) { 367 int n = (i + 1) / 2; 368 while (n-- > 0) strValue.push_back(((numValue >> (n * 8)) & 0xFF)); 369 } 370 if (strValue.length() > 0) 371 pParam = new CNfcParam(token.c_str(), strValue); 372 else 373 pParam = new CNfcParam(token.c_str(), numValue); 374 add(pParam); 375 strValue.erase(); 376 numValue = 0; 377 } 378 break; 379 case STR_VALUE: 380 if (c == '"') { 381 strValue.push_back('\0'); 382 state = END_LINE; 383 pParam = new CNfcParam(token.c_str(), strValue); 384 add(pParam); 385 } else if (isPrintable(c)) 386 strValue.push_back(c); 387 break; 388 case END_LINE: 389 if (c == '\n' || c == '\r') state = BEGIN_LINE; 390 break; 391 default: 392 break; 393 } 394 } 395 396 delete[] p_config; 397 398 moveFromList(); 399 return size() > 0; 400 } 401 402 /******************************************************************************* 403 ** 404 ** Function: CNfcConfig::CNfcConfig() 405 ** 406 ** Description: class constructor 407 ** 408 ** Returns: none 409 ** 410 *******************************************************************************/ 411 CNfcConfig::CNfcConfig() : mValidFile(true), state(0) {} 412 413 /******************************************************************************* 414 ** 415 ** Function: CNfcConfig::~CNfcConfig() 416 ** 417 ** Description: class destructor 418 ** 419 ** Returns: none 420 ** 421 *******************************************************************************/ 422 CNfcConfig::~CNfcConfig() {} 423 424 /******************************************************************************* 425 ** 426 ** Function: CNfcConfig::GetInstance() 427 ** 428 ** Description: get class singleton object 429 ** 430 ** Returns: none 431 ** 432 *******************************************************************************/ 433 CNfcConfig& CNfcConfig::GetInstance() { 434 static CNfcConfig theInstance; 435 436 if (theInstance.size() == 0 && theInstance.mValidFile) { 437 string strPath; 438 if (alternative_config_path[0] != '\0') { 439 strPath.assign(alternative_config_path); 440 strPath += config_name; 441 theInstance.readConfig(strPath.c_str(), true); 442 if (!theInstance.empty()) { 443 return theInstance; 444 } 445 } 446 findConfigFilePathFromTransportConfigPaths(config_name, strPath); 447 theInstance.readConfig(strPath.c_str(), true); 448 } 449 450 return theInstance; 451 } 452 453 /******************************************************************************* 454 ** 455 ** Function: CNfcConfig::getValue() 456 ** 457 ** Description: get a string value of a setting 458 ** 459 ** Returns: true if setting exists 460 ** false if setting does not exist 461 ** 462 *******************************************************************************/ 463 bool CNfcConfig::getValue(const char* name, char* pValue, size_t len) const { 464 const CNfcParam* pParam = find(name); 465 if (pParam == NULL) return false; 466 467 if (pParam->str_len() > 0) { 468 memset(pValue, 0, len); 469 memcpy(pValue, pParam->str_value(), pParam->str_len()); 470 return true; 471 } 472 return false; 473 } 474 475 bool CNfcConfig::getValue(const char* name, char* pValue, long len, 476 long* readlen) const { 477 const CNfcParam* pParam = find(name); 478 if (pParam == NULL) return false; 479 480 if (pParam->str_len() > 0) { 481 if (pParam->str_len() <= (unsigned long)len) { 482 memset(pValue, 0, len); 483 memcpy(pValue, pParam->str_value(), pParam->str_len()); 484 *readlen = pParam->str_len(); 485 } else { 486 *readlen = -1; 487 } 488 489 return true; 490 } 491 return false; 492 } 493 494 /******************************************************************************* 495 ** 496 ** Function: CNfcConfig::getValue() 497 ** 498 ** Description: get a long numerical value of a setting 499 ** 500 ** Returns: true if setting exists 501 ** false if setting does not exist 502 ** 503 *******************************************************************************/ 504 bool CNfcConfig::getValue(const char* name, unsigned long& rValue) const { 505 const CNfcParam* pParam = find(name); 506 if (pParam == NULL) return false; 507 508 if (pParam->str_len() == 0) { 509 rValue = static_cast<unsigned long>(pParam->numValue()); 510 return true; 511 } 512 return false; 513 } 514 515 /******************************************************************************* 516 ** 517 ** Function: CNfcConfig::getValue() 518 ** 519 ** Description: get a short numerical value of a setting 520 ** 521 ** Returns: true if setting exists 522 ** false if setting does not exist 523 ** 524 *******************************************************************************/ 525 bool CNfcConfig::getValue(const char* name, unsigned short& rValue) const { 526 const CNfcParam* pParam = find(name); 527 if (pParam == NULL) return false; 528 529 if (pParam->str_len() == 0) { 530 rValue = static_cast<unsigned short>(pParam->numValue()); 531 return true; 532 } 533 return false; 534 } 535 536 /******************************************************************************* 537 ** 538 ** Function: CNfcConfig::find() 539 ** 540 ** Description: search if a setting exist in the setting array 541 ** 542 ** Returns: pointer to the setting object 543 ** 544 *******************************************************************************/ 545 const CNfcParam* CNfcConfig::find(const char* p_name) const { 546 if (size() == 0) return NULL; 547 548 for (const_iterator it = begin(), itEnd = end(); it != itEnd; ++it) { 549 if (**it < p_name) { 550 continue; 551 } else if (**it == p_name) { 552 if ((*it)->str_len() > 0) { 553 NXPLOG_EXTNS_D("%s found %s=%s\n", __func__, p_name, 554 (*it)->str_value()); 555 } else { 556 NXPLOG_EXTNS_D("%s found %s=(0x%lx)\n", __func__, p_name, 557 (*it)->numValue()); 558 } 559 return *it; 560 } else 561 break; 562 } 563 return NULL; 564 } 565 566 /******************************************************************************* 567 ** 568 ** Function: CNfcConfig::clean() 569 ** 570 ** Description: reset the setting array 571 ** 572 ** Returns: none 573 ** 574 *******************************************************************************/ 575 void CNfcConfig::clean() { 576 if (size() == 0) return; 577 578 for (iterator it = begin(), itEnd = end(); it != itEnd; ++it) delete *it; 579 clear(); 580 } 581 582 /******************************************************************************* 583 ** 584 ** Function: CNfcConfig::Add() 585 ** 586 ** Description: add a setting object to the list 587 ** 588 ** Returns: none 589 ** 590 *******************************************************************************/ 591 void CNfcConfig::add(const CNfcParam* pParam) { 592 if (m_list.size() == 0) { 593 m_list.push_back(pParam); 594 return; 595 } 596 for (list<const CNfcParam *>::iterator it = m_list.begin(), 597 itEnd = m_list.end(); 598 it != itEnd; ++it) { 599 if (**it < pParam->c_str()) continue; 600 m_list.insert(it, pParam); 601 return; 602 } 603 m_list.push_back(pParam); 604 } 605 606 /******************************************************************************* 607 ** 608 ** Function: CNfcConfig::moveFromList() 609 ** 610 ** Description: move the setting object from list to array 611 ** 612 ** Returns: none 613 ** 614 *******************************************************************************/ 615 void CNfcConfig::moveFromList() { 616 if (m_list.size() == 0) return; 617 618 for (list<const CNfcParam *>::iterator it = m_list.begin(), 619 itEnd = m_list.end(); 620 it != itEnd; ++it) 621 push_back(*it); 622 m_list.clear(); 623 } 624 625 /******************************************************************************* 626 ** 627 ** Function: CNfcConfig::moveToList() 628 ** 629 ** Description: move the setting object from array to list 630 ** 631 ** Returns: none 632 ** 633 *******************************************************************************/ 634 void CNfcConfig::moveToList() { 635 if (m_list.size() != 0) m_list.clear(); 636 637 for (iterator it = begin(), itEnd = end(); it != itEnd; ++it) 638 m_list.push_back(*it); 639 clear(); 640 } 641 642 bool CNfcConfig::isModified() { 643 FILE* fd = fopen(config_timestamp_path, "r+"); 644 if (fd == nullptr) { 645 ALOGE("%s Unable to open file '%s' - assuming modified", __func__, 646 config_timestamp_path); 647 return true; 648 } 649 650 uint32_t stored_crc32 = 0; 651 fread(&stored_crc32, sizeof(uint32_t), 1, fd); 652 fclose(fd); 653 654 return stored_crc32 != config_crc32_; 655 } 656 657 void CNfcConfig::resetModified() { 658 FILE* fd = fopen(config_timestamp_path, "w+"); 659 if (fd == nullptr) { 660 ALOGE("%s Unable to open file '%s' for writing", __func__, 661 config_timestamp_path); 662 return; 663 } 664 665 fwrite(&config_crc32_, sizeof(uint32_t), 1, fd); 666 fclose(fd); 667 } 668 669 /******************************************************************************* 670 ** 671 ** Function: CNfcParam::CNfcParam() 672 ** 673 ** Description: class constructor 674 ** 675 ** Returns: none 676 ** 677 *******************************************************************************/ 678 CNfcParam::CNfcParam() : m_numValue(0) {} 679 680 /******************************************************************************* 681 ** 682 ** Function: CNfcParam::~CNfcParam() 683 ** 684 ** Description: class destructor 685 ** 686 ** Returns: none 687 ** 688 *******************************************************************************/ 689 CNfcParam::~CNfcParam() {} 690 691 /******************************************************************************* 692 ** 693 ** Function: CNfcParam::CNfcParam() 694 ** 695 ** Description: class copy constructor 696 ** 697 ** Returns: none 698 ** 699 *******************************************************************************/ 700 CNfcParam::CNfcParam(const char* name, const string& value) 701 : string(name), m_str_value(value), m_numValue(0) {} 702 703 /******************************************************************************* 704 ** 705 ** Function: CNfcParam::CNfcParam() 706 ** 707 ** Description: class copy constructor 708 ** 709 ** Returns: none 710 ** 711 *******************************************************************************/ 712 CNfcParam::CNfcParam(const char* name, unsigned long value) 713 : string(name), m_numValue(value) {} 714 715 /******************************************************************************* 716 ** 717 ** Function: GetStrValue 718 ** 719 ** Description: API function for getting a string value of a setting 720 ** 721 ** Returns: True if found, otherwise False. 722 ** 723 *******************************************************************************/ 724 extern "C" int GetNxpStrValue(const char* name, char* pValue, 725 unsigned long len) { 726 CNfcConfig& rConfig = CNfcConfig::GetInstance(); 727 728 return rConfig.getValue(name, pValue, len); 729 } 730 731 /******************************************************************************* 732 ** 733 ** Function: GetByteArrayValue() 734 ** 735 ** Description: Read byte array value from the config file. 736 ** 737 ** Parameters: 738 ** name - name of the config param to read. 739 ** pValue - pointer to input buffer. 740 ** bufflen - input buffer length. 741 ** len - out parameter to return the number of bytes read from 742 ** config file, return -1 in case bufflen is not enough. 743 ** 744 ** Returns: TRUE[1] if config param name is found in the config file, else 745 ** FALSE[0] 746 ** 747 *******************************************************************************/ 748 extern "C" int GetNxpByteArrayValue(const char* name, char* pValue, 749 long bufflen, long* len) { 750 CNfcConfig& rConfig = CNfcConfig::GetInstance(); 751 752 return rConfig.getValue(name, pValue, bufflen, len); 753 } 754 755 /******************************************************************************* 756 ** 757 ** Function: GetNumValue 758 ** 759 ** Description: API function for getting a numerical value of a setting 760 ** 761 ** Returns: true, if successful 762 ** 763 *******************************************************************************/ 764 extern "C" int GetNxpNumValue(const char* name, void* pValue, 765 unsigned long len) { 766 if (!pValue) return false; 767 768 CNfcConfig& rConfig = CNfcConfig::GetInstance(); 769 const CNfcParam* pParam = rConfig.find(name); 770 771 if (pParam == NULL) return false; 772 unsigned long v = pParam->numValue(); 773 if (v == 0 && pParam->str_len() > 0 && pParam->str_len() < 4) { 774 const unsigned char* p = (const unsigned char*)pParam->str_value(); 775 for (unsigned int i = 0; i < pParam->str_len(); ++i) { 776 v *= 256; 777 v += *p++; 778 } 779 } 780 switch (len) { 781 case sizeof(unsigned long): 782 *(static_cast<unsigned long*>(pValue)) = (unsigned long)v; 783 break; 784 case sizeof(unsigned short): 785 *(static_cast<unsigned short*>(pValue)) = (unsigned short)v; 786 break; 787 case sizeof(unsigned char): 788 *(static_cast<unsigned char*>(pValue)) = (unsigned char)v; 789 break; 790 default: 791 return false; 792 } 793 return true; 794 } 795 796 /******************************************************************************* 797 ** 798 ** Function: resetConfig 799 ** 800 ** Description: reset settings array 801 ** 802 ** Returns: none 803 ** 804 *******************************************************************************/ 805 extern "C" void resetNxpConfig() 806 807 { 808 CNfcConfig& rConfig = CNfcConfig::GetInstance(); 809 810 rConfig.clean(); 811 } 812 813 /******************************************************************************* 814 ** 815 ** Function: readOptionalConfig() 816 ** 817 ** Description: read Config settings from an optional conf file 818 ** 819 ** Returns: none 820 ** 821 *******************************************************************************/ 822 void readOptionalConfig(const char* extra) { 823 string strPath; 824 string configName(extra_config_base); 825 configName += extra; 826 configName += extra_config_ext; 827 828 if (alternative_config_path[0] != '\0') { 829 strPath.assign(alternative_config_path); 830 strPath += configName; 831 } else { 832 findConfigFilePathFromTransportConfigPaths(configName, strPath); 833 } 834 835 CNfcConfig::GetInstance().readConfig(strPath.c_str(), false); 836 } 837 838 /******************************************************************************* 839 ** 840 ** Function: isNxpConfigModified() 841 ** 842 ** Description: check if config file has modified 843 ** 844 ** Returns: 0 if not modified, 1 otherwise. 845 ** 846 *******************************************************************************/ 847 extern "C" int isNxpConfigModified() { 848 CNfcConfig& rConfig = CNfcConfig::GetInstance(); 849 return rConfig.isModified(); 850 } 851 852 /******************************************************************************* 853 ** 854 ** Function: updateNxpConfigTimestamp() 855 ** 856 ** Description: update if config file has modified 857 ** 858 ** Returns: 0 if not modified, 1 otherwise. 859 ** 860 *******************************************************************************/ 861 extern "C" int updateNxpConfigTimestamp() { 862 CNfcConfig& rConfig = CNfcConfig::GetInstance(); 863 rConfig.resetModified(); 864 return 0; 865 } 866