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     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
585         "%s: switching to tech: %d need to switch rf intf to frame", __func__,
586         sCurrentConnectedTargetType);
587     retCode = switchRfInterface(NFA_INTERFACE_FRAME) ? NFA_STATUS_OK
588                                                      : NFA_STATUS_FAILED;
589   } else if (sCurrentConnectedTargetType == TARGET_TYPE_MIFARE_CLASSIC) {
590     retCode = switchRfInterface(NFA_INTERFACE_MIFARE) ? NFA_STATUS_OK
591                                                       : NFA_STATUS_FAILED;
592   } else {
593     retCode = switchRfInterface(NFA_INTERFACE_ISO_DEP) ? NFA_STATUS_OK
594                                                        : NFA_STATUS_FAILED;
595   }
596 
597 TheEnd:
598   DLOG_IF(INFO, nfc_debug_enabled)
599       << StringPrintf("%s: exit 0x%X", __func__, retCode);
600   return retCode;
601 }
602 
603 /*******************************************************************************
604 **
605 ** Function:        reSelect
606 **
607 ** Description:     Deactivates the tag and re-selects it with the specified
608 **                  rf interface.
609 **
610 ** Returns:         status code, 0 on success, 1 on failure,
611 **                  146 (defined in service) on tag lost
612 **
613 *******************************************************************************/
reSelect(tNFA_INTF_TYPE rfInterface,bool fSwitchIfNeeded)614 static int reSelect(tNFA_INTF_TYPE rfInterface, bool fSwitchIfNeeded) {
615   DLOG_IF(INFO, nfc_debug_enabled)
616       << StringPrintf("%s: enter; rf intf = %d, current intf = %d", __func__,
617                       rfInterface, sCurrentRfInterface);
618 
619   sRfInterfaceMutex.lock();
620 
621   if (fSwitchIfNeeded && (rfInterface == sCurrentRfInterface)) {
622     // already in the requested interface
623     sRfInterfaceMutex.unlock();
624     return 0;  // success
625   }
626 
627   NfcTag& natTag = NfcTag::getInstance();
628 
629   tNFA_STATUS status = NFA_STATUS_OK;
630   int rVal = 1;
631 
632   do {
633     // if tag has shutdown, abort this method
634     if (NfcTag::getInstance().isNdefDetectionTimedOut()) {
635       DLOG_IF(INFO, nfc_debug_enabled)
636           << StringPrintf("%s: ndef detection timeout; break", __func__);
637       rVal = STATUS_CODE_TARGET_LOST;
638       break;
639     }
640     if ((sCurrentRfInterface == NFA_INTERFACE_FRAME) &&
641         (NFC_GetNCIVersion() >= NCI_VERSION_2_0)) {
642       {
643         SyncEventGuard g3(sReconnectEvent);
644         if (sCurrentActivatedProtocl == NFA_PROTOCOL_T2T) {
645           status = NFA_SendRawFrame(RW_TAG_SLP_REQ, sizeof(RW_TAG_SLP_REQ), 0);
646         } else if (sCurrentActivatedProtocl == NFA_PROTOCOL_ISO_DEP) {
647           status = NFA_SendRawFrame(RW_DESELECT_REQ,
648                                     sizeof(RW_DESELECT_REQ), 0);
649         }
650         sReconnectEvent.wait(4);
651         if (status != NFA_STATUS_OK) {
652           LOG(ERROR) << StringPrintf("%s: send error=%d", __func__, status);
653           break;
654         }
655       }
656     }
657 
658     {
659       SyncEventGuard g(sReconnectEvent);
660       gIsTagDeactivating = true;
661       sGotDeactivate = false;
662       DLOG_IF(INFO, nfc_debug_enabled)
663           << StringPrintf("%s: deactivate to sleep", __func__);
664       if (NFA_STATUS_OK !=
665           (status = NFA_Deactivate(TRUE)))  // deactivate to sleep state
666       {
667         LOG(ERROR) << StringPrintf("%s: deactivate failed, status = %d",
668                                    __func__, status);
669         break;
670       }
671 
672       if (sReconnectEvent.wait(1000) == false)  // if timeout occurred
673       {
674         LOG(ERROR) << StringPrintf("%s: timeout waiting for deactivate",
675                                    __func__);
676       }
677     }
678 
679     if (!sGotDeactivate) {
680       rVal = STATUS_CODE_TARGET_LOST;
681       break;
682     }
683 
684     if (NfcTag::getInstance().getActivationState() != NfcTag::Sleep) {
685       LOG(ERROR) << StringPrintf("%s: tag is not in sleep", __func__);
686       rVal = STATUS_CODE_TARGET_LOST;
687       break;
688     }
689 
690     gIsTagDeactivating = false;
691 
692     {
693       SyncEventGuard g2(sReconnectEvent);
694 
695       sConnectWaitingForComplete = JNI_TRUE;
696       DLOG_IF(INFO, nfc_debug_enabled)
697           << StringPrintf("%s: select interface %u", __func__, rfInterface);
698       gIsSelectingRfInterface = true;
699       if (NFA_STATUS_OK !=
700           (status = NFA_Select(natTag.mTechHandles[sCurrentConnectedHandle],
701                                natTag.mTechLibNfcTypes[sCurrentConnectedHandle],
702                                rfInterface))) {
703         LOG(ERROR) << StringPrintf("%s: NFA_Select failed, status = %d",
704                                    __func__, status);
705         break;
706       }
707 
708       sConnectOk = false;
709       if (sReconnectEvent.wait(1000) == false)  // if timeout occurred
710       {
711         LOG(ERROR) << StringPrintf("%s: timeout waiting for select", __func__);
712         break;
713       }
714     }
715 
716     /*Retry logic in case of core Generic error while selecting a tag*/
717     if (sConnectOk == false) {
718       LOG(ERROR) << StringPrintf("%s: waiting for Card to be activated",
719                                  __func__);
720       int retry = 0;
721       sConnectWaitingForComplete = JNI_TRUE;
722       do {
723         SyncEventGuard reselectEvent(sReconnectEvent);
724         if (sReconnectEvent.wait(500) == false) {  // if timeout occurred
725           LOG(ERROR) << StringPrintf("%s: timeout ", __func__);
726         }
727         retry++;
728         LOG(ERROR) << StringPrintf("%s: waiting for Card to be activated %x %x",
729                                    __func__, retry, sConnectOk);
730       } while (sConnectOk == false && retry < 3);
731     }
732 
733     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
734         "%s: select completed; sConnectOk=%d", __func__, sConnectOk);
735     if (NfcTag::getInstance().getActivationState() != NfcTag::Active) {
736       LOG(ERROR) << StringPrintf("%s: tag is not active", __func__);
737       rVal = STATUS_CODE_TARGET_LOST;
738       break;
739     }
740     if (sConnectOk) {
741       rVal = 0;  // success
742       sCurrentRfInterface = rfInterface;
743     } else {
744       rVal = 1;
745     }
746   } while (0);
747 
748   sConnectWaitingForComplete = JNI_FALSE;
749   gIsTagDeactivating = false;
750   gIsSelectingRfInterface = false;
751   sRfInterfaceMutex.unlock();
752   DLOG_IF(INFO, nfc_debug_enabled)
753       << StringPrintf("%s: exit; status=%d", __func__, rVal);
754   return rVal;
755 }
756 
757 /*******************************************************************************
758 **
759 ** Function:        switchRfInterface
760 **
761 ** Description:     Switch controller's RF interface to frame, ISO-DEP, or
762 *NFC-DEP.
763 **                  rfInterface: Type of RF interface.
764 **
765 ** Returns:         True if ok.
766 **
767 *******************************************************************************/
switchRfInterface(tNFA_INTF_TYPE rfInterface)768 static bool switchRfInterface(tNFA_INTF_TYPE rfInterface) {
769   NfcTag& natTag = NfcTag::getInstance();
770 
771   if (sCurrentConnectedTargetProtocol != NFC_PROTOCOL_ISO_DEP &&
772       sCurrentConnectedTargetProtocol != NFC_PROTOCOL_MIFARE) {
773     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
774         "%s: protocol: %d not ISO_DEP and not Mifare, do nothing", __func__,
775         natTag.mTechLibNfcTypes[0]);
776     return true;
777   }
778 
779   DLOG_IF(INFO, nfc_debug_enabled)
780       << StringPrintf("%s: new rf intf = %d, cur rf intf = %d", __func__,
781                       rfInterface, sCurrentRfInterface);
782 
783   return (0 == reSelect(rfInterface, true));
784 }
785 
786 /*******************************************************************************
787 **
788 ** Function:        nativeNfcTag_doReconnect
789 **
790 ** Description:     Re-connect to the tag in RF field.
791 **                  e: JVM environment.
792 **                  o: Java object.
793 **
794 ** Returns:         Status code.
795 **
796 *******************************************************************************/
nativeNfcTag_doReconnect(JNIEnv *,jobject)797 static jint nativeNfcTag_doReconnect(JNIEnv*, jobject) {
798   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
799   int retCode = NFCSTATUS_SUCCESS;
800   NfcTag& natTag = NfcTag::getInstance();
801 
802   if (natTag.getActivationState() != NfcTag::Active) {
803     LOG(ERROR) << StringPrintf("%s: tag already deactivated", __func__);
804     retCode = NFCSTATUS_FAILED;
805     goto TheEnd;
806   }
807 
808   // special case for Kovio
809   if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) {
810     DLOG_IF(INFO, nfc_debug_enabled)
811         << StringPrintf("%s: fake out reconnect for Kovio", __func__);
812     goto TheEnd;
813   }
814 
815   // this is only supported for type 2 or 4 (ISO_DEP) tags
816   if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_ISO_DEP)
817     retCode = reSelect(NFA_INTERFACE_ISO_DEP, false);
818   else if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_T2T)
819     retCode = reSelect(NFA_INTERFACE_FRAME, false);
820   else if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE)
821     retCode = reSelect(NFA_INTERFACE_MIFARE, false);
822 
823 TheEnd:
824   DLOG_IF(INFO, nfc_debug_enabled)
825       << StringPrintf("%s: exit 0x%X", __func__, retCode);
826   return retCode;
827 }
828 
829 /*******************************************************************************
830 **
831 ** Function:        nativeNfcTag_doHandleReconnect
832 **
833 ** Description:     Re-connect to the tag in RF field.
834 **                  e: JVM environment.
835 **                  o: Java object.
836 **                  targetHandle: Handle of the tag.
837 **
838 ** Returns:         Status code.
839 **
840 *******************************************************************************/
nativeNfcTag_doHandleReconnect(JNIEnv * e,jobject o,jint targetHandle)841 static jint nativeNfcTag_doHandleReconnect(JNIEnv* e, jobject o,
842                                            jint targetHandle) {
843   DLOG_IF(INFO, nfc_debug_enabled)
844       << StringPrintf("%s: targetHandle = %d", __func__, targetHandle);
845   return nativeNfcTag_doConnect(e, o, targetHandle);
846 }
847 
848 /*******************************************************************************
849 **
850 ** Function:        nativeNfcTag_doDisconnect
851 **
852 ** Description:     Deactivate the RF field.
853 **                  e: JVM environment.
854 **                  o: Java object.
855 **
856 ** Returns:         True if ok.
857 **
858 *******************************************************************************/
nativeNfcTag_doDisconnect(JNIEnv *,jobject)859 jboolean nativeNfcTag_doDisconnect(JNIEnv*, jobject) {
860   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
861   tNFA_STATUS nfaStat = NFA_STATUS_OK;
862 
863   NfcTag::getInstance().resetAllTransceiveTimeouts();
864 
865   if (NfcTag::getInstance().getActivationState() != NfcTag::Active) {
866     LOG(ERROR) << StringPrintf("%s: tag already deactivated", __func__);
867     goto TheEnd;
868   }
869 
870   nfaStat = NFA_Deactivate(FALSE);
871   if (nfaStat != NFA_STATUS_OK)
872     LOG(ERROR) << StringPrintf("%s: deactivate failed; error=0x%X", __func__,
873                                nfaStat);
874 
875 TheEnd:
876   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
877   return (nfaStat == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
878 }
879 
880 /*******************************************************************************
881 **
882 ** Function:        nativeNfcTag_doTransceiveStatus
883 **
884 ** Description:     Receive the completion status of transceive operation.
885 **                  status: operation status.
886 **                  buf: Contains tag's response.
887 **                  bufLen: Length of buffer.
888 **
889 ** Returns:         None
890 **
891 *******************************************************************************/
nativeNfcTag_doTransceiveStatus(tNFA_STATUS status,uint8_t * buf,uint32_t bufLen)892 void nativeNfcTag_doTransceiveStatus(tNFA_STATUS status, uint8_t* buf,
893                                      uint32_t bufLen) {
894   SyncEventGuard g(sTransceiveEvent);
895   DLOG_IF(INFO, nfc_debug_enabled)
896       << StringPrintf("%s: data len=%d", __func__, bufLen);
897 
898   if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
899     if (EXTNS_GetCallBackFlag() == FALSE) {
900       EXTNS_MfcCallBack(buf, bufLen);
901       return;
902     }
903   }
904 
905   if (!sWaitingForTransceive) {
906     LOG(ERROR) << StringPrintf("%s: drop data", __func__);
907     return;
908   }
909   sRxDataStatus = status;
910   if (sRxDataStatus == NFA_STATUS_OK || sRxDataStatus == NFC_STATUS_CONTINUE)
911     sRxDataBuffer.append(buf, bufLen);
912 
913   if (sRxDataStatus == NFA_STATUS_OK) sTransceiveEvent.notifyOne();
914 }
915 
nativeNfcTag_notifyRfTimeout()916 void nativeNfcTag_notifyRfTimeout() {
917   SyncEventGuard g(sTransceiveEvent);
918   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
919       "%s: waiting for transceive: %d", __func__, sWaitingForTransceive);
920   if (!sWaitingForTransceive) return;
921 
922   sTransceiveRfTimeout = true;
923 
924   sTransceiveEvent.notifyOne();
925 }
926 
927 /*******************************************************************************
928 **
929 ** Function:        nativeNfcTag_doTransceive
930 **
931 ** Description:     Send raw data to the tag; receive tag's response.
932 **                  e: JVM environment.
933 **                  o: Java object.
934 **                  raw: Not used.
935 **                  statusTargetLost: Whether tag responds or times out.
936 **
937 ** Returns:         Response from tag.
938 **
939 *******************************************************************************/
nativeNfcTag_doTransceive(JNIEnv * e,jobject o,jbyteArray data,jboolean raw,jintArray statusTargetLost)940 static jbyteArray nativeNfcTag_doTransceive(JNIEnv* e, jobject o,
941                                             jbyteArray data, jboolean raw,
942                                             jintArray statusTargetLost) {
943   int timeout =
944       NfcTag::getInstance().getTransceiveTimeout(sCurrentConnectedTargetType);
945   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
946       "%s: enter; raw=%u; timeout = %d", __func__, raw, timeout);
947 
948   bool waitOk = false;
949   bool isNack = false;
950   jint* targetLost = NULL;
951   tNFA_STATUS status;
952 
953   if (NfcTag::getInstance().getActivationState() != NfcTag::Active) {
954     if (statusTargetLost) {
955       targetLost = e->GetIntArrayElements(statusTargetLost, 0);
956       if (targetLost)
957         *targetLost = 1;  // causes NFC service to throw TagLostException
958       e->ReleaseIntArrayElements(statusTargetLost, targetLost, 0);
959     }
960     DLOG_IF(INFO, nfc_debug_enabled)
961         << StringPrintf("%s: tag not active", __func__);
962     return NULL;
963   }
964 
965   NfcTag& natTag = NfcTag::getInstance();
966 
967   // get input buffer and length from java call
968   ScopedByteArrayRO bytes(e, data);
969   uint8_t* buf = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(
970       &bytes[0]));  // TODO: API bug; NFA_SendRawFrame should take const*!
971   size_t bufLen = bytes.size();
972 
973   if (statusTargetLost) {
974     targetLost = e->GetIntArrayElements(statusTargetLost, 0);
975     if (targetLost) *targetLost = 0;  // success, tag is still present
976   }
977 
978   sSwitchBackTimer.kill();
979   ScopedLocalRef<jbyteArray> result(e, NULL);
980   do {
981     {
982       SyncEventGuard g(sTransceiveEvent);
983       sTransceiveRfTimeout = false;
984       sWaitingForTransceive = true;
985       sRxDataStatus = NFA_STATUS_OK;
986       sRxDataBuffer.clear();
987 
988       if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
989         status = EXTNS_MfcTransceive(buf, bufLen);
990       } else {
991         status = NFA_SendRawFrame(buf, bufLen,
992                                   NFA_DM_DEFAULT_PRESENCE_CHECK_START_DELAY);
993       }
994 
995       if (status != NFA_STATUS_OK) {
996         LOG(ERROR) << StringPrintf("%s: fail send; error=%d", __func__, status);
997         break;
998       }
999       waitOk = sTransceiveEvent.wait(timeout);
1000     }
1001 
1002     if (waitOk == false || sTransceiveRfTimeout)  // if timeout occurred
1003     {
1004       LOG(ERROR) << StringPrintf("%s: wait response timeout", __func__);
1005       if (targetLost)
1006         *targetLost = 1;  // causes NFC service to throw TagLostException
1007       break;
1008     }
1009 
1010     if (NfcTag::getInstance().getActivationState() != NfcTag::Active) {
1011       LOG(ERROR) << StringPrintf("%s: already deactivated", __func__);
1012       if (targetLost)
1013         *targetLost = 1;  // causes NFC service to throw TagLostException
1014       break;
1015     }
1016 
1017     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1018         "%s: response %zu bytes", __func__, sRxDataBuffer.size());
1019 
1020     if ((natTag.getProtocol() == NFA_PROTOCOL_T2T) &&
1021         natTag.isT2tNackResponse(sRxDataBuffer.data(), sRxDataBuffer.size())) {
1022       isNack = true;
1023     }
1024 
1025     if (sRxDataBuffer.size() > 0) {
1026       if (isNack) {
1027         // Some Mifare Ultralight C tags enter the HALT state after it
1028         // responds with a NACK.  Need to perform a "reconnect" operation
1029         // to wake it.
1030         DLOG_IF(INFO, nfc_debug_enabled)
1031             << StringPrintf("%s: try reconnect", __func__);
1032         nativeNfcTag_doReconnect(NULL, NULL);
1033         DLOG_IF(INFO, nfc_debug_enabled)
1034             << StringPrintf("%s: reconnect finish", __func__);
1035       } else if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) {
1036         uint32_t transDataLen = sRxDataBuffer.size();
1037         uint8_t* transData = (uint8_t*)sRxDataBuffer.data();
1038         bool doReconnect = false;
1039 
1040         if (legacy_mfc_reader) {
1041           doReconnect = (EXTNS_CheckMfcResponse(&transData, &transDataLen) ==
1042                          NFCSTATUS_FAILED) ? true : false;
1043         } else {
1044           doReconnect =
1045               ((transDataLen == 1) && (transData[0] != 0x00)) ? true : false;
1046         }
1047 
1048         if (doReconnect) {
1049           nativeNfcTag_doReconnect(e, o);
1050         } else {
1051           if (transDataLen != 0) {
1052             result.reset(e->NewByteArray(transDataLen));
1053             if (result.get() != NULL) {
1054               e->SetByteArrayRegion(result.get(), 0, transDataLen,
1055                                   (const jbyte*)transData);
1056             } else
1057               LOG(ERROR) << StringPrintf("%s: Failed to allocate java byte array",
1058                                        __func__);
1059           }
1060         }
1061       } else {
1062         // marshall data to java for return
1063         result.reset(e->NewByteArray(sRxDataBuffer.size()));
1064         if (result.get() != NULL) {
1065           e->SetByteArrayRegion(result.get(), 0, sRxDataBuffer.size(),
1066                                 (const jbyte*)sRxDataBuffer.data());
1067         } else
1068           LOG(ERROR) << StringPrintf("%s: Failed to allocate java byte array",
1069                                      __func__);
1070       }  // else a nack is treated as a transceive failure to the upper layers
1071 
1072       sRxDataBuffer.clear();
1073     }
1074   } while (0);
1075 
1076   sWaitingForTransceive = false;
1077   if (targetLost) e->ReleaseIntArrayElements(statusTargetLost, targetLost, 0);
1078 
1079   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
1080   return result.release();
1081 }
1082 
1083 /*******************************************************************************
1084 **
1085 ** Function:        nativeNfcTag_doGetNdefType
1086 **
1087 ** Description:     Retrieve the type of tag.
1088 **                  e: JVM environment.
1089 **                  o: Java object.
1090 **                  libnfcType: Type of tag represented by JNI.
1091 **                  javaType: Not used.
1092 **
1093 ** Returns:         Type of tag represented by NFC Service.
1094 **
1095 *******************************************************************************/
nativeNfcTag_doGetNdefType(JNIEnv *,jobject,jint libnfcType,jint javaType)1096 static jint nativeNfcTag_doGetNdefType(JNIEnv*, jobject, jint libnfcType,
1097                                        jint javaType) {
1098   DLOG_IF(INFO, nfc_debug_enabled)
1099       << StringPrintf("%s: enter; libnfc type=%d; java type=%d", __func__,
1100                       libnfcType, javaType);
1101   jint ndefType = NDEF_UNKNOWN_TYPE;
1102 
1103   // For NFA, libnfcType is mapped to the protocol value received
1104   // in the NFA_ACTIVATED_EVT and NFA_DISC_RESULT_EVT event.
1105   if (NFA_PROTOCOL_T1T == libnfcType) {
1106     ndefType = NDEF_TYPE1_TAG;
1107   } else if (NFA_PROTOCOL_T2T == libnfcType) {
1108     ndefType = NDEF_TYPE2_TAG;
1109   } else if (NFA_PROTOCOL_T3T == libnfcType) {
1110     ndefType = NDEF_TYPE3_TAG;
1111   } else if (NFA_PROTOCOL_ISO_DEP == libnfcType) {
1112     ndefType = NDEF_TYPE4_TAG;
1113   } else if (NFC_PROTOCOL_MIFARE == libnfcType) {
1114     ndefType = NDEF_MIFARE_CLASSIC_TAG;
1115   } else {
1116     /* NFA_PROTOCOL_T5T, NFA_PROTOCOL_INVALID and others */
1117     ndefType = NDEF_UNKNOWN_TYPE;
1118   }
1119   DLOG_IF(INFO, nfc_debug_enabled)
1120       << StringPrintf("%s: exit; ndef type=%d", __func__, ndefType);
1121   return ndefType;
1122 }
1123 
1124 /*******************************************************************************
1125 **
1126 ** Function:        nativeNfcTag_doCheckNdefResult
1127 **
1128 ** Description:     Receive the result of checking whether the tag contains a
1129 *NDEF
1130 **                  message.  Called by the NFA_NDEF_DETECT_EVT.
1131 **                  status: Status of the operation.
1132 **                  maxSize: Maximum size of NDEF message.
1133 **                  currentSize: Current size of NDEF message.
1134 **                  flags: Indicate various states.
1135 **
1136 ** Returns:         None
1137 **
1138 *******************************************************************************/
nativeNfcTag_doCheckNdefResult(tNFA_STATUS status,uint32_t maxSize,uint32_t currentSize,uint8_t flags)1139 void nativeNfcTag_doCheckNdefResult(tNFA_STATUS status, uint32_t maxSize,
1140                                     uint32_t currentSize, uint8_t flags) {
1141   // this function's flags parameter is defined using the following macros
1142   // in nfc/include/rw_api.h;
1143   //#define RW_NDEF_FL_READ_ONLY  0x01    /* Tag is read only              */
1144   //#define RW_NDEF_FL_FORMATED   0x02    /* Tag formated for NDEF         */
1145   //#define RW_NDEF_FL_SUPPORTED  0x04    /* NDEF supported by the tag     */
1146   //#define RW_NDEF_FL_UNKNOWN    0x08    /* Unable to find if tag is ndef
1147   // capable/formated/read only */ #define RW_NDEF_FL_FORMATABLE 0x10    /* Tag
1148   // supports format operation */
1149 
1150   if (!sCheckNdefWaitingForComplete) {
1151     LOG(ERROR) << StringPrintf("%s: not waiting", __func__);
1152     return;
1153   }
1154 
1155   if (flags & RW_NDEF_FL_READ_ONLY)
1156     DLOG_IF(INFO, nfc_debug_enabled)
1157         << StringPrintf("%s: flag read-only", __func__);
1158   if (flags & RW_NDEF_FL_FORMATED)
1159     DLOG_IF(INFO, nfc_debug_enabled)
1160         << StringPrintf("%s: flag formatted for ndef", __func__);
1161   if (flags & RW_NDEF_FL_SUPPORTED)
1162     DLOG_IF(INFO, nfc_debug_enabled)
1163         << StringPrintf("%s: flag ndef supported", __func__);
1164   if (flags & RW_NDEF_FL_UNKNOWN)
1165     DLOG_IF(INFO, nfc_debug_enabled)
1166         << StringPrintf("%s: flag all unknown", __func__);
1167   if (flags & RW_NDEF_FL_FORMATABLE)
1168     DLOG_IF(INFO, nfc_debug_enabled)
1169         << StringPrintf("%s: flag formattable", __func__);
1170 
1171   sCheckNdefWaitingForComplete = JNI_FALSE;
1172   sCheckNdefStatus = status;
1173   if (sCheckNdefStatus != NFA_STATUS_OK &&
1174       sCheckNdefStatus != NFA_STATUS_TIMEOUT)
1175     sCheckNdefStatus = NFA_STATUS_FAILED;
1176   sCheckNdefCapable = false;  // assume tag is NOT ndef capable
1177   if (sCheckNdefStatus == NFA_STATUS_OK) {
1178     // NDEF content is on the tag
1179     sCheckNdefMaxSize = maxSize;
1180     sCheckNdefCurrentSize = currentSize;
1181     sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY;
1182     sCheckNdefCapable = true;
1183   } else if (sCheckNdefStatus == NFA_STATUS_FAILED) {
1184     // no NDEF content on the tag
1185     sCheckNdefMaxSize = 0;
1186     sCheckNdefCurrentSize = 0;
1187     sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY;
1188     if ((flags & RW_NDEF_FL_UNKNOWN) == 0)  // if stack understands the tag
1189     {
1190       if (flags & RW_NDEF_FL_SUPPORTED)  // if tag is ndef capable
1191         sCheckNdefCapable = true;
1192     }
1193   } else {
1194     LOG(ERROR) << StringPrintf("%s: unknown status=0x%X", __func__, status);
1195     sCheckNdefMaxSize = 0;
1196     sCheckNdefCurrentSize = 0;
1197     sCheckNdefCardReadOnly = false;
1198   }
1199   sem_post(&sCheckNdefSem);
1200 }
1201 
1202 /*******************************************************************************
1203 **
1204 ** Function:        nativeNfcTag_doCheckNdef
1205 **
1206 ** Description:     Does the tag contain a NDEF message?
1207 **                  e: JVM environment.
1208 **                  o: Java object.
1209 **                  ndefInfo: NDEF info.
1210 **
1211 ** Returns:         Status code; 0 is success.
1212 **
1213 *******************************************************************************/
nativeNfcTag_doCheckNdef(JNIEnv * e,jobject o,jintArray ndefInfo)1214 static jint nativeNfcTag_doCheckNdef(JNIEnv* e, jobject o, jintArray ndefInfo) {
1215   tNFA_STATUS status = NFA_STATUS_FAILED;
1216   jint* ndef = NULL;
1217 
1218   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
1219 
1220   // special case for Kovio
1221   if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) {
1222     DLOG_IF(INFO, nfc_debug_enabled)
1223         << StringPrintf("%s: Kovio tag, no NDEF", __func__);
1224     ndef = e->GetIntArrayElements(ndefInfo, 0);
1225     ndef[0] = 0;
1226     ndef[1] = NDEF_MODE_READ_ONLY;
1227     e->ReleaseIntArrayElements(ndefInfo, ndef, 0);
1228     return NFA_STATUS_FAILED;
1229   } else if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) {
1230     nativeNfcTag_doReconnect(e, o);
1231   }
1232 
1233   /* Create the write semaphore */
1234   if (sem_init(&sCheckNdefSem, 0, 0) == -1) {
1235     LOG(ERROR) << StringPrintf(
1236         "%s: Check NDEF semaphore creation failed (errno=0x%08x)", __func__,
1237         errno);
1238     return JNI_FALSE;
1239   }
1240 
1241   if (NfcTag::getInstance().getActivationState() != NfcTag::Active) {
1242     LOG(ERROR) << StringPrintf("%s: tag already deactivated", __func__);
1243     goto TheEnd;
1244   }
1245 
1246   DLOG_IF(INFO, nfc_debug_enabled)
1247       << StringPrintf("%s: try NFA_RwDetectNDef", __func__);
1248   sCheckNdefWaitingForComplete = JNI_TRUE;
1249 
1250   if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
1251     status = EXTNS_MfcCheckNDef();
1252   } else {
1253     status = NFA_RwDetectNDef();
1254   }
1255 
1256   if (status != NFA_STATUS_OK) {
1257     LOG(ERROR) << StringPrintf("%s: NFA_RwDetectNDef failed, status = 0x%X",
1258                                __func__, status);
1259     goto TheEnd;
1260   }
1261 
1262   /* Wait for check NDEF completion status */
1263   if (sem_wait(&sCheckNdefSem)) {
1264     LOG(ERROR) << StringPrintf(
1265         "%s: Failed to wait for check NDEF semaphore (errno=0x%08x)", __func__,
1266         errno);
1267     goto TheEnd;
1268   }
1269 
1270   if (sCheckNdefStatus == NFA_STATUS_OK) {
1271     // stack found a NDEF message on the tag
1272     ndef = e->GetIntArrayElements(ndefInfo, 0);
1273     if (NfcTag::getInstance().getProtocol() == NFA_PROTOCOL_T1T)
1274       ndef[0] = NfcTag::getInstance().getT1tMaxMessageSize();
1275     else
1276       ndef[0] = sCheckNdefMaxSize;
1277     if (sCheckNdefCardReadOnly)
1278       ndef[1] = NDEF_MODE_READ_ONLY;
1279     else
1280       ndef[1] = NDEF_MODE_READ_WRITE;
1281     e->ReleaseIntArrayElements(ndefInfo, ndef, 0);
1282     status = NFA_STATUS_OK;
1283   } else if (sCheckNdefStatus == NFA_STATUS_FAILED) {
1284     // stack did not find a NDEF message on the tag;
1285     ndef = e->GetIntArrayElements(ndefInfo, 0);
1286     if (NfcTag::getInstance().getProtocol() == NFA_PROTOCOL_T1T)
1287       ndef[0] = NfcTag::getInstance().getT1tMaxMessageSize();
1288     else
1289       ndef[0] = sCheckNdefMaxSize;
1290     if (sCheckNdefCardReadOnly)
1291       ndef[1] = NDEF_MODE_READ_ONLY;
1292     else
1293       ndef[1] = NDEF_MODE_READ_WRITE;
1294     e->ReleaseIntArrayElements(ndefInfo, ndef, 0);
1295     status = NFA_STATUS_FAILED;
1296   } else {
1297     DLOG_IF(INFO, nfc_debug_enabled)
1298         << StringPrintf("%s: unknown status 0x%X", __func__, sCheckNdefStatus);
1299     status = sCheckNdefStatus;
1300   }
1301 
1302   /* Reconnect Mifare Classic Tag for furture use */
1303   if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) {
1304     nativeNfcTag_doReconnect(e, o);
1305   }
1306 
1307 TheEnd:
1308   /* Destroy semaphore */
1309   if (sem_destroy(&sCheckNdefSem)) {
1310     LOG(ERROR) << StringPrintf(
1311         "%s: Failed to destroy check NDEF semaphore (errno=0x%08x)", __func__,
1312         errno);
1313   }
1314   sCheckNdefWaitingForComplete = JNI_FALSE;
1315   DLOG_IF(INFO, nfc_debug_enabled)
1316       << StringPrintf("%s: exit; status=0x%X", __func__, status);
1317   return status;
1318 }
1319 
1320 /*******************************************************************************
1321 **
1322 ** Function:        nativeNfcTag_resetPresenceCheck
1323 **
1324 ** Description:     Reset variables related to presence-check.
1325 **
1326 ** Returns:         None
1327 **
1328 *******************************************************************************/
nativeNfcTag_resetPresenceCheck()1329 void nativeNfcTag_resetPresenceCheck() { sIsTagPresent = true; }
1330 
1331 /*******************************************************************************
1332 **
1333 ** Function:        nativeNfcTag_doPresenceCheckResult
1334 **
1335 ** Description:     Receive the result of presence-check.
1336 **                  status: Result of presence-check.
1337 **
1338 ** Returns:         None
1339 **
1340 *******************************************************************************/
nativeNfcTag_doPresenceCheckResult(tNFA_STATUS status)1341 void nativeNfcTag_doPresenceCheckResult(tNFA_STATUS status) {
1342   SyncEventGuard guard(sPresenceCheckEvent);
1343   sIsTagPresent = status == NFA_STATUS_OK;
1344   sPresenceCheckEvent.notifyOne();
1345 }
1346 
1347 /*******************************************************************************
1348 **
1349 ** Function:        nativeNfcTag_doPresenceCheck
1350 **
1351 ** Description:     Check if the tag is in the RF field.
1352 **                  e: JVM environment.
1353 **                  o: Java object.
1354 **
1355 ** Returns:         True if tag is in RF field.
1356 **
1357 *******************************************************************************/
nativeNfcTag_doPresenceCheck(JNIEnv *,jobject)1358 static jboolean nativeNfcTag_doPresenceCheck(JNIEnv*, jobject) {
1359   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1360   tNFA_STATUS status = NFA_STATUS_OK;
1361   jboolean isPresent = JNI_FALSE;
1362 
1363   // Special case for Kovio.  The deactivation would have already occurred
1364   // but was ignored so that normal tag opertions could complete.  Now we
1365   // want to process as if the deactivate just happened.
1366   if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) {
1367     DLOG_IF(INFO, nfc_debug_enabled)
1368         << StringPrintf("%s: Kovio, force deactivate handling", __func__);
1369     tNFA_DEACTIVATED deactivated = {NFA_DEACTIVATE_TYPE_IDLE};
1370     {
1371       SyncEventGuard g(gDeactivatedEvent);
1372       gActivated = false;  // guard this variable from multi-threaded access
1373       gDeactivatedEvent.notifyOne();
1374     }
1375 
1376     NfcTag::getInstance().setDeactivationState(deactivated);
1377     nativeNfcTag_resetPresenceCheck();
1378     NfcTag::getInstance().connectionEventHandler(NFA_DEACTIVATED_EVT, NULL);
1379     nativeNfcTag_abortWaits();
1380     NfcTag::getInstance().abort();
1381 
1382     return JNI_FALSE;
1383   }
1384 
1385   if (nfcManager_isNfcActive() == false) {
1386     DLOG_IF(INFO, nfc_debug_enabled)
1387         << StringPrintf("%s: NFC is no longer active.", __func__);
1388     return JNI_FALSE;
1389   }
1390 
1391   if (!sRfInterfaceMutex.tryLock()) {
1392     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1393         "%s: tag is being reSelected assume it is present", __func__);
1394     return JNI_TRUE;
1395   }
1396 
1397   sRfInterfaceMutex.unlock();
1398 
1399   if (NfcTag::getInstance().isActivated() == false) {
1400     DLOG_IF(INFO, nfc_debug_enabled)
1401         << StringPrintf("%s: tag already deactivated", __func__);
1402     return JNI_FALSE;
1403   }
1404   if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
1405     status = EXTNS_MfcPresenceCheck();
1406     if (status == NFCSTATUS_SUCCESS) {
1407       return (NFCSTATUS_SUCCESS == EXTNS_GetPresenceCheckStatus()) ? JNI_TRUE
1408                                                                    : JNI_FALSE;
1409     }
1410   }
1411 
1412   {
1413     SyncEventGuard guard(sPresenceCheckEvent);
1414     status =
1415         NFA_RwPresenceCheck(NfcTag::getInstance().getPresenceCheckAlgorithm());
1416     if (status == NFA_STATUS_OK) {
1417       sPresenceCheckEvent.wait();
1418       isPresent = sIsTagPresent ? JNI_TRUE : JNI_FALSE;
1419     }
1420   }
1421 
1422   if (isPresent == JNI_FALSE)
1423     DLOG_IF(INFO, nfc_debug_enabled)
1424         << StringPrintf("%s: tag absent", __func__);
1425   return isPresent;
1426 }
1427 
1428 /*******************************************************************************
1429 **
1430 ** Function:        nativeNfcTag_doIsNdefFormatable
1431 **
1432 ** Description:     Can tag be formatted to store NDEF message?
1433 **                  e: JVM environment.
1434 **                  o: Java object.
1435 **                  libNfcType: Type of tag.
1436 **                  uidBytes: Tag's unique ID.
1437 **                  pollBytes: Data from activation.
1438 **                  actBytes: Data from activation.
1439 **
1440 ** Returns:         True if formattable.
1441 **
1442 *******************************************************************************/
nativeNfcTag_doIsNdefFormatable(JNIEnv * e,jobject o,jint,jbyteArray,jbyteArray,jbyteArray)1443 static jboolean nativeNfcTag_doIsNdefFormatable(JNIEnv* e, jobject o,
1444                                                 jint /*libNfcType*/, jbyteArray,
1445                                                 jbyteArray, jbyteArray) {
1446   jboolean isFormattable = JNI_FALSE;
1447   tNFC_PROTOCOL protocol = NfcTag::getInstance().getProtocol();
1448   if (NFA_PROTOCOL_T1T == protocol || NFA_PROTOCOL_T5T == protocol ||
1449       NFC_PROTOCOL_MIFARE == protocol) {
1450     isFormattable = JNI_TRUE;
1451   } else if (NFA_PROTOCOL_T3T == protocol) {
1452     isFormattable = NfcTag::getInstance().isFelicaLite() ? JNI_TRUE : JNI_FALSE;
1453   } else if (NFA_PROTOCOL_T2T == protocol) {
1454     isFormattable = (NfcTag::getInstance().isMifareUltralight() |
1455                      NfcTag::getInstance().isInfineonMyDMove() |
1456                      NfcTag::getInstance().isKovioType2Tag())
1457                         ? JNI_TRUE
1458                         : JNI_FALSE;
1459   } else if (NFA_PROTOCOL_ISO_DEP == protocol) {
1460     /**
1461      * Determines whether this is a formatable IsoDep tag - currectly only NXP
1462      * DESFire is supported.
1463      */
1464     uint8_t cmd[] = {0x90, 0x60, 0x00, 0x00, 0x00};
1465 
1466     if (NfcTag::getInstance().isMifareDESFire()) {
1467       /* Identifies as DESfire, use get version cmd to be sure */
1468       jbyteArray versionCmd = e->NewByteArray(5);
1469       e->SetByteArrayRegion(versionCmd, 0, 5, (jbyte*)cmd);
1470       jbyteArray respBytes =
1471           nativeNfcTag_doTransceive(e, o, versionCmd, JNI_TRUE, NULL);
1472       if (respBytes != NULL) {
1473         // Check whether the response matches a typical DESfire
1474         // response.
1475         // libNFC even does more advanced checking than we do
1476         // here, and will only format DESfire's with a certain
1477         // major/minor sw version and NXP as a manufacturer.
1478         // We don't want to do such checking here, to avoid
1479         // having to change code in multiple places.
1480         // A succesful (wrapped) DESFire getVersion command returns
1481         // 9 bytes, with byte 7 0x91 and byte 8 having status
1482         // code 0xAF (these values are fixed and well-known).
1483         int respLength = e->GetArrayLength(respBytes);
1484         uint8_t* resp = (uint8_t*)e->GetByteArrayElements(respBytes, NULL);
1485         if (respLength == 9 && resp[7] == 0x91 && resp[8] == 0xAF) {
1486           isFormattable = JNI_TRUE;
1487         }
1488         e->ReleaseByteArrayElements(respBytes, (jbyte*)resp, JNI_ABORT);
1489       }
1490     }
1491   }
1492 
1493   DLOG_IF(INFO, nfc_debug_enabled)
1494       << StringPrintf("%s: is formattable=%u", __func__, isFormattable);
1495   return isFormattable;
1496 }
1497 
1498 /*******************************************************************************
1499 **
1500 ** Function:        nativeNfcTag_doIsIsoDepNdefFormatable
1501 **
1502 ** Description:     Is ISO-DEP tag formattable?
1503 **                  e: JVM environment.
1504 **                  o: Java object.
1505 **                  pollBytes: Data from activation.
1506 **                  actBytes: Data from activation.
1507 **
1508 ** Returns:         True if formattable.
1509 **
1510 *******************************************************************************/
nativeNfcTag_doIsIsoDepNdefFormatable(JNIEnv * e,jobject o,jbyteArray pollBytes,jbyteArray actBytes)1511 static jboolean nativeNfcTag_doIsIsoDepNdefFormatable(JNIEnv* e, jobject o,
1512                                                       jbyteArray pollBytes,
1513                                                       jbyteArray actBytes) {
1514   uint8_t uidFake[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
1515   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1516   jbyteArray uidArray = e->NewByteArray(8);
1517   e->SetByteArrayRegion(uidArray, 0, 8, (jbyte*)uidFake);
1518   return nativeNfcTag_doIsNdefFormatable(e, o, 0, uidArray, pollBytes,
1519                                          actBytes);
1520 }
1521 
1522 /*******************************************************************************
1523 **
1524 ** Function:        nativeNfcTag_makeMifareNdefFormat
1525 **
1526 ** Description:     Format a mifare classic tag so it can store NDEF message.
1527 **                  e: JVM environment.
1528 **                  o: Java object.
1529 **                  key: Key to acces tag.
1530 **                  keySize: size of Key.
1531 **
1532 ** Returns:         True if ok.
1533 **
1534 *******************************************************************************/
nativeNfcTag_makeMifareNdefFormat(JNIEnv * e,jobject o,uint8_t * key,uint32_t keySize)1535 static jboolean nativeNfcTag_makeMifareNdefFormat(JNIEnv* e, jobject o,
1536                                                   uint8_t* key,
1537                                                   uint32_t keySize) {
1538   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
1539   tNFA_STATUS status = NFA_STATUS_OK;
1540 
1541   status = nativeNfcTag_doReconnect(e, o);
1542   if (status != NFA_STATUS_OK) {
1543     DLOG_IF(INFO, nfc_debug_enabled)
1544         << StringPrintf("%s: reconnect error, status=%u", __func__, status);
1545     return JNI_FALSE;
1546   }
1547 
1548   sem_init(&sFormatSem, 0, 0);
1549   sFormatOk = false;
1550 
1551   status = EXTNS_MfcFormatTag(key, keySize);
1552 
1553   if (status == NFA_STATUS_OK) {
1554     DLOG_IF(INFO, nfc_debug_enabled)
1555         << StringPrintf("%s: wait for completion", __func__);
1556     sem_wait(&sFormatSem);
1557     status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED;
1558   } else {
1559     LOG(ERROR) << StringPrintf("%s: error status=%u", __func__, status);
1560   }
1561 
1562   sem_destroy(&sFormatSem);
1563   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
1564   return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
1565 }
1566 
1567 /*******************************************************************************
1568 **
1569 ** Function:        nativeNfcTag_doNdefFormat
1570 **
1571 ** Description:     Format a tag so it can store NDEF message.
1572 **                  e: JVM environment.
1573 **                  o: Java object.
1574 **                  key: Not used.
1575 **
1576 ** Returns:         True if ok.
1577 **
1578 *******************************************************************************/
nativeNfcTag_doNdefFormat(JNIEnv * e,jobject o,jbyteArray)1579 static jboolean nativeNfcTag_doNdefFormat(JNIEnv* e, jobject o, jbyteArray) {
1580   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
1581   tNFA_STATUS status = NFA_STATUS_OK;
1582 
1583   // Do not try to format if tag is already deactivated.
1584   if (NfcTag::getInstance().isActivated() == false) {
1585     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1586         "%s: tag already deactivated(no need to format)", __func__);
1587     return JNI_FALSE;
1588   }
1589 
1590   if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
1591     static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1592     static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7};
1593     jboolean result;
1594 
1595     result =
1596         nativeNfcTag_makeMifareNdefFormat(e, o, mfc_key1, sizeof(mfc_key1));
1597     if (result == JNI_FALSE) {
1598       result =
1599           nativeNfcTag_makeMifareNdefFormat(e, o, mfc_key2, sizeof(mfc_key2));
1600     }
1601     return result;
1602   }
1603 
1604   sem_init(&sFormatSem, 0, 0);
1605   sFormatOk = false;
1606   status = NFA_RwFormatTag();
1607   if (status == NFA_STATUS_OK) {
1608     DLOG_IF(INFO, nfc_debug_enabled)
1609         << StringPrintf("%s: wait for completion", __func__);
1610     sem_wait(&sFormatSem);
1611     status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED;
1612   } else
1613     LOG(ERROR) << StringPrintf("%s: error status=%u", __func__, status);
1614   sem_destroy(&sFormatSem);
1615 
1616   if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_ISO_DEP) {
1617     int retCode = NFCSTATUS_SUCCESS;
1618     retCode = nativeNfcTag_doReconnect(e, o);
1619   }
1620   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
1621   return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
1622 }
1623 
1624 /*******************************************************************************
1625 **
1626 ** Function:        nativeNfcTag_doMakeReadonlyResult
1627 **
1628 ** Description:     Receive the result of making a tag read-only. Called by the
1629 **                  NFA_SET_TAG_RO_EVT.
1630 **                  status: Status of the operation.
1631 **
1632 ** Returns:         None
1633 **
1634 *******************************************************************************/
nativeNfcTag_doMakeReadonlyResult(tNFA_STATUS status)1635 void nativeNfcTag_doMakeReadonlyResult(tNFA_STATUS status) {
1636   if (sMakeReadonlyWaitingForComplete != JNI_FALSE) {
1637     sMakeReadonlyWaitingForComplete = JNI_FALSE;
1638     sMakeReadonlyStatus = status;
1639 
1640     sem_post(&sMakeReadonlySem);
1641   }
1642 }
1643 
1644 /*******************************************************************************
1645 **
1646 ** Function:        nativeNfcTag_makeMifareReadonly
1647 **
1648 ** Description:     Make the mifare classic tag read-only.
1649 **                  e: JVM environment.
1650 **                  o: Java object.
1651 **                  key: Key to access the tag.
1652 **                  keySize: size of Key.
1653 **
1654 ** Returns:         True if ok.
1655 **
1656 *******************************************************************************/
nativeNfcTag_makeMifareReadonly(JNIEnv * e,jobject o,uint8_t * key,int32_t keySize)1657 static jboolean nativeNfcTag_makeMifareReadonly(JNIEnv* e, jobject o,
1658                                                 uint8_t* key, int32_t keySize) {
1659   jboolean result = JNI_FALSE;
1660   tNFA_STATUS status = NFA_STATUS_OK;
1661 
1662   sMakeReadonlyStatus = NFA_STATUS_FAILED;
1663 
1664   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1665 
1666   /* Create the make_readonly semaphore */
1667   if (sem_init(&sMakeReadonlySem, 0, 0) == -1) {
1668     LOG(ERROR) << StringPrintf(
1669         "%s: Make readonly semaphore creation failed (errno=0x%08x)", __func__,
1670         errno);
1671     return JNI_FALSE;
1672   }
1673 
1674   sMakeReadonlyWaitingForComplete = JNI_TRUE;
1675 
1676   status = nativeNfcTag_doReconnect(e, o);
1677   if (status != NFA_STATUS_OK) {
1678     goto TheEnd;
1679   }
1680 
1681   status = EXTNS_MfcSetReadOnly(key, keySize);
1682   if (status != NFA_STATUS_OK) {
1683     goto TheEnd;
1684   }
1685   sem_wait(&sMakeReadonlySem);
1686 
1687   if (sMakeReadonlyStatus == NFA_STATUS_OK) {
1688     result = JNI_TRUE;
1689   }
1690 
1691 TheEnd:
1692   /* Destroy semaphore */
1693   if (sem_destroy(&sMakeReadonlySem)) {
1694     LOG(ERROR) << StringPrintf(
1695         "%s: Failed to destroy read_only semaphore (errno=0x%08x)", __func__,
1696         errno);
1697   }
1698   sMakeReadonlyWaitingForComplete = JNI_FALSE;
1699   return result;
1700 }
1701 
1702 /*******************************************************************************
1703 **
1704 ** Function:        nativeNfcTag_doMakeReadonly
1705 **
1706 ** Description:     Make the tag read-only.
1707 **                  e: JVM environment.
1708 **                  o: Java object.
1709 **                  key: Key to access the tag.
1710 **
1711 ** Returns:         True if ok.
1712 **
1713 *******************************************************************************/
nativeNfcTag_doMakeReadonly(JNIEnv * e,jobject o,jbyteArray)1714 static jboolean nativeNfcTag_doMakeReadonly(JNIEnv* e, jobject o, jbyteArray) {
1715   jboolean result = JNI_FALSE;
1716   tNFA_STATUS status;
1717 
1718   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1719 
1720   if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
1721     static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1722     static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7};
1723     result = nativeNfcTag_makeMifareReadonly(e, o, mfc_key1, sizeof(mfc_key1));
1724     if (result == JNI_FALSE) {
1725       result =
1726           nativeNfcTag_makeMifareReadonly(e, o, mfc_key2, sizeof(mfc_key2));
1727     }
1728     return result;
1729   }
1730 
1731   /* Create the make_readonly semaphore */
1732   if (sem_init(&sMakeReadonlySem, 0, 0) == -1) {
1733     LOG(ERROR) << StringPrintf(
1734         "%s: Make readonly semaphore creation failed (errno=0x%08x)", __func__,
1735         errno);
1736     return JNI_FALSE;
1737   }
1738 
1739   sMakeReadonlyWaitingForComplete = JNI_TRUE;
1740 
1741   // Hard-lock the tag (cannot be reverted)
1742   status = NFA_RwSetTagReadOnly(TRUE);
1743   if (status == NFA_STATUS_REJECTED) {
1744     status = NFA_RwSetTagReadOnly(FALSE);  // try soft lock
1745     if (status != NFA_STATUS_OK) {
1746       LOG(ERROR) << StringPrintf("%s: fail soft lock, status=%d", __func__,
1747                                  status);
1748       goto TheEnd;
1749     }
1750   } else if (status != NFA_STATUS_OK) {
1751     LOG(ERROR) << StringPrintf("%s: fail hard lock, status=%d", __func__,
1752                                status);
1753     goto TheEnd;
1754   }
1755 
1756   /* Wait for check NDEF completion status */
1757   if (sem_wait(&sMakeReadonlySem)) {
1758     LOG(ERROR) << StringPrintf(
1759         "%s: Failed to wait for make_readonly semaphore (errno=0x%08x)",
1760         __func__, errno);
1761     goto TheEnd;
1762   }
1763 
1764   if (sMakeReadonlyStatus == NFA_STATUS_OK) {
1765     result = JNI_TRUE;
1766   }
1767 
1768 TheEnd:
1769   /* Destroy semaphore */
1770   if (sem_destroy(&sMakeReadonlySem)) {
1771     LOG(ERROR) << StringPrintf(
1772         "%s: Failed to destroy read_only semaphore (errno=0x%08x)", __func__,
1773         errno);
1774   }
1775   sMakeReadonlyWaitingForComplete = JNI_FALSE;
1776   return result;
1777 }
1778 
1779 /*******************************************************************************
1780 **
1781 ** Function:        nativeNfcTag_registerNdefTypeHandler
1782 **
1783 ** Description:     Register a callback to receive NDEF message from the tag
1784 **                  from the NFA_NDEF_DATA_EVT.
1785 **
1786 ** Returns:         None
1787 **
1788 *******************************************************************************/
1789 // register a callback to receive NDEF message from the tag
1790 // from the NFA_NDEF_DATA_EVT;
nativeNfcTag_registerNdefTypeHandler()1791 void nativeNfcTag_registerNdefTypeHandler() {
1792   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1793   sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
1794   NFA_RegisterNDefTypeHandler(TRUE, NFA_TNF_DEFAULT, (uint8_t*)"", 0,
1795                               ndefHandlerCallback);
1796   if (legacy_mfc_reader) {
1797     EXTNS_MfcRegisterNDefTypeHandler(ndefHandlerCallback);
1798   }
1799 }
1800 
1801 /*******************************************************************************
1802 **
1803 ** Function:        nativeNfcTag_deregisterNdefTypeHandler
1804 **
1805 ** Description:     No longer need to receive NDEF message from the tag.
1806 **
1807 ** Returns:         None
1808 **
1809 *******************************************************************************/
nativeNfcTag_deregisterNdefTypeHandler()1810 void nativeNfcTag_deregisterNdefTypeHandler() {
1811   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1812   NFA_DeregisterNDefTypeHandler(sNdefTypeHandlerHandle);
1813   sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
1814 }
1815 
1816 /*******************************************************************************
1817 **
1818 ** Function:        nativeNfcTag_acquireRfInterfaceMutexLock
1819 **
1820 ** Description:     acquire sRfInterfaceMutex
1821 **
1822 ** Returns:         None
1823 **
1824 *******************************************************************************/
nativeNfcTag_acquireRfInterfaceMutexLock()1825 void nativeNfcTag_acquireRfInterfaceMutexLock() {
1826   DLOG_IF(INFO, nfc_debug_enabled)
1827       << StringPrintf("%s: try to acquire lock", __func__);
1828   sRfInterfaceMutex.lock();
1829   DLOG_IF(INFO, nfc_debug_enabled)
1830       << StringPrintf("%s: sRfInterfaceMutex lock", __func__);
1831 }
1832 
1833 /*******************************************************************************
1834 **
1835 ** Function:       nativeNfcTag_releaseRfInterfaceMutexLock
1836 **
1837 ** Description:    release the sRfInterfaceMutex
1838 **
1839 ** Returns:        None
1840 **
1841 *******************************************************************************/
nativeNfcTag_releaseRfInterfaceMutexLock()1842 void nativeNfcTag_releaseRfInterfaceMutexLock() {
1843   sRfInterfaceMutex.unlock();
1844   DLOG_IF(INFO, nfc_debug_enabled)
1845       << StringPrintf("%s: sRfInterfaceMutex unlock", __func__);
1846 }
1847 
1848 /*****************************************************************************
1849 **
1850 ** JNI functions for Android 4.0.3
1851 **
1852 *****************************************************************************/
1853 static JNINativeMethod gMethods[] = {
1854     {"doConnect", "(I)I", (void*)nativeNfcTag_doConnect},
1855     {"doDisconnect", "()Z", (void*)nativeNfcTag_doDisconnect},
1856     {"doReconnect", "()I", (void*)nativeNfcTag_doReconnect},
1857     {"doHandleReconnect", "(I)I", (void*)nativeNfcTag_doHandleReconnect},
1858     {"doTransceive", "([BZ[I)[B", (void*)nativeNfcTag_doTransceive},
1859     {"doGetNdefType", "(II)I", (void*)nativeNfcTag_doGetNdefType},
1860     {"doCheckNdef", "([I)I", (void*)nativeNfcTag_doCheckNdef},
1861     {"doRead", "()[B", (void*)nativeNfcTag_doRead},
1862     {"doWrite", "([B)Z", (void*)nativeNfcTag_doWrite},
1863     {"doPresenceCheck", "()Z", (void*)nativeNfcTag_doPresenceCheck},
1864     {"doIsIsoDepNdefFormatable", "([B[B)Z",
1865      (void*)nativeNfcTag_doIsIsoDepNdefFormatable},
1866     {"doNdefFormat", "([B)Z", (void*)nativeNfcTag_doNdefFormat},
1867     {"doMakeReadonly", "([B)Z", (void*)nativeNfcTag_doMakeReadonly},
1868 };
1869 
1870 /*******************************************************************************
1871 **
1872 ** Function:        register_com_android_nfc_NativeNfcTag
1873 **
1874 ** Description:     Regisgter JNI functions with Java Virtual Machine.
1875 **                  e: Environment of JVM.
1876 **
1877 ** Returns:         Status of registration.
1878 **
1879 *******************************************************************************/
register_com_android_nfc_NativeNfcTag(JNIEnv * e)1880 int register_com_android_nfc_NativeNfcTag(JNIEnv* e) {
1881   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1882   return jniRegisterNativeMethods(e, gNativeNfcTagClassName, gMethods,
1883                                   NELEM(gMethods));
1884 }
1885 
1886 } /* namespace android */
1887