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_t [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_t) 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_t) 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 ALOGV("%s: enter", "RouteDataSet::initialize");
122 //check that the libxml2 version in use is compatible
123 //with the version the software has been compiled with
124 LIBXML_TEST_VERSION
125 ALOGV("%s: exit; return=true", "RouteDataSet::initialize");
126 return true;
127 }
128
129
130 /*******************************************************************************
131 **
132 ** Function: deleteDatabase
133 **
134 ** Description: Delete all routes stored in all databases.
135 **
136 ** Returns: None.
137 **
138 *******************************************************************************/
deleteDatabase()139 void RouteDataSet::deleteDatabase()
140 {
141 ALOGV("%s: default db size=%zu; sec elem db size=%zu", "RouteDataSet::deleteDatabase",
142 mDefaultRouteDatabase.size(), mSecElemRouteDatabase.size());
143 Database::iterator it;
144
145 for (it = mDefaultRouteDatabase.begin(); it != mDefaultRouteDatabase.end(); it++)
146 delete (*it);
147 mDefaultRouteDatabase.clear ();
148
149 for (it = mSecElemRouteDatabase.begin(); it != mSecElemRouteDatabase.end(); it++)
150 delete (*it);
151 mSecElemRouteDatabase.clear ();
152 }
153
154
155 /*******************************************************************************
156 **
157 ** Function: import
158 **
159 ** Description: Import data from an XML file. Fill the databases.
160 **
161 ** Returns: True if ok.
162 **
163 *******************************************************************************/
import()164 bool RouteDataSet::import ()
165 {
166 static const char fn [] = "RouteDataSet::import";
167 ALOGV("%s: enter", fn);
168 bool retval = false;
169 xmlDocPtr doc;
170 xmlNodePtr node1;
171 std::string strFilename(bcm_nfc_location);
172 strFilename += sConfigFile;
173
174 deleteDatabase ();
175
176 doc = xmlParseFile (strFilename.c_str());
177 if (doc == NULL)
178 {
179 ALOGV("%s: fail parse", fn);
180 goto TheEnd;
181 }
182
183 node1 = xmlDocGetRootElement (doc);
184 if (node1 == NULL)
185 {
186 ALOGE("%s: fail root element", fn);
187 goto TheEnd;
188 }
189 ALOGV("%s: root=%s", fn, node1->name);
190
191 node1 = node1->xmlChildrenNode;
192 while (node1) //loop through all elements in <Routes ...
193 {
194 if (xmlStrcmp(node1->name, (const xmlChar*) "Route")==0)
195 {
196 xmlChar* value = xmlGetProp (node1, (const xmlChar*) "Type");
197 if (value && (xmlStrcmp (value, (const xmlChar*) "SecElemSelectedRoutes") == 0))
198 {
199 ALOGV("%s: found SecElemSelectedRoutes", fn);
200 xmlNodePtr node2 = node1->xmlChildrenNode;
201 while (node2) //loop all elements in <Route Type="SecElemSelectedRoutes" ...
202 {
203 if (xmlStrcmp(node2->name, (const xmlChar*) "Proto")==0)
204 importProtocolRoute (node2, mSecElemRouteDatabase);
205 else if (xmlStrcmp(node2->name, (const xmlChar*) "Tech")==0)
206 importTechnologyRoute (node2, mSecElemRouteDatabase);
207 node2 = node2->next;
208 } //loop all elements in <Route Type="SecElemSelectedRoutes" ...
209 }
210 else if (value && (xmlStrcmp (value, (const xmlChar*) "DefaultRoutes") == 0))
211 {
212 ALOGV("%s: found DefaultRoutes", fn);
213 xmlNodePtr node2 = node1->xmlChildrenNode;
214 while (node2) //loop all elements in <Route Type="DefaultRoutes" ...
215 {
216 if (xmlStrcmp(node2->name, (const xmlChar*) "Proto")==0)
217 importProtocolRoute (node2, mDefaultRouteDatabase);
218 else if (xmlStrcmp(node2->name, (const xmlChar*) "Tech")==0)
219 importTechnologyRoute (node2, mDefaultRouteDatabase);
220 node2 = node2->next;
221 } //loop all elements in <Route Type="DefaultRoutes" ...
222 }
223 if (value)
224 xmlFree (value);
225 } //check <Route ...
226 node1 = node1->next;
227 } //loop through all elements in <Routes ...
228 retval = true;
229
230 TheEnd:
231 xmlFreeDoc (doc);
232 xmlCleanupParser ();
233 ALOGV("%s: exit; return=%u", fn, retval);
234 return retval;
235 }
236
237
238 /*******************************************************************************
239 **
240 ** Function: saveToFile
241 **
242 ** Description: Save XML data from a string into a file.
243 ** routesXml: XML that represents routes.
244 **
245 ** Returns: True if ok.
246 **
247 *******************************************************************************/
saveToFile(const char * routesXml)248 bool RouteDataSet::saveToFile (const char* routesXml)
249 {
250 static const char fn [] = "RouteDataSet::saveToFile";
251 FILE* fh = NULL;
252 size_t actualWritten = 0;
253 bool retval = false;
254 std::string filename (bcm_nfc_location);
255 int stat = 0;
256
257 filename.append (sConfigFile);
258 fh = fopen (filename.c_str (), "w");
259 if (fh == NULL)
260 {
261 ALOGE("%s: fail to open file", fn);
262 return false;
263 }
264
265 actualWritten = fwrite (routesXml, sizeof(char), strlen(routesXml), fh);
266 retval = actualWritten == strlen(routesXml);
267 fclose (fh);
268 ALOGV("%s: wrote %zu bytes", fn, actualWritten);
269 if (retval == false)
270 ALOGE("%s: error during write", fn);
271
272 //set file permission to
273 //owner read, write; group read; other read
274 stat = chmod (filename.c_str (), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
275 if (stat == -1)
276 ALOGE("%s: error during chmod", fn);
277 return retval;
278 }
279
280
281 /*******************************************************************************
282 **
283 ** Function: loadFromFile
284 **
285 ** Description: Load XML data from file into a string.
286 ** routesXml: string to receive XML data.
287 **
288 ** Returns: True if ok.
289 **
290 *******************************************************************************/
loadFromFile(std::string & routesXml)291 bool RouteDataSet::loadFromFile (std::string& routesXml)
292 {
293 FILE* fh = NULL;
294 size_t actual = 0;
295 char buffer [1024];
296 std::string filename (bcm_nfc_location);
297
298 filename.append (sConfigFile);
299 fh = fopen (filename.c_str (), "r");
300 if (fh == NULL)
301 {
302 ALOGV("%s: fail to open file", "RouteDataSet::loadFromFile");
303 return false;
304 }
305
306 while (true)
307 {
308 actual = fread (buffer, sizeof(char), sizeof(buffer), fh);
309 if (actual == 0)
310 break;
311 routesXml.append (buffer, actual);
312 }
313 fclose (fh);
314 ALOGV("%s: read %zu bytes", "RouteDataSet::loadFromFile", routesXml.length());
315 return true;
316 }
317
318
319
320
321 /*******************************************************************************
322 **
323 ** Function: importProtocolRoute
324 **
325 ** Description: Parse data for protocol routes.
326 ** element: XML node for one protocol route.
327 ** database: store data in this database.
328 **
329 ** Returns: None.
330 **
331 *******************************************************************************/
importProtocolRoute(xmlNodePtr & element,Database & database)332 void RouteDataSet::importProtocolRoute (xmlNodePtr& element, Database& database)
333 {
334 const xmlChar* id = (const xmlChar*) "Id";
335 const xmlChar* secElem = (const xmlChar*) "SecElem";
336 const xmlChar* trueString = (const xmlChar*) "true";
337 const xmlChar* switchOn = (const xmlChar*) "SwitchOn";
338 const xmlChar* switchOff = (const xmlChar*) "SwitchOff";
339 const xmlChar* batteryOff = (const xmlChar*) "BatteryOff";
340 RouteDataForProtocol* data = new RouteDataForProtocol;
341 xmlChar* value = NULL;
342
343 ALOGV_IF(sDebug, "%s: element=%s", "RouteDataSet::importProtocolRoute", element->name);
344 value = xmlGetProp (element, id);
345 if (value)
346 {
347 if (xmlStrcmp (value, (const xmlChar*) "T1T") == 0)
348 data->mProtocol = NFA_PROTOCOL_MASK_T1T;
349 else if (xmlStrcmp (value, (const xmlChar*) "T2T") == 0)
350 data->mProtocol = NFA_PROTOCOL_MASK_T2T;
351 else if (xmlStrcmp (value, (const xmlChar*) "T3T") == 0)
352 data->mProtocol = NFA_PROTOCOL_MASK_T3T;
353 else if (xmlStrcmp (value, (const xmlChar*) "IsoDep") == 0)
354 data->mProtocol = NFA_PROTOCOL_MASK_ISO_DEP;
355 xmlFree (value);
356 ALOGV_IF(sDebug, "%s: %s=0x%X", "RouteDataSet::importProtocolRoute", id, data->mProtocol);
357 }
358
359 value = xmlGetProp (element, secElem);
360 if (value)
361 {
362 data->mNfaEeHandle = strtol ((char*) value, NULL, 16);
363 xmlFree (value);
364 data->mNfaEeHandle = data->mNfaEeHandle | NFA_HANDLE_GROUP_EE;
365 ALOGV_IF(sDebug, "%s: %s=0x%X", "RouteDataSet::importProtocolRoute", secElem, data->mNfaEeHandle);
366 }
367
368 value = xmlGetProp (element, switchOn);
369 if (value)
370 {
371 data->mSwitchOn = (xmlStrcmp (value, trueString) == 0);
372 xmlFree (value);
373 }
374
375 value = xmlGetProp (element, switchOff);
376 if (value)
377 {
378 data->mSwitchOff = (xmlStrcmp (value, trueString) == 0);
379 xmlFree (value);
380 }
381
382 value = xmlGetProp (element, batteryOff);
383 if (value)
384 {
385 data->mBatteryOff = (xmlStrcmp (value, trueString) == 0);
386 xmlFree (value);
387 }
388 database.push_back (data);
389 }
390
391
392 /*******************************************************************************
393 **
394 ** Function: importTechnologyRoute
395 **
396 ** Description: Parse data for technology routes.
397 ** element: XML node for one technology route.
398 ** database: store data in this database.
399 **
400 ** Returns: None.
401 **
402 *******************************************************************************/
importTechnologyRoute(xmlNodePtr & element,Database & database)403 void RouteDataSet::importTechnologyRoute (xmlNodePtr& element, Database& database)
404 {
405 const xmlChar* id = (const xmlChar*) "Id";
406 const xmlChar* secElem = (const xmlChar*) "SecElem";
407 const xmlChar* trueString = (const xmlChar*) "true";
408 const xmlChar* switchOn = (const xmlChar*) "SwitchOn";
409 const xmlChar* switchOff = (const xmlChar*) "SwitchOff";
410 const xmlChar* batteryOff = (const xmlChar*) "BatteryOff";
411 RouteDataForTechnology* data = new RouteDataForTechnology;
412 xmlChar* value = NULL;
413
414 ALOGV_IF(sDebug, "%s: element=%s", "RouteDataSet::importTechnologyRoute", element->name);
415 value = xmlGetProp (element, id);
416 if (value)
417 {
418 if (xmlStrcmp (value, (const xmlChar*) "NfcA") == 0)
419 data->mTechnology = NFA_TECHNOLOGY_MASK_A;
420 else if (xmlStrcmp (value, (const xmlChar*) "NfcB") == 0)
421 data->mTechnology = NFA_TECHNOLOGY_MASK_B;
422 else if (xmlStrcmp (value, (const xmlChar*) "NfcF") == 0)
423 data->mTechnology = NFA_TECHNOLOGY_MASK_F;
424 xmlFree (value);
425 ALOGV_IF(sDebug, "%s: %s=0x%X", "RouteDataSet::importTechnologyRoute", id,
426 data->mTechnology);
427 }
428
429 value = xmlGetProp (element, secElem);
430 if (value)
431 {
432 data->mNfaEeHandle = strtol ((char*) value, NULL, 16);
433 xmlFree (value);
434 data->mNfaEeHandle = data->mNfaEeHandle | NFA_HANDLE_GROUP_EE;
435 ALOGV_IF(sDebug, "%s: %s=0x%X", "RouteDataSet::importTechnologyRoute", secElem, data->mNfaEeHandle);
436 }
437
438 value = xmlGetProp (element, switchOn);
439 if (value)
440 {
441 data->mSwitchOn = (xmlStrcmp (value, trueString) == 0);
442 xmlFree (value);
443 }
444
445 value = xmlGetProp (element, switchOff);
446 if (value)
447 {
448 data->mSwitchOff = (xmlStrcmp (value, trueString) == 0);
449 xmlFree (value);
450 }
451
452 value = xmlGetProp (element, batteryOff);
453 if (value)
454 {
455 data->mBatteryOff = (xmlStrcmp (value, trueString) == 0);
456 xmlFree (value);
457 }
458 database.push_back (data);
459 }
460
461
462 /*******************************************************************************
463 **
464 ** Function: deleteFile
465 **
466 ** Description: Delete route data XML file.
467 **
468 ** Returns: True if ok.
469 **
470 *******************************************************************************/
deleteFile()471 bool RouteDataSet::deleteFile ()
472 {
473 static const char fn [] = "RouteDataSet::deleteFile";
474 std::string filename (bcm_nfc_location);
475 filename.append (sConfigFile);
476 int stat = remove (filename.c_str());
477 ALOGV("%s: exit %u", fn, stat==0);
478 return stat == 0;
479 }
480
481
482 /*******************************************************************************
483 **
484 ** Function: getDatabase
485 **
486 ** Description: Obtain a database of routing data.
487 ** selection: which database.
488 **
489 ** Returns: Pointer to database.
490 **
491 *******************************************************************************/
getDatabase(DatabaseSelection selection)492 RouteDataSet::Database* RouteDataSet::getDatabase (DatabaseSelection selection)
493 {
494 switch (selection)
495 {
496 case DefaultRouteDatabase:
497 return &mDefaultRouteDatabase;
498 case SecElemRouteDatabase:
499 return &mSecElemRouteDatabase;
500 }
501 return NULL;
502 }
503
504
505 /*******************************************************************************
506 **
507 ** Function: printDiagnostic
508 **
509 ** Description: Print some diagnostic output.
510 **
511 ** Returns: None.
512 **
513 *******************************************************************************/
printDiagnostic()514 void RouteDataSet::printDiagnostic ()
515 {
516 static const char fn [] = "RouteDataSet::printDiagnostic";
517 Database* db = getDatabase (DefaultRouteDatabase);
518
519 ALOGV("%s: default route database", fn);
520 for (Database::iterator iter = db->begin(); iter != db->end(); iter++)
521 {
522 RouteData* routeData = *iter;
523 switch (routeData->mRouteType)
524 {
525 case RouteData::ProtocolRoute:
526 {
527 RouteDataForProtocol* proto = (RouteDataForProtocol*) routeData;
528 ALOGV("%s: ee h=0x%X; protocol=0x%X", fn, proto->mNfaEeHandle, proto->mProtocol);
529 }
530 break;
531 case RouteData::TechnologyRoute:
532 {
533 RouteDataForTechnology* tech = (RouteDataForTechnology*) routeData;
534 ALOGV("%s: ee h=0x%X; technology=0x%X", fn, tech->mNfaEeHandle, tech->mTechnology);
535 }
536 break;
537 }
538 }
539
540 ALOGV("%s: sec elem route database", fn);
541 db = getDatabase (SecElemRouteDatabase);
542 for (Database::iterator iter2 = db->begin(); iter2 != db->end(); iter2++)
543 {
544 RouteData* routeData = *iter2;
545 switch (routeData->mRouteType)
546 {
547 case RouteData::ProtocolRoute:
548 {
549 RouteDataForProtocol* proto = (RouteDataForProtocol*) routeData;
550 ALOGV("%s: ee h=0x%X; protocol=0x%X", fn, proto->mNfaEeHandle, proto->mProtocol);
551 }
552 break;
553 case RouteData::TechnologyRoute:
554 {
555 RouteDataForTechnology* tech = (RouteDataForTechnology*) routeData;
556 ALOGV("%s: ee h=0x%X; technology=0x%X", fn, tech->mNfaEeHandle, tech->mTechnology);
557 }
558 break;
559 }
560 }
561 }
562