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