1 /*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 * Import and export general routing data using a XML file.
19 */
20 #include "OverrideLog.h"
21 #include "RouteDataSet.h"
22 #include "libxml/xmlmemory.h"
23 #include <errno.h>
24 #include <sys/stat.h>
25
26 extern char bcm_nfc_location[];
27
28
29 /*******************************************************************************
30 **
31 ** Function: AidBuffer
32 **
33 ** Description: Parse a string of hex numbers. Store result in an array of
34 ** bytes.
35 ** aid: string of hex numbers.
36 **
37 ** Returns: None.
38 **
39 *******************************************************************************/
AidBuffer(std::string & aid)40 AidBuffer::AidBuffer (std::string& aid)
41 : mBuffer (NULL),
42 mBufferLen (0)
43 {
44 unsigned int num = 0;
45 const char delimiter = ':';
46 std::string::size_type pos1 = 0;
47 std::string::size_type pos2 = aid.find_first_of (delimiter);
48
49 //parse the AID string; each hex number is separated by a colon;
50 mBuffer = new UINT8 [aid.length()];
51 while (true)
52 {
53 num = 0;
54 if (pos2 == std::string::npos)
55 {
56 sscanf (aid.substr(pos1).c_str(), "%x", &num);
57 mBuffer [mBufferLen] = (UINT8) num;
58 mBufferLen++;
59 break;
60 }
61 else
62 {
63 sscanf (aid.substr(pos1, pos2-pos1+1).c_str(), "%x", &num);
64 mBuffer [mBufferLen] = (UINT8) num;
65 mBufferLen++;
66 pos1 = pos2 + 1;
67 pos2 = aid.find_first_of (delimiter, pos1);
68 }
69 }
70 }
71
72
73 /*******************************************************************************
74 **
75 ** Function: ~AidBuffer
76 **
77 ** Description: Release all resources.
78 **
79 ** Returns: None.
80 **
81 *******************************************************************************/
~AidBuffer()82 AidBuffer::~AidBuffer ()
83 {
84 delete [] mBuffer;
85 }
86
87
88 /*******************************************************************************/
89 /*******************************************************************************/
90
91
92 const char* RouteDataSet::sConfigFile = "/param/route.xml";
93
94
95 /*******************************************************************************
96 **
97 ** Function: ~RouteDataSet
98 **
99 ** Description: Release all resources.
100 **
101 ** Returns: None.
102 **
103 *******************************************************************************/
~RouteDataSet()104 RouteDataSet::~RouteDataSet ()
105 {
106 deleteDatabase ();
107 }
108
109
110 /*******************************************************************************
111 **
112 ** Function: initialize
113 **
114 ** Description: Initialize resources.
115 **
116 ** Returns: True if ok.
117 **
118 *******************************************************************************/
initialize()119 bool RouteDataSet::initialize ()
120 {
121 static const char fn [] = "RouteDataSet::initialize";
122 ALOGD ("%s: enter", fn);
123 //check that the libxml2 version in use is compatible
124 //with the version the software has been compiled with
125 LIBXML_TEST_VERSION
126 ALOGD ("%s: exit; return=true", fn);
127 return true;
128 }
129
130
131 /*******************************************************************************
132 **
133 ** Function: deleteDatabase
134 **
135 ** Description: Delete all routes stored in all databases.
136 **
137 ** Returns: None.
138 **
139 *******************************************************************************/
deleteDatabase()140 void RouteDataSet::deleteDatabase ()
141 {
142 static const char fn [] = "RouteDataSet::deleteDatabase";
143 ALOGD ("%s: default db size=%zu; sec elem db size=%zu", fn, mDefaultRouteDatabase.size(), mSecElemRouteDatabase.size());
144 Database::iterator it;
145
146 for (it = mDefaultRouteDatabase.begin(); it != mDefaultRouteDatabase.end(); it++)
147 delete (*it);
148 mDefaultRouteDatabase.clear ();
149
150 for (it = mSecElemRouteDatabase.begin(); it != mSecElemRouteDatabase.end(); it++)
151 delete (*it);
152 mSecElemRouteDatabase.clear ();
153 }
154
155
156 /*******************************************************************************
157 **
158 ** Function: import
159 **
160 ** Description: Import data from an XML file. Fill the databases.
161 **
162 ** Returns: True if ok.
163 **
164 *******************************************************************************/
import()165 bool RouteDataSet::import ()
166 {
167 static const char fn [] = "RouteDataSet::import";
168 ALOGD ("%s: enter", fn);
169 bool retval = false;
170 xmlDocPtr doc;
171 xmlNodePtr node1;
172 std::string strFilename(bcm_nfc_location);
173 strFilename += sConfigFile;
174
175 deleteDatabase ();
176
177 doc = xmlParseFile (strFilename.c_str());
178 if (doc == NULL)
179 {
180 ALOGD ("%s: fail parse", fn);
181 goto TheEnd;
182 }
183
184 node1 = xmlDocGetRootElement (doc);
185 if (node1 == NULL)
186 {
187 ALOGE ("%s: fail root element", fn);
188 goto TheEnd;
189 }
190 ALOGD ("%s: root=%s", fn, node1->name);
191
192 node1 = node1->xmlChildrenNode;
193 while (node1) //loop through all elements in <Routes ...
194 {
195 if (xmlStrcmp(node1->name, (const xmlChar*) "Route")==0)
196 {
197 xmlChar* value = xmlGetProp (node1, (const xmlChar*) "Type");
198 if (value && (xmlStrcmp (value, (const xmlChar*) "SecElemSelectedRoutes") == 0))
199 {
200 ALOGD ("%s: found SecElemSelectedRoutes", fn);
201 xmlNodePtr node2 = node1->xmlChildrenNode;
202 while (node2) //loop all elements in <Route Type="SecElemSelectedRoutes" ...
203 {
204 if (xmlStrcmp(node2->name, (const xmlChar*) "Proto")==0)
205 importProtocolRoute (node2, mSecElemRouteDatabase);
206 else if (xmlStrcmp(node2->name, (const xmlChar*) "Tech")==0)
207 importTechnologyRoute (node2, mSecElemRouteDatabase);
208 node2 = node2->next;
209 } //loop all elements in <Route Type="SecElemSelectedRoutes" ...
210 }
211 else if (value && (xmlStrcmp (value, (const xmlChar*) "DefaultRoutes") == 0))
212 {
213 ALOGD ("%s: found DefaultRoutes", fn);
214 xmlNodePtr node2 = node1->xmlChildrenNode;
215 while (node2) //loop all elements in <Route Type="DefaultRoutes" ...
216 {
217 if (xmlStrcmp(node2->name, (const xmlChar*) "Proto")==0)
218 importProtocolRoute (node2, mDefaultRouteDatabase);
219 else if (xmlStrcmp(node2->name, (const xmlChar*) "Tech")==0)
220 importTechnologyRoute (node2, mDefaultRouteDatabase);
221 node2 = node2->next;
222 } //loop all elements in <Route Type="DefaultRoutes" ...
223 }
224 if (value)
225 xmlFree (value);
226 } //check <Route ...
227 node1 = node1->next;
228 } //loop through all elements in <Routes ...
229 retval = true;
230
231 TheEnd:
232 xmlFreeDoc (doc);
233 xmlCleanupParser ();
234 ALOGD ("%s: exit; return=%u", fn, retval);
235 return retval;
236 }
237
238
239 /*******************************************************************************
240 **
241 ** Function: saveToFile
242 **
243 ** Description: Save XML data from a string into a file.
244 ** routesXml: XML that represents routes.
245 **
246 ** Returns: True if ok.
247 **
248 *******************************************************************************/
saveToFile(const char * routesXml)249 bool RouteDataSet::saveToFile (const char* routesXml)
250 {
251 static const char fn [] = "RouteDataSet::saveToFile";
252 FILE* fh = NULL;
253 size_t actualWritten = 0;
254 bool retval = false;
255 std::string filename (bcm_nfc_location);
256 int stat = 0;
257
258 filename.append (sConfigFile);
259 fh = fopen (filename.c_str (), "w");
260 if (fh == NULL)
261 {
262 ALOGE ("%s: fail to open file", fn);
263 return false;
264 }
265
266 actualWritten = fwrite (routesXml, sizeof(char), strlen(routesXml), fh);
267 retval = actualWritten == strlen(routesXml);
268 fclose (fh);
269 ALOGD ("%s: wrote %zu bytes", fn, actualWritten);
270 if (retval == false)
271 ALOGE ("%s: error during write", fn);
272
273 //set file permission to
274 //owner read, write; group read; other read
275 stat = chmod (filename.c_str (), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
276 if (stat == -1)
277 ALOGE ("%s: error during chmod", fn);
278 return retval;
279 }
280
281
282 /*******************************************************************************
283 **
284 ** Function: loadFromFile
285 **
286 ** Description: Load XML data from file into a string.
287 ** routesXml: string to receive XML data.
288 **
289 ** Returns: True if ok.
290 **
291 *******************************************************************************/
loadFromFile(std::string & routesXml)292 bool RouteDataSet::loadFromFile (std::string& routesXml)
293 {
294 static const char fn [] = "RouteDataSet::loadFromFile";
295 FILE* fh = NULL;
296 size_t actual = 0;
297 char buffer [1024];
298 std::string filename (bcm_nfc_location);
299
300 filename.append (sConfigFile);
301 fh = fopen (filename.c_str (), "r");
302 if (fh == NULL)
303 {
304 ALOGD ("%s: fail to open file", fn);
305 return false;
306 }
307
308 while (true)
309 {
310 actual = fread (buffer, sizeof(char), sizeof(buffer), fh);
311 if (actual == 0)
312 break;
313 routesXml.append (buffer, actual);
314 }
315 fclose (fh);
316 ALOGD ("%s: read %zu bytes", fn, routesXml.length());
317 return true;
318 }
319
320
321
322
323 /*******************************************************************************
324 **
325 ** Function: importProtocolRoute
326 **
327 ** Description: Parse data for protocol routes.
328 ** element: XML node for one protocol route.
329 ** database: store data in this database.
330 **
331 ** Returns: None.
332 **
333 *******************************************************************************/
importProtocolRoute(xmlNodePtr & element,Database & database)334 void RouteDataSet::importProtocolRoute (xmlNodePtr& element, Database& database)
335 {
336 static const char fn [] = "RouteDataSet::importProtocolRoute";
337 const xmlChar* id = (const xmlChar*) "Id";
338 const xmlChar* secElem = (const xmlChar*) "SecElem";
339 const xmlChar* trueString = (const xmlChar*) "true";
340 const xmlChar* switchOn = (const xmlChar*) "SwitchOn";
341 const xmlChar* switchOff = (const xmlChar*) "SwitchOff";
342 const xmlChar* batteryOff = (const xmlChar*) "BatteryOff";
343 RouteDataForProtocol* data = new RouteDataForProtocol;
344 xmlChar* value = NULL;
345
346 ALOGD_IF (sDebug, "%s: element=%s", fn, element->name);
347 value = xmlGetProp (element, id);
348 if (value)
349 {
350 if (xmlStrcmp (value, (const xmlChar*) "T1T") == 0)
351 data->mProtocol = NFA_PROTOCOL_MASK_T1T;
352 else if (xmlStrcmp (value, (const xmlChar*) "T2T") == 0)
353 data->mProtocol = NFA_PROTOCOL_MASK_T2T;
354 else if (xmlStrcmp (value, (const xmlChar*) "T3T") == 0)
355 data->mProtocol = NFA_PROTOCOL_MASK_T3T;
356 else if (xmlStrcmp (value, (const xmlChar*) "IsoDep") == 0)
357 data->mProtocol = NFA_PROTOCOL_MASK_ISO_DEP;
358 xmlFree (value);
359 ALOGD_IF (sDebug, "%s: %s=0x%X", fn, id, data->mProtocol);
360 }
361
362 value = xmlGetProp (element, secElem);
363 if (value)
364 {
365 data->mNfaEeHandle = strtol ((char*) value, NULL, 16);
366 xmlFree (value);
367 data->mNfaEeHandle = data->mNfaEeHandle | NFA_HANDLE_GROUP_EE;
368 ALOGD_IF (sDebug, "%s: %s=0x%X", fn, secElem, data->mNfaEeHandle);
369 }
370
371 value = xmlGetProp (element, switchOn);
372 if (value)
373 {
374 data->mSwitchOn = (xmlStrcmp (value, trueString) == 0);
375 xmlFree (value);
376 }
377
378 value = xmlGetProp (element, switchOff);
379 if (value)
380 {
381 data->mSwitchOff = (xmlStrcmp (value, trueString) == 0);
382 xmlFree (value);
383 }
384
385 value = xmlGetProp (element, batteryOff);
386 if (value)
387 {
388 data->mBatteryOff = (xmlStrcmp (value, trueString) == 0);
389 xmlFree (value);
390 }
391 database.push_back (data);
392 }
393
394
395 /*******************************************************************************
396 **
397 ** Function: importTechnologyRoute
398 **
399 ** Description: Parse data for technology routes.
400 ** element: XML node for one technology route.
401 ** database: store data in this database.
402 **
403 ** Returns: None.
404 **
405 *******************************************************************************/
importTechnologyRoute(xmlNodePtr & element,Database & database)406 void RouteDataSet::importTechnologyRoute (xmlNodePtr& element, Database& database)
407 {
408 static const char fn [] = "RouteDataSet::importTechnologyRoute";
409 const xmlChar* id = (const xmlChar*) "Id";
410 const xmlChar* secElem = (const xmlChar*) "SecElem";
411 const xmlChar* trueString = (const xmlChar*) "true";
412 const xmlChar* switchOn = (const xmlChar*) "SwitchOn";
413 const xmlChar* switchOff = (const xmlChar*) "SwitchOff";
414 const xmlChar* batteryOff = (const xmlChar*) "BatteryOff";
415 RouteDataForTechnology* data = new RouteDataForTechnology;
416 xmlChar* value = NULL;
417
418 ALOGD_IF (sDebug, "%s: element=%s", fn, element->name);
419 value = xmlGetProp (element, id);
420 if (value)
421 {
422 if (xmlStrcmp (value, (const xmlChar*) "NfcA") == 0)
423 data->mTechnology = NFA_TECHNOLOGY_MASK_A;
424 else if (xmlStrcmp (value, (const xmlChar*) "NfcB") == 0)
425 data->mTechnology = NFA_TECHNOLOGY_MASK_B;
426 else if (xmlStrcmp (value, (const xmlChar*) "NfcF") == 0)
427 data->mTechnology = NFA_TECHNOLOGY_MASK_F;
428 xmlFree (value);
429 ALOGD_IF (sDebug, "%s: %s=0x%X", fn, id, data->mTechnology);
430 }
431
432 value = xmlGetProp (element, secElem);
433 if (value)
434 {
435 data->mNfaEeHandle = strtol ((char*) value, NULL, 16);
436 xmlFree (value);
437 data->mNfaEeHandle = data->mNfaEeHandle | NFA_HANDLE_GROUP_EE;
438 ALOGD_IF (sDebug, "%s: %s=0x%X", fn, secElem, data->mNfaEeHandle);
439 }
440
441 value = xmlGetProp (element, switchOn);
442 if (value)
443 {
444 data->mSwitchOn = (xmlStrcmp (value, trueString) == 0);
445 xmlFree (value);
446 }
447
448 value = xmlGetProp (element, switchOff);
449 if (value)
450 {
451 data->mSwitchOff = (xmlStrcmp (value, trueString) == 0);
452 xmlFree (value);
453 }
454
455 value = xmlGetProp (element, batteryOff);
456 if (value)
457 {
458 data->mBatteryOff = (xmlStrcmp (value, trueString) == 0);
459 xmlFree (value);
460 }
461 database.push_back (data);
462 }
463
464
465 /*******************************************************************************
466 **
467 ** Function: deleteFile
468 **
469 ** Description: Delete route data XML file.
470 **
471 ** Returns: True if ok.
472 **
473 *******************************************************************************/
deleteFile()474 bool RouteDataSet::deleteFile ()
475 {
476 static const char fn [] = "RouteDataSet::deleteFile";
477 std::string filename (bcm_nfc_location);
478 filename.append (sConfigFile);
479 int stat = remove (filename.c_str());
480 ALOGD ("%s: exit %u", fn, stat==0);
481 return stat == 0;
482 }
483
484
485 /*******************************************************************************
486 **
487 ** Function: getDatabase
488 **
489 ** Description: Obtain a database of routing data.
490 ** selection: which database.
491 **
492 ** Returns: Pointer to database.
493 **
494 *******************************************************************************/
getDatabase(DatabaseSelection selection)495 RouteDataSet::Database* RouteDataSet::getDatabase (DatabaseSelection selection)
496 {
497 switch (selection)
498 {
499 case DefaultRouteDatabase:
500 return &mDefaultRouteDatabase;
501 case SecElemRouteDatabase:
502 return &mSecElemRouteDatabase;
503 }
504 return NULL;
505 }
506
507
508 /*******************************************************************************
509 **
510 ** Function: printDiagnostic
511 **
512 ** Description: Print some diagnostic output.
513 **
514 ** Returns: None.
515 **
516 *******************************************************************************/
printDiagnostic()517 void RouteDataSet::printDiagnostic ()
518 {
519 static const char fn [] = "RouteDataSet::printDiagnostic";
520 Database* db = getDatabase (DefaultRouteDatabase);
521
522 ALOGD ("%s: default route database", fn);
523 for (Database::iterator iter = db->begin(); iter != db->end(); iter++)
524 {
525 RouteData* routeData = *iter;
526 switch (routeData->mRouteType)
527 {
528 case RouteData::ProtocolRoute:
529 {
530 RouteDataForProtocol* proto = (RouteDataForProtocol*) routeData;
531 ALOGD ("%s: ee h=0x%X; protocol=0x%X", fn, proto->mNfaEeHandle, proto->mProtocol);
532 }
533 break;
534 case RouteData::TechnologyRoute:
535 {
536 RouteDataForTechnology* tech = (RouteDataForTechnology*) routeData;
537 ALOGD ("%s: ee h=0x%X; technology=0x%X", fn, tech->mNfaEeHandle, tech->mTechnology);
538 }
539 break;
540 }
541 }
542
543 ALOGD ("%s: sec elem route database", fn);
544 db = getDatabase (SecElemRouteDatabase);
545 for (Database::iterator iter2 = db->begin(); iter2 != db->end(); iter2++)
546 {
547 RouteData* routeData = *iter2;
548 switch (routeData->mRouteType)
549 {
550 case RouteData::ProtocolRoute:
551 {
552 RouteDataForProtocol* proto = (RouteDataForProtocol*) routeData;
553 ALOGD ("%s: ee h=0x%X; protocol=0x%X", fn, proto->mNfaEeHandle, proto->mProtocol);
554 }
555 break;
556 case RouteData::TechnologyRoute:
557 {
558 RouteDataForTechnology* tech = (RouteDataForTechnology*) routeData;
559 ALOGD ("%s: ee h=0x%X; technology=0x%X", fn, tech->mNfaEeHandle, tech->mTechnology);
560 }
561 break;
562 }
563 }
564 }
565