• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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