1 /*
2 * Copyright (C) 2010 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 <stdlib.h>
18
19 #include "errno.h"
20 #include "com_android_nfc.h"
21 #include "com_android_nfc_list.h"
22 #include "phLibNfcStatus.h"
23
24 /*
25 * JNI Initialization
26 */
JNI_OnLoad(JavaVM * jvm,void * reserved)27 jint JNI_OnLoad(JavaVM *jvm, void *reserved)
28 {
29 JNIEnv *e;
30
31 LOGD("NFC Service : loading JNI\n");
32
33 // Check JNI version
34 if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6))
35 return JNI_ERR;
36
37 android::vm = jvm;
38
39 if (android::register_com_android_nfc_NativeNfcManager(e) == -1)
40 return JNI_ERR;
41 if (android::register_com_android_nfc_NativeNfcTag(e) == -1)
42 return JNI_ERR;
43 if (android::register_com_android_nfc_NativeP2pDevice(e) == -1)
44 return JNI_ERR;
45 if (android::register_com_android_nfc_NativeLlcpSocket(e) == -1)
46 return JNI_ERR;
47 if (android::register_com_android_nfc_NativeLlcpConnectionlessSocket(e) == -1)
48 return JNI_ERR;
49 if (android::register_com_android_nfc_NativeLlcpServiceSocket(e) == -1)
50 return JNI_ERR;
51 if (android::register_com_android_nfc_NativeNfcSecureElement(e) == -1)
52 return JNI_ERR;
53
54 return JNI_VERSION_1_6;
55 }
56
57 namespace android {
58
59 extern struct nfc_jni_native_data *exported_nat;
60
61 JavaVM *vm;
62
63 /*
64 * JNI Utils
65 */
nfc_get_env()66 JNIEnv *nfc_get_env()
67 {
68 JNIEnv *e;
69 if (vm->GetEnv((void **)&e, JNI_VERSION_1_6) != JNI_OK) {
70 LOGE("Current thread is not attached to VM");
71 abort();
72 }
73 return e;
74 }
75
nfc_cb_data_init(nfc_jni_callback_data * pCallbackData,void * pContext)76 bool nfc_cb_data_init(nfc_jni_callback_data* pCallbackData, void* pContext)
77 {
78 /* Create semaphore */
79 if(sem_init(&pCallbackData->sem, 0, 0) == -1)
80 {
81 LOGE("Semaphore creation failed (errno=0x%08x)", errno);
82 return false;
83 }
84
85 /* Set default status value */
86 pCallbackData->status = NFCSTATUS_FAILED;
87
88 /* Copy the context */
89 pCallbackData->pContext = pContext;
90
91 /* Add to active semaphore list */
92 if (!listAdd(&nfc_jni_get_monitor()->sem_list, pCallbackData))
93 {
94 LOGE("Failed to add the semaphore to the list");
95 }
96
97 return true;
98 }
99
nfc_cb_data_deinit(nfc_jni_callback_data * pCallbackData)100 void nfc_cb_data_deinit(nfc_jni_callback_data* pCallbackData)
101 {
102 /* Destroy semaphore */
103 if (sem_destroy(&pCallbackData->sem))
104 {
105 LOGE("Failed to destroy semaphore (errno=0x%08x)", errno);
106 }
107
108 /* Remove from active semaphore list */
109 if (!listRemove(&nfc_jni_get_monitor()->sem_list, pCallbackData))
110 {
111 LOGE("Failed to remove semaphore from the list");
112 }
113
114 }
115
nfc_cb_data_releaseAll()116 void nfc_cb_data_releaseAll()
117 {
118 nfc_jni_callback_data* pCallbackData;
119
120 while (listGetAndRemoveNext(&nfc_jni_get_monitor()->sem_list, (void**)&pCallbackData))
121 {
122 pCallbackData->status = NFCSTATUS_FAILED;
123 sem_post(&pCallbackData->sem);
124 }
125 }
126
nfc_jni_cache_object(JNIEnv * e,const char * clsname,jobject * cached_obj)127 int nfc_jni_cache_object(JNIEnv *e, const char *clsname,
128 jobject *cached_obj)
129 {
130 jclass cls;
131 jobject obj;
132 jmethodID ctor;
133
134 cls = e->FindClass(clsname);
135 if(cls == NULL)
136 {
137 return -1;
138 LOGD("Find class error\n");
139 }
140
141
142 ctor = e->GetMethodID(cls, "<init>", "()V");
143
144 obj = e->NewObject(cls, ctor);
145 if(obj == NULL)
146 {
147 return -1;
148 LOGD("Create object error\n");
149 }
150
151 *cached_obj = e->NewGlobalRef(obj);
152 if(*cached_obj == NULL)
153 {
154 e->DeleteLocalRef(obj);
155 LOGD("Global ref error\n");
156 return -1;
157 }
158
159 e->DeleteLocalRef(obj);
160
161 return 0;
162 }
163
164
nfc_jni_get_nat(JNIEnv * e,jobject o)165 struct nfc_jni_native_data* nfc_jni_get_nat(JNIEnv *e, jobject o)
166 {
167 jclass c;
168 jfieldID f;
169
170 /* Retrieve native structure address */
171 c = e->GetObjectClass(o);
172 f = e->GetFieldID(c, "mNative", "I");
173 return (struct nfc_jni_native_data*)e->GetIntField(o, f);
174 }
175
nfc_jni_get_nat_ext(JNIEnv * e)176 struct nfc_jni_native_data* nfc_jni_get_nat_ext(JNIEnv *e)
177 {
178 return exported_nat;
179 }
180
181 static nfc_jni_native_monitor_t *nfc_jni_native_monitor = NULL;
182
nfc_jni_init_monitor(void)183 nfc_jni_native_monitor_t* nfc_jni_init_monitor(void)
184 {
185
186 pthread_mutexattr_t recursive_attr;
187
188 pthread_mutexattr_init(&recursive_attr);
189 pthread_mutexattr_settype(&recursive_attr, PTHREAD_MUTEX_RECURSIVE_NP);
190
191 if(nfc_jni_native_monitor == NULL)
192 {
193 nfc_jni_native_monitor = (nfc_jni_native_monitor_t*)malloc(sizeof(nfc_jni_native_monitor_t));
194 }
195
196 if(nfc_jni_native_monitor != NULL)
197 {
198 memset(nfc_jni_native_monitor, 0, sizeof(nfc_jni_native_monitor_t));
199
200 if(pthread_mutex_init(&nfc_jni_native_monitor->reentrance_mutex, &recursive_attr) == -1)
201 {
202 LOGE("NFC Manager Reentrance Mutex creation returned 0x%08x", errno);
203 return NULL;
204 }
205
206 if(pthread_mutex_init(&nfc_jni_native_monitor->concurrency_mutex, NULL) == -1)
207 {
208 LOGE("NFC Manager Concurrency Mutex creation returned 0x%08x", errno);
209 return NULL;
210 }
211
212 if(!listInit(&nfc_jni_native_monitor->sem_list))
213 {
214 LOGE("NFC Manager Semaphore List creation failed");
215 return NULL;
216 }
217
218 LIST_INIT(&nfc_jni_native_monitor->incoming_socket_head);
219
220 if(pthread_mutex_init(&nfc_jni_native_monitor->incoming_socket_mutex, NULL) == -1)
221 {
222 LOGE("NFC Manager incoming socket mutex creation returned 0x%08x", errno);
223 return NULL;
224 }
225
226 if(pthread_cond_init(&nfc_jni_native_monitor->incoming_socket_cond, NULL) == -1)
227 {
228 LOGE("NFC Manager incoming socket condition creation returned 0x%08x", errno);
229 return NULL;
230 }
231
232 }
233
234 return nfc_jni_native_monitor;
235 }
236
nfc_jni_get_monitor(void)237 nfc_jni_native_monitor_t* nfc_jni_get_monitor(void)
238 {
239 return nfc_jni_native_monitor;
240 }
241
242
nfc_jni_get_p2p_device_handle(JNIEnv * e,jobject o)243 phLibNfc_Handle nfc_jni_get_p2p_device_handle(JNIEnv *e, jobject o)
244 {
245 jclass c;
246 jfieldID f;
247
248 c = e->GetObjectClass(o);
249 f = e->GetFieldID(c, "mHandle", "I");
250
251 return e->GetIntField(o, f);
252 }
253
nfc_jni_get_p2p_device_mode(JNIEnv * e,jobject o)254 jshort nfc_jni_get_p2p_device_mode(JNIEnv *e, jobject o)
255 {
256 jclass c;
257 jfieldID f;
258
259 c = e->GetObjectClass(o);
260 f = e->GetFieldID(c, "mMode", "S");
261
262 return e->GetShortField(o, f);
263 }
264
265
nfc_jni_get_connected_tech_index(JNIEnv * e,jobject o)266 int nfc_jni_get_connected_tech_index(JNIEnv *e, jobject o)
267 {
268
269 jclass c;
270 jfieldID f;
271
272 c = e->GetObjectClass(o);
273 f = e->GetFieldID(c, "mConnectedTechnology", "I");
274
275 return e->GetIntField(o, f);
276
277 }
278
nfc_jni_get_connected_technology(JNIEnv * e,jobject o)279 jint nfc_jni_get_connected_technology(JNIEnv *e, jobject o)
280 {
281 jclass c;
282 jfieldID f;
283 int connectedTech = -1;
284
285 int connectedTechIndex = nfc_jni_get_connected_tech_index(e,o);
286 jintArray techTypes = nfc_jni_get_nfc_tag_type(e, o);
287
288 if ((connectedTechIndex != -1) && (techTypes != NULL) &&
289 (connectedTechIndex < e->GetArrayLength(techTypes))) {
290 jint* technologies = e->GetIntArrayElements(techTypes, 0);
291 if (technologies != NULL) {
292 connectedTech = technologies[connectedTechIndex];
293 e->ReleaseIntArrayElements(techTypes, technologies, JNI_ABORT);
294 }
295 }
296
297 return connectedTech;
298
299 }
300
nfc_jni_get_connected_technology_libnfc_type(JNIEnv * e,jobject o)301 jint nfc_jni_get_connected_technology_libnfc_type(JNIEnv *e, jobject o)
302 {
303 jclass c;
304 jfieldID f;
305 jint connectedLibNfcType = -1;
306
307 int connectedTechIndex = nfc_jni_get_connected_tech_index(e,o);
308 c = e->GetObjectClass(o);
309 f = e->GetFieldID(c, "mTechLibNfcTypes", "[I");
310 jintArray libNfcTypes = (jintArray) e->GetObjectField(o, f);
311
312 if ((connectedTechIndex != -1) && (libNfcTypes != NULL) &&
313 (connectedTechIndex < e->GetArrayLength(libNfcTypes))) {
314 jint* types = e->GetIntArrayElements(libNfcTypes, 0);
315 if (types != NULL) {
316 connectedLibNfcType = types[connectedTechIndex];
317 e->ReleaseIntArrayElements(libNfcTypes, types, JNI_ABORT);
318 }
319 }
320 return connectedLibNfcType;
321
322 }
323
nfc_jni_get_connected_handle(JNIEnv * e,jobject o)324 phLibNfc_Handle nfc_jni_get_connected_handle(JNIEnv *e, jobject o)
325 {
326 jclass c;
327 jfieldID f;
328 phLibNfc_Handle connectedHandle = -1;
329
330 int connectedTechIndex = nfc_jni_get_connected_tech_index(e,o);
331 c = e->GetObjectClass(o);
332 f = e->GetFieldID(c, "mTechHandles", "[I");
333 jintArray techHandles = (jintArray) e->GetObjectField(o, f);
334
335 if ((connectedTechIndex != -1) && (techHandles != NULL) &&
336 (connectedTechIndex < e->GetArrayLength(techHandles))) {
337 jint* handles = e->GetIntArrayElements(techHandles, 0);
338 if (handles != NULL) {
339 connectedHandle = handles[connectedTechIndex];
340 e->ReleaseIntArrayElements(techHandles, handles, JNI_ABORT);
341 }
342 }
343 return connectedHandle;
344
345 }
346
nfc_jni_get_nfc_socket_handle(JNIEnv * e,jobject o)347 phLibNfc_Handle nfc_jni_get_nfc_socket_handle(JNIEnv *e, jobject o)
348 {
349 jclass c;
350 jfieldID f;
351
352 c = e->GetObjectClass(o);
353 f = e->GetFieldID(c, "mHandle", "I");
354
355 return e->GetIntField(o, f);
356 }
357
nfc_jni_get_nfc_tag_type(JNIEnv * e,jobject o)358 jintArray nfc_jni_get_nfc_tag_type(JNIEnv *e, jobject o)
359 {
360 jclass c;
361 jfieldID f;
362 jintArray techtypes;
363
364 c = e->GetObjectClass(o);
365 f = e->GetFieldID(c, "mTechList","[I");
366
367 /* Read the techtypes */
368 techtypes = (jintArray) e->GetObjectField(o, f);
369
370 return techtypes;
371 }
372
373
374
375 //Display status code
nfc_jni_get_status_name(NFCSTATUS status)376 const char* nfc_jni_get_status_name(NFCSTATUS status)
377 {
378 #define STATUS_ENTRY(status) { status, #status }
379
380 struct status_entry {
381 NFCSTATUS code;
382 const char *name;
383 };
384
385 const struct status_entry sNameTable[] = {
386 STATUS_ENTRY(NFCSTATUS_SUCCESS),
387 STATUS_ENTRY(NFCSTATUS_FAILED),
388 STATUS_ENTRY(NFCSTATUS_INVALID_PARAMETER),
389 STATUS_ENTRY(NFCSTATUS_INSUFFICIENT_RESOURCES),
390 STATUS_ENTRY(NFCSTATUS_TARGET_LOST),
391 STATUS_ENTRY(NFCSTATUS_INVALID_HANDLE),
392 STATUS_ENTRY(NFCSTATUS_MULTIPLE_TAGS),
393 STATUS_ENTRY(NFCSTATUS_ALREADY_REGISTERED),
394 STATUS_ENTRY(NFCSTATUS_FEATURE_NOT_SUPPORTED),
395 STATUS_ENTRY(NFCSTATUS_SHUTDOWN),
396 STATUS_ENTRY(NFCSTATUS_ABORTED),
397 STATUS_ENTRY(NFCSTATUS_REJECTED ),
398 STATUS_ENTRY(NFCSTATUS_NOT_INITIALISED),
399 STATUS_ENTRY(NFCSTATUS_PENDING),
400 STATUS_ENTRY(NFCSTATUS_BUFFER_TOO_SMALL),
401 STATUS_ENTRY(NFCSTATUS_ALREADY_INITIALISED),
402 STATUS_ENTRY(NFCSTATUS_BUSY),
403 STATUS_ENTRY(NFCSTATUS_TARGET_NOT_CONNECTED),
404 STATUS_ENTRY(NFCSTATUS_MULTIPLE_PROTOCOLS),
405 STATUS_ENTRY(NFCSTATUS_DESELECTED),
406 STATUS_ENTRY(NFCSTATUS_INVALID_DEVICE),
407 STATUS_ENTRY(NFCSTATUS_MORE_INFORMATION),
408 STATUS_ENTRY(NFCSTATUS_RF_TIMEOUT),
409 STATUS_ENTRY(NFCSTATUS_RF_ERROR),
410 STATUS_ENTRY(NFCSTATUS_BOARD_COMMUNICATION_ERROR),
411 STATUS_ENTRY(NFCSTATUS_INVALID_STATE),
412 STATUS_ENTRY(NFCSTATUS_NOT_REGISTERED),
413 STATUS_ENTRY(NFCSTATUS_RELEASED),
414 STATUS_ENTRY(NFCSTATUS_NOT_ALLOWED),
415 STATUS_ENTRY(NFCSTATUS_INVALID_REMOTE_DEVICE),
416 STATUS_ENTRY(NFCSTATUS_SMART_TAG_FUNC_NOT_SUPPORTED),
417 STATUS_ENTRY(NFCSTATUS_READ_FAILED),
418 STATUS_ENTRY(NFCSTATUS_WRITE_FAILED),
419 STATUS_ENTRY(NFCSTATUS_NO_NDEF_SUPPORT),
420 STATUS_ENTRY(NFCSTATUS_EOF_NDEF_CONTAINER_REACHED),
421 STATUS_ENTRY(NFCSTATUS_INVALID_RECEIVE_LENGTH),
422 STATUS_ENTRY(NFCSTATUS_INVALID_FORMAT),
423 STATUS_ENTRY(NFCSTATUS_INSUFFICIENT_STORAGE),
424 STATUS_ENTRY(NFCSTATUS_FORMAT_ERROR),
425 };
426
427 int i = sizeof(sNameTable)/sizeof(status_entry);
428
429 while(i>0)
430 {
431 i--;
432 if (sNameTable[i].code == PHNFCSTATUS(status))
433 {
434 return sNameTable[i].name;
435 }
436 }
437
438 return "UNKNOWN";
439 }
440
addTechIfNeeded(int * techList,int * handleList,int * typeList,int listSize,int maxListSize,int techToAdd,int handleToAdd,int typeToAdd)441 int addTechIfNeeded(int *techList, int* handleList, int* typeList, int listSize,
442 int maxListSize, int techToAdd, int handleToAdd, int typeToAdd) {
443 bool found = false;
444 for (int i = 0; i < listSize; i++) {
445 if (techList[i] == techToAdd) {
446 found = true;
447 break;
448 }
449 }
450 if (!found && listSize < maxListSize) {
451 techList[listSize] = techToAdd;
452 handleList[listSize] = handleToAdd;
453 typeList[listSize] = typeToAdd;
454 return listSize + 1;
455 }
456 else {
457 return listSize;
458 }
459 }
460
461
462 #define MAX_NUM_TECHNOLOGIES 32
463
464 /*
465 * Utility to get a technology tree and a corresponding handle list from a detected tag.
466 */
nfc_jni_get_technology_tree(JNIEnv * e,phLibNfc_RemoteDevList_t * devList,uint8_t count,jintArray * techList,jintArray * handleList,jintArray * libnfcTypeList)467 void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList,
468 uint8_t count, jintArray* techList, jintArray* handleList,
469 jintArray* libnfcTypeList)
470 {
471 int technologies[MAX_NUM_TECHNOLOGIES];
472 int handles[MAX_NUM_TECHNOLOGIES];
473 int libnfctypes[MAX_NUM_TECHNOLOGIES];
474
475 int index = 0;
476 // TODO: This counts from up to down because on multi-protocols, the
477 // ISO handle is usually the second, and we prefer the ISO. Should implement
478 // a method to find the "preferred handle order" and use that instead,
479 // since we shouldn't have dependencies on the tech list ordering.
480 for (int target = count - 1; target >= 0; target--) {
481 int type = devList[target].psRemoteDevInfo->RemDevType;
482 int handle = devList[target].hTargetDev;
483 switch (type)
484 {
485 case phNfc_eISO14443_A_PICC:
486 case phNfc_eISO14443_4A_PICC:
487 {
488 index = addTechIfNeeded(technologies, handles, libnfctypes, index,
489 MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_4, handle, type);
490 index = addTechIfNeeded(technologies, handles, libnfctypes, index,
491 MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3A, handle, type);
492 break;
493 }
494 case phNfc_eISO14443_4B_PICC:
495 {
496 index = addTechIfNeeded(technologies, handles, libnfctypes, index,
497 MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_4, handle, type);
498 index = addTechIfNeeded(technologies, handles, libnfctypes, index,
499 MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3B, handle, type);
500 }break;
501 case phNfc_eISO14443_3A_PICC:
502 {
503 index = addTechIfNeeded(technologies, handles, libnfctypes,
504 index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3A, handle, type);
505 }break;
506 case phNfc_eISO14443_B_PICC:
507 {
508 // TODO a bug in libnfc will cause 14443-3B only cards
509 // to be returned as this type as well, but these cards
510 // are very rare. Hence assume it's -4B
511 index = addTechIfNeeded(technologies, handles, libnfctypes,
512 index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_4, handle, type);
513 index = addTechIfNeeded(technologies, handles, libnfctypes,
514 index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3B, handle, type);
515 }break;
516 case phNfc_eISO15693_PICC:
517 {
518 index = addTechIfNeeded(technologies, handles, libnfctypes,
519 index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO15693, handle, type);
520 }break;
521 case phNfc_eMifare_PICC:
522 {
523 // We don't want to be too clever here; libnfc has already determined
524 // it's a Mifare, so we only check for UL, for all other tags
525 // we assume it's a mifare classic. This should make us more
526 // future-proof.
527 int sak = devList[target].psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak;
528 switch(sak)
529 {
530 case 0x00:
531 // could be UL or UL-C
532 index = addTechIfNeeded(technologies, handles, libnfctypes,
533 index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_MIFARE_UL, handle, type);
534 index = addTechIfNeeded(technologies, handles, libnfctypes,
535 index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3A, handle, type);
536 break;
537 default:
538 index = addTechIfNeeded(technologies, handles, libnfctypes,
539 index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_MIFARE_CLASSIC, handle, type);
540 index = addTechIfNeeded(technologies, handles, libnfctypes,
541 index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3A, handle, type);
542 break;
543 }
544 }break;
545 case phNfc_eFelica_PICC:
546 {
547 index = addTechIfNeeded(technologies, handles, libnfctypes,
548 index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_FELICA, handle, type);
549 }break;
550 case phNfc_eJewel_PICC:
551 {
552 // Jewel represented as NfcA
553 index = addTechIfNeeded(technologies, handles, libnfctypes,
554 index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3A, handle, type);
555 }break;
556 default:
557 {
558 index = addTechIfNeeded(technologies, handles, libnfctypes,
559 index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_UNKNOWN, handle, type);
560 }
561 }
562 }
563
564 // Build the Java arrays
565 if (techList != NULL) {
566 *techList = e->NewIntArray(index);
567 jint* techItems = e->GetIntArrayElements(*techList, NULL);
568 for (int i = 0; i < index; i++) {
569 techItems[i] = technologies[i];
570 }
571 e->ReleaseIntArrayElements(*techList, techItems, 0);
572 }
573
574 if (handleList != NULL) {
575 *handleList = e->NewIntArray(index);
576 jint* handleItems = e->GetIntArrayElements(*handleList, NULL);
577 for (int i = 0; i < index; i++) {
578 handleItems[i] = handles[i];
579 }
580 e->ReleaseIntArrayElements(*handleList, handleItems, 0);
581 }
582
583 if (libnfcTypeList != NULL) {
584 *libnfcTypeList = e->NewIntArray(index);
585
586 jint* typeItems = e->GetIntArrayElements(*libnfcTypeList, NULL);
587 for (int i = 0; i < index; i++) {
588 typeItems[i] = libnfctypes[i];
589 }
590 e->ReleaseIntArrayElements(*libnfcTypeList, typeItems, 0);
591 }
592 }
593
594 } // namespace android
595