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