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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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 *******************************************************************************/ 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