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