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