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 <pthread.h>
19#include <semaphore.h>
20#include <stdlib.h>
21#include <stdio.h>
22#include <math.h>
23#include <sys/queue.h>
24#include <hardware/hardware.h>
25#include <hardware/nfc.h>
26
27#include "com_android_nfc.h"
28
29#define ERROR_BUFFER_TOO_SMALL       -12
30#define ERROR_INSUFFICIENT_RESOURCES -9
31
32extern uint32_t libnfc_llc_error_count;
33
34static phLibNfc_sConfig_t   gDrvCfg;
35void   *gHWRef;
36static phNfc_sData_t gInputParam;
37static phNfc_sData_t gOutputParam;
38
39uint8_t device_connected_flag;
40static bool driverConfigured = FALSE;
41
42static phLibNfc_Handle              hLlcpHandle;
43static NFCSTATUS                    lastErrorStatus = NFCSTATUS_FAILED;
44static phLibNfc_Llcp_eLinkStatus_t  g_eLinkStatus = phFriNfc_LlcpMac_eLinkDefault;
45
46static jmethodID cached_NfcManager_notifyNdefMessageListeners;
47static jmethodID cached_NfcManager_notifyTransactionListeners;
48static jmethodID cached_NfcManager_notifyLlcpLinkActivation;
49static jmethodID cached_NfcManager_notifyLlcpLinkDeactivated;
50static jmethodID cached_NfcManager_notifyTargetDeselected;
51
52static jmethodID cached_NfcManager_notifySeFieldActivated;
53static jmethodID cached_NfcManager_notifySeFieldDeactivated;
54
55static jmethodID cached_NfcManager_notifySeApduReceived;
56static jmethodID cached_NfcManager_notifySeMifareAccess;
57static jmethodID cached_NfcManager_notifySeEmvCardRemoval;
58
59namespace android {
60
61phLibNfc_Handle     storedHandle = 0;
62
63struct nfc_jni_native_data *exported_nat = NULL;
64
65/* Internal functions declaration */
66static void *nfc_jni_client_thread(void *arg);
67static void nfc_jni_init_callback(void *pContext, NFCSTATUS status);
68static void nfc_jni_deinit_callback(void *pContext, NFCSTATUS status);
69static void nfc_jni_discover_callback(void *pContext, NFCSTATUS status);
70static void nfc_jni_se_set_mode_callback(void *context,
71        phLibNfc_Handle handle, NFCSTATUS status);
72static void nfc_jni_llcpcfg_callback(void *pContext, NFCSTATUS status);
73static void nfc_jni_start_discovery_locked(struct nfc_jni_native_data *nat);
74static void nfc_jni_Discovery_notification_callback(void *pContext,
75        phLibNfc_RemoteDevList_t *psRemoteDevList,
76        uint8_t uNofRemoteDev, NFCSTATUS status);
77static void nfc_jni_transaction_callback(void *context,
78        phLibNfc_eSE_EvtType_t evt_type, phLibNfc_Handle handle,
79        phLibNfc_uSeEvtInfo_t *evt_info, NFCSTATUS status);
80
81/*
82 * Deferred callback called when client thread must be exited
83 */
84static void client_kill_deferred_call(void* arg)
85{
86   struct nfc_jni_native_data *nat = (struct nfc_jni_native_data *)arg;
87
88   nat->running = FALSE;
89}
90
91static void kill_client(nfc_jni_native_data *nat)
92{
93   phDal4Nfc_Message_Wrapper_t  wrapper;
94   phLibNfc_DeferredCall_t     *pMsg;
95
96   usleep(50000);
97
98   LOGD("Terminating client thread...");
99
100   pMsg = (phLibNfc_DeferredCall_t*)malloc(sizeof(phLibNfc_DeferredCall_t));
101   pMsg->pCallback = client_kill_deferred_call;
102   pMsg->pParameter = (void*)nat;
103
104   wrapper.msg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
105   wrapper.msg.pMsgData = pMsg;
106   wrapper.msg.Size     = sizeof(phLibNfc_DeferredCall_t);
107
108   phDal4Nfc_msgsnd(gDrvCfg.nClientId, (struct msgbuf *)&wrapper, sizeof(phLibNfc_Message_t), 0);
109}
110
111static void nfc_jni_ioctl_callback(void *pContext, phNfc_sData_t *pOutput, NFCSTATUS status) {
112   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
113   LOG_CALLBACK("nfc_jni_ioctl_callback", status);
114
115   /* Report the callback status and wake up the caller */
116   pCallbackData->status = status;
117   sem_post(&pCallbackData->sem);
118}
119
120static void nfc_jni_deinit_download_callback(void *pContext, NFCSTATUS status)
121{
122   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
123   LOG_CALLBACK("nfc_jni_deinit_download_callback", status);
124
125   /* Report the callback status and wake up the caller */
126   pCallbackData->status = status;
127   sem_post(&pCallbackData->sem);
128}
129
130static int nfc_jni_download(struct nfc_jni_native_data *nat, uint8_t update)
131{
132    uint8_t OutputBuffer[1];
133    uint8_t InputBuffer[1];
134    struct timespec ts;
135    NFCSTATUS status = NFCSTATUS_FAILED;
136    phLibNfc_StackCapabilities_t caps;
137    struct nfc_jni_callback_data cb_data;
138
139    /* Create the local semaphore */
140    if (!nfc_cb_data_init(&cb_data, NULL))
141    {
142       goto clean_and_return;
143    }
144
145    if(update)
146    {
147        //deinit
148        TRACE("phLibNfc_Mgt_DeInitialize() (download)");
149        REENTRANCE_LOCK();
150        status = phLibNfc_Mgt_DeInitialize(gHWRef, nfc_jni_deinit_download_callback, (void *)&cb_data);
151        REENTRANCE_UNLOCK();
152        if (status != NFCSTATUS_PENDING)
153        {
154            LOGE("phLibNfc_Mgt_DeInitialize() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
155        }
156
157        clock_gettime(CLOCK_REALTIME, &ts);
158        ts.tv_sec += 5;
159
160        /* Wait for callback response */
161        if(sem_timedwait(&cb_data.sem, &ts))
162        {
163            LOGW("Deinitialization timed out (download)");
164        }
165
166        if(cb_data.status != NFCSTATUS_SUCCESS)
167        {
168            LOGW("Deinitialization FAILED (download)");
169        }
170        TRACE("Deinitialization SUCCESS (download)");
171    }
172
173    TRACE("Go in Download Mode");
174    phLibNfc_Download_Mode();
175
176    // Download
177    gInputParam.buffer  = InputBuffer;
178    gInputParam.length  = 0x01;
179    gOutputParam.buffer = OutputBuffer;
180    gOutputParam.length = 0x01;
181
182    LOGD("Download new Firmware");
183    REENTRANCE_LOCK();
184    status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_FW_DOWNLOAD, &gInputParam, &gOutputParam, nfc_jni_ioctl_callback, (void *)&cb_data);
185    REENTRANCE_UNLOCK();
186    if(status != NFCSTATUS_PENDING)
187    {
188        LOGE("phLibNfc_Mgt_IoCtl() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
189        status = NFCSTATUS_FAILED;
190        goto clean_and_return;
191    }
192    TRACE("phLibNfc_Mgt_IoCtl() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
193
194    /* Wait for callback response */
195    if(sem_wait(&cb_data.sem))
196    {
197       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
198       status = NFCSTATUS_FAILED;
199       goto clean_and_return;
200    }
201
202    /* NOTE: we will get NFCSTATUS_FEATURE_NOT_SUPPORTED when we
203       try to download an old-style firmware on top of a new-style
204       firmware.  Hence, this is expected behavior, and not an
205       error condition. */
206    if(cb_data.status != NFCSTATUS_SUCCESS && cb_data.status != NFCSTATUS_FEATURE_NOT_SUPPORTED)
207    {
208        status = cb_data.status;
209        goto clean_and_return;
210    }
211
212    if(cb_data.status == NFCSTATUS_FEATURE_NOT_SUPPORTED)
213    {
214        LOGW("Old-style firmware not installed on top of new-style firmware. Using existing firmware in the chip.");
215    }
216
217reinit:
218    TRACE("phLibNfc_HW_Reset()");
219    phLibNfc_HW_Reset();
220
221    TRACE("phLibNfc_Mgt_Initialize()");
222    REENTRANCE_LOCK();
223    status = phLibNfc_Mgt_Initialize(gHWRef, nfc_jni_init_callback, (void *)&cb_data);
224    REENTRANCE_UNLOCK();
225    if(status != NFCSTATUS_PENDING)
226    {
227        LOGE("phLibNfc_Mgt_Initialize() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
228        goto clean_and_return;
229    }
230    TRACE("phLibNfc_Mgt_Initialize() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
231
232    if(sem_wait(&cb_data.sem))
233    {
234       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
235       status = NFCSTATUS_FAILED;
236       goto clean_and_return;
237    }
238
239    /* Initialization Status */
240    if(cb_data.status != NFCSTATUS_SUCCESS)
241    {
242        status = cb_data.status;
243        goto clean_and_return;
244    }
245
246    /* ====== CAPABILITIES ======= */
247    REENTRANCE_LOCK();
248    status = phLibNfc_Mgt_GetstackCapabilities(&caps, (void*)nat);
249    REENTRANCE_UNLOCK();
250    if (status != NFCSTATUS_SUCCESS)
251    {
252       LOGW("phLibNfc_Mgt_GetstackCapabilities returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
253    }
254    else
255    {
256        LOGD("NFC capabilities: HAL = %x, FW = %x, HW = %x, Model = %x, HCI = %x, Full_FW = %d, Rev = %d, FW Update Info = %d",
257              caps.psDevCapabilities.hal_version,
258              caps.psDevCapabilities.fw_version,
259              caps.psDevCapabilities.hw_version,
260              caps.psDevCapabilities.model_id,
261              caps.psDevCapabilities.hci_version,
262              caps.psDevCapabilities.full_version[NXP_FULL_VERSION_LEN-1],
263              caps.psDevCapabilities.full_version[NXP_FULL_VERSION_LEN-2],
264              caps.psDevCapabilities.firmware_update_info);
265    }
266
267    /*Download is successful*/
268    status = NFCSTATUS_SUCCESS;
269
270clean_and_return:
271   nfc_cb_data_deinit(&cb_data);
272   return status;
273}
274
275static int nfc_jni_configure_driver(struct nfc_jni_native_data *nat)
276{
277    char value[PROPERTY_VALUE_MAX];
278    int result = FALSE;
279    NFCSTATUS status;
280
281    /* ====== CONFIGURE DRIVER ======= */
282    /* Configure hardware link */
283    gDrvCfg.nClientId = phDal4Nfc_msgget(0, 0600);
284
285    TRACE("phLibNfc_Mgt_ConfigureDriver(0x%08x, 0x%08x)", gDrvCfg.nClientId);
286    REENTRANCE_LOCK();
287    status = phLibNfc_Mgt_ConfigureDriver(&gDrvCfg, &gHWRef);
288    REENTRANCE_UNLOCK();
289    if(status == NFCSTATUS_ALREADY_INITIALISED) {
290           LOGW("phLibNfc_Mgt_ConfigureDriver() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
291    }
292    else if(status != NFCSTATUS_SUCCESS)
293    {
294        LOGE("phLibNfc_Mgt_ConfigureDriver() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
295        goto clean_and_return;
296    }
297    TRACE("phLibNfc_Mgt_ConfigureDriver() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
298
299    if(pthread_create(&(nat->thread), NULL, nfc_jni_client_thread, nat) != 0)
300    {
301        LOGE("pthread_create failed");
302        goto clean_and_return;
303    }
304
305    driverConfigured = TRUE;
306
307clean_and_return:
308    return result;
309}
310
311static int nfc_jni_unconfigure_driver(struct nfc_jni_native_data *nat)
312{
313    int result = FALSE;
314    NFCSTATUS status;
315
316    /* Unconfigure driver */
317    TRACE("phLibNfc_Mgt_UnConfigureDriver()");
318    REENTRANCE_LOCK();
319    status = phLibNfc_Mgt_UnConfigureDriver(gHWRef);
320    REENTRANCE_UNLOCK();
321    if(status != NFCSTATUS_SUCCESS)
322    {
323        LOGE("phLibNfc_Mgt_UnConfigureDriver() returned error 0x%04x[%s] -- this should never happen", status, nfc_jni_get_status_name( status));
324    }
325    else
326    {
327       LOGD("phLibNfc_Mgt_UnConfigureDriver() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
328       result = TRUE;
329    }
330
331    driverConfigured = FALSE;
332
333    return result;
334}
335
336static short get_p2p_mode() {
337    char value[PROPERTY_VALUE_MAX];
338    property_get("debug.nfc.NXP_NFCI_MODE", value, "");
339    if (value[0]) {
340        short mode;
341        mode = atoi(value);
342        LOGD("debug.nfc.NXP_NFCI_MODE = %X", mode);
343        return mode;
344    }
345    return phNfc_eP2P_ALL;  // default
346}
347
348static bool get_p2p_target_disable() {
349    char value[PROPERTY_VALUE_MAX];
350    property_get("debug.nfc.TARGET_DISABLE", value, "");
351    if (value[0]) {
352        int mode;
353        mode = atoi(value);
354        LOGD("debug.nfc.TARGET_DISABLE = %d", mode);
355        return mode;
356    }
357    return FALSE;  // default
358}
359
360/* Initialization function */
361static int nfc_jni_initialize(struct nfc_jni_native_data *nat) {
362   struct timespec ts;
363   uint8_t resp[16];
364   NFCSTATUS status;
365   phLibNfc_StackCapabilities_t caps;
366   phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE];
367   uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index = 0, SmartMX_detected = 0;
368   phLibNfc_Llcp_sLinkParameters_t LlcpConfigInfo;
369   struct nfc_jni_callback_data cb_data;
370   uint8_t firmware_status;
371   uint8_t update = TRUE;
372   int result = JNI_FALSE;
373   const hw_module_t* hw_module;
374   nfc_pn544_device_t* pn544_dev = NULL;
375   int ret = 0;
376   LOGD("Start Initialization\n");
377
378   /* Create the local semaphore */
379   if (!nfc_cb_data_init(&cb_data, NULL))
380   {
381      goto clean_and_return;
382   }
383   /* Get EEPROM values and device port from product-specific settings */
384   ret = hw_get_module(NFC_HARDWARE_MODULE_ID, &hw_module);
385   if (ret) {
386      LOGE("hw_get_module() failed.");
387      goto clean_and_return;
388   }
389   ret = nfc_pn544_open(hw_module, &pn544_dev);
390   if (ret) {
391      LOGE("Could not open pn544 hw_module.");
392      goto clean_and_return;
393   }
394   if (pn544_dev->num_eeprom_settings == 0 || pn544_dev->eeprom_settings == NULL) {
395       LOGE("Could not load EEPROM settings");
396       goto clean_and_return;
397   }
398
399   /* Reset device connected handle */
400   device_connected_flag = 0;
401
402   /* Reset stored handle */
403   storedHandle = 0;
404
405   /* Initialize Driver */
406   if(!driverConfigured)
407   {
408       nfc_jni_configure_driver(nat);
409   }
410
411   /* ====== INITIALIZE ======= */
412
413   TRACE("phLibNfc_Mgt_Initialize()");
414   REENTRANCE_LOCK();
415   status = phLibNfc_Mgt_Initialize(gHWRef, nfc_jni_init_callback, (void *)&cb_data);
416   REENTRANCE_UNLOCK();
417   if(status != NFCSTATUS_PENDING)
418   {
419      LOGE("phLibNfc_Mgt_Initialize() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
420      update = FALSE;
421      goto force_download;
422   }
423   TRACE("phLibNfc_Mgt_Initialize returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
424
425   /* Wait for callback response */
426   if(sem_wait(&cb_data.sem))
427   {
428      LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
429      goto clean_and_return;
430   }
431
432   /* Initialization Status */
433   if(cb_data.status != NFCSTATUS_SUCCESS)
434   {
435      update = FALSE;
436      goto force_download;
437   }
438
439   /* ====== CAPABILITIES ======= */
440
441   REENTRANCE_LOCK();
442   status = phLibNfc_Mgt_GetstackCapabilities(&caps, (void*)nat);
443   REENTRANCE_UNLOCK();
444   if (status != NFCSTATUS_SUCCESS)
445   {
446      LOGW("phLibNfc_Mgt_GetstackCapabilities returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
447   }
448   else
449   {
450       LOGD("NFC capabilities: HAL = %x, FW = %x, HW = %x, Model = %x, HCI = %x, Full_FW = %d, Rev = %d, FW Update Info = %d",
451             caps.psDevCapabilities.hal_version,
452             caps.psDevCapabilities.fw_version,
453             caps.psDevCapabilities.hw_version,
454             caps.psDevCapabilities.model_id,
455             caps.psDevCapabilities.hci_version,
456             caps.psDevCapabilities.full_version[NXP_FULL_VERSION_LEN-1],
457             caps.psDevCapabilities.full_version[NXP_FULL_VERSION_LEN-2],
458             caps.psDevCapabilities.firmware_update_info);
459   }
460
461   /* ====== FIRMWARE VERSION ======= */
462   if(caps.psDevCapabilities.firmware_update_info)
463   {
464force_download:
465       for (i=0; i<3; i++)
466       {
467           TRACE("Firmware version not UpToDate");
468           status = nfc_jni_download(nat, update);
469           if(status == NFCSTATUS_SUCCESS)
470           {
471               LOGI("Firmware update SUCCESS");
472               break;
473           }
474           LOGW("Firmware update FAILED");
475           update = FALSE;
476       }
477       if(i>=3)
478       {
479           LOGE("Unable to update firmware, giving up");
480           goto clean_and_return;
481       }
482   }
483   else
484   {
485       TRACE("Firmware version UpToDate");
486   }
487
488   /* ====== EEPROM SETTINGS ======= */
489
490   // Update EEPROM settings
491   TRACE("******  START EEPROM SETTINGS UPDATE ******");
492   for (i = 0; i < pn544_dev->num_eeprom_settings; i++)
493   {
494      gInputParam.buffer = &(pn544_dev->eeprom_settings[i*4]);
495      gInputParam.length = 0x04;
496      gOutputParam.buffer = resp;
497
498      TRACE("> EEPROM SETTING: %d", i);
499
500      REENTRANCE_LOCK();
501      status = phLibNfc_Mgt_IoCtl(gHWRef, NFC_MEM_WRITE, &gInputParam, &gOutputParam, nfc_jni_ioctl_callback, (void *)&cb_data);
502      REENTRANCE_UNLOCK();
503      if (status != NFCSTATUS_PENDING) {
504         LOGE("phLibNfc_Mgt_IoCtl() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
505         goto clean_and_return;
506      }
507      /* Wait for callback response */
508      if(sem_wait(&cb_data.sem))
509      {
510         LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
511         goto clean_and_return;
512      }
513
514      /* Initialization Status */
515      if (cb_data.status != NFCSTATUS_SUCCESS)
516      {
517         goto clean_and_return;
518      }
519   }
520   TRACE("******  ALL EEPROM SETTINGS UPDATED  ******");
521
522   /* ====== SECURE ELEMENTS ======= */
523
524   REENTRANCE_LOCK();
525   LOGD("phLibNfc_SE_GetSecureElementList()");
526   status = phLibNfc_SE_GetSecureElementList(SE_List, &No_SE);
527   REENTRANCE_UNLOCK();
528   if (status != NFCSTATUS_SUCCESS)
529   {
530      LOGD("phLibNfc_SE_GetSecureElementList(): Error");
531      goto clean_and_return;
532   }
533
534   LOGD("\n> Number of Secure Element(s) : %d\n", No_SE);
535   /* Display Secure Element information */
536   for (i = 0; i < No_SE; i++)
537   {
538      if (SE_List[i].eSE_Type == phLibNfc_SE_Type_SmartMX) {
539         LOGD("phLibNfc_SE_GetSecureElementList(): SMX detected, handle=%p", (void*)SE_List[i].hSecureElement);
540      } else if (SE_List[i].eSE_Type == phLibNfc_SE_Type_UICC) {
541         LOGD("phLibNfc_SE_GetSecureElementList(): UICC detected, handle=%p", (void*)SE_List[i].hSecureElement);
542      }
543
544      /* Set SE mode - Off */
545      REENTRANCE_LOCK();
546      status = phLibNfc_SE_SetMode(SE_List[i].hSecureElement,
547            phLibNfc_SE_ActModeOff, nfc_jni_se_set_mode_callback,
548            (void *)&cb_data);
549      REENTRANCE_UNLOCK();
550      if (status != NFCSTATUS_PENDING)
551      {
552         LOGE("phLibNfc_SE_SetMode() returned 0x%04x[%s]", status,
553               nfc_jni_get_status_name(status));
554         goto clean_and_return;
555      }
556      LOGD("phLibNfc_SE_SetMode() returned 0x%04x[%s]", status,
557            nfc_jni_get_status_name(status));
558
559      /* Wait for callback response */
560      if(sem_wait(&cb_data.sem))
561      {
562         LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
563         goto clean_and_return;
564      }
565   }
566
567   /* ====== LLCP ======= */
568
569   /* LLCP Params */
570   TRACE("******  NFC Config Mode NFCIP1 - LLCP ******");
571   LlcpConfigInfo.miu    = nat->miu;
572   LlcpConfigInfo.lto    = nat->lto;
573   LlcpConfigInfo.wks    = nat->wks;
574   LlcpConfigInfo.option = nat->opt;
575
576   REENTRANCE_LOCK();
577   status = phLibNfc_Mgt_SetLlcp_ConfigParams(&LlcpConfigInfo,
578                                              nfc_jni_llcpcfg_callback,
579                                              (void *)&cb_data);
580   REENTRANCE_UNLOCK();
581   if(status != NFCSTATUS_PENDING)
582   {
583      LOGE("phLibNfc_Mgt_SetLlcp_ConfigParams returned 0x%04x[%s]", status,
584           nfc_jni_get_status_name(status));
585      goto clean_and_return;
586   }
587   TRACE("phLibNfc_Mgt_SetLlcp_ConfigParams returned 0x%04x[%s]", status,
588         nfc_jni_get_status_name(status));
589
590   /* Wait for callback response */
591   if(sem_wait(&cb_data.sem))
592   {
593      LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
594      goto clean_and_return;
595   }
596
597   /* ===== DISCOVERY ==== */
598   nat->discovery_cfg.NfcIP_Mode = get_p2p_mode();  //initiator
599   nat->discovery_cfg.Duration = 300000; /* in ms */
600   nat->discovery_cfg.NfcIP_Tgt_Disable = get_p2p_target_disable();
601
602   /* Register for the card emulation mode */
603   REENTRANCE_LOCK();
604   ret = phLibNfc_SE_NtfRegister(nfc_jni_transaction_callback,(void *)nat);
605   REENTRANCE_UNLOCK();
606   if(ret != NFCSTATUS_SUCCESS)
607   {
608        LOGD("phLibNfc_SE_NtfRegister returned 0x%02x",ret);
609        goto clean_and_return;
610   }
611   TRACE("phLibNfc_SE_NtfRegister returned 0x%x\n", ret);
612
613
614   /* ====== END ======= */
615
616   LOGI("NFC Initialized");
617
618   result = TRUE;
619
620clean_and_return:
621   if (result != TRUE)
622   {
623      if(nat)
624      {
625         kill_client(nat);
626      }
627   }
628   if (pn544_dev != NULL) {
629       nfc_pn544_close(pn544_dev);
630   }
631   nfc_cb_data_deinit(&cb_data);
632
633   return result;
634}
635
636static int is_user_build() {
637    char value[PROPERTY_VALUE_MAX];
638    property_get("ro.build.type", value, "");
639    return !strncmp("user", value, PROPERTY_VALUE_MAX);
640}
641
642/*
643 * Last-chance fallback when there is no clean way to recover
644 * Performs a software reset
645  */
646void emergency_recovery(struct nfc_jni_native_data *nat) {
647   if (!is_user_build()) {
648       LOGE("emergency_recovery: force restart of NFC service");
649   } else {
650       // dont recover immediately, so we can debug
651       unsigned int t;
652       for (t=1; t < 1000000; t <<= 1) {
653           LOGE("emergency_recovery: NFC stack dead-locked, please show to npelly");
654           sleep(t);
655       }
656   }
657   abort();  // force a noisy crash
658}
659
660void nfc_jni_reset_timeout_values()
661{
662    REENTRANCE_LOCK();
663    phLibNfc_SetIsoXchgTimeout(NXP_ISO_XCHG_TIMEOUT);
664    phLibNfc_SetHciTimeout(NXP_NFC_HCI_TIMEOUT);
665    phLibNfc_SetFelicaTimeout(NXP_FELICA_XCHG_TIMEOUT);
666    phLibNfc_SetMifareRawTimeout(NXP_MIFARE_XCHG_TIMEOUT);
667    REENTRANCE_UNLOCK();
668}
669
670/*
671 * Restart the polling loop when unable to perform disconnect
672  */
673void nfc_jni_restart_discovery_locked(struct nfc_jni_native_data *nat)
674{
675   int ret;
676   struct nfc_jni_callback_data cb_data;
677
678   TRACE("Restarting polling loop");
679
680   /* Create the local semaphore */
681   if (!nfc_cb_data_init(&cb_data, NULL))
682   {
683      goto clean_and_return;
684   }
685
686   /* Reset the PN544 ISO XCHG / sw watchdog timeouts */
687   nfc_jni_reset_timeout_values();
688
689   /* Reset device connected flag */
690   device_connected_flag = 0;
691
692   /* Restart Polling loop */
693   TRACE("******  Start NFC Discovery ******");
694   REENTRANCE_LOCK();
695   ret = phLibNfc_Mgt_ConfigureDiscovery(NFC_DISCOVERY_RESUME,nat->discovery_cfg, nfc_jni_discover_callback, (void *)&cb_data);
696   REENTRANCE_UNLOCK();
697   TRACE("phLibNfc_Mgt_ConfigureDiscovery(%s-%s-%s-%s-%s-%s, %s-%x-%x) returned 0x%08x\n",
698      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443A==TRUE?"3A":"",
699      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443B==TRUE?"3B":"",
700      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica212==TRUE?"F2":"",
701      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica424==TRUE?"F4":"",
702      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableNfcActive==TRUE?"NFC":"",
703      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso15693==TRUE?"RFID":"",
704      nat->discovery_cfg.PollDevInfo.PollCfgInfo.DisableCardEmulation==FALSE?"CE":"",
705      nat->discovery_cfg.NfcIP_Mode, nat->discovery_cfg.Duration, ret);
706
707   if (ret != NFCSTATUS_PENDING)
708   {
709      emergency_recovery(nat);
710      goto clean_and_return;
711   }
712
713   /* Wait for callback response */
714   if(sem_wait(&cb_data.sem))
715   {
716      LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
717      goto clean_and_return;
718   }
719
720clean_and_return:
721   nfc_cb_data_deinit(&cb_data);
722
723}
724
725 /*
726  *  Utility to recover UID from target infos
727  */
728static phNfc_sData_t get_target_uid(phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo)
729{
730    phNfc_sData_t uid;
731
732    switch(psRemoteDevInfo->RemDevType)
733    {
734    case phNfc_eISO14443_A_PICC:
735    case phNfc_eISO14443_4A_PICC:
736    case phNfc_eISO14443_3A_PICC:
737    case phNfc_eMifare_PICC:
738        uid.buffer = psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Uid;
739        uid.length = psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.UidLength;
740        break;
741    case phNfc_eISO14443_B_PICC:
742    case phNfc_eISO14443_4B_PICC:
743        uid.buffer = psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.Pupi;
744        uid.length = sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.Pupi);
745        break;
746    case phNfc_eFelica_PICC:
747        uid.buffer = psRemoteDevInfo->RemoteDevInfo.Felica_Info.IDm;
748        uid.length = psRemoteDevInfo->RemoteDevInfo.Felica_Info.IDmLength;
749        break;
750    case phNfc_eJewel_PICC:
751        uid.buffer = psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid;
752        uid.length = psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength;
753        break;
754    case phNfc_eISO15693_PICC:
755        uid.buffer = psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Uid;
756        uid.length = psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength;
757        break;
758    case phNfc_eNfcIP1_Target:
759    case phNfc_eNfcIP1_Initiator:
760        uid.buffer = psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.NFCID;
761        uid.length = psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.NFCID_Length;
762        break;
763    default:
764        uid.buffer = NULL;
765        uid.length = 0;
766        break;
767    }
768
769    return uid;
770}
771
772/*
773 * NFC stack message processing
774 */
775static void *nfc_jni_client_thread(void *arg)
776{
777   struct nfc_jni_native_data *nat;
778   JNIEnv *e;
779   JavaVMAttachArgs thread_args;
780   phDal4Nfc_Message_Wrapper_t wrapper;
781
782   nat = (struct nfc_jni_native_data *)arg;
783
784   thread_args.name = "NFC Message Loop";
785   thread_args.version = nat->env_version;
786   thread_args.group = NULL;
787
788   nat->vm->AttachCurrentThread(&e, &thread_args);
789   pthread_setname_np(pthread_self(), "message");
790
791   TRACE("NFC client started");
792   nat->running = TRUE;
793   while(nat->running == TRUE)
794   {
795      /* Fetch next message from the NFC stack message queue */
796      if(phDal4Nfc_msgrcv(gDrvCfg.nClientId, (void *)&wrapper,
797         sizeof(phLibNfc_Message_t), 0, 0) == -1)
798      {
799         LOGE("NFC client received bad message");
800         continue;
801      }
802
803      switch(wrapper.msg.eMsgType)
804      {
805         case PH_LIBNFC_DEFERREDCALL_MSG:
806         {
807            phLibNfc_DeferredCall_t *msg =
808               (phLibNfc_DeferredCall_t *)(wrapper.msg.pMsgData);
809
810            REENTRANCE_LOCK();
811            msg->pCallback(msg->pParameter);
812            REENTRANCE_UNLOCK();
813
814            break;
815         }
816      }
817   }
818   TRACE("NFC client stopped");
819
820   nat->vm->DetachCurrentThread();
821
822   return NULL;
823}
824
825extern uint8_t nfc_jni_is_ndef;
826extern uint8_t *nfc_jni_ndef_buf;
827extern uint32_t nfc_jni_ndef_buf_len;
828
829static phLibNfc_sNfcIPCfg_t nfc_jni_nfcip1_cfg =
830{
831   3,
832   { 0x46, 0x66, 0x6D }
833};
834
835/*
836 * Callbacks
837 */
838
839/* P2P - LLCP callbacks */
840static void nfc_jni_llcp_linkStatus_callback(void *pContext,
841                                                    phFriNfc_LlcpMac_eLinkStatus_t   eLinkStatus)
842{
843   phFriNfc_Llcp_sLinkParameters_t  sLinkParams;
844   JNIEnv *e;
845   NFCSTATUS status;
846
847   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
848
849   struct nfc_jni_native_data *nat = (nfc_jni_native_data *)pContextData->pContext;
850
851   nfc_jni_listen_data_t * pListenData = NULL;
852   nfc_jni_native_monitor * pMonitor = nfc_jni_get_monitor();
853
854   TRACE("Callback: nfc_jni_llcp_linkStatus_callback()");
855
856   nat->vm->GetEnv( (void **)&e, nat->env_version);
857
858   /* Update link status */
859   g_eLinkStatus = eLinkStatus;
860
861   if(eLinkStatus == phFriNfc_LlcpMac_eLinkActivated)
862   {
863      REENTRANCE_LOCK();
864      status = phLibNfc_Llcp_GetRemoteInfo(hLlcpHandle, &sLinkParams);
865      REENTRANCE_UNLOCK();
866      if(status != NFCSTATUS_SUCCESS)
867      {
868           LOGW("GetRemote Info failded - Status = %02x",status);
869      }
870      else
871      {
872           LOGI("LLCP Link activated (LTO=%d, MIU=%d, OPTION=0x%02x, WKS=0x%02x)",sLinkParams.lto,
873                                                                                  sLinkParams.miu,
874                                                                                  sLinkParams.option,
875                                                                                  sLinkParams.wks);
876           device_connected_flag = 1;
877      }
878   }
879   else if(eLinkStatus == phFriNfc_LlcpMac_eLinkDeactivated)
880   {
881      LOGI("LLCP Link deactivated");
882      free(pContextData);
883      /* Reset device connected flag */
884      device_connected_flag = 0;
885
886      /* Reset incoming socket list */
887      while (!LIST_EMPTY(&pMonitor->incoming_socket_head))
888      {
889         pListenData = LIST_FIRST(&pMonitor->incoming_socket_head);
890         LIST_REMOVE(pListenData, entries);
891         free(pListenData);
892      }
893
894      /* Notify manager that the LLCP is lost or deactivated */
895      e->CallVoidMethod(nat->manager, cached_NfcManager_notifyLlcpLinkDeactivated, nat->tag);
896      if(e->ExceptionCheck())
897      {
898         LOGE("Exception occured");
899         kill_client(nat);
900      }
901   }
902}
903
904static void nfc_jni_checkLlcp_callback(void *context,
905                                              NFCSTATUS status)
906{
907   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)context;
908
909   LOG_CALLBACK("nfc_jni_checkLlcp_callback", status);
910
911   pContextData->status = status;
912   sem_post(&pContextData->sem);
913}
914
915static void nfc_jni_llcpcfg_callback(void *pContext, NFCSTATUS status)
916{
917   struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
918   LOG_CALLBACK("nfc_jni_llcpcfg_callback", status);
919
920   /* Report the callback status and wake up the caller */
921   pCallbackData->status = status;
922   sem_post(&pCallbackData->sem);
923}
924
925static void nfc_jni_llcp_transport_listen_socket_callback(void              *pContext,
926                                                          phLibNfc_Handle   hIncomingSocket)
927{
928   phLibNfc_Handle hServiceSocket = (phLibNfc_Handle)pContext;
929   nfc_jni_listen_data_t * pListenData = NULL;
930   nfc_jni_native_monitor * pMonitor = nfc_jni_get_monitor();
931
932   TRACE("nfc_jni_llcp_transport_listen_socket_callback socket handle = %p", (void*)hIncomingSocket);
933
934   pthread_mutex_lock(&pMonitor->incoming_socket_mutex);
935
936   /* Store the connection request */
937   pListenData = (nfc_jni_listen_data_t*)malloc(sizeof(nfc_jni_listen_data_t));
938   if (pListenData == NULL)
939   {
940      LOGE("Failed to create structure to handle incoming LLCP connection request");
941      goto clean_and_return;
942   }
943   pListenData->pServerSocket = hServiceSocket;
944   pListenData->pIncomingSocket = hIncomingSocket;
945   LIST_INSERT_HEAD(&pMonitor->incoming_socket_head, pListenData, entries);
946
947   /* Signal pending accept operations that the list is updated */
948   pthread_cond_broadcast(&pMonitor->incoming_socket_cond);
949
950clean_and_return:
951   pthread_mutex_unlock(&pMonitor->incoming_socket_mutex);
952}
953
954void nfc_jni_llcp_transport_socket_err_callback(void*      pContext,
955                                                       uint8_t    nErrCode)
956{
957   PHNFC_UNUSED_VARIABLE(pContext);
958
959   TRACE("Callback: nfc_jni_llcp_transport_socket_err_callback()");
960
961   if(nErrCode == PHFRINFC_LLCP_ERR_FRAME_REJECTED)
962   {
963      LOGW("Frame Rejected - Disconnected");
964   }
965   else if(nErrCode == PHFRINFC_LLCP_ERR_DISCONNECTED)
966   {
967      LOGD("Socket Disconnected");
968   }
969}
970
971
972static void nfc_jni_discover_callback(void *pContext, NFCSTATUS status)
973{
974    struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
975
976    LOG_CALLBACK("nfc_jni_discover_callback", status);
977
978    pContextData->status = status;
979    sem_post(&pContextData->sem);
980}
981
982static void nfc_jni_Discovery_notification_callback(void *pContext,
983   phLibNfc_RemoteDevList_t *psRemoteDevList,
984   uint8_t uNofRemoteDev, NFCSTATUS status)
985{
986   JNIEnv *e;
987   NFCSTATUS ret;
988   jclass tag_cls = NULL;
989   jobject target_array;
990   jobject tag;
991   jmethodID ctor;
992   jfieldID f;
993   const char * typeName;
994   jbyteArray tagUid;
995   jbyteArray generalBytes = NULL;
996   struct nfc_jni_native_data *nat;
997   struct timespec ts;
998   phNfc_sData_t data;
999   int i;
1000   int target_index = 0; // Target that will be reported (if multiple can be >0)
1001
1002   nat = (struct nfc_jni_native_data *)pContext;
1003
1004   nat->vm->GetEnv( (void **)&e, nat->env_version);
1005
1006   if(status == NFCSTATUS_DESELECTED)
1007   {
1008      LOG_CALLBACK("nfc_jni_Discovery_notification_callback: Target deselected", status);
1009
1010      /* Notify manager that a target was deselected */
1011      e->CallVoidMethod(nat->manager, cached_NfcManager_notifyTargetDeselected);
1012      if(e->ExceptionCheck())
1013      {
1014         LOGE("Exception occured");
1015         kill_client(nat);
1016      }
1017   }
1018   else
1019   {
1020      LOG_CALLBACK("nfc_jni_Discovery_notification_callback", status);
1021      TRACE("Discovered %d tags", uNofRemoteDev);
1022
1023      /* Reset device connected flag */
1024      device_connected_flag = 1;
1025
1026      if((psRemoteDevList->psRemoteDevInfo->RemDevType == phNfc_eNfcIP1_Initiator)
1027          || (psRemoteDevList->psRemoteDevInfo->RemDevType == phNfc_eNfcIP1_Target))
1028      {
1029         tag_cls = e->GetObjectClass(nat->cached_P2pDevice);
1030         if(e->ExceptionCheck())
1031         {
1032            LOGE("Get Object Class Error");
1033            kill_client(nat);
1034            return;
1035         }
1036
1037         /* New target instance */
1038         ctor = e->GetMethodID(tag_cls, "<init>", "()V");
1039         tag = e->NewObject(tag_cls, ctor);
1040
1041         /* Set P2P Target mode */
1042         f = e->GetFieldID(tag_cls, "mMode", "I");
1043
1044         if(psRemoteDevList->psRemoteDevInfo->RemDevType == phNfc_eNfcIP1_Initiator)
1045         {
1046            LOGD("Discovered P2P Initiator");
1047            e->SetIntField(tag, f, (jint)MODE_P2P_INITIATOR);
1048         }
1049         else
1050         {
1051            LOGD("Discovered P2P Target");
1052            e->SetIntField(tag, f, (jint)MODE_P2P_TARGET);
1053         }
1054
1055         if(psRemoteDevList->psRemoteDevInfo->RemDevType == phNfc_eNfcIP1_Initiator)
1056         {
1057            /* Set General Bytes */
1058            f = e->GetFieldID(tag_cls, "mGeneralBytes", "[B");
1059
1060           TRACE("General Bytes length =");
1061           for(i=0;i<psRemoteDevList->psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo_Length;i++)
1062           {
1063               LOGD("%02x ", psRemoteDevList->psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo[i]);
1064           }
1065
1066            generalBytes = e->NewByteArray(psRemoteDevList->psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo_Length);
1067
1068            e->SetByteArrayRegion(generalBytes, 0,
1069                                  psRemoteDevList->psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo_Length,
1070                                  (jbyte *)psRemoteDevList->psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo);
1071
1072            e->SetObjectField(tag, f, generalBytes);
1073         }
1074
1075         /* Set tag handle */
1076         f = e->GetFieldID(tag_cls, "mHandle", "I");
1077         e->SetIntField(tag, f,(jint)psRemoteDevList[target_index].hTargetDev);
1078         TRACE("Target handle = 0x%08x",psRemoteDevList[target_index].hTargetDev);
1079      }
1080      else
1081      {
1082        tag_cls = e->GetObjectClass(nat->cached_NfcTag);
1083        if(e->ExceptionCheck())
1084        {
1085            kill_client(nat);
1086            return;
1087        }
1088
1089        /* New tag instance */
1090        ctor = e->GetMethodID(tag_cls, "<init>", "()V");
1091        tag = e->NewObject(tag_cls, ctor);
1092
1093        bool multi_protocol = false;
1094
1095        if(status == NFCSTATUS_MULTIPLE_PROTOCOLS)
1096        {
1097            TRACE("Multiple Protocol TAG detected\n");
1098            multi_protocol = true;
1099        }
1100        else if (status == NFCSTATUS_MULTIPLE_TAGS) {
1101            // Only one tag will be used
1102            // TODO: suppose there's both a multi-proto and another
1103            // single-proto tag in the field: in that case, we'd want to make sure we
1104            // return a "complete" tag, and not just one "target", which
1105            // is then either half of the multi-proto tag or the complete
1106            // single-proto.
1107            target_index = 0;
1108        } else {
1109            target_index = 0;
1110        }
1111
1112        /* Set tag UID */
1113        f = e->GetFieldID(tag_cls, "mUid", "[B");
1114        data = get_target_uid(psRemoteDevList[target_index].psRemoteDevInfo);
1115        tagUid = e->NewByteArray(data.length);
1116        if(data.length > 0)
1117        {
1118            e->SetByteArrayRegion(tagUid, 0, data.length, (jbyte *)data.buffer);
1119        }
1120        e->SetObjectField(tag, f, tagUid);
1121
1122        /* Generate technology list */
1123        jintArray techList;
1124        jintArray handleList;
1125        jintArray typeList;
1126        nfc_jni_get_technology_tree(e, psRemoteDevList,
1127                multi_protocol ? uNofRemoteDev : 1,
1128                &techList, &handleList, &typeList);
1129
1130        /* Push the technology list into the java object */
1131        f = e->GetFieldID(tag_cls, "mTechList", "[I");
1132        e->SetObjectField(tag, f, techList);
1133
1134        f = e->GetFieldID(tag_cls, "mTechHandles", "[I");
1135        e->SetObjectField(tag, f, handleList);
1136
1137        f = e->GetFieldID(tag_cls, "mTechLibNfcTypes", "[I");
1138        e->SetObjectField(tag, f, typeList);
1139
1140        f = e->GetFieldID(tag_cls, "mConnectedTechIndex", "I");
1141        e->SetIntField(tag, f,(jint)-1);
1142
1143        f = e->GetFieldID(tag_cls, "mConnectedHandle", "I");
1144        e->SetIntField(tag, f,(jint)-1);
1145      }
1146
1147      storedHandle = psRemoteDevList[target_index].hTargetDev;
1148      if (nat->tag != NULL) {
1149          e->DeleteGlobalRef(nat->tag);
1150      }
1151      nat->tag = e->NewGlobalRef(tag);
1152
1153      /* Notify the service */
1154      TRACE("Notify Nfc Service");
1155      if((psRemoteDevList->psRemoteDevInfo->RemDevType == phNfc_eNfcIP1_Initiator)
1156          || (psRemoteDevList->psRemoteDevInfo->RemDevType == phNfc_eNfcIP1_Target))
1157      {
1158         /* Store the hanlde of the P2P device */
1159         hLlcpHandle = psRemoteDevList->hTargetDev;
1160
1161         /* Notify manager that new a P2P device was found */
1162         e->CallVoidMethod(nat->manager, cached_NfcManager_notifyLlcpLinkActivation, tag);
1163         if(e->ExceptionCheck())
1164         {
1165            LOGE("Exception occured");
1166            kill_client(nat);
1167         }
1168      }
1169      else
1170      {
1171         /* Notify manager that new a tag was found */
1172         e->CallVoidMethod(nat->manager, cached_NfcManager_notifyNdefMessageListeners, tag);
1173         if(e->ExceptionCheck())
1174         {
1175            LOGE("Exception occured");
1176            kill_client(nat);
1177         }
1178      }
1179      e->DeleteLocalRef(tag);
1180   }
1181}
1182
1183static void nfc_jni_init_callback(void *pContext, NFCSTATUS status)
1184{
1185   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
1186
1187   LOG_CALLBACK("nfc_jni_init_callback", status);
1188
1189   pContextData->status = status;
1190   sem_post(&pContextData->sem);
1191}
1192
1193static void nfc_jni_deinit_callback(void *pContext, NFCSTATUS status)
1194{
1195   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
1196
1197   LOG_CALLBACK("nfc_jni_deinit_callback", status);
1198
1199   pContextData->status = status;
1200   sem_post(&pContextData->sem);
1201}
1202
1203/* Set Secure Element mode callback*/
1204static void nfc_jni_smartMX_setModeCb (void*            pContext,
1205                                       phLibNfc_Handle  hSecureElement,
1206                                       NFCSTATUS        status)
1207{
1208   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
1209
1210   LOG_CALLBACK("nfc_jni_smartMX_setModeCb", status);
1211
1212   pContextData->status = status;
1213   sem_post(&pContextData->sem);
1214}
1215
1216/* Card Emulation callback */
1217static void nfc_jni_transaction_callback(void *context,
1218   phLibNfc_eSE_EvtType_t evt_type, phLibNfc_Handle handle,
1219   phLibNfc_uSeEvtInfo_t *evt_info, NFCSTATUS status)
1220{
1221    JNIEnv *e;
1222    jobject tmp_array = NULL;
1223    jobject mifare_block = NULL;
1224    struct nfc_jni_native_data *nat;
1225    phNfc_sData_t *aid;
1226    phNfc_sData_t *mifare_command;
1227    struct nfc_jni_callback_data *pCallbackData;
1228    int i=0;
1229
1230    LOG_CALLBACK("nfc_jni_transaction_callback", status);
1231
1232    nat = (struct nfc_jni_native_data *)context;
1233
1234    nat->vm->GetEnv( (void **)&e, nat->env_version);
1235
1236    if(status == NFCSTATUS_SUCCESS)
1237    {
1238        switch(evt_type)
1239        {
1240            case phLibNfc_eSE_EvtStartTransaction:
1241            {
1242                TRACE("> SE EVT_START_TRANSACTION");
1243                if(evt_info->UiccEvtInfo.aid.length <= AID_MAXLEN)
1244                {
1245                    aid = &(evt_info->UiccEvtInfo.aid);
1246
1247                    LOGD("> AID DETECTED");
1248
1249                    if(aid != NULL)
1250                    {
1251                        char aid_str[AID_MAXLEN * 2 + 1];
1252                        aid_str[0] = '\0';
1253                        for (i = 0; i < (int) (aid->length) && i < AID_MAXLEN; i++) {
1254                          snprintf(&aid_str[i*2], 3, "%02x", aid->buffer[i]);
1255                        }
1256                        LOGD("> AID: %s", aid_str);
1257
1258                        tmp_array = e->NewByteArray(aid->length);
1259                        if (tmp_array == NULL)
1260                        {
1261                            goto error;
1262                        }
1263
1264                        e->SetByteArrayRegion((jbyteArray)tmp_array, 0, aid->length, (jbyte *)aid->buffer);
1265                        if(e->ExceptionCheck())
1266                        {
1267                            goto error;
1268                        }
1269                    }
1270                    else
1271                    {
1272                        goto error;
1273                    }
1274
1275                    TRACE("Notify Nfc Service");
1276                    /* Notify manager that a new event occurred on a SE */
1277                    e->CallVoidMethod(nat->manager, cached_NfcManager_notifyTransactionListeners, tmp_array);
1278                    if(e->ExceptionCheck())
1279                    {
1280                        goto error;
1281                    }
1282                }
1283                else
1284                {
1285                    LOGD("> NO AID DETECTED");
1286                }
1287            }break;
1288
1289            case phLibNfc_eSE_EvtApduReceived:
1290            {
1291                phNfc_sData_t *apdu = &(evt_info->UiccEvtInfo.aid);
1292                TRACE("> SE EVT_APDU_RECEIVED");
1293
1294                if (apdu != NULL) {
1295                        TRACE("  APDU length=%d", apdu->length);
1296                        tmp_array = e->NewByteArray(apdu->length);
1297                        if (tmp_array == NULL) {
1298                            goto error;
1299                        }
1300                        e->SetByteArrayRegion((jbyteArray)tmp_array, 0, apdu->length, (jbyte *)apdu->buffer);
1301                        if (e->ExceptionCheck()) {
1302                            goto error;
1303                        }
1304                } else {
1305                        TRACE("  APDU EMPTY");
1306                }
1307
1308                TRACE("Notify Nfc Service");
1309                e->CallVoidMethod(nat->manager, cached_NfcManager_notifySeApduReceived, tmp_array);
1310            }break;
1311
1312            case phLibNfc_eSE_EvtCardRemoval:
1313            {
1314                TRACE("> SE EVT_EMV_CARD_REMOVAL");
1315                TRACE("Notify Nfc Service");
1316                e->CallVoidMethod(nat->manager, cached_NfcManager_notifySeEmvCardRemoval);
1317            }break;
1318
1319            case phLibNfc_eSE_EvtMifareAccess:
1320            {
1321                TRACE("> SE EVT_MIFARE_ACCESS");
1322                mifare_command = &(evt_info->UiccEvtInfo.aid);
1323                TRACE("> MIFARE Block: %d",mifare_command->buffer[1]);
1324                tmp_array = e->NewByteArray(2);
1325                if (tmp_array == NULL)
1326                {
1327                    goto error;
1328                }
1329
1330                e->SetByteArrayRegion((jbyteArray)tmp_array, 0, 2, (jbyte *)mifare_command->buffer);
1331                if(e->ExceptionCheck())
1332                {
1333                    goto error;
1334                }
1335                TRACE("Notify Nfc Service");
1336                e->CallVoidMethod(nat->manager, cached_NfcManager_notifySeMifareAccess, mifare_block);
1337            }break;
1338
1339            case phLibNfc_eSE_EvtFieldOn:
1340            {
1341                TRACE("> SE EVT_FIELD_ON");
1342                TRACE("Notify Nfc Service");
1343                e->CallVoidMethod(nat->manager, cached_NfcManager_notifySeFieldActivated);
1344            }break;
1345
1346            case phLibNfc_eSE_EvtFieldOff:
1347            {
1348                TRACE("> SE EVT_FIELD_OFF");
1349                TRACE("Notify Nfc Service");
1350                e->CallVoidMethod(nat->manager, cached_NfcManager_notifySeFieldDeactivated);
1351            }break;
1352
1353            default:
1354            {
1355                TRACE("Unknown SE event");
1356            }break;
1357        }
1358    }
1359    else
1360    {
1361        LOGE("SE transaction notification error");
1362        goto error;
1363    }
1364
1365    /* Function finished, now clean and return */
1366    goto clean_and_return;
1367
1368 error:
1369    /* In case of error, just discard the notification */
1370    LOGE("Failed to send SE transaction notification");
1371    e->ExceptionClear();
1372
1373 clean_and_return:
1374    if(tmp_array != NULL)
1375    {
1376       e->DeleteLocalRef(tmp_array);
1377    }
1378}
1379
1380static void nfc_jni_se_set_mode_callback(void *pContext,
1381   phLibNfc_Handle handle, NFCSTATUS status)
1382{
1383   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
1384
1385   LOG_CALLBACK("nfc_jni_se_set_mode_callback", status);
1386
1387   pContextData->status = status;
1388   sem_post(&pContextData->sem);
1389}
1390
1391/*
1392 * NFCManager methods
1393 */
1394
1395static void nfc_jni_start_discovery_locked(struct nfc_jni_native_data *nat)
1396{
1397   NFCSTATUS ret;
1398   struct nfc_jni_callback_data cb_data;
1399
1400   /* Create the local semaphore */
1401   if (!nfc_cb_data_init(&cb_data, NULL))
1402   {
1403      goto clean_and_return;
1404   }
1405   /* Reset the PN544 ISO XCHG / sw watchdog timeouts */
1406   nfc_jni_reset_timeout_values();
1407
1408   /* Reset device connected flag */
1409   device_connected_flag = 0;
1410
1411   /* Register callback for remote device notifications.
1412    * Must re-register every time we turn on discovery, since other operations
1413    * (such as opening the Secure Element) can change the remote device
1414    * notification callback*/
1415   REENTRANCE_LOCK();
1416   ret = phLibNfc_RemoteDev_NtfRegister(&nat->registry_info, nfc_jni_Discovery_notification_callback, (void *)nat);
1417   REENTRANCE_UNLOCK();
1418   if(ret != NFCSTATUS_SUCCESS)
1419   {
1420        LOGD("pphLibNfc_RemoteDev_NtfRegister returned 0x%02x",ret);
1421        goto clean_and_return;
1422   }
1423   TRACE("phLibNfc_RemoteDev_NtfRegister(%s-%s-%s-%s-%s-%s-%s-%s) returned 0x%x\n",
1424      nat->registry_info.Jewel==TRUE?"J":"",
1425      nat->registry_info.MifareUL==TRUE?"UL":"",
1426      nat->registry_info.MifareStd==TRUE?"Mi":"",
1427      nat->registry_info.Felica==TRUE?"F":"",
1428      nat->registry_info.ISO14443_4A==TRUE?"4A":"",
1429      nat->registry_info.ISO14443_4B==TRUE?"4B":"",
1430      nat->registry_info.NFC==TRUE?"P2P":"",
1431      nat->registry_info.ISO15693==TRUE?"R":"", ret);
1432
1433   /* Start Polling loop */
1434   TRACE("******  Start NFC Discovery ******");
1435   REENTRANCE_LOCK();
1436   ret = phLibNfc_Mgt_ConfigureDiscovery(NFC_DISCOVERY_CONFIG,nat->discovery_cfg, nfc_jni_discover_callback, (void *)&cb_data);
1437   REENTRANCE_UNLOCK();
1438   TRACE("phLibNfc_Mgt_ConfigureDiscovery(%s-%s-%s-%s-%s-%s, %s-%x-%x) returned 0x%08x\n",
1439      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443A==TRUE?"3A":"",
1440      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443B==TRUE?"3B":"",
1441      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica212==TRUE?"F2":"",
1442      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica424==TRUE?"F4":"",
1443      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableNfcActive==TRUE?"NFC":"",
1444      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso15693==TRUE?"RFID":"",
1445      nat->discovery_cfg.PollDevInfo.PollCfgInfo.DisableCardEmulation==FALSE?"CE":"",
1446      nat->discovery_cfg.NfcIP_Mode, nat->discovery_cfg.Duration, ret);
1447
1448   if(ret != NFCSTATUS_PENDING)
1449   {
1450      emergency_recovery(nat);
1451   }
1452
1453   /* Wait for callback response */
1454   if(sem_wait(&cb_data.sem))
1455   {
1456      LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
1457      goto clean_and_return;
1458   }
1459
1460clean_and_return:
1461   nfc_cb_data_deinit(&cb_data);
1462}
1463
1464static void nfc_jni_stop_discovery_locked(struct nfc_jni_native_data *nat)
1465{
1466   phLibNfc_sADD_Cfg_t discovery_cfg;
1467   NFCSTATUS ret;
1468   struct nfc_jni_callback_data cb_data;
1469
1470   /* Create the local semaphore */
1471   if (!nfc_cb_data_init(&cb_data, NULL))
1472   {
1473      goto clean_and_return;
1474   }
1475
1476   discovery_cfg.PollDevInfo.PollEnabled = 0;
1477   discovery_cfg.Duration = 300000; /* in ms */
1478   discovery_cfg.NfcIP_Mode = phNfc_eDefaultP2PMode;
1479   discovery_cfg.NfcIP_Tgt_Disable = TRUE;
1480
1481   /* Start Polling loop */
1482   TRACE("******  Stop NFC Discovery ******");
1483   REENTRANCE_LOCK();
1484   ret = phLibNfc_Mgt_ConfigureDiscovery(NFC_DISCOVERY_CONFIG,discovery_cfg, nfc_jni_discover_callback, (void *)&cb_data);
1485   REENTRANCE_UNLOCK();
1486   TRACE("phLibNfc_Mgt_ConfigureDiscovery(%s-%s-%s-%s-%s-%s, %s-%x-%x) returned 0x%08x\n",
1487      discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443A==TRUE?"3A":"",
1488      discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443B==TRUE?"3B":"",
1489      discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica212==TRUE?"F2":"",
1490      discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica424==TRUE?"F4":"",
1491      discovery_cfg.PollDevInfo.PollCfgInfo.EnableNfcActive==TRUE?"NFC":"",
1492      discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso15693==TRUE?"RFID":"",
1493      discovery_cfg.PollDevInfo.PollCfgInfo.DisableCardEmulation==FALSE?"CE":"",
1494      discovery_cfg.NfcIP_Mode, discovery_cfg.Duration, ret);
1495
1496   if(ret != NFCSTATUS_PENDING)
1497   {
1498      emergency_recovery(nat);
1499   }
1500
1501   /* Wait for callback response */
1502   if(sem_wait(&cb_data.sem))
1503   {
1504      LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
1505      goto clean_and_return;
1506   }
1507
1508clean_and_return:
1509   nfc_cb_data_deinit(&cb_data);
1510}
1511
1512
1513static void com_android_nfc_NfcManager_disableDiscovery(JNIEnv *e, jobject o)
1514{
1515    struct nfc_jni_native_data *nat;
1516
1517    CONCURRENCY_LOCK();
1518
1519    /* Retrieve native structure address */
1520    nat = nfc_jni_get_nat(e, o);
1521
1522    nfc_jni_stop_discovery_locked(nat);
1523
1524    CONCURRENCY_UNLOCK();
1525
1526}
1527
1528static void com_android_nfc_NfcManager_enableDiscovery(JNIEnv *e, jobject o) {
1529    NFCSTATUS ret;
1530    struct nfc_jni_native_data *nat;
1531
1532    CONCURRENCY_LOCK();
1533
1534    nat = nfc_jni_get_nat(e, o);
1535    nfc_jni_start_discovery_locked(nat);
1536
1537    CONCURRENCY_UNLOCK();
1538}
1539
1540static void com_android_nfc_NfcManager_doResetTimeouts( JNIEnv *e, jobject o) {
1541    CONCURRENCY_LOCK();
1542    nfc_jni_reset_timeout_values();
1543    CONCURRENCY_UNLOCK();
1544}
1545
1546static void setFelicaTimeout(jint timeout) {
1547   // The Felica timeout is configurable in the PN544 upto a maximum of 255 ms.
1548   // It can be set to 0 to disable the timeout altogether, in which case we
1549   // use the sw watchdog as a fallback.
1550   if (timeout <= 255) {
1551       phLibNfc_SetFelicaTimeout(timeout);
1552   } else {
1553       // Disable hw timeout, use sw watchdog for timeout
1554       phLibNfc_SetFelicaTimeout(0);
1555       phLibNfc_SetHciTimeout(timeout);
1556   }
1557
1558}
1559// Calculates ceiling log2 of value
1560static unsigned int log2(int value) {
1561    unsigned int ret = 0;
1562    bool isPowerOf2 = ((value & (value - 1)) == 0);
1563    while ( (value >> ret) > 1 ) ret++;
1564    if (!isPowerOf2) ret++;
1565    return ret;
1566}
1567
1568// The Iso/Mifare Xchg timeout in PN544 is a non-linear function over X
1569// spanning 0 - 4.9s: timeout in seconds = (256 * 16 / 13560000) * 2 ^ X
1570//
1571// We keep the constant part of the formula in a static; note the factor
1572// 1000 off, which is due to the fact that the formula calculates seconds,
1573// but this method gets milliseconds as an argument.
1574static double nxp_nfc_timeout_factor = (256 * 16) / 13560.0;
1575
1576static int calcTimeout(int timeout_in_ms) {
1577   // timeout = (256 * 16 / 13560000) * 2 ^ X
1578   // First find the first X for which timeout > requested timeout
1579   return (log2(ceil(((double) timeout_in_ms) / nxp_nfc_timeout_factor)));
1580}
1581
1582static void setIsoDepTimeout(jint timeout) {
1583   if (timeout <= 4900) {
1584       int value = calcTimeout(timeout);
1585       // Then re-compute the actual timeout based on X
1586       double actual_timeout = nxp_nfc_timeout_factor * (1 << value);
1587       // Set the sw watchdog a bit longer (The PN544 timeout is very accurate,
1588       // but it will take some time to get back through the sw layers.
1589       // 500 ms should be enough).
1590       phLibNfc_SetHciTimeout(ceil(actual_timeout + 500));
1591       value |= 0x10; // bit 4 to enable timeout
1592       phLibNfc_SetIsoXchgTimeout(value);
1593   }
1594   else {
1595       // Also note that if we desire a timeout > 4.9s, the Iso Xchg timeout
1596       // must be disabled completely, to prevent the PN544 from aborting
1597       // the transaction. We reuse the HCI sw watchdog to catch the timeout
1598       // in that case.
1599       phLibNfc_SetIsoXchgTimeout(0x00);
1600       phLibNfc_SetHciTimeout(timeout);
1601   }
1602}
1603
1604static void setNfcATimeout(jint timeout) {
1605   if (timeout <= 4900) {
1606       int value = calcTimeout(timeout);
1607       phLibNfc_SetMifareRawTimeout(value);
1608   }
1609   else {
1610       // Disable mifare raw timeout, use HCI sw watchdog instead
1611       phLibNfc_SetMifareRawTimeout(0x00);
1612       phLibNfc_SetHciTimeout(timeout);
1613   }
1614}
1615
1616static bool com_android_nfc_NfcManager_doSetTimeout( JNIEnv *e, jobject o,
1617        jint tech, jint timeout) {
1618    bool success = false;
1619    CONCURRENCY_LOCK();
1620    if (timeout <= 0) {
1621        LOGE("Timeout must be positive.");
1622        return false;
1623    } else {
1624        switch (tech) {
1625            case TARGET_TYPE_MIFARE_CLASSIC:
1626            case TARGET_TYPE_MIFARE_UL:
1627                // Intentional fall-through, Mifare UL, Classic
1628                // transceive just uses raw 3A frames
1629            case TARGET_TYPE_ISO14443_3A:
1630                setNfcATimeout(timeout);
1631                success = true;
1632                break;
1633            case TARGET_TYPE_ISO14443_4:
1634                setIsoDepTimeout(timeout);
1635                success = true;
1636                break;
1637            case TARGET_TYPE_FELICA:
1638                setFelicaTimeout(timeout);
1639                success = true;
1640                break;
1641            default:
1642                LOGW("doSetTimeout: Timeout not supported for tech %d", tech);
1643                success = false;
1644        }
1645    }
1646    CONCURRENCY_UNLOCK();
1647    return success;
1648}
1649
1650static jint com_android_nfc_NfcManager_doGetTimeout( JNIEnv *e, jobject o,
1651        jint tech) {
1652    int timeout = -1;
1653    CONCURRENCY_LOCK();
1654    switch (tech) {
1655        case TARGET_TYPE_MIFARE_CLASSIC:
1656        case TARGET_TYPE_MIFARE_UL:
1657            // Intentional fall-through, Mifare UL, Classic
1658            // transceive just uses raw 3A frames
1659        case TARGET_TYPE_ISO14443_3A:
1660            timeout = phLibNfc_GetMifareRawTimeout();
1661            if (timeout == 0) {
1662                timeout = phLibNfc_GetHciTimeout();
1663            } else {
1664                // Timeout returned from libnfc needs conversion to ms
1665                timeout = (nxp_nfc_timeout_factor * (1 << timeout));
1666            }
1667            break;
1668        case TARGET_TYPE_ISO14443_4:
1669            timeout = phLibNfc_GetIsoXchgTimeout() & 0x0F; // lower 4 bits only
1670            if (timeout == 0) {
1671                timeout = phLibNfc_GetHciTimeout();
1672            } else {
1673                // Timeout returned from libnfc needs conversion to ms
1674                timeout = (nxp_nfc_timeout_factor * (1 << timeout));
1675            }
1676            break;
1677        case TARGET_TYPE_FELICA:
1678            timeout = phLibNfc_GetFelicaTimeout();
1679            if (timeout == 0) {
1680                timeout = phLibNfc_GetHciTimeout();
1681            } else {
1682                // Felica timeout already in ms
1683            }
1684            break;
1685        default:
1686            LOGW("doGetTimeout: Timeout not supported for tech %d", tech);
1687            break;
1688    }
1689    CONCURRENCY_UNLOCK();
1690    return timeout;
1691}
1692
1693
1694static jboolean com_android_nfc_NfcManager_init_native_struc(JNIEnv *e, jobject o)
1695{
1696   NFCSTATUS status;
1697   struct nfc_jni_native_data *nat = NULL;
1698   jclass cls;
1699   jobject obj;
1700   jfieldID f;
1701
1702   TRACE("******  Init Native Structure ******");
1703
1704   /* Initialize native structure */
1705   nat = (nfc_jni_native_data*)malloc(sizeof(struct nfc_jni_native_data));
1706   if(nat == NULL)
1707   {
1708      LOGD("malloc of nfc_jni_native_data failed");
1709      return FALSE;
1710   }
1711   memset(nat, 0, sizeof(*nat));
1712   e->GetJavaVM(&(nat->vm));
1713   nat->env_version = e->GetVersion();
1714   nat->manager = e->NewGlobalRef(o);
1715
1716   cls = e->GetObjectClass(o);
1717   f = e->GetFieldID(cls, "mNative", "I");
1718   e->SetIntField(o, f, (jint)nat);
1719
1720   /* Initialize native cached references */
1721   cached_NfcManager_notifyNdefMessageListeners = e->GetMethodID(cls,
1722      "notifyNdefMessageListeners","(Lcom/android/nfc/nxp/NativeNfcTag;)V");
1723
1724   cached_NfcManager_notifyTransactionListeners = e->GetMethodID(cls,
1725      "notifyTransactionListeners", "([B)V");
1726
1727   cached_NfcManager_notifyLlcpLinkActivation = e->GetMethodID(cls,
1728      "notifyLlcpLinkActivation","(Lcom/android/nfc/nxp/NativeP2pDevice;)V");
1729
1730   cached_NfcManager_notifyLlcpLinkDeactivated = e->GetMethodID(cls,
1731      "notifyLlcpLinkDeactivated","(Lcom/android/nfc/nxp/NativeP2pDevice;)V");
1732
1733   cached_NfcManager_notifyTargetDeselected = e->GetMethodID(cls,
1734      "notifyTargetDeselected","()V");
1735
1736   cached_NfcManager_notifySeFieldActivated = e->GetMethodID(cls,
1737      "notifySeFieldActivated", "()V");
1738
1739   cached_NfcManager_notifySeFieldDeactivated = e->GetMethodID(cls,
1740      "notifySeFieldDeactivated", "()V");
1741
1742   cached_NfcManager_notifySeApduReceived= e->GetMethodID(cls,
1743      "notifySeApduReceived", "([B)V");
1744
1745   cached_NfcManager_notifySeMifareAccess = e->GetMethodID(cls,
1746      "notifySeMifareAccess", "([B)V");
1747
1748   cached_NfcManager_notifySeEmvCardRemoval =  e->GetMethodID(cls,
1749      "notifySeEmvCardRemoval", "()V");
1750
1751   if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeNfcTag",&(nat->cached_NfcTag)) == -1)
1752   {
1753      LOGD("Native Structure initialization failed");
1754      return FALSE;
1755   }
1756
1757   if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeP2pDevice",&(nat->cached_P2pDevice)) == -1)
1758   {
1759      LOGD("Native Structure initialization failed");
1760      return FALSE;
1761   }
1762   TRACE("****** Init Native Structure OK ******");
1763   return TRUE;
1764
1765}
1766
1767/* Init/Deinit method */
1768static jboolean com_android_nfc_NfcManager_initialize(JNIEnv *e, jobject o)
1769{
1770   struct nfc_jni_native_data *nat = NULL;
1771   int init_result = JNI_FALSE;
1772#ifdef TNFC_EMULATOR_ONLY
1773   char value[PROPERTY_VALUE_MAX];
1774#endif
1775   jboolean result;
1776
1777   CONCURRENCY_LOCK();
1778
1779#ifdef TNFC_EMULATOR_ONLY
1780   if (!property_get("ro.kernel.qemu", value, 0))
1781   {
1782      LOGE("NFC Initialization failed: not running in an emulator\n");
1783      goto clean_and_return;
1784   }
1785#endif
1786
1787   /* Retrieve native structure address */
1788   nat = nfc_jni_get_nat(e, o);
1789
1790   nat->seId = SMX_SECURE_ELEMENT_ID;
1791
1792   nat->lto = 150;  // LLCP_LTO
1793   nat->miu = 128; // LLCP_MIU
1794   nat->wks = 1;  // LLCP_WKS
1795   nat->opt = 0;  // LLCP_OPT
1796   nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443A = TRUE;
1797   nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443B = TRUE;
1798   nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica212 = TRUE;
1799   nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica424 = TRUE;
1800   nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso15693 = TRUE;
1801   nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableNfcActive = TRUE;
1802   nat->discovery_cfg.PollDevInfo.PollCfgInfo.DisableCardEmulation = FALSE;
1803
1804   nat->registry_info.MifareUL = TRUE;
1805   nat->registry_info.MifareStd = TRUE;
1806   nat->registry_info.ISO14443_4A = TRUE;
1807   nat->registry_info.ISO14443_4B = TRUE;
1808   nat->registry_info.Jewel = TRUE;
1809   nat->registry_info.Felica = TRUE;
1810   nat->registry_info.NFC = TRUE;
1811   nat->registry_info.ISO15693 = TRUE;
1812
1813   exported_nat = nat;
1814
1815   /* Perform the initialization */
1816   init_result = nfc_jni_initialize(nat);
1817
1818clean_and_return:
1819   CONCURRENCY_UNLOCK();
1820
1821   /* Convert the result and return */
1822   return (init_result==TRUE)?JNI_TRUE:JNI_FALSE;
1823}
1824
1825static jboolean com_android_nfc_NfcManager_deinitialize(JNIEnv *e, jobject o)
1826{
1827   struct timespec ts;
1828   NFCSTATUS status;
1829   int result = JNI_FALSE;
1830   struct nfc_jni_native_data *nat;
1831   int bStackReset = FALSE;
1832   struct nfc_jni_callback_data cb_data;
1833
1834   CONCURRENCY_LOCK();
1835
1836   /* Retrieve native structure address */
1837   nat = nfc_jni_get_nat(e, o);
1838
1839   /* Clear previous configuration */
1840   memset(&nat->discovery_cfg, 0, sizeof(phLibNfc_sADD_Cfg_t));
1841   memset(&nat->registry_info, 0, sizeof(phLibNfc_Registry_Info_t));
1842
1843   /* Create the local semaphore */
1844   if (nfc_cb_data_init(&cb_data, NULL))
1845   {
1846      TRACE("phLibNfc_Mgt_DeInitialize()");
1847      REENTRANCE_LOCK();
1848      status = phLibNfc_Mgt_DeInitialize(gHWRef, nfc_jni_deinit_callback, (void *)&cb_data);
1849      REENTRANCE_UNLOCK();
1850      if (status == NFCSTATUS_PENDING)
1851      {
1852         TRACE("phLibNfc_Mgt_DeInitialize() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
1853
1854         clock_gettime(CLOCK_REALTIME, &ts);
1855         ts.tv_sec += 5;
1856
1857         /* Wait for callback response */
1858         if(sem_timedwait(&cb_data.sem, &ts) == -1)
1859         {
1860            LOGW("Operation timed out");
1861            bStackReset = TRUE;
1862         }
1863
1864         if(cb_data.status != NFCSTATUS_SUCCESS)
1865         {
1866            LOGE("Failed to deinit the stack");
1867            bStackReset = TRUE;
1868         }
1869      }
1870      else
1871      {
1872         TRACE("phLibNfc_Mgt_DeInitialize() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
1873         bStackReset = TRUE;
1874      }
1875      nfc_cb_data_deinit(&cb_data);
1876   }
1877   else
1878   {
1879       LOGE("Failed to create semaphore (errno=0x%08x)", errno);
1880       bStackReset = TRUE;
1881   }
1882
1883   kill_client(nat);
1884
1885   if(bStackReset == TRUE)
1886   {
1887      /* Complete deinit. failed, try hard restart of NFC */
1888      LOGW("Reseting stack...");
1889      emergency_recovery(nat);
1890   }
1891
1892   result = nfc_jni_unconfigure_driver(nat);
1893
1894   TRACE("NFC Deinitialized");
1895
1896   CONCURRENCY_UNLOCK();
1897
1898   return TRUE;
1899}
1900
1901/* Secure Element methods */
1902static jintArray com_android_nfc_NfcManager_doGetSecureElementList(JNIEnv *e, jobject o) {
1903    NFCSTATUS ret;
1904    jintArray list= NULL;
1905    phLibNfc_SE_List_t se_list[PHLIBNFC_MAXNO_OF_SE];
1906    uint8_t i, se_count = PHLIBNFC_MAXNO_OF_SE;
1907
1908    TRACE("******  Get Secure Element List ******");
1909
1910    TRACE("phLibNfc_SE_GetSecureElementList()");
1911    REENTRANCE_LOCK();
1912    ret = phLibNfc_SE_GetSecureElementList(se_list, &se_count);
1913    REENTRANCE_UNLOCK();
1914    if (ret != NFCSTATUS_SUCCESS) {
1915        LOGE("phLibNfc_SE_GetSecureElementList() returned 0x%04x[%s]", ret,
1916                nfc_jni_get_status_name(ret));
1917        return list;
1918    }
1919    TRACE("phLibNfc_SE_GetSecureElementList() returned 0x%04x[%s]", ret,
1920            nfc_jni_get_status_name(ret));
1921
1922    TRACE("Nb SE: %d", se_count);
1923    list =e->NewIntArray(se_count);
1924    for (i = 0; i < se_count; i++) {
1925        if (se_list[i].eSE_Type == phLibNfc_SE_Type_SmartMX) {
1926            LOGD("phLibNfc_SE_GetSecureElementList(): SMX detected");
1927            LOGD("SE ID #%d: 0x%08x", i, se_list[i].hSecureElement);
1928        } else if(se_list[i].eSE_Type == phLibNfc_SE_Type_UICC) {
1929            LOGD("phLibNfc_SE_GetSecureElementList(): UICC detected");
1930            LOGD("SE ID #%d: 0x%08x", i, se_list[i].hSecureElement);
1931        }
1932        e->SetIntArrayRegion(list, i, 1, (jint*)&se_list[i].hSecureElement);
1933    }
1934
1935    e->DeleteLocalRef(list);
1936
1937    return list;
1938}
1939
1940static void com_android_nfc_NfcManager_doSelectSecureElement(JNIEnv *e, jobject o) {
1941    NFCSTATUS ret;
1942    struct nfc_jni_native_data *nat;
1943    struct nfc_jni_callback_data cb_data;
1944
1945    CONCURRENCY_LOCK();
1946
1947    /* Retrieve native structure address */
1948    nat = nfc_jni_get_nat(e, o);
1949
1950    /* Create the local semaphore */
1951    if (!nfc_cb_data_init(&cb_data, NULL)) {
1952        goto clean_and_return;
1953    }
1954
1955    TRACE("******  Select Secure Element ******");
1956
1957    TRACE("phLibNfc_SE_SetMode()");
1958    /* Set SE mode - Virtual */
1959    REENTRANCE_LOCK();
1960    ret = phLibNfc_SE_SetMode(nat->seId, phLibNfc_SE_ActModeVirtualVolatile, nfc_jni_se_set_mode_callback,
1961            (void *)&cb_data);
1962    REENTRANCE_UNLOCK();
1963    if (ret != NFCSTATUS_PENDING) {
1964        LOGD("phLibNfc_SE_SetMode() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
1965        goto clean_and_return;
1966    }
1967    TRACE("phLibNfc_SE_SetMode() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
1968
1969    /* Wait for callback response */
1970    if (sem_wait(&cb_data.sem)) {
1971        LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
1972        goto clean_and_return;
1973    }
1974
1975    clean_and_return:
1976    nfc_cb_data_deinit(&cb_data);
1977    CONCURRENCY_UNLOCK();
1978}
1979
1980static void com_android_nfc_NfcManager_doDeselectSecureElement(JNIEnv *e, jobject o) {
1981    NFCSTATUS ret;
1982    struct nfc_jni_native_data *nat;
1983    struct nfc_jni_callback_data cb_data;
1984
1985    CONCURRENCY_LOCK();
1986
1987    /* Retrieve native structure address */
1988    nat = nfc_jni_get_nat(e, o);
1989
1990    /* Create the local semaphore */
1991    if (!nfc_cb_data_init(&cb_data, NULL)) {
1992        goto clean_and_return;
1993    }
1994
1995    TRACE("****** Deselect Secure Element ******");
1996
1997    TRACE("phLibNfc_SE_SetMode()");
1998    /* Set SE mode - Default */
1999    REENTRANCE_LOCK();
2000    ret = phLibNfc_SE_SetMode(nat->seId, phLibNfc_SE_ActModeDefault,
2001           nfc_jni_se_set_mode_callback, (void *)&cb_data);
2002    REENTRANCE_UNLOCK();
2003
2004    TRACE("phLibNfc_SE_SetMode returned 0x%02x", ret);
2005    if (ret != NFCSTATUS_PENDING) {
2006        LOGE("phLibNfc_SE_SetMode() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2007        goto clean_and_return;
2008    }
2009    TRACE("phLibNfc_SE_SetMode() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2010
2011    /* Wait for callback response */
2012    if (sem_wait(&cb_data.sem)) {
2013        LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
2014        goto clean_and_return;
2015    }
2016
2017    clean_and_return:
2018    nfc_cb_data_deinit(&cb_data);
2019    CONCURRENCY_UNLOCK();
2020}
2021
2022/* Llcp methods */
2023
2024static jboolean com_android_nfc_NfcManager_doCheckLlcp(JNIEnv *e, jobject o)
2025{
2026   NFCSTATUS ret;
2027   bool freeData = false;
2028   jboolean result = JNI_FALSE;
2029   struct nfc_jni_native_data *nat;
2030   struct nfc_jni_callback_data  *cb_data;
2031
2032
2033   CONCURRENCY_LOCK();
2034
2035   /* Memory allocation for cb_data
2036    * This is on the heap because it is used by libnfc
2037    * even after this call has succesfully finished. It is only freed
2038    * upon link closure in nfc_jni_llcp_linkStatus_callback.
2039    */
2040   cb_data = (struct nfc_jni_callback_data*) malloc (sizeof(nfc_jni_callback_data));
2041
2042   /* Retrieve native structure address */
2043   nat = nfc_jni_get_nat(e, o);
2044
2045   /* Create the local semaphore */
2046   if (!nfc_cb_data_init(cb_data, (void*)nat))
2047   {
2048      goto clean_and_return;
2049   }
2050
2051   /* Check LLCP compliancy */
2052   TRACE("phLibNfc_Llcp_CheckLlcp(hLlcpHandle=0x%08x)", hLlcpHandle);
2053   REENTRANCE_LOCK();
2054   ret = phLibNfc_Llcp_CheckLlcp(hLlcpHandle,
2055                                 nfc_jni_checkLlcp_callback,
2056                                 nfc_jni_llcp_linkStatus_callback,
2057                                 (void*)cb_data);
2058   REENTRANCE_UNLOCK();
2059   /* In case of a NFCIP return NFCSTATUS_SUCCESS and in case of an another protocol
2060    * NFCSTATUS_PENDING. In this case NFCSTATUS_SUCCESS will also cause the callback. */
2061   if(ret != NFCSTATUS_PENDING && ret != NFCSTATUS_SUCCESS)
2062   {
2063      LOGE("phLibNfc_Llcp_CheckLlcp() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2064      freeData = true;
2065      goto clean_and_return;
2066   }
2067   TRACE("phLibNfc_Llcp_CheckLlcp() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2068
2069   /* Wait for callback response */
2070   if(sem_wait(&cb_data->sem))
2071   {
2072      LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
2073      goto clean_and_return;
2074   }
2075
2076   if(cb_data->status == NFCSTATUS_SUCCESS)
2077   {
2078      result = JNI_TRUE;
2079   }
2080
2081clean_and_return:
2082   nfc_cb_data_deinit(cb_data);
2083   if (freeData) {
2084       free(cb_data);
2085   }
2086   CONCURRENCY_UNLOCK();
2087   return result;
2088}
2089
2090static jboolean com_android_nfc_NfcManager_doActivateLlcp(JNIEnv *e, jobject o)
2091{
2092   NFCSTATUS ret;
2093   TRACE("phLibNfc_Llcp_Activate(hRemoteDevice=0x%08x)", hLlcpHandle);
2094   REENTRANCE_LOCK();
2095   ret = phLibNfc_Llcp_Activate(hLlcpHandle);
2096   REENTRANCE_UNLOCK();
2097   if(ret == NFCSTATUS_SUCCESS)
2098   {
2099      TRACE("phLibNfc_Llcp_Activate() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2100      return JNI_TRUE;
2101   }
2102   else
2103   {
2104      LOGE("phLibNfc_Llcp_Activate() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2105      return JNI_FALSE;
2106   }
2107}
2108
2109
2110
2111static jobject com_android_nfc_NfcManager_doCreateLlcpConnectionlessSocket(JNIEnv *e, jobject o, jint nSap)
2112{
2113   NFCSTATUS ret;
2114   jobject connectionlessSocket = NULL;
2115   phLibNfc_Handle hLlcpSocket;
2116   struct nfc_jni_native_data *nat;
2117   jclass clsNativeConnectionlessSocket;
2118   jfieldID f;
2119
2120   /* Retrieve native structure address */
2121   nat = nfc_jni_get_nat(e, o);
2122
2123   /* Create socket */
2124   TRACE("phLibNfc_Llcp_Socket(eType=phFriNfc_LlcpTransport_eConnectionLess, ...)");
2125   REENTRANCE_LOCK();
2126   ret = phLibNfc_Llcp_Socket(phFriNfc_LlcpTransport_eConnectionLess,
2127                              NULL,
2128                              NULL,
2129                              &hLlcpSocket,
2130                              nfc_jni_llcp_transport_socket_err_callback,
2131                              (void*)nat);
2132   REENTRANCE_UNLOCK();
2133
2134   if(ret != NFCSTATUS_SUCCESS)
2135   {
2136      lastErrorStatus = ret;
2137      LOGE("phLibNfc_Llcp_Socket() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2138      return NULL;
2139   }
2140   TRACE("phLibNfc_Llcp_Socket() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2141
2142
2143   /* Bind socket */
2144   TRACE("phLibNfc_Llcp_Bind(hSocket=0x%08x, nSap=0x%02x)", hLlcpSocket, nSap);
2145   REENTRANCE_LOCK();
2146   ret = phLibNfc_Llcp_Bind(hLlcpSocket,nSap);
2147   REENTRANCE_UNLOCK();
2148   if(ret != NFCSTATUS_SUCCESS)
2149   {
2150      lastErrorStatus = ret;
2151      LOGE("phLibNfc_Llcp_Bind() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2152      /* Close socket created */
2153      REENTRANCE_LOCK();
2154      ret = phLibNfc_Llcp_Close(hLlcpSocket);
2155      REENTRANCE_UNLOCK();
2156      return NULL;
2157   }
2158   TRACE("phLibNfc_Llcp_Bind() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2159
2160
2161   /* Create new NativeLlcpConnectionlessSocket object */
2162   if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeLlcpConnectionlessSocket",&(connectionlessSocket)) == -1)
2163   {
2164      return NULL;
2165   }
2166
2167   /* Get NativeConnectionless class object */
2168   clsNativeConnectionlessSocket = e->GetObjectClass(connectionlessSocket);
2169   if(e->ExceptionCheck())
2170   {
2171      return NULL;
2172   }
2173
2174   /* Set socket handle */
2175   f = e->GetFieldID(clsNativeConnectionlessSocket, "mHandle", "I");
2176   e->SetIntField(connectionlessSocket, f,(jint)hLlcpSocket);
2177   TRACE("Connectionless socket Handle = %02x\n",hLlcpSocket);
2178
2179   /* Set the miu link of the connectionless socket */
2180   f = e->GetFieldID(clsNativeConnectionlessSocket, "mLinkMiu", "I");
2181   e->SetIntField(connectionlessSocket, f,(jint)PHFRINFC_LLCP_MIU_DEFAULT);
2182   TRACE("Connectionless socket Link MIU = %d\n",PHFRINFC_LLCP_MIU_DEFAULT);
2183
2184   /* Set socket SAP */
2185   f = e->GetFieldID(clsNativeConnectionlessSocket, "mSap", "I");
2186   e->SetIntField(connectionlessSocket, f,(jint)nSap);
2187   TRACE("Connectionless socket SAP = %d\n",nSap);
2188
2189   return connectionlessSocket;
2190}
2191
2192static jobject com_android_nfc_NfcManager_doCreateLlcpServiceSocket(JNIEnv *e, jobject o, jint nSap, jstring sn, jint miu, jint rw, jint linearBufferLength)
2193{
2194   NFCSTATUS ret;
2195   phLibNfc_Handle hLlcpSocket;
2196   phLibNfc_Llcp_sSocketOptions_t sOptions;
2197   phNfc_sData_t sWorkingBuffer;
2198   phNfc_sData_t serviceName;
2199   struct nfc_jni_native_data *nat;
2200   jobject serviceSocket = NULL;
2201   jclass clsNativeLlcpServiceSocket;
2202   jfieldID f;
2203
2204   /* Retrieve native structure address */
2205   nat = nfc_jni_get_nat(e, o);
2206
2207   /* Set Connection Oriented socket options */
2208   sOptions.miu = miu;
2209   sOptions.rw  = rw;
2210
2211   /* Allocate Working buffer length */
2212   sWorkingBuffer.length = (miu*rw)+ miu + linearBufferLength;
2213   sWorkingBuffer.buffer = (uint8_t*)malloc(sWorkingBuffer.length);
2214
2215
2216   /* Create socket */
2217   TRACE("phLibNfc_Llcp_Socket(hRemoteDevice=0x%08x, eType=phFriNfc_LlcpTransport_eConnectionOriented, ...)", hLlcpHandle);
2218   REENTRANCE_LOCK();
2219   ret = phLibNfc_Llcp_Socket(phFriNfc_LlcpTransport_eConnectionOriented,
2220                              &sOptions,
2221                              &sWorkingBuffer,
2222                              &hLlcpSocket,
2223                              nfc_jni_llcp_transport_socket_err_callback,
2224                              (void*)nat);
2225   REENTRANCE_UNLOCK();
2226
2227   if(ret != NFCSTATUS_SUCCESS)
2228   {
2229      LOGE("phLibNfc_Llcp_Socket() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2230      lastErrorStatus = ret;
2231      return NULL;
2232   }
2233   TRACE("phLibNfc_Llcp_Socket() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2234
2235   /* Bind socket */
2236   TRACE("phLibNfc_Llcp_Bind(hSocket=0x%08x, nSap=0x%02x)", hLlcpSocket, nSap);
2237   REENTRANCE_LOCK();
2238   ret = phLibNfc_Llcp_Bind(hLlcpSocket,nSap);
2239   REENTRANCE_UNLOCK();
2240   if(ret != NFCSTATUS_SUCCESS)
2241   {
2242      lastErrorStatus = ret;
2243      LOGE("phLibNfc_Llcp_Bind() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2244      /* Close socket created */
2245      ret = phLibNfc_Llcp_Close(hLlcpSocket);
2246      return NULL;
2247   }
2248   TRACE("phLibNfc_Llcp_Bind() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2249
2250   /* Service socket */
2251   if (sn == NULL) {
2252       serviceName.buffer = NULL;
2253       serviceName.length = 0;
2254   } else {
2255       serviceName.buffer = (uint8_t*)e->GetStringUTFChars(sn, NULL);
2256       serviceName.length = (uint32_t)e->GetStringUTFLength(sn);
2257   }
2258
2259   TRACE("phLibNfc_Llcp_Listen(hSocket=0x%08x, ...)", hLlcpSocket);
2260   REENTRANCE_LOCK();
2261   ret = phLibNfc_Llcp_Listen( hLlcpSocket,
2262                               &serviceName,
2263                               nfc_jni_llcp_transport_listen_socket_callback,
2264                               (void*)hLlcpSocket);
2265   REENTRANCE_UNLOCK();
2266
2267   if(ret != NFCSTATUS_SUCCESS)
2268   {
2269      LOGE("phLibNfc_Llcp_Listen() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2270      lastErrorStatus = ret;
2271      /* Close created socket */
2272      REENTRANCE_LOCK();
2273      ret = phLibNfc_Llcp_Close(hLlcpSocket);
2274      REENTRANCE_UNLOCK();
2275      return NULL;
2276   }
2277   TRACE("phLibNfc_Llcp_Listen() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2278
2279   /* Create new NativeLlcpServiceSocket object */
2280   if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeLlcpServiceSocket",&(serviceSocket)) == -1)
2281   {
2282      LOGE("Llcp Socket object creation error");
2283      return NULL;
2284   }
2285
2286   /* Get NativeLlcpServiceSocket class object */
2287   clsNativeLlcpServiceSocket = e->GetObjectClass(serviceSocket);
2288   if(e->ExceptionCheck())
2289   {
2290      LOGE("Llcp Socket get object class error");
2291      return NULL;
2292   }
2293
2294   /* Set socket handle */
2295   f = e->GetFieldID(clsNativeLlcpServiceSocket, "mHandle", "I");
2296   e->SetIntField(serviceSocket, f,(jint)hLlcpSocket);
2297   TRACE("Service socket Handle = %02x\n",hLlcpSocket);
2298
2299   /* Set socket linear buffer length */
2300   f = e->GetFieldID(clsNativeLlcpServiceSocket, "mLocalLinearBufferLength", "I");
2301   e->SetIntField(serviceSocket, f,(jint)linearBufferLength);
2302   TRACE("Service socket Linear buffer length = %02x\n",linearBufferLength);
2303
2304   /* Set socket MIU */
2305   f = e->GetFieldID(clsNativeLlcpServiceSocket, "mLocalMiu", "I");
2306   e->SetIntField(serviceSocket, f,(jint)miu);
2307   TRACE("Service socket MIU = %d\n",miu);
2308
2309   /* Set socket RW */
2310   f = e->GetFieldID(clsNativeLlcpServiceSocket, "mLocalRw", "I");
2311   e->SetIntField(serviceSocket, f,(jint)rw);
2312   TRACE("Service socket RW = %d\n",rw);
2313
2314   return serviceSocket;
2315}
2316
2317static jobject com_android_nfc_NfcManager_doCreateLlcpSocket(JNIEnv *e, jobject o, jint nSap, jint miu, jint rw, jint linearBufferLength)
2318{
2319   jobject clientSocket = NULL;
2320   NFCSTATUS ret;
2321   phLibNfc_Handle hLlcpSocket;
2322   phLibNfc_Llcp_sSocketOptions_t sOptions;
2323   phNfc_sData_t sWorkingBuffer;
2324   struct nfc_jni_native_data *nat;
2325   jclass clsNativeLlcpSocket;
2326   jfieldID f;
2327
2328   /* Retrieve native structure address */
2329   nat = nfc_jni_get_nat(e, o);
2330
2331   /* Set Connection Oriented socket options */
2332   sOptions.miu = miu;
2333   sOptions.rw  = rw;
2334
2335   /* Allocate Working buffer length */
2336   sWorkingBuffer.length = (miu*rw)+ miu + linearBufferLength;
2337   sWorkingBuffer.buffer = (uint8_t*)malloc(sWorkingBuffer.length);
2338
2339   /* Create socket */
2340   TRACE("phLibNfc_Llcp_Socket(eType=phFriNfc_LlcpTransport_eConnectionOriented, ...)");
2341   REENTRANCE_LOCK();
2342   ret = phLibNfc_Llcp_Socket(phFriNfc_LlcpTransport_eConnectionOriented,
2343                              &sOptions,
2344                              &sWorkingBuffer,
2345                              &hLlcpSocket,
2346                              nfc_jni_llcp_transport_socket_err_callback,
2347                              (void*)nat);
2348   REENTRANCE_UNLOCK();
2349
2350   if(ret != NFCSTATUS_SUCCESS)
2351   {
2352      LOGE("phLibNfc_Llcp_Socket() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2353      lastErrorStatus = ret;
2354      return NULL;
2355   }
2356   TRACE("phLibNfc_Llcp_Socket() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2357
2358   /* Create new NativeLlcpSocket object */
2359   if(nfc_jni_cache_object(e,"com/android/nfc/nxp/NativeLlcpSocket",&(clientSocket)) == -1)
2360   {
2361      LOGE("Llcp socket object creation error");
2362      return NULL;
2363   }
2364
2365   /* Get NativeConnectionless class object */
2366   clsNativeLlcpSocket = e->GetObjectClass(clientSocket);
2367   if(e->ExceptionCheck())
2368   {
2369      LOGE("Get class object error");
2370      return NULL;
2371   }
2372
2373   /* Test if an SAP number is present */
2374   if(nSap != 0)
2375   {
2376      /* Bind socket */
2377      TRACE("phLibNfc_Llcp_Bind(hSocket=0x%08x, nSap=0x%02x)", hLlcpSocket, nSap);
2378      REENTRANCE_LOCK();
2379      ret = phLibNfc_Llcp_Bind(hLlcpSocket,nSap);
2380      REENTRANCE_UNLOCK();
2381      if(ret != NFCSTATUS_SUCCESS)
2382      {
2383         lastErrorStatus = ret;
2384         LOGE("phLibNfc_Llcp_Bind() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2385         /* Close socket created */
2386         REENTRANCE_LOCK();
2387         ret = phLibNfc_Llcp_Close(hLlcpSocket);
2388         REENTRANCE_UNLOCK();
2389         return NULL;
2390      }
2391      TRACE("phLibNfc_Llcp_Bind() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2392
2393      /* Set socket SAP */
2394      f = e->GetFieldID(clsNativeLlcpSocket, "mSap", "I");
2395      e->SetIntField(clientSocket, f,(jint)nSap);
2396      TRACE("socket SAP = %d\n",nSap);
2397   }
2398
2399   /* Set socket handle */
2400   f = e->GetFieldID(clsNativeLlcpSocket, "mHandle", "I");
2401   e->SetIntField(clientSocket, f,(jint)hLlcpSocket);
2402   TRACE("socket Handle = %02x\n",hLlcpSocket);
2403
2404   /* Set socket MIU */
2405   f = e->GetFieldID(clsNativeLlcpSocket, "mLocalMiu", "I");
2406   e->SetIntField(clientSocket, f,(jint)miu);
2407   TRACE("socket MIU = %d\n",miu);
2408
2409   /* Set socket RW */
2410   f = e->GetFieldID(clsNativeLlcpSocket, "mLocalRw", "I");
2411   e->SetIntField(clientSocket, f,(jint)rw);
2412   TRACE("socket RW = %d\n",rw);
2413
2414
2415   return clientSocket;
2416}
2417
2418static jint com_android_nfc_NfcManager_doGetLastError(JNIEnv *e, jobject o)
2419{
2420   TRACE("Last Error Status = 0x%02x",lastErrorStatus);
2421
2422   if(lastErrorStatus == NFCSTATUS_BUFFER_TOO_SMALL)
2423   {
2424      return ERROR_BUFFER_TOO_SMALL;
2425   }
2426   else if(lastErrorStatus == NFCSTATUS_INSUFFICIENT_RESOURCES)
2427   {
2428      return  ERROR_INSUFFICIENT_RESOURCES;
2429   }
2430   else
2431   {
2432      return lastErrorStatus;
2433   }
2434}
2435
2436static void com_android_nfc_NfcManager_doAbort(JNIEnv *e, jobject o)
2437{
2438    emergency_recovery(NULL);
2439}
2440
2441static jboolean com_android_nfc_NfcManager_doDownload(JNIEnv *e, jobject o)
2442{
2443    char* firmware_version;
2444    jboolean result = FALSE;
2445    int load_result;
2446    int unconfigure_status;
2447    bool drive_state = FALSE;
2448    uint8_t OutputBuffer[1];
2449    uint8_t InputBuffer[1];
2450    struct timespec ts;
2451    NFCSTATUS status = NFCSTATUS_FAILED;
2452    struct nfc_jni_callback_data cb_data;
2453    struct nfc_jni_native_data *nat = NULL;
2454    char value[PROPERTY_VALUE_MAX];
2455
2456    /* Create the local semaphore */
2457    if (!nfc_cb_data_init(&cb_data, NULL))
2458    {
2459       result = FALSE;
2460       goto clean_and_return;
2461    }
2462
2463    /* Retrieve native structure address */
2464    nat = nfc_jni_get_nat(e, o);
2465
2466    CONCURRENCY_LOCK();
2467
2468    /* Initialize Driver */
2469    if(!driverConfigured)
2470    {
2471        result = nfc_jni_configure_driver(nat);
2472        drive_state = TRUE;
2473    }
2474
2475    TRACE("com_android_nfc_NfcManager_doDownload()");
2476
2477    TRACE("Go in Download Mode");
2478    phLibNfc_Download_Mode();
2479
2480    TRACE("Load new Firmware Image");
2481    load_result = phLibNfc_Load_Firmware_Image();
2482    if(load_result != 0)
2483    {
2484        TRACE("Load new Firmware Image - status = %d",load_result);
2485        result = FALSE;
2486        goto clean_and_return;
2487    }
2488
2489    // Download
2490    gInputParam.buffer  = InputBuffer;
2491    gInputParam.length  = 0x01;
2492    gOutputParam.buffer = OutputBuffer;
2493    gOutputParam.length = 0x01;
2494
2495    LOGD("Download new Firmware");
2496    REENTRANCE_LOCK();
2497    status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_FW_DOWNLOAD, &gInputParam, &gOutputParam, nfc_jni_ioctl_callback, (void *)&cb_data);
2498    REENTRANCE_UNLOCK();
2499    if(status != NFCSTATUS_PENDING)
2500    {
2501        LOGE("phLibNfc_Mgt_IoCtl() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
2502        result = FALSE;
2503        goto clean_and_return;
2504    }
2505    TRACE("phLibNfc_Mgt_IoCtl() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
2506
2507    /* Wait for callback response */
2508    if(sem_wait(&cb_data.sem))
2509    {
2510       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
2511       result = FALSE;
2512       goto clean_and_return;
2513    }
2514
2515    /* NOTE: we will get NFCSTATUS_FEATURE_NOT_SUPPORTED when we
2516       try to download an old-style firmware on top of a new-style
2517       firmware.  Hence, this is expected behavior, and not an
2518       error condition. */
2519    if(cb_data.status != NFCSTATUS_SUCCESS && cb_data.status != NFCSTATUS_FEATURE_NOT_SUPPORTED)
2520    {
2521        TRACE("phLibNfc_Mgt_IoCtl() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
2522        result = FALSE;
2523        goto clean_and_return;
2524    }
2525
2526    if(cb_data.status == NFCSTATUS_FEATURE_NOT_SUPPORTED)
2527    {
2528        LOGW("Old-style firmware not installed on top of new-style firmware. Using existing firmware in the chip.");
2529    }
2530
2531    /*Download is successful*/
2532    result = TRUE;
2533
2534clean_and_return:
2535    TRACE("phLibNfc_HW_Reset()");
2536    phLibNfc_HW_Reset();
2537    /* Deinitialize Driver */
2538    if(drive_state)
2539    {
2540        result = nfc_jni_unconfigure_driver(nat);
2541    }
2542    CONCURRENCY_UNLOCK();
2543    nfc_cb_data_deinit(&cb_data);
2544    return result;
2545}
2546
2547static jstring com_android_nfc_NfcManager_doDump(JNIEnv *e, jobject o)
2548{
2549    char buffer[100];
2550    snprintf(buffer, sizeof(buffer), "libnfc llc error_count=%u", libnfc_llc_error_count);
2551    return e->NewStringUTF(buffer);
2552}
2553
2554/*
2555 * JNI registration.
2556 */
2557static JNINativeMethod gMethods[] =
2558{
2559   {"doDownload", "()Z",
2560        (void *)com_android_nfc_NfcManager_doDownload},
2561
2562   {"initializeNativeStructure", "()Z",
2563      (void *)com_android_nfc_NfcManager_init_native_struc},
2564
2565   {"initialize", "()Z",
2566      (void *)com_android_nfc_NfcManager_initialize},
2567
2568   {"deinitialize", "()Z",
2569      (void *)com_android_nfc_NfcManager_deinitialize},
2570
2571   {"enableDiscovery", "()V",
2572      (void *)com_android_nfc_NfcManager_enableDiscovery},
2573
2574   {"doGetSecureElementList", "()[I",
2575      (void *)com_android_nfc_NfcManager_doGetSecureElementList},
2576
2577   {"doSelectSecureElement", "()V",
2578      (void *)com_android_nfc_NfcManager_doSelectSecureElement},
2579
2580   {"doDeselectSecureElement", "()V",
2581      (void *)com_android_nfc_NfcManager_doDeselectSecureElement},
2582
2583   {"doCheckLlcp", "()Z",
2584      (void *)com_android_nfc_NfcManager_doCheckLlcp},
2585
2586   {"doActivateLlcp", "()Z",
2587      (void *)com_android_nfc_NfcManager_doActivateLlcp},
2588
2589   {"doCreateLlcpConnectionlessSocket", "(I)Lcom/android/nfc/nxp/NativeLlcpConnectionlessSocket;",
2590      (void *)com_android_nfc_NfcManager_doCreateLlcpConnectionlessSocket},
2591
2592   {"doCreateLlcpServiceSocket", "(ILjava/lang/String;III)Lcom/android/nfc/nxp/NativeLlcpServiceSocket;",
2593      (void *)com_android_nfc_NfcManager_doCreateLlcpServiceSocket},
2594
2595   {"doCreateLlcpSocket", "(IIII)Lcom/android/nfc/nxp/NativeLlcpSocket;",
2596      (void *)com_android_nfc_NfcManager_doCreateLlcpSocket},
2597
2598   {"doGetLastError", "()I",
2599      (void *)com_android_nfc_NfcManager_doGetLastError},
2600
2601   {"disableDiscovery", "()V",
2602      (void *)com_android_nfc_NfcManager_disableDiscovery},
2603
2604   {"doSetTimeout", "(II)Z",
2605      (void *)com_android_nfc_NfcManager_doSetTimeout},
2606
2607   {"doGetTimeout", "(I)I",
2608      (void *)com_android_nfc_NfcManager_doGetTimeout},
2609
2610   {"doResetTimeouts", "()V",
2611      (void *)com_android_nfc_NfcManager_doResetTimeouts},
2612
2613   {"doAbort", "()V",
2614      (void *)com_android_nfc_NfcManager_doAbort},
2615
2616   {"doDump", "()Ljava/lang/String;",
2617      (void *)com_android_nfc_NfcManager_doDump},
2618};
2619
2620
2621int register_com_android_nfc_NativeNfcManager(JNIEnv *e)
2622{
2623    nfc_jni_native_monitor_t *nfc_jni_native_monitor;
2624
2625   nfc_jni_native_monitor = nfc_jni_init_monitor();
2626   if(nfc_jni_native_monitor == NULL)
2627   {
2628      LOGE("NFC Manager cannot recover native monitor %x\n", errno);
2629      return -1;
2630   }
2631
2632   return jniRegisterNativeMethods(e,
2633      "com/android/nfc/nxp/NativeNfcManager",
2634      gMethods, NELEM(gMethods));
2635}
2636
2637} /* namespace android */
2638