• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 static phNfc_sData_t *com_android_nfc_jni_transceive_buffer;
22 static phNfc_sData_t *com_android_nfc_jni_ioctl_buffer;
23 static phNfc_sRemoteDevInformation_t* SecureElementInfo;
24 static int secureElementHandle;
25 extern void                 *gHWRef;
26 static int SecureElementTech;
27 extern uint8_t device_connected_flag;
28 
29 namespace android {
30 
com_android_nfc_jni_ioctl_callback(void * pContext,phNfc_sData_t * Outparam_Cb,NFCSTATUS status)31 static 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 
com_android_nfc_jni_transceive_callback(void * pContext,phLibNfc_Handle handle,phNfc_sData_t * pResBuffer,NFCSTATUS status)51 static 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 
com_android_nfc_jni_connect_callback(void * pContext,phLibNfc_Handle hRemoteDev,phLibNfc_sRemoteDevInformation_t * psRemoteDevInfo,NFCSTATUS status)64 static 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 
com_android_nfc_jni_disconnect_callback(void * pContext,phLibNfc_Handle hRemoteDev,NFCSTATUS status)76 static 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*/
com_android_nfc_jni_smartMX_setModeCb(void * pContext,phLibNfc_Handle hSecureElement,NFCSTATUS status)89 static 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 
com_android_nfc_jni_open_secure_element_notification_callback(void * pContext,phLibNfc_RemoteDevList_t * psRemoteDevList,uint8_t uNofRemoteDev,NFCSTATUS status)109 static 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 
172 clean_and_return:
173    pContextData->status = status;
174    sem_post(&pContextData->sem);
175 }
176 
177 
com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection(JNIEnv * e,jobject o)178 static 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 
465 clean_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 
com_android_nfc_NativeNfcSecureElement_doDisconnect(JNIEnv * e,jobject o,jint handle)474 static 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 
601 clean_and_return:
602    nfc_cb_data_deinit(&cb_data);
603 
604    CONCURRENCY_UNLOCK();
605    return result;
606 }
607 
com_android_nfc_NativeNfcSecureElement_doTransceive(JNIEnv * e,jobject o,jint handle,jbyteArray data)608 static 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 
694 clean_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 
com_android_nfc_NativeNfcSecureElement_doGetUid(JNIEnv * e,jobject o,jint handle)710 static 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 
com_android_nfc_NativeNfcSecureElement_doGetTechList(JNIEnv * e,jobject o,jint handle)727 static 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  */
744 static 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 
register_com_android_nfc_NativeNfcSecureElement(JNIEnv * e)758 int 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