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