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 */
nfc_jni_tag_rw_callback(void * pContext,NFCSTATUS status)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
nfc_jni_connect_callback(void * pContext,phLibNfc_Handle,phLibNfc_sRemoteDevInformation_t * psRemoteDevInfo,NFCSTATUS status)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
nfc_jni_checkndef_callback(void * pContext,phLibNfc_ChkNdef_Info_t info,NFCSTATUS status)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
nfc_jni_disconnect_callback(void * pContext,phLibNfc_Handle,NFCSTATUS status)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
nfc_jni_async_disconnect_callback(void *,phLibNfc_Handle,NFCSTATUS status)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
nfc_jni_transceive_callback(void * pContext,phLibNfc_Handle,phNfc_sData_t * pResBuffer,NFCSTATUS status)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
nfc_jni_presencecheck_callback(void * pContext,NFCSTATUS status)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
nfc_jni_formatndef_callback(void * pContext,NFCSTATUS status)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
nfc_jni_readonly_callback(void * pContext,NFCSTATUS status)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 */
com_android_nfc_NativeNfcTag_doRead(JNIEnv * e,jobject o)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
com_android_nfc_NativeNfcTag_doWrite(JNIEnv * e,jobject o,jbyteArray buf)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 */
set_target_pollBytes(JNIEnv * e,jobject tag,phLibNfc_sRemoteDevInformation_t * psRemoteDevInfo)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 */
set_target_activationBytes(JNIEnv * e,jobject tag,phLibNfc_sRemoteDevInformation_t * psRemoteDevInfo)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
com_android_nfc_NativeNfcTag_doConnect(JNIEnv * e,jobject o,phLibNfc_Handle handle)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
com_android_nfc_NativeNfcTag_doHandleReconnect(JNIEnv *,jobject,phLibNfc_Handle handle)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
com_android_nfc_NativeNfcTag_doReconnect(JNIEnv * e,jobject o)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
com_android_nfc_NativeNfcTag_doDisconnect(JNIEnv * e,jobject o)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
crc_16_ccitt1(uint8_t * msg,size_t len,uint16_t init)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
nfc_insert_crc_a(uint8_t * msg,size_t len)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
nfc_get_crc_a(uint8_t * msg,size_t len,uint8_t * byte1,uint8_t * byte2)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
crc_valid(uint8_t * msg,size_t len)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
com_android_nfc_NativeNfcTag_doTransceive(JNIEnv * e,jobject o,jbyteArray data,jboolean raw,jintArray statusTargetLost)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
com_android_nfc_NativeNfcTag_doGetNdefType(JNIEnv *,jobject,jint libnfcType,jint javaType)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
com_android_nfc_NativeNfcTag_doCheckNdef(JNIEnv * e,jobject o,jintArray ndefinfo)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
com_android_nfc_NativeNfcTag_doPresenceCheck(JNIEnv * e,jobject o)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
com_android_nfc_NativeNfcTag_doIsIsoDepNdefFormatable(JNIEnv * e,jobject o,jbyteArray pollBytes,jbyteArray actBytes)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
com_android_nfc_NativeNfcTag_doNdefFormat(JNIEnv * e,jobject o,jbyteArray key)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
com_android_nfc_NativeNfcTag_doMakeReadonly(JNIEnv * e,jobject o,jbyteArray key)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
register_com_android_nfc_NativeNfcTag(JNIEnv * e)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