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