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