• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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