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 26extern 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*******************************************************************************/ 40AidBuffer::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*******************************************************************************/ 82AidBuffer::~AidBuffer () 83{ 84 delete [] mBuffer; 85} 86 87 88/*******************************************************************************/ 89/*******************************************************************************/ 90 91 92const 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*******************************************************************************/ 104RouteDataSet::~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*******************************************************************************/ 119bool 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*******************************************************************************/ 140void 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*******************************************************************************/ 165bool 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 231TheEnd: 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*******************************************************************************/ 249bool 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*******************************************************************************/ 292bool 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*******************************************************************************/ 334void 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*******************************************************************************/ 406void 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*******************************************************************************/ 474bool 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*******************************************************************************/ 495RouteDataSet::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*******************************************************************************/ 517void 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