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