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