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