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