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