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