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 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 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*******************************************************************************/ 348CNfcConfig::CNfcConfig() : 349 mValidFile(true) 350{ 351} 352 353/******************************************************************************* 354** 355** Function: CNfcConfig::~CNfcConfig() 356** 357** Description: class destructor 358** 359** Returns: none 360** 361*******************************************************************************/ 362CNfcConfig::~CNfcConfig() 363{ 364} 365 366/******************************************************************************* 367** 368** Function: CNfcConfig::GetInstance() 369** 370** Description: get class singleton object 371** 372** Returns: none 373** 374*******************************************************************************/ 375CNfcConfig& 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*******************************************************************************/ 400bool 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*******************************************************************************/ 427bool 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*******************************************************************************/ 451bool 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*******************************************************************************/ 474const 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*******************************************************************************/ 506void 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*******************************************************************************/ 525void 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*******************************************************************************/ 551void 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*******************************************************************************/ 570void 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*******************************************************************************/ 589CNfcParam::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*******************************************************************************/ 603CNfcParam::~CNfcParam() 604{ 605} 606 607/******************************************************************************* 608** 609** Function: CNfcParam::CNfcParam() 610** 611** Description: class copy constructor 612** 613** Returns: none 614** 615*******************************************************************************/ 616CNfcParam::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*******************************************************************************/ 632CNfcParam::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*******************************************************************************/ 647extern "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*******************************************************************************/ 665extern "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*******************************************************************************/ 711extern 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*******************************************************************************/ 727void 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