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