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