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 #include "OverrideLog.h"
19 #include "config.h"
20 #include <stdio.h>
21 #include <string>
22 #include <vector>
23 #include <list>
24
25 #define LOG_TAG "NfcAdaptation"
26
27 const char transport_config_path[] = "/etc/";
28
29 #define config_name "libnfc-brcm.conf"
30 #define extra_config_base "libnfc-brcm-"
31 #define extra_config_ext ".conf"
32 #define IsStringValue 0x80000000
33
34 using namespace::std;
35
36 class CNfcParam : public string
37 {
38 public:
39 CNfcParam();
40 CNfcParam(const char* name, const string& value);
41 CNfcParam(const char* name, unsigned long value);
42 virtual ~CNfcParam();
numValue() const43 unsigned long numValue() const {return m_numValue;}
str_value() const44 const char* str_value() const {return m_str_value.c_str();}
str_len() const45 size_t str_len() const {return m_str_value.length();}
46 private:
47 string m_str_value;
48 unsigned long m_numValue;
49 };
50
51 class CNfcConfig : public vector<const CNfcParam*>
52 {
53 public:
54 virtual ~CNfcConfig();
55 static CNfcConfig& GetInstance();
56 friend void readOptionalConfig(const char* optional);
57
58 bool getValue(const char* name, char* pValue, size_t& len) const;
59 bool getValue(const char* name, unsigned long& rValue) const;
60 bool getValue(const char* name, unsigned short & rValue) const;
61 const CNfcParam* find(const char* p_name) const;
62 void clean();
63 private:
64 CNfcConfig();
65 bool readConfig(const char* name, bool bResetContent);
66 void moveFromList();
67 void moveToList();
68 void add(const CNfcParam* pParam);
69 list<const CNfcParam*> m_list;
70 bool mValidFile;
71
72 unsigned long state;
73
Is(unsigned long f)74 inline bool Is(unsigned long f) {return (state & f) == f;}
Set(unsigned long f)75 inline void Set(unsigned long f) {state |= f;}
Reset(unsigned long f)76 inline void Reset(unsigned long f) {state &= ~f;}
77 };
78
79 /*******************************************************************************
80 **
81 ** Function: isPrintable()
82 **
83 ** Description: detremine if a char is printable
84 **
85 ** Returns: none
86 **
87 *******************************************************************************/
isPrintable(char c)88 inline bool isPrintable(char c)
89 {
90 return (c >= 'A' && c <= 'Z') ||
91 (c >= 'a' && c <= 'z') ||
92 (c >= '0' && c <= '9') ||
93 c == '/' || c == '_' || c == '-' || c == '.';
94 }
95
96 /*******************************************************************************
97 **
98 ** Function: isDigit()
99 **
100 ** Description: detremine if a char is numeral digit
101 **
102 ** Returns: none
103 **
104 *******************************************************************************/
isDigit(char c,int base)105 inline bool isDigit(char c, int base)
106 {
107 if ('0' <= c && c <= '9')
108 return true;
109 if (base == 16)
110 {
111 if (('A' <= c && c <= 'F') ||
112 ('a' <= c && c <= 'f') )
113 return true;
114 }
115 return false;
116 }
117
118 /*******************************************************************************
119 **
120 ** Function: getDigitValue()
121 **
122 ** Description: return numercal value of a char
123 **
124 ** Returns: none
125 **
126 *******************************************************************************/
getDigitValue(char c,int base)127 inline int getDigitValue(char c, int base)
128 {
129 if ('0' <= c && c <= '9')
130 return c - '0';
131 if (base == 16)
132 {
133 if ('A' <= c && c <= 'F')
134 return c - 'A' + 10;
135 else if ('a' <= c && c <= 'f')
136 return c - 'a' + 10;
137 }
138 return 0;
139 }
140
141 /*******************************************************************************
142 **
143 ** Function: CNfcConfig::readConfig()
144 **
145 ** Description: read Config settings and parse them into a linked list
146 ** move the element from linked list to a array at the end
147 **
148 ** Returns: none
149 **
150 *******************************************************************************/
readConfig(const char * name,bool bResetContent)151 bool CNfcConfig::readConfig(const char* name, bool bResetContent)
152 {
153 enum {
154 BEGIN_LINE = 1,
155 TOKEN,
156 STR_VALUE,
157 NUM_VALUE,
158 BEGIN_HEX,
159 BEGIN_QUOTE,
160 END_LINE
161 };
162
163 FILE* fd = NULL;
164 string token;
165 string strValue;
166 unsigned long numValue = 0;
167 CNfcParam* pParam = NULL;
168 int i = 0;
169 int base = 0;
170 char c = 0;
171
172 state = BEGIN_LINE;
173 /* open config file, read it into a buffer */
174 if ((fd = fopen(name, "rb")) == NULL)
175 {
176 ALOGD("%s Cannot open config file %s\n", __func__, name);
177 if (bResetContent)
178 {
179 ALOGD("%s Using default value for all settings\n", __func__);
180 mValidFile = false;
181 }
182 return false;
183 }
184 ALOGD("%s Opened %s config %s\n", __func__, (bResetContent ? "base" : "optional"), name);
185
186 mValidFile = true;
187 if (size() > 0)
188 {
189 if (bResetContent)
190 clean();
191 else
192 moveToList();
193 }
194
195 for (;;)
196 {
197 if (feof(fd) || fread(&c, 1, 1, fd) != 1)
198 {
199 if (state == BEGIN_LINE)
200 break;
201
202 // got to the EOF but not in BEGIN_LINE state so the file
203 // probably does not end with a newline, so the parser has
204 // not processed current line, simulate a newline in the file
205 c = '\n';
206 }
207
208 switch (state & 0xff)
209 {
210 case BEGIN_LINE:
211 if (c == '#')
212 state = END_LINE;
213 else if (isPrintable(c))
214 {
215 i = 0;
216 token.erase();
217 strValue.erase();
218 state = TOKEN;
219 token.push_back(c);
220 }
221 break;
222 case TOKEN:
223 if (c == '=')
224 {
225 token.push_back('\0');
226 state = BEGIN_QUOTE;
227 }
228 else if (isPrintable(c))
229 token.push_back(c);
230 else
231 state = END_LINE;
232 break;
233 case BEGIN_QUOTE:
234 if (c == '"')
235 {
236 state = STR_VALUE;
237 base = 0;
238 }
239 else if (c == '0')
240 state = BEGIN_HEX;
241 else if (isDigit(c, 10))
242 {
243 state = NUM_VALUE;
244 base = 10;
245 numValue = getDigitValue(c, base);
246 i = 0;
247 }
248 else if (c == '{')
249 {
250 state = NUM_VALUE;
251 base = 16;
252 i = 0;
253 Set(IsStringValue);
254 }
255 else
256 state = END_LINE;
257 break;
258 case BEGIN_HEX:
259 if (c == 'x' || c == 'X')
260 {
261 state = NUM_VALUE;
262 base = 16;
263 numValue = 0;
264 i = 0;
265 break;
266 }
267 else if (isDigit(c, 10))
268 {
269 state = NUM_VALUE;
270 base = 10;
271 numValue = getDigitValue(c, base);
272 break;
273 }
274 else if (c != '\n' && c != '\r')
275 {
276 state = END_LINE;
277 break;
278 }
279 // fal through to numValue to handle numValue
280
281 case NUM_VALUE:
282 if (isDigit(c, base))
283 {
284 numValue *= base;
285 numValue += getDigitValue(c, base);
286 ++i;
287 }
288 else if (base == 16 && (c == ':' || c == '-' || c == ' ' || c == '}'))
289 {
290 if (i > 0)
291 {
292 int n = (i+1) / 2;
293 while (n-- > 0)
294 {
295 unsigned char c = (numValue >> (n * 8)) & 0xFF;
296 strValue.push_back(c);
297 }
298 }
299 Set(IsStringValue);
300 numValue = 0;
301 i = 0;
302 }
303 else
304 {
305 if (c == '\n' || c == '\r')
306 state = BEGIN_LINE;
307 else
308 state = END_LINE;
309 if (Is(IsStringValue) && base == 16 && i > 0)
310 {
311 int n = (i+1) / 2;
312 while (n-- > 0)
313 strValue.push_back(((numValue >> (n * 8)) & 0xFF));
314 }
315 if (strValue.length() > 0)
316 pParam = new CNfcParam(token.c_str(), strValue);
317 else
318 pParam = new CNfcParam(token.c_str(), numValue);
319 add(pParam);
320 strValue.erase();
321 numValue = 0;
322 }
323 break;
324 case STR_VALUE:
325 if (c == '"')
326 {
327 strValue.push_back('\0');
328 state = END_LINE;
329 pParam = new CNfcParam(token.c_str(), strValue);
330 add(pParam);
331 }
332 else if (isPrintable(c))
333 strValue.push_back(c);
334 break;
335 case END_LINE:
336 if (c == '\n' || c == '\r')
337 state = BEGIN_LINE;
338 break;
339 default:
340 break;
341 }
342
343 if (feof(fd))
344 break;
345 }
346
347 fclose(fd);
348
349 moveFromList();
350 return size() > 0;
351 }
352
353 /*******************************************************************************
354 **
355 ** Function: CNfcConfig::CNfcConfig()
356 **
357 ** Description: class constructor
358 **
359 ** Returns: none
360 **
361 *******************************************************************************/
CNfcConfig()362 CNfcConfig::CNfcConfig() :
363 mValidFile(true),
364 state(0)
365 {
366 }
367
368 /*******************************************************************************
369 **
370 ** Function: CNfcConfig::~CNfcConfig()
371 **
372 ** Description: class destructor
373 **
374 ** Returns: none
375 **
376 *******************************************************************************/
~CNfcConfig()377 CNfcConfig::~CNfcConfig()
378 {
379 }
380
381 /*******************************************************************************
382 **
383 ** Function: CNfcConfig::GetInstance()
384 **
385 ** Description: get class singleton object
386 **
387 ** Returns: none
388 **
389 *******************************************************************************/
GetInstance()390 CNfcConfig& CNfcConfig::GetInstance()
391 {
392 static CNfcConfig theInstance;
393
394 if (theInstance.size() == 0 && theInstance.mValidFile)
395 {
396 string strPath;
397 strPath.assign(transport_config_path);
398 strPath += config_name;
399 theInstance.readConfig(strPath.c_str(), true);
400 }
401
402 return theInstance;
403 }
404
405 /*******************************************************************************
406 **
407 ** Function: CNfcConfig::getValue()
408 **
409 ** Description: get a string value of a setting
410 **
411 ** Returns: true if setting exists
412 ** false if setting does not exist
413 **
414 *******************************************************************************/
getValue(const char * name,char * pValue,size_t & len) const415 bool CNfcConfig::getValue(const char* name, char* pValue, size_t& len) const
416 {
417 const CNfcParam* pParam = find(name);
418 if (pParam == NULL)
419 return false;
420
421 if (pParam->str_len() > 0)
422 {
423 memset(pValue, 0, len);
424 if (len > pParam->str_len())
425 len = pParam->str_len();
426 memcpy(pValue, pParam->str_value(), len);
427 return true;
428 }
429 return false;
430 }
431
432 /*******************************************************************************
433 **
434 ** Function: CNfcConfig::getValue()
435 **
436 ** Description: get a long numerical value of a setting
437 **
438 ** Returns: true if setting exists
439 ** false if setting does not exist
440 **
441 *******************************************************************************/
getValue(const char * name,unsigned long & rValue) const442 bool CNfcConfig::getValue(const char* name, unsigned long& rValue) const
443 {
444 const CNfcParam* pParam = find(name);
445 if (pParam == NULL)
446 return false;
447
448 if (pParam->str_len() == 0)
449 {
450 rValue = static_cast<unsigned long>(pParam->numValue());
451 return true;
452 }
453 return false;
454 }
455
456 /*******************************************************************************
457 **
458 ** Function: CNfcConfig::getValue()
459 **
460 ** Description: get a short numerical value of a setting
461 **
462 ** Returns: true if setting exists
463 ** false if setting does not exist
464 **
465 *******************************************************************************/
getValue(const char * name,unsigned short & rValue) const466 bool CNfcConfig::getValue(const char* name, unsigned short& rValue) const
467 {
468 const CNfcParam* pParam = find(name);
469 if (pParam == NULL)
470 return false;
471
472 if (pParam->str_len() == 0)
473 {
474 rValue = static_cast<unsigned short>(pParam->numValue());
475 return true;
476 }
477 return false;
478 }
479
480 /*******************************************************************************
481 **
482 ** Function: CNfcConfig::find()
483 **
484 ** Description: search if a setting exist in the setting array
485 **
486 ** Returns: pointer to the setting object
487 **
488 *******************************************************************************/
find(const char * p_name) const489 const CNfcParam* CNfcConfig::find(const char* p_name) const
490 {
491 if (size() == 0)
492 return NULL;
493
494 for (const_iterator it = begin(), itEnd = end(); it != itEnd; ++it)
495 {
496 if (**it < p_name)
497 continue;
498 else if (**it == p_name)
499 {
500 if((*it)->str_len() > 0)
501 ALOGD("%s found %s=%s\n", __func__, p_name, (*it)->str_value());
502 else
503 ALOGD("%s found %s=(0x%lX)\n", __func__, p_name, (*it)->numValue());
504 return *it;
505 }
506 else
507 break;
508 }
509 return NULL;
510 }
511
512 /*******************************************************************************
513 **
514 ** Function: CNfcConfig::clean()
515 **
516 ** Description: reset the setting array
517 **
518 ** Returns: none
519 **
520 *******************************************************************************/
clean()521 void CNfcConfig::clean()
522 {
523 if (size() == 0)
524 return;
525
526 for (iterator it = begin(), itEnd = end(); it != itEnd; ++it)
527 delete *it;
528 clear();
529 }
530
531 /*******************************************************************************
532 **
533 ** Function: CNfcConfig::Add()
534 **
535 ** Description: add a setting object to the list
536 **
537 ** Returns: none
538 **
539 *******************************************************************************/
add(const CNfcParam * pParam)540 void CNfcConfig::add(const CNfcParam* pParam)
541 {
542 if (m_list.size() == 0)
543 {
544 m_list.push_back(pParam);
545 return;
546 }
547 for (list<const CNfcParam*>::iterator it = m_list.begin(), itEnd = m_list.end(); it != itEnd; ++it)
548 {
549 if (**it < pParam->c_str())
550 continue;
551 m_list.insert(it, pParam);
552 return;
553 }
554 m_list.push_back(pParam);
555 }
556
557 /*******************************************************************************
558 **
559 ** Function: CNfcConfig::moveFromList()
560 **
561 ** Description: move the setting object from list to array
562 **
563 ** Returns: none
564 **
565 *******************************************************************************/
moveFromList()566 void CNfcConfig::moveFromList()
567 {
568 if (m_list.size() == 0)
569 return;
570
571 for (list<const CNfcParam*>::iterator it = m_list.begin(), itEnd = m_list.end(); it != itEnd; ++it)
572 push_back(*it);
573 m_list.clear();
574 }
575
576 /*******************************************************************************
577 **
578 ** Function: CNfcConfig::moveToList()
579 **
580 ** Description: move the setting object from array to list
581 **
582 ** Returns: none
583 **
584 *******************************************************************************/
moveToList()585 void CNfcConfig::moveToList()
586 {
587 if (m_list.size() != 0)
588 m_list.clear();
589
590 for (iterator it = begin(), itEnd = end(); it != itEnd; ++it)
591 m_list.push_back(*it);
592 clear();
593 }
594
595 /*******************************************************************************
596 **
597 ** Function: CNfcParam::CNfcParam()
598 **
599 ** Description: class constructor
600 **
601 ** Returns: none
602 **
603 *******************************************************************************/
CNfcParam()604 CNfcParam::CNfcParam() :
605 m_numValue(0)
606 {
607 }
608
609 /*******************************************************************************
610 **
611 ** Function: CNfcParam::~CNfcParam()
612 **
613 ** Description: class destructor
614 **
615 ** Returns: none
616 **
617 *******************************************************************************/
~CNfcParam()618 CNfcParam::~CNfcParam()
619 {
620 }
621
622 /*******************************************************************************
623 **
624 ** Function: CNfcParam::CNfcParam()
625 **
626 ** Description: class copy constructor
627 **
628 ** Returns: none
629 **
630 *******************************************************************************/
CNfcParam(const char * name,const string & value)631 CNfcParam::CNfcParam(const char* name, const string& value) :
632 string(name),
633 m_str_value(value),
634 m_numValue(0)
635 {
636 }
637
638 /*******************************************************************************
639 **
640 ** Function: CNfcParam::CNfcParam()
641 **
642 ** Description: class copy constructor
643 **
644 ** Returns: none
645 **
646 *******************************************************************************/
CNfcParam(const char * name,unsigned long value)647 CNfcParam::CNfcParam(const char* name, unsigned long value) :
648 string(name),
649 m_numValue(value)
650 {
651 }
652
653 /*******************************************************************************
654 **
655 ** Function: GetStrValue
656 **
657 ** Description: API function for getting a string value of a setting
658 **
659 ** Returns: none
660 **
661 *******************************************************************************/
GetStrValue(const char * name,char * pValue,unsigned long l)662 extern "C" int GetStrValue(const char* name, char* pValue, unsigned long l)
663 {
664 size_t len = l;
665 CNfcConfig& rConfig = CNfcConfig::GetInstance();
666
667 bool b = rConfig.getValue(name, pValue, len);
668 return b ? len : 0;
669 }
670
671 /*******************************************************************************
672 **
673 ** Function: GetNumValue
674 **
675 ** Description: API function for getting a numerical value of a setting
676 **
677 ** Returns: none
678 **
679 *******************************************************************************/
GetNumValue(const char * name,void * pValue,unsigned long len)680 extern "C" int GetNumValue(const char* name, void* pValue, unsigned long len)
681 {
682 if (!pValue)
683 return false;
684
685 CNfcConfig& rConfig = CNfcConfig::GetInstance();
686 const CNfcParam* pParam = rConfig.find(name);
687
688 if (pParam == NULL)
689 return false;
690 unsigned long v = pParam->numValue();
691 if (v == 0 && pParam->str_len() > 0 && pParam->str_len() < 4)
692 {
693 const unsigned char* p = (const unsigned char*)pParam->str_value();
694 for (size_t i = 0 ; i < pParam->str_len(); ++i)
695 {
696 v *= 256;
697 v += *p++;
698 }
699 }
700 switch (len)
701 {
702 case sizeof(unsigned long):
703 *(static_cast<unsigned long*>(pValue)) = (unsigned long)v;
704 break;
705 case sizeof(unsigned short):
706 *(static_cast<unsigned short*>(pValue)) = (unsigned short)v;
707 break;
708 case sizeof(unsigned char):
709 *(static_cast<unsigned char*> (pValue)) = (unsigned char)v;
710 break;
711 default:
712 return false;
713 }
714 return true;
715 }
716
717 /*******************************************************************************
718 **
719 ** Function: resetConfig
720 **
721 ** Description: reset settings array
722 **
723 ** Returns: none
724 **
725 *******************************************************************************/
resetConfig()726 extern void resetConfig()
727 {
728 CNfcConfig& rConfig = CNfcConfig::GetInstance();
729
730 rConfig.clean();
731 }
732
733 /*******************************************************************************
734 **
735 ** Function: readOptionalConfig()
736 **
737 ** Description: read Config settings from an optional conf file
738 **
739 ** Returns: none
740 **
741 *******************************************************************************/
readOptionalConfig(const char * extra)742 void readOptionalConfig(const char* extra)
743 {
744 string strPath;
745 strPath.assign(transport_config_path);
746 strPath += extra_config_base;
747 strPath += extra;
748 strPath += extra_config_ext;
749 CNfcConfig::GetInstance().readConfig(strPath.c_str(), false);
750 }
751
752