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