tizen 2.3 release
[framework/connectivity/mobileap-agent.git] / src / mobileap_bluetooth.c
1 /*
2  * mobileap-agent
3  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <stdio.h>
19 #include <glib.h>
20 #include <dbus/dbus.h>
21 #include <dbus/dbus-glib.h>
22 #include <dbus/dbus-glib-lowlevel.h>
23 #include <bluetooth.h>
24
25 #include "mobileap_softap.h"
26 #include "mobileap_common.h"
27 #include "mobileap_bluetooth.h"
28 #include "mobileap_handler.h"
29 #include "mobileap_notification.h"
30
31 typedef struct {
32         bt_device_info_s *info;
33         char *intf_name;
34         const in_addr_t intf_ip;
35 } __bt_remote_device_s;
36
37 static __bt_remote_device_s __bt_remote_devices[MOBILE_AP_MAX_BT_STA] = {
38         {NULL, NULL, IP_ADDRESS_BT_1},
39         {NULL, NULL, IP_ADDRESS_BT_2},
40         {NULL, NULL, IP_ADDRESS_BT_3},
41         {NULL, NULL, IP_ADDRESS_BT_4}};
42
43 static DBusGMethodInvocation *g_context = NULL;
44
45 static void __bt_nap_connection_changed(bool connected, const char *remote_address,
46                                 const char *interface_name, void *user_data);
47 static void __bt_adapter_state_changed(int result, bt_adapter_state_e adapter_state, void *user_data);
48 static void __handle_bt_adapter_visibility();
49
50 int __recheck_bt_adapter_timer = 0;
51
52 static __bt_remote_device_s *__find_bt_remote(const char *mac)
53 {
54         int i;
55
56         for (i = 0; i < MOBILE_AP_MAX_BT_STA; i++) {
57                 if (__bt_remote_devices[i].info == NULL)
58                         continue;
59
60                 if (!g_ascii_strcasecmp(__bt_remote_devices[i].info->remote_address, mac))
61                         break;
62         }
63
64         if (i == MOBILE_AP_MAX_BT_STA) {
65                 SERR("Not found : %s\n", mac);
66                 return NULL;
67         }
68
69         return &__bt_remote_devices[i];
70 }
71
72 static __bt_remote_device_s *__add_bt_remote(bt_device_info_s *info, const char *intf_name)
73 {
74         int i;
75
76         for (i = 0; i < MOBILE_AP_MAX_BT_STA; i++) {
77                 if (__bt_remote_devices[i].info == NULL)
78                         break;
79         }
80
81         if (i == MOBILE_AP_MAX_BT_STA) {
82                 ERR("Too many BT devices are connected\n");
83                 return NULL;
84         }
85
86         __bt_remote_devices[i].intf_name = g_strdup(intf_name);
87         if (__bt_remote_devices[i].intf_name == NULL) {
88                 ERR("Memory allocation failed\n");
89                 return NULL;
90         }
91
92         _add_interface_routing(__bt_remote_devices[i].intf_name,
93                         __bt_remote_devices[i].intf_ip);
94         _add_routing_rule(__bt_remote_devices[i].intf_name);
95         __bt_remote_devices[i].info = info;
96
97         return &__bt_remote_devices[i];
98 }
99
100 static gboolean __del_bt_remote(const char *mac)
101 {
102         int i;
103
104         for (i = 0; i < MOBILE_AP_MAX_BT_STA; i++) {
105                 if (__bt_remote_devices[i].info == NULL)
106                         continue;
107
108                 if (!g_ascii_strcasecmp(__bt_remote_devices[i].info->remote_address, mac))
109                         break;
110         }
111
112         if (i == MOBILE_AP_MAX_BT_STA) {
113                 SERR("Not found : %s\n", mac);
114                 return FALSE;
115         }
116
117         _del_routing_rule(__bt_remote_devices[i].intf_name);
118         _del_interface_routing(__bt_remote_devices[i].intf_name,
119                         __bt_remote_devices[i].intf_ip);
120          bt_adapter_free_device_info(__bt_remote_devices[i].info);
121          g_free(__bt_remote_devices[i].intf_name);
122
123          __bt_remote_devices[i].info = NULL;
124          __bt_remote_devices[i].intf_name = NULL;
125
126         return TRUE;
127 }
128
129 static void __del_bt_remote_all(void)
130 {
131         int i;
132
133         for (i = 0; i < MOBILE_AP_MAX_BT_STA; i++) {
134                 if (__bt_remote_devices[i].info) {
135                         bt_adapter_free_device_info(__bt_remote_devices[i].info);
136                         __bt_remote_devices[i].info = NULL;
137                 }
138
139                 if (__bt_remote_devices[i].intf_name) {
140                         _del_routing_rule(__bt_remote_devices[i].intf_name);
141                         _del_interface_routing(__bt_remote_devices[i].intf_name,
142                                 __bt_remote_devices[i].intf_ip);
143                         g_free(__bt_remote_devices[i].intf_name);
144                         __bt_remote_devices[i].intf_name = NULL;
145                 }
146         }
147
148         return;
149 }
150
151 static mobile_ap_error_code_e __init_bt(TetheringObject *obj)
152 {
153         int ret;
154
155         ret = bt_initialize();
156         if (ret != BT_ERROR_NONE) {
157                 ERR("bt_initialize is failed : %d\n", ret);
158                 return MOBILE_AP_ERROR_RESOURCE;
159         }
160
161         ret = bt_adapter_set_state_changed_cb(__bt_adapter_state_changed, (void *)obj);
162         if (ret != BT_ERROR_NONE) {
163                 ERR("bt_adapter_set_state_changed_cb is failed : %d\n", ret);
164                 bt_deinitialize();
165                 return MOBILE_AP_ERROR_RESOURCE;
166         }
167
168         return MOBILE_AP_ERROR_NONE;
169 }
170
171 static void __deinit_bt(void)
172 {
173         int ret;
174
175         ret = bt_adapter_unset_state_changed_cb();
176         if (ret != BT_ERROR_NONE)
177                 ERR("bt_adapter_unset_state_changed_cb is failed : %d\n", ret);
178
179         ret = bt_deinitialize();
180         if (ret != BT_ERROR_NONE)
181                 ERR("bt_deinitialize is failed : %d\n", ret);
182
183         return;
184 }
185
186 static gboolean __is_bt_adapter_on(void)
187 {
188         int ret;
189         bt_adapter_state_e adapter_state = BT_ADAPTER_DISABLED;
190
191         ret = bt_adapter_get_state(&adapter_state);
192         if (ret != BT_ERROR_NONE) {
193                 ERR("bt_adapter_get_state is failed : %d\n", ret);
194                 return FALSE;
195         }
196
197         if (adapter_state == BT_ADAPTER_ENABLED)
198                 return TRUE;
199         else
200                 return FALSE;
201 }
202
203 gboolean __bt_adapter_timeout_cb(gpointer data)
204 {
205         DBG("+\n");
206
207         static int retry_count = 0;
208         if (__is_bt_adapter_on() == TRUE) {
209                 DBG("BT Adapter is enabled by other process \n");
210                 retry_count = 0;
211                 DBG("-\n");
212                 return FALSE;
213         } else {
214                 if (++retry_count >= PS_RECHECK_COUNT_MAX) {
215                         retry_count = 0;
216                         ERR("_enable_bt_tethering() is failed because of bt_adapter_eanbled() failed:n");
217                         _mobileap_clear_state(MOBILE_AP_STATE_BT);
218                         __deinit_bt();
219                         dbus_g_method_return(g_context,
220                                         MOBILE_AP_ENABLE_BT_TETHERING_CFM, MOBILE_AP_ERROR_INTERNAL);
221                         g_context = NULL;
222                         _unblock_device_sleep();
223                         DBG("-\n");
224                         return FALSE;
225                 } else {
226                         DBG("-\n");
227                         return TRUE;
228                 }
229         }
230 }
231
232 static mobile_ap_error_code_e __turn_on_bt_adapter(TetheringObject *obj)
233 {
234         int ret;
235
236         ret = bt_adapter_enable();
237         if (ret == BT_ERROR_NOW_IN_PROGRESS) {
238                 if (__recheck_bt_adapter_timer) {
239                         g_source_remove(__recheck_bt_adapter_timer);
240                 }
241                 __recheck_bt_adapter_timer = g_timeout_add(PS_RECHECK_INTERVAL,
242                                 __bt_adapter_timeout_cb, NULL);
243                 return MOBILE_AP_ERROR_NONE;
244         }
245
246         if (ret != BT_ERROR_NONE && ret != BT_ERROR_ALREADY_DONE) {
247                 ERR("bt_adapter_enable is failed : %d\n", ret);
248                 if (ret == BT_ERROR_PERMISSION_DENIED)
249                         return MOBILE_AP_ERROR_PERMISSION_DENIED;
250                 else
251                         return MOBILE_AP_ERROR_RESOURCE;
252         }
253
254         return MOBILE_AP_ERROR_NONE;
255 }
256
257 static mobile_ap_error_code_e __turn_on_bt_nap(TetheringObject *obj)
258 {
259         int bt_ret = BT_ERROR_NONE;
260
261         bt_ret = bt_nap_set_connection_state_changed_cb(__bt_nap_connection_changed, (void *)obj);
262         if (bt_ret != BT_ERROR_NONE) {
263                 ERR("bt_nap_set_connection_state_changed_cb is failed : %d\n", bt_ret);
264                 return MOBILE_AP_ERROR_RESOURCE;
265         }
266
267         bt_ret = bt_nap_activate();
268         if (bt_ret != BT_ERROR_NONE && bt_ret != BT_ERROR_ALREADY_DONE) {
269                 bt_nap_unset_connection_state_changed_cb();
270                 ERR("bt_nap_activate is failed : %d\n", bt_ret);
271                 if (bt_ret == BT_ERROR_PERMISSION_DENIED)
272                         return MOBILE_AP_ERROR_PERMISSION_DENIED;
273                 else
274                         return MOBILE_AP_ERROR_RESOURCE;
275         }
276
277         return MOBILE_AP_ERROR_NONE;
278 }
279
280 static void __turn_off_bt_nap(void)
281 {
282         int bt_ret;
283
284         bt_ret = bt_nap_disconnect_all();
285         if (bt_ret != BT_ERROR_NONE)
286                 ERR("bt_nap_disconnect_all is failed : %d\n", bt_ret);
287         else
288                 DBG("bt_nap_disconnect_all is called\n");
289
290         bt_ret = bt_nap_unset_connection_state_changed_cb();
291         if (bt_ret != BT_ERROR_NONE)
292                 ERR("bt_nap_unset_connection_state_changed_cb is failed : %d\n", bt_ret);
293
294         return;
295 }
296
297 mobile_ap_error_code_e _enable_bt_tethering(TetheringObject *obj)
298 {
299         mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
300
301         DBG("+\n");
302         if (__recheck_bt_adapter_timer) {
303                 g_source_remove(__recheck_bt_adapter_timer);
304                 __recheck_bt_adapter_timer = 0;
305         }
306
307         if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
308                 ERR("Wi-Fi AP is enabled\n");
309                 return MOBILE_AP_ERROR_RESOURCE;
310         }
311
312         ret = _init_tethering(obj);
313         if (ret != MOBILE_AP_ERROR_NONE) {
314                 return ret;
315         }
316
317         ret = __turn_on_bt_nap(obj);
318         if (ret != MOBILE_AP_ERROR_NONE) {
319                 _deinit_tethering(obj);
320                 return ret;
321         }
322         _delete_timeout_noti();
323         _init_timeout_cb(MOBILE_AP_TYPE_BT, (void *)obj);
324         _start_timeout_cb(MOBILE_AP_TYPE_BT, time(NULL) + TETHERING_CONN_TIMEOUT);
325
326         return ret;
327 }
328
329 mobile_ap_error_code_e _disable_bt_tethering(TetheringObject *obj)
330 {
331         int ret = BT_ERROR_NONE;
332         if (!_mobileap_is_enabled(MOBILE_AP_STATE_BT)) {
333                 ERR("BT tethering has not been enabled\n");
334                 return MOBILE_AP_ERROR_NOT_ENABLED;
335         }
336         ret = bt_adapter_unset_visibility_mode_changed_cb();
337         if (ret != BT_ERROR_NONE)
338                 ERR("bt_adapter_unset_visibility_mode_changed_cb is failed : %d\n", ret);
339
340         _block_device_sleep();
341         if (__is_bt_adapter_on()) {
342                 __turn_off_bt_nap();
343                 __deinit_bt();
344         }
345
346         _remove_station_info_all(MOBILE_AP_TYPE_BT);
347         __del_bt_remote_all();
348         _deinit_timeout_cb(MOBILE_AP_TYPE_BT);
349
350         _deinit_tethering(obj);
351         _mobileap_clear_state(MOBILE_AP_STATE_BT);
352         _unblock_device_sleep();
353
354         return MOBILE_AP_ERROR_NONE;
355 }
356
357
358 static void __bt_nap_connection_changed(bool connected, const char *remote_address, const char *interface_name, void *user_data)
359 {
360         if (remote_address == NULL || interface_name == NULL || user_data == NULL) {
361                 ERR("Invalid param\n");
362                 return;
363         }
364
365         __bt_remote_device_s *remote;
366         bt_device_info_s *info;
367         int ret;
368         int n_station = 0;
369
370         SDBG("Remote address : %s, Interface : %s, %s\n",
371                         remote_address, interface_name,
372                         connected ? "Connected" : "Disconnected");
373
374         if (connected) {
375                 ret = bt_adapter_get_bonded_device_info(remote_address, &info);
376                 if (ret != BT_ERROR_NONE) {
377                         ERR("bt_adapter_get_bonded_device_info is failed : %d\n", ret);
378                         return;
379                 }
380
381                 remote = __add_bt_remote(info, interface_name);
382                 if (remote == NULL) {
383                         ERR("__add_bt_remote is failed\n");
384                          bt_adapter_free_device_info(info);
385                         return;
386                 }
387
388                 ret = _mh_core_set_ip_address(interface_name, remote->intf_ip);
389                 if (ret != MOBILE_AP_ERROR_NONE) {
390                         ERR("Setting ip address error : %d\n", ret);
391                 }
392         } else {
393                 _remove_station_info(remote_address, _slist_find_station_by_mac);
394                 if (__del_bt_remote(remote_address) == FALSE) {
395                         ERR("__del_bt_remote is failed\n");
396                 }
397
398                 _get_station_count((gconstpointer)MOBILE_AP_TYPE_BT,
399                                 _slist_find_station_by_interface, &n_station);
400                 if (n_station == 0)
401                         _start_timeout_cb(MOBILE_AP_TYPE_BT, time(NULL) + TETHERING_CONN_TIMEOUT);
402         }
403
404         return;
405 }
406
407 static void __bt_adapter_state_changed(int result, bt_adapter_state_e adapter_state, void *user_data)
408 {
409         if (user_data == NULL) {
410                 ERR("Invalid param\n");
411                 return;
412         }
413
414         DBG("+\n");
415
416         if (!_mobileap_is_enabled(MOBILE_AP_STATE_BT))
417                 return;
418
419         int ret = MOBILE_AP_ERROR_RESOURCE;
420         TetheringObject *obj = (TetheringObject *)user_data;
421
422         if (result != BT_ERROR_NONE) {
423                 ERR("BT Adapter operation is failed : %d\n", result);
424                 goto FAIL;
425         }
426
427         SDBG("BT Adapter is %s\n", adapter_state == BT_ADAPTER_ENABLED ?
428                         "enabled" : "disabled");
429         if (adapter_state == BT_ADAPTER_DISABLED) {
430                 _disable_bt_tethering(obj);
431                 _emit_mobileap_dbus_signal(obj, E_SIGNAL_BT_TETHER_OFF,
432                                 SIGNAL_MSG_NOT_AVAIL_INTERFACE);
433                 return;
434         } else {
435                 ret = _enable_bt_tethering(obj);
436                 if (ret != MOBILE_AP_ERROR_NONE) {
437                         ERR("_enable_bt_tethering() is failed : %d\n", ret);
438                         __deinit_bt();
439                         goto FAIL;
440                 }
441
442                 _emit_mobileap_dbus_signal(obj, E_SIGNAL_BT_TETHER_ON, NULL);
443                 dbus_g_method_return(g_context,
444                                 MOBILE_AP_ENABLE_BT_TETHERING_CFM, ret);
445                 __handle_bt_adapter_visibility();
446                 g_context = NULL;
447                 _unblock_device_sleep();
448
449                 return;
450         }
451
452 FAIL:
453         dbus_g_method_return(g_context,
454                         MOBILE_AP_ENABLE_BT_TETHERING_CFM, ret);
455         g_context = NULL;
456         _mobileap_clear_state(MOBILE_AP_STATE_BT);
457         _unblock_device_sleep();
458
459         return;
460 }
461
462 void _bt_get_remote_device_name(TetheringObject *obj, const char *mac, char **name)
463 {
464         if (obj == NULL || mac == NULL || name == NULL) {
465                 ERR("Invalid param\n");
466                 return;
467         }
468
469         __bt_remote_device_s *remote = NULL;
470
471         remote = __find_bt_remote(mac);
472         if (remote == NULL)
473                 return;
474
475         *name = g_strdup(remote->info->remote_name);
476         if (*name == NULL) {
477                 ERR("Memory allocation failed\n");
478                 return;
479         }
480
481         return;
482 }
483
484 static void __bt_adapter_visibility_changed_cb(int result,
485                                 bt_adapter_visibility_mode_e visibility_mode, void *user_data)
486 {
487         DBG("+\n");
488
489         int ret;
490         int duration;
491         bt_adapter_visibility_mode_e mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
492
493         ret = bt_adapter_get_visibility(&mode, &duration);
494         if (ret != BT_ERROR_NONE) {
495                 ERR("bt_adapter_get_visibility is failed 0x[%X]\n", ret);
496         }
497
498         if (mode == BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE) {
499                         ERR("_launch_toast_popup() is failed\n");
500         }
501
502         DBG("-\n");
503 }
504
505 static void __handle_bt_adapter_visibility()
506 {
507         DBG("+\n");
508
509         int ret;
510         int duration;
511         bt_adapter_visibility_mode_e mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
512
513         ret = bt_adapter_get_visibility(&mode, &duration);
514         if (ret != BT_ERROR_NONE) {
515                 ERR("bt_adapter_get_visibility is failed 0x[%X]\n", ret);
516         }
517
518         if (mode == BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE) {
519                 ret = bt_adapter_set_visibility(BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE, 120);
520                 if (ret != BT_ERROR_NONE) {
521                         ERR("bt_adapter_set_visibility is failed 0x[%X]\n", ret);
522                 }
523         }
524         bt_adapter_set_visibility_mode_changed_cb(__bt_adapter_visibility_changed_cb, NULL);
525         DBG("-\n");
526 }
527 gboolean tethering_enable_bt_tethering(TetheringObject *obj,
528                 DBusGMethodInvocation *context)
529 {
530         mobile_ap_error_code_e ret;
531         gboolean ret_val = FALSE;
532
533         DBG("+\n");
534
535         g_assert(obj != NULL);
536         g_assert(context != NULL);
537
538         if (g_context) {
539                 DBG("It is turnning on\n");
540                 dbus_g_method_return(context,
541                                 MOBILE_AP_ENABLE_BT_TETHERING_CFM,
542                                 MOBILE_AP_ERROR_IN_PROGRESS);
543                 return FALSE;
544         }
545
546         g_context = context;
547
548         _block_device_sleep();
549
550         ret = __init_bt(obj);
551         if (ret != MOBILE_AP_ERROR_NONE)
552                 goto DONE;
553
554         if (!_mobileap_set_state(MOBILE_AP_STATE_BT)) {
555                 ret = MOBILE_AP_ERROR_RESOURCE;
556                 __deinit_bt();
557                 goto DONE;
558         }
559
560         if (__is_bt_adapter_on() == FALSE) {
561                 DBG("Bluetooth is deactivated\n");
562                 if (__turn_on_bt_adapter(obj) != MOBILE_AP_ERROR_NONE) {
563                         ERR("__turn_on_bt_adapter is failed\n");
564                         ret = MOBILE_AP_ERROR_INTERNAL;
565                         _mobileap_clear_state(MOBILE_AP_STATE_BT);
566                         __deinit_bt();
567                         goto DONE;
568                 }
569
570                 return TRUE;
571         }
572
573         ret = _enable_bt_tethering(obj);
574         if (ret != MOBILE_AP_ERROR_NONE) {
575                 ERR("_enable_bt_tethering() is failed : %d\n", ret);
576                 _mobileap_clear_state(MOBILE_AP_STATE_BT);
577                 __deinit_bt();
578         } else {
579                 _emit_mobileap_dbus_signal(obj, E_SIGNAL_BT_TETHER_ON, NULL);
580                 __handle_bt_adapter_visibility();
581                 ret_val = TRUE;
582         }
583
584 DONE:
585         dbus_g_method_return(g_context,
586                         MOBILE_AP_ENABLE_BT_TETHERING_CFM, ret);
587         g_context = NULL;
588
589         _unblock_device_sleep();
590
591         return ret_val;
592 }
593
594 gboolean tethering_disable_bt_tethering(TetheringObject *obj,
595                 DBusGMethodInvocation *context)
596 {
597         mobile_ap_error_code_e ret;
598
599         DBG("+\n");
600
601         g_assert(obj != NULL);
602         g_assert(context != NULL);
603
604         ret = _disable_bt_tethering(obj);
605         if (ret != MOBILE_AP_ERROR_NONE) {
606                 dbus_g_method_return(context, MOBILE_AP_DISABLE_BT_TETHERING_CFM, ret);
607                 return FALSE;
608         }
609
610         _emit_mobileap_dbus_signal(obj, E_SIGNAL_BT_TETHER_OFF, NULL);
611         dbus_g_method_return(context, MOBILE_AP_DISABLE_BT_TETHERING_CFM, ret);
612         return TRUE;
613 }
614
615 gboolean _is_trying_bt_operation(void)
616 {
617         return (g_context ? TRUE : FALSE);
618 }