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