2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <semaphore.h>
20 #include "com_android_nfc.h"
28 static void nfc_jni_receive_callback(void* pContext, uint8_t ssap, NFCSTATUS status)
30 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
31 LOG_CALLBACK("nfc_jni_receiveFrom_callback", status);
33 if(status == NFCSTATUS_SUCCESS)
35 pCallbackData->pContext = (void*)ssap;
36 TRACE("RECEIVE UI_FRAME FROM SAP %d OK \n", ssap);
39 /* Report the callback status and wake up the caller */
40 pCallbackData->status = status;
41 sem_post(&pCallbackData->sem);
44 static void nfc_jni_send_callback(void *pContext, NFCSTATUS status)
46 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
47 LOG_CALLBACK("nfc_jni_sendTo_callback", status);
49 /* Report the callback status and wake up the caller */
50 pCallbackData->status = status;
51 sem_post(&pCallbackData->sem);
57 static jboolean com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo(JNIEnv *e, jobject o, jint nsap, jbyteArray data)
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;
67 /* Retrieve handles */
68 hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o);
69 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
71 /* Create the local semaphore */
72 if (!nfc_cb_data_init(&cb_data, NULL))
74 goto clean_and_return;
77 sSendBuffer.buffer = (uint8_t*)e->GetByteArrayElements(data, NULL);
78 sSendBuffer.length = (uint32_t)e->GetArrayLength(data);
80 TRACE("phLibNfc_Llcp_SendTo()");
82 ret = phLibNfc_Llcp_SendTo(hRemoteDevice,
86 nfc_jni_send_callback,
89 if(ret != NFCSTATUS_PENDING)
91 LOGE("phLibNfc_Llcp_SendTo() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
92 goto clean_and_return;
94 TRACE("phLibNfc_Llcp_SendTo() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
96 /* Wait for callback response */
97 if(sem_wait(&cb_data.sem))
99 LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
100 goto clean_and_return;
103 if(cb_data.status != NFCSTATUS_SUCCESS)
105 goto clean_and_return;
111 if (sSendBuffer.buffer != NULL)
113 e->ReleaseByteArrayElements(data, (jbyte*)sSendBuffer.buffer, JNI_ABORT);
115 nfc_cb_data_deinit(&cb_data);
119 static jobject com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom(JNIEnv *e, jobject o, jint linkMiu)
124 jobject llcpPacket = NULL;
125 phLibNfc_Handle hRemoteDevice;
126 phLibNfc_Handle hLlcpSocket;
127 phNfc_sData_t sReceiveBuffer;
128 jclass clsLlcpPacket;
130 jbyteArray receivedData = NULL;
131 struct nfc_jni_callback_data cb_data;
133 /* Create the local semaphore */
134 if (!nfc_cb_data_init(&cb_data, NULL))
136 goto clean_and_return;
139 /* Create new LlcpPacket object */
140 if(nfc_jni_cache_object(e,"android/nfc/LlcpPacket",&(llcpPacket)) == -1)
142 LOGE("Find LlcpPacket class error");
143 goto clean_and_return;
146 /* Get NativeConnectionless class object */
147 clsLlcpPacket = e->GetObjectClass(llcpPacket);
148 if(e->ExceptionCheck())
150 LOGE("Get Object class error");
151 goto clean_and_return;
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);
159 sReceiveBuffer.buffer = (uint8_t*)malloc(linkMiu);
160 sReceiveBuffer.length = linkMiu;
163 ret = phLibNfc_Llcp_RecvFrom(hRemoteDevice,
166 nfc_jni_receive_callback,
169 if(ret != NFCSTATUS_PENDING)
171 LOGE("phLibNfc_Llcp_RecvFrom() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
172 goto clean_and_return;
174 TRACE("phLibNfc_Llcp_RecvFrom() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
176 /* Wait for callback response */
177 if(sem_wait(&cb_data.sem))
179 LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
180 goto clean_and_return;
183 if(cb_data.status != NFCSTATUS_SUCCESS)
185 goto clean_and_return;
188 ssap = (uint32_t)cb_data.pContext;
189 TRACE("Data Received From SSAP = %d\n, length = %d", ssap, sReceiveBuffer.length);
191 /* Set Llcp Packet remote SAP */
192 f = e->GetFieldID(clsLlcpPacket, "mRemoteSap", "I");
193 e->SetIntField(llcpPacket, f,(jbyte)ssap);
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);
203 if (receivedData != NULL)
205 e->ReleaseByteArrayElements(receivedData, (jbyte*)sReceiveBuffer.buffer, 0);
207 nfc_cb_data_deinit(&cb_data);
211 static jboolean com_android_nfc_NativeLlcpConnectionlessSocket_doClose(JNIEnv *e, jobject o)
214 phLibNfc_Handle hLlcpSocket;
215 TRACE("Close Connectionless socket");
217 /* Retrieve socket handle */
218 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
220 TRACE("phLibNfc_Llcp_Close()");
222 ret = phLibNfc_Llcp_Close(hLlcpSocket);
224 if(ret == NFCSTATUS_SUCCESS)
226 TRACE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
231 LOGE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
240 static JNINativeMethod gMethods[] =
242 {"doSendTo", "(I[B)Z", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo},
244 {"doReceiveFrom", "(I)Landroid/nfc/LlcpPacket;", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom},
246 {"doClose", "()Z", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doClose},
250 int register_com_android_nfc_NativeLlcpConnectionlessSocket(JNIEnv *e)
252 return jniRegisterNativeMethods(e,
253 "com/android/nfc/NativeLlcpConnectionlessSocket",
254 gMethods, NELEM(gMethods));
257 } // android namespace