Fix in LE adapter to return CA_STATUS_OK when BT is not enabled
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / tizen / calenwmonitor.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
21 #include "caleinterface.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <glib.h>
27 #include <arpa/inet.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31
32 #include <bluetooth.h>
33 #include <bluetooth_internal.h>
34 #include <bluetooth_type.h>
35
36 #include "camutex.h"
37 #include "caleadapter.h"
38 #include "caadapterutils.h"
39 #include "oic_string.h"
40 #include "oic_malloc.h"
41
42 /**
43  * Logging tag for module name
44  */
45 #define TAG "OIC_CA_LE_MONITOR"
46
47 #define MICROSECS_PER_SEC 1000000
48
49 static uint64_t const INITIALIZE_TIMEOUT = 1 * MICROSECS_PER_SEC;
50
51 static GMainLoop *g_mainloop = NULL;
52 static ca_thread_pool_t g_threadPoolHandle = NULL;
53
54 /**
55  * Maintains the callback to be notified on device state changed.
56  */
57 static CALEDeviceStateChangedCallback g_bleDeviceStateChangedCallback = NULL;
58
59 /**
60  * Maintains the callback to be notified on device state changed.
61  */
62 static CALEConnectionStateChangedCallback g_bleConnectionStateChangedCallback = NULL;
63
64 /**
65  * Mutex to synchronize access to the deviceStateChanged Callback when the state
66  *           of the LE adapter gets change.
67  */
68 static ca_mutex g_bleDeviceStateChangedCbMutex = NULL;
69
70 /**
71  * Mutex to synchronize access to the ConnectionStateChanged Callback when the state
72  * of the LE adapter gets change.
73  */
74 static ca_mutex g_bleConnectionStateChangedCbMutex = NULL;
75
76 /**
77  * Mutex to synchronize access to
78  */
79 static ca_mutex g_btinitializeMutex = NULL;
80
81 /**
82  * Condition for gmainloop to run.
83  */
84 static ca_cond g_initializeCond = NULL;
85
86 /**
87  * Flag to check if BT stack is initialised.
88  */
89 static bool g_isBTStackInitialised = false;
90
91 /**
92 * This is the callback which will be called when the adapter state gets changed.
93 *
94 * @param result         [IN] Result of the query done to the platform.
95 * @param adapter_state  [IN] State of the LE adapter.
96 * @param user_data      [IN] User data passed by the caller when querying for the state changed cb.
97 *
98 * @return  None.
99 */
100 void CALEAdapterStateChangedCb(int result, bt_adapter_state_e adapter_state,
101                                void *user_data);
102
103 /**
104 * This is the callback which will be called when the connection state gets changed.
105 *
106 * @param result         [IN] Result of the query done to the platform.
107 * @param connected      [IN] State of connection.
108 * @param remoteAddress  [IN] LE address of the device to be notified.
109 * @param user_data      [IN] User data passed by the caller when querying for the state changed cb.
110 *
111 * @return  None.
112 */
113 void CALENWConnectionStateChangedCb(int result, bool connected,
114                                     const char *remoteAddress, void *userData);
115
116 void CALEMainLoopThread(void *param)
117 {
118     OIC_LOG(DEBUG, TAG, "IN");
119
120     int ret = bt_initialize();
121     if (BT_ERROR_NONE != ret)
122     {
123         OIC_LOG(ERROR, TAG, "bt_initialize failed");
124         return;
125     }
126
127     bt_adapter_state_e adapterState = BT_ADAPTER_DISABLED;
128     //Get Bluetooth adapter state
129     ret = bt_adapter_get_state(&adapterState);
130
131     if (BT_ERROR_NONE != ret && BT_ADAPTER_ENABLED == adapterState)
132     {
133         ret = bt_adapter_set_visibility(BT_ADAPTER_VISIBILITY_MODE_GENERAL_DISCOVERABLE, 0);
134         if (BT_ERROR_NONE != ret)
135         {
136             OIC_LOG(ERROR, TAG, "bt_adapter_set_visibility failed");
137             return;
138         }
139     }
140
141     ret = bt_adapter_set_state_changed_cb(CALEAdapterStateChangedCb, NULL);
142     if (BT_ERROR_NONE != ret)
143     {
144         OIC_LOG(DEBUG, TAG, "bt_adapter_set_state_changed_cb failed");
145         return;
146     }
147
148     ret = bt_gatt_set_connection_state_changed_cb(CALENWConnectionStateChangedCb, NULL);
149     if (BT_ERROR_NONE != ret)
150     {
151         OIC_LOG_V(ERROR, TAG,
152                   "bt_gatt_set_connection_state_changed_cb has failed");
153         return;
154     }
155
156     g_mainloop = g_main_loop_new(g_main_context_default(), FALSE);
157
158     ca_mutex_lock(g_btinitializeMutex);
159     g_isBTStackInitialised = true;
160     ca_mutex_unlock(g_btinitializeMutex);
161     ca_cond_signal(g_initializeCond);
162
163     // Run gmainloop to handle the events from bt stack
164     g_main_loop_run(g_mainloop);
165     OIC_LOG(DEBUG, TAG, "OUT");
166 }
167
168 CAResult_t CAInitializeLENetworkMonitor()
169 {
170     OIC_LOG(DEBUG, TAG, "IN");
171
172     if (NULL == g_bleDeviceStateChangedCbMutex)
173     {
174         g_bleDeviceStateChangedCbMutex = ca_mutex_new();
175         if (NULL == g_bleDeviceStateChangedCbMutex)
176         {
177             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
178             return CA_STATUS_FAILED;
179         }
180     }
181
182     if (NULL == g_bleConnectionStateChangedCbMutex)
183     {
184         g_bleConnectionStateChangedCbMutex = ca_mutex_new();
185         if (NULL == g_bleConnectionStateChangedCbMutex)
186         {
187             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
188             ca_mutex_free(g_bleDeviceStateChangedCbMutex);
189             return CA_STATUS_FAILED;
190         }
191     }
192
193     if (NULL == g_btinitializeMutex)
194     {
195         g_btinitializeMutex = ca_mutex_new();
196         if (NULL == g_btinitializeMutex)
197         {
198             OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
199             ca_mutex_free(g_bleDeviceStateChangedCbMutex);
200             ca_mutex_free(g_bleConnectionStateChangedCbMutex);
201             return CA_STATUS_FAILED;
202         }
203     }
204
205     if (NULL == g_initializeCond)
206     {
207         g_initializeCond = ca_cond_new();
208         if (NULL == g_initializeCond)
209         {
210             OIC_LOG(ERROR, TAG, "ca_cond_new failed");
211             ca_mutex_free(g_bleDeviceStateChangedCbMutex);
212             ca_mutex_free(g_bleConnectionStateChangedCbMutex);
213             ca_mutex_free(g_btinitializeMutex);
214             return CA_STATUS_FAILED;
215         }
216     }
217     OIC_LOG(DEBUG, TAG, "OUT");
218
219     return CA_STATUS_OK;
220 }
221
222 void CATerminateLENetworkMonitor()
223 {
224     OIC_LOG(DEBUG, TAG, "IN");
225
226     ca_mutex_free(g_bleDeviceStateChangedCbMutex);
227     g_bleDeviceStateChangedCbMutex = NULL;
228
229     ca_mutex_free(g_bleConnectionStateChangedCbMutex);
230     g_bleConnectionStateChangedCbMutex = NULL;
231
232     ca_mutex_free(g_btinitializeMutex);
233     g_btinitializeMutex = NULL;
234
235     ca_cond_free(g_initializeCond);
236     g_initializeCond = NULL;
237     OIC_LOG(DEBUG, TAG, "OUT");
238 }
239
240 CAResult_t CAInitializeLEAdapter(const ca_thread_pool_t threadPool)
241 {
242     OIC_LOG(DEBUG, TAG, "IN");
243     g_threadPoolHandle = threadPool;
244     OIC_LOG(DEBUG, TAG, "OUT");
245     return CA_STATUS_OK;
246 }
247
248 CAResult_t CAStartLEAdapter()
249 {
250     OIC_LOG(DEBUG, TAG, "IN");
251
252     if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CALEMainLoopThread, (void *) NULL))
253     {
254         OIC_LOG(ERROR, TAG, "Failed to create thread!");
255         return CA_STATUS_FAILED;
256     }
257
258     OIC_LOG(DEBUG, TAG, "OUT");
259     return CA_STATUS_OK;
260 }
261
262 CAResult_t CAStopLEAdapter()
263 {
264
265     int ret = bt_adapter_unset_state_changed_cb();
266     if (BT_ERROR_NONE != ret)
267     {
268         OIC_LOG(DEBUG, TAG, "bt_adapter_unset_state_changed_cb failed");
269         return CA_STATUS_FAILED;
270     }
271
272     ret = bt_deinitialize();
273     if (BT_ERROR_NONE != ret)
274     {
275         OIC_LOG(ERROR, TAG, "bt_deinitialize failed");
276         return CA_STATUS_FAILED;
277     }
278
279     if (g_mainloop)
280     {
281         g_main_loop_quit(g_mainloop);
282     }
283     return CA_STATUS_OK;
284 }
285
286 CAResult_t CAGetLEAdapterState()
287 {
288     OIC_LOG(DEBUG, TAG, "IN");
289
290     ca_mutex_lock(g_btinitializeMutex);
291     if (!g_isBTStackInitialised)
292     {
293         OIC_LOG(INFO, TAG, "Wait for BT initialization");
294         CAWaitResult_t ret = ca_cond_wait_for(g_initializeCond, g_btinitializeMutex,
295                                               INITIALIZE_TIMEOUT);
296         if (CA_WAIT_TIMEDOUT == ret)
297         {
298             OIC_LOG(ERROR, TAG, "Timeout before BT initialize");
299             ca_mutex_unlock(g_btinitializeMutex);
300             return CA_STATUS_FAILED;
301         }
302     }
303     ca_mutex_unlock(g_btinitializeMutex);
304
305     bt_adapter_state_e adapterState = BT_ADAPTER_DISABLED;
306
307     //Get Bluetooth adapter state
308     int ret = bt_adapter_get_state(&adapterState);
309     if (BT_ERROR_NONE != ret)
310     {
311         OIC_LOG_V(ERROR, TAG, "Bluetooth get state failed!, error num [%x]",
312                   ret);
313         return CA_STATUS_FAILED;
314     }
315
316     if (BT_ADAPTER_ENABLED != adapterState)
317     {
318         OIC_LOG(DEBUG, TAG, "BT Adapter is not enabled");
319         return CA_ADAPTER_NOT_ENABLED;
320     }
321
322     OIC_LOG(DEBUG, TAG, "OUT");
323     return CA_STATUS_OK;
324 }
325
326 CAResult_t CAGetLEAddress(char **local_address)
327 {
328     OIC_LOG(DEBUG, TAG, "IN");
329
330     VERIFY_NON_NULL(local_address, TAG, "local_address is null")
331
332     char *address = NULL;
333
334     int ret = bt_adapter_get_address(&address);
335     if (BT_ERROR_NONE != ret || !address)
336     {
337         OIC_LOG_V(ERROR, TAG, "bt_adapter_get_address failed!, error num [%x]",
338                   ret);
339         return CA_STATUS_FAILED;
340     }
341
342     OIC_LOG_V(DEBUG, TAG, "bd address[%s]", address);
343
344     *local_address = address;
345
346     OIC_LOG(DEBUG, TAG, "OUT");
347
348     return CA_STATUS_OK;
349 }
350
351 CAResult_t CASetLEAdapterStateChangedCb(CALEDeviceStateChangedCallback callback)
352 {
353     OIC_LOG(DEBUG, TAG, "IN");
354     ca_mutex_lock(g_bleDeviceStateChangedCbMutex);
355     g_bleDeviceStateChangedCallback = callback;
356     ca_mutex_unlock(g_bleDeviceStateChangedCbMutex);
357     OIC_LOG(DEBUG, TAG, "OUT");
358     return CA_STATUS_OK;
359 }
360
361 CAResult_t CAUnSetLEAdapterStateChangedCb()
362 {
363     OIC_LOG(DEBUG, TAG, "IN");
364     ca_mutex_lock(g_bleDeviceStateChangedCbMutex);
365     g_bleDeviceStateChangedCallback = NULL;
366     ca_mutex_unlock(g_bleDeviceStateChangedCbMutex);
367     OIC_LOG(DEBUG, TAG, "OUT");
368     return CA_STATUS_OK;
369 }
370
371 CAResult_t CASetLENWConnectionStateChangedCb(CALEConnectionStateChangedCallback callback)
372 {
373     OIC_LOG(DEBUG, TAG, "IN");
374     ca_mutex_lock(g_bleConnectionStateChangedCbMutex);
375     g_bleConnectionStateChangedCallback = callback;
376     ca_mutex_unlock(g_bleConnectionStateChangedCbMutex);
377     OIC_LOG(DEBUG, TAG, "OUT");
378     return CA_STATUS_OK;
379 }
380
381 CAResult_t CAUnsetLENWConnectionStateChangedCb()
382 {
383     OIC_LOG(DEBUG, TAG, "IN");
384     ca_mutex_lock(g_bleConnectionStateChangedCbMutex);
385     g_bleConnectionStateChangedCallback = NULL;
386     ca_mutex_unlock(g_bleConnectionStateChangedCbMutex);
387     OIC_LOG(DEBUG, TAG, "OUT");
388     return CA_STATUS_OK;
389 }
390
391 void CALEAdapterStateChangedCb(int result, bt_adapter_state_e adapter_state,
392                                           void *user_data)
393 {
394     OIC_LOG(DEBUG, TAG, "IN");
395
396     ca_mutex_lock(g_bleDeviceStateChangedCbMutex);
397
398     if (NULL == g_bleDeviceStateChangedCallback)
399     {
400         OIC_LOG(ERROR, TAG, "g_bleDeviceStateChangedCallback is NULL!");
401         ca_mutex_unlock(g_bleDeviceStateChangedCbMutex);
402         return;
403     }
404
405     if (BT_ADAPTER_DISABLED == adapter_state)
406     {
407         OIC_LOG(DEBUG, TAG, "Adapter is disabled");
408         g_bleDeviceStateChangedCallback(CA_ADAPTER_DISABLED);
409         ca_mutex_unlock(g_bleDeviceStateChangedCbMutex);
410         return;
411     }
412
413     OIC_LOG(DEBUG, TAG, "Adapter is Enabled");
414
415     int ret = bt_adapter_set_visibility(BT_ADAPTER_VISIBILITY_MODE_GENERAL_DISCOVERABLE, 0);
416     if (BT_ERROR_NONE != ret)
417     {
418         OIC_LOG(ERROR, TAG, "bt_adapter_set_visibility failed");
419         return;
420     }
421
422     g_bleDeviceStateChangedCallback(CA_ADAPTER_ENABLED);
423     ca_mutex_unlock(g_bleDeviceStateChangedCbMutex);
424
425     OIC_LOG(DEBUG, TAG, "OUT");
426 }
427
428 void CALENWConnectionStateChangedCb(int result, bool connected,
429                                     const char *remoteAddress, void *userData)
430 {
431     OIC_LOG(DEBUG, TAG, "IN");
432
433     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL");
434
435     ca_mutex_lock(g_bleConnectionStateChangedCbMutex);
436     char *addr = OICStrdup(remoteAddress);
437     if (NULL == addr)
438     {
439         OIC_LOG(ERROR, TAG, "addr is NULL");
440         ca_mutex_unlock(g_bleConnectionStateChangedCbMutex);
441         return;
442     }
443     g_bleConnectionStateChangedCallback(CA_ADAPTER_GATT_BTLE, addr, connected);
444     OICFree(addr);
445     ca_mutex_unlock(g_bleConnectionStateChangedCbMutex);
446
447     OIC_LOG(DEBUG, TAG, "OUT");
448 }