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