• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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