1 /*
2  * Copyright (C) 2013 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  *  Manage the listen-mode routing table.
19  */
20 
21 #include <cutils/log.h>
22 #include <ScopedLocalRef.h>
23 #include <JNIHelp.h>
24 #include "config.h"
25 #include "JavaClassConstants.h"
26 #include "RoutingManager.h"
27 
28 extern "C"
29 {
30     #include "nfa_ee_api.h"
31     #include "nfa_ce_api.h"
32 }
33 extern bool gActivated;
34 extern SyncEvent gDeactivatedEvent;
35 
36 
37 const JNINativeMethod RoutingManager::sMethods [] =
38 {
39     {"doGetDefaultRouteDestination", "()I", (void*) RoutingManager::com_android_nfc_cardemulation_doGetDefaultRouteDestination},
40     {"doGetDefaultOffHostRouteDestination", "()I", (void*) RoutingManager::com_android_nfc_cardemulation_doGetDefaultOffHostRouteDestination},
41     {"doGetAidMatchingMode", "()I", (void*) RoutingManager::com_android_nfc_cardemulation_doGetAidMatchingMode}
42 };
43 
44 static const int MAX_NUM_EE = 5;
45 
RoutingManager()46 RoutingManager::RoutingManager ()
47 {
48     static const char fn [] = "RoutingManager::RoutingManager()";
49     unsigned long num = 0;
50 
51     // Get the active SE
52     if (GetNumValue("ACTIVE_SE", &num, sizeof(num)))
53         mActiveSe = num;
54     else
55         mActiveSe = 0x00;
56 
57     // Get the "default" route
58     if (GetNumValue("DEFAULT_ISODEP_ROUTE", &num, sizeof(num)))
59         mDefaultEe = num;
60     else
61         mDefaultEe = 0x00;
62     ALOGD("%s: default route is 0x%02X", fn, mDefaultEe);
63 
64     // Get the default "off-host" route.  This is hard-coded at the Java layer
65     // but we can override it here to avoid forcing Java changes.
66     if (GetNumValue("DEFAULT_OFFHOST_ROUTE", &num, sizeof(num)))
67         mOffHostEe = num;
68     else
69         mOffHostEe = 0xf4;
70 
71     if (GetNumValue("AID_MATCHING_MODE", &num, sizeof(num)))
72         mAidMatchingMode = num;
73     else
74         mAidMatchingMode = AID_MATCHING_EXACT_ONLY;
75 
76     ALOGD("%s: mOffHostEe=0x%02X", fn, mOffHostEe);
77 
78     memset (&mEeInfo, 0, sizeof(mEeInfo));
79     mReceivedEeInfo = false;
80     mSeTechMask = 0x00;
81 }
82 
~RoutingManager()83 RoutingManager::~RoutingManager ()
84 {
85     NFA_EeDeregister (nfaEeCallback);
86 }
87 
initialize(nfc_jni_native_data * native)88 bool RoutingManager::initialize (nfc_jni_native_data* native)
89 {
90     static const char fn [] = "RoutingManager::initialize()";
91     mNativeData = native;
92 
93     tNFA_STATUS nfaStat;
94     {
95         SyncEventGuard guard (mEeRegisterEvent);
96         ALOGD ("%s: try ee register", fn);
97         nfaStat = NFA_EeRegister (nfaEeCallback);
98         if (nfaStat != NFA_STATUS_OK)
99         {
100             ALOGE ("%s: fail ee register; error=0x%X", fn, nfaStat);
101             return false;
102         }
103         mEeRegisterEvent.wait ();
104     }
105 
106     mRxDataBuffer.clear ();
107 
108     if (mActiveSe != 0) {
109         {
110             // Wait for EE info if needed
111             SyncEventGuard guard (mEeInfoEvent);
112             if (!mReceivedEeInfo)
113             {
114                 ALOGE("Waiting for EE info");
115                 mEeInfoEvent.wait();
116             }
117         }
118         for (UINT8 i = 0; i < mEeInfo.num_ee; i++)
119         {
120              ALOGD ("%s   EE[%u] Handle: 0x%04x  techA: 0x%02x  techB: 0x%02x  techF: 0x%02x  techBprime: 0x%02x",
121                 fn, i, mEeInfo.ee_disc_info[i].ee_handle,
122                 mEeInfo.ee_disc_info[i].la_protocol,
123                 mEeInfo.ee_disc_info[i].lb_protocol,
124                 mEeInfo.ee_disc_info[i].lf_protocol,
125                 mEeInfo.ee_disc_info[i].lbp_protocol);
126              if (mEeInfo.ee_disc_info[i].ee_handle == (mActiveSe | NFA_HANDLE_GROUP_EE))
127              {
128                  if (mEeInfo.ee_disc_info[i].la_protocol != 0) mSeTechMask |= NFA_TECHNOLOGY_MASK_A;
129 
130                  if (mSeTechMask != 0x00)
131                  {
132                      ALOGD("Configuring tech mask 0x%02x on EE 0x%04x", mSeTechMask, mEeInfo.ee_disc_info[i].ee_handle);
133                      nfaStat = NFA_CeConfigureUiccListenTech(mEeInfo.ee_disc_info[i].ee_handle, mSeTechMask);
134                      if (nfaStat != NFA_STATUS_OK)
135                          ALOGE ("Failed to configure UICC listen technologies.");
136                      // Set technology routes to UICC if it's there
137                      nfaStat = NFA_EeSetDefaultTechRouting(mEeInfo.ee_disc_info[i].ee_handle, mSeTechMask, mSeTechMask,
138                              mSeTechMask);
139                      if (nfaStat != NFA_STATUS_OK)
140                          ALOGE ("Failed to configure UICC technology routing.");
141                  }
142              }
143         }
144     }
145 
146     // Tell the host-routing to only listen on Nfc-A
147     nfaStat = NFA_CeSetIsoDepListenTech(NFA_TECHNOLOGY_MASK_A);
148     if (nfaStat != NFA_STATUS_OK)
149         ALOGE ("Failed to configure CE IsoDep technologies");
150 
151     // Register a wild-card for AIDs routed to the host
152     nfaStat = NFA_CeRegisterAidOnDH (NULL, 0, stackCallback);
153     if (nfaStat != NFA_STATUS_OK)
154         ALOGE("Failed to register wildcard AID for DH");
155 
156     return true;
157 }
158 
getInstance()159 RoutingManager& RoutingManager::getInstance ()
160 {
161     static RoutingManager manager;
162     return manager;
163 }
164 
enableRoutingToHost()165 void RoutingManager::enableRoutingToHost()
166 {
167     tNFA_STATUS nfaStat;
168 
169     {
170         SyncEventGuard guard (mRoutingEvent);
171 
172         // Route Nfc-A to host if we don't have a SE
173         if (mSeTechMask == 0)
174         {
175             nfaStat = NFA_EeSetDefaultTechRouting (mDefaultEe, NFA_TECHNOLOGY_MASK_A, 0, 0);
176             if (nfaStat == NFA_STATUS_OK)
177                 mRoutingEvent.wait ();
178             else
179                 ALOGE ("Fail to set default tech routing");
180         }
181 
182         // Default routing for IsoDep protocol
183         nfaStat = NFA_EeSetDefaultProtoRouting(mDefaultEe, NFA_PROTOCOL_MASK_ISO_DEP, 0, 0);
184         if (nfaStat == NFA_STATUS_OK)
185             mRoutingEvent.wait ();
186         else
187             ALOGE ("Fail to set default proto routing");
188     }
189 }
190 
disableRoutingToHost()191 void RoutingManager::disableRoutingToHost()
192 {
193     tNFA_STATUS nfaStat;
194 
195     {
196         SyncEventGuard guard (mRoutingEvent);
197         // Default routing for NFC-A technology if we don't have a SE
198         if (mSeTechMask == 0)
199         {
200             nfaStat = NFA_EeSetDefaultTechRouting (mDefaultEe, 0, 0, 0);
201             if (nfaStat == NFA_STATUS_OK)
202                 mRoutingEvent.wait ();
203             else
204                 ALOGE ("Fail to set default tech routing");
205         }
206 
207         // Default routing for IsoDep protocol
208         nfaStat = NFA_EeSetDefaultProtoRouting(mDefaultEe, 0, 0, 0);
209         if (nfaStat == NFA_STATUS_OK)
210             mRoutingEvent.wait ();
211         else
212             ALOGE ("Fail to set default proto routing");
213     }
214 }
215 
addAidRouting(const UINT8 * aid,UINT8 aidLen,int route)216 bool RoutingManager::addAidRouting(const UINT8* aid, UINT8 aidLen, int route)
217 {
218     static const char fn [] = "RoutingManager::addAidRouting";
219     ALOGD ("%s: enter", fn);
220     tNFA_STATUS nfaStat = NFA_EeAddAidRouting(route, aidLen, (UINT8*) aid, 0x01);
221     if (nfaStat == NFA_STATUS_OK)
222     {
223         ALOGD ("%s: routed AID", fn);
224         return true;
225     } else
226     {
227         ALOGE ("%s: failed to route AID", fn);
228         return false;
229     }
230 }
231 
removeAidRouting(const UINT8 * aid,UINT8 aidLen)232 bool RoutingManager::removeAidRouting(const UINT8* aid, UINT8 aidLen)
233 {
234     static const char fn [] = "RoutingManager::removeAidRouting";
235     ALOGD ("%s: enter", fn);
236     tNFA_STATUS nfaStat = NFA_EeRemoveAidRouting(aidLen, (UINT8*) aid);
237     if (nfaStat == NFA_STATUS_OK)
238     {
239         ALOGD ("%s: removed AID", fn);
240         return true;
241     } else
242     {
243         ALOGE ("%s: failed to remove AID", fn);
244         return false;
245     }
246 }
247 
commitRouting()248 bool RoutingManager::commitRouting()
249 {
250     static const char fn [] = "RoutingManager::commitRouting";
251     tNFA_STATUS nfaStat = 0;
252     ALOGD ("%s", fn);
253     {
254         SyncEventGuard guard (mEeUpdateEvent);
255         nfaStat = NFA_EeUpdateNow();
256         if (nfaStat == NFA_STATUS_OK)
257         {
258             mEeUpdateEvent.wait (); //wait for NFA_EE_UPDATED_EVT
259         }
260     }
261     return (nfaStat == NFA_STATUS_OK);
262 }
263 
onNfccShutdown()264 void RoutingManager::onNfccShutdown ()
265 {
266     static const char fn [] = "RoutingManager:onNfccShutdown";
267     if (mActiveSe == 0x00) return;
268 
269     tNFA_STATUS nfaStat = NFA_STATUS_FAILED;
270     UINT8 actualNumEe = MAX_NUM_EE;
271     tNFA_EE_INFO eeInfo[MAX_NUM_EE];
272 
273     memset (&eeInfo, 0, sizeof(eeInfo));
274     if ((nfaStat = NFA_EeGetInfo (&actualNumEe, eeInfo)) != NFA_STATUS_OK)
275     {
276         ALOGE ("%s: fail get info; error=0x%X", fn, nfaStat);
277         return;
278     }
279     if (actualNumEe != 0)
280     {
281         for (UINT8 xx = 0; xx < actualNumEe; xx++)
282         {
283             if ((eeInfo[xx].num_interface != 0)
284                 && (eeInfo[xx].ee_interface[0] != NCI_NFCEE_INTERFACE_HCI_ACCESS)
285                 && (eeInfo[xx].ee_status == NFA_EE_STATUS_ACTIVE))
286             {
287                 ALOGD ("%s: Handle: 0x%04x Change Status Active to Inactive", fn, eeInfo[xx].ee_handle);
288                 SyncEventGuard guard (mEeSetModeEvent);
289                 if ((nfaStat = NFA_EeModeSet (eeInfo[xx].ee_handle, NFA_EE_MD_DEACTIVATE)) == NFA_STATUS_OK)
290                 {
291                     mEeSetModeEvent.wait (); //wait for NFA_EE_MODE_SET_EVT
292                 }
293                 else
294                 {
295                     ALOGE ("Failed to set EE inactive");
296                 }
297             }
298         }
299     }
300     else
301     {
302         ALOGD ("%s: No active EEs found", fn);
303     }
304 }
305 
notifyActivated()306 void RoutingManager::notifyActivated ()
307 {
308     JNIEnv* e = NULL;
309     ScopedAttach attach(mNativeData->vm, &e);
310     if (e == NULL)
311     {
312         ALOGE ("jni env is null");
313         return;
314     }
315 
316     e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifyHostEmuActivated);
317     if (e->ExceptionCheck())
318     {
319         e->ExceptionClear();
320         ALOGE ("fail notify");
321     }
322 }
323 
notifyDeactivated()324 void RoutingManager::notifyDeactivated ()
325 {
326     mRxDataBuffer.clear();
327     JNIEnv* e = NULL;
328     ScopedAttach attach(mNativeData->vm, &e);
329     if (e == NULL)
330     {
331         ALOGE ("jni env is null");
332         return;
333     }
334 
335     e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifyHostEmuDeactivated);
336     if (e->ExceptionCheck())
337     {
338         e->ExceptionClear();
339         ALOGE ("fail notify");
340     }
341 }
342 
handleData(const UINT8 * data,UINT32 dataLen,tNFA_STATUS status)343 void RoutingManager::handleData (const UINT8* data, UINT32 dataLen, tNFA_STATUS status)
344 {
345     if (dataLen <= 0)
346     {
347         ALOGE("no data");
348         goto TheEnd;
349     }
350 
351     if (status == NFA_STATUS_CONTINUE)
352     {
353         mRxDataBuffer.insert (mRxDataBuffer.end(), &data[0], &data[dataLen]); //append data; more to come
354         return; //expect another NFA_CE_DATA_EVT to come
355     }
356     else if (status == NFA_STATUS_OK)
357     {
358         mRxDataBuffer.insert (mRxDataBuffer.end(), &data[0], &data[dataLen]); //append data
359         //entire data packet has been received; no more NFA_CE_DATA_EVT
360     }
361     else if (status == NFA_STATUS_FAILED)
362     {
363         ALOGE("RoutingManager::handleData: read data fail");
364         goto TheEnd;
365     }
366 
367     {
368         JNIEnv* e = NULL;
369         ScopedAttach attach(mNativeData->vm, &e);
370         if (e == NULL)
371         {
372             ALOGE ("jni env is null");
373             goto TheEnd;
374         }
375 
376         ScopedLocalRef<jobject> dataJavaArray(e, e->NewByteArray(mRxDataBuffer.size()));
377         if (dataJavaArray.get() == NULL)
378         {
379             ALOGE ("fail allocate array");
380             goto TheEnd;
381         }
382 
383         e->SetByteArrayRegion ((jbyteArray)dataJavaArray.get(), 0, mRxDataBuffer.size(),
384                 (jbyte *)(&mRxDataBuffer[0]));
385         if (e->ExceptionCheck())
386         {
387             e->ExceptionClear();
388             ALOGE ("fail fill array");
389             goto TheEnd;
390         }
391 
392         e->CallVoidMethod (mNativeData->manager, android::gCachedNfcManagerNotifyHostEmuData, dataJavaArray.get());
393         if (e->ExceptionCheck())
394         {
395             e->ExceptionClear();
396             ALOGE ("fail notify");
397         }
398     }
399 TheEnd:
400     mRxDataBuffer.clear();
401 }
402 
stackCallback(UINT8 event,tNFA_CONN_EVT_DATA * eventData)403 void RoutingManager::stackCallback (UINT8 event, tNFA_CONN_EVT_DATA* eventData)
404 {
405     static const char fn [] = "RoutingManager::stackCallback";
406     ALOGD("%s: event=0x%X", fn, event);
407     RoutingManager& routingManager = RoutingManager::getInstance();
408 
409     switch (event)
410     {
411     case NFA_CE_REGISTERED_EVT:
412         {
413             tNFA_CE_REGISTERED& ce_registered = eventData->ce_registered;
414             ALOGD("%s: NFA_CE_REGISTERED_EVT; status=0x%X; h=0x%X", fn, ce_registered.status, ce_registered.handle);
415         }
416         break;
417 
418     case NFA_CE_DEREGISTERED_EVT:
419         {
420             tNFA_CE_DEREGISTERED& ce_deregistered = eventData->ce_deregistered;
421             ALOGD("%s: NFA_CE_DEREGISTERED_EVT; h=0x%X", fn, ce_deregistered.handle);
422         }
423         break;
424 
425     case NFA_CE_ACTIVATED_EVT:
426         {
427             routingManager.notifyActivated();
428         }
429         break;
430 
431     case NFA_DEACTIVATED_EVT:
432     case NFA_CE_DEACTIVATED_EVT:
433         {
434             ALOGD("%s: NFA_DEACTIVATED_EVT, NFA_CE_DEACTIVATED_EVT", fn);
435             routingManager.notifyDeactivated();
436             SyncEventGuard g (gDeactivatedEvent);
437             gActivated = false; //guard this variable from multi-threaded access
438             gDeactivatedEvent.notifyOne ();
439         }
440         break;
441 
442     case NFA_CE_DATA_EVT:
443         {
444             tNFA_CE_DATA& ce_data = eventData->ce_data;
445             ALOGD("%s: NFA_CE_DATA_EVT; stat=0x%X; h=0x%X; data len=%u", fn, ce_data.status, ce_data.handle, ce_data.len);
446             getInstance().handleData(ce_data.p_data, ce_data.len, ce_data.status);
447         }
448         break;
449     }
450 }
451 /*******************************************************************************
452 **
453 ** Function:        nfaEeCallback
454 **
455 ** Description:     Receive execution environment-related events from stack.
456 **                  event: Event code.
457 **                  eventData: Event data.
458 **
459 ** Returns:         None
460 **
461 *******************************************************************************/
nfaEeCallback(tNFA_EE_EVT event,tNFA_EE_CBACK_DATA * eventData)462 void RoutingManager::nfaEeCallback (tNFA_EE_EVT event, tNFA_EE_CBACK_DATA* eventData)
463 {
464     static const char fn [] = "RoutingManager::nfaEeCallback";
465 
466     RoutingManager& routingManager = RoutingManager::getInstance();
467 
468     switch (event)
469     {
470     case NFA_EE_REGISTER_EVT:
471         {
472             SyncEventGuard guard (routingManager.mEeRegisterEvent);
473             ALOGD ("%s: NFA_EE_REGISTER_EVT; status=%u", fn, eventData->ee_register);
474             routingManager.mEeRegisterEvent.notifyOne();
475         }
476         break;
477 
478     case NFA_EE_MODE_SET_EVT:
479         {
480             SyncEventGuard guard (routingManager.mEeSetModeEvent);
481             ALOGD ("%s: NFA_EE_MODE_SET_EVT; status: 0x%04X  handle: 0x%04X  ", fn,
482                     eventData->mode_set.status, eventData->mode_set.ee_handle);
483             routingManager.mEeSetModeEvent.notifyOne();
484         }
485         break;
486 
487     case NFA_EE_SET_TECH_CFG_EVT:
488         {
489             ALOGD ("%s: NFA_EE_SET_TECH_CFG_EVT; status=0x%X", fn, eventData->status);
490             SyncEventGuard guard(routingManager.mRoutingEvent);
491             routingManager.mRoutingEvent.notifyOne();
492         }
493         break;
494 
495     case NFA_EE_SET_PROTO_CFG_EVT:
496         {
497             ALOGD ("%s: NFA_EE_SET_PROTO_CFG_EVT; status=0x%X", fn, eventData->status);
498             SyncEventGuard guard(routingManager.mRoutingEvent);
499             routingManager.mRoutingEvent.notifyOne();
500         }
501         break;
502 
503     case NFA_EE_ACTION_EVT:
504         {
505             tNFA_EE_ACTION& action = eventData->action;
506             if (action.trigger == NFC_EE_TRIG_SELECT)
507                 ALOGD ("%s: NFA_EE_ACTION_EVT; h=0x%X; trigger=select (0x%X)", fn, action.ee_handle, action.trigger);
508             else if (action.trigger == NFC_EE_TRIG_APP_INIT)
509             {
510                 tNFC_APP_INIT& app_init = action.param.app_init;
511                 ALOGD ("%s: NFA_EE_ACTION_EVT; h=0x%X; trigger=app-init (0x%X); aid len=%u; data len=%u", fn,
512                         action.ee_handle, action.trigger, app_init.len_aid, app_init.len_data);
513             }
514             else if (action.trigger == NFC_EE_TRIG_RF_PROTOCOL)
515                 ALOGD ("%s: NFA_EE_ACTION_EVT; h=0x%X; trigger=rf protocol (0x%X)", fn, action.ee_handle, action.trigger);
516             else if (action.trigger == NFC_EE_TRIG_RF_TECHNOLOGY)
517                 ALOGD ("%s: NFA_EE_ACTION_EVT; h=0x%X; trigger=rf tech (0x%X)", fn, action.ee_handle, action.trigger);
518             else
519                 ALOGE ("%s: NFA_EE_ACTION_EVT; h=0x%X; unknown trigger (0x%X)", fn, action.ee_handle, action.trigger);
520         }
521         break;
522 
523     case NFA_EE_DISCOVER_REQ_EVT:
524         {
525             ALOGD ("%s: NFA_EE_DISCOVER_REQ_EVT; status=0x%X; num ee=%u", __FUNCTION__,
526                     eventData->discover_req.status, eventData->discover_req.num_ee);
527             SyncEventGuard guard (routingManager.mEeInfoEvent);
528             memcpy (&routingManager.mEeInfo, &eventData->discover_req, sizeof(routingManager.mEeInfo));
529             routingManager.mReceivedEeInfo = true;
530             routingManager.mEeInfoEvent.notifyOne();
531         }
532         break;
533 
534     case NFA_EE_NO_CB_ERR_EVT:
535         ALOGD ("%s: NFA_EE_NO_CB_ERR_EVT  status=%u", fn, eventData->status);
536         break;
537 
538     case NFA_EE_ADD_AID_EVT:
539         {
540             ALOGD ("%s: NFA_EE_ADD_AID_EVT  status=%u", fn, eventData->status);
541         }
542         break;
543 
544     case NFA_EE_REMOVE_AID_EVT:
545         {
546             ALOGD ("%s: NFA_EE_REMOVE_AID_EVT  status=%u", fn, eventData->status);
547         }
548         break;
549 
550     case NFA_EE_NEW_EE_EVT:
551         {
552             ALOGD ("%s: NFA_EE_NEW_EE_EVT  h=0x%X; status=%u", fn,
553                 eventData->new_ee.ee_handle, eventData->new_ee.ee_status);
554         }
555         break;
556 
557     case NFA_EE_UPDATED_EVT:
558         {
559             ALOGD("%s: NFA_EE_UPDATED_EVT", fn);
560             SyncEventGuard guard(routingManager.mEeUpdateEvent);
561             routingManager.mEeUpdateEvent.notifyOne();
562         }
563         break;
564 
565     default:
566         ALOGE ("%s: unknown event=%u ????", fn, event);
567         break;
568     }
569 }
570 
registerJniFunctions(JNIEnv * e)571 int RoutingManager::registerJniFunctions (JNIEnv* e)
572 {
573     static const char fn [] = "RoutingManager::registerJniFunctions";
574     ALOGD ("%s", fn);
575     return jniRegisterNativeMethods (e, "com/android/nfc/cardemulation/AidRoutingManager", sMethods, NELEM(sMethods));
576 }
577 
com_android_nfc_cardemulation_doGetDefaultRouteDestination(JNIEnv *)578 int RoutingManager::com_android_nfc_cardemulation_doGetDefaultRouteDestination (JNIEnv*)
579 {
580     return getInstance().mDefaultEe;
581 }
582 
com_android_nfc_cardemulation_doGetDefaultOffHostRouteDestination(JNIEnv *)583 int RoutingManager::com_android_nfc_cardemulation_doGetDefaultOffHostRouteDestination (JNIEnv*)
584 {
585     return getInstance().mOffHostEe;
586 }
587 
com_android_nfc_cardemulation_doGetAidMatchingMode(JNIEnv *)588 int RoutingManager::com_android_nfc_cardemulation_doGetAidMatchingMode (JNIEnv*)
589 {
590     return getInstance().mAidMatchingMode;
591 }
592