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