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