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 27const 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 34using namespace::std; 35 36class CNfcParam : public string 37{ 38public: 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();} 46private: 47 string m_str_value; 48 unsigned long m_numValue; 49}; 50 51class CNfcConfig : public vector<const CNfcParam*> 52{ 53public: 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(); 63private: 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*******************************************************************************/ 88inline 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*******************************************************************************/ 105inline 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*******************************************************************************/ 127inline 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*******************************************************************************/ 151bool 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*******************************************************************************/ 362CNfcConfig::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*******************************************************************************/ 377CNfcConfig::~CNfcConfig() 378{ 379} 380 381/******************************************************************************* 382** 383** Function: CNfcConfig::GetInstance() 384** 385** Description: get class singleton object 386** 387** Returns: none 388** 389*******************************************************************************/ 390CNfcConfig& 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*******************************************************************************/ 415bool 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*******************************************************************************/ 442bool 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*******************************************************************************/ 466bool 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*******************************************************************************/ 489const 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*******************************************************************************/ 521void 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*******************************************************************************/ 540void 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*******************************************************************************/ 566void 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*******************************************************************************/ 585void 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*******************************************************************************/ 604CNfcParam::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*******************************************************************************/ 618CNfcParam::~CNfcParam() 619{ 620} 621 622/******************************************************************************* 623** 624** Function: CNfcParam::CNfcParam() 625** 626** Description: class copy constructor 627** 628** Returns: none 629** 630*******************************************************************************/ 631CNfcParam::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*******************************************************************************/ 647CNfcParam::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*******************************************************************************/ 662extern "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*******************************************************************************/ 680extern "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*******************************************************************************/ 726extern 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*******************************************************************************/ 742void 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