• 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 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