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 22namespace android { 23 24/* 25 * Callbacks 26 */ 27 28static 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 44static 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*/ 57static 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 110clean_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 119static 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 202clean_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 211static 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 */ 240static 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 250int 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