config.cpp revision 5c65c3a0f42e174e47fecd4e569606003217ff4e
190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/****************************************************************************** 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Copyright (C) 2011-2012 Broadcom Corporation 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License"); 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * you may not use this file except in compliance with the License. 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * You may obtain a copy of the License at: 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * http://www.apache.org/licenses/LICENSE-2.0 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Unless required by applicable law or agreed to in writing, software 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS, 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * See the License for the specific language governing permissions and 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * limitations under the License. 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 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 27const char alternative_config_path[] = ""; 28const 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 35using namespace::std; 36 37class CNfcParam : public string 38{ 39public: 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();} 47private: 48 string m_str_value; 49 unsigned long m_numValue; 50}; 51 52class CNfcConfig : public vector<const CNfcParam*> 53{ 54public: 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(); 64private: 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*******************************************************************************/ 89inline 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*******************************************************************************/ 106inline 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*******************************************************************************/ 128inline 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*******************************************************************************/ 152bool 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*******************************************************************************/ 349CNfcConfig::CNfcConfig() : 350 mValidFile(true) 351{ 352} 353 354/******************************************************************************* 355** 356** Function: CNfcConfig::~CNfcConfig() 357** 358** Description: class destructor 359** 360** Returns: none 361** 362*******************************************************************************/ 363CNfcConfig::~CNfcConfig() 364{ 365} 366 367/******************************************************************************* 368** 369** Function: CNfcConfig::GetInstance() 370** 371** Description: get class singleton object 372** 373** Returns: none 374** 375*******************************************************************************/ 376CNfcConfig& 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*******************************************************************************/ 411bool 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*******************************************************************************/ 438bool 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*******************************************************************************/ 462bool 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*******************************************************************************/ 485const 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*******************************************************************************/ 517void 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*******************************************************************************/ 536void 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*******************************************************************************/ 562void 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*******************************************************************************/ 581void 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*******************************************************************************/ 600CNfcParam::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*******************************************************************************/ 614CNfcParam::~CNfcParam() 615{ 616} 617 618/******************************************************************************* 619** 620** Function: CNfcParam::CNfcParam() 621** 622** Description: class copy constructor 623** 624** Returns: none 625** 626*******************************************************************************/ 627CNfcParam::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*******************************************************************************/ 643CNfcParam::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*******************************************************************************/ 658extern "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*******************************************************************************/ 676extern "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*******************************************************************************/ 722extern 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*******************************************************************************/ 738void 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