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