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