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