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