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