| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <phNxpConfig.h> |
| #include <stdio.h> |
| #include <string> |
| #include <vector> |
| #include <list> |
| #include <sys/stat.h> |
| |
| #include <phNxpLog.h> |
| |
| #if GENERIC_TARGET |
| const char alternative_config_path[] = "/data/nfc/"; |
| #else |
| const char alternative_config_path[] = ""; |
| #endif |
| |
| #if 1 |
| const char transport_config_path[] = "/etc/"; |
| #else |
| const char transport_config_path[] = "res/"; |
| #endif |
| |
| #define config_name "libnfc-nxp.conf" |
| #define extra_config_base "libnfc-nxp-" |
| #define extra_config_ext ".conf" |
| #define IsStringValue 0x80000000 |
| |
| const char config_timestamp_path[] = "/data/nfc/libnfc-nxpConfigState.bin"; |
| |
| using namespace::std; |
| |
| class CNxpNfcParam : public string |
| { |
| public: |
| CNxpNfcParam (); |
| CNxpNfcParam (const char* name, const string& value); |
| CNxpNfcParam (const char* name, unsigned long value); |
| virtual ~CNxpNfcParam (); |
| unsigned long numValue () const {return m_numValue;} |
| const char* str_value () const {return m_str_value.c_str();} |
| size_t str_len () const {return m_str_value.length();} |
| private: |
| string m_str_value; |
| unsigned long m_numValue; |
| }; |
| |
| class CNxpNfcConfig : public vector<const CNxpNfcParam*> |
| { |
| public: |
| virtual ~CNxpNfcConfig (); |
| static CNxpNfcConfig& GetInstance (); |
| friend void readOptionalConfig (const char* optional); |
| int checkTimestamp (); |
| |
| bool getValue (const char* name, char* pValue, size_t len) const; |
| bool getValue (const char* name, unsigned long& rValue) const; |
| bool getValue (const char* name, unsigned short & rValue) const; |
| bool getValue (const char* name, char* pValue, long len, long* readlen) const; |
| const CNxpNfcParam* find (const char* p_name) const; |
| void clean (); |
| private: |
| CNxpNfcConfig (); |
| bool readConfig (const char* name, bool bResetContent); |
| void moveFromList (); |
| void moveToList (); |
| void add (const CNxpNfcParam* pParam); |
| list<const CNxpNfcParam*> m_list; |
| bool mValidFile; |
| unsigned long m_timeStamp; |
| |
| unsigned long state; |
| |
| inline bool Is (unsigned long f) {return (state & f) == f;} |
| inline void Set (unsigned long f) {state |= f;} |
| inline void Reset (unsigned long f) {state &= ~f;} |
| }; |
| |
| /******************************************************************************* |
| ** |
| ** Function: isPrintable() |
| ** |
| ** Description: determine if 'c' is printable |
| ** |
| ** Returns: 1, if printable, otherwise 0 |
| ** |
| *******************************************************************************/ |
| inline bool isPrintable (char c) |
| { |
| return (c >= 'A' && c <= 'Z') || |
| (c >= 'a' && c <= 'z') || |
| (c >= '0' && c <= '9') || |
| c == '/' || c == '_' || c == '-' || c == '.'; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: isDigit() |
| ** |
| ** Description: determine if 'c' is numeral digit |
| ** |
| ** Returns: true, if numerical digit |
| ** |
| *******************************************************************************/ |
| inline bool isDigit (char c, int base) |
| { |
| if ('0' <= c && c <= '9') |
| return true; |
| if (base == 16) |
| { |
| if (('A' <= c && c <= 'F') || |
| ('a' <= c && c <= 'f')) |
| return true; |
| } |
| return false; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: getDigitValue() |
| ** |
| ** Description: return numerical value of a decimal or hex char |
| ** |
| ** Returns: numerical value if decimal or hex char, otherwise 0 |
| ** |
| *******************************************************************************/ |
| inline int getDigitValue (char c, int base) |
| { |
| if ('0' <= c && c <= '9') |
| return c - '0'; |
| if (base == 16) |
| { |
| if ('A' <= c && c <= 'F') |
| return c - 'A' + 10; |
| else if ('a' <= c && c <= 'f') |
| return c - 'a' + 10; |
| } |
| return 0; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::readConfig() |
| ** |
| ** Description: read Config settings and parse them into a linked list |
| ** move the element from linked list to a array at the end |
| ** |
| ** Returns: 1, if there are any config data, 0 otherwise |
| ** |
| *******************************************************************************/ |
| bool CNxpNfcConfig::readConfig (const char* name, bool bResetContent) |
| { |
| enum { |
| BEGIN_LINE = 1, |
| TOKEN, |
| STR_VALUE, |
| NUM_VALUE, |
| BEGIN_HEX, |
| BEGIN_QUOTE, |
| END_LINE |
| }; |
| |
| FILE* fd; |
| struct stat buf; |
| string token; |
| string strValue; |
| unsigned long numValue = 0; |
| CNxpNfcParam* pParam = NULL; |
| int i = 0; |
| int base = 0; |
| char c; |
| int bflag = 0; |
| state = BEGIN_LINE; |
| /* open config file, read it into a buffer */ |
| if ((fd = fopen (name, "rb")) == NULL) |
| { |
| ALOGE ("%s Cannot open config file %s\n", __func__, name); |
| if (bResetContent) |
| { |
| ALOGE ("%s Using default value for all settings\n", __func__); |
| mValidFile = false; |
| } |
| return false; |
| } |
| stat (name, &buf); |
| m_timeStamp = (unsigned long) buf.st_mtime; |
| |
| mValidFile = true; |
| if (size() > 0) |
| { |
| if (bResetContent) |
| clean (); |
| else |
| moveToList (); |
| } |
| |
| while (!feof (fd) && fread (&c, 1, 1, fd) == 1) |
| { |
| switch (state & 0xff) |
| { |
| case BEGIN_LINE: |
| if (c == '#') |
| { |
| state = END_LINE; |
| } |
| else if (isPrintable (c)) |
| { |
| i = 0; |
| token.erase (); |
| strValue.erase (); |
| state = TOKEN; |
| token.push_back (c); |
| } |
| break; |
| case TOKEN: |
| if (c == '=') |
| { |
| token.push_back ('\0'); |
| state = BEGIN_QUOTE; |
| } |
| else if (isPrintable (c)) |
| { |
| token.push_back (c); |
| } |
| else |
| { |
| state = END_LINE; |
| } |
| break; |
| case BEGIN_QUOTE: |
| if (c == '"') |
| { |
| state = STR_VALUE; |
| base = 0; |
| } |
| else if (c == '0') |
| { |
| state = BEGIN_HEX; |
| } |
| else if (isDigit (c, 10)) |
| { |
| state = NUM_VALUE; |
| base = 10; |
| numValue = getDigitValue (c, base); |
| i = 0; |
| } |
| else if (c == '{') |
| { |
| state = NUM_VALUE; |
| bflag = 1; |
| base = 16; |
| i = 0; |
| Set (IsStringValue); |
| } |
| else |
| state = END_LINE; |
| |
| break; |
| case BEGIN_HEX: |
| if (c == 'x' || c == 'X') |
| { |
| state = NUM_VALUE; |
| base = 16; |
| numValue = 0; |
| i = 0; |
| break; |
| } |
| else if (isDigit (c, 10)) |
| { |
| state = NUM_VALUE; |
| base = 10; |
| numValue = getDigitValue (c, base); |
| break; |
| } |
| else if (c != '\n' && c != '\r') |
| { |
| state = END_LINE; |
| break; |
| } |
| // fall through to numValue to handle numValue |
| |
| case NUM_VALUE: |
| if (isDigit (c, base)) |
| { |
| numValue *= base; |
| numValue += getDigitValue (c, base); |
| ++i; |
| } |
| else if(bflag == 1 && (c == ' ' || c == '\r' || c=='\n' || c=='\t')) |
| { |
| break; |
| } |
| else if (base == 16 && (c== ','|| c == ':' || c == '-' || c == ' ' || c == '}')) |
| { |
| |
| if( c=='}' ) |
| { |
| bflag = 0; |
| } |
| if (i > 0) |
| { |
| int n = (i+1) / 2; |
| while (n-- > 0) |
| { |
| numValue = numValue >> (n * 8); |
| unsigned char c = (numValue) & 0xFF; |
| strValue.push_back (c); |
| } |
| } |
| |
| Set (IsStringValue); |
| numValue = 0; |
| i = 0; |
| } |
| else |
| { |
| if (c == '\n' || c == '\r') |
| { |
| if (bflag == 0) |
| { |
| state = BEGIN_LINE; |
| } |
| } |
| else |
| { |
| if (bflag == 0) |
| { |
| state = END_LINE; |
| } |
| } |
| if (Is (IsStringValue) && base == 16 && i > 0) |
| { |
| int n = (i+1) / 2; |
| while (n-- > 0) |
| strValue.push_back (((numValue >> (n * 8)) & 0xFF)); |
| } |
| if (strValue.length() > 0) |
| pParam = new CNxpNfcParam (token.c_str (), strValue); |
| else |
| pParam = new CNxpNfcParam (token.c_str (), numValue); |
| |
| add (pParam); |
| strValue.erase (); |
| numValue = 0; |
| } |
| break; |
| case STR_VALUE: |
| if (c == '"') |
| { |
| strValue.push_back('\0'); |
| state = END_LINE; |
| pParam = new CNxpNfcParam(token.c_str(), strValue); |
| add(pParam); |
| } |
| else if (isPrintable(c)) |
| { |
| strValue.push_back(c); |
| } |
| break; |
| case END_LINE: |
| if (c == '\n' || c == '\r') |
| { |
| state = BEGIN_LINE; |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| |
| fclose (fd); |
| |
| moveFromList (); |
| return size () > 0; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::CNxpNfcConfig() |
| ** |
| ** Description: class constructor |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| CNxpNfcConfig::CNxpNfcConfig () : |
| mValidFile (true), |
| m_timeStamp (0), |
| state (0) |
| { |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::~CNxpNfcConfig() |
| ** |
| ** Description: class destructor |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| CNxpNfcConfig::~CNxpNfcConfig () |
| { |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::GetInstance() |
| ** |
| ** Description: get class singleton object |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| CNxpNfcConfig& CNxpNfcConfig::GetInstance () |
| { |
| static CNxpNfcConfig theInstance; |
| |
| if (theInstance.size () == 0 && theInstance.mValidFile) |
| { |
| string strPath; |
| if (alternative_config_path [0] != '\0') |
| { |
| strPath.assign (alternative_config_path); |
| strPath += config_name; |
| theInstance.readConfig (strPath.c_str (), true); |
| if (!theInstance.empty ()) |
| { |
| return theInstance; |
| } |
| } |
| strPath.assign (transport_config_path); |
| strPath += config_name; |
| theInstance.readConfig (strPath.c_str (), true); |
| } |
| |
| return theInstance; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::getValue() |
| ** |
| ** Description: get a string value of a setting |
| ** |
| ** Returns: true if setting exists |
| ** false if setting does not exist |
| ** |
| *******************************************************************************/ |
| bool CNxpNfcConfig::getValue (const char* name, char* pValue, size_t len) const |
| { |
| const CNxpNfcParam* pParam = find (name); |
| if (pParam == NULL) |
| return false; |
| |
| if (pParam->str_len () > 0) |
| { |
| memset (pValue, 0, len); |
| memcpy (pValue, pParam->str_value (), pParam->str_len ()); |
| return true; |
| } |
| return false; |
| } |
| |
| bool CNxpNfcConfig::getValue (const char* name, char* pValue, long len,long* readlen) const |
| { |
| const CNxpNfcParam* pParam = find (name); |
| if (pParam == NULL) |
| return false; |
| |
| if (pParam->str_len () > 0) |
| { |
| if(pParam->str_len () <= (unsigned long) len) |
| { |
| memset (pValue, 0, len); |
| memcpy (pValue, pParam->str_value (), pParam->str_len ()); |
| *readlen = pParam->str_len (); |
| } |
| else |
| { |
| *readlen = -1; |
| } |
| |
| return true; |
| } |
| return false; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::getValue() |
| ** |
| ** Description: get a long numerical value of a setting |
| ** |
| ** Returns: true if setting exists |
| ** false if setting does not exist |
| ** |
| *******************************************************************************/ |
| bool CNxpNfcConfig::getValue (const char* name, unsigned long& rValue) const |
| { |
| const CNxpNfcParam* pParam = find (name); |
| if (pParam == NULL) |
| return false; |
| |
| if (pParam->str_len () == 0) |
| { |
| rValue = static_cast<unsigned long> (pParam->numValue ()); |
| return true; |
| } |
| return false; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::getValue() |
| ** |
| ** Description: get a short numerical value of a setting |
| ** |
| ** Returns: true if setting exists |
| ** false if setting does not exist |
| ** |
| *******************************************************************************/ |
| bool CNxpNfcConfig::getValue (const char* name, unsigned short& rValue) const |
| { |
| const CNxpNfcParam* pParam = find (name); |
| if (pParam == NULL) |
| return false; |
| |
| if (pParam->str_len () == 0) |
| { |
| rValue = static_cast<unsigned short> (pParam->numValue ()); |
| return true; |
| } |
| return false; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::find() |
| ** |
| ** Description: search if a setting exist in the setting array |
| ** |
| ** Returns: pointer to the setting object |
| ** |
| *******************************************************************************/ |
| const CNxpNfcParam* CNxpNfcConfig::find (const char* p_name) const |
| { |
| if (size () == 0) |
| return NULL; |
| |
| for (const_iterator it = begin (), itEnd = end (); it != itEnd; ++it) |
| { |
| if (**it < p_name) |
| { |
| continue; |
| } |
| else if (**it == p_name) |
| { |
| if ((*it)->str_len () > 0) |
| { |
| NXPLOG_EXTNS_D ("%s found %s=%s\n", __func__, p_name, (*it)->str_value()); |
| } |
| else |
| { |
| NXPLOG_EXTNS_D ("%s found %s=(0x%lx)\n", __func__, p_name, (*it)->numValue()); |
| } |
| return *it; |
| } |
| else |
| break; |
| } |
| return NULL; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::clean() |
| ** |
| ** Description: reset the setting array |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| void CNxpNfcConfig::clean () |
| { |
| if (size () == 0) |
| return; |
| |
| for (iterator it = begin (), itEnd = end (); it != itEnd; ++it) |
| delete *it; |
| |
| clear (); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::Add() |
| ** |
| ** Description: add a setting object to the list |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| void CNxpNfcConfig::add (const CNxpNfcParam* pParam) |
| { |
| if (m_list.size () == 0) |
| { |
| m_list.push_back (pParam); |
| return; |
| } |
| for (list<const CNxpNfcParam*>::iterator it = m_list.begin (), itEnd = m_list.end (); it != itEnd; ++it) |
| { |
| if (**it < pParam->c_str ()) |
| continue; |
| |
| m_list.insert (it, pParam); |
| return; |
| } |
| m_list.push_back (pParam); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::moveFromList() |
| ** |
| ** Description: move the setting object from list to array |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| void CNxpNfcConfig::moveFromList () |
| { |
| if (m_list.size () == 0) |
| return; |
| |
| for (list<const CNxpNfcParam*>::iterator it = m_list.begin (), itEnd = m_list.end (); it != itEnd; ++it) |
| push_back (*it); |
| |
| m_list.clear (); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::moveToList() |
| ** |
| ** Description: move the setting object from array to list |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| void CNxpNfcConfig::moveToList () |
| { |
| if (m_list.size () != 0) |
| m_list.clear (); |
| |
| for (iterator it = begin (), itEnd = end (); it != itEnd; ++it) |
| m_list.push_back (*it); |
| |
| clear(); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcConfig::checkTimestamp() |
| ** |
| ** Description: check if config file has modified |
| ** |
| ** Returns: 0 if not modified, 1 otherwise. |
| ** |
| *******************************************************************************/ |
| int CNxpNfcConfig::checkTimestamp () |
| { |
| FILE* fd; |
| struct stat st; |
| unsigned long value = 0; |
| int ret = 0; |
| |
| if (stat(config_timestamp_path, &st) != 0) |
| { |
| ALOGD ("%s file %s not exist, creat it.\n", __func__, config_timestamp_path); |
| if ((fd = fopen (config_timestamp_path, "w+")) != NULL) |
| { |
| fwrite (&m_timeStamp, sizeof(unsigned long), 1, fd); |
| fclose (fd); |
| } |
| return 1; |
| } |
| else |
| { |
| fd = fopen (config_timestamp_path, "r+"); |
| if (fd == NULL) |
| { |
| ALOGE ("%s Cannot open file %s\n", __func__, config_timestamp_path); |
| return 1; |
| } |
| |
| fread (&value, sizeof(unsigned long), 1, fd); |
| ret = (value != m_timeStamp); |
| if (ret) |
| { |
| fseek (fd, 0, SEEK_SET); |
| fwrite (&m_timeStamp, sizeof(unsigned long), 1, fd); |
| } |
| fclose (fd); |
| } |
| return ret; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcParam::CNxpNfcParam() |
| ** |
| ** Description: class constructor |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| CNxpNfcParam::CNxpNfcParam () : |
| m_numValue (0) |
| { |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcParam::~CNxpNfcParam() |
| ** |
| ** Description: class destructor |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| CNxpNfcParam::~CNxpNfcParam () |
| { |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcParam::CNxpNfcParam() |
| ** |
| ** Description: class copy constructor |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| CNxpNfcParam::CNxpNfcParam (const char* name, const string& value) : |
| string (name), |
| m_str_value (value), |
| m_numValue (0) |
| { |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: CNxpNfcParam::CNxpNfcParam() |
| ** |
| ** Description: class copy constructor |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| CNxpNfcParam::CNxpNfcParam (const char* name, unsigned long value) : |
| string (name), |
| m_numValue (value) |
| { |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: GetStrValue |
| ** |
| ** Description: API function for getting a string value of a setting |
| ** |
| ** Returns: True if found, otherwise False. |
| ** |
| *******************************************************************************/ |
| extern "C" int GetNxpStrValue (const char* name, char* pValue, unsigned long len) |
| { |
| CNxpNfcConfig& rConfig = CNxpNfcConfig::GetInstance (); |
| |
| return rConfig.getValue (name, pValue, len); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: GetByteArrayValue() |
| ** |
| ** Description: Read byte array value from the config file. |
| ** |
| ** Parameters: |
| ** name - name of the config param to read. |
| ** pValue - pointer to input buffer. |
| ** bufflen - input buffer length. |
| ** len - out parameter to return the number of bytes read from config file, |
| ** return -1 in case bufflen is not enough. |
| ** |
| ** Returns: TRUE[1] if config param name is found in the config file, else FALSE[0] |
| ** |
| *******************************************************************************/ |
| extern "C" int GetNxpByteArrayValue (const char* name, char* pValue, long bufflen, long *len) |
| { |
| CNxpNfcConfig& rConfig = CNxpNfcConfig::GetInstance (); |
| |
| return rConfig.getValue (name, pValue, bufflen,len); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: GetNumValue |
| ** |
| ** Description: API function for getting a numerical value of a setting |
| ** |
| ** Returns: true, if successful |
| ** |
| *******************************************************************************/ |
| extern "C" int GetNxpNumValue (const char* name, void* pValue, unsigned long len) |
| { |
| if (!pValue) |
| return false; |
| |
| CNxpNfcConfig& rConfig = CNxpNfcConfig::GetInstance (); |
| const CNxpNfcParam* pParam = rConfig.find (name); |
| |
| if (pParam == NULL) |
| return false; |
| |
| unsigned long v = pParam->numValue (); |
| if (v == 0 && pParam->str_len () > 0 && pParam->str_len () < 4) |
| { |
| const unsigned char* p = (const unsigned char*) pParam->str_value (); |
| for (unsigned int i = 0 ; i < pParam->str_len (); ++i) |
| { |
| v *= 256; |
| v += *p++; |
| } |
| } |
| switch (len) |
| { |
| case sizeof(unsigned long): |
| *(static_cast<unsigned long*>(pValue)) = (unsigned long) v; |
| break; |
| case sizeof(unsigned short): |
| *(static_cast<unsigned short*>(pValue)) = (unsigned short) v; |
| break; |
| case sizeof(unsigned char): |
| *(static_cast<unsigned char*> (pValue)) = (unsigned char) v; |
| break; |
| default: |
| return false; |
| } |
| return true; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: resetConfig |
| ** |
| ** Description: reset settings array |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| extern "C" void resetNxpConfig () |
| { |
| CNxpNfcConfig& rConfig = CNxpNfcConfig::GetInstance (); |
| |
| rConfig.clean (); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: readOptionalConfig() |
| ** |
| ** Description: read Config settings from an optional conf file |
| ** |
| ** Returns: none |
| ** |
| *******************************************************************************/ |
| void readOptionalConfig (const char* extra) |
| { |
| string strPath; |
| strPath.assign (transport_config_path); |
| if (alternative_config_path [0] != '\0') |
| strPath.assign (alternative_config_path); |
| |
| strPath += extra_config_base; |
| strPath += extra; |
| strPath += extra_config_ext; |
| CNxpNfcConfig::GetInstance ().readConfig (strPath.c_str (), false); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function: isNxpConfigModified() |
| ** |
| ** Description: check if config file has modified |
| ** |
| ** Returns: 0 if not modified, 1 otherwise. |
| ** |
| *******************************************************************************/ |
| extern "C" int isNxpConfigModified () |
| { |
| CNxpNfcConfig& rConfig = CNxpNfcConfig::GetInstance (); |
| return rConfig.checkTimestamp (); |
| } |