• 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 
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