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
25static phLibNfc_Data_t nfc_jni_ndef_rw;
26static phLibNfc_Handle handle;
27uint8_t *nfc_jni_ndef_buf = NULL;
28uint32_t nfc_jni_ndef_buf_len = 0;
29
30extern uint8_t device_connected_flag;
31
32namespace android {
33
34extern phLibNfc_Handle storedHandle;
35
36extern void nfc_jni_restart_discovery_locked(struct nfc_jni_native_data *nat);
37extern void nfc_jni_reset_timeout_values();
38
39/*
40 * Callbacks
41 */
42 static void nfc_jni_tag_rw_callback(void *pContext, NFCSTATUS status)
43{
44   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
45   LOG_CALLBACK("nfc_jni_tag_rw_callback", status);
46
47   /* Report the callback status and wake up the caller */
48   pCallbackData->status = status;
49   sem_post(&pCallbackData->sem);
50}
51
52static 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
73static 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
100static 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
118static 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
131static phNfc_sData_t *nfc_jni_transceive_buffer;
132
133static 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
146static 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
156static 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
166static 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 */
177static 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
228clean_and_return:
229   nfc_cb_data_deinit(&cb_data);
230   CONCURRENCY_UNLOCK();
231
232   return buf;
233}
234
235
236static 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
283clean_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 */
294void 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 */
375void 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
440static 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
489clean_and_return:
490   nfc_cb_data_deinit(&cb_data);
491   CONCURRENCY_UNLOCK();
492   return status;
493}
494
495static jint com_android_nfc_NativeNfcTag_doHandleReconnect(JNIEnv *e,
496   jobject o, phLibNfc_Handle handle)
497{
498   jint status;
499   struct nfc_jni_callback_data cb_data;
500   phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL;
501   CONCURRENCY_LOCK();
502
503   /* Create the local semaphore */
504   if (!nfc_cb_data_init(&cb_data, &pRemDevInfo))
505   {
506      status = NFCSTATUS_NOT_ENOUGH_MEMORY;
507      goto clean_and_return;
508   }
509
510   TRACE("phLibNfc_RemoteDev_ReConnect(RW)");
511   REENTRANCE_LOCK();
512   storedHandle = handle;
513   status = phLibNfc_RemoteDev_ReConnect(handle, nfc_jni_connect_callback,(void *)&cb_data);
514   REENTRANCE_UNLOCK();
515   if(status != NFCSTATUS_PENDING)
516   {
517      ALOGE("phLibNfc_RemoteDev_ReConnect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
518      goto clean_and_return;
519   }
520   TRACE("phLibNfc_RemoteDev_ReConnect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
521
522   /* Wait for callback response */
523   if(sem_wait(&cb_data.sem))
524   {
525      ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
526      status = NFCSTATUS_ABORTED;
527      goto clean_and_return;
528   }
529
530   status = cb_data.status;
531
532   /* Connect Status */
533   if(status != NFCSTATUS_SUCCESS)
534   {
535      goto clean_and_return;
536   }
537
538clean_and_return:
539   nfc_cb_data_deinit(&cb_data);
540   CONCURRENCY_UNLOCK();
541   return status;
542}
543
544static 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
567static jboolean com_android_nfc_NativeNfcTag_doDisconnect(JNIEnv *e, jobject o)
568{
569   phLibNfc_Handle handle = 0;
570   NFCSTATUS status;
571   jboolean result = JNI_FALSE;
572   struct nfc_jni_callback_data cb_data;
573
574   CONCURRENCY_LOCK();
575
576   handle = nfc_jni_get_connected_handle(e, o);
577
578   /* Create the local semaphore */
579   if (!nfc_cb_data_init(&cb_data, NULL))
580   {
581      goto clean_and_return;
582   }
583
584   /* Reset the stored handle */
585   storedHandle = 0;
586
587   nfc_jni_reset_timeout_values();
588
589   /* Disconnect */
590   TRACE("Disconnecting from tag (%x)", handle);
591
592   if (handle == -1) {
593       // Was never connected to any tag, exit
594       result = JNI_TRUE;
595       ALOGE("doDisconnect() - Target already disconnected");
596       nfc_jni_restart_discovery_locked(nfc_jni_get_nat_ext(e));
597       goto clean_and_return;
598   }
599
600    TRACE("phLibNfc_RemoteDev_Disconnect(%x)", handle);
601    REENTRANCE_LOCK();
602    status = phLibNfc_RemoteDev_Disconnect(handle, NFC_DISCOVERY_CONTINUE,
603                                          nfc_jni_disconnect_callback, (void *)&cb_data);
604    REENTRANCE_UNLOCK();
605
606    if(status == NFCSTATUS_TARGET_NOT_CONNECTED)
607    {
608        result = JNI_TRUE;
609        TRACE("phLibNfc_RemoteDev_Disconnect() - Target already disconnected");
610        goto clean_and_return;
611    }
612    if(status != NFCSTATUS_PENDING)
613    {
614        ALOGE("phLibNfc_RemoteDev_Disconnect(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status));
615        nfc_jni_restart_discovery_locked(nfc_jni_get_nat_ext(e));
616        goto clean_and_return;
617    }
618    TRACE("phLibNfc_RemoteDev_Disconnect(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status));
619
620    /* Wait for callback response */
621    if(sem_wait(&cb_data.sem))
622    {
623       ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
624       goto clean_and_return;
625    }
626
627    /* Disconnect Status */
628    if(cb_data.status != NFCSTATUS_SUCCESS)
629    {
630        goto clean_and_return;
631    }
632
633    result = JNI_TRUE;
634
635clean_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
643static uint16_t
644crc_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
657static void
658nfc_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
667static void
668nfc_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
677static bool
678crc_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
695static 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    }
870clean_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
895static jint com_android_nfc_NativeNfcTag_doGetNdefType(JNIEnv *e, jobject o,
896        jint libnfcType, jint javaType)
897{
898    jint ndefType =  NDEF_UNKNOWN_TYPE;
899
900    switch (libnfcType) {
901          case phNfc_eJewel_PICC:
902              ndefType = NDEF_TYPE1_TAG;
903              break;
904          case phNfc_eISO14443_3A_PICC:
905              ndefType = NDEF_TYPE2_TAG;;
906              break;
907          case phNfc_eFelica_PICC:
908              ndefType = NDEF_TYPE3_TAG;
909              break;
910          case phNfc_eISO14443_A_PICC:
911          case phNfc_eISO14443_4A_PICC:
912          case phNfc_eISO14443_B_PICC:
913          case phNfc_eISO14443_4B_PICC:
914              ndefType = NDEF_TYPE4_TAG;
915              break;
916          case phNfc_eMifare_PICC:
917              if (javaType == TARGET_TYPE_MIFARE_UL) {
918                  ndefType = NDEF_TYPE2_TAG;
919              } else {
920                  ndefType = NDEF_MIFARE_CLASSIC_TAG;
921              }
922              break;
923          case phNfc_eISO15693_PICC:
924              ndefType = NDEF_ICODE_SLI_TAG;
925              break;
926          default:
927              ndefType = NDEF_UNKNOWN_TYPE;
928              break;
929    }
930    return ndefType;
931}
932
933static 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
999clean_and_return:
1000   e->ReleaseIntArrayElements(ndefinfo, ndef, 0);
1001   nfc_cb_data_deinit(&cb_data);
1002   CONCURRENCY_UNLOCK();
1003   return status;
1004}
1005
1006static 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
1047clean_and_return:
1048   nfc_cb_data_deinit(&cb_data);
1049
1050   CONCURRENCY_UNLOCK();
1051
1052   return result;
1053}
1054
1055static 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
1101static 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
1145clean_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
1152static 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
1196clean_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 */
1205static 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
1235int 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