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