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 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 while (!feof(fd) && fread(&c, 1, 1, fd) == 1) 196 { 197 switch (state & 0xff) 198 { 199 case BEGIN_LINE: 200 if (c == '#') 201 state = END_LINE; 202 else if (isPrintable(c)) 203 { 204 i = 0; 205 token.erase(); 206 strValue.erase(); 207 state = TOKEN; 208 token.push_back(c); 209 } 210 break; 211 case TOKEN: 212 if (c == '=') 213 { 214 token.push_back('\0'); 215 state = BEGIN_QUOTE; 216 } 217 else if (isPrintable(c)) 218 token.push_back(c); 219 else 220 state = END_LINE; 221 break; 222 case BEGIN_QUOTE: 223 if (c == '"') 224 { 225 state = STR_VALUE; 226 base = 0; 227 } 228 else if (c == '0') 229 state = BEGIN_HEX; 230 else if (isDigit(c, 10)) 231 { 232 state = NUM_VALUE; 233 base = 10; 234 numValue = getDigitValue(c, base); 235 i = 0; 236 } 237 else if (c == '{') 238 { 239 state = NUM_VALUE; 240 base = 16; 241 i = 0; 242 Set(IsStringValue); 243 } 244 else 245 state = END_LINE; 246 break; 247 case BEGIN_HEX: 248 if (c == 'x' || c == 'X') 249 { 250 state = NUM_VALUE; 251 base = 16; 252 numValue = 0; 253 i = 0; 254 break; 255 } 256 else if (isDigit(c, 10)) 257 { 258 state = NUM_VALUE; 259 base = 10; 260 numValue = getDigitValue(c, base); 261 break; 262 } 263 else if (c != '\n' && c != '\r') 264 { 265 state = END_LINE; 266 break; 267 } 268 // fal through to numValue to handle numValue 269 270 case NUM_VALUE: 271 if (isDigit(c, base)) 272 { 273 numValue *= base; 274 numValue += getDigitValue(c, base); 275 ++i; 276 } 277 else if (base == 16 && (c == ':' || c == '-' || c == ' ' || c == '}')) 278 { 279 if (i > 0) 280 { 281 int n = (i+1) / 2; 282 while (n-- > 0) 283 { 284 unsigned char c = (numValue >> (n * 8)) & 0xFF; 285 strValue.push_back(c); 286 } 287 } 288 Set(IsStringValue); 289 numValue = 0; 290 i = 0; 291 } 292 else 293 { 294 if (c == '\n' || c == '\r') 295 state = BEGIN_LINE; 296 else 297 state = END_LINE; 298 if (Is(IsStringValue) && base == 16 && i > 0) 299 { 300 int n = (i+1) / 2; 301 while (n-- > 0) 302 strValue.push_back(((numValue >> (n * 8)) & 0xFF)); 303 } 304 if (strValue.length() > 0) 305 pParam = new CNfcParam(token.c_str(), strValue); 306 else 307 pParam = new CNfcParam(token.c_str(), numValue); 308 add(pParam); 309 strValue.erase(); 310 numValue = 0; 311 } 312 break; 313 case STR_VALUE: 314 if (c == '"') 315 { 316 strValue.push_back('\0'); 317 state = END_LINE; 318 pParam = new CNfcParam(token.c_str(), strValue); 319 add(pParam); 320 } 321 else if (isPrintable(c)) 322 strValue.push_back(c); 323 break; 324 case END_LINE: 325 if (c == '\n' || c == '\r') 326 state = BEGIN_LINE; 327 break; 328 default: 329 break; 330 } 331 } 332 333 fclose(fd); 334 335 moveFromList(); 336 return size() > 0; 337 } 338 339 /******************************************************************************* 340 ** 341 ** Function: CNfcConfig::CNfcConfig() 342 ** 343 ** Description: class constructor 344 ** 345 ** Returns: none 346 ** 347 *******************************************************************************/ 348 CNfcConfig::CNfcConfig() : 349 mValidFile(true) 350 { 351 } 352 353 /******************************************************************************* 354 ** 355 ** Function: CNfcConfig::~CNfcConfig() 356 ** 357 ** Description: class destructor 358 ** 359 ** Returns: none 360 ** 361 *******************************************************************************/ 362 CNfcConfig::~CNfcConfig() 363 { 364 } 365 366 /******************************************************************************* 367 ** 368 ** Function: CNfcConfig::GetInstance() 369 ** 370 ** Description: get class singleton object 371 ** 372 ** Returns: none 373 ** 374 *******************************************************************************/ 375 CNfcConfig& CNfcConfig::GetInstance() 376 { 377 static CNfcConfig theInstance; 378 379 if (theInstance.size() == 0 && theInstance.mValidFile) 380 { 381 string strPath; 382 strPath.assign(transport_config_path); 383 strPath += config_name; 384 theInstance.readConfig(strPath.c_str(), true); 385 } 386 387 return theInstance; 388 } 389 390 /******************************************************************************* 391 ** 392 ** Function: CNfcConfig::getValue() 393 ** 394 ** Description: get a string value of a setting 395 ** 396 ** Returns: true if setting exists 397 ** false if setting does not exist 398 ** 399 *******************************************************************************/ 400 bool CNfcConfig::getValue(const char* name, char* pValue, size_t& len) const 401 { 402 const CNfcParam* pParam = find(name); 403 if (pParam == NULL) 404 return false; 405 406 if (pParam->str_len() > 0) 407 { 408 memset(pValue, 0, len); 409 if (len > pParam->str_len()) 410 len = pParam->str_len(); 411 memcpy(pValue, pParam->str_value(), len); 412 return true; 413 } 414 return false; 415 } 416 417 /******************************************************************************* 418 ** 419 ** Function: CNfcConfig::getValue() 420 ** 421 ** Description: get a long numerical value of a setting 422 ** 423 ** Returns: true if setting exists 424 ** false if setting does not exist 425 ** 426 *******************************************************************************/ 427 bool CNfcConfig::getValue(const char* name, unsigned long& rValue) const 428 { 429 const CNfcParam* pParam = find(name); 430 if (pParam == NULL) 431 return false; 432 433 if (pParam->str_len() == 0) 434 { 435 rValue = static_cast<unsigned long>(pParam->numValue()); 436 return true; 437 } 438 return false; 439 } 440 441 /******************************************************************************* 442 ** 443 ** Function: CNfcConfig::getValue() 444 ** 445 ** Description: get a short numerical value of a setting 446 ** 447 ** Returns: true if setting exists 448 ** false if setting does not exist 449 ** 450 *******************************************************************************/ 451 bool CNfcConfig::getValue(const char* name, unsigned short& rValue) const 452 { 453 const CNfcParam* pParam = find(name); 454 if (pParam == NULL) 455 return false; 456 457 if (pParam->str_len() == 0) 458 { 459 rValue = static_cast<unsigned short>(pParam->numValue()); 460 return true; 461 } 462 return false; 463 } 464 465 /******************************************************************************* 466 ** 467 ** Function: CNfcConfig::find() 468 ** 469 ** Description: search if a setting exist in the setting array 470 ** 471 ** Returns: pointer to the setting object 472 ** 473 *******************************************************************************/ 474 const CNfcParam* CNfcConfig::find(const char* p_name) const 475 { 476 if (size() == 0) 477 return NULL; 478 479 for (const_iterator it = begin(), itEnd = end(); it != itEnd; ++it) 480 { 481 if (**it < p_name) 482 continue; 483 else if (**it == p_name) 484 { 485 if((*it)->str_len() > 0) 486 ALOGD("%s found %s=%s\n", __func__, p_name, (*it)->str_value()); 487 else 488 ALOGD("%s found %s=(0x%lX)\n", __func__, p_name, (*it)->numValue()); 489 return *it; 490 } 491 else 492 break; 493 } 494 return NULL; 495 } 496 497 /******************************************************************************* 498 ** 499 ** Function: CNfcConfig::clean() 500 ** 501 ** Description: reset the setting array 502 ** 503 ** Returns: none 504 ** 505 *******************************************************************************/ 506 void CNfcConfig::clean() 507 { 508 if (size() == 0) 509 return; 510 511 for (iterator it = begin(), itEnd = end(); it != itEnd; ++it) 512 delete *it; 513 clear(); 514 } 515 516 /******************************************************************************* 517 ** 518 ** Function: CNfcConfig::Add() 519 ** 520 ** Description: add a setting object to the list 521 ** 522 ** Returns: none 523 ** 524 *******************************************************************************/ 525 void CNfcConfig::add(const CNfcParam* pParam) 526 { 527 if (m_list.size() == 0) 528 { 529 m_list.push_back(pParam); 530 return; 531 } 532 for (list<const CNfcParam*>::iterator it = m_list.begin(), itEnd = m_list.end(); it != itEnd; ++it) 533 { 534 if (**it < pParam->c_str()) 535 continue; 536 m_list.insert(it, pParam); 537 return; 538 } 539 m_list.push_back(pParam); 540 } 541 542 /******************************************************************************* 543 ** 544 ** Function: CNfcConfig::moveFromList() 545 ** 546 ** Description: move the setting object from list to array 547 ** 548 ** Returns: none 549 ** 550 *******************************************************************************/ 551 void CNfcConfig::moveFromList() 552 { 553 if (m_list.size() == 0) 554 return; 555 556 for (list<const CNfcParam*>::iterator it = m_list.begin(), itEnd = m_list.end(); it != itEnd; ++it) 557 push_back(*it); 558 m_list.clear(); 559 } 560 561 /******************************************************************************* 562 ** 563 ** Function: CNfcConfig::moveToList() 564 ** 565 ** Description: move the setting object from array to list 566 ** 567 ** Returns: none 568 ** 569 *******************************************************************************/ 570 void CNfcConfig::moveToList() 571 { 572 if (m_list.size() != 0) 573 m_list.clear(); 574 575 for (iterator it = begin(), itEnd = end(); it != itEnd; ++it) 576 m_list.push_back(*it); 577 clear(); 578 } 579 580 /******************************************************************************* 581 ** 582 ** Function: CNfcParam::CNfcParam() 583 ** 584 ** Description: class constructor 585 ** 586 ** Returns: none 587 ** 588 *******************************************************************************/ 589 CNfcParam::CNfcParam() : 590 m_numValue(0) 591 { 592 } 593 594 /******************************************************************************* 595 ** 596 ** Function: CNfcParam::~CNfcParam() 597 ** 598 ** Description: class destructor 599 ** 600 ** Returns: none 601 ** 602 *******************************************************************************/ 603 CNfcParam::~CNfcParam() 604 { 605 } 606 607 /******************************************************************************* 608 ** 609 ** Function: CNfcParam::CNfcParam() 610 ** 611 ** Description: class copy constructor 612 ** 613 ** Returns: none 614 ** 615 *******************************************************************************/ 616 CNfcParam::CNfcParam(const char* name, const string& value) : 617 string(name), 618 m_str_value(value), 619 m_numValue(0) 620 { 621 } 622 623 /******************************************************************************* 624 ** 625 ** Function: CNfcParam::CNfcParam() 626 ** 627 ** Description: class copy constructor 628 ** 629 ** Returns: none 630 ** 631 *******************************************************************************/ 632 CNfcParam::CNfcParam(const char* name, unsigned long value) : 633 string(name), 634 m_numValue(value) 635 { 636 } 637 638 /******************************************************************************* 639 ** 640 ** Function: GetStrValue 641 ** 642 ** Description: API function for getting a string value of a setting 643 ** 644 ** Returns: none 645 ** 646 *******************************************************************************/ 647 extern "C" int GetStrValue(const char* name, char* pValue, unsigned long l) 648 { 649 size_t len = l; 650 CNfcConfig& rConfig = CNfcConfig::GetInstance(); 651 652 bool b = rConfig.getValue(name, pValue, len); 653 return b ? len : 0; 654 } 655 656 /******************************************************************************* 657 ** 658 ** Function: GetNumValue 659 ** 660 ** Description: API function for getting a numerical value of a setting 661 ** 662 ** Returns: none 663 ** 664 *******************************************************************************/ 665 extern "C" int GetNumValue(const char* name, void* pValue, unsigned long len) 666 { 667 if (!pValue) 668 return false; 669 670 CNfcConfig& rConfig = CNfcConfig::GetInstance(); 671 const CNfcParam* pParam = rConfig.find(name); 672 673 if (pParam == NULL) 674 return false; 675 unsigned long v = pParam->numValue(); 676 if (v == 0 && pParam->str_len() > 0 && pParam->str_len() < 4) 677 { 678 const unsigned char* p = (const unsigned char*)pParam->str_value(); 679 for (size_t i = 0 ; i < pParam->str_len(); ++i) 680 { 681 v *= 256; 682 v += *p++; 683 } 684 } 685 switch (len) 686 { 687 case sizeof(unsigned long): 688 *(static_cast<unsigned long*>(pValue)) = (unsigned long)v; 689 break; 690 case sizeof(unsigned short): 691 *(static_cast<unsigned short*>(pValue)) = (unsigned short)v; 692 break; 693 case sizeof(unsigned char): 694 *(static_cast<unsigned char*> (pValue)) = (unsigned char)v; 695 break; 696 default: 697 return false; 698 } 699 return true; 700 } 701 702 /******************************************************************************* 703 ** 704 ** Function: resetConfig 705 ** 706 ** Description: reset settings array 707 ** 708 ** Returns: none 709 ** 710 *******************************************************************************/ 711 extern void resetConfig() 712 { 713 CNfcConfig& rConfig = CNfcConfig::GetInstance(); 714 715 rConfig.clean(); 716 } 717 718 /******************************************************************************* 719 ** 720 ** Function: readOptionalConfig() 721 ** 722 ** Description: read Config settings from an optional conf file 723 ** 724 ** Returns: none 725 ** 726 *******************************************************************************/ 727 void readOptionalConfig(const char* extra) 728 { 729 string strPath; 730 strPath.assign(transport_config_path); 731 strPath += extra_config_base; 732 strPath += extra; 733 strPath += extra_config_ext; 734 CNfcConfig::GetInstance().readConfig(strPath.c_str(), false); 735 } 736 737