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