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