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
22 namespace android {
23
24 /*
25 * Callbacks
26 */
27
nfc_jni_receive_callback(void * pContext,uint8_t ssap,NFCSTATUS status)28 static 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
nfc_jni_send_callback(void * pContext,NFCSTATUS status)44 static 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 */
com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo(JNIEnv * e,jobject o,jint nsap,jbyteArray data)57 static 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
110 clean_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
com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom(JNIEnv * e,jobject o,jint linkMiu)119 static 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
202 clean_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
com_android_nfc_NativeLlcpConnectionlessSocket_doClose(JNIEnv * e,jobject o)211 static 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 */
240 static 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
register_com_android_nfc_NativeLlcpConnectionlessSocket(JNIEnv * e)250 int register_com_android_nfc_NativeLlcpConnectionlessSocket(JNIEnv *e)
251 {
252 return jniRegisterNativeMethods(e,
253 "com/android/nfc/NativeLlcpConnectionlessSocket",
254 gMethods, NELEM(gMethods));
255 }
256
257 } // android namespace
258