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 <semaphore.h>
18
19#include "com_android_nfc.h"
20
21static phNfc_sData_t *com_android_nfc_jni_transceive_buffer;
22static phNfc_sData_t *com_android_nfc_jni_ioctl_buffer;
23static phNfc_sRemoteDevInformation_t* SecureElementInfo;
24static int secureElementHandle;
25extern void                 *gHWRef;
26static int SecureElementTech;
27extern uint8_t device_connected_flag;
28
29namespace android {
30
31static void com_android_nfc_jni_ioctl_callback ( void*            pContext,
32                                            phNfc_sData_t*   Outparam_Cb,
33                                            NFCSTATUS        status)
34{
35    struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
36
37	if (status == NFCSTATUS_SUCCESS )
38	{
39	    LOG_CALLBACK("> IOCTL successful",status);
40	}
41	else
42	{
43	    LOG_CALLBACK("> IOCTL error",status);
44	}
45
46   com_android_nfc_jni_ioctl_buffer = Outparam_Cb;
47   pContextData->status = status;
48   sem_post(&pContextData->sem);
49}
50
51static void com_android_nfc_jni_transceive_callback(void *pContext,
52   phLibNfc_Handle handle, phNfc_sData_t *pResBuffer, NFCSTATUS status)
53{
54   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
55
56   LOG_CALLBACK("com_android_nfc_jni_transceive_callback", status);
57
58   com_android_nfc_jni_transceive_buffer = pResBuffer;
59   pContextData->status = status;
60   sem_post(&pContextData->sem);
61}
62
63
64static void com_android_nfc_jni_connect_callback(void *pContext,
65                                            phLibNfc_Handle hRemoteDev,
66                                            phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo, NFCSTATUS status)
67{
68   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
69
70   LOG_CALLBACK("com_android_nfc_jni_connect_callback", status);
71
72   pContextData->status = status;
73   sem_post(&pContextData->sem);
74}
75
76static void com_android_nfc_jni_disconnect_callback(void *pContext,
77                                               phLibNfc_Handle hRemoteDev,
78                                               NFCSTATUS status)
79{
80   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
81
82   LOG_CALLBACK("com_android_nfc_jni_disconnect_callback", status);
83
84   pContextData->status = status;
85   sem_post(&pContextData->sem);
86}
87
88/* Set Secure Element mode callback*/
89static void com_android_nfc_jni_smartMX_setModeCb (void*            pContext,
90							                                phLibNfc_Handle  hSecureElement,
91                                              NFCSTATUS        status)
92{
93    struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
94
95	if(status==NFCSTATUS_SUCCESS)
96	{
97	    LOG_CALLBACK("SE Set Mode is Successful",status);
98	    TRACE("SE Handle: %lu", hSecureElement);
99	}
100	else
101	{
102	    LOG_CALLBACK("SE Set Mode is failed\n ",status);
103  }
104
105   pContextData->status = status;
106   sem_post(&pContextData->sem);
107}
108
109static void com_android_nfc_jni_open_secure_element_notification_callback(void *pContext,
110                                                                     phLibNfc_RemoteDevList_t *psRemoteDevList,
111                                                                     uint8_t uNofRemoteDev,
112                                                                     NFCSTATUS status)
113{
114   struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
115   NFCSTATUS ret;
116   int i;
117   JNIEnv *e = nfc_get_env();
118
119   if(status == NFCSTATUS_DESELECTED)
120   {
121      LOG_CALLBACK("com_android_nfc_jni_open_secure_element_notification_callback: Target deselected", status);
122   }
123   else
124   {
125      LOG_CALLBACK("com_android_nfc_jni_open_secure_element_notification_callback", status);
126      TRACE("Discovered %d secure elements", uNofRemoteDev);
127
128      if(status == NFCSTATUS_MULTIPLE_PROTOCOLS)
129      {
130         bool foundHandle = false;
131         TRACE("Multiple Protocol supported\n");
132         for (i=0; i<uNofRemoteDev; i++) {
133             // Always open the phNfc_eISO14443_A_PICC protocol
134             TRACE("Protocol %d handle=%x type=%d", i, psRemoteDevList[i].hTargetDev,
135                     psRemoteDevList[i].psRemoteDevInfo->RemDevType);
136             if (psRemoteDevList[i].psRemoteDevInfo->RemDevType == phNfc_eISO14443_A_PICC) {
137                 secureElementHandle = psRemoteDevList[i].hTargetDev;
138                 foundHandle = true;
139             }
140         }
141         if (!foundHandle) {
142             ALOGE("Could not find ISO-DEP secure element");
143             status = NFCSTATUS_FAILED;
144             goto clean_and_return;
145         }
146      }
147      else
148      {
149         secureElementHandle = psRemoteDevList->hTargetDev;
150      }
151
152      TRACE("Secure Element Handle: 0x%08x", secureElementHandle);
153
154      /* Set type name */
155      jintArray techList;
156      nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, NULL, NULL);
157
158      // TODO: Should use the "connected" technology, for now use the first
159      if ((techList != NULL) && e->GetArrayLength(techList) > 0) {
160         e->GetIntArrayRegion(techList, 0, 1, &SecureElementTech);
161         TRACE("Store Secure Element Info\n");
162         SecureElementInfo = psRemoteDevList->psRemoteDevInfo;
163
164         TRACE("Discovered secure element: tech=%d", SecureElementTech);
165      }
166      else {
167         ALOGE("Discovered secure element, but could not resolve tech");
168         status = NFCSTATUS_FAILED;
169      }
170
171      // This thread may not return to the virtual machine for a long time
172      // so make sure to delete the local refernce to the tech list.
173      e->DeleteLocalRef(techList);
174   }
175
176clean_and_return:
177   pContextData->status = status;
178   sem_post(&pContextData->sem);
179}
180
181
182static jint com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection(JNIEnv *e, jobject o)
183{
184   NFCSTATUS ret;
185   int semResult;
186
187   phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE];
188   uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0;
189   phLibNfc_sADD_Cfg_t discovery_cfg;
190   phLibNfc_Registry_Info_t registry_info;
191   phNfc_sData_t        InParam;
192   phNfc_sData_t        OutParam;
193   uint8_t              ExternalRFDetected[3] = {0x00, 0xFC, 0x01};
194   uint8_t              GpioGetValue[3] = {0x00, 0xF8, 0x2B};
195   uint8_t              GpioSetValue[4];
196   uint8_t              gpioValue;
197   uint8_t              Output_Buff[10];
198   uint8_t              reg_value;
199   uint8_t              mask_value;
200   struct nfc_jni_callback_data cb_data;
201   struct nfc_jni_callback_data cb_data_SE_Notification;
202
203   /* Create the local semaphore */
204   if (!nfc_cb_data_init(&cb_data, NULL))
205   {
206      goto clean_and_return;
207   }
208
209   /* Create the local semaphore */
210   if (!nfc_cb_data_init(&cb_data_SE_Notification, NULL))
211   {
212      goto clean_and_return;
213   }
214
215   /* Registery */
216   registry_info.MifareUL = TRUE;
217   registry_info.MifareStd = TRUE;
218   registry_info.ISO14443_4A = TRUE;
219   registry_info.ISO14443_4B = TRUE;
220   registry_info.Jewel = TRUE;
221   registry_info.Felica = TRUE;
222   registry_info.NFC = FALSE;
223
224   CONCURRENCY_LOCK();
225
226   TRACE("Open Secure Element");
227
228   /* Check if NFC device is already connected to a tag or P2P peer */
229   if (device_connected_flag == 1)
230   {
231       ALOGD("Unable to open SE connection, device already connected to a P2P peer or a Tag");
232       goto clean_and_return;
233   }
234
235   /* Test if External RF field is detected */
236   InParam.buffer = ExternalRFDetected;
237   InParam.length = 3;
238   OutParam.buffer = Output_Buff;
239   TRACE("phLibNfc_Mgt_IoCtl()");
240   REENTRANCE_LOCK();
241   ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
242   REENTRANCE_UNLOCK();
243   if(ret!=NFCSTATUS_PENDING)
244   {
245      ALOGE("IOCTL status error");
246      goto clean_and_return;
247   }
248
249   /* Wait for callback response */
250   if(sem_wait(&cb_data.sem))
251   {
252      ALOGE("IOCTL semaphore error");
253      goto clean_and_return;
254   }
255
256   if(cb_data.status != NFCSTATUS_SUCCESS)
257   {
258      ALOGE("READ MEM ERROR");
259      goto clean_and_return;
260   }
261
262   /* Check the value */
263   reg_value = com_android_nfc_jni_ioctl_buffer->buffer[0];
264   mask_value = reg_value & 0x40;
265
266   if(mask_value == 0x40)
267   {
268      // There is an external RF field present, fail the open request
269      ALOGD("Unable to open SE connection, external RF Field detected");
270      goto clean_and_return;
271   }
272
273   /* Get Secure Element List */
274   TRACE("phLibNfc_SE_GetSecureElementList()");
275   ret = phLibNfc_SE_GetSecureElementList( SE_List, &No_SE);
276   if (ret == NFCSTATUS_SUCCESS)
277   {
278      TRACE("\n> Number of Secure Element(s) : %d\n", No_SE);
279      /* Display Secure Element information */
280      for (i = 0; i<No_SE; i++)
281      {
282         if (SE_List[i].eSE_Type == phLibNfc_SE_Type_SmartMX)
283         {
284           TRACE("> SMX detected");
285           TRACE("> Secure Element Handle : %d\n", SE_List[i].hSecureElement);
286           /* save SMARTMX index */
287           SmartMX_detected = 1;
288           SmartMX_index = i;
289         }
290      }
291
292      if(SmartMX_detected)
293      {
294         REENTRANCE_LOCK();
295         TRACE("phLibNfc_RemoteDev_NtfRegister()");
296         ret = phLibNfc_RemoteDev_NtfRegister(&registry_info,
297                 com_android_nfc_jni_open_secure_element_notification_callback,
298                 (void *)&cb_data_SE_Notification);
299         REENTRANCE_UNLOCK();
300         if(ret != NFCSTATUS_SUCCESS)
301         {
302            ALOGE("Register Notification error");
303            goto clean_and_return;
304         }
305
306         /* Set wired mode */
307         REENTRANCE_LOCK();
308         TRACE("phLibNfc_SE_SetMode: Wired mode");
309         ret = phLibNfc_SE_SetMode( SE_List[SmartMX_index].hSecureElement,
310                                     phLibNfc_SE_ActModeWired,
311                                     com_android_nfc_jni_smartMX_setModeCb,
312                                     (void *)&cb_data);
313         REENTRANCE_UNLOCK();
314         if (ret != NFCSTATUS_PENDING )
315         {
316            ALOGE("\n> SE Set SmartMX mode ERROR \n" );
317            goto clean_and_return;
318         }
319
320         /* Wait for callback response */
321         if(sem_wait(&cb_data.sem))
322         {
323            ALOGE("Secure Element opening error");
324            goto clean_and_return;
325         }
326
327         if(cb_data.status != NFCSTATUS_SUCCESS)
328         {
329            ALOGE("SE set mode failed");
330            goto clean_and_return;
331         }
332
333         TRACE("Waiting for notification");
334         /* Wait for callback response */
335         if(sem_wait(&cb_data_SE_Notification.sem))
336         {
337            ALOGE("Secure Element opening error");
338            goto clean_and_return;
339         }
340
341         if(cb_data_SE_Notification.status != NFCSTATUS_SUCCESS &&
342                 cb_data_SE_Notification.status != NFCSTATUS_MULTIPLE_PROTOCOLS)
343         {
344            ALOGE("SE detection failed");
345            goto clean_and_return;
346         }
347         CONCURRENCY_UNLOCK();
348
349         /* Connect Tag */
350         CONCURRENCY_LOCK();
351         TRACE("phLibNfc_RemoteDev_Connect(SMX)");
352         REENTRANCE_LOCK();
353         ret = phLibNfc_RemoteDev_Connect(secureElementHandle, com_android_nfc_jni_connect_callback,(void *)&cb_data);
354         REENTRANCE_UNLOCK();
355         if(ret != NFCSTATUS_PENDING)
356         {
357            ALOGE("phLibNfc_RemoteDev_Connect(SMX) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
358            goto clean_and_return;
359         }
360         TRACE("phLibNfc_RemoteDev_Connect(SMX) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
361
362         /* Wait for callback response */
363         if(sem_wait(&cb_data.sem))
364         {
365             ALOGE("CONNECT semaphore error");
366             goto clean_and_return;
367         }
368
369         /* Connect Status */
370         if(cb_data.status != NFCSTATUS_SUCCESS)
371         {
372            ALOGE("Secure Element connect error");
373            goto clean_and_return;
374         }
375
376         CONCURRENCY_UNLOCK();
377
378         /* Get GPIO information */
379         CONCURRENCY_LOCK();
380         InParam.buffer = GpioGetValue;
381         InParam.length = 3;
382         OutParam.buffer = Output_Buff;
383         TRACE("phLibNfc_Mgt_IoCtl()- GPIO Get Value");
384         REENTRANCE_LOCK();
385         ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
386         REENTRANCE_UNLOCK();
387         if(ret!=NFCSTATUS_PENDING)
388         {
389             ALOGE("IOCTL status error");
390         }
391
392         /* Wait for callback response */
393         if(sem_wait(&cb_data.sem))
394         {
395            ALOGE("IOCTL semaphore error");
396            goto clean_and_return;
397         }
398
399         if(cb_data.status != NFCSTATUS_SUCCESS)
400         {
401            ALOGE("READ MEM ERROR");
402            goto clean_and_return;
403         }
404
405         gpioValue = com_android_nfc_jni_ioctl_buffer->buffer[0];
406         TRACE("GpioValue = Ox%02x",gpioValue);
407
408         /* Set GPIO information */
409         GpioSetValue[0] = 0x00;
410         GpioSetValue[1] = 0xF8;
411         GpioSetValue[2] = 0x2B;
412         GpioSetValue[3] = (gpioValue | 0x40);
413
414         TRACE("GpioValue to be set = Ox%02x",GpioSetValue[3]);
415
416         for(i=0;i<4;i++)
417         {
418             TRACE("0x%02x",GpioSetValue[i]);
419         }
420
421         InParam.buffer = GpioSetValue;
422         InParam.length = 4;
423         OutParam.buffer = Output_Buff;
424         TRACE("phLibNfc_Mgt_IoCtl()- GPIO Set Value");
425         REENTRANCE_LOCK();
426         ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_WRITE,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
427         REENTRANCE_UNLOCK();
428         if(ret!=NFCSTATUS_PENDING)
429         {
430             ALOGE("IOCTL status error");
431             goto clean_and_return;
432         }
433
434         /* Wait for callback response */
435         if(sem_wait(&cb_data.sem))
436         {
437            ALOGE("IOCTL semaphore error");
438            goto clean_and_return;
439         }
440
441         if(cb_data.status != NFCSTATUS_SUCCESS)
442         {
443            ALOGE("READ MEM ERROR");
444            goto clean_and_return;
445         }
446         CONCURRENCY_UNLOCK();
447
448         nfc_cb_data_deinit(&cb_data);
449         nfc_cb_data_deinit(&cb_data_SE_Notification);
450
451         /* Return the Handle of the SecureElement */
452         return secureElementHandle;
453      }
454      else
455      {
456         ALOGE("phLibNfc_SE_GetSecureElementList(): No SMX detected");
457         goto clean_and_return;
458      }
459  }
460  else
461  {
462      ALOGE("phLibNfc_SE_GetSecureElementList(): Error");
463      goto clean_and_return;
464  }
465
466clean_and_return:
467   nfc_cb_data_deinit(&cb_data);
468   nfc_cb_data_deinit(&cb_data_SE_Notification);
469
470   CONCURRENCY_UNLOCK();
471   return 0;
472}
473
474
475static jboolean com_android_nfc_NativeNfcSecureElement_doDisconnect(JNIEnv *e, jobject o, jint handle)
476{
477   jclass cls;
478   jfieldID f;
479   NFCSTATUS status;
480   jboolean result = JNI_FALSE;
481   phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE];
482   uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0;
483   uint32_t SmartMX_Handle;
484   struct nfc_jni_callback_data cb_data;
485   phNfc_sData_t    InParam;
486   phNfc_sData_t    OutParam;
487   uint8_t          Output_Buff[10];
488   uint8_t          GpioGetValue[3] = {0x00, 0xF8, 0x2B};
489   uint8_t          GpioSetValue[4];
490   uint8_t          gpioValue;
491
492   /* Create the local semaphore */
493   if (!nfc_cb_data_init(&cb_data, NULL))
494   {
495      goto clean_and_return;
496   }
497
498   TRACE("Close Secure element function ");
499
500   CONCURRENCY_LOCK();
501   /* Disconnect */
502   TRACE("Disconnecting from SMX (handle = 0x%x)", handle);
503   REENTRANCE_LOCK();
504   status = phLibNfc_RemoteDev_Disconnect(handle,
505                                          NFC_SMARTMX_RELEASE,
506                                          com_android_nfc_jni_disconnect_callback,
507                                          (void *)&cb_data);
508   REENTRANCE_UNLOCK();
509   if(status != NFCSTATUS_PENDING)
510   {
511      ALOGE("phLibNfc_RemoteDev_Disconnect(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
512      goto clean_and_return;
513   }
514   TRACE("phLibNfc_RemoteDev_Disconnect(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
515
516   /* Wait for callback response */
517   if(sem_wait(&cb_data.sem))
518   {
519       goto clean_and_return;
520   }
521
522   /* Disconnect Status */
523   if(cb_data.status != NFCSTATUS_SUCCESS)
524   {
525     ALOGE("\n> Disconnect SE ERROR \n" );
526      goto clean_and_return;
527   }
528   CONCURRENCY_UNLOCK();
529
530   /* Get GPIO information */
531   CONCURRENCY_LOCK();
532   InParam.buffer = GpioGetValue;
533   InParam.length = 3;
534   OutParam.buffer = Output_Buff;
535   TRACE("phLibNfc_Mgt_IoCtl()- GPIO Get Value");
536   REENTRANCE_LOCK();
537   status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
538   REENTRANCE_UNLOCK();
539   if(status!=NFCSTATUS_PENDING)
540   {
541       ALOGE("IOCTL status error");
542       goto clean_and_return;
543   }
544
545   /* Wait for callback response */
546   if(sem_wait(&cb_data.sem))
547   {
548      ALOGE("IOCTL semaphore error");
549      goto clean_and_return;
550   }
551
552   if(cb_data.status != NFCSTATUS_SUCCESS)
553   {
554      ALOGE("READ MEM ERROR");
555      goto clean_and_return;
556   }
557
558   gpioValue = com_android_nfc_jni_ioctl_buffer->buffer[0];
559   TRACE("GpioValue = Ox%02x",gpioValue);
560
561   /* Set GPIO information */
562   GpioSetValue[0] = 0x00;
563   GpioSetValue[1] = 0xF8;
564   GpioSetValue[2] = 0x2B;
565   GpioSetValue[3] = (gpioValue & 0xBF);
566
567   TRACE("GpioValue to be set = Ox%02x",GpioSetValue[3]);
568
569   for(i=0;i<4;i++)
570   {
571       TRACE("0x%02x",GpioSetValue[i]);
572   }
573
574   InParam.buffer = GpioSetValue;
575   InParam.length = 4;
576   OutParam.buffer = Output_Buff;
577   TRACE("phLibNfc_Mgt_IoCtl()- GPIO Set Value");
578   REENTRANCE_LOCK();
579   status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_WRITE,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
580   REENTRANCE_UNLOCK();
581   if(status!=NFCSTATUS_PENDING)
582   {
583       ALOGE("IOCTL status error");
584       goto clean_and_return;
585   }
586
587   /* Wait for callback response */
588   if(sem_wait(&cb_data.sem))
589   {
590      ALOGE("IOCTL semaphore error");
591      goto clean_and_return;
592   }
593
594   if(cb_data.status != NFCSTATUS_SUCCESS)
595   {
596      ALOGE("READ MEM ERROR");
597      goto clean_and_return;
598   }
599
600   result = JNI_TRUE;
601
602clean_and_return:
603   nfc_cb_data_deinit(&cb_data);
604
605   CONCURRENCY_UNLOCK();
606   return result;
607}
608
609static jbyteArray com_android_nfc_NativeNfcSecureElement_doTransceive(JNIEnv *e,
610   jobject o,jint handle, jbyteArray data)
611{
612   uint8_t offset = 0;
613   uint8_t *buf;
614   uint32_t buflen;
615   phLibNfc_sTransceiveInfo_t transceive_info;
616   jbyteArray result = NULL;
617   int res;
618
619   int tech = SecureElementTech;
620   NFCSTATUS status;
621   struct nfc_jni_callback_data cb_data;
622
623   /* Create the local semaphore */
624   if (!nfc_cb_data_init(&cb_data, NULL))
625   {
626      goto clean_and_return;
627   }
628
629   TRACE("Exchange APDU function ");
630
631   CONCURRENCY_LOCK();
632
633   TRACE("Secure Element tech: %d\n", tech);
634
635   buf = (uint8_t *)e->GetByteArrayElements(data, NULL);
636   buflen = (uint32_t)e->GetArrayLength(data);
637
638   /* Prepare transceive info structure */
639   if(tech == TARGET_TYPE_MIFARE_CLASSIC || tech == TARGET_TYPE_MIFARE_UL)
640   {
641      offset = 2;
642      transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0];
643      transceive_info.addr = (uint8_t)buf[1];
644   }
645   else if(tech == TARGET_TYPE_ISO14443_4)
646   {
647      transceive_info.cmd.Iso144434Cmd = phNfc_eIso14443_4_Raw;
648      transceive_info.addr = 0;
649   }
650
651   transceive_info.sSendData.buffer = buf + offset;
652   transceive_info.sSendData.length = buflen - offset;
653   transceive_info.sRecvData.buffer = (uint8_t*)malloc(1024);
654   transceive_info.sRecvData.length = 1024;
655
656   if(transceive_info.sRecvData.buffer == NULL)
657   {
658      goto clean_and_return;
659   }
660
661   TRACE("phLibNfc_RemoteDev_Transceive(SMX)");
662   REENTRANCE_LOCK();
663   status = phLibNfc_RemoteDev_Transceive(handle, &transceive_info,
664		   com_android_nfc_jni_transceive_callback, (void *)&cb_data);
665   REENTRANCE_UNLOCK();
666   if(status != NFCSTATUS_PENDING)
667   {
668      ALOGE("phLibNfc_RemoteDev_Transceive(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
669      goto clean_and_return;
670   }
671   TRACE("phLibNfc_RemoteDev_Transceive(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
672
673   /* Wait for callback response */
674   if(sem_wait(&cb_data.sem))
675   {
676       ALOGE("TRANSCEIVE semaphore error");
677       goto clean_and_return;
678   }
679
680   if(cb_data.status != NFCSTATUS_SUCCESS)
681   {
682      ALOGE("TRANSCEIVE error");
683      goto clean_and_return;
684   }
685
686   /* Copy results back to Java */
687   result = e->NewByteArray(com_android_nfc_jni_transceive_buffer->length);
688   if(result != NULL)
689   {
690      e->SetByteArrayRegion(result, 0,
691    		  com_android_nfc_jni_transceive_buffer->length,
692         (jbyte *)com_android_nfc_jni_transceive_buffer->buffer);
693   }
694
695clean_and_return:
696   nfc_cb_data_deinit(&cb_data);
697
698   if(transceive_info.sRecvData.buffer != NULL)
699   {
700      free(transceive_info.sRecvData.buffer);
701   }
702
703   e->ReleaseByteArrayElements(data,
704      (jbyte *)transceive_info.sSendData.buffer, JNI_ABORT);
705
706   CONCURRENCY_UNLOCK();
707
708   return result;
709}
710
711static jbyteArray com_android_nfc_NativeNfcSecureElement_doGetUid(JNIEnv *e, jobject o, jint handle)
712{
713   TRACE("Get Secure element UID function ");
714   jbyteArray SecureElementUid;
715
716   if(handle == secureElementHandle)
717   {
718      SecureElementUid = e->NewByteArray(SecureElementInfo->RemoteDevInfo.Iso14443A_Info.UidLength);
719      e->SetByteArrayRegion(SecureElementUid, 0, SecureElementInfo->RemoteDevInfo.Iso14443A_Info.UidLength,(jbyte *)SecureElementInfo->RemoteDevInfo.Iso14443A_Info.Uid);
720      return SecureElementUid;
721   }
722   else
723   {
724      return NULL;
725   }
726}
727
728static jintArray com_android_nfc_NativeNfcSecureElement_doGetTechList(JNIEnv *e, jobject o, jint handle)
729{
730   jintArray techList;
731   TRACE("Get Secure element Type function ");
732
733   if(handle == secureElementHandle)
734   {
735      techList = e->NewIntArray(1);
736      e->SetIntArrayRegion(techList, 0, 1, &SecureElementTech);
737      return techList;
738   }
739   else
740   {
741      return NULL;
742   }
743}
744
745
746/*
747 * JNI registration.
748 */
749static JNINativeMethod gMethods[] =
750{
751   {"doNativeOpenSecureElementConnection", "()I",
752      (void *)com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection},
753   {"doNativeDisconnectSecureElementConnection", "(I)Z",
754      (void *)com_android_nfc_NativeNfcSecureElement_doDisconnect},
755   {"doTransceive", "(I[B)[B",
756      (void *)com_android_nfc_NativeNfcSecureElement_doTransceive},
757   {"doGetUid", "(I)[B",
758      (void *)com_android_nfc_NativeNfcSecureElement_doGetUid},
759   {"doGetTechList", "(I)[I",
760      (void *)com_android_nfc_NativeNfcSecureElement_doGetTechList},
761};
762
763int register_com_android_nfc_NativeNfcSecureElement(JNIEnv *e)
764{
765   return jniRegisterNativeMethods(e,
766      "com/android/nfc/dhimpl/NativeNfcSecureElement",
767      gMethods, NELEM(gMethods));
768}
769
770} // namespace android
771