iotivity 0.9.0
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / caleadapter.c
1 /******************************************************************
2  *
3  * Copyright 2014 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20 #include "caleadapter.h"
21
22 #ifdef __TIZEN__
23 #include <arpa/inet.h>
24 #include <sys/socket.h>
25 #include <netdb.h>
26 #include <ifaddrs.h>
27 #include <unistd.h>
28 #include <pthread.h>
29 #endif //#ifdef __TIZEN__
30 #include <stdio.h>
31 #include <stdlib.h>
32
33 #ifdef __TIZEN__
34 #include "cableserver.h"
35 #include "cableclient.h"
36 #include "cacommon.h"
37 #else // __ARDUINO__
38 #include "BLEAdapterArduino.h"
39 #include "caadapterutils.h"
40 #endif //#ifdef __TIZEN__
41 #define CALEADAPTER_TAG "CA_BLE_ADAPTER"
42
43 static CANetworkChangeCallback gNetworkCallback = NULL;
44 static char gLocalBLEAddress[16] =
45 { 0, };
46
47 static int gIsServer = 0;
48
49 int CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback);
50
51 #ifdef __TIZEN__
52 int CALEDeviceStateChangedCb(int result, bt_adapter_state_e adapter_state, void *user_data);
53 #endif //#ifdef __TIZEN__
54
55 pthread_mutex_t gBleIsServerMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
56
57 pthread_mutex_t gBleNetworkCbMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
58
59 pthread_mutex_t gBleLocalAddressMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
60
61 CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback,
62         CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback)
63 {
64     OCLog(DEBUG, CALEADAPTER_TAG, "IN");
65
66     //Input validation
67     VERIFY_NON_NULL(registerCallback, NULL, "RegisterConnectivity callback is null");
68     VERIFY_NON_NULL(reqRespCallback, NULL, "PacketReceived Callback is null");
69     VERIFY_NON_NULL(netCallback, NULL, "NetworkChange Callback is null");
70
71 #ifdef __TIZEN__
72
73     int ret = bt_initialize();
74     if (0 != ret)
75     {
76         OCLog(ERROR, CALEADAPTER_TAG, "bt_initialize failed!");
77         return CA_STATUS_FAILED;
78     }
79
80 #endif //#ifdef __TIZEN__
81     CASetBLEReqRescallback(reqRespCallback);
82     CALERegisterNetworkNotifications(netCallback);
83
84     CAConnectivityHandler_t connHandler;
85     connHandler.startListenServer = CAStartLEListeningServer;
86     connHandler.startDiscoverServer = CAStartLEDiscoveryServer;
87     connHandler.sendData = CASendLEUnicastData;
88     connHandler.sendDataToAll = CASendLEMulticastData;
89     connHandler.startNotifyServer = CAStartLENotifyServer;
90     connHandler.sendNotification = CASendLENotification;
91     connHandler.GetnetInfo = CAGetLEInterfaceInformation;
92     connHandler.readData = CAReadLEData;
93     connHandler.terminate = CATerminateLE;
94     registerCallback(connHandler, CA_LE);
95
96     OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
97
98     return CA_STATUS_OK;
99 }
100
101 void CATerminateLE()
102 {
103     OCLog(DEBUG, CALEADAPTER_TAG, "IN");
104
105     CASetBLEReqRescallback(NULL);
106     CALERegisterNetworkNotifications(NULL);
107
108     pthread_mutex_lock(&gBleIsServerMutex);
109     if (gIsServer == 1)
110     {
111         CAStopBleGattServer();
112     }
113     else
114     {
115         CAStopBLEGattClient();
116     }
117     pthread_mutex_unlock(&gBleIsServerMutex);
118
119     OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
120     return;
121 }
122
123 void CALEServerInitThreadFunc(void *param)
124 {
125     OCLog(DEBUG, CALEADAPTER_TAG, "[CALEServerInitThreadFunc]IN");
126
127     CAStartBleGattServer();
128
129     OCLog(DEBUG, CALEADAPTER_TAG, "[CALEServerInitThreadFunc] OUT");
130 }
131
132 void CALEClientInitThreadFunc(void *param)
133 {
134     OCLog(DEBUG, CALEADAPTER_TAG, "[CALEClientInitThreadFunc]IN");
135
136     CAStartBLEGattClient();
137
138     OCLog(DEBUG, CALEADAPTER_TAG, "[CALEClientInitThreadFunc] OUT");
139 }
140
141 CAResult_t CAStartLEListeningServer()
142 {
143     OCLog(DEBUG, CALEADAPTER_TAG, "IN");
144
145     int init_pthread_status = 0;
146     pthread_t pthread_id = 0;
147     pthread_attr_t attr;
148     pthread_attr_init(&attr);
149     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
150
151     init_pthread_status = pthread_create(&pthread_id, &attr, CALEServerInitThreadFunc, NULL);
152
153     if (init_pthread_status != 0)
154     {
155         OCLog(ERROR, CALEADAPTER_TAG, "pthread_create failed!");
156         return CA_STATUS_FAILED;
157     }
158
159     OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
160     pthread_mutex_lock(&gBleIsServerMutex);
161     gIsServer = 1;
162     pthread_mutex_unlock(&gBleIsServerMutex);
163     return CA_STATUS_OK;
164 }
165
166 CAResult_t CAStartLEDiscoveryServer()
167 {
168     OCLog(DEBUG, CALEADAPTER_TAG, "IN");
169
170     int init_pthread_status = 0;
171     pthread_t pthread_id = 0;
172     pthread_attr_t attr;
173     pthread_attr_init(&attr);
174     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
175
176     init_pthread_status = pthread_create(&pthread_id, &attr, CALEClientInitThreadFunc, NULL);
177
178     if (init_pthread_status != 0)
179     {
180         OCLog(ERROR, CALEADAPTER_TAG, "pthread_create failed!");
181         return CA_STATUS_FAILED;
182     }
183
184     OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
185     pthread_mutex_lock(&gBleIsServerMutex);
186     gIsServer = 0;
187     pthread_mutex_unlock(&gBleIsServerMutex);
188     return CA_STATUS_OK;
189 }
190
191 CAResult_t CAStartLENotifyServer()
192 {
193     OCLog(DEBUG, CALEADAPTER_TAG, "IN");
194
195     OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
196
197     return CA_STATUS_OK;
198 }
199
200 uint32_t CASendLENotification(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen)
201 {
202     OCLog(DEBUG, CALEADAPTER_TAG, "IN");
203
204     OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
205
206     return CA_STATUS_OK;
207 }
208
209 CAResult_t CAReadLEData()
210 {
211     OCLog(DEBUG, CALEADAPTER_TAG, "IN");
212
213     OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
214
215     return CA_STATUS_OK;
216 }
217
218 uint32_t CASendLEUnicastData(const CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen)
219 {
220     OCLog(DEBUG, CALEADAPTER_TAG, "IN");
221
222     //Input validation
223     VERIFY_NON_NULL(endpoint, NULL, "Remote endpoint is null");
224     VERIFY_NON_NULL(data, NULL, "Data is null");
225
226     CAResult_t result = CA_STATUS_FAILED;
227
228 #ifdef __TIZEN__
229     pthread_mutex_lock(&gBleIsServerMutex);
230     if (gIsServer)
231     {
232         result = CAUpdateCharacteristicsInGattServer(data, dataLen);
233         if (CA_STATUS_OK != result)
234         {
235             OCLogv(ERROR, CALEADAPTER_TAG,
236                     "[SendLEUnicastData] sending unicast data to [%s] failed\n", endpoint->addressInfo.BT.btMacAddress);
237             pthread_mutex_unlock(&gBleIsServerMutex);
238             return 0;
239         }
240     }
241     else
242     {
243
244         result = CAUpdateCharacteristicsToGattServer(endpoint->addressInfo.BT.btMacAddress, data,
245                 dataLen, UNICAST, 0);
246         if (CA_STATUS_OK != result)
247         {
248             OCLogv(ERROR, CALEADAPTER_TAG,
249                     "[SendLEUnicastData] sending unicast data to [%s] failed\n", endpoint->addressInfo.BT.btMacAddress);
250             pthread_mutex_unlock(&gBleIsServerMutex);
251             return 0;
252         }
253     }
254     pthread_mutex_unlock(&gBleIsServerMutex);
255 #else
256     char *tempPath = "temp_path";
257     updateCharacteristicsInGattServer(tempPath, (char *) data, dataLen);
258 #endif //#ifdef __TIZEN__
259     OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
260
261     return dataLen;
262 }
263
264 uint32_t CASendLEMulticastData(void *data, uint32_t dataLen)
265 {
266     OCLog(DEBUG, CALEADAPTER_TAG, "IN");
267
268     //Input validation
269     VERIFY_NON_NULL(data, NULL, "Data is null");
270
271     if (0 >= dataLen)
272     {
273         OCLog(ERROR, CALEADAPTER_TAG, "Invalid Parameter");
274         return 0;
275     }
276
277     CAResult_t result = CA_STATUS_FAILED;
278 #ifdef __TIZEN__
279     pthread_mutex_lock(&gBleIsServerMutex);
280     if (gIsServer)
281     {
282         result = CAUpdateCharacteristicsInGattServer(data, dataLen);
283         if (CA_STATUS_OK != result)
284         {
285             OCLogv(ERROR, CALEADAPTER_TAG,
286                     "[CASendLEMulticastData] updating data in server is failed");
287             pthread_mutex_unlock(&gBleIsServerMutex);
288             return 0;
289         }
290     }
291     else
292     {
293         result = CAUpdateCharacteristicsToAllGattServers(data, dataLen);
294         if (CA_STATUS_OK != result)
295         {
296             OCLogv(ERROR, CALEADAPTER_TAG,
297                     "[SendLEMulticastDataToAll] multicasting data to servers failed" );
298             pthread_mutex_unlock(&gBleIsServerMutex);
299             return 0;
300         }
301     }
302     pthread_mutex_unlock(&gBleIsServerMutex);
303 #else
304     char *tempPath = "temp_path";
305     updateCharacteristicsInGattServer(tempPath, (char *) data, dataLen);
306 #endif //#ifdef __TIZEN__
307     OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
308     return dataLen;
309 }
310
311 CAResult_t CAGetLEInterfaceInformation(CALocalConnectivityt_t **info, uint32_t *size)
312 {
313     OCLog(DEBUG, CALEADAPTER_TAG, "IN");
314
315     VERIFY_NON_NULL(info, NULL, "CALocalConnectivity info is null");
316
317 #ifdef OIC_ARDUINODUE
318     OCLog(DEBUG, CALEADAPTER_TAG, "Info from ARDUINO");
319     //1: call corresponding Arduino API
320 #endif
321
322 #if __TIZEN__
323
324     char *local_address = NULL;
325
326     bt_adapter_get_address(&local_address);
327     if (NULL == local_address)
328     {
329         OCLog(ERROR, CALEADAPTER_TAG, "Get local bt adapter address failed");
330         return CA_STATUS_FAILED;
331     }
332
333 #endif //#if ARDUINODUE
334     *size = 0;
335     (*info) = (CALocalConnectivityt_t *) OICMalloc(sizeof(CALocalConnectivityt_t));
336     if (NULL == (*info))
337     {
338         OCLog(ERROR, CALEADAPTER_TAG, "Malloc failure!");
339         return CA_STATUS_FAILED;
340     }
341     memset((*info), 0x0, sizeof(CALocalConnectivityt_t));
342
343     strncpy((*info)->addressInfo.BT.btMacAddress, local_address, strlen(local_address));
344     pthread_mutex_lock(&gBleLocalAddressMutex);
345     strncpy(gLocalBLEAddress, local_address, sizeof(gLocalBLEAddress));
346     pthread_mutex_unlock(&gBleLocalAddressMutex);
347
348     (*info)->type = CA_LE;
349     *size = 1;
350     OICFree(local_address);
351
352     OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
353     return CA_STATUS_OK;
354 }
355
356 int CALERegisterNetworkNotifications(CANetworkChangeCallback netCallback)
357 {
358     OCLog(DEBUG, CALEADAPTER_TAG, "IN");
359
360     pthread_mutex_lock(&gBleNetworkCbMutex);
361     gNetworkCallback = netCallback;
362     pthread_mutex_unlock(&gBleNetworkCbMutex);
363     int ret = 0;
364 #ifdef __TIZEN__
365     if (netCallback)
366     {
367         ret = bt_adapter_set_state_changed_cb(CALEDeviceStateChangedCb, NULL);
368         if(ret != 0)
369         {
370             OCLog(ERROR, CALEADAPTER_TAG, "bt_adapter_set_state_changed_cb failed!");
371         }
372     }
373     else
374     {
375         ret = bt_adapter_unset_state_changed_cb();
376         if(ret != 0)
377         {
378             OCLog(ERROR, CALEADAPTER_TAG, "bt_adapter_set_state_changed_cb failed!");
379         }
380     }
381 #endif //#ifdef __TIZEN__
382     OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
383     return CA_STATUS_OK;
384 }
385
386 #ifdef __TIZEN__
387
388 int CALEDeviceStateChangedCb(int result, bt_adapter_state_e adapter_state, void *user_data)
389 {
390     OCLog(DEBUG, CALEADAPTER_TAG, "IN");
391
392     bt_adapter_state_e btAdaptorState = BT_ADAPTER_DISABLED;
393     if (BT_ADAPTER_ENABLED == adapter_state)
394     {
395         btAdaptorState = BT_ADAPTER_ENABLED;
396     }
397
398     CALocalConnectivityt_t localEndpoint;
399
400     pthread_mutex_lock(&gBleLocalAddressMutex);
401     strncpy(localEndpoint.addressInfo.BT.btMacAddress, gLocalBLEAddress, strlen(gLocalBLEAddress));
402     pthread_mutex_unlock(&gBleLocalAddressMutex);
403
404     pthread_mutex_lock(&gBleNetworkCbMutex);
405     if(NULL != gNetworkCallback)
406     {
407         gNetworkCallback(&localEndpoint, adapter_state);
408     }
409     else
410     {
411         OCLog(ERROR, CALEADAPTER_TAG, "gNetworkCallback is NULL");
412     }
413     pthread_mutex_unlock(&gBleNetworkCbMutex);
414     OCLog(DEBUG, CALEADAPTER_TAG, "OUT");
415     return CA_STATUS_OK;
416 }
417 #endif //#ifdef OIC_TIZEN