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 <errno.h>
18 #include <malloc.h>
19 #include <semaphore.h>
20
21 #include "com_android_nfc.h"
22
23 namespace android {
24
25 /*
26 * Callbacks
27 */
28
nfc_jni_receive_callback(void * pContext,uint8_t ssap,NFCSTATUS status)29 static void nfc_jni_receive_callback(void* pContext, uint8_t ssap, NFCSTATUS status)
30 {
31 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
32 LOG_CALLBACK("nfc_jni_receiveFrom_callback", status);
33
34 if(status == NFCSTATUS_SUCCESS)
35 {
36 pCallbackData->pContext = (void*)(uintptr_t)ssap;
37 TRACE("RECEIVE UI_FRAME FROM SAP %d OK \n", ssap);
38 }
39
40 /* Report the callback status and wake up the caller */
41 pCallbackData->status = status;
42 sem_post(&pCallbackData->sem);
43 }
44
nfc_jni_send_callback(void * pContext,NFCSTATUS status)45 static void nfc_jni_send_callback(void *pContext, NFCSTATUS status)
46 {
47 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
48 LOG_CALLBACK("nfc_jni_sendTo_callback", status);
49
50 /* Report the callback status and wake up the caller */
51 pCallbackData->status = status;
52 sem_post(&pCallbackData->sem);
53 }
54
55 /*
56 * Methods
57 */
com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo(JNIEnv * e,jobject o,jint nsap,jbyteArray data)58 static jboolean com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo(JNIEnv *e, jobject o, jint nsap, jbyteArray data)
59 {
60 NFCSTATUS ret;
61 struct timespec ts;
62 phLibNfc_Handle hRemoteDevice;
63 phLibNfc_Handle hLlcpSocket;
64 phNfc_sData_t sSendBuffer = {NULL, 0};
65 struct nfc_jni_callback_data cb_data;
66 jboolean result = JNI_FALSE;
67
68 /* Retrieve handles */
69 hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o);
70 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
71
72 /* Create the local semaphore */
73 if (!nfc_cb_data_init(&cb_data, NULL))
74 {
75 goto clean_and_return;
76 }
77
78 sSendBuffer.buffer = (uint8_t*)e->GetByteArrayElements(data, NULL);
79 sSendBuffer.length = (uint32_t)e->GetArrayLength(data);
80
81 TRACE("phLibNfc_Llcp_SendTo()");
82 REENTRANCE_LOCK();
83 ret = phLibNfc_Llcp_SendTo(hRemoteDevice,
84 hLlcpSocket,
85 nsap,
86 &sSendBuffer,
87 nfc_jni_send_callback,
88 (void*)&cb_data);
89 REENTRANCE_UNLOCK();
90 if(ret != NFCSTATUS_PENDING)
91 {
92 ALOGE("phLibNfc_Llcp_SendTo() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
93 goto clean_and_return;
94 }
95 TRACE("phLibNfc_Llcp_SendTo() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
96
97 /* Wait for callback response */
98 if(sem_wait(&cb_data.sem))
99 {
100 ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
101 goto clean_and_return;
102 }
103
104 if(cb_data.status != NFCSTATUS_SUCCESS)
105 {
106 goto clean_and_return;
107 }
108
109 result = JNI_TRUE;
110
111 clean_and_return:
112 if (sSendBuffer.buffer != NULL)
113 {
114 e->ReleaseByteArrayElements(data, (jbyte*)sSendBuffer.buffer, JNI_ABORT);
115 }
116 nfc_cb_data_deinit(&cb_data);
117 return result;
118 }
119
com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom(JNIEnv * e,jobject o,jint linkMiu)120 static jobject com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom(JNIEnv *e, jobject o, jint linkMiu)
121 {
122 NFCSTATUS ret;
123 struct timespec ts;
124 uint8_t ssap;
125 jobject llcpPacket = NULL;
126 phLibNfc_Handle hRemoteDevice;
127 phLibNfc_Handle hLlcpSocket;
128 phNfc_sData_t sReceiveBuffer;
129 jclass clsLlcpPacket;
130 jfieldID f;
131 jbyteArray receivedData = NULL;
132 struct nfc_jni_callback_data cb_data;
133
134 /* Create the local semaphore */
135 if (!nfc_cb_data_init(&cb_data, NULL))
136 {
137 goto clean_and_return;
138 }
139
140 /* Create new LlcpPacket object */
141 if(nfc_jni_cache_object(e,"com/android/nfc/LlcpPacket",&(llcpPacket)) == -1)
142 {
143 ALOGE("Find LlcpPacket class error");
144 goto clean_and_return;
145 }
146
147 /* Get NativeConnectionless class object */
148 clsLlcpPacket = e->GetObjectClass(llcpPacket);
149 if(e->ExceptionCheck())
150 {
151 ALOGE("Get Object class error");
152 goto clean_and_return;
153 }
154
155 /* Retrieve handles */
156 hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o);
157 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
158 TRACE("phLibNfc_Llcp_RecvFrom(), Socket Handle = 0x%02x, Link LIU = %d", hLlcpSocket, linkMiu);
159
160 sReceiveBuffer.buffer = (uint8_t*)malloc(linkMiu);
161 sReceiveBuffer.length = linkMiu;
162
163 REENTRANCE_LOCK();
164 ret = phLibNfc_Llcp_RecvFrom(hRemoteDevice,
165 hLlcpSocket,
166 &sReceiveBuffer,
167 nfc_jni_receive_callback,
168 &cb_data);
169 REENTRANCE_UNLOCK();
170 if(ret != NFCSTATUS_PENDING && ret != NFCSTATUS_SUCCESS)
171 {
172 ALOGE("phLibNfc_Llcp_RecvFrom() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
173 goto clean_and_return;
174 }
175 TRACE("phLibNfc_Llcp_RecvFrom() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
176
177 /* Wait for callback response */
178 if(sem_wait(&cb_data.sem))
179 {
180 ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
181 goto clean_and_return;
182 }
183
184 if(cb_data.status != NFCSTATUS_SUCCESS)
185 {
186 goto clean_and_return;
187 }
188
189 ssap = (uintptr_t)cb_data.pContext;
190 TRACE("Data Received From SSAP = %d\n, length = %d", ssap, sReceiveBuffer.length);
191
192 /* Set Llcp Packet remote SAP */
193 f = e->GetFieldID(clsLlcpPacket, "mRemoteSap", "I");
194 e->SetIntField(llcpPacket, f,(jbyte)ssap);
195
196 /* Set Llcp Packet Buffer */
197 ALOGD("Set LlcpPacket Data Buffer\n");
198 f = e->GetFieldID(clsLlcpPacket, "mDataBuffer", "[B");
199 receivedData = e->NewByteArray(sReceiveBuffer.length);
200 e->SetByteArrayRegion(receivedData, 0, sReceiveBuffer.length,(jbyte *)sReceiveBuffer.buffer);
201 e->SetObjectField(llcpPacket, f, receivedData);
202
203 clean_and_return:
204 nfc_cb_data_deinit(&cb_data);
205 return llcpPacket;
206 }
207
com_android_nfc_NativeLlcpConnectionlessSocket_doClose(JNIEnv * e,jobject o)208 static jboolean com_android_nfc_NativeLlcpConnectionlessSocket_doClose(JNIEnv *e, jobject o)
209 {
210 NFCSTATUS ret;
211 phLibNfc_Handle hLlcpSocket;
212 TRACE("Close Connectionless socket");
213
214 /* Retrieve socket handle */
215 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o);
216
217 TRACE("phLibNfc_Llcp_Close()");
218 REENTRANCE_LOCK();
219 ret = phLibNfc_Llcp_Close(hLlcpSocket);
220 REENTRANCE_UNLOCK();
221 if(ret == NFCSTATUS_SUCCESS)
222 {
223 TRACE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
224 return TRUE;
225 }
226 else
227 {
228 ALOGE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
229 return FALSE;
230 }
231 }
232
233
234 /*
235 * JNI registration.
236 */
237 static JNINativeMethod gMethods[] =
238 {
239 {"doSendTo", "(I[B)Z", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo},
240
241 {"doReceiveFrom", "(I)Lcom/android/nfc/LlcpPacket;", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom},
242
243 {"doClose", "()Z", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doClose},
244 };
245
246
register_com_android_nfc_NativeLlcpConnectionlessSocket(JNIEnv * e)247 int register_com_android_nfc_NativeLlcpConnectionlessSocket(JNIEnv *e)
248 {
249 return jniRegisterNativeMethods(e,
250 "com/android/nfc/dhimpl/NativeLlcpConnectionlessSocket",
251 gMethods, NELEM(gMethods));
252 }
253
254 } // android namespace
255