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 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 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 *******************************************************************************/ 362 CNfcConfig::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 *******************************************************************************/ 377 CNfcConfig::~CNfcConfig() 378 { 379 } 380 381 /******************************************************************************* 382 ** 383 ** Function: CNfcConfig::GetInstance() 384 ** 385 ** Description: get class singleton object 386 ** 387 ** Returns: none 388 ** 389 *******************************************************************************/ 390 CNfcConfig& 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 *******************************************************************************/ 415 bool 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 *******************************************************************************/ 442 bool 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 *******************************************************************************/ 466 bool 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 *******************************************************************************/ 489 const 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 *******************************************************************************/ 521 void 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 *******************************************************************************/ 540 void 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 *******************************************************************************/ 566 void 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 *******************************************************************************/ 585 void 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 *******************************************************************************/ 604 CNfcParam::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 *******************************************************************************/ 618 CNfcParam::~CNfcParam() 619 { 620 } 621 622 /******************************************************************************* 623 ** 624 ** Function: CNfcParam::CNfcParam() 625 ** 626 ** Description: class copy constructor 627 ** 628 ** Returns: none 629 ** 630 *******************************************************************************/ 631 CNfcParam::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 *******************************************************************************/ 647 CNfcParam::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 *******************************************************************************/ 662 extern "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 *******************************************************************************/ 680 extern "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 *******************************************************************************/ 726 extern 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 *******************************************************************************/ 742 void 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