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