Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2012 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 #include "OverrideLog.h"
     20 #include "NfcJniUtil.h"
     21 #include "JavaClassConstants.h"
     22 extern "C"
     23 {
     24     #include "nfa_api.h"
     25     #include "nfa_p2p_api.h"
     26 }
     27 
     28 
     29 namespace android
     30 {
     31 
     32 
     33 /*****************************************************************************
     34 **
     35 ** private variables and functions
     36 **
     37 *****************************************************************************/
     38 static sem_t        sConnlessRecvSem;
     39 static jboolean     sConnlessRecvWaitingForData = JNI_FALSE;
     40 static uint8_t*     sConnlessRecvBuf = NULL;
     41 static uint32_t     sConnlessRecvLen = 0;
     42 static uint32_t     sConnlessRecvRemoteSap = 0;
     43 
     44 
     45 /*******************************************************************************
     46 **
     47 ** Function:        nativeLlcpConnectionlessSocket_doSendTo
     48 **
     49 ** Description:     Send data to peer.
     50 **                  e: JVM environment.
     51 **                  o: Java object.
     52 **                  nsap: service access point.
     53 **                  data: buffer for data.
     54 **
     55 ** Returns:         True if ok.
     56 **
     57 *******************************************************************************/
     58 static jboolean nativeLlcpConnectionlessSocket_doSendTo (JNIEnv *e, jobject o, jint nsap, jbyteArray data)
     59 {
     60     tNFA_STATUS status = NFA_STATUS_FAILED;
     61     jint handle = 0;
     62     uint8_t* buf = NULL;
     63     uint32_t len = 0;
     64     jclass c = NULL;
     65     jfieldID f = NULL;
     66 
     67     ALOGD ("%s: nsap = %d", __FUNCTION__, nsap);
     68 
     69     c = e->GetObjectClass (o);
     70     f = e->GetFieldID (c, "mHandle", "I");
     71     handle = e->GetIntField (o, f);
     72 
     73     buf = (uint8_t*) e->GetByteArrayElements (data, NULL);
     74     len = (uint32_t) e->GetArrayLength (data);
     75 
     76     ALOGD ("NFA_P2pSendUI: len = %d", len);
     77     status = NFA_P2pSendUI ((tNFA_HANDLE) handle, nsap, len, buf);
     78 
     79     ALOGD ("%s: NFA_P2pSendUI done, status = %d", __FUNCTION__, status);
     80     if (status != NFA_STATUS_OK)
     81     {
     82         ALOGE ("%s: NFA_P2pSendUI failed, status = %d", __FUNCTION__, status);
     83         return JNI_FALSE;
     84     }
     85     return JNI_TRUE;
     86 }
     87 
     88 
     89 /*******************************************************************************
     90 **
     91 ** Function:        nativeLlcpConnectionlessSocket_receiveData
     92 **
     93 ** Description:     Receive data from the stack.
     94 **                  data: buffer contains data.
     95 **                  len: length of data.
     96 **                  remoteSap: remote service access point.
     97 **
     98 ** Returns:         None
     99 **
    100 *******************************************************************************/
    101 void nativeLlcpConnectionlessSocket_receiveData (uint8_t* data, uint32_t len, uint32_t remoteSap)
    102 {
    103     ALOGD ("%s: waiting for data = %d, len = %d", __FUNCTION__, sConnlessRecvWaitingForData, len);
    104 
    105     // Sanity...
    106     if (sConnlessRecvLen < len)
    107     {
    108         len = sConnlessRecvLen;
    109     }
    110 
    111     if (sConnlessRecvWaitingForData)
    112     {
    113         sConnlessRecvWaitingForData = JNI_FALSE;
    114         sConnlessRecvLen = len;
    115         memcpy (sConnlessRecvBuf, data, len);
    116         sConnlessRecvRemoteSap = remoteSap;
    117 
    118         sem_post (&sConnlessRecvSem);
    119     }
    120 }
    121 
    122 
    123 /*******************************************************************************
    124 **
    125 ** Function:        connectionlessCleanup
    126 **
    127 ** Description:     Free resources.
    128 **
    129 ** Returns:         None
    130 **
    131 *******************************************************************************/
    132 static jobject connectionlessCleanup ()
    133 {
    134     sConnlessRecvWaitingForData = JNI_FALSE;
    135     sConnlessRecvLen = 0;
    136     if (sConnlessRecvBuf != NULL)
    137     {
    138         free (sConnlessRecvBuf);
    139         sConnlessRecvBuf = NULL;
    140     }
    141     return NULL;
    142 }
    143 
    144 
    145 /*******************************************************************************
    146 **
    147 ** Function:        nativeLlcpConnectionlessSocket_abortWait
    148 **
    149 ** Description:     Abort current operation and unblock threads.
    150 **
    151 ** Returns:         None
    152 **
    153 *******************************************************************************/
    154 void nativeLlcpConnectionlessSocket_abortWait ()
    155 {
    156     sem_post (&sConnlessRecvSem);
    157 }
    158 
    159 
    160 /*******************************************************************************
    161 **
    162 ** Function:        nativeLlcpConnectionlessSocket_doReceiveFrom
    163 **
    164 ** Description:     Receive data from a peer.
    165 **                  e: JVM environment.
    166 **                  o: Java object.
    167 **                  linkMiu: max info unit
    168 **
    169 ** Returns:         LlcpPacket Java object.
    170 **
    171 *******************************************************************************/
    172 static jobject nativeLlcpConnectionlessSocket_doReceiveFrom (JNIEnv *e, jobject o, jint linkMiu)
    173 {
    174     jbyteArray receivedData = NULL;
    175     jobject llcpPacket = NULL;
    176     jclass clsLlcpPacket = NULL;
    177     jfieldID f = NULL;
    178 
    179     ALOGD ("%s: linkMiu = %d", __FUNCTION__, linkMiu);
    180 
    181     if (sConnlessRecvWaitingForData != JNI_FALSE)
    182     {
    183         ALOGD ("%s: Already waiting for incoming data", __FUNCTION__);
    184         return NULL;
    185     }
    186 
    187     sConnlessRecvBuf = (uint8_t*) malloc (linkMiu);
    188     if (sConnlessRecvBuf == NULL)
    189     {
    190         ALOGD ("%s: Failed to allocate %d bytes memory buffer", __FUNCTION__, linkMiu);
    191         return NULL;
    192     }
    193     sConnlessRecvLen = linkMiu;
    194 
    195     // Create the write semaphore
    196     if (sem_init (&sConnlessRecvSem, 0, 0) == -1)
    197     {
    198         ALOGE ("%s: semaphore creation failed (errno=0x%08x)", __FUNCTION__, errno);
    199         return connectionlessCleanup ();
    200     }
    201 
    202     sConnlessRecvWaitingForData = JNI_TRUE;
    203 
    204     // Wait for sConnlessRecvSem completion status
    205     if (sem_wait (&sConnlessRecvSem))
    206     {
    207         ALOGE ("%s: Failed to wait for write semaphore (errno=0x%08x)", __FUNCTION__, errno);
    208         goto TheEnd;
    209     }
    210 
    211     // Create new LlcpPacket object
    212     if (nfc_jni_cache_object (e, "com/android/nfc/LlcpPacket", &(llcpPacket)) == -1)
    213     {
    214         ALOGE ("%s: Find LlcpPacket class error", __FUNCTION__);
    215         return connectionlessCleanup ();
    216     }
    217 
    218     // Get NativeConnectionless class object
    219     clsLlcpPacket = e->GetObjectClass (llcpPacket);
    220     if (e->ExceptionCheck ())
    221     {
    222         e->ExceptionClear();
    223         ALOGE ("%s: Get Object class error", __FUNCTION__);
    224         return connectionlessCleanup ();
    225     }
    226 
    227     // Set Llcp Packet remote SAP
    228     f = e->GetFieldID (clsLlcpPacket, "mRemoteSap", "I");
    229     e->SetIntField (llcpPacket, f, (jbyte) sConnlessRecvRemoteSap);
    230 
    231     // Set Llcp Packet Buffer
    232     ALOGD ("%s: Received Llcp packet buffer size = %d\n", __FUNCTION__, sConnlessRecvLen);
    233     f = e->GetFieldID (clsLlcpPacket, "mDataBuffer", "[B");
    234     receivedData = e->NewByteArray (sConnlessRecvLen);
    235     e->SetByteArrayRegion (receivedData, 0, sConnlessRecvLen, (jbyte*) sConnlessRecvBuf);
    236     e->SetObjectField (llcpPacket, f, receivedData);
    237 
    238 TheEnd:
    239     connectionlessCleanup ();
    240     if (sem_destroy (&sConnlessRecvSem))
    241     {
    242         ALOGE ("%s: Failed to destroy sConnlessRecvSem semaphore (errno=0x%08x)", __FUNCTION__, errno);
    243     }
    244     return llcpPacket;
    245 }
    246 
    247 
    248 /*******************************************************************************
    249 **
    250 ** Function:        nativeLlcpConnectionlessSocket_doClose
    251 **
    252 ** Description:     Close socket.
    253 **                  e: JVM environment.
    254 **                  o: Java object.
    255 **
    256 ** Returns:         True if ok.
    257 **
    258 *******************************************************************************/
    259 static jboolean nativeLlcpConnectionlessSocket_doClose (JNIEnv *e, jobject o)
    260 {
    261     tNFA_STATUS status = NFA_STATUS_FAILED;
    262     jint handle = 0;
    263     jclass c = NULL;
    264     jfieldID f = NULL;
    265 
    266     ALOGD ("%s", __FUNCTION__);
    267 
    268     c = e->GetObjectClass (o);
    269     f = e->GetFieldID (c, "mHandle", "I");
    270     handle = e->GetIntField (o, f);
    271 
    272     status = NFA_P2pDisconnect ((tNFA_HANDLE) handle, FALSE);
    273     if (status != NFA_STATUS_OK)
    274     {
    275         ALOGE ("%s: disconnect failed, status = %d", __FUNCTION__, status);
    276         return JNI_FALSE;
    277     }
    278     return JNI_TRUE;
    279 }
    280 
    281 
    282 /*****************************************************************************
    283 **
    284 ** Description:     JNI functions
    285 **
    286 *****************************************************************************/
    287 static JNINativeMethod gMethods[] =
    288 {
    289     {"doSendTo", "(I[B)Z", (void*) nativeLlcpConnectionlessSocket_doSendTo},
    290     {"doReceiveFrom", "(I)Lcom/android/nfc/LlcpPacket;", (void*) nativeLlcpConnectionlessSocket_doReceiveFrom},
    291     {"doClose", "()Z", (void*) nativeLlcpConnectionlessSocket_doClose},
    292 };
    293 
    294 
    295 /*******************************************************************************
    296 **
    297 ** Function:        register_com_android_nfc_NativeLlcpConnectionlessSocket
    298 **
    299 ** Description:     Regisgter JNI functions with Java Virtual Machine.
    300 **                  e: Environment of JVM.
    301 **
    302 ** Returns:         Status of registration.
    303 **
    304 *******************************************************************************/
    305 int register_com_android_nfc_NativeLlcpConnectionlessSocket (JNIEnv *e)
    306 {
    307     return jniRegisterNativeMethods (e, gNativeLlcpConnectionlessSocketClassName, gMethods, NELEM(gMethods));
    308 }
    309 
    310 
    311 } // android namespace
    312