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