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(®istry_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