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