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 /*
18 * Tag-reading, tag-writing operations.
19 */
20 #include "_OverrideLog.h"
21 #include "NfcTag.h"
22 #include "JavaClassConstants.h"
23 #include "config.h"
24 #include <ScopedLocalRef.h>
25 #include <ScopedPrimitiveArray.h>
26
27 extern "C"
28 {
29 #include "rw_int.h"
30 #include "nfc_brcm_defs.h"
31 #include "phNxpExtns.h"
32 }
33
34
35 /*******************************************************************************
36 **
37 ** Function: NfcTag
38 **
39 ** Description: Initialize member variables.
40 **
41 ** Returns: None
42 **
43 *******************************************************************************/
NfcTag()44 NfcTag::NfcTag ()
45 : mNumTechList (0),
46 mTechnologyTimeoutsTable (MAX_NUM_TECHNOLOGY),
47 mNativeData (NULL),
48 mIsActivated (false),
49 mActivationState (Idle),
50 mProtocol(NFC_PROTOCOL_UNKNOWN),
51 mtT1tMaxMessageSize (0),
52 mReadCompletedStatus (NFA_STATUS_OK),
53 mLastKovioUidLen (0),
54 mNdefDetectionTimedOut (false),
55 mIsDynamicTagId (false),
56 mPresenceCheckAlgorithm (NFA_RW_PRES_CHK_DEFAULT),
57 mIsFelicaLite(false)
58 {
59 memset (mTechList, 0, sizeof(mTechList));
60 memset (mTechHandles, 0, sizeof(mTechHandles));
61 memset (mTechLibNfcTypes, 0, sizeof(mTechLibNfcTypes));
62 memset (mTechParams, 0, sizeof(mTechParams));
63 memset(mLastKovioUid, 0, NFC_KOVIO_MAX_LEN);
64 }
65
66
67 /*******************************************************************************
68 **
69 ** Function: getInstance
70 **
71 ** Description: Get a reference to the singleton NfcTag object.
72 **
73 ** Returns: Reference to NfcTag object.
74 **
75 *******************************************************************************/
getInstance()76 NfcTag& NfcTag::getInstance ()
77 {
78 static NfcTag tag;
79 return tag;
80 }
81
82
83 /*******************************************************************************
84 **
85 ** Function: initialize
86 **
87 ** Description: Reset member variables.
88 ** native: Native data.
89 **
90 ** Returns: None
91 **
92 *******************************************************************************/
initialize(nfc_jni_native_data * native)93 void NfcTag::initialize (nfc_jni_native_data* native)
94 {
95 long num = 0;
96
97 mNativeData = native;
98 mIsActivated = false;
99 mActivationState = Idle;
100 mProtocol = NFC_PROTOCOL_UNKNOWN;
101 mNumTechList = 0;
102 mtT1tMaxMessageSize = 0;
103 mReadCompletedStatus = NFA_STATUS_OK;
104 resetTechnologies ();
105 if (GetNumValue(NAME_PRESENCE_CHECK_ALGORITHM, &num, sizeof(num)))
106 mPresenceCheckAlgorithm = num;
107 }
108
109
110 /*******************************************************************************
111 **
112 ** Function: abort
113 **
114 ** Description: Unblock all operations.
115 **
116 ** Returns: None
117 **
118 *******************************************************************************/
abort()119 void NfcTag::abort ()
120 {
121 SyncEventGuard g (mReadCompleteEvent);
122 mReadCompleteEvent.notifyOne ();
123 }
124
125
126 /*******************************************************************************
127 **
128 ** Function: getActivationState
129 **
130 ** Description: What is the current state: Idle, Sleep, or Activated.
131 **
132 ** Returns: Idle, Sleep, or Activated.
133 **
134 *******************************************************************************/
getActivationState()135 NfcTag::ActivationState NfcTag::getActivationState ()
136 {
137 return mActivationState;
138 }
139
140
141 /*******************************************************************************
142 **
143 ** Function: setDeactivationState
144 **
145 ** Description: Set the current state: Idle or Sleep.
146 ** deactivated: state of deactivation.
147 **
148 ** Returns: None.
149 **
150 *******************************************************************************/
setDeactivationState(tNFA_DEACTIVATED & deactivated)151 void NfcTag::setDeactivationState (tNFA_DEACTIVATED& deactivated)
152 {
153 static const char fn [] = "NfcTag::setDeactivationState";
154 mActivationState = Idle;
155 mNdefDetectionTimedOut = false;
156 if (deactivated.type == NFA_DEACTIVATE_TYPE_SLEEP)
157 mActivationState = Sleep;
158 ALOGV("%s: state=%u", fn, mActivationState);
159 }
160
161
162 /*******************************************************************************
163 **
164 ** Function: setActivationState
165 **
166 ** Description: Set the current state to Active.
167 **
168 ** Returns: None.
169 **
170 *******************************************************************************/
setActivationState()171 void NfcTag::setActivationState ()
172 {
173 static const char fn [] = "NfcTag::setActivationState";
174 mNdefDetectionTimedOut = false;
175 mActivationState = Active;
176 ALOGV("%s: state=%u", fn, mActivationState);
177 }
178
179 /*******************************************************************************
180 **
181 ** Function: isActivated
182 **
183 ** Description: Is tag activated?
184 **
185 ** Returns: True if tag is activated.
186 **
187 *******************************************************************************/
isActivated()188 bool NfcTag::isActivated ()
189 {
190 return mIsActivated;
191 }
192
193
194 /*******************************************************************************
195 **
196 ** Function: getProtocol
197 **
198 ** Description: Get the protocol of the current tag.
199 **
200 ** Returns: Protocol number.
201 **
202 *******************************************************************************/
getProtocol()203 tNFC_PROTOCOL NfcTag::getProtocol()
204 {
205 return mProtocol;
206 }
207
208 /*******************************************************************************
209 **
210 ** Function TimeDiff
211 **
212 ** Description Computes time difference in milliseconds.
213 **
214 ** Returns Time difference in milliseconds
215 **
216 *******************************************************************************/
TimeDiff(timespec start,timespec end)217 uint32_t TimeDiff(timespec start, timespec end)
218 {
219 timespec temp;
220 if ((end.tv_nsec-start.tv_nsec)<0)
221 {
222 temp.tv_sec = end.tv_sec-start.tv_sec-1;
223 temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
224 }
225 else
226 {
227 temp.tv_sec = end.tv_sec-start.tv_sec;
228 temp.tv_nsec = end.tv_nsec-start.tv_nsec;
229 }
230
231 return (temp.tv_sec * 1000) + (temp.tv_nsec / 1000000);
232 }
233
234 /*******************************************************************************
235 **
236 ** Function: IsSameKovio
237 **
238 ** Description: Checks if tag activate is the same (UID) Kovio tag previously
239 ** activated. This is needed due to a problem with some Kovio
240 ** tags re-activating multiple times.
241 ** activationData: data from activation.
242 **
243 ** Returns: true if the activation is from the same tag previously
244 ** activated, false otherwise
245 **
246 *******************************************************************************/
IsSameKovio(tNFA_ACTIVATED & activationData)247 bool NfcTag::IsSameKovio(tNFA_ACTIVATED& activationData)
248 {
249 static const char fn [] = "NfcTag::IsSameKovio";
250 ALOGV("%s: enter", fn);
251 tNFC_ACTIVATE_DEVT& rfDetail = activationData.activate_ntf;
252
253 if (rfDetail.protocol != NFC_PROTOCOL_KOVIO)
254 return false;
255
256 memcpy (&(mTechParams[0]), &(rfDetail.rf_tech_param), sizeof(rfDetail.rf_tech_param));
257 if (mTechParams [0].mode != NFC_DISCOVERY_TYPE_POLL_KOVIO)
258 return false;
259
260 struct timespec now;
261 clock_gettime(CLOCK_REALTIME, &now);
262
263 bool rVal = false;
264 if (mTechParams[0].param.pk.uid_len == mLastKovioUidLen)
265 {
266 if (memcmp(mLastKovioUid, &mTechParams [0].param.pk.uid, mTechParams[0].param.pk.uid_len) == 0)
267 {
268 //same tag
269 if (TimeDiff(mLastKovioTime, now) < 500)
270 {
271 // same tag within 500 ms, ignore activation
272 rVal = true;
273 }
274 }
275 }
276
277 // save Kovio tag info
278 if (!rVal)
279 {
280 if ((mLastKovioUidLen = mTechParams[0].param.pk.uid_len) > NFC_KOVIO_MAX_LEN)
281 mLastKovioUidLen = NFC_KOVIO_MAX_LEN;
282 memcpy(mLastKovioUid, mTechParams[0].param.pk.uid, mLastKovioUidLen);
283 }
284 mLastKovioTime = now;
285 ALOGV("%s: exit, is same Kovio=%d", fn, rVal);
286 return rVal;
287 }
288
289 /*******************************************************************************
290 **
291 ** Function: discoverTechnologies
292 **
293 ** Description: Discover the technologies that NFC service needs by interpreting
294 ** the data structures from the stack.
295 ** activationData: data from activation.
296 **
297 ** Returns: None
298 **
299 *******************************************************************************/
discoverTechnologies(tNFA_ACTIVATED & activationData)300 void NfcTag::discoverTechnologies (tNFA_ACTIVATED& activationData)
301 {
302 static const char fn [] = "NfcTag::discoverTechnologies (activation)";
303 ALOGV("%s: enter", fn);
304 tNFC_ACTIVATE_DEVT& rfDetail = activationData.activate_ntf;
305
306 mNumTechList = 0;
307 mTechHandles [mNumTechList] = rfDetail.rf_disc_id;
308 mTechLibNfcTypes [mNumTechList] = rfDetail.protocol;
309
310 //save the stack's data structure for interpretation later
311 memcpy (&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param), sizeof(rfDetail.rf_tech_param));
312
313 if (NFC_PROTOCOL_T1T == rfDetail.protocol)
314 {
315 mTechList [mNumTechList] = TARGET_TYPE_ISO14443_3A; //is TagTechnology.NFC_A by Java API
316 }
317 else if (NFC_PROTOCOL_T2T == rfDetail.protocol)
318 {
319 mTechList [mNumTechList] = TARGET_TYPE_ISO14443_3A; //is TagTechnology.NFC_A by Java API
320 // could be MifFare UL or Classic or Kovio
321 {
322 // need to look at first byte of uid to find Manufacture Byte
323 tNFC_RF_TECH_PARAMS tech_params;
324 memcpy (&tech_params, &(rfDetail.rf_tech_param), sizeof(rfDetail.rf_tech_param));
325
326 if ((tech_params.param.pa.nfcid1[0] == 0x04 && rfDetail.rf_tech_param.param.pa.sel_rsp == 0) ||
327 rfDetail.rf_tech_param.param.pa.sel_rsp == 0x18 ||
328 rfDetail.rf_tech_param.param.pa.sel_rsp == 0x08)
329 {
330 if (rfDetail.rf_tech_param.param.pa.sel_rsp == 0)
331 {
332 mNumTechList++;
333 mTechHandles [mNumTechList] = rfDetail.rf_disc_id;
334 mTechLibNfcTypes [mNumTechList] = rfDetail.protocol;
335 //save the stack's data structure for interpretation later
336 memcpy (&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param), sizeof(rfDetail.rf_tech_param));
337 mTechList [mNumTechList] = TARGET_TYPE_MIFARE_UL; //is TagTechnology.MIFARE_ULTRALIGHT by Java API
338 }
339 }
340 }
341 }
342 else if (NFC_PROTOCOL_T3T == rfDetail.protocol)
343 {
344 uint8_t xx = 0;
345
346 mTechList [mNumTechList] = TARGET_TYPE_FELICA;
347
348 //see if it is Felica Lite.
349 while (xx < activationData.params.t3t.num_system_codes)
350 {
351 if (activationData.params.t3t.p_system_codes[xx++] == T3T_SYSTEM_CODE_FELICA_LITE)
352 {
353 mIsFelicaLite = true;
354 break;
355 }
356 }
357 }
358 else if (NFC_PROTOCOL_ISO_DEP == rfDetail.protocol)
359 {
360 //type-4 tag uses technology ISO-DEP and technology A or B
361 mTechList [mNumTechList] = TARGET_TYPE_ISO14443_4; //is TagTechnology.ISO_DEP by Java API
362 if ( (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_A) ||
363 (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_A_ACTIVE) ||
364 (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_A) ||
365 (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE) )
366 {
367 mNumTechList++;
368 mTechHandles [mNumTechList] = rfDetail.rf_disc_id;
369 mTechLibNfcTypes [mNumTechList] = rfDetail.protocol;
370 mTechList [mNumTechList] = TARGET_TYPE_ISO14443_3A; //is TagTechnology.NFC_A by Java API
371 //save the stack's data structure for interpretation later
372 memcpy (&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param), sizeof(rfDetail.rf_tech_param));
373 }
374 else if ( (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_B) ||
375 (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_B_PRIME) ||
376 (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_B) ||
377 (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_B_PRIME) )
378 {
379 mNumTechList++;
380 mTechHandles [mNumTechList] = rfDetail.rf_disc_id;
381 mTechLibNfcTypes [mNumTechList] = rfDetail.protocol;
382 mTechList [mNumTechList] = TARGET_TYPE_ISO14443_3B; //is TagTechnology.NFC_B by Java API
383 //save the stack's data structure for interpretation later
384 memcpy (&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param), sizeof(rfDetail.rf_tech_param));
385 }
386 }
387 else if (NFC_PROTOCOL_15693 == rfDetail.protocol)
388 {
389 //is TagTechnology.NFC_V by Java API
390 mTechList [mNumTechList] = TARGET_TYPE_ISO15693;
391 }
392 else if (NFC_PROTOCOL_KOVIO == rfDetail.protocol)
393 {
394 ALOGV("%s: Kovio", fn);
395 mTechList [mNumTechList] = TARGET_TYPE_KOVIO_BARCODE;
396 }
397 else if (NFC_PROTOCOL_MIFARE == rfDetail.protocol)
398 {
399 ALOGV("%s: Mifare Classic", fn);
400 EXTNS_MfcInit (activationData);
401 mTechList [mNumTechList] = TARGET_TYPE_ISO14443_3A; //is TagTechnology.NFC_A by Java API
402 mNumTechList++;
403 mTechHandles [mNumTechList] = rfDetail.rf_disc_id;
404 mTechLibNfcTypes [mNumTechList] = rfDetail.protocol;
405 //save the stack's data structure for interpretation later
406 memcpy (&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param), sizeof(rfDetail.rf_tech_param));
407 mTechList [mNumTechList] = TARGET_TYPE_MIFARE_CLASSIC; //is TagTechnology.MIFARE_CLASSIC by Java API
408 }
409 else
410 {
411 ALOGE("%s: unknown protocol ????", fn);
412 mTechList [mNumTechList] = TARGET_TYPE_UNKNOWN;
413 }
414
415 mNumTechList++;
416 for (int i=0; i < mNumTechList; i++)
417 {
418 ALOGV("%s: index=%d; tech=%d; handle=%d; nfc type=%d", fn,
419 i, mTechList[i], mTechHandles[i], mTechLibNfcTypes[i]);
420 }
421 ALOGV("%s: exit", fn);
422 }
423
424
425 /*******************************************************************************
426 **
427 ** Function: discoverTechnologies
428 **
429 ** Description: Discover the technologies that NFC service needs by interpreting
430 ** the data structures from the stack.
431 ** discoveryData: data from discovery events(s).
432 **
433 ** Returns: None
434 **
435 *******************************************************************************/
discoverTechnologies(tNFA_DISC_RESULT & discoveryData)436 void NfcTag::discoverTechnologies (tNFA_DISC_RESULT& discoveryData)
437 {
438 static const char fn [] = "NfcTag::discoverTechnologies (discovery)";
439 tNFC_RESULT_DEVT& discovery_ntf = discoveryData.discovery_ntf;
440
441 ALOGV("%s: enter: rf disc. id=%u; protocol=%u, mNumTechList=%u", fn, discovery_ntf.rf_disc_id, discovery_ntf.protocol, mNumTechList);
442 if (mNumTechList >= MAX_NUM_TECHNOLOGY)
443 {
444 ALOGE("%s: exceed max=%d", fn, MAX_NUM_TECHNOLOGY);
445 goto TheEnd;
446 }
447 mTechHandles [mNumTechList] = discovery_ntf.rf_disc_id;
448 mTechLibNfcTypes [mNumTechList] = discovery_ntf.protocol;
449
450 //save the stack's data structure for interpretation later
451 memcpy (&(mTechParams[mNumTechList]), &(discovery_ntf.rf_tech_param), sizeof(discovery_ntf.rf_tech_param));
452
453 if (NFC_PROTOCOL_T1T == discovery_ntf.protocol)
454 {
455 mTechList [mNumTechList] = TARGET_TYPE_ISO14443_3A; //is TagTechnology.NFC_A by Java API
456 }
457 else if (NFC_PROTOCOL_T2T == discovery_ntf.protocol)
458 {
459 mTechList [mNumTechList] = TARGET_TYPE_ISO14443_3A; //is TagTechnology.NFC_A by Java API
460 //type-2 tags are identical to Mifare Ultralight, so Ultralight is also discovered
461 if ((discovery_ntf.rf_tech_param.param.pa.sel_rsp == 0) &&
462 (mNumTechList < (MAX_NUM_TECHNOLOGY-1)))
463 {
464 // Mifare Ultralight
465 mNumTechList++;
466 mTechHandles [mNumTechList] = discovery_ntf.rf_disc_id;
467 mTechLibNfcTypes [mNumTechList] = discovery_ntf.protocol;
468 mTechList [mNumTechList] = TARGET_TYPE_MIFARE_UL; //is TagTechnology.MIFARE_ULTRALIGHT by Java API
469 }
470
471 //save the stack's data structure for interpretation later
472 memcpy (&(mTechParams[mNumTechList]), &(discovery_ntf.rf_tech_param), sizeof(discovery_ntf.rf_tech_param));
473 }
474 else if (NFC_PROTOCOL_T3T == discovery_ntf.protocol)
475 {
476 mTechList [mNumTechList] = TARGET_TYPE_FELICA;
477 }
478 else if (NFC_PROTOCOL_ISO_DEP == discovery_ntf.protocol)
479 {
480 //type-4 tag uses technology ISO-DEP and technology A or B
481 mTechList [mNumTechList] = TARGET_TYPE_ISO14443_4; //is TagTechnology.ISO_DEP by Java API
482 if ( (discovery_ntf.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_A) ||
483 (discovery_ntf.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_A_ACTIVE) ||
484 (discovery_ntf.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_A) ||
485 (discovery_ntf.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE) )
486 {
487 if (mNumTechList < (MAX_NUM_TECHNOLOGY-1))
488 {
489 mNumTechList++;
490 mTechHandles [mNumTechList] = discovery_ntf.rf_disc_id;
491 mTechLibNfcTypes [mNumTechList] = discovery_ntf.protocol;
492 mTechList [mNumTechList] = TARGET_TYPE_ISO14443_3A; //is TagTechnology.NFC_A by Java API
493 //save the stack's data structure for interpretation later
494 memcpy (&(mTechParams[mNumTechList]), &(discovery_ntf.rf_tech_param), sizeof(discovery_ntf.rf_tech_param));
495 }
496 }
497 else if ( (discovery_ntf.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_B) ||
498 (discovery_ntf.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_B_PRIME) ||
499 (discovery_ntf.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_B) ||
500 (discovery_ntf.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_B_PRIME) )
501 {
502 if (mNumTechList < (MAX_NUM_TECHNOLOGY-1))
503 {
504 mNumTechList++;
505 mTechHandles [mNumTechList] = discovery_ntf.rf_disc_id;
506 mTechLibNfcTypes [mNumTechList] = discovery_ntf.protocol;
507 mTechList [mNumTechList] = TARGET_TYPE_ISO14443_3B; //is TagTechnology.NFC_B by Java API
508 //save the stack's data structure for interpretation later
509 memcpy (&(mTechParams[mNumTechList]), &(discovery_ntf.rf_tech_param), sizeof(discovery_ntf.rf_tech_param));
510 }
511 }
512 }
513 else if (NFC_PROTOCOL_15693 == discovery_ntf.protocol)
514 {
515 //is TagTechnology.NFC_V by Java API
516 mTechList [mNumTechList] = TARGET_TYPE_ISO15693;
517 }
518 else if (NFC_PROTOCOL_MIFARE == discovery_ntf.protocol)
519 {
520 mTechList [mNumTechList] = TARGET_TYPE_MIFARE_CLASSIC;
521 if (mNumTechList < (MAX_NUM_TECHNOLOGY-1))
522 {
523 mNumTechList++;
524 mTechHandles [mNumTechList] = discovery_ntf.rf_disc_id;
525 mTechLibNfcTypes [mNumTechList] = discovery_ntf.protocol;
526 mTechList [mNumTechList] = TARGET_TYPE_ISO14443_3A;
527 //save the stack's data structure for interpretation later
528 memcpy (&(mTechParams[mNumTechList]), &(discovery_ntf.rf_tech_param), sizeof(discovery_ntf.rf_tech_param));
529 }
530 }
531 else
532 {
533 ALOGE("%s: unknown protocol ????", fn);
534 mTechList [mNumTechList] = TARGET_TYPE_UNKNOWN;
535 }
536
537 mNumTechList++;
538 if (discovery_ntf.more != NCI_DISCOVER_NTF_MORE)
539 {
540 for (int i=0; i < mNumTechList; i++)
541 {
542 ALOGV("%s: index=%d; tech=%d; handle=%d; nfc type=%d", fn,
543 i, mTechList[i], mTechHandles[i], mTechLibNfcTypes[i]);
544 }
545 }
546
547 TheEnd:
548 ALOGV("%s: exit", fn);
549 }
550
551
552 /*******************************************************************************
553 **
554 ** Function: createNativeNfcTag
555 **
556 ** Description: Create a brand new Java NativeNfcTag object;
557 ** fill the objects's member variables with data;
558 ** notify NFC service;
559 ** activationData: data from activation.
560 **
561 ** Returns: None
562 **
563 *******************************************************************************/
createNativeNfcTag(tNFA_ACTIVATED & activationData)564 void NfcTag::createNativeNfcTag (tNFA_ACTIVATED& activationData)
565 {
566 static const char fn [] = "NfcTag::createNativeNfcTag";
567 ALOGV("%s: enter", fn);
568
569 JNIEnv* e = NULL;
570 ScopedAttach attach(mNativeData->vm, &e);
571 if (e == NULL)
572 {
573 ALOGE("%s: jni env is null", fn);
574 return;
575 }
576
577 ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(mNativeData->cached_NfcTag));
578 if (e->ExceptionCheck())
579 {
580 e->ExceptionClear();
581 ALOGE("%s: failed to get class", fn);
582 return;
583 }
584
585 //create a new Java NativeNfcTag object
586 jmethodID ctor = e->GetMethodID(tag_cls.get(), "<init>", "()V");
587 ScopedLocalRef<jobject> tag(e, e->NewObject(tag_cls.get(), ctor));
588
589 //fill NativeNfcTag's mProtocols, mTechList, mTechHandles, mTechLibNfcTypes
590 fillNativeNfcTagMembers1(e, tag_cls.get(), tag.get());
591
592 //fill NativeNfcTag's members: mHandle, mConnectedTechnology
593 fillNativeNfcTagMembers2(e, tag_cls.get(), tag.get(), activationData);
594
595 //fill NativeNfcTag's members: mTechPollBytes
596 fillNativeNfcTagMembers3(e, tag_cls.get(), tag.get(), activationData);
597
598 //fill NativeNfcTag's members: mTechActBytes
599 fillNativeNfcTagMembers4(e, tag_cls.get(), tag.get(), activationData);
600
601 //fill NativeNfcTag's members: mUid
602 fillNativeNfcTagMembers5(e, tag_cls.get(), tag.get(), activationData);
603
604 if (mNativeData->tag != NULL)
605 {
606 e->DeleteGlobalRef(mNativeData->tag);
607 }
608 mNativeData->tag = e->NewGlobalRef(tag.get());
609
610 //notify NFC service about this new tag
611 ALOGV("%s: try notify nfc service", fn);
612 e->CallVoidMethod(mNativeData->manager, android::gCachedNfcManagerNotifyNdefMessageListeners, tag.get());
613 if (e->ExceptionCheck())
614 {
615 e->ExceptionClear();
616 ALOGE("%s: fail notify nfc service", fn);
617 }
618
619 ALOGV("%s: exit", fn);
620 }
621
622
623 /*******************************************************************************
624 **
625 ** Function: fillNativeNfcTagMembers1
626 **
627 ** Description: Fill NativeNfcTag's members: mProtocols, mTechList, mTechHandles, mTechLibNfcTypes.
628 ** e: JVM environment.
629 ** tag_cls: Java NativeNfcTag class.
630 ** tag: Java NativeNfcTag object.
631 **
632 ** Returns: None
633 **
634 *******************************************************************************/
fillNativeNfcTagMembers1(JNIEnv * e,jclass tag_cls,jobject tag)635 void NfcTag::fillNativeNfcTagMembers1 (JNIEnv* e, jclass tag_cls, jobject tag)
636 {
637 static const char fn [] = "NfcTag::fillNativeNfcTagMembers1";
638 ALOGV("%s", fn);
639
640 //create objects that represent NativeNfcTag's member variables
641 ScopedLocalRef<jintArray> techList(e, e->NewIntArray(mNumTechList));
642 ScopedLocalRef<jintArray> handleList(e, e->NewIntArray(mNumTechList));
643 ScopedLocalRef<jintArray> typeList(e, e->NewIntArray(mNumTechList));
644
645 {
646 ScopedIntArrayRW technologies(e, techList.get());
647 ScopedIntArrayRW handles(e, handleList.get());
648 ScopedIntArrayRW types(e, typeList.get());
649 for (int i = 0; i < mNumTechList; i++) {
650 mNativeData->tProtocols [i] = mTechLibNfcTypes [i];
651 mNativeData->handles [i] = mTechHandles [i];
652 technologies [i] = mTechList [i];
653 handles [i] = mTechHandles [i];
654 types [i] = mTechLibNfcTypes [i];
655 }
656 }
657
658 jfieldID f = NULL;
659
660 f = e->GetFieldID(tag_cls, "mTechList", "[I");
661 e->SetObjectField(tag, f, techList.get());
662
663 f = e->GetFieldID(tag_cls, "mTechHandles", "[I");
664 e->SetObjectField(tag, f, handleList.get());
665
666 f = e->GetFieldID(tag_cls, "mTechLibNfcTypes", "[I");
667 e->SetObjectField(tag, f, typeList.get());
668 }
669
670
671 /*******************************************************************************
672 **
673 ** Function: fillNativeNfcTagMembers2
674 **
675 ** Description: Fill NativeNfcTag's members: mConnectedTechIndex or mConnectedTechnology.
676 ** The original Google's implementation is in set_target_pollBytes(
677 ** in com_android_nfc_NativeNfcTag.cpp;
678 ** e: JVM environment.
679 ** tag_cls: Java NativeNfcTag class.
680 ** tag: Java NativeNfcTag object.
681 ** activationData: data from activation.
682 **
683 ** Returns: None
684 **
685 *******************************************************************************/
fillNativeNfcTagMembers2(JNIEnv * e,jclass tag_cls,jobject tag,tNFA_ACTIVATED &)686 void NfcTag::fillNativeNfcTagMembers2 (JNIEnv* e, jclass tag_cls, jobject tag, tNFA_ACTIVATED& /*activationData*/)
687 {
688 static const char fn [] = "NfcTag::fillNativeNfcTagMembers2";
689 ALOGV("%s", fn);
690 jfieldID f = e->GetFieldID(tag_cls, "mConnectedTechIndex", "I");
691 e->SetIntField(tag, f, (jint) 0);
692 }
693
694
695 /*******************************************************************************
696 **
697 ** Function: fillNativeNfcTagMembers3
698 **
699 ** Description: Fill NativeNfcTag's members: mTechPollBytes.
700 ** The original Google's implementation is in set_target_pollBytes(
701 ** in com_android_nfc_NativeNfcTag.cpp;
702 ** e: JVM environment.
703 ** tag_cls: Java NativeNfcTag class.
704 ** tag: Java NativeNfcTag object.
705 ** activationData: data from activation.
706 **
707 ** Returns: None
708 **
709 *******************************************************************************/
fillNativeNfcTagMembers3(JNIEnv * e,jclass tag_cls,jobject tag,tNFA_ACTIVATED & activationData)710 void NfcTag::fillNativeNfcTagMembers3 (JNIEnv* e, jclass tag_cls, jobject tag, tNFA_ACTIVATED& activationData)
711 {
712 static const char fn [] = "NfcTag::fillNativeNfcTagMembers3";
713 ScopedLocalRef<jbyteArray> pollBytes(e, e->NewByteArray(0));
714 ScopedLocalRef<jclass> byteArrayClass(e, e->GetObjectClass(pollBytes.get()));
715 ScopedLocalRef<jobjectArray> techPollBytes(e, e->NewObjectArray(mNumTechList, byteArrayClass.get(), 0));
716 int len = 0;
717
718 for (int i = 0; i < mNumTechList; i++)
719 {
720 ALOGV("%s: index=%d; rf tech params mode=%u", fn, i, mTechParams [i].mode);
721 if (NFC_DISCOVERY_TYPE_POLL_A == mTechParams [i].mode
722 || NFC_DISCOVERY_TYPE_POLL_A_ACTIVE == mTechParams [i].mode
723 || NFC_DISCOVERY_TYPE_LISTEN_A == mTechParams [i].mode
724 || NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE == mTechParams [i].mode)
725 {
726 ALOGV("%s: tech A", fn);
727 pollBytes.reset(e->NewByteArray(2));
728 e->SetByteArrayRegion(pollBytes.get(), 0, 2, (jbyte*) mTechParams [i].param.pa.sens_res);
729 }
730 else if (NFC_DISCOVERY_TYPE_POLL_B == mTechParams [i].mode
731 || NFC_DISCOVERY_TYPE_POLL_B_PRIME == mTechParams [i].mode
732 || NFC_DISCOVERY_TYPE_LISTEN_B == mTechParams [i].mode
733 || NFC_DISCOVERY_TYPE_LISTEN_B_PRIME == mTechParams [i].mode)
734 {
735 if (mTechList [i] == TARGET_TYPE_ISO14443_3B) //is TagTechnology.NFC_B by Java API
736 {
737 /*****************
738 see NFC Forum Digital Protocol specification; section 5.6.2;
739 in SENSB_RES response, byte 6 through 9 is Application Data, byte 10-12 or 13 is Protocol Info;
740 used by public API: NfcB.getApplicationData(), NfcB.getProtocolInfo();
741 *****************/
742 ALOGV("%s: tech B; TARGET_TYPE_ISO14443_3B", fn);
743 len = mTechParams [i].param.pb.sensb_res_len;
744 len = len - 4; //subtract 4 bytes for NFCID0 at byte 2 through 5
745 pollBytes.reset(e->NewByteArray(len));
746 e->SetByteArrayRegion(pollBytes.get(), 0, len, (jbyte*) (mTechParams [i].param.pb.sensb_res+4));
747 }
748 else
749 {
750 pollBytes.reset(e->NewByteArray(0));
751 }
752 }
753 else if (NFC_DISCOVERY_TYPE_POLL_F == mTechParams [i].mode
754 || NFC_DISCOVERY_TYPE_POLL_F_ACTIVE == mTechParams [i].mode
755 || NFC_DISCOVERY_TYPE_LISTEN_F == mTechParams [i].mode
756 || NFC_DISCOVERY_TYPE_LISTEN_F_ACTIVE == mTechParams [i].mode)
757 {
758 /****************
759 see NFC Forum Type 3 Tag Operation Specification; sections 2.3.2, 2.3.1.2;
760 see NFC Forum Digital Protocol Specification; sections 6.6.2;
761 PMm: manufacture parameter; 8 bytes;
762 System Code: 2 bytes;
763 ****************/
764 ALOGV("%s: tech F", fn);
765 uint8_t result [10]; //return result to NFC service
766 memset (result, 0, sizeof(result));
767 len = 10;
768
769 /****
770 for (int ii = 0; ii < mTechParams [i].param.pf.sensf_res_len; ii++)
771 {
772 ALOGV("%s: tech F, sendf_res[%d]=%d (0x%x)",
773 fn, ii, mTechParams [i].param.pf.sensf_res[ii],mTechParams [i].param.pf.sensf_res[ii]);
774 }
775 ***/
776 memcpy (result, mTechParams [i].param.pf.sensf_res + 8, 8); //copy PMm
777 if (activationData.params.t3t.num_system_codes > 0) //copy the first System Code
778 {
779 uint16_t systemCode = *(activationData.params.t3t.p_system_codes);
780 result [8] = (uint8_t) (systemCode >> 8);
781 result [9] = (uint8_t) systemCode;
782 ALOGV("%s: tech F; sys code=0x%X 0x%X", fn, result [8], result [9]);
783 }
784 pollBytes.reset(e->NewByteArray(len));
785 e->SetByteArrayRegion(pollBytes.get(), 0, len, (jbyte*) result);
786 }
787 else if (NFC_DISCOVERY_TYPE_POLL_ISO15693 == mTechParams [i].mode
788 || NFC_DISCOVERY_TYPE_LISTEN_ISO15693 == mTechParams [i].mode)
789 {
790 ALOGV("%s: tech iso 15693", fn);
791 //iso 15693 response flags: 1 octet
792 //iso 15693 Data Structure Format Identifier (DSF ID): 1 octet
793 //used by public API: NfcV.getDsfId(), NfcV.getResponseFlags();
794 uint8_t data [2]= {activationData.params.i93.afi, activationData.params.i93.dsfid};
795 pollBytes.reset(e->NewByteArray(2));
796 e->SetByteArrayRegion(pollBytes.get(), 0, 2, (jbyte *) data);
797 }
798 else
799 {
800 ALOGE("%s: tech unknown ????", fn);
801 pollBytes.reset(e->NewByteArray(0));
802 } //switch: every type of technology
803 e->SetObjectArrayElement(techPollBytes.get(), i, pollBytes.get());
804 } //for: every technology in the array
805 jfieldID f = e->GetFieldID(tag_cls, "mTechPollBytes", "[[B");
806 e->SetObjectField(tag, f, techPollBytes.get());
807 }
808
809
810 /*******************************************************************************
811 **
812 ** Function: fillNativeNfcTagMembers4
813 **
814 ** Description: Fill NativeNfcTag's members: mTechActBytes.
815 ** The original Google's implementation is in set_target_activationBytes()
816 ** in com_android_nfc_NativeNfcTag.cpp;
817 ** e: JVM environment.
818 ** tag_cls: Java NativeNfcTag class.
819 ** tag: Java NativeNfcTag object.
820 ** activationData: data from activation.
821 **
822 ** Returns: None
823 **
824 *******************************************************************************/
fillNativeNfcTagMembers4(JNIEnv * e,jclass tag_cls,jobject tag,tNFA_ACTIVATED & activationData)825 void NfcTag::fillNativeNfcTagMembers4 (JNIEnv* e, jclass tag_cls, jobject tag, tNFA_ACTIVATED& activationData)
826 {
827 static const char fn [] = "NfcTag::fillNativeNfcTagMembers4";
828 ScopedLocalRef<jbyteArray> actBytes(e, e->NewByteArray(0));
829 ScopedLocalRef<jclass> byteArrayClass(e, e->GetObjectClass(actBytes.get()));
830 ScopedLocalRef<jobjectArray> techActBytes(e, e->NewObjectArray(mNumTechList, byteArrayClass.get(), 0));
831
832 for (int i = 0; i < mNumTechList; i++)
833 {
834 ALOGV("%s: index=%d", fn, i);
835 if (NFC_PROTOCOL_T1T == mTechLibNfcTypes[i] || NFC_PROTOCOL_T2T == mTechLibNfcTypes[i])
836 {
837 if (mTechLibNfcTypes[i] == NFC_PROTOCOL_T1T)
838 ALOGV("%s: T1T; tech A", fn);
839 else if (mTechLibNfcTypes[i] == NFC_PROTOCOL_T2T)
840 ALOGV("%s: T2T; tech A", fn);
841 actBytes.reset(e->NewByteArray(1));
842 e->SetByteArrayRegion(actBytes.get(), 0, 1, (jbyte*) &mTechParams [i].param.pa.sel_rsp);
843 }
844 else if (NFC_PROTOCOL_T3T == mTechLibNfcTypes[i])
845 {
846 //felica
847 ALOGV("%s: T3T; felica; tech F", fn);
848 //really, there is no data
849 actBytes.reset(e->NewByteArray(0));
850 }
851 else if (NFC_PROTOCOL_MIFARE == mTechLibNfcTypes[i])
852 {
853 ALOGV("%s: Mifare Classic; tech A", fn);
854 actBytes.reset (e->NewByteArray(1));
855 e->SetByteArrayRegion (actBytes.get(), 0, 1,
856 (jbyte*) &mTechParams [i].param.pa.sel_rsp);
857 }
858 else if (NFC_PROTOCOL_ISO_DEP == mTechLibNfcTypes[i])
859 {
860 //t4t
861 if (mTechList [i] == TARGET_TYPE_ISO14443_4) //is TagTechnology.ISO_DEP by Java API
862 {
863 if ( (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) ||
864 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A_ACTIVE) ||
865 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_A) ||
866 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE) )
867 {
868 //see NFC Forum Digital Protocol specification, section 11.6.2, "RATS Response"; search for "historical bytes";
869 //copy historical bytes into Java object;
870 //the public API, IsoDep.getHistoricalBytes(), returns this data;
871 if (activationData.activate_ntf.intf_param.type == NFC_INTERFACE_ISO_DEP)
872 {
873 tNFC_INTF_PA_ISO_DEP& pa_iso = activationData.activate_ntf.intf_param.intf_param.pa_iso;
874 ALOGV("%s: T4T; ISO_DEP for tech A; copy historical bytes; len=%u", fn, pa_iso.his_byte_len);
875 actBytes.reset(e->NewByteArray(pa_iso.his_byte_len));
876 if (pa_iso.his_byte_len > 0)
877 e->SetByteArrayRegion(actBytes.get(), 0, pa_iso.his_byte_len, (jbyte*) (pa_iso.his_byte));
878 }
879 else
880 {
881 ALOGE("%s: T4T; ISO_DEP for tech A; wrong interface=%u", fn, activationData.activate_ntf.intf_param.type);
882 actBytes.reset(e->NewByteArray(0));
883 }
884 }
885 else if ( (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_B) ||
886 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_B_PRIME) ||
887 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_B) ||
888 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_B_PRIME) )
889 {
890 //see NFC Forum Digital Protocol specification, section 12.6.2, "ATTRIB Response";
891 //copy higher-layer response bytes into Java object;
892 //the public API, IsoDep.getHiLayerResponse(), returns this data;
893 if (activationData.activate_ntf.intf_param.type == NFC_INTERFACE_ISO_DEP)
894 {
895 tNFC_INTF_PB_ISO_DEP& pb_iso = activationData.activate_ntf.intf_param.intf_param.pb_iso;
896 ALOGV("%s: T4T; ISO_DEP for tech B; copy response bytes; len=%u", fn, pb_iso.hi_info_len);
897 actBytes.reset(e->NewByteArray(pb_iso.hi_info_len));
898 if (pb_iso.hi_info_len > 0)
899 e->SetByteArrayRegion(actBytes.get(), 0, pb_iso.hi_info_len, (jbyte*) (pb_iso.hi_info));
900 }
901 else
902 {
903 ALOGE("%s: T4T; ISO_DEP for tech B; wrong interface=%u", fn, activationData.activate_ntf.intf_param.type);
904 actBytes.reset(e->NewByteArray(0));
905 }
906 }
907 }
908 else if (mTechList [i] == TARGET_TYPE_ISO14443_3A) //is TagTechnology.NFC_A by Java API
909 {
910 ALOGV("%s: T4T; tech A", fn);
911 actBytes.reset(e->NewByteArray(1));
912 e->SetByteArrayRegion(actBytes.get(), 0, 1, (jbyte*) &mTechParams [i].param.pa.sel_rsp);
913 }
914 else
915 {
916 actBytes.reset(e->NewByteArray(0));
917 }
918 } //case NFC_PROTOCOL_ISO_DEP: //t4t
919 else if (NFC_PROTOCOL_15693 == mTechLibNfcTypes[i])
920 {
921 ALOGV("%s: tech iso 15693", fn);
922 //iso 15693 response flags: 1 octet
923 //iso 15693 Data Structure Format Identifier (DSF ID): 1 octet
924 //used by public API: NfcV.getDsfId(), NfcV.getResponseFlags();
925 uint8_t data [2]= {activationData.params.i93.afi, activationData.params.i93.dsfid};
926 actBytes.reset(e->NewByteArray(2));
927 e->SetByteArrayRegion(actBytes.get(), 0, 2, (jbyte *) data);
928 }
929 else
930 {
931 ALOGV("%s: tech unknown ????", fn);
932 actBytes.reset(e->NewByteArray(0));
933 }
934 e->SetObjectArrayElement(techActBytes.get(), i, actBytes.get());
935 } //for: every technology in the array
936 jfieldID f = e->GetFieldID (tag_cls, "mTechActBytes", "[[B");
937 e->SetObjectField(tag, f, techActBytes.get());
938 }
939
940
941 /*******************************************************************************
942 **
943 ** Function: fillNativeNfcTagMembers5
944 **
945 ** Description: Fill NativeNfcTag's members: mUid.
946 ** The original Google's implementation is in nfc_jni_Discovery_notification_callback()
947 ** in com_android_nfc_NativeNfcManager.cpp;
948 ** e: JVM environment.
949 ** tag_cls: Java NativeNfcTag class.
950 ** tag: Java NativeNfcTag object.
951 ** activationData: data from activation.
952 **
953 ** Returns: None
954 **
955 *******************************************************************************/
fillNativeNfcTagMembers5(JNIEnv * e,jclass tag_cls,jobject tag,tNFA_ACTIVATED & activationData)956 void NfcTag::fillNativeNfcTagMembers5 (JNIEnv* e, jclass tag_cls, jobject tag, tNFA_ACTIVATED& activationData)
957 {
958 static const char fn [] = "NfcTag::fillNativeNfcTagMembers5";
959 int len = 0;
960 ScopedLocalRef<jbyteArray> uid(e, NULL);
961
962 if (NFC_DISCOVERY_TYPE_POLL_KOVIO == mTechParams [0].mode)
963 {
964 ALOGV("%s: Kovio", fn);
965 len = mTechParams [0].param.pk.uid_len;
966 uid.reset(e->NewByteArray(len));
967 e->SetByteArrayRegion(uid.get(), 0, len,
968 (jbyte*) &mTechParams [0].param.pk.uid);
969 }
970 else if (NFC_DISCOVERY_TYPE_POLL_A == mTechParams [0].mode
971 || NFC_DISCOVERY_TYPE_POLL_A_ACTIVE == mTechParams [0].mode
972 || NFC_DISCOVERY_TYPE_LISTEN_A == mTechParams [0].mode
973 || NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE == mTechParams [0].mode)
974 {
975 ALOGV("%s: tech A", fn);
976 len = mTechParams [0].param.pa.nfcid1_len;
977 uid.reset(e->NewByteArray(len));
978 e->SetByteArrayRegion(uid.get(), 0, len,
979 (jbyte*) &mTechParams [0].param.pa.nfcid1);
980 //a tag's NFCID1 can change dynamically at each activation;
981 //only the first byte (0x08) is constant; a dynamic NFCID1's length
982 //must be 4 bytes (see NFC Digitial Protocol,
983 //section 4.7.2 SDD_RES Response, Requirements 20).
984 mIsDynamicTagId = (mTechParams [0].param.pa.nfcid1_len == 4) &&
985 (mTechParams [0].param.pa.nfcid1 [0] == 0x08);
986 }
987 else if (NFC_DISCOVERY_TYPE_POLL_B == mTechParams [0].mode
988 || NFC_DISCOVERY_TYPE_POLL_B_PRIME == mTechParams [0].mode
989 || NFC_DISCOVERY_TYPE_LISTEN_B == mTechParams [0].mode
990 || NFC_DISCOVERY_TYPE_LISTEN_B_PRIME == mTechParams [0].mode)
991 {
992 ALOGV("%s: tech B", fn);
993 uid.reset(e->NewByteArray(NFC_NFCID0_MAX_LEN));
994 e->SetByteArrayRegion(uid.get(), 0, NFC_NFCID0_MAX_LEN,
995 (jbyte*) &mTechParams [0].param.pb.nfcid0);
996 }
997 else if (NFC_DISCOVERY_TYPE_POLL_F == mTechParams [0].mode
998 || NFC_DISCOVERY_TYPE_POLL_F_ACTIVE == mTechParams [0].mode
999 || NFC_DISCOVERY_TYPE_LISTEN_F == mTechParams [0].mode
1000 || NFC_DISCOVERY_TYPE_LISTEN_F_ACTIVE == mTechParams [0].mode)
1001 {
1002 uid.reset(e->NewByteArray(NFC_NFCID2_LEN));
1003 e->SetByteArrayRegion(uid.get(), 0, NFC_NFCID2_LEN,
1004 (jbyte*) &mTechParams [0].param.pf.nfcid2);
1005 ALOGV("%s: tech F", fn);
1006 }
1007 else if (NFC_DISCOVERY_TYPE_POLL_ISO15693 == mTechParams [0].mode
1008 || NFC_DISCOVERY_TYPE_LISTEN_ISO15693 == mTechParams [0].mode)
1009 {
1010 ALOGV("%s: tech iso 15693", fn);
1011 jbyte data [I93_UID_BYTE_LEN]; //8 bytes
1012 for (int i=0; i<I93_UID_BYTE_LEN; ++i) //reverse the ID
1013 data[i] = activationData.params.i93.uid [I93_UID_BYTE_LEN - i - 1];
1014 uid.reset(e->NewByteArray(I93_UID_BYTE_LEN));
1015 e->SetByteArrayRegion(uid.get(), 0, I93_UID_BYTE_LEN, data);
1016 }
1017 else
1018 {
1019 ALOGE("%s: tech unknown ????", fn);
1020 uid.reset(e->NewByteArray(0));
1021 }
1022 jfieldID f = e->GetFieldID(tag_cls, "mUid", "[B");
1023 e->SetObjectField(tag, f, uid.get());
1024 }
1025
1026
1027 /*******************************************************************************
1028 **
1029 ** Function: isP2pDiscovered
1030 **
1031 ** Description: Does the peer support P2P?
1032 **
1033 ** Returns: True if the peer supports P2P.
1034 **
1035 *******************************************************************************/
isP2pDiscovered()1036 bool NfcTag::isP2pDiscovered ()
1037 {
1038 static const char fn [] = "NfcTag::isP2pDiscovered";
1039 bool retval = false;
1040
1041 for (int i = 0; i < mNumTechList; i++)
1042 {
1043 if (mTechLibNfcTypes[i] == NFA_PROTOCOL_NFC_DEP)
1044 {
1045 //if remote device supports P2P
1046 ALOGV("%s: discovered P2P", fn);
1047 retval = true;
1048 break;
1049 }
1050 }
1051 ALOGV("%s: return=%u", fn, retval);
1052 return retval;
1053 }
1054
1055
1056 /*******************************************************************************
1057 **
1058 ** Function: selectP2p
1059 **
1060 ** Description: Select the preferred P2P technology if there is a choice.
1061 **
1062 ** Returns: None
1063 **
1064 *******************************************************************************/
selectP2p()1065 void NfcTag::selectP2p()
1066 {
1067 static const char fn [] = "NfcTag::selectP2p";
1068 uint8_t rfDiscoveryId = 0;
1069
1070 for (int i = 0; i < mNumTechList; i++)
1071 {
1072 //if remote device does not support P2P, just skip it
1073 if (mTechLibNfcTypes[i] != NFA_PROTOCOL_NFC_DEP)
1074 continue;
1075
1076 //if remote device supports tech F;
1077 //tech F is preferred because it is faster than tech A
1078 if ( (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_F) ||
1079 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_F_ACTIVE) )
1080 {
1081 rfDiscoveryId = mTechHandles[i];
1082 break; //no need to search further
1083 }
1084 else if ( (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) ||
1085 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A_ACTIVE) )
1086 {
1087 //only choose tech A if tech F is unavailable
1088 if (rfDiscoveryId == 0)
1089 rfDiscoveryId = mTechHandles[i];
1090 }
1091 }
1092
1093 if (rfDiscoveryId > 0)
1094 {
1095 ALOGV("%s: select P2P; target rf discov id=0x%X", fn, rfDiscoveryId);
1096 tNFA_STATUS stat = NFA_Select (rfDiscoveryId, NFA_PROTOCOL_NFC_DEP, NFA_INTERFACE_NFC_DEP);
1097 if (stat != NFA_STATUS_OK)
1098 ALOGE("%s: fail select P2P; error=0x%X", fn, stat);
1099 }
1100 else
1101 ALOGE("%s: cannot find P2P", fn);
1102 resetTechnologies ();
1103 }
1104
1105
1106 /*******************************************************************************
1107 **
1108 ** Function: resetTechnologies
1109 **
1110 ** Description: Clear all data related to the technology, protocol of the tag.
1111 **
1112 ** Returns: None
1113 **
1114 *******************************************************************************/
resetTechnologies()1115 void NfcTag::resetTechnologies ()
1116 {
1117 static const char fn [] = "NfcTag::resetTechnologies";
1118 ALOGV("%s", fn);
1119 mNumTechList = 0;
1120 memset (mTechList, 0, sizeof(mTechList));
1121 memset (mTechHandles, 0, sizeof(mTechHandles));
1122 memset (mTechLibNfcTypes, 0, sizeof(mTechLibNfcTypes));
1123 memset (mTechParams, 0, sizeof(mTechParams));
1124 mIsDynamicTagId = false;
1125 mIsFelicaLite = false;
1126 resetAllTransceiveTimeouts ();
1127 }
1128
1129
1130 /*******************************************************************************
1131 **
1132 ** Function: selectFirstTag
1133 **
1134 ** Description: When multiple tags are discovered, just select the first one to activate.
1135 **
1136 ** Returns: None
1137 **
1138 *******************************************************************************/
selectFirstTag()1139 void NfcTag::selectFirstTag ()
1140 {
1141 static const char fn [] = "NfcTag::selectFirstTag";
1142 int foundIdx = -1;
1143 tNFA_INTF_TYPE rf_intf = NFA_INTERFACE_FRAME;
1144
1145 for (int i = 0; i < mNumTechList; i++)
1146 {
1147 ALOGV("%s: nfa target idx=%d h=0x%X; protocol=0x%X",
1148 fn, i, mTechHandles [i], mTechLibNfcTypes [i]);
1149 if (mTechLibNfcTypes[i] != NFA_PROTOCOL_NFC_DEP)
1150 {
1151 foundIdx = i;
1152 break;
1153 }
1154 }
1155
1156 if (foundIdx != -1)
1157 {
1158 if (mTechLibNfcTypes [foundIdx] == NFA_PROTOCOL_ISO_DEP)
1159 {
1160 rf_intf = NFA_INTERFACE_ISO_DEP;
1161 }
1162 else if (mTechLibNfcTypes [foundIdx] == NFA_PROTOCOL_MIFARE)
1163 {
1164 rf_intf = NFA_INTERFACE_MIFARE;
1165 }
1166 else
1167 rf_intf = NFA_INTERFACE_FRAME;
1168
1169 tNFA_STATUS stat = NFA_Select (mTechHandles [foundIdx], mTechLibNfcTypes [foundIdx], rf_intf);
1170 if (stat != NFA_STATUS_OK)
1171 ALOGE("%s: fail select; error=0x%X", fn, stat);
1172 }
1173 else
1174 ALOGE("%s: only found NFC-DEP technology.", fn);
1175 }
1176
1177
1178 /*******************************************************************************
1179 **
1180 ** Function: getT1tMaxMessageSize
1181 **
1182 ** Description: Get the maximum size (octet) that a T1T can store.
1183 **
1184 ** Returns: Maximum size in octets.
1185 **
1186 *******************************************************************************/
getT1tMaxMessageSize()1187 int NfcTag::getT1tMaxMessageSize ()
1188 {
1189 static const char fn [] = "NfcTag::getT1tMaxMessageSize";
1190
1191 if (mProtocol != NFC_PROTOCOL_T1T)
1192 {
1193 ALOGE("%s: wrong protocol %u", fn, mProtocol);
1194 return 0;
1195 }
1196 return mtT1tMaxMessageSize;
1197 }
1198
1199
1200 /*******************************************************************************
1201 **
1202 ** Function: calculateT1tMaxMessageSize
1203 **
1204 ** Description: Calculate type-1 tag's max message size based on header ROM bytes.
1205 ** activate: reference to activation data.
1206 **
1207 ** Returns: None
1208 **
1209 *******************************************************************************/
calculateT1tMaxMessageSize(tNFA_ACTIVATED & activate)1210 void NfcTag::calculateT1tMaxMessageSize (tNFA_ACTIVATED& activate)
1211 {
1212 static const char fn [] = "NfcTag::calculateT1tMaxMessageSize";
1213
1214 //make sure the tag is type-1
1215 if (activate.activate_ntf.protocol != NFC_PROTOCOL_T1T)
1216 {
1217 mtT1tMaxMessageSize = 0;
1218 return;
1219 }
1220
1221 //examine the first byte of header ROM bytes
1222 switch (activate.params.t1t.hr[0])
1223 {
1224 case RW_T1T_IS_TOPAZ96:
1225 mtT1tMaxMessageSize = 90;
1226 break;
1227 case RW_T1T_IS_TOPAZ512:
1228 mtT1tMaxMessageSize = 462;
1229 break;
1230 default:
1231 ALOGE("%s: unknown T1T HR0=%u", fn, activate.params.t1t.hr[0]);
1232 mtT1tMaxMessageSize = 0;
1233 break;
1234 }
1235 }
1236
1237
1238 /*******************************************************************************
1239 **
1240 ** Function: isMifareUltralight
1241 **
1242 ** Description: Whether the currently activated tag is Mifare Ultralight.
1243 **
1244 ** Returns: True if tag is Mifare Ultralight.
1245 **
1246 *******************************************************************************/
isMifareUltralight()1247 bool NfcTag::isMifareUltralight ()
1248 {
1249 static const char fn [] = "NfcTag::isMifareUltralight";
1250 bool retval = false;
1251
1252 for (int i =0; i < mNumTechList; i++)
1253 {
1254 if (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A)
1255 {
1256 //see NFC Digital Protocol, section 4.6.3 (SENS_RES); section 4.8.2 (SEL_RES).
1257 //see "MF0ICU1 Functional specification MIFARE Ultralight", Rev. 3.4 - 4 February 2008,
1258 //section 6.7.
1259 if ( (mTechParams[i].param.pa.sens_res[0] == 0x44) &&
1260 (mTechParams[i].param.pa.sens_res[1] == 0) &&
1261 ( (mTechParams[i].param.pa.sel_rsp == 0) || (mTechParams[i].param.pa.sel_rsp == 0x04) ) &&
1262 (mTechParams[i].param.pa.nfcid1[0] == 0x04) )
1263 {
1264 retval = true;
1265 }
1266 break;
1267 }
1268 }
1269 ALOGV("%s: return=%u", fn, retval);
1270 return retval;
1271 }
1272
1273
1274 /*******************************************************************************
1275 **
1276 ** Function: isMifareDESFire
1277 **
1278 ** Description: Whether the currently activated tag is Mifare DESFire.
1279 **
1280 ** Returns: True if tag is Mifare DESFire.
1281 **
1282 *******************************************************************************/
isMifareDESFire()1283 bool NfcTag::isMifareDESFire ()
1284 {
1285 static const char fn [] = "NfcTag::isMifareDESFire";
1286 bool retval = false;
1287
1288 for (int i =0; i < mNumTechList; i++)
1289 {
1290 if ( (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) ||
1291 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_A) ||
1292 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE) )
1293 {
1294 /* DESfire has one sak byte and 2 ATQA bytes */
1295 if ( (mTechParams[i].param.pa.sens_res[0] == 0x44) &&
1296 (mTechParams[i].param.pa.sens_res[1] == 0x03) &&
1297 (mTechParams[i].param.pa.sel_rsp == 0x20) )
1298 {
1299 retval = true;
1300 }
1301 break;
1302 }
1303 }
1304
1305 ALOGV("%s: return=%u", fn, retval);
1306 return retval;
1307 }
1308
1309
1310 /*******************************************************************************
1311 **
1312 ** Function: isFelicaLite
1313 **
1314 ** Description: Whether the currently activated tag is Felica Lite.
1315 **
1316 ** Returns: True if tag is Felica Lite.
1317 **
1318 *******************************************************************************/
1319
isFelicaLite()1320 bool NfcTag::isFelicaLite ()
1321 {
1322 return mIsFelicaLite;
1323 }
1324
1325
1326 /*******************************************************************************
1327 **
1328 ** Function: isT2tNackResponse
1329 **
1330 ** Description: Whether the response is a T2T NACK response.
1331 ** See NFC Digital Protocol Technical Specification (2010-11-17).
1332 ** Chapter 9 (Type 2 Tag Platform), section 9.6 (READ).
1333 ** response: buffer contains T2T response.
1334 ** responseLen: length of the response.
1335 **
1336 ** Returns: True if the response is NACK
1337 **
1338 *******************************************************************************/
isT2tNackResponse(const uint8_t * response,uint32_t responseLen)1339 bool NfcTag::isT2tNackResponse (const uint8_t* response, uint32_t responseLen)
1340 {
1341 static const char fn [] = "NfcTag::isT2tNackResponse";
1342 bool isNack = false;
1343
1344 if (responseLen == 1)
1345 {
1346 if (response[0] == 0xA)
1347 isNack = false; //an ACK response, so definitely not a NACK
1348 else
1349 isNack = true; //assume every value is a NACK
1350 }
1351 ALOGV("%s: return %u", fn, isNack);
1352 return isNack;
1353 }
1354
1355
1356 /*******************************************************************************
1357 **
1358 ** Function: isNdefDetectionTimedOut
1359 **
1360 ** Description: Whether NDEF-detection algorithm timed out.
1361 **
1362 ** Returns: True if NDEF-detection algorithm timed out.
1363 **
1364 *******************************************************************************/
isNdefDetectionTimedOut()1365 bool NfcTag::isNdefDetectionTimedOut ()
1366 {
1367 return mNdefDetectionTimedOut;
1368 }
1369
1370
1371 /*******************************************************************************
1372 **
1373 ** Function: connectionEventHandler
1374 **
1375 ** Description: Handle connection-related events.
1376 ** event: event code.
1377 ** data: pointer to event data.
1378 **
1379 ** Returns: None
1380 **
1381 *******************************************************************************/
connectionEventHandler(uint8_t event,tNFA_CONN_EVT_DATA * data)1382 void NfcTag::connectionEventHandler (uint8_t event, tNFA_CONN_EVT_DATA* data)
1383 {
1384 static const char fn [] = "NfcTag::connectionEventHandler";
1385
1386 switch (event)
1387 {
1388 case NFA_DISC_RESULT_EVT:
1389 {
1390 tNFA_DISC_RESULT& disc_result = data->disc_result;
1391 if (disc_result.status == NFA_STATUS_OK)
1392 {
1393 discoverTechnologies (disc_result);
1394 }
1395 }
1396 break;
1397
1398 case NFA_ACTIVATED_EVT:
1399 // Only do tag detection if we are polling and it is not 'EE Direct RF' activation
1400 // (which may happen when we are activated as a tag).
1401 if (data->activated.activate_ntf.rf_tech_param.mode < NCI_DISCOVERY_TYPE_LISTEN_A
1402 && data->activated.activate_ntf.intf_param.type != NFC_INTERFACE_EE_DIRECT_RF)
1403 {
1404 tNFA_ACTIVATED& activated = data->activated;
1405 if (IsSameKovio(activated))
1406 break;
1407 mIsActivated = true;
1408 mProtocol = activated.activate_ntf.protocol;
1409 calculateT1tMaxMessageSize (activated);
1410 discoverTechnologies (activated);
1411 createNativeNfcTag (activated);
1412 }
1413 break;
1414
1415 case NFA_DEACTIVATED_EVT:
1416 mIsActivated = false;
1417 mProtocol = NFC_PROTOCOL_UNKNOWN;
1418 resetTechnologies ();
1419 break;
1420
1421 case NFA_READ_CPLT_EVT:
1422 {
1423 SyncEventGuard g (mReadCompleteEvent);
1424 mReadCompletedStatus = data->status;
1425 mNdefDetectionTimedOut = data->status != NFA_STATUS_OK;
1426 if (mNdefDetectionTimedOut)
1427 ALOGE("%s: NDEF detection timed out", fn);
1428 mReadCompleteEvent.notifyOne ();
1429 }
1430 break;
1431
1432 case NFA_NDEF_DETECT_EVT:
1433 {
1434 tNFA_NDEF_DETECT& ndef_detect = data->ndef_detect;
1435 mNdefDetectionTimedOut = ndef_detect.status == NFA_STATUS_TIMEOUT;
1436 if (mNdefDetectionTimedOut)
1437 ALOGE("%s: NDEF detection timed out", fn);
1438 }
1439 }
1440 }
1441
1442
1443 /*******************************************************************************
1444 **
1445 ** Function setActive
1446 **
1447 ** Description Sets the active state for the object
1448 **
1449 ** Returns None.
1450 **
1451 *******************************************************************************/
setActive(bool active)1452 void NfcTag::setActive(bool active)
1453 {
1454 mIsActivated = active;
1455 }
1456
1457
1458 /*******************************************************************************
1459 **
1460 ** Function: isDynamicTagId
1461 **
1462 ** Description: Whether a tag has a dynamic tag ID.
1463 **
1464 ** Returns: True if ID is dynamic.
1465 **
1466 *******************************************************************************/
isDynamicTagId()1467 bool NfcTag::isDynamicTagId ()
1468 {
1469 return mIsDynamicTagId &&
1470 (mTechList [0] == TARGET_TYPE_ISO14443_4) && //type-4 tag
1471 (mTechList [1] == TARGET_TYPE_ISO14443_3A); //tech A
1472 }
1473
1474
1475 /*******************************************************************************
1476 **
1477 ** Function: resetAllTransceiveTimeouts
1478 **
1479 ** Description: Reset all timeouts for all technologies to default values.
1480 **
1481 ** Returns: none
1482 **
1483 *******************************************************************************/
resetAllTransceiveTimeouts()1484 void NfcTag::resetAllTransceiveTimeouts ()
1485 {
1486 mTechnologyTimeoutsTable [TARGET_TYPE_ISO14443_3A] = 618; //NfcA
1487 mTechnologyTimeoutsTable [TARGET_TYPE_ISO14443_3B] = 1000; //NfcB
1488 mTechnologyTimeoutsTable [TARGET_TYPE_ISO14443_4] = 618; //ISO-DEP
1489 mTechnologyTimeoutsTable [TARGET_TYPE_FELICA] = 255; //Felica
1490 mTechnologyTimeoutsTable [TARGET_TYPE_ISO15693] = 1000;//NfcV
1491 mTechnologyTimeoutsTable [TARGET_TYPE_NDEF] = 1000;
1492 mTechnologyTimeoutsTable [TARGET_TYPE_NDEF_FORMATABLE] = 1000;
1493 mTechnologyTimeoutsTable [TARGET_TYPE_MIFARE_CLASSIC] = 618; //MifareClassic
1494 mTechnologyTimeoutsTable [TARGET_TYPE_MIFARE_UL] = 618; //MifareUltralight
1495 mTechnologyTimeoutsTable [TARGET_TYPE_KOVIO_BARCODE] = 1000; //NfcBarcode
1496 }
1497
1498 /*******************************************************************************
1499 **
1500 ** Function: getTransceiveTimeout
1501 **
1502 ** Description: Get the timeout value for one technology.
1503 ** techId: one of the values in TARGET_TYPE_* defined in NfcJniUtil.h
1504 **
1505 ** Returns: Timeout value in millisecond.
1506 **
1507 *******************************************************************************/
getTransceiveTimeout(int techId)1508 int NfcTag::getTransceiveTimeout (int techId)
1509 {
1510 static const char fn [] = "NfcTag::getTransceiveTimeout";
1511 int retval = 1000;
1512 if ((techId > 0) && (techId < (int) mTechnologyTimeoutsTable.size()))
1513 retval = mTechnologyTimeoutsTable [techId];
1514 else
1515 ALOGE("%s: invalid tech=%d", fn, techId);
1516 return retval;
1517 }
1518
1519
1520 /*******************************************************************************
1521 **
1522 ** Function: setTransceiveTimeout
1523 **
1524 ** Description: Set the timeout value for one technology.
1525 ** techId: one of the values in TARGET_TYPE_* defined in NfcJniUtil.h
1526 ** timeout: timeout value in millisecond.
1527 **
1528 ** Returns: Timeout value.
1529 **
1530 *******************************************************************************/
setTransceiveTimeout(int techId,int timeout)1531 void NfcTag::setTransceiveTimeout (int techId, int timeout)
1532 {
1533 static const char fn [] = "NfcTag::setTransceiveTimeout";
1534 if ((techId >= 0) && (techId < (int) mTechnologyTimeoutsTable.size()))
1535 mTechnologyTimeoutsTable [techId] = timeout;
1536 else
1537 ALOGE("%s: invalid tech=%d", fn, techId);
1538 }
1539
1540
1541 /*******************************************************************************
1542 **
1543 ** Function: getPresenceCheckAlgorithm
1544 **
1545 ** Description: Get presence-check algorithm from .conf file.
1546 **
1547 ** Returns: Presence-check algorithm.
1548 **
1549 *******************************************************************************/
getPresenceCheckAlgorithm()1550 tNFA_RW_PRES_CHK_OPTION NfcTag::getPresenceCheckAlgorithm ()
1551 {
1552 return mPresenceCheckAlgorithm;
1553 }
1554
1555
1556 /*******************************************************************************
1557 **
1558 ** Function: isInfineonMyDMove
1559 **
1560 ** Description: Whether the currently activated tag is Infineon My-D Move.
1561 **
1562 ** Returns: True if tag is Infineon My-D Move.
1563 **
1564 *******************************************************************************/
isInfineonMyDMove()1565 bool NfcTag::isInfineonMyDMove ()
1566 {
1567 static const char fn [] = "NfcTag::isInfineonMyDMove";
1568 bool retval = false;
1569
1570 for (int i =0; i < mNumTechList; i++)
1571 {
1572 if (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A)
1573 {
1574 //see Infineon my-d move, my-d move NFC, SLE 66R01P, SLE 66R01PN,
1575 //Short Product Information, 2011-11-24, section 3.5
1576 if (mTechParams[i].param.pa.nfcid1[0] == 0x05)
1577 {
1578 uint8_t highNibble = mTechParams[i].param.pa.nfcid1[1] & 0xF0;
1579 if (highNibble == 0x30)
1580 retval = true;
1581 }
1582 break;
1583 }
1584 }
1585 ALOGV("%s: return=%u", fn, retval);
1586 return retval;
1587 }
1588
1589
1590 /*******************************************************************************
1591 **
1592 ** Function: isKovioType2Tag
1593 **
1594 ** Description: Whether the currently activated tag is Kovio Type-2 tag.
1595 **
1596 ** Returns: True if tag is Kovio Type-2 tag.
1597 **
1598 *******************************************************************************/
isKovioType2Tag()1599 bool NfcTag::isKovioType2Tag ()
1600 {
1601 static const char fn [] = "NfcTag::isKovioType2Tag";
1602 bool retval = false;
1603
1604 for (int i =0; i < mNumTechList; i++)
1605 {
1606 if (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A)
1607 {
1608 //Kovio 2Kb RFID Tag, Functional Specification,
1609 //March 2, 2012, v2.0, section 8.3.
1610 if (mTechParams[i].param.pa.nfcid1[0] == 0x37)
1611 retval = true;
1612 break;
1613 }
1614 }
1615 ALOGV("%s: return=%u", fn, retval);
1616 return retval;
1617 }
1618