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