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