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