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
34 #include "ndef_utils.h"
35 #include "nfa_api.h"
36 #include "nfa_rw_api.h"
37 #include "nfc_brcm_defs.h"
38 #include "phNxpExtns.h"
39 #include "rw_api.h"
40
41 using android::base::StringPrintf;
42
43 namespace android {
44 extern nfc_jni_native_data* getNative(JNIEnv* e, jobject o);
45 extern bool nfcManager_isNfcActive();
46 } // namespace android
47
48 extern bool gActivated;
49 extern SyncEvent gDeactivatedEvent;
50 extern bool nfc_debug_enabled;
51 extern bool legacy_mfc_reader;
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 && legacy_mfc_reader) {
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 && legacy_mfc_reader) {
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 && legacy_mfc_reader) {
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 && legacy_mfc_reader) {
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 && legacy_mfc_reader) {
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 && legacy_mfc_reader) {
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 && legacy_mfc_reader) {
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 && legacy_mfc_reader) {
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 bool doReconnect = false;
974
975 if (legacy_mfc_reader) {
976 doReconnect = (EXTNS_CheckMfcResponse(&transData, &transDataLen) ==
977 NFCSTATUS_FAILED) ? true : false;
978 } else {
979 doReconnect =
980 ((transDataLen == 1) && (transData[0] != 0x00)) ? true : false;
981 }
982
983 if (doReconnect) {
984 nativeNfcTag_doReconnect(e, o);
985 } else {
986 if (transDataLen != 0) {
987 result.reset(e->NewByteArray(transDataLen));
988 if (result.get() != NULL) {
989 e->SetByteArrayRegion(result.get(), 0, transDataLen,
990 (const jbyte*)transData);
991 } else
992 LOG(ERROR) << StringPrintf("%s: Failed to allocate java byte array",
993 __func__);
994 }
995 }
996 } else {
997 // marshall data to java for return
998 result.reset(e->NewByteArray(sRxDataBuffer.size()));
999 if (result.get() != NULL) {
1000 e->SetByteArrayRegion(result.get(), 0, sRxDataBuffer.size(),
1001 (const jbyte*)sRxDataBuffer.data());
1002 } else
1003 LOG(ERROR) << StringPrintf("%s: Failed to allocate java byte array",
1004 __func__);
1005 } // else a nack is treated as a transceive failure to the upper layers
1006
1007 sRxDataBuffer.clear();
1008 }
1009 } while (0);
1010
1011 sWaitingForTransceive = false;
1012 if (targetLost) e->ReleaseIntArrayElements(statusTargetLost, targetLost, 0);
1013
1014 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
1015 return result.release();
1016 }
1017
1018 /*******************************************************************************
1019 **
1020 ** Function: nativeNfcTag_doGetNdefType
1021 **
1022 ** Description: Retrieve the type of tag.
1023 ** e: JVM environment.
1024 ** o: Java object.
1025 ** libnfcType: Type of tag represented by JNI.
1026 ** javaType: Not used.
1027 **
1028 ** Returns: Type of tag represented by NFC Service.
1029 **
1030 *******************************************************************************/
nativeNfcTag_doGetNdefType(JNIEnv *,jobject,jint libnfcType,jint javaType)1031 static jint nativeNfcTag_doGetNdefType(JNIEnv*, jobject, jint libnfcType,
1032 jint javaType) {
1033 DLOG_IF(INFO, nfc_debug_enabled)
1034 << StringPrintf("%s: enter; libnfc type=%d; java type=%d", __func__,
1035 libnfcType, javaType);
1036 jint ndefType = NDEF_UNKNOWN_TYPE;
1037
1038 // For NFA, libnfcType is mapped to the protocol value received
1039 // in the NFA_ACTIVATED_EVT and NFA_DISC_RESULT_EVT event.
1040 if (NFA_PROTOCOL_T1T == libnfcType) {
1041 ndefType = NDEF_TYPE1_TAG;
1042 } else if (NFA_PROTOCOL_T2T == libnfcType) {
1043 ndefType = NDEF_TYPE2_TAG;
1044 } else if (NFA_PROTOCOL_T3T == libnfcType) {
1045 ndefType = NDEF_TYPE3_TAG;
1046 } else if (NFA_PROTOCOL_ISO_DEP == libnfcType) {
1047 ndefType = NDEF_TYPE4_TAG;
1048 } else if (NFC_PROTOCOL_MIFARE == libnfcType) {
1049 ndefType = NDEF_MIFARE_CLASSIC_TAG;
1050 } else {
1051 /* NFA_PROTOCOL_T5T, NFA_PROTOCOL_INVALID and others */
1052 ndefType = NDEF_UNKNOWN_TYPE;
1053 }
1054 DLOG_IF(INFO, nfc_debug_enabled)
1055 << StringPrintf("%s: exit; ndef type=%d", __func__, ndefType);
1056 return ndefType;
1057 }
1058
1059 /*******************************************************************************
1060 **
1061 ** Function: nativeNfcTag_doCheckNdefResult
1062 **
1063 ** Description: Receive the result of checking whether the tag contains a
1064 *NDEF
1065 ** message. Called by the NFA_NDEF_DETECT_EVT.
1066 ** status: Status of the operation.
1067 ** maxSize: Maximum size of NDEF message.
1068 ** currentSize: Current size of NDEF message.
1069 ** flags: Indicate various states.
1070 **
1071 ** Returns: None
1072 **
1073 *******************************************************************************/
nativeNfcTag_doCheckNdefResult(tNFA_STATUS status,uint32_t maxSize,uint32_t currentSize,uint8_t flags)1074 void nativeNfcTag_doCheckNdefResult(tNFA_STATUS status, uint32_t maxSize,
1075 uint32_t currentSize, uint8_t flags) {
1076 // this function's flags parameter is defined using the following macros
1077 // in nfc/include/rw_api.h;
1078 //#define RW_NDEF_FL_READ_ONLY 0x01 /* Tag is read only */
1079 //#define RW_NDEF_FL_FORMATED 0x02 /* Tag formated for NDEF */
1080 //#define RW_NDEF_FL_SUPPORTED 0x04 /* NDEF supported by the tag */
1081 //#define RW_NDEF_FL_UNKNOWN 0x08 /* Unable to find if tag is ndef
1082 // capable/formated/read only */ #define RW_NDEF_FL_FORMATABLE 0x10 /* Tag
1083 // supports format operation */
1084
1085 if (!sCheckNdefWaitingForComplete) {
1086 LOG(ERROR) << StringPrintf("%s: not waiting", __func__);
1087 return;
1088 }
1089
1090 if (flags & RW_NDEF_FL_READ_ONLY)
1091 DLOG_IF(INFO, nfc_debug_enabled)
1092 << StringPrintf("%s: flag read-only", __func__);
1093 if (flags & RW_NDEF_FL_FORMATED)
1094 DLOG_IF(INFO, nfc_debug_enabled)
1095 << StringPrintf("%s: flag formatted for ndef", __func__);
1096 if (flags & RW_NDEF_FL_SUPPORTED)
1097 DLOG_IF(INFO, nfc_debug_enabled)
1098 << StringPrintf("%s: flag ndef supported", __func__);
1099 if (flags & RW_NDEF_FL_UNKNOWN)
1100 DLOG_IF(INFO, nfc_debug_enabled)
1101 << StringPrintf("%s: flag all unknown", __func__);
1102 if (flags & RW_NDEF_FL_FORMATABLE)
1103 DLOG_IF(INFO, nfc_debug_enabled)
1104 << StringPrintf("%s: flag formattable", __func__);
1105
1106 sCheckNdefWaitingForComplete = JNI_FALSE;
1107 sCheckNdefStatus = status;
1108 if (sCheckNdefStatus != NFA_STATUS_OK &&
1109 sCheckNdefStatus != NFA_STATUS_TIMEOUT)
1110 sCheckNdefStatus = NFA_STATUS_FAILED;
1111 sCheckNdefCapable = false; // assume tag is NOT ndef capable
1112 if (sCheckNdefStatus == NFA_STATUS_OK) {
1113 // NDEF content is on the tag
1114 sCheckNdefMaxSize = maxSize;
1115 sCheckNdefCurrentSize = currentSize;
1116 sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY;
1117 sCheckNdefCapable = true;
1118 } else if (sCheckNdefStatus == NFA_STATUS_FAILED) {
1119 // no NDEF content on the tag
1120 sCheckNdefMaxSize = 0;
1121 sCheckNdefCurrentSize = 0;
1122 sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY;
1123 if ((flags & RW_NDEF_FL_UNKNOWN) == 0) // if stack understands the tag
1124 {
1125 if (flags & RW_NDEF_FL_SUPPORTED) // if tag is ndef capable
1126 sCheckNdefCapable = true;
1127 }
1128 } else {
1129 LOG(ERROR) << StringPrintf("%s: unknown status=0x%X", __func__, status);
1130 sCheckNdefMaxSize = 0;
1131 sCheckNdefCurrentSize = 0;
1132 sCheckNdefCardReadOnly = false;
1133 }
1134 sem_post(&sCheckNdefSem);
1135 }
1136
1137 /*******************************************************************************
1138 **
1139 ** Function: nativeNfcTag_doCheckNdef
1140 **
1141 ** Description: Does the tag contain a NDEF message?
1142 ** e: JVM environment.
1143 ** o: Java object.
1144 ** ndefInfo: NDEF info.
1145 **
1146 ** Returns: Status code; 0 is success.
1147 **
1148 *******************************************************************************/
nativeNfcTag_doCheckNdef(JNIEnv * e,jobject o,jintArray ndefInfo)1149 static jint nativeNfcTag_doCheckNdef(JNIEnv* e, jobject o, jintArray ndefInfo) {
1150 tNFA_STATUS status = NFA_STATUS_FAILED;
1151 jint* ndef = NULL;
1152
1153 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
1154
1155 // special case for Kovio
1156 if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) {
1157 DLOG_IF(INFO, nfc_debug_enabled)
1158 << StringPrintf("%s: Kovio tag, no NDEF", __func__);
1159 ndef = e->GetIntArrayElements(ndefInfo, 0);
1160 ndef[0] = 0;
1161 ndef[1] = NDEF_MODE_READ_ONLY;
1162 e->ReleaseIntArrayElements(ndefInfo, ndef, 0);
1163 return NFA_STATUS_FAILED;
1164 } else if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) {
1165 nativeNfcTag_doReconnect(e, o);
1166 }
1167
1168 /* Create the write semaphore */
1169 if (sem_init(&sCheckNdefSem, 0, 0) == -1) {
1170 LOG(ERROR) << StringPrintf(
1171 "%s: Check NDEF semaphore creation failed (errno=0x%08x)", __func__,
1172 errno);
1173 return JNI_FALSE;
1174 }
1175
1176 if (NfcTag::getInstance().getActivationState() != NfcTag::Active) {
1177 LOG(ERROR) << StringPrintf("%s: tag already deactivated", __func__);
1178 goto TheEnd;
1179 }
1180
1181 DLOG_IF(INFO, nfc_debug_enabled)
1182 << StringPrintf("%s: try NFA_RwDetectNDef", __func__);
1183 sCheckNdefWaitingForComplete = JNI_TRUE;
1184
1185 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
1186 status = EXTNS_MfcCheckNDef();
1187 } else {
1188 status = NFA_RwDetectNDef();
1189 }
1190
1191 if (status != NFA_STATUS_OK) {
1192 LOG(ERROR) << StringPrintf("%s: NFA_RwDetectNDef failed, status = 0x%X",
1193 __func__, status);
1194 goto TheEnd;
1195 }
1196
1197 /* Wait for check NDEF completion status */
1198 if (sem_wait(&sCheckNdefSem)) {
1199 LOG(ERROR) << StringPrintf(
1200 "%s: Failed to wait for check NDEF semaphore (errno=0x%08x)", __func__,
1201 errno);
1202 goto TheEnd;
1203 }
1204
1205 if (sCheckNdefStatus == NFA_STATUS_OK) {
1206 // stack found a NDEF message on the tag
1207 ndef = e->GetIntArrayElements(ndefInfo, 0);
1208 if (NfcTag::getInstance().getProtocol() == NFA_PROTOCOL_T1T)
1209 ndef[0] = NfcTag::getInstance().getT1tMaxMessageSize();
1210 else
1211 ndef[0] = sCheckNdefMaxSize;
1212 if (sCheckNdefCardReadOnly)
1213 ndef[1] = NDEF_MODE_READ_ONLY;
1214 else
1215 ndef[1] = NDEF_MODE_READ_WRITE;
1216 e->ReleaseIntArrayElements(ndefInfo, ndef, 0);
1217 status = NFA_STATUS_OK;
1218 } else if (sCheckNdefStatus == NFA_STATUS_FAILED) {
1219 // stack did not find a NDEF message on the tag;
1220 ndef = e->GetIntArrayElements(ndefInfo, 0);
1221 if (NfcTag::getInstance().getProtocol() == NFA_PROTOCOL_T1T)
1222 ndef[0] = NfcTag::getInstance().getT1tMaxMessageSize();
1223 else
1224 ndef[0] = sCheckNdefMaxSize;
1225 if (sCheckNdefCardReadOnly)
1226 ndef[1] = NDEF_MODE_READ_ONLY;
1227 else
1228 ndef[1] = NDEF_MODE_READ_WRITE;
1229 e->ReleaseIntArrayElements(ndefInfo, ndef, 0);
1230 status = NFA_STATUS_FAILED;
1231 } else {
1232 DLOG_IF(INFO, nfc_debug_enabled)
1233 << StringPrintf("%s: unknown status 0x%X", __func__, sCheckNdefStatus);
1234 status = sCheckNdefStatus;
1235 }
1236
1237 /* Reconnect Mifare Classic Tag for furture use */
1238 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) {
1239 nativeNfcTag_doReconnect(e, o);
1240 }
1241
1242 TheEnd:
1243 /* Destroy semaphore */
1244 if (sem_destroy(&sCheckNdefSem)) {
1245 LOG(ERROR) << StringPrintf(
1246 "%s: Failed to destroy check NDEF semaphore (errno=0x%08x)", __func__,
1247 errno);
1248 }
1249 sCheckNdefWaitingForComplete = JNI_FALSE;
1250 DLOG_IF(INFO, nfc_debug_enabled)
1251 << StringPrintf("%s: exit; status=0x%X", __func__, status);
1252 return status;
1253 }
1254
1255 /*******************************************************************************
1256 **
1257 ** Function: nativeNfcTag_resetPresenceCheck
1258 **
1259 ** Description: Reset variables related to presence-check.
1260 **
1261 ** Returns: None
1262 **
1263 *******************************************************************************/
nativeNfcTag_resetPresenceCheck()1264 void nativeNfcTag_resetPresenceCheck() { sIsTagPresent = true; }
1265
1266 /*******************************************************************************
1267 **
1268 ** Function: nativeNfcTag_doPresenceCheckResult
1269 **
1270 ** Description: Receive the result of presence-check.
1271 ** status: Result of presence-check.
1272 **
1273 ** Returns: None
1274 **
1275 *******************************************************************************/
nativeNfcTag_doPresenceCheckResult(tNFA_STATUS status)1276 void nativeNfcTag_doPresenceCheckResult(tNFA_STATUS status) {
1277 SyncEventGuard guard(sPresenceCheckEvent);
1278 sIsTagPresent = status == NFA_STATUS_OK;
1279 sPresenceCheckEvent.notifyOne();
1280 }
1281
1282 /*******************************************************************************
1283 **
1284 ** Function: nativeNfcTag_doPresenceCheck
1285 **
1286 ** Description: Check if the tag is in the RF field.
1287 ** e: JVM environment.
1288 ** o: Java object.
1289 **
1290 ** Returns: True if tag is in RF field.
1291 **
1292 *******************************************************************************/
nativeNfcTag_doPresenceCheck(JNIEnv *,jobject)1293 static jboolean nativeNfcTag_doPresenceCheck(JNIEnv*, jobject) {
1294 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1295 tNFA_STATUS status = NFA_STATUS_OK;
1296 jboolean isPresent = JNI_FALSE;
1297
1298 // Special case for Kovio. The deactivation would have already occurred
1299 // but was ignored so that normal tag opertions could complete. Now we
1300 // want to process as if the deactivate just happened.
1301 if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) {
1302 DLOG_IF(INFO, nfc_debug_enabled)
1303 << StringPrintf("%s: Kovio, force deactivate handling", __func__);
1304 tNFA_DEACTIVATED deactivated = {NFA_DEACTIVATE_TYPE_IDLE};
1305 {
1306 SyncEventGuard g(gDeactivatedEvent);
1307 gActivated = false; // guard this variable from multi-threaded access
1308 gDeactivatedEvent.notifyOne();
1309 }
1310
1311 NfcTag::getInstance().setDeactivationState(deactivated);
1312 nativeNfcTag_resetPresenceCheck();
1313 NfcTag::getInstance().connectionEventHandler(NFA_DEACTIVATED_EVT, NULL);
1314 nativeNfcTag_abortWaits();
1315 NfcTag::getInstance().abort();
1316
1317 return JNI_FALSE;
1318 }
1319
1320 if (nfcManager_isNfcActive() == false) {
1321 DLOG_IF(INFO, nfc_debug_enabled)
1322 << StringPrintf("%s: NFC is no longer active.", __func__);
1323 return JNI_FALSE;
1324 }
1325
1326 if (!sRfInterfaceMutex.tryLock()) {
1327 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1328 "%s: tag is being reSelected assume it is present", __func__);
1329 return JNI_TRUE;
1330 }
1331
1332 sRfInterfaceMutex.unlock();
1333
1334 if (NfcTag::getInstance().isActivated() == false) {
1335 DLOG_IF(INFO, nfc_debug_enabled)
1336 << StringPrintf("%s: tag already deactivated", __func__);
1337 return JNI_FALSE;
1338 }
1339 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
1340 status = EXTNS_MfcPresenceCheck();
1341 if (status == NFCSTATUS_SUCCESS) {
1342 return (NFCSTATUS_SUCCESS == EXTNS_GetPresenceCheckStatus()) ? JNI_TRUE
1343 : JNI_FALSE;
1344 }
1345 }
1346
1347 {
1348 SyncEventGuard guard(sPresenceCheckEvent);
1349 status =
1350 NFA_RwPresenceCheck(NfcTag::getInstance().getPresenceCheckAlgorithm());
1351 if (status == NFA_STATUS_OK) {
1352 sPresenceCheckEvent.wait();
1353 isPresent = sIsTagPresent ? JNI_TRUE : JNI_FALSE;
1354 }
1355 }
1356
1357 if (isPresent == JNI_FALSE)
1358 DLOG_IF(INFO, nfc_debug_enabled)
1359 << StringPrintf("%s: tag absent", __func__);
1360 return isPresent;
1361 }
1362
1363 /*******************************************************************************
1364 **
1365 ** Function: nativeNfcTag_doIsNdefFormatable
1366 **
1367 ** Description: Can tag be formatted to store NDEF message?
1368 ** e: JVM environment.
1369 ** o: Java object.
1370 ** libNfcType: Type of tag.
1371 ** uidBytes: Tag's unique ID.
1372 ** pollBytes: Data from activation.
1373 ** actBytes: Data from activation.
1374 **
1375 ** Returns: True if formattable.
1376 **
1377 *******************************************************************************/
nativeNfcTag_doIsNdefFormatable(JNIEnv * e,jobject o,jint,jbyteArray,jbyteArray,jbyteArray)1378 static jboolean nativeNfcTag_doIsNdefFormatable(JNIEnv* e, jobject o,
1379 jint /*libNfcType*/, jbyteArray,
1380 jbyteArray, jbyteArray) {
1381 jboolean isFormattable = JNI_FALSE;
1382 tNFC_PROTOCOL protocol = NfcTag::getInstance().getProtocol();
1383 if (NFA_PROTOCOL_T1T == protocol || NFA_PROTOCOL_T5T == protocol ||
1384 NFC_PROTOCOL_MIFARE == protocol) {
1385 isFormattable = JNI_TRUE;
1386 } else if (NFA_PROTOCOL_T3T == protocol) {
1387 isFormattable = NfcTag::getInstance().isFelicaLite() ? JNI_TRUE : JNI_FALSE;
1388 } else if (NFA_PROTOCOL_T2T == protocol) {
1389 isFormattable = (NfcTag::getInstance().isMifareUltralight() |
1390 NfcTag::getInstance().isInfineonMyDMove() |
1391 NfcTag::getInstance().isKovioType2Tag())
1392 ? JNI_TRUE
1393 : JNI_FALSE;
1394 } else if (NFA_PROTOCOL_ISO_DEP == protocol) {
1395 /**
1396 * Determines whether this is a formatable IsoDep tag - currectly only NXP
1397 * DESFire is supported.
1398 */
1399 uint8_t cmd[] = {0x90, 0x60, 0x00, 0x00, 0x00};
1400
1401 if (NfcTag::getInstance().isMifareDESFire()) {
1402 /* Identifies as DESfire, use get version cmd to be sure */
1403 jbyteArray versionCmd = e->NewByteArray(5);
1404 e->SetByteArrayRegion(versionCmd, 0, 5, (jbyte*)cmd);
1405 jbyteArray respBytes =
1406 nativeNfcTag_doTransceive(e, o, versionCmd, JNI_TRUE, NULL);
1407 if (respBytes != NULL) {
1408 // Check whether the response matches a typical DESfire
1409 // response.
1410 // libNFC even does more advanced checking than we do
1411 // here, and will only format DESfire's with a certain
1412 // major/minor sw version and NXP as a manufacturer.
1413 // We don't want to do such checking here, to avoid
1414 // having to change code in multiple places.
1415 // A succesful (wrapped) DESFire getVersion command returns
1416 // 9 bytes, with byte 7 0x91 and byte 8 having status
1417 // code 0xAF (these values are fixed and well-known).
1418 int respLength = e->GetArrayLength(respBytes);
1419 uint8_t* resp = (uint8_t*)e->GetByteArrayElements(respBytes, NULL);
1420 if (respLength == 9 && resp[7] == 0x91 && resp[8] == 0xAF) {
1421 isFormattable = JNI_TRUE;
1422 }
1423 e->ReleaseByteArrayElements(respBytes, (jbyte*)resp, JNI_ABORT);
1424 }
1425 }
1426 }
1427
1428 DLOG_IF(INFO, nfc_debug_enabled)
1429 << StringPrintf("%s: is formattable=%u", __func__, isFormattable);
1430 return isFormattable;
1431 }
1432
1433 /*******************************************************************************
1434 **
1435 ** Function: nativeNfcTag_doIsIsoDepNdefFormatable
1436 **
1437 ** Description: Is ISO-DEP tag formattable?
1438 ** e: JVM environment.
1439 ** o: Java object.
1440 ** pollBytes: Data from activation.
1441 ** actBytes: Data from activation.
1442 **
1443 ** Returns: True if formattable.
1444 **
1445 *******************************************************************************/
nativeNfcTag_doIsIsoDepNdefFormatable(JNIEnv * e,jobject o,jbyteArray pollBytes,jbyteArray actBytes)1446 static jboolean nativeNfcTag_doIsIsoDepNdefFormatable(JNIEnv* e, jobject o,
1447 jbyteArray pollBytes,
1448 jbyteArray actBytes) {
1449 uint8_t uidFake[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
1450 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1451 jbyteArray uidArray = e->NewByteArray(8);
1452 e->SetByteArrayRegion(uidArray, 0, 8, (jbyte*)uidFake);
1453 return nativeNfcTag_doIsNdefFormatable(e, o, 0, uidArray, pollBytes,
1454 actBytes);
1455 }
1456
1457 /*******************************************************************************
1458 **
1459 ** Function: nativeNfcTag_makeMifareNdefFormat
1460 **
1461 ** Description: Format a mifare classic tag so it can store NDEF message.
1462 ** e: JVM environment.
1463 ** o: Java object.
1464 ** key: Key to acces tag.
1465 ** keySize: size of Key.
1466 **
1467 ** Returns: True if ok.
1468 **
1469 *******************************************************************************/
nativeNfcTag_makeMifareNdefFormat(JNIEnv * e,jobject o,uint8_t * key,uint32_t keySize)1470 static jboolean nativeNfcTag_makeMifareNdefFormat(JNIEnv* e, jobject o,
1471 uint8_t* key,
1472 uint32_t keySize) {
1473 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
1474 tNFA_STATUS status = NFA_STATUS_OK;
1475
1476 status = nativeNfcTag_doReconnect(e, o);
1477 if (status != NFA_STATUS_OK) {
1478 DLOG_IF(INFO, nfc_debug_enabled)
1479 << StringPrintf("%s: reconnect error, status=%u", __func__, status);
1480 return JNI_FALSE;
1481 }
1482
1483 sem_init(&sFormatSem, 0, 0);
1484 sFormatOk = false;
1485
1486 status = EXTNS_MfcFormatTag(key, keySize);
1487
1488 if (status == NFA_STATUS_OK) {
1489 DLOG_IF(INFO, nfc_debug_enabled)
1490 << StringPrintf("%s: wait for completion", __func__);
1491 sem_wait(&sFormatSem);
1492 status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED;
1493 } else {
1494 LOG(ERROR) << StringPrintf("%s: error status=%u", __func__, status);
1495 }
1496
1497 sem_destroy(&sFormatSem);
1498 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
1499 return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
1500 }
1501
1502 /*******************************************************************************
1503 **
1504 ** Function: nativeNfcTag_doNdefFormat
1505 **
1506 ** Description: Format a tag so it can store NDEF message.
1507 ** e: JVM environment.
1508 ** o: Java object.
1509 ** key: Not used.
1510 **
1511 ** Returns: True if ok.
1512 **
1513 *******************************************************************************/
nativeNfcTag_doNdefFormat(JNIEnv * e,jobject o,jbyteArray)1514 static jboolean nativeNfcTag_doNdefFormat(JNIEnv* e, jobject o, jbyteArray) {
1515 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__);
1516 tNFA_STATUS status = NFA_STATUS_OK;
1517
1518 // Do not try to format if tag is already deactivated.
1519 if (NfcTag::getInstance().isActivated() == false) {
1520 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1521 "%s: tag already deactivated(no need to format)", __func__);
1522 return JNI_FALSE;
1523 }
1524
1525 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
1526 static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1527 static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7};
1528 jboolean result;
1529
1530 result =
1531 nativeNfcTag_makeMifareNdefFormat(e, o, mfc_key1, sizeof(mfc_key1));
1532 if (result == JNI_FALSE) {
1533 result =
1534 nativeNfcTag_makeMifareNdefFormat(e, o, mfc_key2, sizeof(mfc_key2));
1535 }
1536 return result;
1537 }
1538
1539 sem_init(&sFormatSem, 0, 0);
1540 sFormatOk = false;
1541 status = NFA_RwFormatTag();
1542 if (status == NFA_STATUS_OK) {
1543 DLOG_IF(INFO, nfc_debug_enabled)
1544 << StringPrintf("%s: wait for completion", __func__);
1545 sem_wait(&sFormatSem);
1546 status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED;
1547 } else
1548 LOG(ERROR) << StringPrintf("%s: error status=%u", __func__, status);
1549 sem_destroy(&sFormatSem);
1550
1551 if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_ISO_DEP) {
1552 int retCode = NFCSTATUS_SUCCESS;
1553 retCode = nativeNfcTag_doReconnect(e, o);
1554 }
1555 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__);
1556 return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
1557 }
1558
1559 /*******************************************************************************
1560 **
1561 ** Function: nativeNfcTag_doMakeReadonlyResult
1562 **
1563 ** Description: Receive the result of making a tag read-only. Called by the
1564 ** NFA_SET_TAG_RO_EVT.
1565 ** status: Status of the operation.
1566 **
1567 ** Returns: None
1568 **
1569 *******************************************************************************/
nativeNfcTag_doMakeReadonlyResult(tNFA_STATUS status)1570 void nativeNfcTag_doMakeReadonlyResult(tNFA_STATUS status) {
1571 if (sMakeReadonlyWaitingForComplete != JNI_FALSE) {
1572 sMakeReadonlyWaitingForComplete = JNI_FALSE;
1573 sMakeReadonlyStatus = status;
1574
1575 sem_post(&sMakeReadonlySem);
1576 }
1577 }
1578
1579 /*******************************************************************************
1580 **
1581 ** Function: nativeNfcTag_makeMifareReadonly
1582 **
1583 ** Description: Make the mifare classic tag read-only.
1584 ** e: JVM environment.
1585 ** o: Java object.
1586 ** key: Key to access the tag.
1587 ** keySize: size of Key.
1588 **
1589 ** Returns: True if ok.
1590 **
1591 *******************************************************************************/
nativeNfcTag_makeMifareReadonly(JNIEnv * e,jobject o,uint8_t * key,int32_t keySize)1592 static jboolean nativeNfcTag_makeMifareReadonly(JNIEnv* e, jobject o,
1593 uint8_t* key, int32_t keySize) {
1594 jboolean result = JNI_FALSE;
1595 tNFA_STATUS status = NFA_STATUS_OK;
1596
1597 sMakeReadonlyStatus = NFA_STATUS_FAILED;
1598
1599 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1600
1601 /* Create the make_readonly semaphore */
1602 if (sem_init(&sMakeReadonlySem, 0, 0) == -1) {
1603 LOG(ERROR) << StringPrintf(
1604 "%s: Make readonly semaphore creation failed (errno=0x%08x)", __func__,
1605 errno);
1606 return JNI_FALSE;
1607 }
1608
1609 sMakeReadonlyWaitingForComplete = JNI_TRUE;
1610
1611 status = nativeNfcTag_doReconnect(e, o);
1612 if (status != NFA_STATUS_OK) {
1613 goto TheEnd;
1614 }
1615
1616 status = EXTNS_MfcSetReadOnly(key, keySize);
1617 if (status != NFA_STATUS_OK) {
1618 goto TheEnd;
1619 }
1620 sem_wait(&sMakeReadonlySem);
1621
1622 if (sMakeReadonlyStatus == NFA_STATUS_OK) {
1623 result = JNI_TRUE;
1624 }
1625
1626 TheEnd:
1627 /* Destroy semaphore */
1628 if (sem_destroy(&sMakeReadonlySem)) {
1629 LOG(ERROR) << StringPrintf(
1630 "%s: Failed to destroy read_only semaphore (errno=0x%08x)", __func__,
1631 errno);
1632 }
1633 sMakeReadonlyWaitingForComplete = JNI_FALSE;
1634 return result;
1635 }
1636
1637 /*******************************************************************************
1638 **
1639 ** Function: nativeNfcTag_doMakeReadonly
1640 **
1641 ** Description: Make the tag read-only.
1642 ** e: JVM environment.
1643 ** o: Java object.
1644 ** key: Key to access the tag.
1645 **
1646 ** Returns: True if ok.
1647 **
1648 *******************************************************************************/
nativeNfcTag_doMakeReadonly(JNIEnv * e,jobject o,jbyteArray)1649 static jboolean nativeNfcTag_doMakeReadonly(JNIEnv* e, jobject o, jbyteArray) {
1650 jboolean result = JNI_FALSE;
1651 tNFA_STATUS status;
1652
1653 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1654
1655 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE && legacy_mfc_reader) {
1656 static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1657 static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7};
1658 result = nativeNfcTag_makeMifareReadonly(e, o, mfc_key1, sizeof(mfc_key1));
1659 if (result == JNI_FALSE) {
1660 result =
1661 nativeNfcTag_makeMifareReadonly(e, o, mfc_key2, sizeof(mfc_key2));
1662 }
1663 return result;
1664 }
1665
1666 /* Create the make_readonly semaphore */
1667 if (sem_init(&sMakeReadonlySem, 0, 0) == -1) {
1668 LOG(ERROR) << StringPrintf(
1669 "%s: Make readonly semaphore creation failed (errno=0x%08x)", __func__,
1670 errno);
1671 return JNI_FALSE;
1672 }
1673
1674 sMakeReadonlyWaitingForComplete = JNI_TRUE;
1675
1676 // Hard-lock the tag (cannot be reverted)
1677 status = NFA_RwSetTagReadOnly(TRUE);
1678 if (status == NFA_STATUS_REJECTED) {
1679 status = NFA_RwSetTagReadOnly(FALSE); // try soft lock
1680 if (status != NFA_STATUS_OK) {
1681 LOG(ERROR) << StringPrintf("%s: fail soft lock, status=%d", __func__,
1682 status);
1683 goto TheEnd;
1684 }
1685 } else if (status != NFA_STATUS_OK) {
1686 LOG(ERROR) << StringPrintf("%s: fail hard lock, status=%d", __func__,
1687 status);
1688 goto TheEnd;
1689 }
1690
1691 /* Wait for check NDEF completion status */
1692 if (sem_wait(&sMakeReadonlySem)) {
1693 LOG(ERROR) << StringPrintf(
1694 "%s: Failed to wait for make_readonly semaphore (errno=0x%08x)",
1695 __func__, errno);
1696 goto TheEnd;
1697 }
1698
1699 if (sMakeReadonlyStatus == NFA_STATUS_OK) {
1700 result = JNI_TRUE;
1701 }
1702
1703 TheEnd:
1704 /* Destroy semaphore */
1705 if (sem_destroy(&sMakeReadonlySem)) {
1706 LOG(ERROR) << StringPrintf(
1707 "%s: Failed to destroy read_only semaphore (errno=0x%08x)", __func__,
1708 errno);
1709 }
1710 sMakeReadonlyWaitingForComplete = JNI_FALSE;
1711 return result;
1712 }
1713
1714 /*******************************************************************************
1715 **
1716 ** Function: nativeNfcTag_registerNdefTypeHandler
1717 **
1718 ** Description: Register a callback to receive NDEF message from the tag
1719 ** from the NFA_NDEF_DATA_EVT.
1720 **
1721 ** Returns: None
1722 **
1723 *******************************************************************************/
1724 // register a callback to receive NDEF message from the tag
1725 // from the NFA_NDEF_DATA_EVT;
nativeNfcTag_registerNdefTypeHandler()1726 void nativeNfcTag_registerNdefTypeHandler() {
1727 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1728 sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
1729 NFA_RegisterNDefTypeHandler(TRUE, NFA_TNF_DEFAULT, (uint8_t*)"", 0,
1730 ndefHandlerCallback);
1731 if (legacy_mfc_reader) {
1732 EXTNS_MfcRegisterNDefTypeHandler(ndefHandlerCallback);
1733 }
1734 }
1735
1736 /*******************************************************************************
1737 **
1738 ** Function: nativeNfcTag_deregisterNdefTypeHandler
1739 **
1740 ** Description: No longer need to receive NDEF message from the tag.
1741 **
1742 ** Returns: None
1743 **
1744 *******************************************************************************/
nativeNfcTag_deregisterNdefTypeHandler()1745 void nativeNfcTag_deregisterNdefTypeHandler() {
1746 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1747 NFA_DeregisterNDefTypeHandler(sNdefTypeHandlerHandle);
1748 sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
1749 }
1750
1751 /*******************************************************************************
1752 **
1753 ** Function: nativeNfcTag_acquireRfInterfaceMutexLock
1754 **
1755 ** Description: acquire sRfInterfaceMutex
1756 **
1757 ** Returns: None
1758 **
1759 *******************************************************************************/
nativeNfcTag_acquireRfInterfaceMutexLock()1760 void nativeNfcTag_acquireRfInterfaceMutexLock() {
1761 DLOG_IF(INFO, nfc_debug_enabled)
1762 << StringPrintf("%s: try to acquire lock", __func__);
1763 sRfInterfaceMutex.lock();
1764 DLOG_IF(INFO, nfc_debug_enabled)
1765 << StringPrintf("%s: sRfInterfaceMutex lock", __func__);
1766 }
1767
1768 /*******************************************************************************
1769 **
1770 ** Function: nativeNfcTag_releaseRfInterfaceMutexLock
1771 **
1772 ** Description: release the sRfInterfaceMutex
1773 **
1774 ** Returns: None
1775 **
1776 *******************************************************************************/
nativeNfcTag_releaseRfInterfaceMutexLock()1777 void nativeNfcTag_releaseRfInterfaceMutexLock() {
1778 sRfInterfaceMutex.unlock();
1779 DLOG_IF(INFO, nfc_debug_enabled)
1780 << StringPrintf("%s: sRfInterfaceMutex unlock", __func__);
1781 }
1782
1783 /*****************************************************************************
1784 **
1785 ** JNI functions for Android 4.0.3
1786 **
1787 *****************************************************************************/
1788 static JNINativeMethod gMethods[] = {
1789 {"doConnect", "(I)I", (void*)nativeNfcTag_doConnect},
1790 {"doDisconnect", "()Z", (void*)nativeNfcTag_doDisconnect},
1791 {"doReconnect", "()I", (void*)nativeNfcTag_doReconnect},
1792 {"doHandleReconnect", "(I)I", (void*)nativeNfcTag_doHandleReconnect},
1793 {"doTransceive", "([BZ[I)[B", (void*)nativeNfcTag_doTransceive},
1794 {"doGetNdefType", "(II)I", (void*)nativeNfcTag_doGetNdefType},
1795 {"doCheckNdef", "([I)I", (void*)nativeNfcTag_doCheckNdef},
1796 {"doRead", "()[B", (void*)nativeNfcTag_doRead},
1797 {"doWrite", "([B)Z", (void*)nativeNfcTag_doWrite},
1798 {"doPresenceCheck", "()Z", (void*)nativeNfcTag_doPresenceCheck},
1799 {"doIsIsoDepNdefFormatable", "([B[B)Z",
1800 (void*)nativeNfcTag_doIsIsoDepNdefFormatable},
1801 {"doNdefFormat", "([B)Z", (void*)nativeNfcTag_doNdefFormat},
1802 {"doMakeReadonly", "([B)Z", (void*)nativeNfcTag_doMakeReadonly},
1803 };
1804
1805 /*******************************************************************************
1806 **
1807 ** Function: register_com_android_nfc_NativeNfcTag
1808 **
1809 ** Description: Regisgter JNI functions with Java Virtual Machine.
1810 ** e: Environment of JVM.
1811 **
1812 ** Returns: Status of registration.
1813 **
1814 *******************************************************************************/
register_com_android_nfc_NativeNfcTag(JNIEnv * e)1815 int register_com_android_nfc_NativeNfcTag(JNIEnv* e) {
1816 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__);
1817 return jniRegisterNativeMethods(e, gNativeNfcTagClassName, gMethods,
1818 NELEM(gMethods));
1819 }
1820
1821 } /* namespace android */
1822