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