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