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*)(uintptr_t)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       ALOGE("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       ALOGE("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,"com/android/nfc/LlcpPacket",&(llcpPacket)) == -1)
    141    {
    142       ALOGE("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       ALOGE("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 && ret != NFCSTATUS_SUCCESS)
    170    {
    171       ALOGE("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       ALOGE("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 = (uintptr_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    ALOGD("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    nfc_cb_data_deinit(&cb_data);
    204    return llcpPacket;
    205 }
    206 
    207 static jboolean com_android_nfc_NativeLlcpConnectionlessSocket_doClose(JNIEnv *e, jobject o)
    208 {
    209    NFCSTATUS ret;
    210    phLibNfc_Handle hLlcpSocket;
    211    TRACE("Close Connectionless socket");
    212 
    213    /* Retrieve socket handle */
    214    hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
    215 
    216    TRACE("phLibNfc_Llcp_Close()");
    217    REENTRANCE_LOCK();
    218    ret = phLibNfc_Llcp_Close(hLlcpSocket);
    219    REENTRANCE_UNLOCK();
    220    if(ret == NFCSTATUS_SUCCESS)
    221    {
    222       TRACE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    223       return TRUE;
    224    }
    225    else
    226    {
    227       ALOGE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    228       return FALSE;
    229    }
    230 }
    231 
    232 
    233 /*
    234  * JNI registration.
    235  */
    236 static JNINativeMethod gMethods[] =
    237 {
    238    {"doSendTo", "(I[B)Z", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo},
    239 
    240    {"doReceiveFrom", "(I)Lcom/android/nfc/LlcpPacket;", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom},
    241 
    242    {"doClose", "()Z", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doClose},
    243 };
    244 
    245 
    246 int register_com_android_nfc_NativeLlcpConnectionlessSocket(JNIEnv *e)
    247 {
    248    return jniRegisterNativeMethods(e,
    249       "com/android/nfc/dhimpl/NativeLlcpConnectionlessSocket",
    250       gMethods, NELEM(gMethods));
    251 }
    252 
    253 } // android namespace
    254