Home | History | Annotate | Download | only in jni
      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 <errno.h>
     18 #include <malloc.h>
     19 #include <semaphore.h>
     20 
     21 #include "com_android_nfc.h"
     22 
     23 namespace android {
     24 
     25 /*
     26  * Callbacks
     27  */
     28 
     29 static void nfc_jni_receive_callback(void* pContext, uint8_t ssap, NFCSTATUS status)
     30 {
     31    struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
     32    LOG_CALLBACK("nfc_jni_receiveFrom_callback", status);
     33 
     34    if(status == NFCSTATUS_SUCCESS)
     35    {
     36       pCallbackData->pContext = (void*)(uintptr_t)ssap;
     37       TRACE("RECEIVE UI_FRAME FROM SAP %d OK \n", ssap);
     38    }
     39 
     40    /* Report the callback status and wake up the caller */
     41    pCallbackData->status = status;
     42    sem_post(&pCallbackData->sem);
     43 }
     44 
     45 static void nfc_jni_send_callback(void *pContext, NFCSTATUS status)
     46 {
     47    struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
     48    LOG_CALLBACK("nfc_jni_sendTo_callback", status);
     49 
     50    /* Report the callback status and wake up the caller */
     51    pCallbackData->status = status;
     52    sem_post(&pCallbackData->sem);
     53 }
     54 
     55 /*
     56 * Methods
     57 */
     58 static jboolean com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo(JNIEnv *e, jobject o, jint nsap, jbyteArray data)
     59 {
     60    NFCSTATUS ret;
     61    struct timespec ts;
     62    phLibNfc_Handle hRemoteDevice;
     63    phLibNfc_Handle hLlcpSocket;
     64    phNfc_sData_t sSendBuffer = {NULL, 0};
     65    struct nfc_jni_callback_data cb_data;
     66    jboolean result = JNI_FALSE;
     67 
     68    /* Retrieve handles */
     69    hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o);
     70    hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
     71 
     72    /* Create the local semaphore */
     73    if (!nfc_cb_data_init(&cb_data, NULL))
     74    {
     75       goto clean_and_return;
     76    }
     77 
     78    sSendBuffer.buffer = (uint8_t*)e->GetByteArrayElements(data, NULL);
     79    sSendBuffer.length = (uint32_t)e->GetArrayLength(data);
     80 
     81    TRACE("phLibNfc_Llcp_SendTo()");
     82    REENTRANCE_LOCK();
     83    ret = phLibNfc_Llcp_SendTo(hRemoteDevice,
     84                               hLlcpSocket,
     85                               nsap,
     86                               &sSendBuffer,
     87                               nfc_jni_send_callback,
     88                               (void*)&cb_data);
     89    REENTRANCE_UNLOCK();
     90    if(ret != NFCSTATUS_PENDING)
     91    {
     92       ALOGE("phLibNfc_Llcp_SendTo() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
     93       goto clean_and_return;
     94    }
     95    TRACE("phLibNfc_Llcp_SendTo() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
     96 
     97    /* Wait for callback response */
     98    if(sem_wait(&cb_data.sem))
     99    {
    100       ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
    101       goto clean_and_return;
    102    }
    103 
    104    if(cb_data.status != NFCSTATUS_SUCCESS)
    105    {
    106       goto clean_and_return;
    107    }
    108 
    109    result = JNI_TRUE;
    110 
    111 clean_and_return:
    112    if (sSendBuffer.buffer != NULL)
    113    {
    114       e->ReleaseByteArrayElements(data, (jbyte*)sSendBuffer.buffer, JNI_ABORT);
    115    }
    116    nfc_cb_data_deinit(&cb_data);
    117    return result;
    118 }
    119 
    120 static jobject com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom(JNIEnv *e, jobject o, jint linkMiu)
    121 {
    122    NFCSTATUS ret;
    123    struct timespec ts;
    124    uint8_t ssap;
    125    jobject llcpPacket = NULL;
    126    phLibNfc_Handle hRemoteDevice;
    127    phLibNfc_Handle hLlcpSocket;
    128    phNfc_sData_t sReceiveBuffer;
    129    jclass clsLlcpPacket;
    130    jfieldID f;
    131    jbyteArray receivedData = NULL;
    132    struct nfc_jni_callback_data cb_data;
    133 
    134    /* Create the local semaphore */
    135    if (!nfc_cb_data_init(&cb_data, NULL))
    136    {
    137       goto clean_and_return;
    138    }
    139 
    140    /* Create new LlcpPacket object */
    141    if(nfc_jni_cache_object(e,"com/android/nfc/LlcpPacket",&(llcpPacket)) == -1)
    142    {
    143       ALOGE("Find LlcpPacket class error");
    144       goto clean_and_return;
    145    }
    146 
    147    /* Get NativeConnectionless class object */
    148    clsLlcpPacket = e->GetObjectClass(llcpPacket);
    149    if(e->ExceptionCheck())
    150    {
    151       ALOGE("Get Object class error");
    152       goto clean_and_return;
    153    }
    154 
    155    /* Retrieve handles */
    156    hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o);
    157    hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
    158    TRACE("phLibNfc_Llcp_RecvFrom(), Socket Handle = 0x%02x, Link LIU = %d", hLlcpSocket, linkMiu);
    159 
    160    sReceiveBuffer.buffer = (uint8_t*)malloc(linkMiu);
    161    sReceiveBuffer.length = linkMiu;
    162 
    163    REENTRANCE_LOCK();
    164    ret = phLibNfc_Llcp_RecvFrom(hRemoteDevice,
    165                                 hLlcpSocket,
    166                                 &sReceiveBuffer,
    167                                 nfc_jni_receive_callback,
    168                                 &cb_data);
    169    REENTRANCE_UNLOCK();
    170    if(ret != NFCSTATUS_PENDING && ret != NFCSTATUS_SUCCESS)
    171    {
    172       ALOGE("phLibNfc_Llcp_RecvFrom() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    173       goto clean_and_return;
    174    }
    175    TRACE("phLibNfc_Llcp_RecvFrom() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    176 
    177    /* Wait for callback response */
    178    if(sem_wait(&cb_data.sem))
    179    {
    180       ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
    181       goto clean_and_return;
    182    }
    183 
    184    if(cb_data.status != NFCSTATUS_SUCCESS)
    185    {
    186        goto clean_and_return;
    187    }
    188 
    189    ssap = (uintptr_t)cb_data.pContext;
    190    TRACE("Data Received From SSAP = %d\n, length = %d", ssap, sReceiveBuffer.length);
    191 
    192    /* Set Llcp Packet remote SAP */
    193    f = e->GetFieldID(clsLlcpPacket, "mRemoteSap", "I");
    194    e->SetIntField(llcpPacket, f,(jbyte)ssap);
    195 
    196    /* Set Llcp Packet Buffer */
    197    ALOGD("Set LlcpPacket Data Buffer\n");
    198    f = e->GetFieldID(clsLlcpPacket, "mDataBuffer", "[B");
    199    receivedData = e->NewByteArray(sReceiveBuffer.length);
    200    e->SetByteArrayRegion(receivedData, 0, sReceiveBuffer.length,(jbyte *)sReceiveBuffer.buffer);
    201    e->SetObjectField(llcpPacket, f, receivedData);
    202 
    203 clean_and_return:
    204    nfc_cb_data_deinit(&cb_data);
    205    return llcpPacket;
    206 }
    207 
    208 static jboolean com_android_nfc_NativeLlcpConnectionlessSocket_doClose(JNIEnv *e, jobject o)
    209 {
    210    NFCSTATUS ret;
    211    phLibNfc_Handle hLlcpSocket;
    212    TRACE("Close Connectionless socket");
    213 
    214    /* Retrieve socket handle */
    215    hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
    216 
    217    TRACE("phLibNfc_Llcp_Close()");
    218    REENTRANCE_LOCK();
    219    ret = phLibNfc_Llcp_Close(hLlcpSocket);
    220    REENTRANCE_UNLOCK();
    221    if(ret == NFCSTATUS_SUCCESS)
    222    {
    223       TRACE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    224       return TRUE;
    225    }
    226    else
    227    {
    228       ALOGE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    229       return FALSE;
    230    }
    231 }
    232 
    233 
    234 /*
    235  * JNI registration.
    236  */
    237 static JNINativeMethod gMethods[] =
    238 {
    239    {"doSendTo", "(I[B)Z", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo},
    240 
    241    {"doReceiveFrom", "(I)Lcom/android/nfc/LlcpPacket;", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom},
    242 
    243    {"doClose", "()Z", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doClose},
    244 };
    245 
    246 
    247 int register_com_android_nfc_NativeLlcpConnectionlessSocket(JNIEnv *e)
    248 {
    249    return jniRegisterNativeMethods(e,
    250       "com/android/nfc/dhimpl/NativeLlcpConnectionlessSocket",
    251       gMethods, NELEM(gMethods));
    252 }
    253 
    254 } // android namespace
    255