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