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