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