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