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