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 #include <android-base/stringprintf.h>
18 #include <base/logging.h>
19 #include <errno.h>
20 #include <malloc.h>
21 #include <nativehelper/ScopedLocalRef.h>
22 #include <nativehelper/ScopedPrimitiveArray.h>
23 #include <semaphore.h>
24 #include <signal.h>
25 #include <string.h>
26 #include <time.h>
27 #include <string>
28 #include "IntervalTimer.h"
29 #include "JavaClassConstants.h"
30 #include "Mutex.h"
31 #include "NfcJniUtil.h"
32 #include "NfcTag.h"
33 
34 #include "ndef_utils.h"
35 #include "nfa_api.h"
36 #include "nfa_rw_api.h"
37 #include "nfc_brcm_defs.h"
38 #include "phNxpExtns.h"
39 #include "rw_api.h"
40 
41 using android::base::StringPrintf;
42 
43 namespace android {
44 extern nfc_jni_native_data* getNative(JNIEnv* e, jobject o);
45 extern bool nfcManager_isNfcActive();
46 }  // namespace android
47 
48 extern bool gActivated;
49 extern SyncEvent gDeactivatedEvent;
50 extern bool nfc_debug_enabled;
51 extern bool legacy_mfc_reader;
52 
53 /*****************************************************************************
54 **
55 ** public variables and functions
56 **
57 *****************************************************************************/
58 namespace android {
59 bool gIsTagDeactivating = false;  // flag for nfa callback indicating we are
60                                   // deactivating for RF interface switch
61 bool gIsSelectingRfInterface =
62     false;  // flag for nfa callback indicating we are
63             // selecting for RF interface switch
64 }  // namespace android
65 
66 /*****************************************************************************
67 **
68 ** private variables and functions
69 **
70 *****************************************************************************/
71 namespace android {
72 
73 // Pre-defined tag type values. These must match the values in
74 // framework Ndef.java for Google public NFC API.
75 #define NDEF_UNKNOWN_TYPE (-1)
76 #define NDEF_TYPE1_TAG 1
77 #define NDEF_TYPE2_TAG 2
78 #define NDEF_TYPE3_TAG 3
79 #define NDEF_TYPE4_TAG 4
80 #define NDEF_MIFARE_CLASSIC_TAG 101
81 
82 #define STATUS_CODE_TARGET_LOST 146  // this error code comes from the service
83 
84 static uint32_t sCheckNdefCurrentSize = 0;
85 static tNFA_STATUS sCheckNdefStatus =
86     0;  // whether tag already contains a NDEF message
87 static bool sCheckNdefCapable = false;  // whether tag has NDEF capability
88 static tNFA_HANDLE sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
89 static tNFA_INTF_TYPE sCurrentRfInterface = NFA_INTERFACE_ISO_DEP;
90 static tNFA_INTF_TYPE sCurrentActivatedProtocl = NFA_INTERFACE_ISO_DEP;
91 static std::basic_string<uint8_t> sRxDataBuffer;
92 static tNFA_STATUS sRxDataStatus = NFA_STATUS_OK;
93 static bool sWaitingForTransceive = false;
94 static bool sTransceiveRfTimeout = false;
95 static Mutex sRfInterfaceMutex;
96 static uint32_t sReadDataLen = 0;
97 static uint8_t* sReadData = NULL;
98 static bool sIsReadingNdefMessage = false;
99 static SyncEvent sReadEvent;
100 static sem_t sWriteSem;
101 static sem_t sFormatSem;
102 static SyncEvent sTransceiveEvent;
103 static SyncEvent sReconnectEvent;
104 static sem_t sCheckNdefSem;
105 static SyncEvent sPresenceCheckEvent;
106 static sem_t sMakeReadonlySem;
107 static IntervalTimer sSwitchBackTimer;  // timer used to tell us to switch back
108                                         // to ISO_DEP frame interface
109 uint8_t RW_TAG_SLP_REQ[] = {0x50, 0x00};
110 uint8_t RW_DESELECT_REQ[] = {0xC2};
111 static jboolean sWriteOk = JNI_FALSE;
112 static jboolean sWriteWaitingForComplete = JNI_FALSE;
113 static bool sFormatOk = false;
114 static jboolean sConnectOk = JNI_FALSE;
115 static jboolean sConnectWaitingForComplete = JNI_FALSE;
116 static bool sGotDeactivate = false;
117 static uint32_t sCheckNdefMaxSize = 0;
118 static bool sCheckNdefCardReadOnly = false;
119 static jboolean sCheckNdefWaitingForComplete = JNI_FALSE;
120 static bool sIsTagPresent = true;
121 static tNFA_STATUS sMakeReadonlyStatus = NFA_STATUS_FAILED;
122 static jboolean sMakeReadonlyWaitingForComplete = JNI_FALSE;
123 static int sCurrentConnectedTargetType = TARGET_TYPE_UNKNOWN;
124 static int sCurrentConnectedTargetProtocol = NFC_PROTOCOL_UNKNOWN;
125 static int sCurrentConnectedHandle = 0;
126 static int reSelect(tNFA_INTF_TYPE rfInterface, bool fSwitchIfNeeded);
127 static bool switchRfInterface(tNFA_INTF_TYPE rfInterface);
128 
129 /*******************************************************************************
130 **
131 ** Function:        nativeNfcTag_abortWaits
132 **
133 ** Description:     Unblock all thread synchronization objects.
134 **
135 ** Returns:         None
136 **
137 *******************************************************************************/
nativeNfcTag_abortWaits()138 void nativeNfcTag_abortWaits() {
139   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
140   {
141     SyncEventGuard g(sReadEvent);
142     sReadEvent.notifyOne();
143   }
144   sem_post(&sWriteSem);
145   sem_post(&sFormatSem);
146   {
147     SyncEventGuard g(sTransceiveEvent);
148     sTransceiveEvent.notifyOne();
149   }
150   {
151     SyncEventGuard g(sReconnectEvent);
152     sReconnectEvent.notifyOne();
153   }
154 
155   sem_post(&sCheckNdefSem);
156   {
157     SyncEventGuard guard(sPresenceCheckEvent);
158     sPresenceCheckEvent.notifyOne();
159   }
160   sem_post(&sMakeReadonlySem);
161   sCurrentRfInterface = NFA_INTERFACE_ISO_DEP;
162   sCurrentActivatedProtocl = NFA_INTERFACE_ISO_DEP;
163   sCurrentConnectedTargetType = TARGET_TYPE_UNKNOWN;
164   sCurrentConnectedTargetProtocol = NFC_PROTOCOL_UNKNOWN;
165 }
166 
167 /*******************************************************************************
168 **
169 ** Function:        nativeNfcTag_doReadCompleted
170 **
171 ** Description:     Receive the completion status of read operation.  Called by
172 **                  NFA_READ_CPLT_EVT.
173 **                  status: Status of operation.
174 **
175 ** Returns:         None
176 **
177 *******************************************************************************/
nativeNfcTag_doReadCompleted(tNFA_STATUS status)178 void nativeNfcTag_doReadCompleted(tNFA_STATUS status) {
179   DLOG_IF(INFO, nfc_debug_enabled)
180       << StringPrintf("%s: status=0x%X; is reading=%u", __func__, status,
181                       sIsReadingNdefMessage);
182 
183   if (sIsReadingNdefMessage == false)
184     return;  // not reading NDEF message right now, so just return
185 
186   if (status != NFA_STATUS_OK) {
187     sReadDataLen = 0;
188     if (sReadData) free(sReadData);
189     sReadData = NULL;
190   }
191   SyncEventGuard g(sReadEvent);
192   sReadEvent.notifyOne();
193 }
194 
195 /*******************************************************************************
196 **
197 ** Function:        nativeNfcTag_setRfInterface
198 **
199 ** Description:     Set rf interface.
200 **
201 ** Returns:         void
202 **
203 *******************************************************************************/
nativeNfcTag_setRfInterface(tNFA_INTF_TYPE rfInterface)204 void nativeNfcTag_setRfInterface(tNFA_INTF_TYPE rfInterface) {
205   sCurrentRfInterface = rfInterface;
206 }
207 
208 /*******************************************************************************
209  **
210  ** Function:        nativeNfcTag_setActivatedRfProtocol
211  **
212  ** Description:     Set rf Activated Protocol.
213  **
214  ** Returns:         void
215  **
216  *******************************************************************************/
nativeNfcTag_setActivatedRfProtocol(tNFA_INTF_TYPE rfProtocol)217 void nativeNfcTag_setActivatedRfProtocol(tNFA_INTF_TYPE rfProtocol) {
218   sCurrentActivatedProtocl = rfProtocol;
219 }
220 
221 /*******************************************************************************
222 **
223 ** Function:        ndefHandlerCallback
224 **
225 ** Description:     Receive NDEF-message related events from stack.
226 **                  event: Event code.
227 **                  p_data: Event data.
228 **
229 ** Returns:         None
230 **
231 *******************************************************************************/
ndefHandlerCallback(tNFA_NDEF_EVT event,tNFA_NDEF_EVT_DATA * eventData)232 static void ndefHandlerCallback(tNFA_NDEF_EVT event,
233                                 tNFA_NDEF_EVT_DATA* eventData) {
234   DLOG_IF(INFO, nfc_debug_enabled)
235       << StringPrintf("%s: event=%u, eventData=%p", __func__, event, eventData);
236 
237   switch (event) {
238     case NFA_NDEF_REGISTER_EVT: {
239       tNFA_NDEF_REGISTER& ndef_reg = eventData->ndef_reg;
240       DLOG_IF(INFO, nfc_debug_enabled)
241           << StringPrintf("%s: NFA_NDEF_REGISTER_EVT; status=0x%X; h=0x%X",
242                           __func__, ndef_reg.status, ndef_reg.ndef_type_handle);
243       sNdefTypeHandlerHandle = ndef_reg.ndef_type_handle;
244     } break;
245 
246     case NFA_NDEF_DATA_EVT: {
247       DLOG_IF(INFO, nfc_debug_enabled)
248           << StringPrintf("%s: NFA_NDEF_DATA_EVT; data_len = %u", __func__,
249                           eventData->ndef_data.len);
250       sReadDataLen = eventData->ndef_data.len;
251       sReadData = (uint8_t*)malloc(sReadDataLen);
252       memcpy(sReadData, eventData->ndef_data.p_data, eventData->ndef_data.len);
253     } break;
254 
255     default:
256       LOG(ERROR) << StringPrintf("%s: Unknown event %u ????", __func__, event);
257       break;
258   }
259 }
260 
261 /*******************************************************************************
262 **
263 ** Function:        nativeNfcTag_doRead
264 **
265 ** Description:     Read the NDEF message on the tag.
266 **                  e: JVM environment.
267 **                  o: Java object.
268 **
269 ** Returns:         NDEF message.
270 **
271 *******************************************************************************/
nativeNfcTag_doRead(JNIEnv * e,jobject)272 static jbyteArray nativeNfcTag_doRead(JNIEnv* e, jobject) {
273   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
274   tNFA_STATUS status = NFA_STATUS_FAILED;
275   jbyteArray buf = NULL;
276 
277   sReadDataLen = 0;
278   if (sReadData != NULL) {
279     free(sReadData);
280     sReadData = NULL;
281   }
282 
283   if (sCheckNdefCurrentSize > 0) {
284     {
285       SyncEventGuard g(sReadEvent);
286       sIsReadingNdefMessage = true;
287       if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
288         status = EXTNS_MfcReadNDef();
289       } else {
290         status = NFA_RwReadNDef();
291       }
292       sReadEvent.wait();  // wait for NFA_READ_CPLT_EVT
293     }
294     sIsReadingNdefMessage = false;
295 
296     if (sReadDataLen > 0)  // if stack actually read data from the tag
297     {
298       DLOG_IF(INFO, nfc_debug_enabled)
299           << StringPrintf("%s: read %u bytes", __func__, sReadDataLen);
300       buf = e->NewByteArray(sReadDataLen);
301       e->SetByteArrayRegion(buf, 0, sReadDataLen, (jbyte*)sReadData);
302     }
303   } else {
304     DLOG_IF(INFO, nfc_debug_enabled)
305         << StringPrintf("%s: create empty buffer", __func__);
306     sReadDataLen = 0;
307     sReadData = (uint8_t*)malloc(1);
308     buf = e->NewByteArray(sReadDataLen);
309     e->SetByteArrayRegion(buf, 0, sReadDataLen, (jbyte*)sReadData);
310   }
311 
312   if (sReadData) {
313     free(sReadData);
314     sReadData = NULL;
315   }
316   sReadDataLen = 0;
317 
318   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
319   return buf;
320 }
321 
322 /*******************************************************************************
323 **
324 ** Function:        nativeNfcTag_doWriteStatus
325 **
326 ** Description:     Receive the completion status of write operation.  Called
327 **                  by NFA_WRITE_CPLT_EVT.
328 **                  isWriteOk: Status of operation.
329 **
330 ** Returns:         None
331 **
332 *******************************************************************************/
nativeNfcTag_doWriteStatus(jboolean isWriteOk)333 void nativeNfcTag_doWriteStatus(jboolean isWriteOk) {
334   if (sWriteWaitingForComplete != JNI_FALSE) {
335     sWriteWaitingForComplete = JNI_FALSE;
336     sWriteOk = isWriteOk;
337     sem_post(&sWriteSem);
338   }
339 }
340 
341 /*******************************************************************************
342 **
343 ** Function:        nativeNfcTag_formatStatus
344 **
345 ** Description:     Receive the completion status of format operation.  Called
346 **                  by NFA_FORMAT_CPLT_EVT.
347 **                  isOk: Status of operation.
348 **
349 ** Returns:         None
350 **
351 *******************************************************************************/
nativeNfcTag_formatStatus(bool isOk)352 void nativeNfcTag_formatStatus(bool isOk) {
353   sFormatOk = isOk;
354   sem_post(&sFormatSem);
355 }
356 
357 /*******************************************************************************
358 **
359 ** Function:        nativeNfcTag_doWrite
360 **
361 ** Description:     Write a NDEF message to the tag.
362 **                  e: JVM environment.
363 **                  o: Java object.
364 **                  buf: Contains a NDEF message.
365 **
366 ** Returns:         True if ok.
367 **
368 *******************************************************************************/
nativeNfcTag_doWrite(JNIEnv * e,jobject,jbyteArray buf)369 static jboolean nativeNfcTag_doWrite(JNIEnv* e, jobject, jbyteArray buf) {
370   jboolean result = JNI_FALSE;
371   tNFA_STATUS status = 0;
372   const int maxBufferSize = 1024;
373   uint8_t buffer[maxBufferSize] = {0};
374   uint32_t curDataSize = 0;
375 
376   ScopedByteArrayRO bytes(e, buf);
377   uint8_t* p_data = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(
378       &bytes[0]));  // TODO: const-ness API bug in NFA_RwWriteNDef!
379 
380   DLOG_IF(INFO, nfc_debug_enabled)
381       << StringPrintf("%s: enter; len = %zu", __func__, bytes.size());
382 
383   /* Create the write semaphore */
384   if (sem_init(&sWriteSem, 0, 0) == -1) {
385     LOG(ERROR) << StringPrintf("%s: semaphore creation failed (errno=0x%08x)",
386                                __func__, errno);
387     return JNI_FALSE;
388   }
389 
390   sWriteWaitingForComplete = JNI_TRUE;
391   if (sCheckNdefStatus == NFA_STATUS_FAILED) {
392     // if tag does not contain a NDEF message
393     // and tag is capable of storing NDEF message
394     if (sCheckNdefCapable) {
395       DLOG_IF(INFO, nfc_debug_enabled)
396           << StringPrintf("%s: try format", __func__);
397       sem_init(&sFormatSem, 0, 0);
398       sFormatOk = false;
399       if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
400         static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
401         static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7};
402 
403         status = EXTNS_MfcFormatTag(mfc_key1, sizeof(mfc_key1));
404         if (status != NFA_STATUS_OK) {
405           LOG(ERROR) << StringPrintf("%s: can't format mifare classic tag",
406                                      __func__);
407           sem_destroy(&sFormatSem);
408           goto TheEnd;
409         }
410 
411         if (sFormatOk == false)  // if format operation failed
412         {
413           sem_wait(&sFormatSem);
414           sem_destroy(&sFormatSem);
415           sem_init(&sFormatSem, 0, 0);
416           status = EXTNS_MfcFormatTag(mfc_key2, sizeof(mfc_key2));
417           if (status != NFA_STATUS_OK) {
418             LOG(ERROR) << StringPrintf("%s: can't format mifare classic tag",
419                                        __func__);
420             sem_destroy(&sFormatSem);
421             goto TheEnd;
422           }
423         }
424       } else {
425         status = NFA_RwFormatTag();
426         if (status != NFA_STATUS_OK) {
427           LOG(ERROR) << StringPrintf("%s: can't format mifare classic tag",
428                                      __func__);
429           sem_destroy(&sFormatSem);
430           goto TheEnd;
431         }
432       }
433       sem_wait(&sFormatSem);
434       sem_destroy(&sFormatSem);
435       if (sFormatOk == false)  // if format operation failed
436         goto TheEnd;
437     }
438     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: try write", __func__);
439     status = NFA_RwWriteNDef(p_data, bytes.size());
440   } else if (bytes.size() == 0) {
441     // if (NXP TagWriter wants to erase tag) then create and write an empty ndef
442     // message
443     NDEF_MsgInit(buffer, maxBufferSize, &curDataSize);
444     status = NDEF_MsgAddRec(buffer, maxBufferSize, &curDataSize, NDEF_TNF_EMPTY,
445                             NULL, 0, NULL, 0, NULL, 0);
446     DLOG_IF(INFO, nfc_debug_enabled)
447         << StringPrintf("%s: create empty ndef msg; status=%u; size=%u",
448                         __func__, status, curDataSize);
449     if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
450       status = EXTNS_MfcWriteNDef(buffer, curDataSize);
451     } else {
452       status = NFA_RwWriteNDef(buffer, curDataSize);
453     }
454   } else {
455     DLOG_IF(INFO, nfc_debug_enabled)
456         << StringPrintf("%s: NFA_RwWriteNDef", __func__);
457     if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
458       status = EXTNS_MfcWriteNDef(p_data, bytes.size());
459     } else {
460       status = NFA_RwWriteNDef(p_data, bytes.size());
461     }
462   }
463 
464   if (status != NFA_STATUS_OK) {
465     LOG(ERROR) << StringPrintf("%s: write/format error=%d", __func__, status);
466     goto TheEnd;
467   }
468 
469   /* Wait for write completion status */
470   sWriteOk = false;
471   if (sem_wait(&sWriteSem)) {
472     LOG(ERROR) << StringPrintf("%s: wait semaphore (errno=0x%08x)", __func__,
473                                errno);
474     goto TheEnd;
475   }
476 
477   result = sWriteOk;
478 
479 TheEnd:
480   /* Destroy semaphore */
481   if (sem_destroy(&sWriteSem)) {
482     LOG(ERROR) << StringPrintf("%s: failed destroy semaphore (errno=0x%08x)",
483                                __func__, errno);
484   }
485   sWriteWaitingForComplete = JNI_FALSE;
486   DLOG_IF(INFO, nfc_debug_enabled)
487       << StringPrintf("%s: exit; result=%d", __func__, result);
488   return result;
489 }
490 
491 /*******************************************************************************
492 **
493 ** Function:        nativeNfcTag_doConnectStatus
494 **
495 ** Description:     Receive the completion status of connect operation.
496 **                  isConnectOk: Status of the operation.
497 **
498 ** Returns:         None
499 **
500 *******************************************************************************/
nativeNfcTag_doConnectStatus(jboolean isConnectOk)501 void nativeNfcTag_doConnectStatus(jboolean isConnectOk) {
502   if (EXTNS_GetConnectFlag() == TRUE && legacy_mfc_reader) {
503     EXTNS_MfcActivated();
504     EXTNS_SetConnectFlag(FALSE);
505     return;
506   }
507 
508   if (sConnectWaitingForComplete != JNI_FALSE) {
509     sConnectWaitingForComplete = JNI_FALSE;
510     sConnectOk = isConnectOk;
511     SyncEventGuard g(sReconnectEvent);
512     sReconnectEvent.notifyOne();
513   }
514 }
515 
516 /*******************************************************************************
517 **
518 ** Function:        nativeNfcTag_doDeactivateStatus
519 **
520 ** Description:     Receive the completion status of deactivate operation.
521 **
522 ** Returns:         None
523 **
524 *******************************************************************************/
nativeNfcTag_doDeactivateStatus(int status)525 void nativeNfcTag_doDeactivateStatus(int status) {
526   if (EXTNS_GetDeactivateFlag() == TRUE && legacy_mfc_reader) {
527     EXTNS_MfcDisconnect();
528     EXTNS_SetDeactivateFlag(FALSE);
529     return;
530   }
531 
532   sGotDeactivate = (status == 0);
533 
534   SyncEventGuard g(sReconnectEvent);
535   sReconnectEvent.notifyOne();
536 }
537 
538 /*******************************************************************************
539 **
540 ** Function:        nativeNfcTag_doConnect
541 **
542 ** Description:     Connect to the tag in RF field.
543 **                  e: JVM environment.
544 **                  o: Java object.
545 **                  targetHandle: Handle of the tag.
546 **
547 ** Returns:         Must return NXP status code, which NFC service expects.
548 **
549 *******************************************************************************/
nativeNfcTag_doConnect(JNIEnv *,jobject,jint targetHandle)550 static jint nativeNfcTag_doConnect(JNIEnv*, jobject, jint targetHandle) {
551   DLOG_IF(INFO, nfc_debug_enabled)
552       << StringPrintf("%s: targetHandle = %d", __func__, targetHandle);
553   int i = targetHandle;
554   NfcTag& natTag = NfcTag::getInstance();
555   int retCode = NFCSTATUS_SUCCESS;
556 
557   if (i >= NfcTag::MAX_NUM_TECHNOLOGY) {
558     LOG(ERROR) << StringPrintf("%s: Handle not found", __func__);
559     retCode = NFCSTATUS_FAILED;
560     goto TheEnd;
561   }
562 
563   if (natTag.getActivationState() != NfcTag::Active) {
564     LOG(ERROR) << StringPrintf("%s: tag already deactivated", __func__);
565     retCode = NFCSTATUS_FAILED;
566     goto TheEnd;
567   }
568 
569   sCurrentConnectedTargetType = natTag.mTechList[i];
570   sCurrentConnectedTargetProtocol = natTag.mTechLibNfcTypes[i];
571   sCurrentConnectedHandle = targetHandle;
572 
573   if (sCurrentConnectedTargetProtocol != NFC_PROTOCOL_ISO_DEP &&
574       sCurrentConnectedTargetProtocol != NFC_PROTOCOL_MIFARE) {
575     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
576         "%s() Nfc type = %d, do nothing for non ISO_DEP and non Mifare ",
577         __func__, sCurrentConnectedTargetProtocol);
578     retCode = NFCSTATUS_SUCCESS;
579     goto TheEnd;
580   }
581 
582   if (sCurrentConnectedTargetType == TARGET_TYPE_ISO14443_3A ||
583       sCurrentConnectedTargetType == TARGET_TYPE_ISO14443_3B) {
584 
585       if (sCurrentConnectedTargetProtocol != NFC_PROTOCOL_MIFARE) {
586         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
587         "%s: switching to tech: %d need to switch rf intf to frame", __func__,
588         sCurrentConnectedTargetType);
589         retCode = switchRfInterface(NFA_INTERFACE_FRAME) ? NFA_STATUS_OK
590                                                          : NFA_STATUS_FAILED;
591       }
592   } else if (sCurrentConnectedTargetType == TARGET_TYPE_MIFARE_CLASSIC) {
593     retCode = switchRfInterface(NFA_INTERFACE_MIFARE) ? NFA_STATUS_OK
594                                                       : NFA_STATUS_FAILED;
595   } else {
596     retCode = switchRfInterface(NFA_INTERFACE_ISO_DEP) ? NFA_STATUS_OK
597                                                        : NFA_STATUS_FAILED;
598   }
599 
600 TheEnd:
601   DLOG_IF(INFO, nfc_debug_enabled)
602       << StringPrintf("%s: exit 0x%X", __func__, retCode);
603   return retCode;
604 }
605 
606 /*******************************************************************************
607 **
608 ** Function:        reSelect
609 **
610 ** Description:     Deactivates the tag and re-selects it with the specified
611 **                  rf interface.
612 **
613 ** Returns:         status code, 0 on success, 1 on failure,
614 **                  146 (defined in service) on tag lost
615 **
616 *******************************************************************************/
reSelect(tNFA_INTF_TYPE rfInterface,bool fSwitchIfNeeded)617 static int reSelect(tNFA_INTF_TYPE rfInterface, bool fSwitchIfNeeded) {
618   DLOG_IF(INFO, nfc_debug_enabled)
619       << StringPrintf("%s: enter; rf intf = %d, current intf = %d", __func__,
620                       rfInterface, sCurrentRfInterface);
621 
622   sRfInterfaceMutex.lock();
623 
624   if (fSwitchIfNeeded && (rfInterface == sCurrentRfInterface)) {
625     // already in the requested interface
626     sRfInterfaceMutex.unlock();
627     return 0;  // success
628   }
629 
630   NfcTag& natTag = NfcTag::getInstance();
631 
632   tNFA_STATUS status = NFA_STATUS_OK;
633   int rVal = 1;
634 
635   do {
636     // if tag has shutdown, abort this method
637     if (NfcTag::getInstance().isNdefDetectionTimedOut()) {
638       DLOG_IF(INFO, nfc_debug_enabled)
639           << StringPrintf("%s: ndef detection timeout; break", __func__);
640       rVal = STATUS_CODE_TARGET_LOST;
641       break;
642     }
643     if ((sCurrentRfInterface == NFA_INTERFACE_FRAME) &&
644         (NFC_GetNCIVersion() >= NCI_VERSION_2_0)) {
645       {
646         SyncEventGuard g3(sReconnectEvent);
647         if (sCurrentActivatedProtocl == NFA_PROTOCOL_T2T) {
648           status = NFA_SendRawFrame(RW_TAG_SLP_REQ, sizeof(RW_TAG_SLP_REQ), 0);
649         } else if (sCurrentActivatedProtocl == NFA_PROTOCOL_ISO_DEP) {
650           status = NFA_SendRawFrame(RW_DESELECT_REQ,
651                                     sizeof(RW_DESELECT_REQ), 0);
652         }
653         sReconnectEvent.wait(4);
654         if (status != NFA_STATUS_OK) {
655           LOG(ERROR) << StringPrintf("%s: send error=%d", __func__, status);
656           break;
657         }
658       }
659     }
660 
661     {
662       SyncEventGuard g(sReconnectEvent);
663       gIsTagDeactivating = true;
664       sGotDeactivate = false;
665       DLOG_IF(INFO, nfc_debug_enabled)
666           << StringPrintf("%s: deactivate to sleep", __func__);
667       if (NFA_STATUS_OK !=
668           (status = NFA_Deactivate(TRUE)))  // deactivate to sleep state
669       {
670         LOG(ERROR) << StringPrintf("%s: deactivate failed, status = %d",
671                                    __func__, status);
672         break;
673       }
674 
675       if (sReconnectEvent.wait(1000) == false)  // if timeout occurred
676       {
677         LOG(ERROR) << StringPrintf("%s: timeout waiting for deactivate",
678                                    __func__);
679       }
680     }
681 
682     if (!sGotDeactivate) {
683       rVal = STATUS_CODE_TARGET_LOST;
684       break;
685     }
686 
687     if (NfcTag::getInstance().getActivationState() != NfcTag::Sleep) {
688       LOG(ERROR) << StringPrintf("%s: tag is not in sleep", __func__);
689       rVal = STATUS_CODE_TARGET_LOST;
690       break;
691     }
692 
693     gIsTagDeactivating = false;
694 
695     {
696       SyncEventGuard g2(sReconnectEvent);
697 
698       sConnectWaitingForComplete = JNI_TRUE;
699       DLOG_IF(INFO, nfc_debug_enabled)
700           << StringPrintf("%s: select interface %u", __func__, rfInterface);
701       gIsSelectingRfInterface = true;
702       if (NFA_STATUS_OK !=
703           (status = NFA_Select(natTag.mTechHandles[sCurrentConnectedHandle],
704                                natTag.mTechLibNfcTypes[sCurrentConnectedHandle],
705                                rfInterface))) {
706         LOG(ERROR) << StringPrintf("%s: NFA_Select failed, status = %d",
707                                    __func__, status);
708         break;
709       }
710 
711       sConnectOk = false;
712       if (sReconnectEvent.wait(1000) == false)  // if timeout occurred
713       {
714         LOG(ERROR) << StringPrintf("%s: timeout waiting for select", __func__);
715         break;
716       }
717     }
718 
719     /*Retry logic in case of core Generic error while selecting a tag*/
720     if (sConnectOk == false) {
721       LOG(ERROR) << StringPrintf("%s: waiting for Card to be activated",
722                                  __func__);
723       int retry = 0;
724       sConnectWaitingForComplete = JNI_TRUE;
725       do {
726         SyncEventGuard reselectEvent(sReconnectEvent);
727         if (sReconnectEvent.wait(500) == false) {  // if timeout occurred
728           LOG(ERROR) << StringPrintf("%s: timeout ", __func__);
729         }
730         retry++;
731         LOG(ERROR) << StringPrintf("%s: waiting for Card to be activated %x %x",
732                                    __func__, retry, sConnectOk);
733       } while (sConnectOk == false && retry < 3);
734     }
735 
736     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
737         "%s: select completed; sConnectOk=%d", __func__, sConnectOk);
738     if (NfcTag::getInstance().getActivationState() != NfcTag::Active) {
739       LOG(ERROR) << StringPrintf("%s: tag is not active", __func__);
740       rVal = STATUS_CODE_TARGET_LOST;
741       break;
742     }
743     if (sConnectOk) {
744       rVal = 0;  // success
745       sCurrentRfInterface = rfInterface;
746     } else {
747       rVal = 1;
748     }
749   } while (0);
750 
751   sConnectWaitingForComplete = JNI_FALSE;
752   gIsTagDeactivating = false;
753   gIsSelectingRfInterface = false;
754   sRfInterfaceMutex.unlock();
755   DLOG_IF(INFO, nfc_debug_enabled)
756       << StringPrintf("%s: exit; status=%d", __func__, rVal);
757   return rVal;
758 }
759 
760 /*******************************************************************************
761 **
762 ** Function:        switchRfInterface
763 **
764 ** Description:     Switch controller's RF interface to frame, ISO-DEP, or
765 *NFC-DEP.
766 **                  rfInterface: Type of RF interface.
767 **
768 ** Returns:         True if ok.
769 **
770 *******************************************************************************/
switchRfInterface(tNFA_INTF_TYPE rfInterface)771 static bool switchRfInterface(tNFA_INTF_TYPE rfInterface) {
772   NfcTag& natTag = NfcTag::getInstance();
773 
774   if (sCurrentConnectedTargetProtocol != NFC_PROTOCOL_ISO_DEP &&
775       sCurrentConnectedTargetProtocol != NFC_PROTOCOL_MIFARE) {
776     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
777         "%s: protocol: %d not ISO_DEP and not Mifare, do nothing", __func__,
778         natTag.mTechLibNfcTypes[0]);
779     return true;
780   }
781 
782   DLOG_IF(INFO, nfc_debug_enabled)
783       << StringPrintf("%s: new rf intf = %d, cur rf intf = %d", __func__,
784                       rfInterface, sCurrentRfInterface);
785 
786   return (0 == reSelect(rfInterface, true));
787 }
788 
789 /*******************************************************************************
790 **
791 ** Function:        nativeNfcTag_doReconnect
792 **
793 ** Description:     Re-connect to the tag in RF field.
794 **                  e: JVM environment.
795 **                  o: Java object.
796 **
797 ** Returns:         Status code.
798 **
799 *******************************************************************************/
nativeNfcTag_doReconnect(JNIEnv *,jobject)800 static jint nativeNfcTag_doReconnect(JNIEnv*, jobject) {
801   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
802   int retCode = NFCSTATUS_SUCCESS;
803   NfcTag& natTag = NfcTag::getInstance();
804 
805   if (natTag.getActivationState() != NfcTag::Active) {
806     LOG(ERROR) << StringPrintf("%s: tag already deactivated", __func__);
807     retCode = NFCSTATUS_FAILED;
808     goto TheEnd;
809   }
810 
811   // special case for Kovio
812   if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) {
813     DLOG_IF(INFO, nfc_debug_enabled)
814         << StringPrintf("%s: fake out reconnect for Kovio", __func__);
815     goto TheEnd;
816   }
817 
818   // this is only supported for type 2 or 4 (ISO_DEP) tags
819   if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_ISO_DEP)
820     retCode = reSelect(NFA_INTERFACE_ISO_DEP, false);
821   else if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_T2T)
822     retCode = reSelect(NFA_INTERFACE_FRAME, false);
823   else if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE)
824     retCode = reSelect(NFA_INTERFACE_MIFARE, false);
825 
826 TheEnd:
827   DLOG_IF(INFO, nfc_debug_enabled)
828       << StringPrintf("%s: exit 0x%X", __func__, retCode);
829   return retCode;
830 }
831 
832 /*******************************************************************************
833 **
834 ** Function:        nativeNfcTag_doHandleReconnect
835 **
836 ** Description:     Re-connect to the tag in RF field.
837 **                  e: JVM environment.
838 **                  o: Java object.
839 **                  targetHandle: Handle of the tag.
840 **
841 ** Returns:         Status code.
842 **
843 *******************************************************************************/
nativeNfcTag_doHandleReconnect(JNIEnv * e,jobject o,jint targetHandle)844 static jint nativeNfcTag_doHandleReconnect(JNIEnv* e, jobject o,
845                                            jint targetHandle) {
846   DLOG_IF(INFO, nfc_debug_enabled)
847       << StringPrintf("%s: targetHandle = %d", __func__, targetHandle);
848   return nativeNfcTag_doConnect(e, o, targetHandle);
849 }
850 
851 /*******************************************************************************
852 **
853 ** Function:        nativeNfcTag_doDisconnect
854 **
855 ** Description:     Deactivate the RF field.
856 **                  e: JVM environment.
857 **                  o: Java object.
858 **
859 ** Returns:         True if ok.
860 **
861 *******************************************************************************/
nativeNfcTag_doDisconnect(JNIEnv *,jobject)862 jboolean nativeNfcTag_doDisconnect(JNIEnv*, jobject) {
863   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
864   tNFA_STATUS nfaStat = NFA_STATUS_OK;
865 
866   NfcTag::getInstance().resetAllTransceiveTimeouts();
867 
868   if (NfcTag::getInstance().getActivationState() != NfcTag::Active) {
869     LOG(WARNING) << StringPrintf("%s: tag already deactivated", __func__);
870     goto TheEnd;
871   }
872 
873   nfaStat = NFA_Deactivate(FALSE);
874   if (nfaStat != NFA_STATUS_OK)
875     LOG(ERROR) << StringPrintf("%s: deactivate failed; error=0x%X", __func__,
876                                nfaStat);
877 
878 TheEnd:
879   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
880   return (nfaStat == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
881 }
882 
883 /*******************************************************************************
884 **
885 ** Function:        nativeNfcTag_doTransceiveStatus
886 **
887 ** Description:     Receive the completion status of transceive operation.
888 **                  status: operation status.
889 **                  buf: Contains tag's response.
890 **                  bufLen: Length of buffer.
891 **
892 ** Returns:         None
893 **
894 *******************************************************************************/
nativeNfcTag_doTransceiveStatus(tNFA_STATUS status,uint8_t * buf,uint32_t bufLen)895 void nativeNfcTag_doTransceiveStatus(tNFA_STATUS status, uint8_t* buf,
896                                      uint32_t bufLen) {
897   SyncEventGuard g(sTransceiveEvent);
898   DLOG_IF(INFO, nfc_debug_enabled)
899       << StringPrintf("%s: data len=%d", __func__, bufLen);
900 
901   if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
902     if (EXTNS_GetCallBackFlag() == FALSE) {
903       EXTNS_MfcCallBack(buf, bufLen);
904       return;
905     }
906   }
907 
908   if (!sWaitingForTransceive) {
909     LOG(ERROR) << StringPrintf("%s: drop data", __func__);
910     return;
911   }
912   sRxDataStatus = status;
913   if (sRxDataStatus == NFA_STATUS_OK || sRxDataStatus == NFC_STATUS_CONTINUE)
914     sRxDataBuffer.append(buf, bufLen);
915 
916   if (sRxDataStatus == NFA_STATUS_OK) sTransceiveEvent.notifyOne();
917 }
918 
nativeNfcTag_notifyRfTimeout()919 void nativeNfcTag_notifyRfTimeout() {
920   SyncEventGuard g(sTransceiveEvent);
921   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
922       "%s: waiting for transceive: %d", __func__, sWaitingForTransceive);
923   if (!sWaitingForTransceive) return;
924 
925   sTransceiveRfTimeout = true;
926 
927   sTransceiveEvent.notifyOne();
928 }
929 
930 /*******************************************************************************
931 **
932 ** Function:        nativeNfcTag_doTransceive
933 **
934 ** Description:     Send raw data to the tag; receive tag's response.
935 **                  e: JVM environment.
936 **                  o: Java object.
937 **                  raw: Not used.
938 **                  statusTargetLost: Whether tag responds or times out.
939 **
940 ** Returns:         Response from tag.
941 **
942 *******************************************************************************/
nativeNfcTag_doTransceive(JNIEnv * e,jobject o,jbyteArray data,jboolean raw,jintArray statusTargetLost)943 static jbyteArray nativeNfcTag_doTransceive(JNIEnv* e, jobject o,
944                                             jbyteArray data, jboolean raw,
945                                             jintArray statusTargetLost) {
946   int timeout =
947       NfcTag::getInstance().getTransceiveTimeout(sCurrentConnectedTargetType);
948   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
949       "%s: enter; raw=%u; timeout = %d", __func__, raw, timeout);
950 
951   bool waitOk = false;
952   bool isNack = false;
953   jint* targetLost = NULL;
954   tNFA_STATUS status;
955 
956   if (NfcTag::getInstance().getActivationState() != NfcTag::Active) {
957     if (statusTargetLost) {
958       targetLost = e->GetIntArrayElements(statusTargetLost, 0);
959       if (targetLost)
960         *targetLost = 1;  // causes NFC service to throw TagLostException
961       e->ReleaseIntArrayElements(statusTargetLost, targetLost, 0);
962     }
963     DLOG_IF(INFO, nfc_debug_enabled)
964         << StringPrintf("%s: tag not active", __func__);
965     return NULL;
966   }
967 
968   NfcTag& natTag = NfcTag::getInstance();
969 
970   // get input buffer and length from java call
971   ScopedByteArrayRO bytes(e, data);
972   uint8_t* buf = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(
973       &bytes[0]));  // TODO: API bug; NFA_SendRawFrame should take const*!
974   size_t bufLen = bytes.size();
975 
976   if (statusTargetLost) {
977     targetLost = e->GetIntArrayElements(statusTargetLost, 0);
978     if (targetLost) *targetLost = 0;  // success, tag is still present
979   }
980 
981   sSwitchBackTimer.kill();
982   ScopedLocalRef<jbyteArray> result(e, NULL);
983   do {
984     {
985       SyncEventGuard g(sTransceiveEvent);
986       sTransceiveRfTimeout = false;
987       sWaitingForTransceive = true;
988       sRxDataStatus = NFA_STATUS_OK;
989       sRxDataBuffer.clear();
990 
991       if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
992         status = EXTNS_MfcTransceive(buf, bufLen);
993       } else {
994         status = NFA_SendRawFrame(buf, bufLen,
995                                   NFA_DM_DEFAULT_PRESENCE_CHECK_START_DELAY);
996       }
997 
998       if (status != NFA_STATUS_OK) {
999         LOG(ERROR) << StringPrintf("%s: fail send; error=%d", __func__, status);
1000         break;
1001       }
1002       waitOk = sTransceiveEvent.wait(timeout);
1003     }
1004 
1005     if (waitOk == false || sTransceiveRfTimeout)  // if timeout occurred
1006     {
1007       LOG(ERROR) << StringPrintf("%s: wait response timeout", __func__);
1008       if (targetLost)
1009         *targetLost = 1;  // causes NFC service to throw TagLostException
1010       break;
1011     }
1012 
1013     if (NfcTag::getInstance().getActivationState() != NfcTag::Active) {
1014       LOG(ERROR) << StringPrintf("%s: already deactivated", __func__);
1015       if (targetLost)
1016         *targetLost = 1;  // causes NFC service to throw TagLostException
1017       break;
1018     }
1019 
1020     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1021         "%s: response %zu bytes", __func__, sRxDataBuffer.size());
1022 
1023     if ((natTag.getProtocol() == NFA_PROTOCOL_T2T) &&
1024         natTag.isT2tNackResponse(sRxDataBuffer.data(), sRxDataBuffer.size())) {
1025       isNack = true;
1026     }
1027 
1028     if (sRxDataBuffer.size() > 0) {
1029       if (isNack) {
1030         // Some Mifare Ultralight C tags enter the HALT state after it
1031         // responds with a NACK.  Need to perform a "reconnect" operation
1032         // to wake it.
1033         DLOG_IF(INFO, nfc_debug_enabled)
1034             << StringPrintf("%s: try reconnect", __func__);
1035         nativeNfcTag_doReconnect(NULL, NULL);
1036         DLOG_IF(INFO, nfc_debug_enabled)
1037             << StringPrintf("%s: reconnect finish", __func__);
1038       } else if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) {
1039         uint32_t transDataLen = sRxDataBuffer.size();
1040         uint8_t* transData = (uint8_t*)sRxDataBuffer.data();
1041         bool doReconnect = false;
1042 
1043         if (legacy_mfc_reader) {
1044           doReconnect = (EXTNS_CheckMfcResponse(&transData, &transDataLen) ==
1045                          NFCSTATUS_FAILED) ? true : false;
1046         } else {
1047           doReconnect =
1048               ((transDataLen == 1) && (transData[0] != 0x00)) ? true : false;
1049         }
1050 
1051         if (doReconnect) {
1052           nativeNfcTag_doReconnect(e, o);
1053         } else {
1054           if (transDataLen != 0) {
1055             result.reset(e->NewByteArray(transDataLen));
1056             if (result.get() != NULL) {
1057               e->SetByteArrayRegion(result.get(), 0, transDataLen,
1058                                   (const jbyte*)transData);
1059             } else
1060               LOG(ERROR) << StringPrintf("%s: Failed to allocate java byte array",
1061                                        __func__);
1062           }
1063         }
1064       } else {
1065         // marshall data to java for return
1066         result.reset(e->NewByteArray(sRxDataBuffer.size()));
1067         if (result.get() != NULL) {
1068           e->SetByteArrayRegion(result.get(), 0, sRxDataBuffer.size(),
1069                                 (const jbyte*)sRxDataBuffer.data());
1070         } else
1071           LOG(ERROR) << StringPrintf("%s: Failed to allocate java byte array",
1072                                      __func__);
1073       }  // else a nack is treated as a transceive failure to the upper layers
1074 
1075       sRxDataBuffer.clear();
1076     }
1077   } while (0);
1078 
1079   sWaitingForTransceive = false;
1080   if (targetLost) e->ReleaseIntArrayElements(statusTargetLost, targetLost, 0);
1081 
1082   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
1083   return result.release();
1084 }
1085 
1086 /*******************************************************************************
1087 **
1088 ** Function:        nativeNfcTag_doGetNdefType
1089 **
1090 ** Description:     Retrieve the type of tag.
1091 **                  e: JVM environment.
1092 **                  o: Java object.
1093 **                  libnfcType: Type of tag represented by JNI.
1094 **                  javaType: Not used.
1095 **
1096 ** Returns:         Type of tag represented by NFC Service.
1097 **
1098 *******************************************************************************/
nativeNfcTag_doGetNdefType(JNIEnv *,jobject,jint libnfcType,jint javaType)1099 static jint nativeNfcTag_doGetNdefType(JNIEnv*, jobject, jint libnfcType,
1100                                        jint javaType) {
1101   DLOG_IF(INFO, nfc_debug_enabled)
1102       << StringPrintf("%s: enter; libnfc type=%d; java type=%d", __func__,
1103                       libnfcType, javaType);
1104   jint ndefType = NDEF_UNKNOWN_TYPE;
1105 
1106   // For NFA, libnfcType is mapped to the protocol value received
1107   // in the NFA_ACTIVATED_EVT and NFA_DISC_RESULT_EVT event.
1108   if (NFA_PROTOCOL_T1T == libnfcType) {
1109     ndefType = NDEF_TYPE1_TAG;
1110   } else if (NFA_PROTOCOL_T2T == libnfcType) {
1111     ndefType = NDEF_TYPE2_TAG;
1112   } else if (NFA_PROTOCOL_T3T == libnfcType) {
1113     ndefType = NDEF_TYPE3_TAG;
1114   } else if (NFA_PROTOCOL_ISO_DEP == libnfcType) {
1115     ndefType = NDEF_TYPE4_TAG;
1116   } else if (NFC_PROTOCOL_MIFARE == libnfcType) {
1117     ndefType = NDEF_MIFARE_CLASSIC_TAG;
1118   } else {
1119     /* NFA_PROTOCOL_T5T, NFA_PROTOCOL_INVALID and others */
1120     ndefType = NDEF_UNKNOWN_TYPE;
1121   }
1122   DLOG_IF(INFO, nfc_debug_enabled)
1123       << StringPrintf("%s: exit; ndef type=%d", __func__, ndefType);
1124   return ndefType;
1125 }
1126 
1127 /*******************************************************************************
1128 **
1129 ** Function:        nativeNfcTag_doCheckNdefResult
1130 **
1131 ** Description:     Receive the result of checking whether the tag contains a
1132 *NDEF
1133 **                  message.  Called by the NFA_NDEF_DETECT_EVT.
1134 **                  status: Status of the operation.
1135 **                  maxSize: Maximum size of NDEF message.
1136 **                  currentSize: Current size of NDEF message.
1137 **                  flags: Indicate various states.
1138 **
1139 ** Returns:         None
1140 **
1141 *******************************************************************************/
nativeNfcTag_doCheckNdefResult(tNFA_STATUS status,uint32_t maxSize,uint32_t currentSize,uint8_t flags)1142 void nativeNfcTag_doCheckNdefResult(tNFA_STATUS status, uint32_t maxSize,
1143                                     uint32_t currentSize, uint8_t flags) {
1144   // this function's flags parameter is defined using the following macros
1145   // in nfc/include/rw_api.h;
1146   //#define RW_NDEF_FL_READ_ONLY  0x01    /* Tag is read only              */
1147   //#define RW_NDEF_FL_FORMATED   0x02    /* Tag formated for NDEF         */
1148   //#define RW_NDEF_FL_SUPPORTED  0x04    /* NDEF supported by the tag     */
1149   //#define RW_NDEF_FL_UNKNOWN    0x08    /* Unable to find if tag is ndef
1150   // capable/formated/read only */ #define RW_NDEF_FL_FORMATABLE 0x10    /* Tag
1151   // supports format operation */
1152 
1153   if (!sCheckNdefWaitingForComplete) {
1154     LOG(ERROR) << StringPrintf("%s: not waiting", __func__);
1155     return;
1156   }
1157 
1158   if (flags & RW_NDEF_FL_READ_ONLY)
1159     DLOG_IF(INFO, nfc_debug_enabled)
1160         << StringPrintf("%s: flag read-only", __func__);
1161   if (flags & RW_NDEF_FL_FORMATED)
1162     DLOG_IF(INFO, nfc_debug_enabled)
1163         << StringPrintf("%s: flag formatted for ndef", __func__);
1164   if (flags & RW_NDEF_FL_SUPPORTED)
1165     DLOG_IF(INFO, nfc_debug_enabled)
1166         << StringPrintf("%s: flag ndef supported", __func__);
1167   if (flags & RW_NDEF_FL_UNKNOWN)
1168     DLOG_IF(INFO, nfc_debug_enabled)
1169         << StringPrintf("%s: flag all unknown", __func__);
1170   if (flags & RW_NDEF_FL_FORMATABLE)
1171     DLOG_IF(INFO, nfc_debug_enabled)
1172         << StringPrintf("%s: flag formattable", __func__);
1173 
1174   sCheckNdefWaitingForComplete = JNI_FALSE;
1175   sCheckNdefStatus = status;
1176   if (sCheckNdefStatus != NFA_STATUS_OK &&
1177       sCheckNdefStatus != NFA_STATUS_TIMEOUT)
1178     sCheckNdefStatus = NFA_STATUS_FAILED;
1179   sCheckNdefCapable = false;  // assume tag is NOT ndef capable
1180   if (sCheckNdefStatus == NFA_STATUS_OK) {
1181     // NDEF content is on the tag
1182     sCheckNdefMaxSize = maxSize;
1183     sCheckNdefCurrentSize = currentSize;
1184     sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY;
1185     sCheckNdefCapable = true;
1186   } else if (sCheckNdefStatus == NFA_STATUS_FAILED) {
1187     // no NDEF content on the tag
1188     sCheckNdefMaxSize = 0;
1189     sCheckNdefCurrentSize = 0;
1190     sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY;
1191     if ((flags & RW_NDEF_FL_UNKNOWN) == 0)  // if stack understands the tag
1192     {
1193       if (flags & RW_NDEF_FL_SUPPORTED)  // if tag is ndef capable
1194         sCheckNdefCapable = true;
1195     }
1196   } else {
1197     LOG(ERROR) << StringPrintf("%s: unknown status=0x%X", __func__, status);
1198     sCheckNdefMaxSize = 0;
1199     sCheckNdefCurrentSize = 0;
1200     sCheckNdefCardReadOnly = false;
1201   }
1202   sem_post(&sCheckNdefSem);
1203 }
1204 
1205 /*******************************************************************************
1206 **
1207 ** Function:        nativeNfcTag_doCheckNdef
1208 **
1209 ** Description:     Does the tag contain a NDEF message?
1210 **                  e: JVM environment.
1211 **                  o: Java object.
1212 **                  ndefInfo: NDEF info.
1213 **
1214 ** Returns:         Status code; 0 is success.
1215 **
1216 *******************************************************************************/
nativeNfcTag_doCheckNdef(JNIEnv * e,jobject o,jintArray ndefInfo)1217 static jint nativeNfcTag_doCheckNdef(JNIEnv* e, jobject o, jintArray ndefInfo) {
1218   tNFA_STATUS status = NFA_STATUS_FAILED;
1219   jint* ndef = NULL;
1220 
1221   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
1222 
1223   // special case for Kovio
1224   if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) {
1225     DLOG_IF(INFO, nfc_debug_enabled)
1226         << StringPrintf("%s: Kovio tag, no NDEF", __func__);
1227     ndef = e->GetIntArrayElements(ndefInfo, 0);
1228     ndef[0] = 0;
1229     ndef[1] = NDEF_MODE_READ_ONLY;
1230     e->ReleaseIntArrayElements(ndefInfo, ndef, 0);
1231     return NFA_STATUS_FAILED;
1232   } else if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) {
1233     nativeNfcTag_doReconnect(e, o);
1234   }
1235 
1236   /* Create the write semaphore */
1237   if (sem_init(&sCheckNdefSem, 0, 0) == -1) {
1238     LOG(ERROR) << StringPrintf(
1239         "%s: Check NDEF semaphore creation failed (errno=0x%08x)", __func__,
1240         errno);
1241     return JNI_FALSE;
1242   }
1243 
1244   if (NfcTag::getInstance().getActivationState() != NfcTag::Active) {
1245     LOG(ERROR) << StringPrintf("%s: tag already deactivated", __func__);
1246     goto TheEnd;
1247   }
1248 
1249   DLOG_IF(INFO, nfc_debug_enabled)
1250       << StringPrintf("%s: try NFA_RwDetectNDef", __func__);
1251   sCheckNdefWaitingForComplete = JNI_TRUE;
1252 
1253   if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
1254     status = EXTNS_MfcCheckNDef();
1255   } else {
1256     status = NFA_RwDetectNDef();
1257   }
1258 
1259   if (status != NFA_STATUS_OK) {
1260     LOG(ERROR) << StringPrintf("%s: NFA_RwDetectNDef failed, status = 0x%X",
1261                                __func__, status);
1262     goto TheEnd;
1263   }
1264 
1265   /* Wait for check NDEF completion status */
1266   if (sem_wait(&sCheckNdefSem)) {
1267     LOG(ERROR) << StringPrintf(
1268         "%s: Failed to wait for check NDEF semaphore (errno=0x%08x)", __func__,
1269         errno);
1270     goto TheEnd;
1271   }
1272 
1273   if (sCheckNdefStatus == NFA_STATUS_OK) {
1274     // stack found a NDEF message on the tag
1275     ndef = e->GetIntArrayElements(ndefInfo, 0);
1276     if (NfcTag::getInstance().getProtocol() == NFA_PROTOCOL_T1T)
1277       ndef[0] = NfcTag::getInstance().getT1tMaxMessageSize();
1278     else
1279       ndef[0] = sCheckNdefMaxSize;
1280     if (sCheckNdefCardReadOnly)
1281       ndef[1] = NDEF_MODE_READ_ONLY;
1282     else
1283       ndef[1] = NDEF_MODE_READ_WRITE;
1284     e->ReleaseIntArrayElements(ndefInfo, ndef, 0);
1285     status = NFA_STATUS_OK;
1286   } else if (sCheckNdefStatus == NFA_STATUS_FAILED) {
1287     // stack did not find a NDEF message on the tag;
1288     ndef = e->GetIntArrayElements(ndefInfo, 0);
1289     if (NfcTag::getInstance().getProtocol() == NFA_PROTOCOL_T1T)
1290       ndef[0] = NfcTag::getInstance().getT1tMaxMessageSize();
1291     else
1292       ndef[0] = sCheckNdefMaxSize;
1293     if (sCheckNdefCardReadOnly)
1294       ndef[1] = NDEF_MODE_READ_ONLY;
1295     else
1296       ndef[1] = NDEF_MODE_READ_WRITE;
1297     e->ReleaseIntArrayElements(ndefInfo, ndef, 0);
1298     status = NFA_STATUS_FAILED;
1299   } else {
1300     DLOG_IF(INFO, nfc_debug_enabled)
1301         << StringPrintf("%s: unknown status 0x%X", __func__, sCheckNdefStatus);
1302     status = sCheckNdefStatus;
1303   }
1304 
1305   /* Reconnect Mifare Classic Tag for furture use */
1306   if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) {
1307     nativeNfcTag_doReconnect(e, o);
1308   }
1309 
1310 TheEnd:
1311   /* Destroy semaphore */
1312   if (sem_destroy(&sCheckNdefSem)) {
1313     LOG(ERROR) << StringPrintf(
1314         "%s: Failed to destroy check NDEF semaphore (errno=0x%08x)", __func__,
1315         errno);
1316   }
1317   sCheckNdefWaitingForComplete = JNI_FALSE;
1318   DLOG_IF(INFO, nfc_debug_enabled)
1319       << StringPrintf("%s: exit; status=0x%X", __func__, status);
1320   return status;
1321 }
1322 
1323 /*******************************************************************************
1324 **
1325 ** Function:        nativeNfcTag_resetPresenceCheck
1326 **
1327 ** Description:     Reset variables related to presence-check.
1328 **
1329 ** Returns:         None
1330 **
1331 *******************************************************************************/
nativeNfcTag_resetPresenceCheck()1332 void nativeNfcTag_resetPresenceCheck() { sIsTagPresent = true; }
1333 
1334 /*******************************************************************************
1335 **
1336 ** Function:        nativeNfcTag_doPresenceCheckResult
1337 **
1338 ** Description:     Receive the result of presence-check.
1339 **                  status: Result of presence-check.
1340 **
1341 ** Returns:         None
1342 **
1343 *******************************************************************************/
nativeNfcTag_doPresenceCheckResult(tNFA_STATUS status)1344 void nativeNfcTag_doPresenceCheckResult(tNFA_STATUS status) {
1345   SyncEventGuard guard(sPresenceCheckEvent);
1346   sIsTagPresent = status == NFA_STATUS_OK;
1347   sPresenceCheckEvent.notifyOne();
1348 }
1349 
1350 /*******************************************************************************
1351 **
1352 ** Function:        nativeNfcTag_doPresenceCheck
1353 **
1354 ** Description:     Check if the tag is in the RF field.
1355 **                  e: JVM environment.
1356 **                  o: Java object.
1357 **
1358 ** Returns:         True if tag is in RF field.
1359 **
1360 *******************************************************************************/
nativeNfcTag_doPresenceCheck(JNIEnv *,jobject)1361 static jboolean nativeNfcTag_doPresenceCheck(JNIEnv*, jobject) {
1362   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1363   tNFA_STATUS status = NFA_STATUS_OK;
1364   jboolean isPresent = JNI_FALSE;
1365 
1366   // Special case for Kovio.  The deactivation would have already occurred
1367   // but was ignored so that normal tag opertions could complete.  Now we
1368   // want to process as if the deactivate just happened.
1369   if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) {
1370     DLOG_IF(INFO, nfc_debug_enabled)
1371         << StringPrintf("%s: Kovio, force deactivate handling", __func__);
1372     tNFA_DEACTIVATED deactivated = {NFA_DEACTIVATE_TYPE_IDLE};
1373     {
1374       SyncEventGuard g(gDeactivatedEvent);
1375       gActivated = false;  // guard this variable from multi-threaded access
1376       gDeactivatedEvent.notifyOne();
1377     }
1378 
1379     NfcTag::getInstance().setDeactivationState(deactivated);
1380     nativeNfcTag_resetPresenceCheck();
1381     NfcTag::getInstance().connectionEventHandler(NFA_DEACTIVATED_EVT, NULL);
1382     nativeNfcTag_abortWaits();
1383     NfcTag::getInstance().abort();
1384 
1385     return JNI_FALSE;
1386   }
1387 
1388   if (nfcManager_isNfcActive() == false) {
1389     DLOG_IF(INFO, nfc_debug_enabled)
1390         << StringPrintf("%s: NFC is no longer active.", __func__);
1391     return JNI_FALSE;
1392   }
1393 
1394   if (!sRfInterfaceMutex.tryLock()) {
1395     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1396         "%s: tag is being reSelected assume it is present", __func__);
1397     return JNI_TRUE;
1398   }
1399 
1400   sRfInterfaceMutex.unlock();
1401 
1402   if (NfcTag::getInstance().isActivated() == false) {
1403     DLOG_IF(INFO, nfc_debug_enabled)
1404         << StringPrintf("%s: tag already deactivated", __func__);
1405     return JNI_FALSE;
1406   }
1407   if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
1408     status = EXTNS_MfcPresenceCheck();
1409     if (status == NFCSTATUS_SUCCESS) {
1410       return (NFCSTATUS_SUCCESS == EXTNS_GetPresenceCheckStatus()) ? JNI_TRUE
1411                                                                    : JNI_FALSE;
1412     }
1413   }
1414 
1415   {
1416     SyncEventGuard guard(sPresenceCheckEvent);
1417     status =
1418         NFA_RwPresenceCheck(NfcTag::getInstance().getPresenceCheckAlgorithm());
1419     if (status == NFA_STATUS_OK) {
1420       sPresenceCheckEvent.wait();
1421       isPresent = sIsTagPresent ? JNI_TRUE : JNI_FALSE;
1422     }
1423   }
1424 
1425   if (isPresent == JNI_FALSE)
1426     DLOG_IF(INFO, nfc_debug_enabled)
1427         << StringPrintf("%s: tag absent", __func__);
1428   return isPresent;
1429 }
1430 
1431 /*******************************************************************************
1432 **
1433 ** Function:        nativeNfcTag_doIsNdefFormatable
1434 **
1435 ** Description:     Can tag be formatted to store NDEF message?
1436 **                  e: JVM environment.
1437 **                  o: Java object.
1438 **                  libNfcType: Type of tag.
1439 **                  uidBytes: Tag's unique ID.
1440 **                  pollBytes: Data from activation.
1441 **                  actBytes: Data from activation.
1442 **
1443 ** Returns:         True if formattable.
1444 **
1445 *******************************************************************************/
nativeNfcTag_doIsNdefFormatable(JNIEnv * e,jobject o,jint,jbyteArray,jbyteArray,jbyteArray)1446 static jboolean nativeNfcTag_doIsNdefFormatable(JNIEnv* e, jobject o,
1447                                                 jint /*libNfcType*/, jbyteArray,
1448                                                 jbyteArray, jbyteArray) {
1449   jboolean isFormattable = JNI_FALSE;
1450   tNFC_PROTOCOL protocol = NfcTag::getInstance().getProtocol();
1451   if (NFA_PROTOCOL_T1T == protocol || NFA_PROTOCOL_T5T == protocol ||
1452       NFC_PROTOCOL_MIFARE == protocol) {
1453     isFormattable = JNI_TRUE;
1454   } else if (NFA_PROTOCOL_T3T == protocol) {
1455     isFormattable = NfcTag::getInstance().isFelicaLite() ? JNI_TRUE : JNI_FALSE;
1456   } else if (NFA_PROTOCOL_T2T == protocol) {
1457     isFormattable = (NfcTag::getInstance().isMifareUltralight() |
1458                      NfcTag::getInstance().isInfineonMyDMove() |
1459                      NfcTag::getInstance().isKovioType2Tag())
1460                         ? JNI_TRUE
1461                         : JNI_FALSE;
1462   } else if (NFA_PROTOCOL_ISO_DEP == protocol) {
1463     /**
1464      * Determines whether this is a formatable IsoDep tag - currectly only NXP
1465      * DESFire is supported.
1466      */
1467     uint8_t cmd[] = {0x90, 0x60, 0x00, 0x00, 0x00};
1468 
1469     if (NfcTag::getInstance().isMifareDESFire()) {
1470       /* Identifies as DESfire, use get version cmd to be sure */
1471       jbyteArray versionCmd = e->NewByteArray(5);
1472       e->SetByteArrayRegion(versionCmd, 0, 5, (jbyte*)cmd);
1473       jbyteArray respBytes =
1474           nativeNfcTag_doTransceive(e, o, versionCmd, JNI_TRUE, NULL);
1475       if (respBytes != NULL) {
1476         // Check whether the response matches a typical DESfire
1477         // response.
1478         // libNFC even does more advanced checking than we do
1479         // here, and will only format DESfire's with a certain
1480         // major/minor sw version and NXP as a manufacturer.
1481         // We don't want to do such checking here, to avoid
1482         // having to change code in multiple places.
1483         // A succesful (wrapped) DESFire getVersion command returns
1484         // 9 bytes, with byte 7 0x91 and byte 8 having status
1485         // code 0xAF (these values are fixed and well-known).
1486         int respLength = e->GetArrayLength(respBytes);
1487         uint8_t* resp = (uint8_t*)e->GetByteArrayElements(respBytes, NULL);
1488         if (respLength == 9 && resp[7] == 0x91 && resp[8] == 0xAF) {
1489           isFormattable = JNI_TRUE;
1490         }
1491         e->ReleaseByteArrayElements(respBytes, (jbyte*)resp, JNI_ABORT);
1492       }
1493     }
1494   }
1495 
1496   DLOG_IF(INFO, nfc_debug_enabled)
1497       << StringPrintf("%s: is formattable=%u", __func__, isFormattable);
1498   return isFormattable;
1499 }
1500 
1501 /*******************************************************************************
1502 **
1503 ** Function:        nativeNfcTag_doIsIsoDepNdefFormatable
1504 **
1505 ** Description:     Is ISO-DEP tag formattable?
1506 **                  e: JVM environment.
1507 **                  o: Java object.
1508 **                  pollBytes: Data from activation.
1509 **                  actBytes: Data from activation.
1510 **
1511 ** Returns:         True if formattable.
1512 **
1513 *******************************************************************************/
nativeNfcTag_doIsIsoDepNdefFormatable(JNIEnv * e,jobject o,jbyteArray pollBytes,jbyteArray actBytes)1514 static jboolean nativeNfcTag_doIsIsoDepNdefFormatable(JNIEnv* e, jobject o,
1515                                                       jbyteArray pollBytes,
1516                                                       jbyteArray actBytes) {
1517   uint8_t uidFake[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
1518   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1519   jbyteArray uidArray = e->NewByteArray(8);
1520   e->SetByteArrayRegion(uidArray, 0, 8, (jbyte*)uidFake);
1521   return nativeNfcTag_doIsNdefFormatable(e, o, 0, uidArray, pollBytes,
1522                                          actBytes);
1523 }
1524 
1525 /*******************************************************************************
1526 **
1527 ** Function:        nativeNfcTag_makeMifareNdefFormat
1528 **
1529 ** Description:     Format a mifare classic tag so it can store NDEF message.
1530 **                  e: JVM environment.
1531 **                  o: Java object.
1532 **                  key: Key to acces tag.
1533 **                  keySize: size of Key.
1534 **
1535 ** Returns:         True if ok.
1536 **
1537 *******************************************************************************/
nativeNfcTag_makeMifareNdefFormat(JNIEnv * e,jobject o,uint8_t * key,uint32_t keySize)1538 static jboolean nativeNfcTag_makeMifareNdefFormat(JNIEnv* e, jobject o,
1539                                                   uint8_t* key,
1540                                                   uint32_t keySize) {
1541   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
1542   tNFA_STATUS status = NFA_STATUS_OK;
1543 
1544   status = nativeNfcTag_doReconnect(e, o);
1545   if (status != NFA_STATUS_OK) {
1546     DLOG_IF(INFO, nfc_debug_enabled)
1547         << StringPrintf("%s: reconnect error, status=%u", __func__, status);
1548     return JNI_FALSE;
1549   }
1550 
1551   sem_init(&sFormatSem, 0, 0);
1552   sFormatOk = false;
1553 
1554   status = EXTNS_MfcFormatTag(key, keySize);
1555 
1556   if (status == NFA_STATUS_OK) {
1557     DLOG_IF(INFO, nfc_debug_enabled)
1558         << StringPrintf("%s: wait for completion", __func__);
1559     sem_wait(&sFormatSem);
1560     status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED;
1561   } else {
1562     LOG(ERROR) << StringPrintf("%s: error status=%u", __func__, status);
1563   }
1564 
1565   sem_destroy(&sFormatSem);
1566   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
1567   return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
1568 }
1569 
1570 /*******************************************************************************
1571 **
1572 ** Function:        nativeNfcTag_doNdefFormat
1573 **
1574 ** Description:     Format a tag so it can store NDEF message.
1575 **                  e: JVM environment.
1576 **                  o: Java object.
1577 **                  key: Not used.
1578 **
1579 ** Returns:         True if ok.
1580 **
1581 *******************************************************************************/
nativeNfcTag_doNdefFormat(JNIEnv * e,jobject o,jbyteArray)1582 static jboolean nativeNfcTag_doNdefFormat(JNIEnv* e, jobject o, jbyteArray) {
1583   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
1584   tNFA_STATUS status = NFA_STATUS_OK;
1585 
1586   // Do not try to format if tag is already deactivated.
1587   if (NfcTag::getInstance().isActivated() == false) {
1588     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1589         "%s: tag already deactivated(no need to format)", __func__);
1590     return JNI_FALSE;
1591   }
1592 
1593   if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
1594     static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1595     static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7};
1596     jboolean result;
1597 
1598     result =
1599         nativeNfcTag_makeMifareNdefFormat(e, o, mfc_key1, sizeof(mfc_key1));
1600     if (result == JNI_FALSE) {
1601       result =
1602           nativeNfcTag_makeMifareNdefFormat(e, o, mfc_key2, sizeof(mfc_key2));
1603     }
1604     return result;
1605   }
1606 
1607   sem_init(&sFormatSem, 0, 0);
1608   sFormatOk = false;
1609   status = NFA_RwFormatTag();
1610   if (status == NFA_STATUS_OK) {
1611     DLOG_IF(INFO, nfc_debug_enabled)
1612         << StringPrintf("%s: wait for completion", __func__);
1613     sem_wait(&sFormatSem);
1614     status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED;
1615   } else
1616     LOG(ERROR) << StringPrintf("%s: error status=%u", __func__, status);
1617   sem_destroy(&sFormatSem);
1618 
1619   if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_ISO_DEP) {
1620     int retCode = NFCSTATUS_SUCCESS;
1621     retCode = nativeNfcTag_doReconnect(e, o);
1622   }
1623   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
1624   return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
1625 }
1626 
1627 /*******************************************************************************
1628 **
1629 ** Function:        nativeNfcTag_doMakeReadonlyResult
1630 **
1631 ** Description:     Receive the result of making a tag read-only. Called by the
1632 **                  NFA_SET_TAG_RO_EVT.
1633 **                  status: Status of the operation.
1634 **
1635 ** Returns:         None
1636 **
1637 *******************************************************************************/
nativeNfcTag_doMakeReadonlyResult(tNFA_STATUS status)1638 void nativeNfcTag_doMakeReadonlyResult(tNFA_STATUS status) {
1639   if (sMakeReadonlyWaitingForComplete != JNI_FALSE) {
1640     sMakeReadonlyWaitingForComplete = JNI_FALSE;
1641     sMakeReadonlyStatus = status;
1642 
1643     sem_post(&sMakeReadonlySem);
1644   }
1645 }
1646 
1647 /*******************************************************************************
1648 **
1649 ** Function:        nativeNfcTag_makeMifareReadonly
1650 **
1651 ** Description:     Make the mifare classic tag read-only.
1652 **                  e: JVM environment.
1653 **                  o: Java object.
1654 **                  key: Key to access the tag.
1655 **                  keySize: size of Key.
1656 **
1657 ** Returns:         True if ok.
1658 **
1659 *******************************************************************************/
nativeNfcTag_makeMifareReadonly(JNIEnv * e,jobject o,uint8_t * key,int32_t keySize)1660 static jboolean nativeNfcTag_makeMifareReadonly(JNIEnv* e, jobject o,
1661                                                 uint8_t* key, int32_t keySize) {
1662   jboolean result = JNI_FALSE;
1663   tNFA_STATUS status = NFA_STATUS_OK;
1664 
1665   sMakeReadonlyStatus = NFA_STATUS_FAILED;
1666 
1667   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1668 
1669   /* Create the make_readonly semaphore */
1670   if (sem_init(&sMakeReadonlySem, 0, 0) == -1) {
1671     LOG(ERROR) << StringPrintf(
1672         "%s: Make readonly semaphore creation failed (errno=0x%08x)", __func__,
1673         errno);
1674     return JNI_FALSE;
1675   }
1676 
1677   sMakeReadonlyWaitingForComplete = JNI_TRUE;
1678 
1679   status = nativeNfcTag_doReconnect(e, o);
1680   if (status != NFA_STATUS_OK) {
1681     goto TheEnd;
1682   }
1683 
1684   status = EXTNS_MfcSetReadOnly(key, keySize);
1685   if (status != NFA_STATUS_OK) {
1686     goto TheEnd;
1687   }
1688   sem_wait(&sMakeReadonlySem);
1689 
1690   if (sMakeReadonlyStatus == NFA_STATUS_OK) {
1691     result = JNI_TRUE;
1692   }
1693 
1694 TheEnd:
1695   /* Destroy semaphore */
1696   if (sem_destroy(&sMakeReadonlySem)) {
1697     LOG(ERROR) << StringPrintf(
1698         "%s: Failed to destroy read_only semaphore (errno=0x%08x)", __func__,
1699         errno);
1700   }
1701   sMakeReadonlyWaitingForComplete = JNI_FALSE;
1702   return result;
1703 }
1704 
1705 /*******************************************************************************
1706 **
1707 ** Function:        nativeNfcTag_doMakeReadonly
1708 **
1709 ** Description:     Make the tag read-only.
1710 **                  e: JVM environment.
1711 **                  o: Java object.
1712 **                  key: Key to access the tag.
1713 **
1714 ** Returns:         True if ok.
1715 **
1716 *******************************************************************************/
nativeNfcTag_doMakeReadonly(JNIEnv * e,jobject o,jbyteArray)1717 static jboolean nativeNfcTag_doMakeReadonly(JNIEnv* e, jobject o, jbyteArray) {
1718   jboolean result = JNI_FALSE;
1719   tNFA_STATUS status;
1720 
1721   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1722 
1723   if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
1724     static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1725     static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7};
1726     result = nativeNfcTag_makeMifareReadonly(e, o, mfc_key1, sizeof(mfc_key1));
1727     if (result == JNI_FALSE) {
1728       result =
1729           nativeNfcTag_makeMifareReadonly(e, o, mfc_key2, sizeof(mfc_key2));
1730     }
1731     return result;
1732   }
1733 
1734   /* Create the make_readonly semaphore */
1735   if (sem_init(&sMakeReadonlySem, 0, 0) == -1) {
1736     LOG(ERROR) << StringPrintf(
1737         "%s: Make readonly semaphore creation failed (errno=0x%08x)", __func__,
1738         errno);
1739     return JNI_FALSE;
1740   }
1741 
1742   sMakeReadonlyWaitingForComplete = JNI_TRUE;
1743 
1744   // Hard-lock the tag (cannot be reverted)
1745   status = NFA_RwSetTagReadOnly(TRUE);
1746   if (status == NFA_STATUS_REJECTED) {
1747     status = NFA_RwSetTagReadOnly(FALSE);  // try soft lock
1748     if (status != NFA_STATUS_OK) {
1749       LOG(ERROR) << StringPrintf("%s: fail soft lock, status=%d", __func__,
1750                                  status);
1751       goto TheEnd;
1752     }
1753   } else if (status != NFA_STATUS_OK) {
1754     LOG(ERROR) << StringPrintf("%s: fail hard lock, status=%d", __func__,
1755                                status);
1756     goto TheEnd;
1757   }
1758 
1759   /* Wait for check NDEF completion status */
1760   if (sem_wait(&sMakeReadonlySem)) {
1761     LOG(ERROR) << StringPrintf(
1762         "%s: Failed to wait for make_readonly semaphore (errno=0x%08x)",
1763         __func__, errno);
1764     goto TheEnd;
1765   }
1766 
1767   if (sMakeReadonlyStatus == NFA_STATUS_OK) {
1768     result = JNI_TRUE;
1769   }
1770 
1771 TheEnd:
1772   /* Destroy semaphore */
1773   if (sem_destroy(&sMakeReadonlySem)) {
1774     LOG(ERROR) << StringPrintf(
1775         "%s: Failed to destroy read_only semaphore (errno=0x%08x)", __func__,
1776         errno);
1777   }
1778   sMakeReadonlyWaitingForComplete = JNI_FALSE;
1779   return result;
1780 }
1781 
1782 /*******************************************************************************
1783 **
1784 ** Function:        nativeNfcTag_registerNdefTypeHandler
1785 **
1786 ** Description:     Register a callback to receive NDEF message from the tag
1787 **                  from the NFA_NDEF_DATA_EVT.
1788 **
1789 ** Returns:         None
1790 **
1791 *******************************************************************************/
1792 // register a callback to receive NDEF message from the tag
1793 // from the NFA_NDEF_DATA_EVT;
nativeNfcTag_registerNdefTypeHandler()1794 void nativeNfcTag_registerNdefTypeHandler() {
1795   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1796   sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
1797   NFA_RegisterNDefTypeHandler(TRUE, NFA_TNF_DEFAULT, (uint8_t*)"", 0,
1798                               ndefHandlerCallback);
1799   if (legacy_mfc_reader) {
1800     EXTNS_MfcRegisterNDefTypeHandler(ndefHandlerCallback);
1801   }
1802 }
1803 
1804 /*******************************************************************************
1805 **
1806 ** Function:        nativeNfcTag_deregisterNdefTypeHandler
1807 **
1808 ** Description:     No longer need to receive NDEF message from the tag.
1809 **
1810 ** Returns:         None
1811 **
1812 *******************************************************************************/
nativeNfcTag_deregisterNdefTypeHandler()1813 void nativeNfcTag_deregisterNdefTypeHandler() {
1814   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1815   NFA_DeregisterNDefTypeHandler(sNdefTypeHandlerHandle);
1816   sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
1817 }
1818 
1819 /*******************************************************************************
1820 **
1821 ** Function:        nativeNfcTag_acquireRfInterfaceMutexLock
1822 **
1823 ** Description:     acquire sRfInterfaceMutex
1824 **
1825 ** Returns:         None
1826 **
1827 *******************************************************************************/
nativeNfcTag_acquireRfInterfaceMutexLock()1828 void nativeNfcTag_acquireRfInterfaceMutexLock() {
1829   DLOG_IF(INFO, nfc_debug_enabled)
1830       << StringPrintf("%s: try to acquire lock", __func__);
1831   sRfInterfaceMutex.lock();
1832   DLOG_IF(INFO, nfc_debug_enabled)
1833       << StringPrintf("%s: sRfInterfaceMutex lock", __func__);
1834 }
1835 
1836 /*******************************************************************************
1837 **
1838 ** Function:       nativeNfcTag_releaseRfInterfaceMutexLock
1839 **
1840 ** Description:    release the sRfInterfaceMutex
1841 **
1842 ** Returns:        None
1843 **
1844 *******************************************************************************/
nativeNfcTag_releaseRfInterfaceMutexLock()1845 void nativeNfcTag_releaseRfInterfaceMutexLock() {
1846   sRfInterfaceMutex.unlock();
1847   DLOG_IF(INFO, nfc_debug_enabled)
1848       << StringPrintf("%s: sRfInterfaceMutex unlock", __func__);
1849 }
1850 
1851 /*****************************************************************************
1852 **
1853 ** JNI functions for Android 4.0.3
1854 **
1855 *****************************************************************************/
1856 static JNINativeMethod gMethods[] = {
1857     {"doConnect", "(I)I", (void*)nativeNfcTag_doConnect},
1858     {"doDisconnect", "()Z", (void*)nativeNfcTag_doDisconnect},
1859     {"doReconnect", "()I", (void*)nativeNfcTag_doReconnect},
1860     {"doHandleReconnect", "(I)I", (void*)nativeNfcTag_doHandleReconnect},
1861     {"doTransceive", "([BZ[I)[B", (void*)nativeNfcTag_doTransceive},
1862     {"doGetNdefType", "(II)I", (void*)nativeNfcTag_doGetNdefType},
1863     {"doCheckNdef", "([I)I", (void*)nativeNfcTag_doCheckNdef},
1864     {"doRead", "()[B", (void*)nativeNfcTag_doRead},
1865     {"doWrite", "([B)Z", (void*)nativeNfcTag_doWrite},
1866     {"doPresenceCheck", "()Z", (void*)nativeNfcTag_doPresenceCheck},
1867     {"doIsIsoDepNdefFormatable", "([B[B)Z",
1868      (void*)nativeNfcTag_doIsIsoDepNdefFormatable},
1869     {"doNdefFormat", "([B)Z", (void*)nativeNfcTag_doNdefFormat},
1870     {"doMakeReadonly", "([B)Z", (void*)nativeNfcTag_doMakeReadonly},
1871 };
1872 
1873 /*******************************************************************************
1874 **
1875 ** Function:        register_com_android_nfc_NativeNfcTag
1876 **
1877 ** Description:     Regisgter JNI functions with Java Virtual Machine.
1878 **                  e: Environment of JVM.
1879 **
1880 ** Returns:         Status of registration.
1881 **
1882 *******************************************************************************/
register_com_android_nfc_NativeNfcTag(JNIEnv * e)1883 int register_com_android_nfc_NativeNfcTag(JNIEnv* e) {
1884   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1885   return jniRegisterNativeMethods(e, gNativeNfcTagClassName, gMethods,
1886                                   NELEM(gMethods));
1887 }
1888 
1889 } /* namespace android */
1890