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