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 <semaphore.h> 18 19 #include "com_android_nfc.h" 20 21 static phNfc_sData_t *com_android_nfc_jni_transceive_buffer; 22 static phNfc_sData_t *com_android_nfc_jni_ioctl_buffer; 23 static phNfc_sRemoteDevInformation_t* SecureElementInfo; 24 static int secureElementHandle; 25 extern void *gHWRef; 26 static int SecureElementTech; 27 extern uint8_t device_connected_flag; 28 29 namespace android { 30 31 static void com_android_nfc_jni_ioctl_callback ( void* pContext, 32 phNfc_sData_t* Outparam_Cb, 33 NFCSTATUS status) 34 { 35 struct nfc_jni_callback_data * pContextData = (struct nfc_jni_callback_data*)pContext; 36 37 if (status == NFCSTATUS_SUCCESS ) 38 { 39 LOG_CALLBACK("> IOCTL successful",status); 40 } 41 else 42 { 43 LOG_CALLBACK("> IOCTL error",status); 44 } 45 46 com_android_nfc_jni_ioctl_buffer = Outparam_Cb; 47 pContextData->status = status; 48 sem_post(&pContextData->sem); 49 } 50 51 static void com_android_nfc_jni_transceive_callback(void *pContext, 52 phLibNfc_Handle handle, phNfc_sData_t *pResBuffer, NFCSTATUS status) 53 { 54 struct nfc_jni_callback_data * pContextData = (struct nfc_jni_callback_data*)pContext; 55 56 LOG_CALLBACK("com_android_nfc_jni_transceive_callback", status); 57 58 com_android_nfc_jni_transceive_buffer = pResBuffer; 59 pContextData->status = status; 60 sem_post(&pContextData->sem); 61 } 62 63 64 static void com_android_nfc_jni_connect_callback(void *pContext, 65 phLibNfc_Handle hRemoteDev, 66 phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo, NFCSTATUS status) 67 { 68 struct nfc_jni_callback_data * pContextData = (struct nfc_jni_callback_data*)pContext; 69 70 LOG_CALLBACK("com_android_nfc_jni_connect_callback", status); 71 72 pContextData->status = status; 73 sem_post(&pContextData->sem); 74 } 75 76 static void com_android_nfc_jni_disconnect_callback(void *pContext, 77 phLibNfc_Handle hRemoteDev, 78 NFCSTATUS status) 79 { 80 struct nfc_jni_callback_data * pContextData = (struct nfc_jni_callback_data*)pContext; 81 82 LOG_CALLBACK("com_android_nfc_jni_disconnect_callback", status); 83 84 pContextData->status = status; 85 sem_post(&pContextData->sem); 86 } 87 88 /* Set Secure Element mode callback*/ 89 static void com_android_nfc_jni_smartMX_setModeCb (void* pContext, 90 phLibNfc_Handle hSecureElement, 91 NFCSTATUS status) 92 { 93 struct nfc_jni_callback_data * pContextData = (struct nfc_jni_callback_data*)pContext; 94 95 if(status==NFCSTATUS_SUCCESS) 96 { 97 LOG_CALLBACK("SE Set Mode is Successful",status); 98 TRACE("SE Handle: %lu", hSecureElement); 99 } 100 else 101 { 102 LOG_CALLBACK("SE Set Mode is failed\n ",status); 103 } 104 105 pContextData->status = status; 106 sem_post(&pContextData->sem); 107 } 108 109 static void com_android_nfc_jni_open_secure_element_notification_callback(void *pContext, 110 phLibNfc_RemoteDevList_t *psRemoteDevList, 111 uint8_t uNofRemoteDev, 112 NFCSTATUS status) 113 { 114 struct nfc_jni_callback_data * pContextData = (struct nfc_jni_callback_data*)pContext; 115 NFCSTATUS ret; 116 int i; 117 JNIEnv *e = nfc_get_env(); 118 119 if(status == NFCSTATUS_DESELECTED) 120 { 121 LOG_CALLBACK("com_android_nfc_jni_open_secure_element_notification_callback: Target deselected", status); 122 } 123 else 124 { 125 LOG_CALLBACK("com_android_nfc_jni_open_secure_element_notification_callback", status); 126 TRACE("Discovered %d secure elements", uNofRemoteDev); 127 128 if(status == NFCSTATUS_MULTIPLE_PROTOCOLS) 129 { 130 bool foundHandle = false; 131 TRACE("Multiple Protocol supported\n"); 132 for (i=0; i<uNofRemoteDev; i++) { 133 // Always open the phNfc_eISO14443_A_PICC protocol 134 TRACE("Protocol %d handle=%x type=%d", i, psRemoteDevList[i].hTargetDev, 135 psRemoteDevList[i].psRemoteDevInfo->RemDevType); 136 if (psRemoteDevList[i].psRemoteDevInfo->RemDevType == phNfc_eISO14443_A_PICC) { 137 secureElementHandle = psRemoteDevList[i].hTargetDev; 138 foundHandle = true; 139 } 140 } 141 if (!foundHandle) { 142 ALOGE("Could not find ISO-DEP secure element"); 143 status = NFCSTATUS_FAILED; 144 goto clean_and_return; 145 } 146 } 147 else 148 { 149 secureElementHandle = psRemoteDevList->hTargetDev; 150 } 151 152 TRACE("Secure Element Handle: 0x%08x", secureElementHandle); 153 154 /* Set type name */ 155 ScopedLocalRef<jintArray> techList(e, NULL); 156 nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, NULL, NULL); 157 158 // TODO: Should use the "connected" technology, for now use the first 159 if ((techList.get() != NULL) && e->GetArrayLength(techList.get()) > 0) { 160 e->GetIntArrayRegion(techList.get(), 0, 1, &SecureElementTech); 161 TRACE("Store Secure Element Info\n"); 162 SecureElementInfo = psRemoteDevList->psRemoteDevInfo; 163 164 TRACE("Discovered secure element: tech=%d", SecureElementTech); 165 } 166 else { 167 ALOGE("Discovered secure element, but could not resolve tech"); 168 status = NFCSTATUS_FAILED; 169 } 170 } 171 172 clean_and_return: 173 pContextData->status = status; 174 sem_post(&pContextData->sem); 175 } 176 177 178 static jint com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection(JNIEnv *e, jobject o) 179 { 180 NFCSTATUS ret; 181 int semResult; 182 jint errorCode = EE_ERROR_INIT; 183 184 phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE]; 185 uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0; 186 phLibNfc_sADD_Cfg_t discovery_cfg; 187 phLibNfc_Registry_Info_t registry_info; 188 phNfc_sData_t InParam; 189 phNfc_sData_t OutParam; 190 uint8_t ExternalRFDetected[3] = {0x00, 0xFC, 0x01}; 191 uint8_t GpioGetValue[3] = {0x00, 0xF8, 0x2B}; 192 uint8_t GpioSetValue[4]; 193 uint8_t gpioValue; 194 uint8_t Output_Buff[10]; 195 uint8_t reg_value; 196 uint8_t mask_value; 197 struct nfc_jni_callback_data cb_data; 198 struct nfc_jni_callback_data cb_data_SE_Notification; 199 200 /* Create the local semaphore */ 201 if (!nfc_cb_data_init(&cb_data, NULL)) 202 { 203 goto clean_and_return; 204 } 205 206 /* Create the local semaphore */ 207 if (!nfc_cb_data_init(&cb_data_SE_Notification, NULL)) 208 { 209 goto clean_and_return; 210 } 211 212 /* Registery */ 213 registry_info.MifareUL = TRUE; 214 registry_info.MifareStd = TRUE; 215 registry_info.ISO14443_4A = TRUE; 216 registry_info.ISO14443_4B = TRUE; 217 registry_info.Jewel = TRUE; 218 registry_info.Felica = TRUE; 219 registry_info.NFC = FALSE; 220 221 CONCURRENCY_LOCK(); 222 223 TRACE("Open Secure Element"); 224 225 /* Check if NFC device is already connected to a tag or P2P peer */ 226 if (device_connected_flag == 1) 227 { 228 ALOGE("Unable to open SE connection, device already connected to a P2P peer or a Tag"); 229 errorCode = EE_ERROR_LISTEN_MODE; 230 goto clean_and_return; 231 } 232 233 /* Test if External RF field is detected */ 234 InParam.buffer = ExternalRFDetected; 235 InParam.length = 3; 236 OutParam.buffer = Output_Buff; 237 TRACE("phLibNfc_Mgt_IoCtl()"); 238 REENTRANCE_LOCK(); 239 ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data); 240 REENTRANCE_UNLOCK(); 241 if(ret!=NFCSTATUS_PENDING) 242 { 243 ALOGE("IOCTL status error"); 244 goto clean_and_return; 245 } 246 247 /* Wait for callback response */ 248 if(sem_wait(&cb_data.sem)) 249 { 250 ALOGE("IOCTL semaphore error"); 251 goto clean_and_return; 252 } 253 254 if(cb_data.status != NFCSTATUS_SUCCESS) 255 { 256 ALOGE("READ MEM ERROR"); 257 goto clean_and_return; 258 } 259 260 /* Check the value */ 261 reg_value = com_android_nfc_jni_ioctl_buffer->buffer[0]; 262 mask_value = reg_value & 0x40; 263 264 if(mask_value == 0x40) 265 { 266 // There is an external RF field present, fail the open request 267 ALOGD("Unable to open SE connection, external RF Field detected"); 268 errorCode = EE_ERROR_EXT_FIELD; 269 goto clean_and_return; 270 } 271 272 /* Get Secure Element List */ 273 TRACE("phLibNfc_SE_GetSecureElementList()"); 274 ret = phLibNfc_SE_GetSecureElementList( SE_List, &No_SE); 275 if (ret == NFCSTATUS_SUCCESS) 276 { 277 TRACE("\n> Number of Secure Element(s) : %d\n", No_SE); 278 /* Display Secure Element information */ 279 for (i = 0; i<No_SE; i++) 280 { 281 if (SE_List[i].eSE_Type == phLibNfc_SE_Type_SmartMX) 282 { 283 TRACE("> SMX detected"); 284 TRACE("> Secure Element Handle : %d\n", SE_List[i].hSecureElement); 285 /* save SMARTMX index */ 286 SmartMX_detected = 1; 287 SmartMX_index = i; 288 } 289 } 290 291 if(SmartMX_detected) 292 { 293 REENTRANCE_LOCK(); 294 TRACE("phLibNfc_RemoteDev_NtfRegister()"); 295 ret = phLibNfc_RemoteDev_NtfRegister(®istry_info, 296 com_android_nfc_jni_open_secure_element_notification_callback, 297 (void *)&cb_data_SE_Notification); 298 REENTRANCE_UNLOCK(); 299 if(ret != NFCSTATUS_SUCCESS) 300 { 301 ALOGE("Register Notification error"); 302 goto clean_and_return; 303 } 304 305 /* Set wired mode */ 306 REENTRANCE_LOCK(); 307 TRACE("phLibNfc_SE_SetMode: Wired mode"); 308 ret = phLibNfc_SE_SetMode( SE_List[SmartMX_index].hSecureElement, 309 phLibNfc_SE_ActModeWired, 310 com_android_nfc_jni_smartMX_setModeCb, 311 (void *)&cb_data); 312 REENTRANCE_UNLOCK(); 313 if (ret != NFCSTATUS_PENDING ) 314 { 315 ALOGE("\n> SE Set SmartMX mode ERROR \n" ); 316 goto clean_and_return; 317 } 318 319 /* Wait for callback response */ 320 if(sem_wait(&cb_data.sem)) 321 { 322 ALOGE("Secure Element opening error"); 323 goto clean_and_return; 324 } 325 326 if(cb_data.status != NFCSTATUS_SUCCESS) 327 { 328 ALOGE("SE set mode failed"); 329 goto clean_and_return; 330 } 331 332 TRACE("Waiting for notification"); 333 /* Wait for callback response */ 334 if(sem_wait(&cb_data_SE_Notification.sem)) 335 { 336 ALOGE("Secure Element opening error"); 337 goto clean_and_return; 338 } 339 340 if(cb_data_SE_Notification.status != NFCSTATUS_SUCCESS && 341 cb_data_SE_Notification.status != NFCSTATUS_MULTIPLE_PROTOCOLS) 342 { 343 ALOGE("SE detection failed"); 344 goto clean_and_return; 345 } 346 CONCURRENCY_UNLOCK(); 347 348 /* Connect Tag */ 349 CONCURRENCY_LOCK(); 350 TRACE("phLibNfc_RemoteDev_Connect(SMX)"); 351 REENTRANCE_LOCK(); 352 ret = phLibNfc_RemoteDev_Connect(secureElementHandle, com_android_nfc_jni_connect_callback,(void *)&cb_data); 353 REENTRANCE_UNLOCK(); 354 if(ret != NFCSTATUS_PENDING) 355 { 356 ALOGE("phLibNfc_RemoteDev_Connect(SMX) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 357 goto clean_and_return; 358 } 359 TRACE("phLibNfc_RemoteDev_Connect(SMX) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 360 361 /* Wait for callback response */ 362 if(sem_wait(&cb_data.sem)) 363 { 364 ALOGE("CONNECT semaphore error"); 365 goto clean_and_return; 366 } 367 368 /* Connect Status */ 369 if(cb_data.status != NFCSTATUS_SUCCESS) 370 { 371 ALOGE("Secure Element connect error"); 372 goto clean_and_return; 373 } 374 375 CONCURRENCY_UNLOCK(); 376 377 /* Get GPIO information */ 378 CONCURRENCY_LOCK(); 379 InParam.buffer = GpioGetValue; 380 InParam.length = 3; 381 OutParam.buffer = Output_Buff; 382 TRACE("phLibNfc_Mgt_IoCtl()- GPIO Get Value"); 383 REENTRANCE_LOCK(); 384 ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data); 385 REENTRANCE_UNLOCK(); 386 if(ret!=NFCSTATUS_PENDING) 387 { 388 ALOGE("IOCTL status error"); 389 } 390 391 /* Wait for callback response */ 392 if(sem_wait(&cb_data.sem)) 393 { 394 ALOGE("IOCTL semaphore error"); 395 goto clean_and_return; 396 } 397 398 if(cb_data.status != NFCSTATUS_SUCCESS) 399 { 400 ALOGE("READ MEM ERROR"); 401 goto clean_and_return; 402 } 403 404 gpioValue = com_android_nfc_jni_ioctl_buffer->buffer[0]; 405 TRACE("GpioValue = Ox%02x",gpioValue); 406 407 /* Set GPIO information */ 408 GpioSetValue[0] = 0x00; 409 GpioSetValue[1] = 0xF8; 410 GpioSetValue[2] = 0x2B; 411 GpioSetValue[3] = (gpioValue | 0x40); 412 413 TRACE("GpioValue to be set = Ox%02x",GpioSetValue[3]); 414 415 for(i=0;i<4;i++) 416 { 417 TRACE("0x%02x",GpioSetValue[i]); 418 } 419 420 InParam.buffer = GpioSetValue; 421 InParam.length = 4; 422 OutParam.buffer = Output_Buff; 423 TRACE("phLibNfc_Mgt_IoCtl()- GPIO Set Value"); 424 REENTRANCE_LOCK(); 425 ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_WRITE,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data); 426 REENTRANCE_UNLOCK(); 427 if(ret!=NFCSTATUS_PENDING) 428 { 429 ALOGE("IOCTL status error"); 430 goto clean_and_return; 431 } 432 433 /* Wait for callback response */ 434 if(sem_wait(&cb_data.sem)) 435 { 436 ALOGE("IOCTL semaphore error"); 437 goto clean_and_return; 438 } 439 440 if(cb_data.status != NFCSTATUS_SUCCESS) 441 { 442 ALOGE("READ MEM ERROR"); 443 goto clean_and_return; 444 } 445 CONCURRENCY_UNLOCK(); 446 447 nfc_cb_data_deinit(&cb_data); 448 nfc_cb_data_deinit(&cb_data_SE_Notification); 449 450 /* Return the Handle of the SecureElement */ 451 return secureElementHandle; 452 } 453 else 454 { 455 ALOGE("phLibNfc_SE_GetSecureElementList(): No SMX detected"); 456 goto clean_and_return; 457 } 458 } 459 else 460 { 461 ALOGE("phLibNfc_SE_GetSecureElementList(): Error"); 462 goto clean_and_return; 463 } 464 465 clean_and_return: 466 nfc_cb_data_deinit(&cb_data); 467 nfc_cb_data_deinit(&cb_data_SE_Notification); 468 469 CONCURRENCY_UNLOCK(); 470 return errorCode; 471 } 472 473 474 static jboolean com_android_nfc_NativeNfcSecureElement_doDisconnect(JNIEnv *e, jobject o, jint handle) 475 { 476 jclass cls; 477 jfieldID f; 478 NFCSTATUS status; 479 jboolean result = JNI_FALSE; 480 phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE]; 481 uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0; 482 uint32_t SmartMX_Handle; 483 struct nfc_jni_callback_data cb_data; 484 phNfc_sData_t InParam; 485 phNfc_sData_t OutParam; 486 uint8_t Output_Buff[10]; 487 uint8_t GpioGetValue[3] = {0x00, 0xF8, 0x2B}; 488 uint8_t GpioSetValue[4]; 489 uint8_t gpioValue; 490 491 /* Create the local semaphore */ 492 if (!nfc_cb_data_init(&cb_data, NULL)) 493 { 494 goto clean_and_return; 495 } 496 497 TRACE("Close Secure element function "); 498 499 CONCURRENCY_LOCK(); 500 /* Disconnect */ 501 TRACE("Disconnecting from SMX (handle = 0x%x)", handle); 502 REENTRANCE_LOCK(); 503 status = phLibNfc_RemoteDev_Disconnect(handle, 504 NFC_SMARTMX_RELEASE, 505 com_android_nfc_jni_disconnect_callback, 506 (void *)&cb_data); 507 REENTRANCE_UNLOCK(); 508 if(status != NFCSTATUS_PENDING) 509 { 510 ALOGE("phLibNfc_RemoteDev_Disconnect(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 511 goto clean_and_return; 512 } 513 TRACE("phLibNfc_RemoteDev_Disconnect(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 514 515 /* Wait for callback response */ 516 if(sem_wait(&cb_data.sem)) 517 { 518 goto clean_and_return; 519 } 520 521 /* Disconnect Status */ 522 if(cb_data.status != NFCSTATUS_SUCCESS) 523 { 524 ALOGE("\n> Disconnect SE ERROR \n" ); 525 goto clean_and_return; 526 } 527 CONCURRENCY_UNLOCK(); 528 529 /* Get GPIO information */ 530 CONCURRENCY_LOCK(); 531 InParam.buffer = GpioGetValue; 532 InParam.length = 3; 533 OutParam.buffer = Output_Buff; 534 TRACE("phLibNfc_Mgt_IoCtl()- GPIO Get Value"); 535 REENTRANCE_LOCK(); 536 status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data); 537 REENTRANCE_UNLOCK(); 538 if(status!=NFCSTATUS_PENDING) 539 { 540 ALOGE("IOCTL status error"); 541 goto clean_and_return; 542 } 543 544 /* Wait for callback response */ 545 if(sem_wait(&cb_data.sem)) 546 { 547 ALOGE("IOCTL semaphore error"); 548 goto clean_and_return; 549 } 550 551 if(cb_data.status != NFCSTATUS_SUCCESS) 552 { 553 ALOGE("READ MEM ERROR"); 554 goto clean_and_return; 555 } 556 557 gpioValue = com_android_nfc_jni_ioctl_buffer->buffer[0]; 558 TRACE("GpioValue = Ox%02x",gpioValue); 559 560 /* Set GPIO information */ 561 GpioSetValue[0] = 0x00; 562 GpioSetValue[1] = 0xF8; 563 GpioSetValue[2] = 0x2B; 564 GpioSetValue[3] = (gpioValue & 0xBF); 565 566 TRACE("GpioValue to be set = Ox%02x",GpioSetValue[3]); 567 568 for(i=0;i<4;i++) 569 { 570 TRACE("0x%02x",GpioSetValue[i]); 571 } 572 573 InParam.buffer = GpioSetValue; 574 InParam.length = 4; 575 OutParam.buffer = Output_Buff; 576 TRACE("phLibNfc_Mgt_IoCtl()- GPIO Set Value"); 577 REENTRANCE_LOCK(); 578 status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_WRITE,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data); 579 REENTRANCE_UNLOCK(); 580 if(status!=NFCSTATUS_PENDING) 581 { 582 ALOGE("IOCTL status error"); 583 goto clean_and_return; 584 } 585 586 /* Wait for callback response */ 587 if(sem_wait(&cb_data.sem)) 588 { 589 ALOGE("IOCTL semaphore error"); 590 goto clean_and_return; 591 } 592 593 if(cb_data.status != NFCSTATUS_SUCCESS) 594 { 595 ALOGE("READ MEM ERROR"); 596 goto clean_and_return; 597 } 598 599 result = JNI_TRUE; 600 601 clean_and_return: 602 nfc_cb_data_deinit(&cb_data); 603 604 CONCURRENCY_UNLOCK(); 605 return result; 606 } 607 608 static jbyteArray com_android_nfc_NativeNfcSecureElement_doTransceive(JNIEnv *e, 609 jobject o,jint handle, jbyteArray data) 610 { 611 uint8_t offset = 0; 612 uint8_t *buf; 613 uint32_t buflen; 614 phLibNfc_sTransceiveInfo_t transceive_info; 615 jbyteArray result = NULL; 616 int res; 617 618 int tech = SecureElementTech; 619 NFCSTATUS status; 620 struct nfc_jni_callback_data cb_data; 621 622 /* Create the local semaphore */ 623 if (!nfc_cb_data_init(&cb_data, NULL)) 624 { 625 goto clean_and_return; 626 } 627 628 TRACE("Exchange APDU function "); 629 630 CONCURRENCY_LOCK(); 631 632 TRACE("Secure Element tech: %d\n", tech); 633 634 buf = (uint8_t *)e->GetByteArrayElements(data, NULL); 635 buflen = (uint32_t)e->GetArrayLength(data); 636 637 /* Prepare transceive info structure */ 638 if(tech == TARGET_TYPE_MIFARE_CLASSIC || tech == TARGET_TYPE_MIFARE_UL) 639 { 640 offset = 2; 641 transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0]; 642 transceive_info.addr = (uint8_t)buf[1]; 643 } 644 else if(tech == TARGET_TYPE_ISO14443_4) 645 { 646 transceive_info.cmd.Iso144434Cmd = phNfc_eIso14443_4_Raw; 647 transceive_info.addr = 0; 648 } 649 650 transceive_info.sSendData.buffer = buf + offset; 651 transceive_info.sSendData.length = buflen - offset; 652 transceive_info.sRecvData.buffer = (uint8_t*)malloc(1024); 653 transceive_info.sRecvData.length = 1024; 654 655 if(transceive_info.sRecvData.buffer == NULL) 656 { 657 goto clean_and_return; 658 } 659 660 TRACE("phLibNfc_RemoteDev_Transceive(SMX)"); 661 REENTRANCE_LOCK(); 662 status = phLibNfc_RemoteDev_Transceive(handle, &transceive_info, 663 com_android_nfc_jni_transceive_callback, (void *)&cb_data); 664 REENTRANCE_UNLOCK(); 665 if(status != NFCSTATUS_PENDING) 666 { 667 ALOGE("phLibNfc_RemoteDev_Transceive(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 668 goto clean_and_return; 669 } 670 TRACE("phLibNfc_RemoteDev_Transceive(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 671 672 /* Wait for callback response */ 673 if(sem_wait(&cb_data.sem)) 674 { 675 ALOGE("TRANSCEIVE semaphore error"); 676 goto clean_and_return; 677 } 678 679 if(cb_data.status != NFCSTATUS_SUCCESS) 680 { 681 ALOGE("TRANSCEIVE error"); 682 goto clean_and_return; 683 } 684 685 /* Copy results back to Java */ 686 result = e->NewByteArray(com_android_nfc_jni_transceive_buffer->length); 687 if(result != NULL) 688 { 689 e->SetByteArrayRegion(result, 0, 690 com_android_nfc_jni_transceive_buffer->length, 691 (jbyte *)com_android_nfc_jni_transceive_buffer->buffer); 692 } 693 694 clean_and_return: 695 nfc_cb_data_deinit(&cb_data); 696 697 if(transceive_info.sRecvData.buffer != NULL) 698 { 699 free(transceive_info.sRecvData.buffer); 700 } 701 702 e->ReleaseByteArrayElements(data, 703 (jbyte *)transceive_info.sSendData.buffer, JNI_ABORT); 704 705 CONCURRENCY_UNLOCK(); 706 707 return result; 708 } 709 710 static jbyteArray com_android_nfc_NativeNfcSecureElement_doGetUid(JNIEnv *e, jobject o, jint handle) 711 { 712 TRACE("Get Secure element UID function "); 713 jbyteArray SecureElementUid; 714 715 if(handle == secureElementHandle) 716 { 717 SecureElementUid = e->NewByteArray(SecureElementInfo->RemoteDevInfo.Iso14443A_Info.UidLength); 718 e->SetByteArrayRegion(SecureElementUid, 0, SecureElementInfo->RemoteDevInfo.Iso14443A_Info.UidLength,(jbyte *)SecureElementInfo->RemoteDevInfo.Iso14443A_Info.Uid); 719 return SecureElementUid; 720 } 721 else 722 { 723 return NULL; 724 } 725 } 726 727 static jintArray com_android_nfc_NativeNfcSecureElement_doGetTechList(JNIEnv *e, jobject o, jint handle) 728 { 729 jintArray techList; 730 TRACE("Get Secure element Type function "); 731 732 if (handle != secureElementHandle) { 733 return NULL; 734 } 735 jintArray result = e->NewIntArray(1); 736 e->SetIntArrayRegion(result, 0, 1, &SecureElementTech); 737 return result; 738 } 739 740 741 /* 742 * JNI registration. 743 */ 744 static JNINativeMethod gMethods[] = 745 { 746 {"doNativeOpenSecureElementConnection", "()I", 747 (void *)com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection}, 748 {"doNativeDisconnectSecureElementConnection", "(I)Z", 749 (void *)com_android_nfc_NativeNfcSecureElement_doDisconnect}, 750 {"doTransceive", "(I[B)[B", 751 (void *)com_android_nfc_NativeNfcSecureElement_doTransceive}, 752 {"doGetUid", "(I)[B", 753 (void *)com_android_nfc_NativeNfcSecureElement_doGetUid}, 754 {"doGetTechList", "(I)[I", 755 (void *)com_android_nfc_NativeNfcSecureElement_doGetTechList}, 756 }; 757 758 int register_com_android_nfc_NativeNfcSecureElement(JNIEnv *e) 759 { 760 return jniRegisterNativeMethods(e, 761 "com/android/nfc/dhimpl/NativeNfcSecureElement", 762 gMethods, NELEM(gMethods)); 763 } 764 765 } // namespace android 766