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