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