• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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