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=%u; sec elem db size=%u", 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 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 ALOGD ("%s: wrote %u 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 chmod (filename.c_str (), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 275 return retval; 276 } 277 278 279 /******************************************************************************* 280 ** 281 ** Function: loadFromFile 282 ** 283 ** Description: Load XML data from file into a string. 284 ** routesXml: string to receive XML data. 285 ** 286 ** Returns: True if ok. 287 ** 288 *******************************************************************************/ 289 bool RouteDataSet::loadFromFile (std::string& routesXml) 290 { 291 static const char fn [] = "RouteDataSet::loadFromFile"; 292 FILE* fh = NULL; 293 size_t actual = 0; 294 char buffer [1024]; 295 std::string filename (bcm_nfc_location); 296 297 filename.append (sConfigFile); 298 fh = fopen (filename.c_str (), "r"); 299 if (fh == NULL) 300 { 301 ALOGD ("%s: fail to open file", fn); 302 return false; 303 } 304 305 while (true) 306 { 307 actual = fread (buffer, sizeof(char), sizeof(buffer), fh); 308 if (actual == 0) 309 break; 310 routesXml.append (buffer, actual); 311 } 312 fclose (fh); 313 ALOGD ("%s: read %u bytes", fn, routesXml.length()); 314 return true; 315 } 316 317 318 319 320 /******************************************************************************* 321 ** 322 ** Function: importProtocolRoute 323 ** 324 ** Description: Parse data for protocol routes. 325 ** element: XML node for one protocol route. 326 ** database: store data in this database. 327 ** 328 ** Returns: None. 329 ** 330 *******************************************************************************/ 331 void RouteDataSet::importProtocolRoute (xmlNodePtr& element, Database& database) 332 { 333 static const char fn [] = "RouteDataSet::importProtocolRoute"; 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 ALOGD_IF (sDebug, "%s: element=%s", fn, 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 ALOGD_IF (sDebug, "%s: %s=0x%X", fn, 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 ALOGD_IF (sDebug, "%s: %s=0x%X", fn, 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 *******************************************************************************/ 403 void RouteDataSet::importTechnologyRoute (xmlNodePtr& element, Database& database) 404 { 405 static const char fn [] = "RouteDataSet::importTechnologyRoute"; 406 const xmlChar* id = (const xmlChar*) "Id"; 407 const xmlChar* secElem = (const xmlChar*) "SecElem"; 408 const xmlChar* trueString = (const xmlChar*) "true"; 409 const xmlChar* switchOn = (const xmlChar*) "SwitchOn"; 410 const xmlChar* switchOff = (const xmlChar*) "SwitchOff"; 411 const xmlChar* batteryOff = (const xmlChar*) "BatteryOff"; 412 RouteDataForTechnology* data = new RouteDataForTechnology; 413 xmlChar* value = NULL; 414 415 ALOGD_IF (sDebug, "%s: element=%s", fn, element->name); 416 value = xmlGetProp (element, id); 417 if (value) 418 { 419 if (xmlStrcmp (value, (const xmlChar*) "NfcA") == 0) 420 data->mTechnology = NFA_TECHNOLOGY_MASK_A; 421 else if (xmlStrcmp (value, (const xmlChar*) "NfcB") == 0) 422 data->mTechnology = NFA_TECHNOLOGY_MASK_B; 423 else if (xmlStrcmp (value, (const xmlChar*) "NfcF") == 0) 424 data->mTechnology = NFA_TECHNOLOGY_MASK_F; 425 xmlFree (value); 426 ALOGD_IF (sDebug, "%s: %s=0x%X", fn, id, 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 ALOGD_IF (sDebug, "%s: %s=0x%X", fn, 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 *******************************************************************************/ 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 ALOGD ("%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 *******************************************************************************/ 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 *******************************************************************************/ 514 void RouteDataSet::printDiagnostic () 515 { 516 static const char fn [] = "RouteDataSet::printDiagnostic"; 517 Database* db = getDatabase (DefaultRouteDatabase); 518 519 ALOGD ("%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 ALOGD ("%s: ee h=0x%X; protocol=0x%X", fn, proto->mNfaEeHandle, proto->mProtocol); 529 } 530 break; 531 // TODO: RouteData::TechnologyRoute isn't handled --- bug? 532 } 533 } 534 535 ALOGD ("%s: sec elem route database", fn); 536 db = getDatabase (SecElemRouteDatabase); 537 for (Database::iterator iter2 = db->begin(); iter2 != db->end(); iter2++) 538 { 539 RouteData* routeData = *iter2; 540 switch (routeData->mRouteType) 541 { 542 case RouteData::ProtocolRoute: 543 { 544 RouteDataForProtocol* proto = (RouteDataForProtocol*) routeData; 545 ALOGD ("%s: ee h=0x%X; protocol=0x%X", fn, proto->mNfaEeHandle, proto->mProtocol); 546 } 547 break; 548 case RouteData::TechnologyRoute: 549 { 550 RouteDataForTechnology* tech = (RouteDataForTechnology*) routeData; 551 ALOGD ("%s: ee h=0x%X; technology=0x%X", fn, tech->mNfaEeHandle, tech->mTechnology); 552 } 553 break; 554 } 555 } 556 } 557