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 #include <errno.h> 19 20 #include "com_android_nfc.h" 21 #include "phNfcHalTypes.h" 22 23 static phLibNfc_Data_t nfc_jni_ndef_rw; 24 static phLibNfc_Handle handle; 25 uint8_t *nfc_jni_ndef_buf = NULL; 26 uint32_t nfc_jni_ndef_buf_len = 0; 27 28 extern uint8_t device_connected_flag; 29 30 namespace android { 31 32 extern phLibNfc_Handle storedHandle; 33 34 extern void nfc_jni_restart_discovery_locked(struct nfc_jni_native_data *nat); 35 extern void nfc_jni_reset_timeout_values(); 36 37 /* 38 * Callbacks 39 */ 40 static void nfc_jni_tag_rw_callback(void *pContext, NFCSTATUS status) 41 { 42 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; 43 LOG_CALLBACK("nfc_jni_tag_rw_callback", status); 44 45 /* Report the callback status and wake up the caller */ 46 pCallbackData->status = status; 47 sem_post(&pCallbackData->sem); 48 } 49 50 static void nfc_jni_connect_callback(void *pContext, 51 phLibNfc_Handle hRemoteDev, 52 phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo, NFCSTATUS status) 53 { 54 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; 55 LOG_CALLBACK("nfc_jni_connect_callback", status); 56 57 /* Report the callback status and wake up the caller */ 58 pCallbackData->status = status; 59 if (pCallbackData->pContext != NULL) { 60 // Store the remote dev info ptr in the callback context 61 // Note that this ptr will remain valid, it is tied to a statically 62 // allocated buffer in libnfc. 63 phLibNfc_sRemoteDevInformation_t** ppRemoteDevInfo = 64 (phLibNfc_sRemoteDevInformation_t**)pCallbackData->pContext; 65 *ppRemoteDevInfo = psRemoteDevInfo; 66 } 67 68 sem_post(&pCallbackData->sem); 69 } 70 71 static void nfc_jni_checkndef_callback(void *pContext, 72 phLibNfc_ChkNdef_Info_t info, NFCSTATUS status) 73 { 74 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; 75 LOG_CALLBACK("nfc_jni_checkndef_callback", status); 76 phLibNfc_ChkNdef_Info_t* pNdefInfo = (phLibNfc_ChkNdef_Info_t*) (pCallbackData->pContext); 77 if(status == NFCSTATUS_OK) 78 { 79 if(nfc_jni_ndef_buf) 80 { 81 free(nfc_jni_ndef_buf); 82 } 83 nfc_jni_ndef_buf_len = info.MaxNdefMsgLength; 84 nfc_jni_ndef_buf = (uint8_t*)malloc(nfc_jni_ndef_buf_len); 85 if (pNdefInfo != NULL) *pNdefInfo = info; 86 } 87 else { 88 if (pNdefInfo != NULL) { 89 memset(pNdefInfo, 0, sizeof(*pNdefInfo)); 90 } 91 } 92 93 /* Report the callback status and wake up the caller */ 94 pCallbackData->status = status; 95 sem_post(&pCallbackData->sem); 96 } 97 98 static void nfc_jni_disconnect_callback(void *pContext, 99 phLibNfc_Handle hRemoteDev, NFCSTATUS status) 100 { 101 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; 102 LOG_CALLBACK("nfc_jni_disconnect_callback", status); 103 104 if(nfc_jni_ndef_buf) 105 { 106 free(nfc_jni_ndef_buf); 107 } 108 nfc_jni_ndef_buf = NULL; 109 nfc_jni_ndef_buf_len = 0; 110 111 /* Report the callback status and wake up the caller */ 112 pCallbackData->status = status; 113 sem_post(&pCallbackData->sem); 114 } 115 116 static void nfc_jni_async_disconnect_callback(void *pContext, 117 phLibNfc_Handle hRemoteDev, NFCSTATUS status) 118 { 119 LOG_CALLBACK("nfc_jni_async_disconnect_callback", status); 120 121 if(nfc_jni_ndef_buf) 122 { 123 free(nfc_jni_ndef_buf); 124 } 125 nfc_jni_ndef_buf = NULL; 126 nfc_jni_ndef_buf_len = 0; 127 } 128 129 static phNfc_sData_t *nfc_jni_transceive_buffer; 130 131 static void nfc_jni_transceive_callback(void *pContext, 132 phLibNfc_Handle handle, phNfc_sData_t *pResBuffer, NFCSTATUS status) 133 { 134 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; 135 LOG_CALLBACK("nfc_jni_transceive_callback", status); 136 137 nfc_jni_transceive_buffer = pResBuffer; 138 139 /* Report the callback status and wake up the caller */ 140 pCallbackData->status = status; 141 sem_post(&pCallbackData->sem); 142 } 143 144 static void nfc_jni_presencecheck_callback(void *pContext, NFCSTATUS status) 145 { 146 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; 147 LOG_CALLBACK("nfc_jni_presencecheck_callback", status); 148 149 /* Report the callback status and wake up the caller */ 150 pCallbackData->status = status; 151 sem_post(&pCallbackData->sem); 152 } 153 154 static void nfc_jni_formatndef_callback(void *pContext, NFCSTATUS status) 155 { 156 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; 157 LOG_CALLBACK("nfc_jni_formatndef_callback", status); 158 159 /* Report the callback status and wake up the caller */ 160 pCallbackData->status = status; 161 sem_post(&pCallbackData->sem); 162 } 163 164 static void nfc_jni_readonly_callback(void *pContext, NFCSTATUS status) 165 { 166 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; 167 LOG_CALLBACK("nfc_jni_readonly_callback", status); 168 169 /* Report the callback status and wake up the caller */ 170 pCallbackData->status = status; 171 sem_post(&pCallbackData->sem); 172 } 173 174 /* Functions */ 175 static jbyteArray com_android_nfc_NativeNfcTag_doRead(JNIEnv *e, 176 jobject o) 177 { 178 NFCSTATUS status; 179 phLibNfc_Handle handle = 0; 180 jbyteArray buf = NULL; 181 struct nfc_jni_callback_data cb_data; 182 183 CONCURRENCY_LOCK(); 184 185 /* Create the local semaphore */ 186 if (!nfc_cb_data_init(&cb_data, NULL)) 187 { 188 goto clean_and_return; 189 } 190 191 handle = nfc_jni_get_connected_handle(e, o); 192 193 nfc_jni_ndef_rw.length = nfc_jni_ndef_buf_len; 194 nfc_jni_ndef_rw.buffer = nfc_jni_ndef_buf; 195 196 TRACE("phLibNfc_Ndef_Read()"); 197 REENTRANCE_LOCK(); 198 status = phLibNfc_Ndef_Read(handle, &nfc_jni_ndef_rw, 199 phLibNfc_Ndef_EBegin, 200 nfc_jni_tag_rw_callback, 201 (void *)&cb_data); 202 REENTRANCE_UNLOCK(); 203 if(status != NFCSTATUS_PENDING) 204 { 205 LOGE("phLibNfc_Ndef_Read() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 206 goto clean_and_return; 207 } 208 TRACE("phLibNfc_Ndef_Read() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 209 210 /* Wait for callback response */ 211 if(sem_wait(&cb_data.sem)) 212 { 213 LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); 214 goto clean_and_return; 215 } 216 217 if(cb_data.status != NFCSTATUS_SUCCESS) 218 { 219 goto clean_and_return; 220 } 221 222 buf = e->NewByteArray(nfc_jni_ndef_rw.length); 223 e->SetByteArrayRegion(buf, 0, nfc_jni_ndef_rw.length, 224 (jbyte *)nfc_jni_ndef_rw.buffer); 225 226 clean_and_return: 227 nfc_cb_data_deinit(&cb_data); 228 CONCURRENCY_UNLOCK(); 229 230 return buf; 231 } 232 233 234 static jboolean com_android_nfc_NativeNfcTag_doWrite(JNIEnv *e, 235 jobject o, jbyteArray buf) 236 { 237 NFCSTATUS status; 238 jboolean result = JNI_FALSE; 239 struct nfc_jni_callback_data cb_data; 240 241 phLibNfc_Handle handle = nfc_jni_get_connected_handle(e, o); 242 243 CONCURRENCY_LOCK(); 244 245 /* Create the local semaphore */ 246 if (!nfc_cb_data_init(&cb_data, NULL)) 247 { 248 goto clean_and_return; 249 } 250 251 nfc_jni_ndef_rw.length = (uint32_t)e->GetArrayLength(buf); 252 nfc_jni_ndef_rw.buffer = (uint8_t *)e->GetByteArrayElements(buf, NULL); 253 254 TRACE("phLibNfc_Ndef_Write()"); 255 TRACE("Ndef Handle :0x%x\n",handle); 256 TRACE("Ndef buffer length : %d", nfc_jni_ndef_rw.length); 257 REENTRANCE_LOCK(); 258 status = phLibNfc_Ndef_Write(handle, &nfc_jni_ndef_rw,nfc_jni_tag_rw_callback, (void *)&cb_data); 259 REENTRANCE_UNLOCK(); 260 if(status != NFCSTATUS_PENDING) 261 { 262 LOGE("phLibNfc_Ndef_Write() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 263 goto clean_and_return; 264 } 265 TRACE("phLibNfc_Ndef_Write() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 266 267 /* Wait for callback response */ 268 if(sem_wait(&cb_data.sem)) 269 { 270 LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); 271 goto clean_and_return; 272 } 273 274 if(cb_data.status != NFCSTATUS_SUCCESS) 275 { 276 goto clean_and_return; 277 } 278 279 result = JNI_TRUE; 280 281 clean_and_return: 282 e->ReleaseByteArrayElements(buf, (jbyte *)nfc_jni_ndef_rw.buffer, JNI_ABORT); 283 284 nfc_cb_data_deinit(&cb_data); 285 CONCURRENCY_UNLOCK(); 286 return result; 287 } 288 289 /* 290 * Utility to recover poll bytes from target infos 291 */ 292 static void set_target_pollBytes(JNIEnv *e, jobject tag, 293 phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo) 294 { 295 jclass tag_cls = e->GetObjectClass(tag); 296 jfieldID f = e->GetFieldID(tag_cls, "mTechPollBytes", "[[B"); 297 298 jobjectArray existingPollBytes = (jobjectArray) e->GetObjectField(tag, f); 299 300 if (existingPollBytes != NULL) { 301 return; 302 } 303 304 jfieldID techListField = e->GetFieldID(tag_cls, "mTechList", "[I"); 305 jintArray techList = (jintArray) e->GetObjectField(tag, techListField); 306 jint *techId = e->GetIntArrayElements(techList, 0); 307 int techListLength = e->GetArrayLength(techList); 308 309 jbyteArray pollBytes = e->NewByteArray(0); 310 jobjectArray techPollBytes = e->NewObjectArray(techListLength, 311 e->GetObjectClass(pollBytes), 0); 312 313 for (int tech = 0; tech < techListLength; tech++) { 314 switch(techId[tech]) 315 { 316 /* ISO14443-3A: ATQA/SENS_RES */ 317 case TARGET_TYPE_ISO14443_3A: 318 if (psRemoteDevInfo->RemDevType == phNfc_eJewel_PICC) { 319 // Jewel ATQA is not read and stored by the PN544, but it is fixed 320 // at {0x00, 0x0C} in the spec. So eJewel can safely be 321 // translated to {0x00, 0x0C}. 322 const static jbyte JewelAtqA[2] = {0x00, 0x0C}; 323 pollBytes = e->NewByteArray(2); 324 e->SetByteArrayRegion(pollBytes, 0, 2, (jbyte*) JewelAtqA); 325 } 326 else { 327 pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA)); 328 e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA), 329 (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA); 330 } 331 break; 332 /* ISO14443-3B: Application data (4 bytes) and Protocol Info (3 bytes) from ATQB/SENSB_RES */ 333 case TARGET_TYPE_ISO14443_3B: 334 pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData) 335 + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo)); 336 e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData), 337 (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData); 338 e->SetByteArrayRegion(pollBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData), 339 sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo), 340 (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo); 341 break; 342 /* JIS_X_6319_4: PAD0 (2 byte), PAD1 (2 byte), MRTI(2 byte), PAD2 (1 byte), RC (2 byte) */ 343 case TARGET_TYPE_FELICA: 344 pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm) 345 + sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode)); 346 e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm), 347 (jbyte *)psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm); 348 e->SetByteArrayRegion(pollBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm), 349 sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode), 350 (jbyte *)psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode); 351 break; 352 /* ISO15693: response flags (1 byte), DSFID (1 byte) */ 353 case TARGET_TYPE_ISO15693: 354 pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags) 355 + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid)); 356 e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags), 357 (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags); 358 e->SetByteArrayRegion(pollBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags), 359 sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid), 360 (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid); 361 break; 362 default: 363 pollBytes = e->NewByteArray(0); 364 break; 365 } 366 e->SetObjectArrayElement(techPollBytes, tech, pollBytes); 367 } 368 369 e->SetObjectField(tag, f, techPollBytes); 370 371 e->ReleaseIntArrayElements(techList, techId, 0); 372 373 } 374 375 /* 376 * Utility to recover activation bytes from target infos 377 */ 378 static void set_target_activationBytes(JNIEnv *e, jobject tag, 379 phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo) 380 { 381 jclass tag_cls = e->GetObjectClass(tag); 382 383 jfieldID f = e->GetFieldID(tag_cls, "mTechActBytes", "[[B"); 384 jobjectArray existingActBytes = (jobjectArray) e->GetObjectField(tag, f); 385 386 if (existingActBytes != NULL) { 387 return; 388 } 389 390 jfieldID techListField = e->GetFieldID(tag_cls, "mTechList", "[I"); 391 jintArray techList = (jintArray) e->GetObjectField(tag, techListField); 392 int techListLength = e->GetArrayLength(techList); 393 jint *techId = e->GetIntArrayElements(techList, 0); 394 395 jbyteArray actBytes = e->NewByteArray(0); 396 jobjectArray techActBytes = e->NewObjectArray(techListLength, 397 e->GetObjectClass(actBytes), 0); 398 399 for (int tech = 0; tech < techListLength; tech++) { 400 switch(techId[tech]) { 401 402 /* ISO14443-3A: SAK/SEL_RES */ 403 case TARGET_TYPE_ISO14443_3A: 404 actBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak)); 405 e->SetByteArrayRegion(actBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak), 406 (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak); 407 break; 408 /* ISO14443-3A & ISO14443-4: SAK/SEL_RES, historical bytes from ATS */ 409 /* ISO14443-3B & ISO14443-4: HiLayerResp */ 410 case TARGET_TYPE_ISO14443_4: 411 // Determine whether -A or -B 412 if (psRemoteDevInfo->RemDevType == phNfc_eISO14443_B_PICC || 413 psRemoteDevInfo->RemDevType == phNfc_eISO14443_4B_PICC) { 414 actBytes = e->NewByteArray(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerRespLength); 415 e->SetByteArrayRegion(actBytes, 0, psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerRespLength, 416 (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerResp); 417 } 418 else if (psRemoteDevInfo->RemDevType == phNfc_eISO14443_A_PICC || 419 psRemoteDevInfo->RemDevType == phNfc_eISO14443_4A_PICC) { 420 actBytes = e->NewByteArray(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppDataLength); 421 e->SetByteArrayRegion(actBytes, 0, 422 psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppDataLength, 423 (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppData); 424 } 425 break; 426 /* ISO15693: response flags (1 byte), DSFID (1 byte) */ 427 case TARGET_TYPE_ISO15693: 428 actBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags) 429 + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid)); 430 e->SetByteArrayRegion(actBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags), 431 (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags); 432 e->SetByteArrayRegion(actBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags), 433 sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid), 434 (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid); 435 break; 436 default: 437 actBytes = e->NewByteArray(0); 438 break; 439 } 440 e->SetObjectArrayElement(techActBytes, tech, actBytes); 441 } 442 e->SetObjectField(tag, f, techActBytes); 443 444 e->ReleaseIntArrayElements(techList, techId, 0); 445 } 446 447 static jint com_android_nfc_NativeNfcTag_doConnect(JNIEnv *e, 448 jobject o, phLibNfc_Handle handle) 449 { 450 jclass cls; 451 jfieldID f; 452 jint status; 453 struct nfc_jni_callback_data cb_data; 454 phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL; 455 456 CONCURRENCY_LOCK(); 457 458 /* Create the local semaphore */ 459 if (!nfc_cb_data_init(&cb_data, &pRemDevInfo)) 460 { 461 status = NFCSTATUS_NOT_ENOUGH_MEMORY; 462 goto clean_and_return; 463 } 464 465 TRACE("phLibNfc_RemoteDev_Connect(RW)"); 466 REENTRANCE_LOCK(); 467 storedHandle = handle; 468 status = phLibNfc_RemoteDev_Connect(handle, nfc_jni_connect_callback,(void *)&cb_data); 469 REENTRANCE_UNLOCK(); 470 if(status != NFCSTATUS_PENDING) 471 { 472 LOGE("phLibNfc_RemoteDev_Connect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 473 goto clean_and_return; 474 } 475 TRACE("phLibNfc_RemoteDev_Connect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 476 477 /* Wait for callback response */ 478 if(sem_wait(&cb_data.sem)) 479 { 480 LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); 481 status = NFCSTATUS_ABORTED; 482 goto clean_and_return; 483 } 484 485 status = cb_data.status; 486 TRACE("phLibNfc_RemoteDev_Connect() - Status code = %d", status); 487 488 /* Connect Status */ 489 if(status != NFCSTATUS_SUCCESS) 490 { 491 goto clean_and_return; 492 } 493 494 // Success, set poll & act bytes 495 set_target_pollBytes(e, o, pRemDevInfo); 496 set_target_activationBytes(e, o, pRemDevInfo); 497 498 clean_and_return: 499 nfc_cb_data_deinit(&cb_data); 500 CONCURRENCY_UNLOCK(); 501 return status; 502 } 503 504 static jint com_android_nfc_NativeNfcTag_doHandleReconnect(JNIEnv *e, 505 jobject o, phLibNfc_Handle handle) 506 { 507 jclass cls; 508 jfieldID f; 509 jint status; 510 struct nfc_jni_callback_data cb_data; 511 phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL; 512 CONCURRENCY_LOCK(); 513 514 /* Create the local semaphore */ 515 if (!nfc_cb_data_init(&cb_data, &pRemDevInfo)) 516 { 517 status = NFCSTATUS_NOT_ENOUGH_MEMORY; 518 goto clean_and_return; 519 } 520 521 TRACE("phLibNfc_RemoteDev_ReConnect(RW)"); 522 REENTRANCE_LOCK(); 523 storedHandle = handle; 524 status = phLibNfc_RemoteDev_ReConnect(handle, nfc_jni_connect_callback,(void *)&cb_data); 525 REENTRANCE_UNLOCK(); 526 if(status != NFCSTATUS_PENDING) 527 { 528 LOGE("phLibNfc_RemoteDev_ReConnect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 529 goto clean_and_return; 530 } 531 TRACE("phLibNfc_RemoteDev_ReConnect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 532 533 /* Wait for callback response */ 534 if(sem_wait(&cb_data.sem)) 535 { 536 LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); 537 status = NFCSTATUS_ABORTED; 538 goto clean_and_return; 539 } 540 541 status = cb_data.status; 542 543 /* Connect Status */ 544 if(status != NFCSTATUS_SUCCESS) 545 { 546 goto clean_and_return; 547 } 548 549 clean_and_return: 550 nfc_cb_data_deinit(&cb_data); 551 CONCURRENCY_UNLOCK(); 552 return status; 553 } 554 555 static jint com_android_nfc_NativeNfcTag_doReconnect(JNIEnv *e, 556 jobject o) 557 { 558 // Reconnect is provided by libnfc by just calling connect again 559 // on the same handle. 560 int libNfcType = nfc_jni_get_connected_technology_libnfc_type(e, o); 561 if (libNfcType != -1) { 562 // Note that some tag types are stateless, hence we do not reconnect 563 // those. Currently those are the Jewel and Iso15693 technologies. 564 if ((libNfcType != phNfc_eJewel_PICC) && (libNfcType != phNfc_eISO15693_PICC)) { 565 phLibNfc_Handle handle = nfc_jni_get_connected_handle(e,o); 566 return com_android_nfc_NativeNfcTag_doConnect(e, o, handle); 567 } 568 else { 569 return NFCSTATUS_SUCCESS; 570 } 571 } 572 else { 573 return NFCSTATUS_REJECTED; 574 } 575 } 576 577 578 static jboolean com_android_nfc_NativeNfcTag_doDisconnect(JNIEnv *e, jobject o) 579 { 580 phLibNfc_Handle handle = 0; 581 jclass cls; 582 jfieldID f; 583 NFCSTATUS status; 584 jboolean result = JNI_FALSE; 585 struct nfc_jni_callback_data cb_data; 586 587 CONCURRENCY_LOCK(); 588 589 handle = nfc_jni_get_connected_handle(e, o); 590 591 /* Create the local semaphore */ 592 if (!nfc_cb_data_init(&cb_data, NULL)) 593 { 594 goto clean_and_return; 595 } 596 597 /* Reset the stored handle */ 598 storedHandle = 0; 599 600 nfc_jni_reset_timeout_values(); 601 602 /* Disconnect */ 603 TRACE("Disconnecting from tag (%x)", handle); 604 605 if (handle == -1) { 606 // Was never connected to any tag, exit 607 result = JNI_TRUE; 608 LOGE("doDisconnect() - Target already disconnected"); 609 nfc_jni_restart_discovery_locked(nfc_jni_get_nat_ext(e)); 610 goto clean_and_return; 611 } 612 613 TRACE("phLibNfc_RemoteDev_Disconnect(%x)", handle); 614 REENTRANCE_LOCK(); 615 status = phLibNfc_RemoteDev_Disconnect(handle, NFC_DISCOVERY_CONTINUE, 616 nfc_jni_disconnect_callback, (void *)&cb_data); 617 REENTRANCE_UNLOCK(); 618 619 if(status == NFCSTATUS_TARGET_NOT_CONNECTED) 620 { 621 result = JNI_TRUE; 622 TRACE("phLibNfc_RemoteDev_Disconnect() - Target already disconnected"); 623 goto clean_and_return; 624 } 625 if(status != NFCSTATUS_PENDING) 626 { 627 LOGE("phLibNfc_RemoteDev_Disconnect(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status)); 628 nfc_jni_restart_discovery_locked(nfc_jni_get_nat_ext(e)); 629 goto clean_and_return; 630 } 631 TRACE("phLibNfc_RemoteDev_Disconnect(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status)); 632 633 /* Wait for callback response */ 634 if(sem_wait(&cb_data.sem)) 635 { 636 LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); 637 goto clean_and_return; 638 } 639 640 /* Disconnect Status */ 641 if(cb_data.status != NFCSTATUS_SUCCESS) 642 { 643 goto clean_and_return; 644 } 645 646 result = JNI_TRUE; 647 648 clean_and_return: 649 /* Reset device connected flag */ 650 device_connected_flag = 0; 651 nfc_cb_data_deinit(&cb_data); 652 CONCURRENCY_UNLOCK(); 653 return result; 654 } 655 656 static uint16_t 657 crc_16_ccitt1( uint8_t* msg, size_t len, uint16_t init ) 658 { 659 uint16_t b, crc = init; 660 661 do { 662 b = *msg++ ^ (crc & 0xFF); 663 b ^= (b << 4) & 0xFF; 664 crc = (crc >> 8) ^ (b << 8) ^ (b << 3) ^ (b >> 4); 665 } while( --len ); 666 667 return crc; 668 } 669 670 static void 671 nfc_insert_crc_a( uint8_t* msg, size_t len ) 672 { 673 uint16_t crc; 674 675 crc = crc_16_ccitt1( msg, len, 0x6363 ); 676 msg[len] = crc & 0xFF; 677 msg[len + 1] = (crc >> 8) & 0xFF; 678 } 679 680 static void 681 nfc_get_crc_a( uint8_t* msg, size_t len, uint8_t* byte1, uint8_t* byte2) 682 { 683 uint16_t crc; 684 685 crc = crc_16_ccitt1( msg, len, 0x6363 ); 686 *byte1 = crc & 0xFF; 687 *byte2 = (crc >> 8) & 0xFF; 688 } 689 690 static bool 691 crc_valid( uint8_t* msg, size_t len) 692 { 693 uint8_t crcByte1, crcByte2; 694 695 nfc_get_crc_a(nfc_jni_transceive_buffer->buffer, 696 len - 2, &crcByte1, &crcByte2); 697 698 if (msg[len - 2] == crcByte1 && 699 msg[len - 1] == crcByte2) { 700 return true; 701 } 702 else { 703 return false; 704 } 705 706 } 707 708 static jbyteArray com_android_nfc_NativeNfcTag_doTransceive(JNIEnv *e, 709 jobject o, jbyteArray data, jboolean raw, jintArray statusTargetLost) 710 { 711 uint8_t offset = 0; 712 // buf is the pointer to the JNI array and never overwritten, 713 // outbuf is passed into the transceive - it may be pointed to new memory 714 // to be extended with CRC. 715 uint8_t *buf = NULL; 716 uint32_t buflen; 717 718 uint8_t *outbuf = NULL; 719 uint32_t outlen; 720 phLibNfc_sTransceiveInfo_t transceive_info; 721 jbyteArray result = NULL; 722 int res; 723 phLibNfc_Handle handle = nfc_jni_get_connected_handle(e, o); 724 NFCSTATUS status; 725 struct nfc_jni_callback_data cb_data; 726 int selectedTech = 0; 727 int selectedLibNfcType = 0; 728 jint* technologies = NULL; 729 bool checkResponseCrc = false; 730 731 jint *targetLost; 732 if (statusTargetLost != NULL) { 733 targetLost = e->GetIntArrayElements(statusTargetLost, 0); 734 if (targetLost != NULL) { 735 *targetLost = 0; 736 } 737 } else { 738 targetLost = NULL; 739 } 740 741 memset(&transceive_info, 0, sizeof(transceive_info)); 742 CONCURRENCY_LOCK(); 743 744 /* Create the local semaphore */ 745 if (!nfc_cb_data_init(&cb_data, NULL)) 746 { 747 goto clean_and_return; 748 } 749 750 selectedTech = nfc_jni_get_connected_technology(e, o); 751 selectedLibNfcType = nfc_jni_get_connected_technology_libnfc_type(e, o); 752 753 buf = outbuf = (uint8_t *)e->GetByteArrayElements(data, NULL); 754 buflen = outlen = (uint32_t)e->GetArrayLength(data); 755 756 switch (selectedTech) { 757 case TARGET_TYPE_FELICA: 758 transceive_info.cmd.FelCmd = phNfc_eFelica_Raw; 759 transceive_info.addr = 0; 760 break; 761 case TARGET_TYPE_MIFARE_CLASSIC: 762 case TARGET_TYPE_MIFARE_UL: 763 if (raw) { 764 transceive_info.cmd.MfCmd = phHal_eMifareRaw; 765 transceive_info.addr = 0; 766 // Need to add in the crc here 767 outbuf = (uint8_t*)malloc(buflen + 2); 768 outlen += 2; 769 memcpy(outbuf, buf, buflen); 770 nfc_insert_crc_a(outbuf, buflen); 771 772 checkResponseCrc = true; 773 } else { 774 offset = 2; 775 transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0]; 776 transceive_info.addr = (uint8_t)buf[1]; 777 } 778 break; 779 case TARGET_TYPE_ISO14443_3A: 780 // Check which libnfc type 781 if (selectedLibNfcType == phNfc_eJewel_PICC) { 782 // For the Jewel pipe, CRC is automatically computed 783 transceive_info.cmd.JewelCmd = phNfc_eJewel_Raw; 784 transceive_info.addr = 0; 785 } else { 786 if (raw) { 787 // Use Mifare Raw to implement a standard 788 // ISO14443-3A transceive, with CRC added 789 transceive_info.cmd.MfCmd = phHal_eMifareRaw; 790 transceive_info.addr = 0; 791 // Need to add in the crc here 792 outbuf = (uint8_t*)malloc(buflen + 2); 793 outlen += 2; 794 memcpy(outbuf, buf, buflen); 795 nfc_insert_crc_a(outbuf, buflen); 796 797 checkResponseCrc = true; 798 } else { 799 // Use the mifare pipe 800 offset = 2; 801 transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0]; 802 transceive_info.addr = (uint8_t)buf[1]; 803 } 804 805 } 806 break; 807 case TARGET_TYPE_ISO14443_4: 808 transceive_info.cmd.Iso144434Cmd = phNfc_eIso14443_4_Raw; 809 transceive_info.addr = 0; 810 break; 811 case TARGET_TYPE_ISO15693: 812 transceive_info.cmd.Iso15693Cmd = phNfc_eIso15693_Cmd; 813 transceive_info.addr = 0; 814 break; 815 case TARGET_TYPE_UNKNOWN: 816 case TARGET_TYPE_ISO14443_3B: 817 // Not supported 818 goto clean_and_return; 819 default: 820 break; 821 } 822 823 transceive_info.sSendData.buffer = outbuf + offset; 824 transceive_info.sSendData.length = outlen - offset; 825 transceive_info.sRecvData.buffer = (uint8_t*)malloc(1024); 826 transceive_info.sRecvData.length = 1024; 827 if(transceive_info.sRecvData.buffer == NULL) 828 { 829 goto clean_and_return; 830 } 831 832 TRACE("phLibNfc_RemoteDev_Transceive()"); 833 REENTRANCE_LOCK(); 834 status = phLibNfc_RemoteDev_Transceive(handle, &transceive_info, 835 nfc_jni_transceive_callback, (void *)&cb_data); 836 REENTRANCE_UNLOCK(); 837 if(status != NFCSTATUS_PENDING) 838 { 839 LOGE("phLibNfc_RemoteDev_Transceive() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 840 if ((targetLost != NULL) && (status == NFCSTATUS_TARGET_LOST)) { 841 *targetLost = 1; 842 } 843 goto clean_and_return; 844 } 845 TRACE("phLibNfc_RemoteDev_Transceive() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 846 847 /* Wait for callback response */ 848 if(sem_wait(&cb_data.sem)) 849 { 850 LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); 851 goto clean_and_return; 852 } 853 854 if(cb_data.status != NFCSTATUS_SUCCESS) 855 { 856 if ((targetLost != NULL) && (cb_data.status == NFCSTATUS_TARGET_LOST)) { 857 *targetLost = 1; 858 } 859 goto clean_and_return; 860 } 861 862 /* Copy results back to Java * 863 * In case of NfcA and raw, also check the CRC in the response 864 * and cut it off in the returned data. 865 */ 866 if ((nfc_jni_transceive_buffer->length > 2) && checkResponseCrc) { 867 if (crc_valid(nfc_jni_transceive_buffer->buffer, nfc_jni_transceive_buffer->length)) { 868 result = e->NewByteArray(nfc_jni_transceive_buffer->length - 2); 869 if (result != NULL) { 870 e->SetByteArrayRegion(result, 0, 871 nfc_jni_transceive_buffer->length - 2, 872 (jbyte *)nfc_jni_transceive_buffer->buffer); 873 } 874 } 875 } else { 876 result = e->NewByteArray(nfc_jni_transceive_buffer->length); 877 if (result != NULL) { 878 e->SetByteArrayRegion(result, 0, 879 nfc_jni_transceive_buffer->length, 880 (jbyte *)nfc_jni_transceive_buffer->buffer); 881 } 882 } 883 clean_and_return: 884 if(transceive_info.sRecvData.buffer != NULL) 885 { 886 free(transceive_info.sRecvData.buffer); 887 } 888 889 if ((outbuf != buf) && (outbuf != NULL)) { 890 // Buf was extended and re-alloced with crc bytes, free separately 891 free(outbuf); 892 } 893 894 e->ReleaseByteArrayElements(data, 895 (jbyte *)buf, JNI_ABORT); 896 897 if (targetLost != NULL) { 898 e->ReleaseIntArrayElements(statusTargetLost, targetLost, 0); 899 } 900 901 nfc_cb_data_deinit(&cb_data); 902 903 CONCURRENCY_UNLOCK(); 904 905 return result; 906 } 907 908 static jint com_android_nfc_NativeNfcTag_doGetNdefType(JNIEnv *e, jobject o, 909 jint libnfcType, jint javaType) 910 { 911 jint ndefType = NDEF_UNKNOWN_TYPE; 912 913 switch (libnfcType) { 914 case phNfc_eJewel_PICC: 915 ndefType = NDEF_TYPE1_TAG; 916 break; 917 case phNfc_eISO14443_3A_PICC: 918 ndefType = NDEF_TYPE2_TAG;; 919 break; 920 case phNfc_eFelica_PICC: 921 ndefType = NDEF_TYPE3_TAG; 922 break; 923 case phNfc_eISO14443_A_PICC: 924 case phNfc_eISO14443_4A_PICC: 925 case phNfc_eISO14443_B_PICC: 926 case phNfc_eISO14443_4B_PICC: 927 ndefType = NDEF_TYPE4_TAG; 928 break; 929 case phNfc_eMifare_PICC: 930 if (javaType == TARGET_TYPE_MIFARE_UL) { 931 ndefType = NDEF_TYPE2_TAG; 932 } else { 933 ndefType = NDEF_MIFARE_CLASSIC_TAG; 934 } 935 break; 936 case phNfc_eISO15693_PICC: 937 ndefType = NDEF_ICODE_SLI_TAG; 938 break; 939 default: 940 ndefType = NDEF_UNKNOWN_TYPE; 941 break; 942 } 943 return ndefType; 944 } 945 946 static jint com_android_nfc_NativeNfcTag_doCheckNdef(JNIEnv *e, jobject o, jintArray ndefinfo) 947 { 948 phLibNfc_Handle handle = 0; 949 jint status; 950 phLibNfc_ChkNdef_Info_t sNdefInfo; 951 struct nfc_jni_callback_data cb_data; 952 jint *ndef = e->GetIntArrayElements(ndefinfo, 0); 953 int apiCardState = NDEF_MODE_UNKNOWN; 954 955 CONCURRENCY_LOCK(); 956 957 /* Create the local semaphore */ 958 if (!nfc_cb_data_init(&cb_data, NULL)) 959 { 960 status = NFCSTATUS_NOT_ENOUGH_MEMORY; 961 goto clean_and_return; 962 } 963 cb_data.pContext = &sNdefInfo; 964 965 handle = nfc_jni_get_connected_handle(e, o); 966 967 TRACE("phLibNfc_Ndef_CheckNdef()"); 968 REENTRANCE_LOCK(); 969 status = phLibNfc_Ndef_CheckNdef(handle, nfc_jni_checkndef_callback,(void *)&cb_data); 970 REENTRANCE_UNLOCK(); 971 if(status != NFCSTATUS_PENDING) 972 { 973 LOGE("phLibNfc_Ndef_CheckNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 974 goto clean_and_return; 975 } 976 TRACE("phLibNfc_Ndef_CheckNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 977 978 /* Wait for callback response */ 979 if(sem_wait(&cb_data.sem)) 980 { 981 LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); 982 status = NFCSTATUS_ABORTED; 983 goto clean_and_return; 984 } 985 986 status = cb_data.status; 987 TRACE("phLibNfc_Ndef_CheckNdef() - Status code = %d", status); 988 989 if (status != NFCSTATUS_SUCCESS) 990 { 991 goto clean_and_return; 992 } 993 994 ndef[0] = sNdefInfo.MaxNdefMsgLength; 995 // Translate the card state to know values for the NFC API 996 switch (sNdefInfo.NdefCardState) { 997 case PHLIBNFC_NDEF_CARD_INITIALISED: 998 apiCardState = NDEF_MODE_READ_WRITE; 999 break; 1000 case PHLIBNFC_NDEF_CARD_READ_ONLY: 1001 apiCardState = NDEF_MODE_READ_ONLY; 1002 break; 1003 case PHLIBNFC_NDEF_CARD_READ_WRITE: 1004 apiCardState = NDEF_MODE_READ_WRITE; 1005 break; 1006 case PHLIBNFC_NDEF_CARD_INVALID: 1007 apiCardState = NDEF_MODE_UNKNOWN; 1008 break; 1009 } 1010 ndef[1] = apiCardState; 1011 1012 clean_and_return: 1013 e->ReleaseIntArrayElements(ndefinfo, ndef, 0); 1014 nfc_cb_data_deinit(&cb_data); 1015 CONCURRENCY_UNLOCK(); 1016 return status; 1017 } 1018 1019 static jboolean com_android_nfc_NativeNfcTag_doPresenceCheck(JNIEnv *e, jobject o) 1020 { 1021 phLibNfc_Handle handle = 0; 1022 NFCSTATUS status; 1023 jboolean result = JNI_FALSE; 1024 struct nfc_jni_callback_data cb_data; 1025 1026 CONCURRENCY_LOCK(); 1027 1028 /* Create the local semaphore */ 1029 if (!nfc_cb_data_init(&cb_data, NULL)) 1030 { 1031 goto clean_and_return; 1032 } 1033 1034 handle = nfc_jni_get_connected_handle(e, o); 1035 1036 TRACE("phLibNfc_RemoteDev_CheckPresence()"); 1037 REENTRANCE_LOCK(); 1038 status = phLibNfc_RemoteDev_CheckPresence(handle, nfc_jni_presencecheck_callback, (void *)&cb_data); 1039 REENTRANCE_UNLOCK(); 1040 1041 if(status != NFCSTATUS_PENDING) 1042 { 1043 LOGE("phLibNfc_RemoteDev_CheckPresence() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 1044 goto clean_and_return; 1045 } 1046 TRACE("phLibNfc_RemoteDev_CheckPresence() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 1047 1048 /* Wait for callback response */ 1049 if(sem_wait(&cb_data.sem)) 1050 { 1051 LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); 1052 goto clean_and_return; 1053 } 1054 1055 if (cb_data.status == NFCSTATUS_SUCCESS) 1056 { 1057 result = JNI_TRUE; 1058 } 1059 1060 clean_and_return: 1061 nfc_cb_data_deinit(&cb_data); 1062 1063 CONCURRENCY_UNLOCK(); 1064 1065 return result; 1066 } 1067 1068 static jboolean com_android_nfc_NativeNfcTag_doIsIsoDepNdefFormatable(JNIEnv *e, 1069 jobject o, jbyteArray pollBytes, jbyteArray actBytes) 1070 { 1071 // Determines whether this is a formatable IsoDep tag - currently only NXP DESFire 1072 // is supported. 1073 jboolean result = JNI_FALSE; 1074 1075 // DESfire has one sak byte and 2 ATQA bytes 1076 if (pollBytes != NULL && (e->GetArrayLength(pollBytes) >= 2) && 1077 actBytes != NULL && (e->GetArrayLength(actBytes) >= 1)) { 1078 jbyte* poll = e->GetByteArrayElements(pollBytes, NULL); 1079 jbyte* act = e->GetByteArrayElements(actBytes, NULL); 1080 if (act[0] == 0x20 && poll[1] == 0x03) { 1081 uint8_t cmd[] = {0x90, 0x60, 0x00, 0x00, 0x00}; 1082 // Identifies as DESfire, use get version cmd to be sure 1083 jbyteArray versionCmd = e->NewByteArray(5); 1084 e->SetByteArrayRegion(versionCmd, 0, 5, (jbyte*)cmd); 1085 jbyteArray respBytes = com_android_nfc_NativeNfcTag_doTransceive(e, o, 1086 versionCmd, JNI_TRUE, NULL); 1087 if (respBytes != NULL) { 1088 // Check whether the response matches a typical DESfire 1089 // response. 1090 // libNFC even does more advanced checking than we do 1091 // here, and will only format DESfire's with a certain 1092 // major/minor sw version and NXP as a manufacturer. 1093 // We don't want to do such checking here, to avoid 1094 // having to change code in multiple places. 1095 // A succesful (wrapped) DESFire getVersion command returns 1096 // 9 bytes, with byte 7 0x91 and byte 8 having status 1097 // code 0xAF (these values are fixed and well-known). 1098 int respLength = e->GetArrayLength(respBytes); 1099 jbyte* resp = e->GetByteArrayElements(respBytes, NULL); 1100 if (respLength == 9 && resp[7] == (jbyte)0x91 && 1101 resp[8] == (jbyte)0xAF) { 1102 result = JNI_TRUE; 1103 } 1104 e->ReleaseByteArrayElements(respBytes, (jbyte *)resp, JNI_ABORT); 1105 } 1106 } 1107 e->ReleaseByteArrayElements(pollBytes, (jbyte *)poll, JNI_ABORT); 1108 e->ReleaseByteArrayElements(actBytes, (jbyte *)act, JNI_ABORT); 1109 } 1110 1111 return result; 1112 } 1113 1114 static jboolean com_android_nfc_NativeNfcTag_doNdefFormat(JNIEnv *e, jobject o, jbyteArray key) 1115 { 1116 phLibNfc_Handle handle = 0; 1117 NFCSTATUS status; 1118 phNfc_sData_t keyBuffer; 1119 jboolean result = JNI_FALSE; 1120 struct nfc_jni_callback_data cb_data; 1121 1122 CONCURRENCY_LOCK(); 1123 1124 /* Create the local semaphore */ 1125 if (!nfc_cb_data_init(&cb_data, NULL)) 1126 { 1127 goto clean_and_return; 1128 } 1129 1130 handle = nfc_jni_get_connected_handle(e, o); 1131 1132 keyBuffer.buffer = (uint8_t *)e->GetByteArrayElements(key, NULL); 1133 keyBuffer.length = e->GetArrayLength(key); 1134 TRACE("phLibNfc_RemoteDev_FormatNdef()"); 1135 REENTRANCE_LOCK(); 1136 status = phLibNfc_RemoteDev_FormatNdef(handle, &keyBuffer, nfc_jni_formatndef_callback, (void *)&cb_data); 1137 REENTRANCE_UNLOCK(); 1138 1139 if(status != NFCSTATUS_PENDING) 1140 { 1141 LOGE("phLibNfc_RemoteDev_FormatNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 1142 goto clean_and_return; 1143 } 1144 TRACE("phLibNfc_RemoteDev_FormatNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 1145 1146 /* Wait for callback response */ 1147 if(sem_wait(&cb_data.sem)) 1148 { 1149 LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); 1150 goto clean_and_return; 1151 } 1152 1153 if (cb_data.status == NFCSTATUS_SUCCESS) 1154 { 1155 result = JNI_TRUE; 1156 } 1157 1158 clean_and_return: 1159 e->ReleaseByteArrayElements(key, (jbyte *)keyBuffer.buffer, JNI_ABORT); 1160 nfc_cb_data_deinit(&cb_data); 1161 CONCURRENCY_UNLOCK(); 1162 return result; 1163 } 1164 1165 static jboolean com_android_nfc_NativeNfcTag_doMakeReadonly(JNIEnv *e, jobject o) 1166 { 1167 phLibNfc_Handle handle = 0; 1168 NFCSTATUS status; 1169 jboolean result = JNI_FALSE; 1170 struct nfc_jni_callback_data cb_data; 1171 1172 CONCURRENCY_LOCK(); 1173 1174 /* Create the local semaphore */ 1175 if (!nfc_cb_data_init(&cb_data, NULL)) 1176 { 1177 goto clean_and_return; 1178 } 1179 1180 handle = nfc_jni_get_connected_handle(e, o); 1181 1182 TRACE("phLibNfc_ConvertToReadOnlyNdef()"); 1183 REENTRANCE_LOCK(); 1184 status = phLibNfc_ConvertToReadOnlyNdef(handle, nfc_jni_readonly_callback, (void *)&cb_data); 1185 REENTRANCE_UNLOCK(); 1186 1187 if(status != NFCSTATUS_PENDING) 1188 { 1189 LOGE("pphLibNfc_ConvertToReadOnlyNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 1190 goto clean_and_return; 1191 } 1192 TRACE("phLibNfc_ConvertToReadOnlyNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status)); 1193 1194 /* Wait for callback response */ 1195 if(sem_wait(&cb_data.sem)) 1196 { 1197 LOGE("Failed to wait for semaphore (errno=0x%08x)", errno); 1198 goto clean_and_return; 1199 } 1200 1201 if (cb_data.status == NFCSTATUS_SUCCESS) 1202 { 1203 result = JNI_TRUE; 1204 } 1205 1206 clean_and_return: 1207 nfc_cb_data_deinit(&cb_data); 1208 CONCURRENCY_UNLOCK(); 1209 return result; 1210 } 1211 /* 1212 * JNI registration. 1213 */ 1214 static JNINativeMethod gMethods[] = 1215 { 1216 {"doConnect", "(I)I", 1217 (void *)com_android_nfc_NativeNfcTag_doConnect}, 1218 {"doDisconnect", "()Z", 1219 (void *)com_android_nfc_NativeNfcTag_doDisconnect}, 1220 {"doReconnect", "()I", 1221 (void *)com_android_nfc_NativeNfcTag_doReconnect}, 1222 {"doHandleReconnect", "(I)I", 1223 (void *)com_android_nfc_NativeNfcTag_doHandleReconnect}, 1224 {"doTransceive", "([BZ[I)[B", 1225 (void *)com_android_nfc_NativeNfcTag_doTransceive}, 1226 {"doGetNdefType", "(II)I", 1227 (void *)com_android_nfc_NativeNfcTag_doGetNdefType}, 1228 {"doCheckNdef", "([I)I", 1229 (void *)com_android_nfc_NativeNfcTag_doCheckNdef}, 1230 {"doRead", "()[B", 1231 (void *)com_android_nfc_NativeNfcTag_doRead}, 1232 {"doWrite", "([B)Z", 1233 (void *)com_android_nfc_NativeNfcTag_doWrite}, 1234 {"doPresenceCheck", "()Z", 1235 (void *)com_android_nfc_NativeNfcTag_doPresenceCheck}, 1236 {"doIsIsoDepNdefFormatable", "([B[B)Z", 1237 (void *)com_android_nfc_NativeNfcTag_doIsIsoDepNdefFormatable}, 1238 {"doNdefFormat", "([B)Z", 1239 (void *)com_android_nfc_NativeNfcTag_doNdefFormat}, 1240 {"doMakeReadonly", "()Z", 1241 (void *)com_android_nfc_NativeNfcTag_doMakeReadonly}, 1242 }; 1243 1244 int register_com_android_nfc_NativeNfcTag(JNIEnv *e) 1245 { 1246 return jniRegisterNativeMethods(e, 1247 "com/android/nfc/nxp/NativeNfcTag", 1248 gMethods, NELEM(gMethods)); 1249 } 1250 1251 } // namespace android 1252