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 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 */ 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 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 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 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 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 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 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 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 238 nfc_jni_native_monitor_t* nfc_jni_get_monitor(void) 239 { 240 return nfc_jni_native_monitor; 241 } 242 243 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 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 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 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 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 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 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 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 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 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 */ 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