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