OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / packages / apps / Nfc / jni / com_android_nfc_NativeLlcpConnectionlessSocket.cpp
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
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
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 */
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
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
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
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