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#include <ScopedLocalRef.h>
28
29#include "com_android_nfc.h"
30
31#define ERROR_BUFFER_TOO_SMALL       -12
32#define ERROR_INSUFFICIENT_RESOURCES -9
33
34extern uint32_t libnfc_llc_error_count;
35
36static phLibNfc_sConfig_t   gDrvCfg;
37void   *gHWRef;
38static phNfc_sData_t gInputParam;
39static phNfc_sData_t gOutputParam;
40
41uint8_t device_connected_flag;
42static bool driverConfigured = FALSE;
43
44static phLibNfc_Handle              hLlcpHandle;
45static NFCSTATUS                    lastErrorStatus = NFCSTATUS_FAILED;
46static phLibNfc_Llcp_eLinkStatus_t  g_eLinkStatus = phFriNfc_LlcpMac_eLinkDefault;
47
48static jmethodID cached_NfcManager_notifyNdefMessageListeners;
49static jmethodID cached_NfcManager_notifyLlcpLinkActivation;
50static jmethodID cached_NfcManager_notifyLlcpLinkDeactivated;
51static jmethodID cached_NfcManager_notifyTargetDeselected;
52
53static jmethodID cached_NfcManager_notifyRfFieldActivated;
54static jmethodID cached_NfcManager_notifyRfFieldDeactivated;
55namespace android {
56
57phLibNfc_Handle     storedHandle = 0;
58
59struct nfc_jni_native_data *exported_nat = NULL;
60
61/* Internal functions declaration */
62static void *nfc_jni_client_thread(void *arg);
63static void nfc_jni_init_callback(void *pContext, NFCSTATUS status);
64static void nfc_jni_deinit_callback(void *pContext, NFCSTATUS status);
65static void nfc_jni_discover_callback(void *pContext, NFCSTATUS status);
66static void nfc_jni_se_set_mode_callback(void *context,
67        phLibNfc_Handle handle, NFCSTATUS status);
68static void nfc_jni_llcpcfg_callback(void *pContext, NFCSTATUS status);
69static void nfc_jni_start_discovery_locked(struct nfc_jni_native_data *nat, bool resume);
70static void nfc_jni_Discovery_notification_callback(void *pContext,
71        phLibNfc_RemoteDevList_t *psRemoteDevList,
72        uint8_t uNofRemoteDev, NFCSTATUS status);
73static void nfc_jni_transaction_callback(void *context,
74        phLibNfc_eSE_EvtType_t evt_type, phLibNfc_Handle handle,
75        phLibNfc_uSeEvtInfo_t *evt_info, NFCSTATUS status);
76static bool performDownload(struct nfc_jni_native_data *nat, bool takeLock);
77
78extern void set_target_activationBytes(JNIEnv *e, jobject tag,
79        phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo);
80extern void set_target_pollBytes(JNIEnv *e, jobject tag,
81        phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo);
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   NFCSTATUS ret;
910   const char * typeName;
911   struct timespec ts;
912   phNfc_sData_t data;
913   int i;
914   int target_index = 0; // Target that will be reported (if multiple can be >0)
915
916   struct nfc_jni_native_data* nat = (struct nfc_jni_native_data *)pContext;
917
918   JNIEnv *e;
919   nat->vm->GetEnv( (void **)&e, nat->env_version);
920
921   if(status == NFCSTATUS_DESELECTED)
922   {
923      LOG_CALLBACK("nfc_jni_Discovery_notification_callback: Target deselected", status);
924
925      /* Notify manager that a target was deselected */
926      e->CallVoidMethod(nat->manager, cached_NfcManager_notifyTargetDeselected);
927      if(e->ExceptionCheck())
928      {
929         ALOGE("Exception occurred");
930         kill_client(nat);
931      }
932   }
933   else
934   {
935      LOG_CALLBACK("nfc_jni_Discovery_notification_callback", status);
936      TRACE("Discovered %d tags", uNofRemoteDev);
937
938      target_index = find_preferred_target(psRemoteDevList, uNofRemoteDev);
939
940      ScopedLocalRef<jobject> tag(e, NULL);
941
942      /* Reset device connected flag */
943      device_connected_flag = 1;
944      phLibNfc_sRemoteDevInformation_t *remDevInfo = psRemoteDevList[target_index].psRemoteDevInfo;
945      phLibNfc_Handle remDevHandle = psRemoteDevList[target_index].hTargetDev;
946      if((remDevInfo->RemDevType == phNfc_eNfcIP1_Initiator)
947          || (remDevInfo->RemDevType == phNfc_eNfcIP1_Target))
948      {
949         ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(nat->cached_P2pDevice));
950         if(e->ExceptionCheck())
951         {
952            ALOGE("Get Object Class Error");
953            kill_client(nat);
954            return;
955         }
956
957         /* New target instance */
958         jmethodID ctor = e->GetMethodID(tag_cls.get(), "<init>", "()V");
959         tag.reset(e->NewObject(tag_cls.get(), ctor));
960
961         /* Set P2P Target mode */
962         jfieldID f = e->GetFieldID(tag_cls.get(), "mMode", "I");
963
964         if(remDevInfo->RemDevType == phNfc_eNfcIP1_Initiator)
965         {
966            ALOGD("Discovered P2P Initiator");
967            e->SetIntField(tag.get(), f, (jint)MODE_P2P_INITIATOR);
968         }
969         else
970         {
971            ALOGD("Discovered P2P Target");
972            e->SetIntField(tag.get(), f, (jint)MODE_P2P_TARGET);
973         }
974
975         if(remDevInfo->RemDevType == phNfc_eNfcIP1_Initiator)
976         {
977            /* Set General Bytes */
978            f = e->GetFieldID(tag_cls.get(), "mGeneralBytes", "[B");
979
980           TRACE("General Bytes length =");
981           for(i=0;i<remDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo_Length;i++)
982           {
983               ALOGD("%02x ", remDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo[i]);
984           }
985
986            ScopedLocalRef<jbyteArray> generalBytes(e, e->NewByteArray(remDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo_Length));
987
988            e->SetByteArrayRegion(generalBytes.get(), 0,
989                                  remDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo_Length,
990                                  (jbyte *)remDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo);
991            e->SetObjectField(tag.get(), f, generalBytes.get());
992         }
993
994         /* Set tag handle */
995         f = e->GetFieldID(tag_cls.get(), "mHandle", "I");
996         e->SetIntField(tag.get(), f,(jint)remDevHandle);
997         TRACE("Target handle = 0x%08x",remDevHandle);
998      }
999      else
1000      {
1001        ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(nat->cached_NfcTag));
1002        if(e->ExceptionCheck())
1003        {
1004            kill_client(nat);
1005            return;
1006        }
1007
1008        /* New tag instance */
1009        jmethodID ctor = e->GetMethodID(tag_cls.get(), "<init>", "()V");
1010        tag.reset(e->NewObject(tag_cls.get(), ctor));
1011
1012        bool multi_protocol = false;
1013
1014        if(status == NFCSTATUS_MULTIPLE_PROTOCOLS)
1015        {
1016            TRACE("Multiple Protocol TAG detected\n");
1017            multi_protocol = true;
1018        }
1019
1020        /* Set tag UID */
1021        jfieldID f = e->GetFieldID(tag_cls.get(), "mUid", "[B");
1022        data = get_target_uid(remDevInfo);
1023        ScopedLocalRef<jbyteArray> tagUid(e, e->NewByteArray(data.length));
1024        if(data.length > 0)
1025        {
1026           e->SetByteArrayRegion(tagUid.get(), 0, data.length, (jbyte *)data.buffer);
1027        }
1028        e->SetObjectField(tag.get(), f, tagUid.get());
1029
1030        /* Generate technology list */
1031        ScopedLocalRef<jintArray> techList(e, NULL);
1032        ScopedLocalRef<jintArray> handleList(e, NULL);
1033        ScopedLocalRef<jintArray> typeList(e, NULL);
1034        nfc_jni_get_technology_tree(e, psRemoteDevList,
1035                multi_protocol ? uNofRemoteDev : 1,
1036                &techList, &handleList, &typeList);
1037
1038        /* Push the technology list into the java object */
1039        f = e->GetFieldID(tag_cls.get(), "mTechList", "[I");
1040        e->SetObjectField(tag.get(), f, techList.get());
1041
1042        f = e->GetFieldID(tag_cls.get(), "mTechHandles", "[I");
1043        e->SetObjectField(tag.get(), f, handleList.get());
1044
1045        f = e->GetFieldID(tag_cls.get(), "mTechLibNfcTypes", "[I");
1046        e->SetObjectField(tag.get(), f, typeList.get());
1047
1048        f = e->GetFieldID(tag_cls.get(), "mConnectedTechIndex", "I");
1049        e->SetIntField(tag.get(), f,(jint)-1);
1050
1051        f = e->GetFieldID(tag_cls.get(), "mConnectedHandle", "I");
1052        e->SetIntField(tag.get(), f,(jint)-1);
1053
1054        set_target_pollBytes(e, tag.get(), psRemoteDevList->psRemoteDevInfo);
1055
1056        set_target_activationBytes(e, tag.get(), psRemoteDevList->psRemoteDevInfo);
1057      }
1058
1059      storedHandle = remDevHandle;
1060      if (nat->tag != NULL) {
1061          e->DeleteGlobalRef(nat->tag);
1062      }
1063      nat->tag = e->NewGlobalRef(tag.get());
1064
1065      /* Notify the service */
1066      TRACE("Notify Nfc Service");
1067      if((remDevInfo->RemDevType == phNfc_eNfcIP1_Initiator)
1068          || (remDevInfo->RemDevType == phNfc_eNfcIP1_Target))
1069      {
1070         /* Store the handle of the P2P device */
1071         hLlcpHandle = remDevHandle;
1072
1073         /* Notify manager that new a P2P device was found */
1074         e->CallVoidMethod(nat->manager, cached_NfcManager_notifyLlcpLinkActivation, tag.get());
1075         if(e->ExceptionCheck())
1076         {
1077            ALOGE("Exception occurred");
1078            kill_client(nat);
1079         }
1080      }
1081      else
1082      {
1083         /* Notify manager that new a tag was found */
1084         e->CallVoidMethod(nat->manager, cached_NfcManager_notifyNdefMessageListeners, tag.get());
1085         if(e->ExceptionCheck())
1086         {
1087            ALOGE("Exception occurred");
1088            kill_client(nat);
1089         }
1090      }
1091   }
1092}
1093
1094static void nfc_jni_init_callback(void *pContext, NFCSTATUS status)
1095{
1096   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
1097
1098   LOG_CALLBACK("nfc_jni_init_callback", status);
1099
1100   pContextData->status = status;
1101   sem_post(&pContextData->sem);
1102}
1103
1104static void nfc_jni_deinit_callback(void *pContext, NFCSTATUS status)
1105{
1106   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
1107
1108   LOG_CALLBACK("nfc_jni_deinit_callback", status);
1109
1110   pContextData->status = status;
1111   sem_post(&pContextData->sem);
1112}
1113
1114/* Set Secure Element mode callback*/
1115static void nfc_jni_smartMX_setModeCb (void*            pContext,
1116                                       phLibNfc_Handle  /*hSecureElement*/,
1117                                       NFCSTATUS        status)
1118{
1119   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
1120
1121   LOG_CALLBACK("nfc_jni_smartMX_setModeCb", status);
1122
1123   pContextData->status = status;
1124   sem_post(&pContextData->sem);
1125}
1126
1127/* Card Emulation callback */
1128static void nfc_jni_transaction_callback(void *context,
1129   phLibNfc_eSE_EvtType_t evt_type, phLibNfc_Handle /*handle*/,
1130   phLibNfc_uSeEvtInfo_t *evt_info, NFCSTATUS status)
1131{
1132    JNIEnv *e;
1133    jobject tmp_array = NULL;
1134    jobject mifare_block = NULL;
1135    struct nfc_jni_native_data *nat;
1136    phNfc_sData_t *aid;
1137    phNfc_sData_t *mifare_command;
1138    struct nfc_jni_callback_data *pCallbackData;
1139    int i=0;
1140
1141    LOG_CALLBACK("nfc_jni_transaction_callback", status);
1142
1143    nat = (struct nfc_jni_native_data *)context;
1144
1145    nat->vm->GetEnv( (void **)&e, nat->env_version);
1146
1147    if(status == NFCSTATUS_SUCCESS)
1148    {
1149        switch(evt_type)
1150        {
1151            case phLibNfc_eSE_EvtStartTransaction:
1152            {
1153                TRACE("> SE EVT_START_TRANSACTION");
1154            }break;
1155
1156            case phLibNfc_eSE_EvtApduReceived:
1157            {
1158                TRACE("> SE EVT_APDU_RECEIVED");
1159            }break;
1160
1161            case phLibNfc_eSE_EvtCardRemoval:
1162            {
1163                TRACE("> SE EVT_EMV_CARD_REMOVAL");
1164            }break;
1165
1166            case phLibNfc_eSE_EvtMifareAccess:
1167            {
1168                TRACE("> SE EVT_MIFARE_ACCESS");
1169            }break;
1170
1171            case phLibNfc_eSE_EvtFieldOn:
1172            {
1173                TRACE("> SE EVT_FIELD_ON");
1174                e->CallVoidMethod(nat->manager, cached_NfcManager_notifyRfFieldActivated);
1175            }break;
1176
1177            case phLibNfc_eSE_EvtFieldOff:
1178            {
1179                TRACE("> SE EVT_FIELD_OFF");
1180                e->CallVoidMethod(nat->manager, cached_NfcManager_notifyRfFieldDeactivated);
1181            }break;
1182
1183            default:
1184            {
1185                TRACE("Unknown SE event");
1186            }break;
1187        }
1188    }
1189    else
1190    {
1191        ALOGE("SE transaction notification error");
1192        goto error;
1193    }
1194
1195    /* Function finished, now clean and return */
1196    goto clean_and_return;
1197
1198 error:
1199    /* In case of error, just discard the notification */
1200    ALOGE("Failed to send SE transaction notification");
1201    e->ExceptionClear();
1202
1203 clean_and_return:
1204    if(tmp_array != NULL)
1205    {
1206       e->DeleteLocalRef(tmp_array);
1207    }
1208}
1209
1210static void nfc_jni_se_set_mode_callback(void *pContext,
1211   phLibNfc_Handle /*handle*/, NFCSTATUS status)
1212{
1213   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
1214
1215   LOG_CALLBACK("nfc_jni_se_set_mode_callback", status);
1216
1217   pContextData->status = status;
1218   sem_post(&pContextData->sem);
1219}
1220
1221/*
1222 * NFCManager methods
1223 */
1224
1225static void nfc_jni_start_discovery_locked(struct nfc_jni_native_data *nat, bool resume)
1226{
1227   NFCSTATUS ret;
1228   struct nfc_jni_callback_data cb_data;
1229   int numRetries = 3;
1230
1231   /* Create the local semaphore */
1232   if (!nfc_cb_data_init(&cb_data, NULL))
1233   {
1234      goto clean_and_return;
1235   }
1236   /* Reset the PN544 ISO XCHG / sw watchdog timeouts */
1237   nfc_jni_reset_timeout_values();
1238
1239   /* Reload the p2p modes */
1240   nat->discovery_cfg.NfcIP_Mode = nat->p2p_initiator_modes;  //initiator
1241   nat->discovery_cfg.NfcIP_Target_Mode = nat->p2p_target_modes;  //target
1242   nat->discovery_cfg.NfcIP_Tgt_Disable = FALSE;
1243
1244   /* Reset device connected flag */
1245   device_connected_flag = 0;
1246configure:
1247   /* Start Polling loop */
1248   TRACE("******  Start NFC Discovery ******");
1249   REENTRANCE_LOCK();
1250   ret = phLibNfc_Mgt_ConfigureDiscovery(resume ? NFC_DISCOVERY_RESUME : NFC_DISCOVERY_CONFIG,
1251      nat->discovery_cfg, nfc_jni_discover_callback, (void *)&cb_data);
1252   REENTRANCE_UNLOCK();
1253   TRACE("phLibNfc_Mgt_ConfigureDiscovery(%s-%s-%s-%s-%s-%s, %s-%x-%x) returned 0x%08x\n",
1254      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443A==TRUE?"3A":"",
1255      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443B==TRUE?"3B":"",
1256      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica212==TRUE?"F2":"",
1257      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica424==TRUE?"F4":"",
1258      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableNfcActive==TRUE?"NFC":"",
1259      nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso15693==TRUE?"RFID":"",
1260      nat->discovery_cfg.PollDevInfo.PollCfgInfo.DisableCardEmulation==FALSE?"CE":"",
1261      nat->discovery_cfg.NfcIP_Mode, nat->discovery_cfg.Duration, ret);
1262
1263   if (ret == NFCSTATUS_BUSY && numRetries-- > 0)
1264   {
1265      TRACE("ConfigDiscovery BUSY, retrying");
1266      usleep(1000000);
1267      goto configure;
1268   }
1269
1270   if(ret != NFCSTATUS_PENDING)
1271   {
1272      emergency_recovery(nat);
1273      goto clean_and_return;
1274   }
1275
1276   /* Wait for callback response */
1277   if(sem_wait(&cb_data.sem))
1278   {
1279      ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
1280      goto clean_and_return;
1281   }
1282
1283clean_and_return:
1284   nfc_cb_data_deinit(&cb_data);
1285}
1286
1287static void nfc_jni_stop_discovery_locked(struct nfc_jni_native_data *nat)
1288{
1289   phLibNfc_sADD_Cfg_t discovery_cfg;
1290   NFCSTATUS ret;
1291   struct nfc_jni_callback_data cb_data;
1292   int numRetries = 3;
1293
1294   /* Create the local semaphore */
1295   if (!nfc_cb_data_init(&cb_data, NULL))
1296   {
1297      goto clean_and_return;
1298   }
1299
1300   discovery_cfg.PollDevInfo.PollEnabled = 0;
1301   discovery_cfg.NfcIP_Mode = phNfc_eDefaultP2PMode;
1302   discovery_cfg.NfcIP_Target_Mode = 0;
1303   discovery_cfg.NfcIP_Tgt_Disable = TRUE;
1304
1305configure:
1306   /* Start Polling loop */
1307   TRACE("******  Stop NFC Discovery ******");
1308   REENTRANCE_LOCK();
1309   ret = phLibNfc_Mgt_ConfigureDiscovery(NFC_DISCOVERY_CONFIG,discovery_cfg, nfc_jni_discover_callback, (void *)&cb_data);
1310   REENTRANCE_UNLOCK();
1311   TRACE("phLibNfc_Mgt_ConfigureDiscovery(%s-%s-%s-%s-%s-%s, %s-%x-%x) returned 0x%08x\n",
1312      discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443A==TRUE?"3A":"",
1313      discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443B==TRUE?"3B":"",
1314      discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica212==TRUE?"F2":"",
1315      discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica424==TRUE?"F4":"",
1316      discovery_cfg.PollDevInfo.PollCfgInfo.EnableNfcActive==TRUE?"NFC":"",
1317      discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso15693==TRUE?"RFID":"",
1318      discovery_cfg.PollDevInfo.PollCfgInfo.DisableCardEmulation==FALSE?"CE":"",
1319      discovery_cfg.NfcIP_Mode, discovery_cfg.Duration, ret);
1320
1321   if (ret == NFCSTATUS_BUSY && numRetries-- > 0)
1322   {
1323      TRACE("ConfigDiscovery BUSY, retrying");
1324      usleep(1000000);
1325      goto configure;
1326   }
1327
1328   if(ret != NFCSTATUS_PENDING)
1329   {
1330      ALOGE("[STOP] ConfigDiscovery returned %x", ret);
1331      emergency_recovery(nat);
1332   }
1333
1334   /* Wait for callback response */
1335   if(sem_wait(&cb_data.sem))
1336   {
1337      ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
1338      goto clean_and_return;
1339   }
1340
1341clean_and_return:
1342   nfc_cb_data_deinit(&cb_data);
1343}
1344
1345
1346static void com_android_nfc_NfcManager_disableDiscovery(JNIEnv *e, jobject o)
1347{
1348    struct nfc_jni_native_data *nat;
1349
1350    CONCURRENCY_LOCK();
1351
1352    /* Retrieve native structure address */
1353    nat = nfc_jni_get_nat(e, o);
1354
1355    nfc_jni_stop_discovery_locked(nat);
1356
1357    CONCURRENCY_UNLOCK();
1358
1359}
1360
1361// TODO: use enable_lptd
1362static void com_android_nfc_NfcManager_enableDiscovery(JNIEnv *e, jobject o, jint modes,
1363        jboolean, jboolean reader_mode, jboolean enable_p2p, jboolean restart)
1364{
1365    NFCSTATUS ret;
1366    struct nfc_jni_native_data *nat;
1367
1368    CONCURRENCY_LOCK();
1369
1370    nat = nfc_jni_get_nat(e, o);
1371
1372   /* Register callback for remote device notifications.
1373    * Must re-register every time we turn on discovery, since other operations
1374    * (such as opening the Secure Element) can change the remote device
1375    * notification callback*/
1376   REENTRANCE_LOCK();
1377   ret = phLibNfc_RemoteDev_NtfRegister(&nat->registry_info, nfc_jni_Discovery_notification_callback, (void *)nat);
1378   REENTRANCE_UNLOCK();
1379   if(ret != NFCSTATUS_SUCCESS)
1380   {
1381        ALOGD("pphLibNfc_RemoteDev_NtfRegister returned 0x%02x",ret);
1382        goto clean_and_return;
1383   }
1384   TRACE("phLibNfc_RemoteDev_NtfRegister(%s-%s-%s-%s-%s-%s-%s-%s) returned 0x%x\n",
1385      nat->registry_info.Jewel==TRUE?"J":"",
1386      nat->registry_info.MifareUL==TRUE?"UL":"",
1387      nat->registry_info.MifareStd==TRUE?"Mi":"",
1388      nat->registry_info.Felica==TRUE?"F":"",
1389      nat->registry_info.ISO14443_4A==TRUE?"4A":"",
1390      nat->registry_info.ISO14443_4B==TRUE?"4B":"",
1391      nat->registry_info.NFC==TRUE?"P2P":"",
1392      nat->registry_info.ISO15693==TRUE?"R":"", ret);
1393
1394    if (modes != 0)
1395    {
1396
1397        if (enable_p2p)
1398        {
1399            nat->p2p_initiator_modes = phNfc_eP2P_ALL;
1400            nat->p2p_target_modes = 0x0E; // All passive except 106, active
1401            nat->discovery_cfg.Duration = 300000; /* in ms */
1402        }
1403        else
1404        {
1405            nat->p2p_initiator_modes = 0;
1406            nat->p2p_target_modes = 0;
1407            nat->discovery_cfg.Duration = 200000; /* in ms */
1408
1409        }
1410
1411        if (reader_mode)
1412        {
1413            nat->discovery_cfg.PollDevInfo.PollCfgInfo.DisableCardEmulation = TRUE;
1414            nat->discovery_cfg.Duration = 200000; /* in ms */
1415        }
1416        else
1417        {
1418            nat->discovery_cfg.PollDevInfo.PollCfgInfo.DisableCardEmulation = FALSE;
1419            nat->discovery_cfg.Duration = 300000; /* in ms */
1420        }
1421        nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443A = (modes & 0x01) != 0;
1422        nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443B = (modes & 0x02) != 0;
1423        nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica212 = (modes & 0x04) != 0;
1424        nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica424 = (modes & 0x04) != 0;
1425        nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso15693 = (modes & 0x08) != 0;
1426    }
1427
1428    nfc_jni_start_discovery_locked(nat, false);
1429clean_and_return:
1430    CONCURRENCY_UNLOCK();
1431}
1432
1433static void com_android_nfc_NfcManager_doResetTimeouts(JNIEnv*, jobject) {
1434    CONCURRENCY_LOCK();
1435    nfc_jni_reset_timeout_values();
1436    CONCURRENCY_UNLOCK();
1437}
1438
1439static void setFelicaTimeout(jint timeout) {
1440   // The Felica timeout is configurable in the PN544 upto a maximum of 255 ms.
1441   // It can be set to 0 to disable the timeout altogether, in which case we
1442   // use the sw watchdog as a fallback.
1443   if (timeout <= 255) {
1444       phLibNfc_SetFelicaTimeout(timeout);
1445   } else {
1446       // Disable hw timeout, use sw watchdog for timeout
1447       phLibNfc_SetFelicaTimeout(0);
1448       phLibNfc_SetHciTimeout(timeout);
1449   }
1450
1451}
1452// Calculates ceiling log2 of value
1453static unsigned int log2(int value) {
1454    unsigned int ret = 0;
1455    bool isPowerOf2 = ((value & (value - 1)) == 0);
1456    while ( (value >> ret) > 1 ) ret++;
1457    if (!isPowerOf2) ret++;
1458    return ret;
1459}
1460
1461// The Iso/Mifare Xchg timeout in PN544 is a non-linear function over X
1462// spanning 0 - 4.9s: timeout in seconds = (256 * 16 / 13560000) * 2 ^ X
1463//
1464// We keep the constant part of the formula in a static; note the factor
1465// 1000 off, which is due to the fact that the formula calculates seconds,
1466// but this method gets milliseconds as an argument.
1467static double nxp_nfc_timeout_factor = (256 * 16) / 13560.0;
1468
1469static int calcTimeout(int timeout_in_ms) {
1470   // timeout = (256 * 16 / 13560000) * 2 ^ X
1471   // First find the first X for which timeout > requested timeout
1472   return (log2(ceil(((double) timeout_in_ms) / nxp_nfc_timeout_factor)));
1473}
1474
1475static void setIsoDepTimeout(jint timeout) {
1476   if (timeout <= 4900) {
1477       int value = calcTimeout(timeout);
1478       // Then re-compute the actual timeout based on X
1479       double actual_timeout = nxp_nfc_timeout_factor * (1 << value);
1480       // Set the sw watchdog a bit longer (The PN544 timeout is very accurate,
1481       // but it will take some time to get back through the sw layers.
1482       // 500 ms should be enough).
1483       phLibNfc_SetHciTimeout(ceil(actual_timeout + 500));
1484       value |= 0x10; // bit 4 to enable timeout
1485       phLibNfc_SetIsoXchgTimeout(value);
1486   }
1487   else {
1488       // Also note that if we desire a timeout > 4.9s, the Iso Xchg timeout
1489       // must be disabled completely, to prevent the PN544 from aborting
1490       // the transaction. We reuse the HCI sw watchdog to catch the timeout
1491       // in that case.
1492       phLibNfc_SetIsoXchgTimeout(0x00);
1493       phLibNfc_SetHciTimeout(timeout);
1494   }
1495}
1496
1497static void setNfcATimeout(jint timeout) {
1498   if (timeout <= 4900) {
1499       int value = calcTimeout(timeout);
1500       phLibNfc_SetMifareRawTimeout(value);
1501   }
1502   else {
1503       // Disable mifare raw timeout, use HCI sw watchdog instead
1504       phLibNfc_SetMifareRawTimeout(0x00);
1505       phLibNfc_SetHciTimeout(timeout);
1506   }
1507}
1508
1509static bool com_android_nfc_NfcManager_doSetTimeout(JNIEnv*, jobject,
1510        jint tech, jint timeout) {
1511    bool success = false;
1512    CONCURRENCY_LOCK();
1513    if (timeout <= 0) {
1514        ALOGE("Timeout must be positive.");
1515        success = false;
1516    } else {
1517        switch (tech) {
1518            case TARGET_TYPE_MIFARE_CLASSIC:
1519            case TARGET_TYPE_MIFARE_UL:
1520                // Intentional fall-through, Mifare UL, Classic
1521                // transceive just uses raw 3A frames
1522            case TARGET_TYPE_ISO14443_3A:
1523                setNfcATimeout(timeout);
1524                success = true;
1525                break;
1526            case TARGET_TYPE_ISO14443_4:
1527                setIsoDepTimeout(timeout);
1528                success = true;
1529                break;
1530            case TARGET_TYPE_FELICA:
1531                setFelicaTimeout(timeout);
1532                success = true;
1533                break;
1534            default:
1535                ALOGW("doSetTimeout: Timeout not supported for tech %d", tech);
1536                success = false;
1537        }
1538    }
1539    CONCURRENCY_UNLOCK();
1540    return success;
1541}
1542
1543static jint com_android_nfc_NfcManager_doGetTimeout(JNIEnv*, jobject,
1544        jint tech) {
1545    int timeout = -1;
1546    CONCURRENCY_LOCK();
1547    switch (tech) {
1548        case TARGET_TYPE_MIFARE_CLASSIC:
1549        case TARGET_TYPE_MIFARE_UL:
1550            // Intentional fall-through, Mifare UL, Classic
1551            // transceive just uses raw 3A frames
1552        case TARGET_TYPE_ISO14443_3A:
1553            timeout = phLibNfc_GetMifareRawTimeout();
1554            if (timeout == 0) {
1555                timeout = phLibNfc_GetHciTimeout();
1556            } else {
1557                // Timeout returned from libnfc needs conversion to ms
1558                timeout = (nxp_nfc_timeout_factor * (1 << timeout));
1559            }
1560            break;
1561        case TARGET_TYPE_ISO14443_4:
1562            timeout = phLibNfc_GetIsoXchgTimeout() & 0x0F; // lower 4 bits only
1563            if (timeout == 0) {
1564                timeout = phLibNfc_GetHciTimeout();
1565            } else {
1566                // Timeout returned from libnfc needs conversion to ms
1567                timeout = (nxp_nfc_timeout_factor * (1 << timeout));
1568            }
1569            break;
1570        case TARGET_TYPE_FELICA:
1571            timeout = phLibNfc_GetFelicaTimeout();
1572            if (timeout == 0) {
1573                timeout = phLibNfc_GetHciTimeout();
1574            } else {
1575                // Felica timeout already in ms
1576            }
1577            break;
1578        default:
1579            ALOGW("doGetTimeout: Timeout not supported for tech %d", tech);
1580            break;
1581    }
1582    CONCURRENCY_UNLOCK();
1583    return timeout;
1584}
1585
1586
1587static jboolean com_android_nfc_NfcManager_init_native_struc(JNIEnv *e, jobject o)
1588{
1589   NFCSTATUS status;
1590   struct nfc_jni_native_data *nat = NULL;
1591   jclass cls;
1592   jobject obj;
1593   jfieldID f;
1594
1595   TRACE("******  Init Native Structure ******");
1596
1597   /* Initialize native structure */
1598   nat = (nfc_jni_native_data*)malloc(sizeof(struct nfc_jni_native_data));
1599   if(nat == NULL)
1600   {
1601      ALOGD("malloc of nfc_jni_native_data failed");
1602      return FALSE;
1603   }
1604   memset(nat, 0, sizeof(*nat));
1605   e->GetJavaVM(&(nat->vm));
1606   nat->env_version = e->GetVersion();
1607   nat->manager = e->NewGlobalRef(o);
1608
1609   cls = e->GetObjectClass(o);
1610   f = e->GetFieldID(cls, "mNative", "J");
1611   e->SetLongField(o, f, (jlong)nat);
1612
1613   /* Initialize native cached references */
1614   cached_NfcManager_notifyNdefMessageListeners = e->GetMethodID(cls,
1615      "notifyNdefMessageListeners","(Lcom/android/nfc/dhimpl/NativeNfcTag;)V");
1616
1617   cached_NfcManager_notifyLlcpLinkActivation = e->GetMethodID(cls,
1618      "notifyLlcpLinkActivation","(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V");
1619
1620   cached_NfcManager_notifyLlcpLinkDeactivated = e->GetMethodID(cls,
1621      "notifyLlcpLinkDeactivated","(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V");
1622
1623   cached_NfcManager_notifyRfFieldActivated = e->GetMethodID(cls,
1624      "notifyRfFieldActivated", "()V");
1625
1626   cached_NfcManager_notifyRfFieldDeactivated = e->GetMethodID(cls,
1627      "notifyRfFieldDeactivated", "()V");
1628
1629   if(nfc_jni_cache_object(e,"com/android/nfc/dhimpl/NativeNfcTag",&(nat->cached_NfcTag)) == -1)
1630   {
1631      ALOGD("Native Structure initialization failed");
1632      return FALSE;
1633   }
1634
1635   if(nfc_jni_cache_object(e,"com/android/nfc/dhimpl/NativeP2pDevice",&(nat->cached_P2pDevice)) == -1)
1636   {
1637      ALOGD("Native Structure initialization failed");
1638      return FALSE;
1639   }
1640   TRACE("****** Init Native Structure OK ******");
1641   return TRUE;
1642
1643}
1644
1645/* Init/Deinit method */
1646static jboolean com_android_nfc_NfcManager_initialize(JNIEnv *e, jobject o)
1647{
1648   struct nfc_jni_native_data *nat = NULL;
1649   int init_result = JNI_FALSE;
1650#ifdef TNFC_EMULATOR_ONLY
1651   char value[PROPERTY_VALUE_MAX];
1652#endif
1653   jboolean result;
1654
1655   CONCURRENCY_LOCK();
1656
1657#ifdef TNFC_EMULATOR_ONLY
1658   if (!property_get("ro.kernel.qemu", value, 0))
1659   {
1660      ALOGE("NFC Initialization failed: not running in an emulator\n");
1661      goto clean_and_return;
1662   }
1663#endif
1664
1665   /* Retrieve native structure address */
1666   nat = nfc_jni_get_nat(e, o);
1667
1668   nat->seId = SMX_SECURE_ELEMENT_ID;
1669
1670   nat->lto = 150;  // LLCP_LTO
1671   nat->miu = 128; // LLCP_MIU
1672   // WKS indicates well-known services; 1 << sap for each supported SAP.
1673   // We support Link mgmt (SAP 0), SDP (SAP 1) and SNEP (SAP 4)
1674   nat->wks = 0x13;  // LLCP_WKS
1675   nat->opt = 0;  // LLCP_OPT
1676   nat->p2p_initiator_modes = phNfc_eP2P_ALL;
1677   nat->p2p_target_modes = 0x0E; // All passive except 106, active
1678   nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443A = TRUE;
1679   nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso14443B = TRUE;
1680   nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica212 = TRUE;
1681   nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableFelica424 = TRUE;
1682   nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableIso15693 = TRUE;
1683   nat->discovery_cfg.PollDevInfo.PollCfgInfo.EnableNfcActive = TRUE;
1684   nat->discovery_cfg.PollDevInfo.PollCfgInfo.DisableCardEmulation = FALSE;
1685
1686   nat->registry_info.MifareUL = TRUE;
1687   nat->registry_info.MifareStd = TRUE;
1688   nat->registry_info.ISO14443_4A = TRUE;
1689   nat->registry_info.ISO14443_4B = TRUE;
1690   nat->registry_info.Jewel = TRUE;
1691   nat->registry_info.Felica = TRUE;
1692   nat->registry_info.NFC = TRUE;
1693   nat->registry_info.ISO15693 = TRUE;
1694
1695   exported_nat = nat;
1696
1697   /* Perform the initialization */
1698   init_result = nfc_jni_initialize(nat);
1699
1700clean_and_return:
1701   CONCURRENCY_UNLOCK();
1702
1703   /* Convert the result and return */
1704   return (init_result==TRUE)?JNI_TRUE:JNI_FALSE;
1705}
1706
1707static jboolean com_android_nfc_NfcManager_deinitialize(JNIEnv *e, jobject o)
1708{
1709   struct timespec ts;
1710   NFCSTATUS status;
1711   int result = JNI_FALSE;
1712   struct nfc_jni_native_data *nat;
1713   int bStackReset = FALSE;
1714   struct nfc_jni_callback_data cb_data;
1715
1716   CONCURRENCY_LOCK();
1717
1718   /* Retrieve native structure address */
1719   nat = nfc_jni_get_nat(e, o);
1720
1721   /* Clear previous configuration */
1722   memset(&nat->discovery_cfg, 0, sizeof(phLibNfc_sADD_Cfg_t));
1723   memset(&nat->registry_info, 0, sizeof(phLibNfc_Registry_Info_t));
1724
1725   /* Create the local semaphore */
1726   if (nfc_cb_data_init(&cb_data, NULL))
1727   {
1728      TRACE("phLibNfc_Mgt_DeInitialize()");
1729      REENTRANCE_LOCK();
1730      status = phLibNfc_Mgt_DeInitialize(gHWRef, nfc_jni_deinit_callback, (void *)&cb_data);
1731      REENTRANCE_UNLOCK();
1732      if (status == NFCSTATUS_PENDING)
1733      {
1734         TRACE("phLibNfc_Mgt_DeInitialize() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
1735
1736         clock_gettime(CLOCK_REALTIME, &ts);
1737         ts.tv_sec += 5;
1738
1739         /* Wait for callback response */
1740         if(sem_timedwait(&cb_data.sem, &ts) == -1)
1741         {
1742            ALOGW("Operation timed out");
1743            bStackReset = TRUE;
1744         }
1745
1746         if(cb_data.status != NFCSTATUS_SUCCESS)
1747         {
1748            ALOGE("Failed to deinit the stack");
1749            bStackReset = TRUE;
1750         }
1751      }
1752      else
1753      {
1754         TRACE("phLibNfc_Mgt_DeInitialize() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
1755         bStackReset = TRUE;
1756      }
1757      nfc_cb_data_deinit(&cb_data);
1758   }
1759   else
1760   {
1761       ALOGE("Failed to create semaphore (errno=0x%08x)", errno);
1762       bStackReset = TRUE;
1763   }
1764
1765   kill_client(nat);
1766
1767   if(bStackReset == TRUE)
1768   {
1769      /* Complete deinit. failed, try hard restart of NFC */
1770      ALOGW("Reseting stack...");
1771      emergency_recovery(nat);
1772   }
1773
1774   result = nfc_jni_unconfigure_driver(nat);
1775
1776   TRACE("NFC Deinitialized");
1777
1778   CONCURRENCY_UNLOCK();
1779
1780   return TRUE;
1781}
1782
1783/* Llcp methods */
1784
1785static jboolean com_android_nfc_NfcManager_doCheckLlcp(JNIEnv *e, jobject o)
1786{
1787   NFCSTATUS ret;
1788   bool freeData = false;
1789   jboolean result = JNI_FALSE;
1790   struct nfc_jni_native_data *nat;
1791   struct nfc_jni_callback_data  *cb_data;
1792
1793
1794   CONCURRENCY_LOCK();
1795
1796   /* Memory allocation for cb_data
1797    * This is on the heap because it is used by libnfc
1798    * even after this call has succesfully finished. It is only freed
1799    * upon link closure in nfc_jni_llcp_linkStatus_callback.
1800    */
1801   cb_data = (struct nfc_jni_callback_data*) malloc (sizeof(nfc_jni_callback_data));
1802
1803   /* Retrieve native structure address */
1804   nat = nfc_jni_get_nat(e, o);
1805
1806   /* Create the local semaphore */
1807   if (!nfc_cb_data_init(cb_data, (void*)nat))
1808   {
1809      goto clean_and_return;
1810   }
1811
1812   /* Check LLCP compliancy */
1813   TRACE("phLibNfc_Llcp_CheckLlcp(hLlcpHandle=0x%08x)", hLlcpHandle);
1814   REENTRANCE_LOCK();
1815   ret = phLibNfc_Llcp_CheckLlcp(hLlcpHandle,
1816                                 nfc_jni_checkLlcp_callback,
1817                                 nfc_jni_llcp_linkStatus_callback,
1818                                 (void*)cb_data);
1819   REENTRANCE_UNLOCK();
1820   /* In case of a NFCIP return NFCSTATUS_SUCCESS and in case of an another protocol
1821    * NFCSTATUS_PENDING. In this case NFCSTATUS_SUCCESS will also cause the callback. */
1822   if(ret != NFCSTATUS_PENDING && ret != NFCSTATUS_SUCCESS)
1823   {
1824      ALOGE("phLibNfc_Llcp_CheckLlcp() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
1825      freeData = true;
1826      goto clean_and_return;
1827   }
1828   TRACE("phLibNfc_Llcp_CheckLlcp() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
1829
1830   /* Wait for callback response */
1831   if(sem_wait(&cb_data->sem))
1832   {
1833      ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
1834      goto clean_and_return;
1835   }
1836
1837   if(cb_data->status == NFCSTATUS_SUCCESS)
1838   {
1839      result = JNI_TRUE;
1840   }
1841
1842clean_and_return:
1843   nfc_cb_data_deinit(cb_data);
1844   if (freeData) {
1845       free(cb_data);
1846   }
1847   CONCURRENCY_UNLOCK();
1848   return result;
1849}
1850
1851static jboolean com_android_nfc_NfcManager_doActivateLlcp(JNIEnv*, jobject)
1852{
1853   NFCSTATUS ret;
1854   TRACE("phLibNfc_Llcp_Activate(hRemoteDevice=0x%08x)", hLlcpHandle);
1855   REENTRANCE_LOCK();
1856   ret = phLibNfc_Llcp_Activate(hLlcpHandle);
1857   REENTRANCE_UNLOCK();
1858   if(ret == NFCSTATUS_SUCCESS)
1859   {
1860      TRACE("phLibNfc_Llcp_Activate() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
1861      return JNI_TRUE;
1862   }
1863   else
1864   {
1865      ALOGE("phLibNfc_Llcp_Activate() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
1866      return JNI_FALSE;
1867   }
1868}
1869
1870
1871
1872static jobject com_android_nfc_NfcManager_doCreateLlcpConnectionlessSocket(JNIEnv *e, jobject o,
1873        jint nSap, jstring sn)
1874{
1875   NFCSTATUS ret;
1876   jobject connectionlessSocket = NULL;
1877   phLibNfc_Handle hLlcpSocket;
1878   struct nfc_jni_native_data *nat;
1879   phNfc_sData_t sWorkingBuffer = {NULL, 0};
1880   phNfc_sData_t serviceName = {NULL, 0};
1881   phLibNfc_Llcp_sLinkParameters_t sParams;
1882   jclass clsNativeConnectionlessSocket;
1883   jfieldID f;
1884
1885   /* Retrieve native structure address */
1886   nat = nfc_jni_get_nat(e, o);
1887
1888   /* Allocate Working buffer length */
1889   phLibNfc_Llcp_GetLocalInfo(hLlcpHandle, &sParams);
1890   sWorkingBuffer.length = sParams.miu + 1; // extra byte for SAP
1891   sWorkingBuffer.buffer = (uint8_t*)malloc(sWorkingBuffer.length);
1892
1893   /* Create socket */
1894   TRACE("phLibNfc_Llcp_Socket(eType=phFriNfc_LlcpTransport_eConnectionLess, ...)");
1895   REENTRANCE_LOCK();
1896   ret = phLibNfc_Llcp_Socket(phFriNfc_LlcpTransport_eConnectionLess,
1897                              NULL,
1898                              &sWorkingBuffer,
1899                              &hLlcpSocket,
1900                              nfc_jni_llcp_transport_socket_err_callback,
1901                              (void*)nat);
1902   REENTRANCE_UNLOCK();
1903
1904   if(ret != NFCSTATUS_SUCCESS)
1905   {
1906      lastErrorStatus = ret;
1907      ALOGE("phLibNfc_Llcp_Socket() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
1908      goto error;
1909   }
1910   TRACE("phLibNfc_Llcp_Socket() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
1911
1912   /* Service socket */
1913   if (sn == NULL) {
1914       serviceName.buffer = NULL;
1915       serviceName.length = 0;
1916   } else {
1917       serviceName.buffer = (uint8_t*)e->GetStringUTFChars(sn, NULL);
1918       serviceName.length = (uint32_t)e->GetStringUTFLength(sn);
1919   }
1920
1921   /* Bind socket */
1922   TRACE("phLibNfc_Llcp_Bind(hSocket=0x%08x, nSap=0x%02x)", hLlcpSocket, nSap);
1923   REENTRANCE_LOCK();
1924   ret = phLibNfc_Llcp_Bind(hLlcpSocket,nSap, &serviceName);
1925   REENTRANCE_UNLOCK();
1926   if(ret != NFCSTATUS_SUCCESS)
1927   {
1928      lastErrorStatus = ret;
1929      ALOGE("phLibNfc_Llcp_Bind() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
1930      /* Close socket created */
1931      REENTRANCE_LOCK();
1932      ret = phLibNfc_Llcp_Close(hLlcpSocket);
1933      REENTRANCE_UNLOCK();
1934      goto error;
1935   }
1936   TRACE("phLibNfc_Llcp_Bind() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
1937
1938
1939   /* Create new NativeLlcpConnectionlessSocket object */
1940   if(nfc_jni_cache_object(e,"com/android/nfc/dhimpl/NativeLlcpConnectionlessSocket",&(connectionlessSocket)) == -1)
1941   {
1942      goto error;
1943   }
1944
1945   /* Get NativeConnectionless class object */
1946   clsNativeConnectionlessSocket = e->GetObjectClass(connectionlessSocket);
1947   if(e->ExceptionCheck())
1948   {
1949      goto error;
1950   }
1951
1952   /* Set socket handle */
1953   f = e->GetFieldID(clsNativeConnectionlessSocket, "mHandle", "I");
1954   e->SetIntField(connectionlessSocket, f,(jint)hLlcpSocket);
1955   TRACE("Connectionless socket Handle = %02x\n",hLlcpSocket);
1956
1957   /* Set the miu link of the connectionless socket */
1958   f = e->GetFieldID(clsNativeConnectionlessSocket, "mLinkMiu", "I");
1959   e->SetIntField(connectionlessSocket, f,(jint)PHFRINFC_LLCP_MIU_DEFAULT);
1960   TRACE("Connectionless socket Link MIU = %d\n",PHFRINFC_LLCP_MIU_DEFAULT);
1961
1962   /* Set socket SAP */
1963   f = e->GetFieldID(clsNativeConnectionlessSocket, "mSap", "I");
1964   e->SetIntField(connectionlessSocket, f,(jint)nSap);
1965   TRACE("Connectionless socket SAP = %d\n",nSap);
1966
1967   return connectionlessSocket;
1968error:
1969   if (serviceName.buffer != NULL) {
1970      e->ReleaseStringUTFChars(sn, (const char *)serviceName.buffer);
1971   }
1972
1973   if (sWorkingBuffer.buffer != NULL) {
1974       free(sWorkingBuffer.buffer);
1975   }
1976
1977   return NULL;
1978}
1979
1980static jobject com_android_nfc_NfcManager_doCreateLlcpServiceSocket(JNIEnv *e, jobject o, jint nSap, jstring sn, jint miu, jint rw, jint linearBufferLength)
1981{
1982   NFCSTATUS ret;
1983   phLibNfc_Handle hLlcpSocket;
1984   phLibNfc_Llcp_sSocketOptions_t sOptions;
1985   phNfc_sData_t sWorkingBuffer;
1986   phNfc_sData_t serviceName;
1987   struct nfc_jni_native_data *nat;
1988   jobject serviceSocket = NULL;
1989   jclass clsNativeLlcpServiceSocket;
1990   jfieldID f;
1991
1992   /* Retrieve native structure address */
1993   nat = nfc_jni_get_nat(e, o);
1994
1995   /* Set Connection Oriented socket options */
1996   sOptions.miu = miu;
1997   sOptions.rw  = rw;
1998
1999   /* Allocate Working buffer length */
2000   sWorkingBuffer.length = (miu*rw)+ miu + linearBufferLength;
2001   sWorkingBuffer.buffer = (uint8_t*)malloc(sWorkingBuffer.length);
2002
2003
2004   /* Create socket */
2005   TRACE("phLibNfc_Llcp_Socket(hRemoteDevice=0x%08x, eType=phFriNfc_LlcpTransport_eConnectionOriented, ...)", hLlcpHandle);
2006   REENTRANCE_LOCK();
2007   ret = phLibNfc_Llcp_Socket(phFriNfc_LlcpTransport_eConnectionOriented,
2008                              &sOptions,
2009                              &sWorkingBuffer,
2010                              &hLlcpSocket,
2011                              nfc_jni_llcp_transport_socket_err_callback,
2012                              (void*)nat);
2013   REENTRANCE_UNLOCK();
2014
2015   if(ret != NFCSTATUS_SUCCESS)
2016   {
2017      ALOGE("phLibNfc_Llcp_Socket() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2018      lastErrorStatus = ret;
2019      goto error;
2020   }
2021   TRACE("phLibNfc_Llcp_Socket() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2022
2023   /* Service socket */
2024   if (sn == NULL) {
2025       serviceName.buffer = NULL;
2026       serviceName.length = 0;
2027   } else {
2028       serviceName.buffer = (uint8_t*)e->GetStringUTFChars(sn, NULL);
2029       serviceName.length = (uint32_t)e->GetStringUTFLength(sn);
2030   }
2031
2032   /* Bind socket */
2033   TRACE("phLibNfc_Llcp_Bind(hSocket=0x%08x, nSap=0x%02x)", hLlcpSocket, nSap);
2034   REENTRANCE_LOCK();
2035   ret = phLibNfc_Llcp_Bind(hLlcpSocket,nSap, &serviceName);
2036   REENTRANCE_UNLOCK();
2037   if(ret != NFCSTATUS_SUCCESS)
2038   {
2039      lastErrorStatus = ret;
2040      ALOGE("phLibNfc_Llcp_Bind() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2041      /* Close socket created */
2042      ret = phLibNfc_Llcp_Close(hLlcpSocket);
2043      goto error;
2044   }
2045   TRACE("phLibNfc_Llcp_Bind() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2046
2047   TRACE("phLibNfc_Llcp_Listen(hSocket=0x%08x, ...)", hLlcpSocket);
2048   REENTRANCE_LOCK();
2049   ret = phLibNfc_Llcp_Listen( hLlcpSocket,
2050                               nfc_jni_llcp_transport_listen_socket_callback,
2051                               (void*)hLlcpSocket);
2052   REENTRANCE_UNLOCK();
2053
2054   if(ret != NFCSTATUS_SUCCESS)
2055   {
2056      ALOGE("phLibNfc_Llcp_Listen() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2057      lastErrorStatus = ret;
2058      /* Close created socket */
2059      REENTRANCE_LOCK();
2060      ret = phLibNfc_Llcp_Close(hLlcpSocket);
2061      REENTRANCE_UNLOCK();
2062      goto error;
2063   }
2064   TRACE("phLibNfc_Llcp_Listen() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2065
2066   /* Create new NativeLlcpServiceSocket object */
2067   if(nfc_jni_cache_object(e,"com/android/nfc/dhimpl/NativeLlcpServiceSocket",&(serviceSocket)) == -1)
2068   {
2069      ALOGE("Llcp Socket object creation error");
2070      goto error;
2071   }
2072
2073   /* Get NativeLlcpServiceSocket class object */
2074   clsNativeLlcpServiceSocket = e->GetObjectClass(serviceSocket);
2075   if(e->ExceptionCheck())
2076   {
2077      ALOGE("Llcp Socket get object class error");
2078      goto error;
2079   }
2080
2081   /* Set socket handle */
2082   f = e->GetFieldID(clsNativeLlcpServiceSocket, "mHandle", "I");
2083   e->SetIntField(serviceSocket, f,(jint)hLlcpSocket);
2084   TRACE("Service socket Handle = %02x\n",hLlcpSocket);
2085
2086   /* Set socket linear buffer length */
2087   f = e->GetFieldID(clsNativeLlcpServiceSocket, "mLocalLinearBufferLength", "I");
2088   e->SetIntField(serviceSocket, f,(jint)linearBufferLength);
2089   TRACE("Service socket Linear buffer length = %02x\n",linearBufferLength);
2090
2091   /* Set socket MIU */
2092   f = e->GetFieldID(clsNativeLlcpServiceSocket, "mLocalMiu", "I");
2093   e->SetIntField(serviceSocket, f,(jint)miu);
2094   TRACE("Service socket MIU = %d\n",miu);
2095
2096   /* Set socket RW */
2097   f = e->GetFieldID(clsNativeLlcpServiceSocket, "mLocalRw", "I");
2098   e->SetIntField(serviceSocket, f,(jint)rw);
2099   TRACE("Service socket RW = %d\n",rw);
2100
2101   return serviceSocket;
2102error:
2103   if (serviceName.buffer != NULL) {
2104      e->ReleaseStringUTFChars(sn, (const char *)serviceName.buffer);
2105   }
2106   return NULL;
2107}
2108
2109static jobject com_android_nfc_NfcManager_doCreateLlcpSocket(JNIEnv *e, jobject o, jint nSap, jint miu, jint rw, jint linearBufferLength)
2110{
2111   jobject clientSocket = NULL;
2112   NFCSTATUS ret;
2113   phLibNfc_Handle hLlcpSocket;
2114   phLibNfc_Llcp_sSocketOptions_t sOptions;
2115   phNfc_sData_t sWorkingBuffer;
2116   struct nfc_jni_native_data *nat;
2117   jclass clsNativeLlcpSocket;
2118   jfieldID f;
2119
2120   /* Retrieve native structure address */
2121   nat = nfc_jni_get_nat(e, o);
2122
2123   /* Set Connection Oriented socket options */
2124   sOptions.miu = miu;
2125   sOptions.rw  = rw;
2126
2127   /* Allocate Working buffer length */
2128   sWorkingBuffer.length = (miu*rw)+ miu + linearBufferLength;
2129   sWorkingBuffer.buffer = (uint8_t*)malloc(sWorkingBuffer.length);
2130
2131   /* Create socket */
2132   TRACE("phLibNfc_Llcp_Socket(eType=phFriNfc_LlcpTransport_eConnectionOriented, ...)");
2133   REENTRANCE_LOCK();
2134   ret = phLibNfc_Llcp_Socket(phFriNfc_LlcpTransport_eConnectionOriented,
2135                              &sOptions,
2136                              &sWorkingBuffer,
2137                              &hLlcpSocket,
2138                              nfc_jni_llcp_transport_socket_err_callback,
2139                              (void*)nat);
2140   REENTRANCE_UNLOCK();
2141
2142   if(ret != NFCSTATUS_SUCCESS)
2143   {
2144      ALOGE("phLibNfc_Llcp_Socket() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2145      lastErrorStatus = ret;
2146      return NULL;
2147   }
2148   TRACE("phLibNfc_Llcp_Socket() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2149
2150   /* Create new NativeLlcpSocket object */
2151   if(nfc_jni_cache_object(e,"com/android/nfc/dhimpl/NativeLlcpSocket",&(clientSocket)) == -1)
2152   {
2153      ALOGE("Llcp socket object creation error");
2154      return NULL;
2155   }
2156
2157   /* Get NativeConnectionless class object */
2158   clsNativeLlcpSocket = e->GetObjectClass(clientSocket);
2159   if(e->ExceptionCheck())
2160   {
2161      ALOGE("Get class object error");
2162      return NULL;
2163   }
2164
2165   /* Test if an SAP number is present */
2166   if(nSap != 0)
2167   {
2168      /* Bind socket */
2169      TRACE("phLibNfc_Llcp_Bind(hSocket=0x%08x, nSap=0x%02x)", hLlcpSocket, nSap);
2170      REENTRANCE_LOCK();
2171      ret = phLibNfc_Llcp_Bind(hLlcpSocket,nSap, NULL);
2172      REENTRANCE_UNLOCK();
2173      if(ret != NFCSTATUS_SUCCESS)
2174      {
2175         lastErrorStatus = ret;
2176         ALOGE("phLibNfc_Llcp_Bind() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2177         /* Close socket created */
2178         REENTRANCE_LOCK();
2179         ret = phLibNfc_Llcp_Close(hLlcpSocket);
2180         REENTRANCE_UNLOCK();
2181         return NULL;
2182      }
2183      TRACE("phLibNfc_Llcp_Bind() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
2184
2185      /* Set socket SAP */
2186      f = e->GetFieldID(clsNativeLlcpSocket, "mSap", "I");
2187      e->SetIntField(clientSocket, f,(jint)nSap);
2188      TRACE("socket SAP = %d\n",nSap);
2189   }
2190
2191   /* Set socket handle */
2192   f = e->GetFieldID(clsNativeLlcpSocket, "mHandle", "I");
2193   e->SetIntField(clientSocket, f,(jint)hLlcpSocket);
2194   TRACE("socket Handle = %02x\n",hLlcpSocket);
2195
2196   /* Set socket MIU */
2197   f = e->GetFieldID(clsNativeLlcpSocket, "mLocalMiu", "I");
2198   e->SetIntField(clientSocket, f,(jint)miu);
2199   TRACE("socket MIU = %d\n",miu);
2200
2201   /* Set socket RW */
2202   f = e->GetFieldID(clsNativeLlcpSocket, "mLocalRw", "I");
2203   e->SetIntField(clientSocket, f,(jint)rw);
2204   TRACE("socket RW = %d\n",rw);
2205
2206
2207   return clientSocket;
2208}
2209
2210static jint com_android_nfc_NfcManager_doGetLastError(JNIEnv*, jobject)
2211{
2212   TRACE("Last Error Status = 0x%02x",lastErrorStatus);
2213
2214   if(lastErrorStatus == NFCSTATUS_BUFFER_TOO_SMALL)
2215   {
2216      return ERROR_BUFFER_TOO_SMALL;
2217   }
2218   else if(lastErrorStatus == NFCSTATUS_INSUFFICIENT_RESOURCES)
2219   {
2220      return  ERROR_INSUFFICIENT_RESOURCES;
2221   }
2222   else
2223   {
2224      return lastErrorStatus;
2225   }
2226}
2227
2228static void com_android_nfc_NfcManager_doAbort(JNIEnv*, jobject)
2229{
2230    emergency_recovery(NULL);
2231}
2232
2233static void com_android_nfc_NfcManager_doSetP2pInitiatorModes(JNIEnv *e, jobject o,
2234        jint modes)
2235{
2236    ALOGE("Setting init modes to %x", modes);
2237    struct nfc_jni_native_data *nat = NULL;
2238    nat = nfc_jni_get_nat(e, o);
2239    nat->p2p_initiator_modes = modes;
2240}
2241
2242static void com_android_nfc_NfcManager_doSetP2pTargetModes(JNIEnv *e, jobject o,
2243        jint modes)
2244{
2245    ALOGE("Setting target modes to %x", modes);
2246    struct nfc_jni_native_data *nat = NULL;
2247    nat = nfc_jni_get_nat(e, o);
2248    nat->p2p_target_modes = modes;
2249}
2250
2251static bool performDownload(struct nfc_jni_native_data* nat, bool takeLock) {
2252    bool result = FALSE;
2253    int load_result;
2254    bool wasDisabled = FALSE;
2255    uint8_t OutputBuffer[1];
2256    uint8_t InputBuffer[1];
2257    NFCSTATUS status = NFCSTATUS_FAILED;
2258    struct nfc_jni_callback_data cb_data;
2259
2260    /* Create the local semaphore */
2261    if (!nfc_cb_data_init(&cb_data, NULL))
2262    {
2263       result = FALSE;
2264       goto clean_and_return;
2265    }
2266
2267    if (takeLock)
2268    {
2269        CONCURRENCY_LOCK();
2270    }
2271
2272    /* Initialize Driver */
2273    if(!driverConfigured)
2274    {
2275        result = nfc_jni_configure_driver(nat);
2276        wasDisabled = TRUE;
2277    }
2278    TRACE("com_android_nfc_NfcManager_doDownload()");
2279
2280    TRACE("Go in Download Mode");
2281    phLibNfc_Download_Mode();
2282
2283    TRACE("Load new Firmware Image");
2284    load_result = phLibNfc_Load_Firmware_Image();
2285    if(load_result != 0)
2286    {
2287        TRACE("Load new Firmware Image - status = %d",load_result);
2288        result = FALSE;
2289        goto clean_and_return;
2290    }
2291
2292    // Download
2293    gInputParam.buffer  = InputBuffer;
2294    gInputParam.length  = 0x01;
2295    gOutputParam.buffer = OutputBuffer;
2296    gOutputParam.length = 0x01;
2297
2298    ALOGD("Download new Firmware");
2299    REENTRANCE_LOCK();
2300    status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_FW_DOWNLOAD, &gInputParam, &gOutputParam, nfc_jni_ioctl_callback, (void *)&cb_data);
2301    REENTRANCE_UNLOCK();
2302    if(status != NFCSTATUS_PENDING)
2303    {
2304        ALOGE("phLibNfc_Mgt_IoCtl() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
2305        result = FALSE;
2306        goto clean_and_return;
2307    }
2308    TRACE("phLibNfc_Mgt_IoCtl() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
2309
2310    /* Wait for callback response */
2311    if(sem_wait(&cb_data.sem))
2312    {
2313       ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
2314       result = FALSE;
2315       goto clean_and_return;
2316    }
2317
2318    /* NOTE: we will get NFCSTATUS_FEATURE_NOT_SUPPORTED when we
2319       try to download an old-style firmware on top of a new-style
2320       firmware.  Hence, this is expected behavior, and not an
2321       error condition. */
2322    if(cb_data.status != NFCSTATUS_SUCCESS && cb_data.status != NFCSTATUS_FEATURE_NOT_SUPPORTED)
2323    {
2324        TRACE("phLibNfc_Mgt_IoCtl() (download) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
2325        result = FALSE;
2326        goto clean_and_return;
2327    }
2328
2329    if(cb_data.status == NFCSTATUS_FEATURE_NOT_SUPPORTED)
2330    {
2331        ALOGW("Old-style firmware not installed on top of new-style firmware. Using existing firmware in the chip.");
2332    }
2333
2334    /*Download is successful*/
2335    result = TRUE;
2336clean_and_return:
2337    TRACE("phLibNfc_HW_Reset()");
2338    phLibNfc_HW_Reset();
2339    /* Deinitialize Driver */
2340    if(wasDisabled)
2341    {
2342        result = nfc_jni_unconfigure_driver(nat);
2343    }
2344    if (takeLock)
2345    {
2346        CONCURRENCY_UNLOCK();
2347    }
2348    nfc_cb_data_deinit(&cb_data);
2349    return result;
2350}
2351
2352static jboolean com_android_nfc_NfcManager_doDownload(JNIEnv *e, jobject o)
2353{
2354    struct nfc_jni_native_data *nat = NULL;
2355    nat = nfc_jni_get_nat(e, o);
2356    return performDownload(nat, true);
2357}
2358
2359static jstring com_android_nfc_NfcManager_doDump(JNIEnv *e, jobject)
2360{
2361    char buffer[100];
2362    snprintf(buffer, sizeof(buffer), "libnfc llc error_count=%u", libnfc_llc_error_count);
2363    return e->NewStringUTF(buffer);
2364}
2365
2366/*
2367 * JNI registration.
2368 */
2369static JNINativeMethod gMethods[] =
2370{
2371   {"doDownload", "()Z",
2372        (void *)com_android_nfc_NfcManager_doDownload},
2373
2374   {"initializeNativeStructure", "()Z",
2375      (void *)com_android_nfc_NfcManager_init_native_struc},
2376
2377   {"doInitialize", "()Z",
2378      (void *)com_android_nfc_NfcManager_initialize},
2379
2380   {"doDeinitialize", "()Z",
2381      (void *)com_android_nfc_NfcManager_deinitialize},
2382
2383   {"doEnableDiscovery", "(IZZZZ)V",
2384      (void *)com_android_nfc_NfcManager_enableDiscovery},
2385
2386   {"doCheckLlcp", "()Z",
2387      (void *)com_android_nfc_NfcManager_doCheckLlcp},
2388
2389   {"doActivateLlcp", "()Z",
2390      (void *)com_android_nfc_NfcManager_doActivateLlcp},
2391
2392   {"doCreateLlcpConnectionlessSocket", "(ILjava/lang/String;)Lcom/android/nfc/dhimpl/NativeLlcpConnectionlessSocket;",
2393      (void *)com_android_nfc_NfcManager_doCreateLlcpConnectionlessSocket},
2394
2395   {"doCreateLlcpServiceSocket", "(ILjava/lang/String;III)Lcom/android/nfc/dhimpl/NativeLlcpServiceSocket;",
2396      (void *)com_android_nfc_NfcManager_doCreateLlcpServiceSocket},
2397
2398   {"doCreateLlcpSocket", "(IIII)Lcom/android/nfc/dhimpl/NativeLlcpSocket;",
2399      (void *)com_android_nfc_NfcManager_doCreateLlcpSocket},
2400
2401   {"doGetLastError", "()I",
2402      (void *)com_android_nfc_NfcManager_doGetLastError},
2403
2404   {"disableDiscovery", "()V",
2405      (void *)com_android_nfc_NfcManager_disableDiscovery},
2406
2407   {"doSetTimeout", "(II)Z",
2408      (void *)com_android_nfc_NfcManager_doSetTimeout},
2409
2410   {"doGetTimeout", "(I)I",
2411      (void *)com_android_nfc_NfcManager_doGetTimeout},
2412
2413   {"doResetTimeouts", "()V",
2414      (void *)com_android_nfc_NfcManager_doResetTimeouts},
2415
2416   {"doAbort", "()V",
2417      (void *)com_android_nfc_NfcManager_doAbort},
2418
2419   {"doSetP2pInitiatorModes","(I)V",
2420      (void *)com_android_nfc_NfcManager_doSetP2pInitiatorModes},
2421
2422   {"doSetP2pTargetModes","(I)V",
2423      (void *)com_android_nfc_NfcManager_doSetP2pTargetModes},
2424
2425   {"doDump", "()Ljava/lang/String;",
2426      (void *)com_android_nfc_NfcManager_doDump},
2427};
2428
2429
2430int register_com_android_nfc_NativeNfcManager(JNIEnv *e)
2431{
2432    nfc_jni_native_monitor_t *nfc_jni_native_monitor;
2433
2434   nfc_jni_native_monitor = nfc_jni_init_monitor();
2435   if(nfc_jni_native_monitor == NULL)
2436   {
2437      ALOGE("NFC Manager cannot recover native monitor %x\n", errno);
2438      return -1;
2439   }
2440
2441   return jniRegisterNativeMethods(e,
2442      "com/android/nfc/dhimpl/NativeNfcManager",
2443      gMethods, NELEM(gMethods));
2444}
2445
2446} /* namespace android */
2447