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
26static phLibNfc_Data_t nfc_jni_ndef_rw;
27static phLibNfc_Handle handle;
28uint8_t *nfc_jni_ndef_buf = NULL;
29uint32_t nfc_jni_ndef_buf_len = 0;
30
31extern uint8_t device_connected_flag;
32
33namespace android {
34
35extern phLibNfc_Handle storedHandle;
36
37extern void nfc_jni_restart_discovery_locked(struct nfc_jni_native_data *nat);
38extern 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
53static 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
74static 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
101static 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
119static 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
132static phNfc_sData_t *nfc_jni_transceive_buffer;
133
134static 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
147static 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
157static 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
167static 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 */
178static 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
229clean_and_return:
230   nfc_cb_data_deinit(&cb_data);
231   CONCURRENCY_UNLOCK();
232
233   return buf;
234}
235
236
237static 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
284clean_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 */
295void 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 */
376void 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
441static 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
490clean_and_return:
491   nfc_cb_data_deinit(&cb_data);
492   CONCURRENCY_UNLOCK();
493   return status;
494}
495
496static 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
539clean_and_return:
540   nfc_cb_data_deinit(&cb_data);
541   CONCURRENCY_UNLOCK();
542   return status;
543}
544
545static 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
568static 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
636clean_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
644static uint16_t
645crc_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
658static void
659nfc_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
668static void
669nfc_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
678static bool
679crc_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
696static 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    }
871clean_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
896static 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
934static 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
1000clean_and_return:
1001   e->ReleaseIntArrayElements(ndefinfo, ndef, 0);
1002   nfc_cb_data_deinit(&cb_data);
1003   CONCURRENCY_UNLOCK();
1004   return status;
1005}
1006
1007static 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
1048clean_and_return:
1049   nfc_cb_data_deinit(&cb_data);
1050
1051   CONCURRENCY_UNLOCK();
1052
1053   return result;
1054}
1055
1056static 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
1102static 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
1146clean_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
1153static 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
1197clean_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 */
1206static 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
1236int 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