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 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 while (!feof(fd) && fread(&c, 1, 1, fd) == 1)
196 {
197 switch (state & 0xff)
198 {
199 case BEGIN_LINE:
200 if (c == '#')
201 state = END_LINE;
202 else if (isPrintable(c))
203 {
204 i = 0;
205 token.erase();
206 strValue.erase();
207 state = TOKEN;
208 token.push_back(c);
209 }
210 break;
211 case TOKEN:
212 if (c == '=')
213 {
214 token.push_back('\0');
215 state = BEGIN_QUOTE;
216 }
217 else if (isPrintable(c))
218 token.push_back(c);
219 else
220 state = END_LINE;
221 break;
222 case BEGIN_QUOTE:
223 if (c == '"')
224 {
225 state = STR_VALUE;
226 base = 0;
227 }
228 else if (c == '0')
229 state = BEGIN_HEX;
230 else if (isDigit(c, 10))
231 {
232 state = NUM_VALUE;
233 base = 10;
234 numValue = getDigitValue(c, base);
235 i = 0;
236 }
237 else if (c == '{')
238 {
239 state = NUM_VALUE;
240 base = 16;
241 i = 0;
242 Set(IsStringValue);
243 }
244 else
245 state = END_LINE;
246 break;
247 case BEGIN_HEX:
248 if (c == 'x' || c == 'X')
249 {
250 state = NUM_VALUE;
251 base = 16;
252 numValue = 0;
253 i = 0;
254 break;
255 }
256 else if (isDigit(c, 10))
257 {
258 state = NUM_VALUE;
259 base = 10;
260 numValue = getDigitValue(c, base);
261 break;
262 }
263 else if (c != '\n' && c != '\r')
264 {
265 state = END_LINE;
266 break;
267 }
268 // fal through to numValue to handle numValue
269
270 case NUM_VALUE:
271 if (isDigit(c, base))
272 {
273 numValue *= base;
274 numValue += getDigitValue(c, base);
275 ++i;
276 }
277 else if (base == 16 && (c == ':' || c == '-' || c == ' ' || c == '}'))
278 {
279 if (i > 0)
280 {
281 int n = (i+1) / 2;
282 while (n-- > 0)
283 {
284 unsigned char c = (numValue >> (n * 8)) & 0xFF;
285 strValue.push_back(c);
286 }
287 }
288 Set(IsStringValue);
289 numValue = 0;
290 i = 0;
291 }
292 else
293 {
294 if (c == '\n' || c == '\r')
295 state = BEGIN_LINE;
296 else
297 state = END_LINE;
298 if (Is(IsStringValue) && base == 16 && i > 0)
299 {
300 int n = (i+1) / 2;
301 while (n-- > 0)
302 strValue.push_back(((numValue >> (n * 8)) & 0xFF));
303 }
304 if (strValue.length() > 0)
305 pParam = new CNfcParam(token.c_str(), strValue);
306 else
307 pParam = new CNfcParam(token.c_str(), numValue);
308 add(pParam);
309 strValue.erase();
310 numValue = 0;
311 }
312 break;
313 case STR_VALUE:
314 if (c == '"')
315 {
316 strValue.push_back('\0');
317 state = END_LINE;
318 pParam = new CNfcParam(token.c_str(), strValue);
319 add(pParam);
320 }
321 else if (isPrintable(c))
322 strValue.push_back(c);
323 break;
324 case END_LINE:
325 if (c == '\n' || c == '\r')
326 state = BEGIN_LINE;
327 break;
328 default:
329 break;
330 }
331 }
332
333 fclose(fd);
334
335 moveFromList();
336 return size() > 0;
337 }
338
339 /*******************************************************************************
340 **
341 ** Function: CNfcConfig::CNfcConfig()
342 **
343 ** Description: class constructor
344 **
345 ** Returns: none
346 **
347 *******************************************************************************/
CNfcConfig()348 CNfcConfig::CNfcConfig() :
349 mValidFile(true)
350 {
351 }
352
353 /*******************************************************************************
354 **
355 ** Function: CNfcConfig::~CNfcConfig()
356 **
357 ** Description: class destructor
358 **
359 ** Returns: none
360 **
361 *******************************************************************************/
~CNfcConfig()362 CNfcConfig::~CNfcConfig()
363 {
364 }
365
366 /*******************************************************************************
367 **
368 ** Function: CNfcConfig::GetInstance()
369 **
370 ** Description: get class singleton object
371 **
372 ** Returns: none
373 **
374 *******************************************************************************/
GetInstance()375 CNfcConfig& CNfcConfig::GetInstance()
376 {
377 static CNfcConfig theInstance;
378
379 if (theInstance.size() == 0 && theInstance.mValidFile)
380 {
381 string strPath;
382 strPath.assign(transport_config_path);
383 strPath += config_name;
384 theInstance.readConfig(strPath.c_str(), true);
385 }
386
387 return theInstance;
388 }
389
390 /*******************************************************************************
391 **
392 ** Function: CNfcConfig::getValue()
393 **
394 ** Description: get a string value of a setting
395 **
396 ** Returns: true if setting exists
397 ** false if setting does not exist
398 **
399 *******************************************************************************/
getValue(const char * name,char * pValue,size_t & len) const400 bool CNfcConfig::getValue(const char* name, char* pValue, size_t& len) const
401 {
402 const CNfcParam* pParam = find(name);
403 if (pParam == NULL)
404 return false;
405
406 if (pParam->str_len() > 0)
407 {
408 memset(pValue, 0, len);
409 if (len > pParam->str_len())
410 len = pParam->str_len();
411 memcpy(pValue, pParam->str_value(), len);
412 return true;
413 }
414 return false;
415 }
416
417 /*******************************************************************************
418 **
419 ** Function: CNfcConfig::getValue()
420 **
421 ** Description: get a long numerical value of a setting
422 **
423 ** Returns: true if setting exists
424 ** false if setting does not exist
425 **
426 *******************************************************************************/
getValue(const char * name,unsigned long & rValue) const427 bool CNfcConfig::getValue(const char* name, unsigned long& rValue) const
428 {
429 const CNfcParam* pParam = find(name);
430 if (pParam == NULL)
431 return false;
432
433 if (pParam->str_len() == 0)
434 {
435 rValue = static_cast<unsigned long>(pParam->numValue());
436 return true;
437 }
438 return false;
439 }
440
441 /*******************************************************************************
442 **
443 ** Function: CNfcConfig::getValue()
444 **
445 ** Description: get a short numerical value of a setting
446 **
447 ** Returns: true if setting exists
448 ** false if setting does not exist
449 **
450 *******************************************************************************/
getValue(const char * name,unsigned short & rValue) const451 bool CNfcConfig::getValue(const char* name, unsigned short& rValue) const
452 {
453 const CNfcParam* pParam = find(name);
454 if (pParam == NULL)
455 return false;
456
457 if (pParam->str_len() == 0)
458 {
459 rValue = static_cast<unsigned short>(pParam->numValue());
460 return true;
461 }
462 return false;
463 }
464
465 /*******************************************************************************
466 **
467 ** Function: CNfcConfig::find()
468 **
469 ** Description: search if a setting exist in the setting array
470 **
471 ** Returns: pointer to the setting object
472 **
473 *******************************************************************************/
find(const char * p_name) const474 const CNfcParam* CNfcConfig::find(const char* p_name) const
475 {
476 if (size() == 0)
477 return NULL;
478
479 for (const_iterator it = begin(), itEnd = end(); it != itEnd; ++it)
480 {
481 if (**it < p_name)
482 continue;
483 else if (**it == p_name)
484 {
485 if((*it)->str_len() > 0)
486 ALOGD("%s found %s=%s\n", __func__, p_name, (*it)->str_value());
487 else
488 ALOGD("%s found %s=(0x%lX)\n", __func__, p_name, (*it)->numValue());
489 return *it;
490 }
491 else
492 break;
493 }
494 return NULL;
495 }
496
497 /*******************************************************************************
498 **
499 ** Function: CNfcConfig::clean()
500 **
501 ** Description: reset the setting array
502 **
503 ** Returns: none
504 **
505 *******************************************************************************/
clean()506 void CNfcConfig::clean()
507 {
508 if (size() == 0)
509 return;
510
511 for (iterator it = begin(), itEnd = end(); it != itEnd; ++it)
512 delete *it;
513 clear();
514 }
515
516 /*******************************************************************************
517 **
518 ** Function: CNfcConfig::Add()
519 **
520 ** Description: add a setting object to the list
521 **
522 ** Returns: none
523 **
524 *******************************************************************************/
add(const CNfcParam * pParam)525 void CNfcConfig::add(const CNfcParam* pParam)
526 {
527 if (m_list.size() == 0)
528 {
529 m_list.push_back(pParam);
530 return;
531 }
532 for (list<const CNfcParam*>::iterator it = m_list.begin(), itEnd = m_list.end(); it != itEnd; ++it)
533 {
534 if (**it < pParam->c_str())
535 continue;
536 m_list.insert(it, pParam);
537 return;
538 }
539 m_list.push_back(pParam);
540 }
541
542 /*******************************************************************************
543 **
544 ** Function: CNfcConfig::moveFromList()
545 **
546 ** Description: move the setting object from list to array
547 **
548 ** Returns: none
549 **
550 *******************************************************************************/
moveFromList()551 void CNfcConfig::moveFromList()
552 {
553 if (m_list.size() == 0)
554 return;
555
556 for (list<const CNfcParam*>::iterator it = m_list.begin(), itEnd = m_list.end(); it != itEnd; ++it)
557 push_back(*it);
558 m_list.clear();
559 }
560
561 /*******************************************************************************
562 **
563 ** Function: CNfcConfig::moveToList()
564 **
565 ** Description: move the setting object from array to list
566 **
567 ** Returns: none
568 **
569 *******************************************************************************/
moveToList()570 void CNfcConfig::moveToList()
571 {
572 if (m_list.size() != 0)
573 m_list.clear();
574
575 for (iterator it = begin(), itEnd = end(); it != itEnd; ++it)
576 m_list.push_back(*it);
577 clear();
578 }
579
580 /*******************************************************************************
581 **
582 ** Function: CNfcParam::CNfcParam()
583 **
584 ** Description: class constructor
585 **
586 ** Returns: none
587 **
588 *******************************************************************************/
CNfcParam()589 CNfcParam::CNfcParam() :
590 m_numValue(0)
591 {
592 }
593
594 /*******************************************************************************
595 **
596 ** Function: CNfcParam::~CNfcParam()
597 **
598 ** Description: class destructor
599 **
600 ** Returns: none
601 **
602 *******************************************************************************/
~CNfcParam()603 CNfcParam::~CNfcParam()
604 {
605 }
606
607 /*******************************************************************************
608 **
609 ** Function: CNfcParam::CNfcParam()
610 **
611 ** Description: class copy constructor
612 **
613 ** Returns: none
614 **
615 *******************************************************************************/
CNfcParam(const char * name,const string & value)616 CNfcParam::CNfcParam(const char* name, const string& value) :
617 string(name),
618 m_str_value(value),
619 m_numValue(0)
620 {
621 }
622
623 /*******************************************************************************
624 **
625 ** Function: CNfcParam::CNfcParam()
626 **
627 ** Description: class copy constructor
628 **
629 ** Returns: none
630 **
631 *******************************************************************************/
CNfcParam(const char * name,unsigned long value)632 CNfcParam::CNfcParam(const char* name, unsigned long value) :
633 string(name),
634 m_numValue(value)
635 {
636 }
637
638 /*******************************************************************************
639 **
640 ** Function: GetStrValue
641 **
642 ** Description: API function for getting a string value of a setting
643 **
644 ** Returns: none
645 **
646 *******************************************************************************/
GetStrValue(const char * name,char * pValue,unsigned long l)647 extern "C" int GetStrValue(const char* name, char* pValue, unsigned long l)
648 {
649 size_t len = l;
650 CNfcConfig& rConfig = CNfcConfig::GetInstance();
651
652 bool b = rConfig.getValue(name, pValue, len);
653 return b ? len : 0;
654 }
655
656 /*******************************************************************************
657 **
658 ** Function: GetNumValue
659 **
660 ** Description: API function for getting a numerical value of a setting
661 **
662 ** Returns: none
663 **
664 *******************************************************************************/
GetNumValue(const char * name,void * pValue,unsigned long len)665 extern "C" int GetNumValue(const char* name, void* pValue, unsigned long len)
666 {
667 if (!pValue)
668 return false;
669
670 CNfcConfig& rConfig = CNfcConfig::GetInstance();
671 const CNfcParam* pParam = rConfig.find(name);
672
673 if (pParam == NULL)
674 return false;
675 unsigned long v = pParam->numValue();
676 if (v == 0 && pParam->str_len() > 0 && pParam->str_len() < 4)
677 {
678 const unsigned char* p = (const unsigned char*)pParam->str_value();
679 for (size_t i = 0 ; i < pParam->str_len(); ++i)
680 {
681 v *= 256;
682 v += *p++;
683 }
684 }
685 switch (len)
686 {
687 case sizeof(unsigned long):
688 *(static_cast<unsigned long*>(pValue)) = (unsigned long)v;
689 break;
690 case sizeof(unsigned short):
691 *(static_cast<unsigned short*>(pValue)) = (unsigned short)v;
692 break;
693 case sizeof(unsigned char):
694 *(static_cast<unsigned char*> (pValue)) = (unsigned char)v;
695 break;
696 default:
697 return false;
698 }
699 return true;
700 }
701
702 /*******************************************************************************
703 **
704 ** Function: resetConfig
705 **
706 ** Description: reset settings array
707 **
708 ** Returns: none
709 **
710 *******************************************************************************/
resetConfig()711 extern void resetConfig()
712 {
713 CNfcConfig& rConfig = CNfcConfig::GetInstance();
714
715 rConfig.clean();
716 }
717
718 /*******************************************************************************
719 **
720 ** Function: readOptionalConfig()
721 **
722 ** Description: read Config settings from an optional conf file
723 **
724 ** Returns: none
725 **
726 *******************************************************************************/
readOptionalConfig(const char * extra)727 void readOptionalConfig(const char* extra)
728 {
729 string strPath;
730 strPath.assign(transport_config_path);
731 strPath += extra_config_base;
732 strPath += extra;
733 strPath += extra_config_ext;
734 CNfcConfig::GetInstance().readConfig(strPath.c_str(), false);
735 }
736
737