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