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 */ 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 */ 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 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 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 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 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 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 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 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 224 nfc_jni_native_monitor_t* nfc_jni_get_monitor(void) 225 { 226 return nfc_jni_native_monitor; 227 } 228 229 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 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 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 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 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 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 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 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 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 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 */ 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