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