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