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