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