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_sem;
     22 static NFCSTATUS nfc_jni_cb_status = NFCSTATUS_FAILED;
     23 
     24 namespace android {
     25 
     26 /*
     27  * Callbacks
     28  */
     29 
     30 static void nfc_jni_disconnect_callback(void*        pContext,
     31                                                NFCSTATUS    status)
     32 {
     33    PHNFC_UNUSED_VARIABLE(pContext);
     34 
     35    LOG_CALLBACK("nfc_jni_llcp_disconnect_callback", status);
     36 
     37    nfc_jni_cb_status = status;
     38 
     39    sem_post(nfc_jni_llcp_sem);
     40 }
     41 
     42 
     43 static void nfc_jni_connect_callback(void* pContext, uint8_t nErrCode, NFCSTATUS status)
     44 {
     45    PHNFC_UNUSED_VARIABLE(pContext);
     46 
     47    LOG_CALLBACK("nfc_jni_llcp_connect_callback", status);
     48 
     49    nfc_jni_cb_status = status;
     50 
     51    if(status == NFCSTATUS_SUCCESS)
     52    {
     53       TRACE("Socket connected\n");
     54    }
     55    else
     56    {
     57       LOGD("Socket not connected:");
     58       switch(nErrCode)
     59       {
     60          case PHFRINFC_LLCP_DM_OPCODE_SAP_NOT_ACTIVE:
     61             {
     62                LOGD("> SAP NOT ACTIVE\n");
     63             }break;
     64 
     65          case PHFRINFC_LLCP_DM_OPCODE_SAP_NOT_FOUND:
     66             {
     67                LOGD("> SAP NOT FOUND\n");
     68             }break;
     69 
     70          case PHFRINFC_LLCP_DM_OPCODE_CONNECT_REJECTED:
     71             {
     72                LOGD("> CONNECT REJECTED\n");
     73             }break;
     74 
     75          case PHFRINFC_LLCP_DM_OPCODE_CONNECT_NOT_ACCEPTED:
     76             {
     77                LOGD("> CONNECT NOT ACCEPTED\n");
     78             }break;
     79 
     80          case PHFRINFC_LLCP_DM_OPCODE_SOCKET_NOT_AVAILABLE:
     81             {
     82                LOGD("> SOCKET NOT AVAILABLE\n");
     83             }break;
     84       }
     85    }
     86 
     87    sem_post(nfc_jni_llcp_sem);
     88 }
     89 
     90 
     91 
     92 
     93 static void nfc_jni_receive_callback(void* pContext, NFCSTATUS    status)
     94 {
     95    uint8_t i;
     96    PHNFC_UNUSED_VARIABLE(pContext);
     97 
     98    LOG_CALLBACK("nfc_jni_llcp_receive_callback", status);
     99 
    100    nfc_jni_cb_status = status;
    101 
    102    sem_post(nfc_jni_llcp_sem);
    103 }
    104 
    105 static void nfc_jni_send_callback(void *pContext, NFCSTATUS status)
    106 {
    107    PHNFC_UNUSED_VARIABLE(pContext);
    108 
    109    LOG_CALLBACK("nfc_jni_llcp_send_callback", status);
    110 
    111    nfc_jni_cb_status = status;
    112 
    113    sem_post(nfc_jni_llcp_sem);
    114 }
    115 
    116 /*
    117  * Methods
    118  */
    119 static jboolean com_android_nfc_NativeLlcpSocket_doConnect(JNIEnv *e, jobject o, jint nSap)
    120 {
    121    NFCSTATUS ret;
    122    struct timespec ts;
    123    phLibNfc_Handle hLlcpSocket;
    124 
    125    /* Retrieve socket handle */
    126    hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
    127 
    128    TRACE("phLibNfc_Llcp_Connect(%d)",nSap);
    129    REENTRANCE_LOCK();
    130    ret = phLibNfc_Llcp_Connect(hLlcpSocket,
    131                                nSap,
    132                                nfc_jni_connect_callback,
    133                                (void*)hLlcpSocket);
    134    REENTRANCE_UNLOCK();
    135    if(ret != NFCSTATUS_PENDING)
    136    {
    137       LOGE("phLibNfc_Llcp_Connect(%d) returned 0x%04x[%s]", nSap, ret, nfc_jni_get_status_name(ret));
    138       return FALSE;
    139    }
    140    TRACE("phLibNfc_Llcp_Connect(%d) returned 0x%04x[%s]", nSap, ret, nfc_jni_get_status_name(ret));
    141 
    142    /* Wait for callback response */
    143    if(sem_wait(nfc_jni_llcp_sem) == -1)
    144       return FALSE;
    145 
    146    if(nfc_jni_cb_status == NFCSTATUS_SUCCESS)
    147    {
    148       TRACE("LLCP Connect request OK");
    149       return TRUE;
    150    }
    151    else
    152    {
    153       LOGD("LLCP Connect request KO");
    154       return FALSE;
    155    }
    156 }
    157 
    158 static jboolean com_android_nfc_NativeLlcpSocket_doConnectBy(JNIEnv *e, jobject o, jstring sn)
    159 {
    160    NFCSTATUS ret;
    161    struct timespec ts;
    162    phNfc_sData_t serviceName;
    163    phLibNfc_Handle hLlcpSocket;
    164 
    165    /* Retrieve socket handle */
    166    hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
    167 
    168    /* Service socket */
    169    serviceName.buffer = (uint8_t*)e->GetStringUTFChars(sn, NULL);
    170    serviceName.length = (uint32_t)e->GetStringUTFLength(sn);
    171 
    172    TRACE("phLibNfc_Llcp_ConnectByUri()");
    173    REENTRANCE_LOCK();
    174    ret = phLibNfc_Llcp_ConnectByUri(hLlcpSocket,
    175                                     &serviceName,
    176                                     nfc_jni_connect_callback,
    177                                     (void*)hLlcpSocket);
    178    REENTRANCE_UNLOCK();
    179    if(ret != NFCSTATUS_PENDING)
    180    {
    181       LOGE("phLibNfc_Llcp_ConnectByUri() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    182       return FALSE;
    183    }
    184    TRACE("phLibNfc_Llcp_ConnectByUri() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    185 
    186    /* Wait for callback response */
    187    if(sem_wait(nfc_jni_llcp_sem) == -1)
    188       return FALSE;
    189 
    190    if(nfc_jni_cb_status == NFCSTATUS_SUCCESS)
    191    {
    192       return TRUE;
    193    }
    194    else
    195    {
    196       return FALSE;
    197    }
    198 }
    199 
    200 static jboolean com_android_nfc_NativeLlcpSocket_doClose(JNIEnv *e, jobject o)
    201 {
    202    NFCSTATUS ret;
    203    phLibNfc_Handle hLlcpSocket;
    204 
    205    /* Retrieve socket handle */
    206    hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
    207 
    208    TRACE("phLibNfc_Llcp_Close()");
    209    REENTRANCE_LOCK();
    210    ret = phLibNfc_Llcp_Close(hLlcpSocket);
    211    REENTRANCE_UNLOCK();
    212    if(ret != NFCSTATUS_SUCCESS)
    213    {
    214       LOGE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    215       return FALSE;
    216    }
    217    TRACE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    218    return TRUE;
    219 }
    220 
    221 static jboolean com_android_nfc_NativeLlcpSocket_doSend(JNIEnv *e, jobject o, jbyteArray  data)
    222 {
    223    NFCSTATUS ret;
    224    struct timespec ts;
    225    phLibNfc_Handle hLlcpSocket;
    226    phNfc_sData_t sSendBuffer;
    227 
    228    /* Retrieve socket handle */
    229    hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
    230 
    231    sSendBuffer.buffer = (uint8_t*)e->GetByteArrayElements(data, NULL);
    232    sSendBuffer.length = (uint32_t)e->GetArrayLength(data);
    233 
    234    TRACE("phLibNfc_Llcp_Send()");
    235    REENTRANCE_LOCK();
    236    ret = phLibNfc_Llcp_Send(hLlcpSocket,
    237                             &sSendBuffer,
    238                             nfc_jni_send_callback,
    239                             (void*)hLlcpSocket);
    240    REENTRANCE_UNLOCK();
    241    if(ret != NFCSTATUS_PENDING)
    242    {
    243       LOGE("phLibNfc_Llcp_Send() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    244       return FALSE;
    245    }
    246    TRACE("phLibNfc_Llcp_Send() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    247 
    248    /* Wait for callback response */
    249    if(sem_wait(nfc_jni_llcp_sem) == -1)
    250       return FALSE;
    251 
    252 
    253    if(nfc_jni_cb_status == NFCSTATUS_SUCCESS)
    254    {
    255       return TRUE;
    256    }
    257    else
    258    {
    259       return FALSE;
    260    }
    261 }
    262 
    263 static jint com_android_nfc_NativeLlcpSocket_doReceive(JNIEnv *e, jobject o, jbyteArray  buffer)
    264 {
    265    NFCSTATUS ret;
    266    struct timespec ts;
    267    phLibNfc_Handle hLlcpSocket;
    268    phNfc_sData_t sReceiveBuffer;
    269 
    270    /* Retrieve socket handle */
    271    hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
    272 
    273    sReceiveBuffer.buffer = (uint8_t*)e->GetByteArrayElements(buffer, NULL);
    274    sReceiveBuffer.length = (uint32_t)e->GetArrayLength(buffer);
    275 
    276    TRACE("phLibNfc_Llcp_Recv()");
    277    REENTRANCE_LOCK();
    278    ret = phLibNfc_Llcp_Recv(hLlcpSocket,
    279                             &sReceiveBuffer,
    280                             nfc_jni_receive_callback,
    281                             (void*)hLlcpSocket);
    282    REENTRANCE_UNLOCK();
    283    if((ret != NFCSTATUS_SUCCESS) && (ret != NFCSTATUS_PENDING))
    284    {
    285        /* Return status should be either SUCCESS or PENDING */
    286        LOGE("phLibNfc_Llcp_Recv() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    287        return 0;
    288    }
    289    TRACE("phLibNfc_Llcp_Recv() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    290 
    291    /* Wait for callback response (happen if status is either SUCCESS or PENDING) */
    292    if(sem_wait(nfc_jni_llcp_sem) == -1)
    293    {
    294       return 0;
    295    }
    296 
    297    if(nfc_jni_cb_status == NFCSTATUS_SUCCESS)
    298    {
    299       return sReceiveBuffer.length;
    300    }
    301    else
    302    {
    303       return 0;
    304    }
    305 }
    306 
    307 static jint com_android_nfc_NativeLlcpSocket_doGetRemoteSocketMIU(JNIEnv *e, jobject o)
    308 {
    309    NFCSTATUS ret;
    310    phLibNfc_Handle hLlcpSocket;
    311    phLibNfc_Llcp_sSocketOptions_t   remoteSocketOption;
    312 
    313    /* Retrieve socket handle */
    314    hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
    315 
    316    TRACE("phLibNfc_Llcp_SocketGetRemoteOptions(MIU)");
    317    REENTRANCE_LOCK();
    318    ret  = phLibNfc_Llcp_SocketGetRemoteOptions(hLlcpSocket,
    319                                                &remoteSocketOption);
    320    REENTRANCE_UNLOCK();
    321    if(ret == NFCSTATUS_SUCCESS)
    322    {
    323       TRACE("phLibNfc_Llcp_SocketGetRemoteOptions(MIU) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    324       return remoteSocketOption.miu;
    325    }
    326    else
    327    {
    328       LOGW("phLibNfc_Llcp_SocketGetRemoteOptions(MIU) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    329       return 0;
    330    }
    331 }
    332 
    333 static jint com_android_nfc_NativeLlcpSocket_doGetRemoteSocketRW(JNIEnv *e, jobject o)
    334 {
    335    NFCSTATUS ret;
    336    phLibNfc_Handle hLlcpSocket;
    337    phLibNfc_Llcp_sSocketOptions_t   remoteSocketOption;
    338 
    339    /* Retrieve socket handle */
    340    hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
    341 
    342    TRACE("phLibNfc_Llcp_SocketGetRemoteOptions(RW)");
    343    REENTRANCE_LOCK();
    344    ret  = phLibNfc_Llcp_SocketGetRemoteOptions(hLlcpSocket,
    345                                                &remoteSocketOption);
    346    REENTRANCE_UNLOCK();
    347    if(ret == NFCSTATUS_SUCCESS)
    348    {
    349       TRACE("phLibNfc_Llcp_SocketGetRemoteOptions(RW) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    350       return remoteSocketOption.rw;
    351    }
    352    else
    353    {
    354       LOGW("phLibNfc_Llcp_SocketGetRemoteOptions(RW) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    355       return 0;
    356    }
    357 }
    358 
    359 
    360 /*
    361  * JNI registration.
    362  */
    363 static JNINativeMethod gMethods[] =
    364 {
    365    {"doConnect", "(I)Z",
    366       (void *)com_android_nfc_NativeLlcpSocket_doConnect},
    367 
    368    {"doConnectBy", "(Ljava/lang/String;)Z",
    369       (void *)com_android_nfc_NativeLlcpSocket_doConnectBy},
    370 
    371    {"doClose", "()Z",
    372       (void *)com_android_nfc_NativeLlcpSocket_doClose},
    373 
    374    {"doSend", "([B)Z",
    375       (void *)com_android_nfc_NativeLlcpSocket_doSend},
    376 
    377    {"doReceive", "([B)I",
    378       (void *)com_android_nfc_NativeLlcpSocket_doReceive},
    379 
    380    {"doGetRemoteSocketMiu", "()I",
    381       (void *)com_android_nfc_NativeLlcpSocket_doGetRemoteSocketMIU},
    382 
    383    {"doGetRemoteSocketRw", "()I",
    384       (void *)com_android_nfc_NativeLlcpSocket_doGetRemoteSocketRW},
    385 };
    386 
    387 
    388 int register_com_android_nfc_NativeLlcpSocket(JNIEnv *e)
    389 {
    390     nfc_jni_llcp_sem = (sem_t *)malloc(sizeof(sem_t));
    391    if(sem_init(nfc_jni_llcp_sem, 0, 0) == -1)
    392       return -1;
    393 
    394    return jniRegisterNativeMethods(e,
    395       "com/android/nfc/NativeLlcpSocket",gMethods, NELEM(gMethods));
    396 }
    397 
    398 } // namespace android
    399