Merge "Apply actd for edutm mode" into tizen
[platform/core/connectivity/bluetooth-frwk.git] / bt-core / bt-core-adapter.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
18 #include <vconf.h>
19 #include <vconf-keys.h>
20 #include <vconf-internal-radio-keys.h>
21 #include <bundle.h>
22 #include <eventsystem.h>
23 #include <stdio.h>
24 #ifdef TIZEN_FEATURE_ACTD
25 #include <actd/unit_control.h>
26 #endif
27
28 #include "bt-core-main.h"
29 #include "bt-core-adapter.h"
30 #include "bt-core-common.h"
31 #include "bt-core-dbus-handler.h"
32 #include "bt-core-noti-handler.h"
33
34 #define BT_CORE_IDLE_TERM_TIME 200 /* 200ms */
35 #define BT_CORE_CHECK_ADAPTER_OBJECT_PATH_MAX 50
36
37 #ifdef TIZEN_FEATURE_BT_OTP
38 #define BT_OTP_OBJECT_PATH      "/org/projectx/otp"
39 #define BT_OTP_INTERFACE_NAME   "org.projectx.otp_service"
40 #define BLE_DISABLED            "LeDisabled"
41 #endif
42
43 static bt_status_t adapter_status = BT_DEACTIVATED;
44 static bt_le_status_t adapter_le_status = BT_LE_DEACTIVATED;
45 static gboolean is_recovery_mode = FALSE;
46 static guint core_enable_timer_id;
47
48
49 static int bt_status_before[BT_MODE_MAX] = { VCONFKEY_BT_STATUS_OFF, };
50 static int bt_le_status_before[BT_MODE_MAX] = { VCONFKEY_BT_LE_STATUS_OFF, };
51
52 static int __bt_eventsystem_set_value(const char *event, const char *key, const char *value);
53
54 static void __bt_core_set_status(bt_status_t status)
55 {
56         adapter_status = status;
57 }
58
59 bt_status_t _bt_core_get_status(void)
60 {
61         return adapter_status;
62 }
63
64 static void __bt_core_set_le_status(bt_le_status_t status)
65 {
66         adapter_le_status = status;
67 }
68
69 bt_le_status_t _bt_core_get_le_status(void)
70 {
71         return adapter_le_status;
72 }
73
74 int _bt_core_get_bt_status(bt_mode_e mode)
75 {
76         return bt_status_before[mode];
77 }
78
79 int _bt_core_get_bt_le_status(bt_mode_e mode)
80 {
81         return bt_le_status_before[mode];
82 }
83
84 void _bt_core_set_bt_status(bt_mode_e mode, int status)
85 {
86         bt_status_before[mode] = status;
87 }
88
89 void _bt_core_set_bt_le_status(bt_mode_e mode, int status)
90 {
91         bt_le_status_before[mode] = status;
92 }
93
94 gboolean _bt_core_is_recovery_mode(void)
95 {
96         return is_recovery_mode;
97 }
98
99 static gboolean __bt_core_idle_terminate(gpointer data)
100 {
101         BT_DBG("+");
102         _bt_core_terminate();
103         return FALSE;
104 }
105
106 gboolean _bt_core_is_flight_mode_enabled(void)
107 {
108         int isFlightMode = 0;
109         int ret = -1;
110
111         if (TIZEN_FEATURE_FLIGHTMODE_ENABLED) {
112                 ret = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &isFlightMode);
113                 if (ret != 0)
114                         BT_ERR("vconf_get_bool failed");
115
116                 return isFlightMode;
117         } else {
118                 return FALSE;
119         }
120 }
121
122 #ifdef TIZEN_FEATURE_ACTD
123 static int __bt_call_systemact_service(const char *service_name)
124 {
125         int ret;
126
127         BT_DBG("Use System Activated : %s", service_name);
128
129         ret = actd_start_unit(UNIT_CONTROL_BUS_TYPE_SYSTEM, service_name, 5000);
130
131         if (ret != UNIT_CONTROL_OK) {
132                 BT_ERR("Failed to activate the %s: %d", service_name, ret);
133                 /* Return Success even if the activating result is fail */
134                 return 0;
135         }
136
137         return 0;
138 }
139 #else
140 static int __bt_call_systemact_service(const char *file_path)
141 {
142         BT_DBG("+");
143         FILE *fp;
144
145         if (!file_path) {
146                 BT_ERR("service file path is NULL");
147                 return -1;
148         }
149
150         if (!access(file_path, F_OK)) {
151                 remove(file_path);
152                 usleep(100);
153         }
154
155         fp = fopen(file_path, "w");
156         if (!fp) {
157                 BT_ERR("Failed to fopen service file");
158                 return -1;
159         }
160
161
162         fclose(fp);
163         BT_DBG("-");
164         return 0;
165
166 }
167 #endif
168
169 static int __execute_command(const char *cmd, char *const arg_list[])
170 {
171         int pid;
172         int pid2;
173         int status = 0;
174         BT_DBG("+");
175
176         pid = fork();
177         switch (pid) {
178         case -1:
179                 BT_ERR("fork failed");
180                 return -1;
181
182         case 0:
183                 pid2 = fork();
184                 if (pid2 == -1) {
185                         BT_ERR("fork failed");
186                 } else if (pid2 == 0) {
187                         execv(cmd, arg_list);
188                         exit(256);
189                 }
190                 exit(0);
191                 break;
192
193         default:
194                 BT_DBG("parent : forked[%d]", pid);
195                 waitpid(pid, &status, 0);
196                 BT_DBG("child is terminated : %d", status);
197                 break;
198         }
199         BT_DBG("-");
200         return 0;
201 }
202
203 static int __bt_stack_up(void)
204 {
205         int ret;
206
207         /* activate HCI logger */
208         ret = __bt_call_systemact_service(BT_SYSTEMACT_HCI_LOGGER_START);
209         if (ret < 0) {
210                 BT_ERR("Failed to call systemact service");
211                 return -1;
212         }
213
214         /* activate Bluez */
215         ret = __bt_call_systemact_service(BT_SYSTEMACT_BLUEZ_START);
216         if (ret < 0) {
217                 BT_ERR("Failed to call systemact service");
218                 return -1;
219         }
220
221         /* activate bluetooth-share */
222         ret = __bt_call_systemact_service(BT_SYSTEMACT_BLUETOOTH_SHARE_START);
223         if (ret < 0) {
224                 BT_ERR("Failed to call systemact service");
225                 return -1;
226         }
227
228
229         return 0;
230
231
232
233 }
234
235 int _bt_enable_adapter(void)
236 {
237         int ret;
238         bt_status_t status;
239 #if 0
240         bt_le_status_t le_status;
241 #endif
242         BT_INFO("");
243
244         status = _bt_core_get_status();
245         if (status != BT_DEACTIVATED) {
246                 BT_ERR("Invalid state %d", status);
247                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
248                 return -1;
249         }
250
251 #if 0 /* only the concept of private */
252         le_status = _bt_core_get_le_status();
253         if (le_status == BT_LE_ACTIVATED) {
254                 /* Turn on PSCAN, (ISCAN if needed) */
255                 /* Return with 0 for the Enabled response. */
256                 __bt_core_set_status(BT_ACTIVATED);
257                 BT_INFO("BR/EDR is enabled.");
258                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
259                 return 0;
260         }
261 #endif
262
263         __bt_core_set_status(BT_ACTIVATING);
264         if (TIZEN_FEATURE_BT_USB_DONGLE) {
265                 ret = __bt_call_systemact_service(BT_SYSTEMACT_HCI_UP);
266                 if (ret < 0)
267                         BT_ERR("Failed to call systemact service");
268         } else {
269                 ret = __bt_stack_up();
270         }
271         if (ret < 0) {
272                 BT_ERR("running script failed");
273                 if (TIZEN_FEATURE_BT_USB_DONGLE) {
274                         ret = __bt_call_systemact_service(BT_SYSTEMACT_HCI_DOWN);
275                         if (ret < 0)
276                                 BT_ERR("Failed to call systemact service");
277                 } else {
278                         ret = __execute_command("/usr/etc/bluetooth/bt-dev-end.sh", NULL);
279                 }
280                 __bt_core_set_status(BT_DEACTIVATED);
281                 return -1;
282         }
283
284         return 0;
285 }
286
287 int _bt_disable_adapter(void)
288 {
289         bt_status_t status;
290 #if 0
291         bt_le_status_t le_status;
292 #endif
293
294         BT_INFO_C("Disable adapter");
295
296 #if 0 /* only the concept of private */
297         le_status = _bt_core_get_le_status();
298         BT_DBG("le_status : %d", le_status);
299         if (le_status == BT_LE_ACTIVATED) {
300                 /* Turn off PSCAN, (ISCAN if needed) */
301                 /* Return with 0 for the Disabled response. */
302                 __bt_core_set_status(BT_DEACTIVATED);
303                 BT_INFO("BR/EDR is disabled. now LE only mode");
304                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
305                 return 0;
306         }
307 #endif
308
309         status = _bt_core_get_status();
310         if (status == BT_ACTIVATING) {
311                 /* Forcely terminate */
312                 if (TIZEN_FEATURE_BT_USB_DONGLE) {
313                         if (__bt_call_systemact_service(BT_SYSTEMACT_HCI_DOWN) < 0)
314                                 BT_ERR("Failed to call systemact service");
315                 } else {
316 #ifdef TIZEN_FEATURE_RADIO
317                         int radio_status = VCONFKEY_RADIO_STATUS_OFF;
318
319                         /* Check if radio status on or off */
320                         if (vconf_get_int(VCONFKEY_RADIO_STATUS, &radio_status) < 0)
321                                 BT_ERR("Fail to get radio status");
322
323                         BT_DBG("Radio status: %d", radio_status);
324
325                         if (radio_status == VCONFKEY_RADIO_STATUS_ON) {
326                                 if (__bt_call_systemact_service(BT_SYSTEMACT_STACK_DOWN_WITH_RADIO) < 0)
327                                         BT_ERR("running script failed");
328                         } else {
329                                 if (__bt_call_systemact_service(BT_SYSTEMACT_STACK_DOWN) < 0)
330                                         BT_ERR("running script failed");
331                         }
332 #else
333                         if (__bt_call_systemact_service(BT_SYSTEMACT_STACK_DOWN) < 0)
334                                 BT_ERR("running script failed");
335 #endif
336                 }
337                 _bt_core_terminate();
338                 return 0;
339         } else if (status != BT_ACTIVATED) {
340                 BT_ERR("Invalid state %d", status);
341                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
342         }
343
344         __bt_core_set_status(BT_DEACTIVATING);
345         if (TIZEN_FEATURE_BT_USB_DONGLE) {
346                 if (__bt_call_systemact_service(BT_SYSTEMACT_HCI_DOWN) < 0) {
347                         BT_ERR("Failed to call systemact service");
348                         __bt_core_set_status(BT_ACTIVATED);
349                         return -1;
350                 }
351         } else {
352 #ifdef TIZEN_FEATURE_RADIO
353                 int radio_status = VCONFKEY_RADIO_STATUS_OFF;
354
355                 /* Check if radio status on or off */
356                 if (vconf_get_int(VCONFKEY_RADIO_STATUS, &radio_status) < 0)
357                         BT_ERR("Fail to get radio status");
358
359                 BT_DBG("Radio status: %d", radio_status);
360
361                 if (radio_status == VCONFKEY_RADIO_STATUS_ON) {
362                         if (__bt_call_systemact_service(BT_SYSTEMACT_STACK_DOWN_WITH_RADIO) < 0) {
363                                 BT_ERR("running script failed");
364                                 __bt_core_set_status(BT_ACTIVATED);
365                                 return -1;
366                         }
367                 } else {
368                         if (__bt_call_systemact_service(BT_SYSTEMACT_STACK_DOWN) < 0) {
369                                 BT_ERR("running script failed");
370                                 __bt_core_set_status(BT_ACTIVATED);
371                                 return -1;
372                         }
373                 }
374 #else
375                 if (__bt_call_systemact_service(BT_SYSTEMACT_STACK_DOWN) < 0) {
376                                 BT_ERR("running script failed");
377                                 __bt_core_set_status(BT_ACTIVATED);
378                                 return -1;
379                 }
380 #endif
381         }
382
383         return 0;
384 }
385
386 int _bt_enable_adapter_le(void)
387 {
388         BT_DBG("");
389
390         int ret;
391         bt_status_t status;
392         bt_le_status_t le_status;
393         le_status = _bt_core_get_le_status();
394         retv_if(le_status == BT_LE_ACTIVATED, 0);
395         retv_if(le_status != BT_LE_DEACTIVATED, -1);
396
397         status = _bt_core_get_status();
398         if (status == BT_DEACTIVATED) {
399                 __bt_core_set_le_status(BT_LE_ACTIVATING);
400                 BT_DBG("Activate BT");
401                 if (TIZEN_FEATURE_BT_USB_DONGLE) {
402                         ret = __bt_call_systemact_service(BT_SYSTEMACT_HCI_UP);
403                         if (ret < 0)
404                                 BT_ERR("Failed to call systemact service");
405                 } else {
406                         ret = __bt_call_systemact_service(BT_SYSTEMACT_STACK_UP);
407                         if (ret < 0)
408                                 BT_ERR("Failed to call systemact service");
409                 }
410                 if (ret < 0) {
411                         BT_ERR("running script failed");
412                         if (TIZEN_FEATURE_BT_USB_DONGLE) {
413                                 ret = __bt_call_systemact_service(BT_SYSTEMACT_HCI_DOWN);
414                                 if (ret < 0)
415                                         BT_ERR("Failed to call systemact service");
416                         } else {
417                                 ret = __execute_command("/usr/etc/bluetooth/bt-dev-end.sh &", NULL);
418                         }
419                         __bt_core_set_status(BT_DEACTIVATED);
420                         __bt_core_set_le_status(BT_LE_DEACTIVATED);
421                         return -1;
422                 }
423         } else {
424                 __bt_core_set_le_status(BT_LE_ACTIVATED);
425                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
426         }
427 #ifdef TIZEN_FEATURE_BT_HPS
428         ret = _bt_core_start_httpproxy();
429         if (ret < 0)
430                 BT_ERR("_bt_core_start_httpproxy() failed");
431 #endif
432
433         return 0;
434 }
435
436 #ifdef TIZEN_FEATURE_BT_OTP
437 static void _bt_core_stop_otp()
438 {
439         GError *error = NULL;
440         GDBusMessage *msg = NULL;
441         GDBusConnection *conn = _bt_core_get_gdbus_connection();
442         msg = g_dbus_message_new_signal(BT_OTP_OBJECT_PATH, BT_OTP_INTERFACE_NAME, BLE_DISABLED);
443         if (!g_dbus_connection_send_message(conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 0, NULL)) {
444                 if (error != NULL) {
445                         BT_ERR("Failed to send BLE_DISABLED signal to OTP : errCode[%x], \
446                                         message[%s]",
447                                         error->code, error->message);
448                         g_clear_error(&error);
449                 }
450         }
451 }
452 #endif
453
454 int _bt_disable_adapter_le(void)
455 {
456         BT_DBG("+");
457
458         bt_status_t status;
459         bt_le_status_t le_status;
460
461         le_status = _bt_core_get_le_status();
462         retv_if(le_status == BT_LE_DEACTIVATED, 0);
463         retv_if(le_status == BT_LE_DEACTIVATING, -1);
464
465 #ifdef TIZEN_FEATURE_BT_HPS
466         _bt_core_stop_httpproxy();
467 #endif
468
469 #ifdef TIZEN_FEATURE_BT_OTP
470         _bt_core_stop_otp();
471 #endif
472
473         status = _bt_core_get_status();
474         BT_DBG("status : %d", status);
475
476         if (status == BT_DEACTIVATED) {
477                 __bt_core_set_le_status(BT_LE_DEACTIVATING);
478                 int ret;
479                 if (TIZEN_FEATURE_BT_USB_DONGLE) {
480                         ret = __bt_call_systemact_service(BT_SYSTEMACT_HCI_DOWN);
481                         if (ret < 0)
482                                 BT_ERR("Failed to call systemact service");
483                 } else {
484                         ret = __execute_command("/usr/etc/bluetooth/bt-stack-down.sh", NULL);
485                 }
486                 if (ret < 0) {
487                         BT_ERR("running script failed");
488                         __bt_core_set_le_status(BT_LE_ACTIVATED);
489                         return -1;
490                 }
491         } else {
492                         g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
493         }
494
495         __bt_core_set_le_status(BT_LE_DEACTIVATED);
496
497         BT_DBG("-");
498         return 0;
499 }
500
501 int _bt_core_service_request_adapter(int service_function)
502 {
503         int ret = -1;
504
505         GArray *in_param1 = NULL;
506         GArray *in_param2 = NULL;
507         GArray *in_param3 = NULL;
508         GArray *in_param4 = NULL;
509         GArray *out_param = NULL;
510
511         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
512
513         ret = _bt_core_service_request(BT_CORE_SERVICE, service_function,
514                         in_param1, in_param2, in_param3, in_param4, &out_param);
515         if (ret < 0)
516                 BT_ERR("_bt_core_service_request_adapter() failed");
517
518         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
519
520         return ret;
521 }
522
523 static gboolean __bt_core_check_the_adapter_path(void)
524 {
525         GError *err = NULL;
526         GDBusProxy *manager_proxy = NULL;
527         GVariant *result = NULL;
528         char *adapter_path = NULL;
529         GDBusConnection *conn = NULL;
530
531         conn = _bt_core_get_gdbus_connection();
532         if (conn == NULL)
533                 return FALSE;
534
535         manager_proxy =  g_dbus_proxy_new_sync(conn,
536                         G_DBUS_PROXY_FLAGS_NONE, NULL,
537                         "org.bluez",
538                         "/",
539                         "org.freedesktop.DBus.ObjectManager",
540                         NULL, &err);
541
542         if (!manager_proxy) {
543                 if (err != NULL) {
544                         BT_ERR("Unable to create proxy: %s", err->message);
545                         g_clear_error(&err);
546                 } else {
547                         BT_ERR("Fail to create proxy");
548                 }
549                 goto fail;
550         }
551
552         result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
553                         G_DBUS_CALL_FLAGS_NONE, 1000, NULL, &err);
554         if (!result) {
555                 if (err != NULL) {
556                         BT_ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
557                         g_clear_error(&err);
558                 } else{
559                         BT_ERR("Fail to get DefaultAdapter");
560                 }
561                 goto fail;
562         }
563
564         if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
565                 BT_ERR("Incorrect result\n");
566                 goto fail;
567         }
568
569         g_variant_get(result, "(&o)", &adapter_path);
570
571         if (adapter_path == NULL ||
572                 strlen(adapter_path) >= BT_CORE_CHECK_ADAPTER_OBJECT_PATH_MAX) {
573                 BT_ERR("Adapter path is inproper\n");
574                 goto fail;
575         }
576
577         g_variant_unref(result);
578         g_object_unref(manager_proxy);
579
580         return TRUE;
581
582 fail:
583         if (result)
584                 g_variant_unref(result);
585
586         if (manager_proxy)
587                 g_object_unref(manager_proxy);
588
589         return FALSE;
590 }
591
592 void _bt_core_update_status(void)
593 {
594         int bt_status = VCONFKEY_BT_STATUS_OFF;
595         int bt_le_status = VCONFKEY_BT_LE_STATUS_OFF;
596         gboolean ret = FALSE;
597
598         ret = __bt_core_check_the_adapter_path();
599         BT_INFO("check the real status of bt_adapter");
600
601         if (ret != TRUE) {
602                 __bt_core_set_status(BT_DEACTIVATED);
603                 __bt_core_set_le_status(BT_DEACTIVATED);
604         } else {
605                 if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status) < 0)
606                         BT_ERR("no bluetooth device info, so BT was disabled at previous session");
607                 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status) < 0)
608                         BT_ERR("no bluetooth le info, so BT LE was disabled at previous session");
609
610                 BT_INFO("bt_status = %d, bt_le_status = %d", bt_status, bt_le_status);
611
612                 if (bt_status & VCONFKEY_BT_STATUS_ON)
613                         __bt_core_set_status(BT_ACTIVATED);
614                 if (bt_le_status & VCONFKEY_BT_LE_STATUS_ON)
615                         __bt_core_set_le_status(BT_ACTIVATED);
616         }
617 }
618
619 gboolean _bt_core_enable_adapter(void)
620 {
621         int ret;
622
623         _bt_set_flightmode_request(FALSE);
624         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
625                 BT_ERR("Set vconf failed");
626
627         ret = _bt_enable_adapter();
628         if (ret < 0)
629                 return FALSE;
630         else
631                 return TRUE;
632 }
633
634 static gboolean __bt_core_terminate_cb(gpointer data)
635 {
636         _bt_core_terminate();
637
638         return FALSE;
639 }
640
641 gboolean _bt_core_disable_adapter(void)
642 {
643         int ret;
644         gboolean adapter_state;
645
646         _bt_set_flightmode_request(FALSE);
647         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
648                 BT_ERR("Set vconf failed");
649
650         adapter_state = __bt_core_check_the_adapter_path();
651         if (adapter_state == FALSE)
652                 BT_INFO("Default adapter is NOT normal.");
653
654         ret = _bt_disable_adapter();
655         if (adapter_state == FALSE) {
656                 g_timeout_add(BT_CORE_IDLE_TERM_TIME,
657                               __bt_core_terminate_cb, NULL);
658                 return TRUE;
659         } else {
660                 if (ret < 0)
661                         return FALSE;
662                 else
663                         return TRUE;
664         }
665 }
666
667 gboolean _bt_core_recover_adapter(void)
668 {
669         int ret;
670 #if 0
671         int ret_le;
672 #endif
673         BT_INFO_C("Recover bt adapter");
674
675         _bt_set_flightmode_request(FALSE);
676         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
677                 BT_ERR("Set vconf failed");
678
679         is_recovery_mode = TRUE;
680
681         _bt_core_update_status();
682
683         if (_bt_core_get_status() == BT_ACTIVATED) {
684                 _bt_core_set_bt_status(BT_RECOVERY_MODE, 1);
685 #ifdef TIZEN_FEATURE_BUSACT
686                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
687 #endif
688         }
689         if (_bt_core_get_le_status() == BT_LE_ACTIVATED) {
690                 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 1);
691 #ifdef TIZEN_FEATURE_BUSACT
692                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
693 #endif
694         }
695
696         ret = _bt_disable_adapter();
697         if (ret < 0)
698                 BT_ERR("_bt_disable_adapter() failed");
699
700 /* In platform, don't seperate BR/EDR and LE status */
701 #if 0
702         ret_le = _bt_disable_adapter_le();
703         if (ret_le < 0)
704                 BT_ERR("_bt_disable_adapter_le() failed");
705 #endif
706         return TRUE;
707 }
708
709 gboolean _bt_core_enable_adapter_le(void)
710 {
711         int ret;
712
713         ret = _bt_enable_adapter_le();
714         if (ret < 0)
715                 return FALSE;
716         else
717                 return TRUE;
718 }
719
720 gboolean _bt_core_disable_adapter_le(void)
721 {
722         BT_DBG("+");
723
724         int ret;
725
726         ret = _bt_disable_adapter_le();
727         if (ret < 0)
728                 return FALSE;
729         else
730                 return TRUE;
731 }
732
733 gboolean __bt_core_reset_adapter(void)
734 {
735         /* Forcely terminate */
736         if (__execute_command("/usr/etc/bluetooth/bt-reset-env.sh", NULL) < 0)
737                 BT_ERR("running script failed");
738
739         g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
740
741         return TRUE;
742 }
743
744 static gboolean __bt_core_enable_core_timeout_cb(gpointer data)
745 {
746         BT_DBG("+");
747
748         core_enable_timer_id = 0;
749
750         _bt_core_init_vconf_value();
751
752         return FALSE;
753 }
754
755 gboolean _bt_core_enable_core(void)
756 {
757         BT_DBG("+");
758
759         _bt_core_update_status();
760
761         if (core_enable_timer_id > 0)
762                 g_source_remove(core_enable_timer_id);
763
764         core_enable_timer_id = g_timeout_add(200, (GSourceFunc)__bt_core_enable_core_timeout_cb, NULL);
765
766         BT_DBG("-");
767         return TRUE;
768 }
769
770 gboolean _bt_core_set_transfer_value(gboolean value)
771 {
772         const char *event_val = NULL;
773         gboolean ret = TRUE;
774
775         BT_DBG("value: %d", value);
776
777         event_val = value ? EVT_VAL_BT_TRANSFERING : EVT_VAL_BT_NON_TRANSFERING;
778
779         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_TRANSFERING_STATE,
780                                                 event_val) != ES_R_OK) {
781                 BT_ERR("Fail to set BT state value");
782                 ret = FALSE;
783         }
784
785         if (ret == FALSE || value == FALSE) {
786                 BT_DBG("Terminate bt-core process");
787                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
788         }
789
790         BT_DBG("-");
791         return ret;
792 }
793
794 gboolean _bt_core_factory_test_mode(const char *type, const char *arg)
795 {
796         BT_DBG("Test item : %s", type);
797
798 #ifdef TIZEN_FEATURE_ACTD
799         if (g_strcmp0(type, "Enable_RF_Test") == 0) {
800                 __bt_call_systemact_service(BT_SYSTEMACT_EDUTM_ON);
801         } else if (g_strcmp0(type, "Disable_RF_Test") == 0) {
802                 __bt_call_systemact_service(BT_SYSTEMACT_EDUTM_OFF);
803         } else {
804                 BT_DBG("Terminate bt-core process");
805                 g_timeout_add(BT_CORE_IDLE_TERM_TIME, __bt_core_idle_terminate, NULL);
806                 return FALSE;
807         }
808 #else
809         char *cmd = NULL;
810         char *arg_list[3] = { NULL, NULL, NULL };
811
812         if (g_strcmp0(type, "Enable_RF_Test") == 0) {
813                 cmd = "/usr/etc/bluetooth/bt-edutm-on.sh";
814                 arg_list[0] = "bt-edutm-on.sh";
815         } else if (g_strcmp0(type, "Disable_RF_Test") == 0) {
816                 cmd = "/usr/etc/bluetooth/bt-edutm-off.sh";
817                 arg_list[0] = "bt-edutm-off.sh";
818         } else if (g_strcmp0(type, "Slave_Mode") == 0) {
819                 cmd = "/usr/etc/bluetooth/bt-mode-slave.sh";
820                 arg_list[0] = "bt-mode-slave.sh";
821         } else if (g_strcmp0(type, "Master_Mode") == 0) {
822                 cmd = "/usr/etc/bluetooth/bt-mode-master.sh";
823                 arg_list[0] = "bt-mode-master.sh";
824         } else if (g_strcmp0(type, "SSP_Debug_Mode") == 0) {
825                 cmd = "/usr/etc/bluetooth/bt-set-ssp-debug-mode.sh";
826                 arg_list[0] = "bt-set-ssp-debug-mode.sh";
827                 arg_list[1] = (char *)arg;
828         } else if (g_strcmp0(type, "RF_Channel") == 0) {
829                 cmd = "/usr/etc/bluetooth/bt-enable-rf-channel.sh";
830                 arg_list[0] = "bt-enable-rf-channel.sh";
831                 arg_list[1] = (char *)arg;
832         } else {
833                 return FALSE;
834         }
835
836         BT_DBG("Run %s", cmd);
837         if (__execute_command(cmd, arg_list) < 0)
838                 BT_ERR("running script failed");
839 #endif
840
841         return TRUE;
842 }
843
844 static gboolean __bt_core_recovery_cb(gpointer data)
845 {
846         int ret = 0;
847         gboolean is_request_failed = FALSE;
848         static gboolean is_first_failure = TRUE;
849
850         BT_DBG("+");
851
852         if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
853                 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
854                 if (ret < 0)
855                         is_request_failed = TRUE;
856         }
857
858         if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
859                 ret = _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
860                 if (ret < 0)
861                         is_request_failed = TRUE;
862         }
863
864         if (is_request_failed == TRUE) {
865                 BT_ERR("Recovery is failed.");
866                 if (is_first_failure == TRUE) {
867                         g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
868                         is_first_failure = FALSE;
869                         return FALSE;
870                 } else {
871                         is_first_failure = TRUE;
872                         return FALSE;
873                 }
874         } else
875                 is_first_failure = TRUE;
876
877         if (_bt_core_get_bt_status(BT_RECOVERY_MODE) == 1) {
878                 _bt_core_set_bt_status(BT_RECOVERY_MODE, 0);
879                 ret = _bt_enable_adapter();
880                 if (ret < 0)
881                         BT_ERR("_bt_enable_adapter() failed");
882         }
883
884 #if 0
885         if (_bt_core_get_bt_le_status(BT_RECOVERY_MODE) == 1) {
886                 _bt_core_set_bt_le_status(BT_RECOVERY_MODE, 0);
887                 ret = _bt_enable_adapter_le();
888                 if (ret < 0)
889                         BT_ERR("_bt_enable_adapter_le() failed");
890         }
891 #endif
892         is_recovery_mode = FALSE;
893
894         BT_DBG("-");
895
896         return FALSE;
897 }
898
899 static gboolean __bt_core_enable_timeout_cb(gpointer data)
900 {
901         bt_status_t adapter_status;
902         bt_le_status_t adapter_status_le;
903
904         BT_DBG("");
905
906         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 0) != 0)
907                 BT_ERR("Set vconf failed");
908
909         adapter_status = _bt_core_get_status();
910         adapter_status_le = _bt_core_get_le_status();
911
912         if (adapter_status == BT_DEACTIVATED &&
913                         _bt_core_get_bt_status(BT_FLIGHT_MODE) != 0) {
914                 _bt_core_set_bt_status(BT_FLIGHT_MODE, 0);
915                 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER);
916                 _bt_enable_adapter();
917         }
918
919         if (adapter_status_le == BT_LE_DEACTIVATED &&
920                         _bt_core_get_bt_le_status(BT_FLIGHT_MODE) != 0) {
921                 _bt_core_set_bt_le_status(BT_FLIGHT_MODE, 0);
922                 _bt_core_service_request_adapter(BT_ENABLE_ADAPTER_LE);
923                 _bt_enable_adapter_le();
924         }
925
926         return FALSE;
927 }
928
929 static gboolean __bt_core_disable_timeout_cb(gpointer data)
930 {
931         bt_status_t adapter_status;
932         bt_le_status_t adapter_status_le;
933
934         BT_DBG("");
935
936         if (vconf_set_int(BT_OFF_DUE_TO_FLIGHT_MODE, 1) != 0)
937                 BT_ERR("Set vconf failed");
938
939         adapter_status = _bt_core_get_status();
940         adapter_status_le = _bt_core_get_le_status();
941
942         if (adapter_status == BT_ACTIVATED) {
943                 int bt_status_before_mode = 0;
944
945                 if (vconf_get_int(VCONFKEY_BT_STATUS, &bt_status_before_mode) == 0)
946                         _bt_core_set_bt_status(BT_FLIGHT_MODE, bt_status_before_mode);
947
948 #ifdef TIZEN_FEATURE_BUSACT
949                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER);
950 #endif
951                 _bt_disable_adapter();
952         }
953
954         if (adapter_status_le == BT_LE_ACTIVATED) {
955                 int bt_le_status_before_mode = 0;
956
957                 if (vconf_get_int(VCONFKEY_BT_LE_STATUS, &bt_le_status_before_mode) == 0)
958                         _bt_core_set_bt_le_status(BT_FLIGHT_MODE, bt_le_status_before_mode);
959
960 #ifdef TIZEN_FEATURE_BUSACT
961                 _bt_core_service_request_adapter(BT_DISABLE_ADAPTER_LE);
962 #endif
963                 _bt_disable_adapter_le();
964         }
965
966         return FALSE;
967 }
968
969 static int __bt_eventsystem_set_value(const char *event, const char *key, const char *value)
970 {
971         int ret;
972         bundle *b = NULL;
973
974         b = bundle_create();
975
976         bundle_add_str(b, key, value);
977
978         ret = eventsystem_send_system_event(event, b);
979
980         BT_DBG("eventsystem_send_system_event result: %d", ret);
981
982         bundle_free(b);
983
984         return ret;
985 }
986
987 void _bt_core_adapter_added_cb(void)
988 {
989         bt_status_t status;
990         bt_le_status_t le_status;
991         gboolean flight_mode_status;
992
993         BT_DBG("");
994
995         status = _bt_core_get_status();
996         BT_DBG("status : %d", status);
997         le_status = _bt_core_get_le_status();
998         BT_DBG("le_status : %d", le_status);
999
1000         if (status == BT_ACTIVATING)
1001                 __bt_core_set_status(BT_ACTIVATED);
1002         if (le_status == BT_LE_ACTIVATING)
1003                 __bt_core_set_le_status(BT_LE_ACTIVATED);
1004
1005         flight_mode_status = _bt_core_is_flight_mode_enabled();
1006
1007         if (flight_mode_status == TRUE && _bt_is_flightmode_request() == TRUE) {
1008                 _bt_set_flightmode_request(FALSE);
1009                 g_timeout_add(2000, (GSourceFunc)__bt_core_disable_timeout_cb, NULL);
1010                 return;
1011         }
1012         _bt_set_flightmode_request(FALSE);
1013
1014         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_STATE,
1015                                                 EVT_VAL_BT_ON) != ES_R_OK)
1016                 BT_ERR("Fail to set BT state value");
1017
1018         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_LE_STATE,
1019                                                 EVT_VAL_BT_LE_ON) != ES_R_OK)
1020                 BT_ERR("Fail to set BT LE state value");
1021
1022         _bt_core_terminate();
1023 }
1024
1025 void _bt_core_adapter_removed_cb(void)
1026 {
1027         int flight_mode_value = 0;
1028         int power_saving_mode = 0;
1029         gboolean flight_mode_status;
1030         static int timer_id = -1;
1031
1032         BT_DBG("is_recovery_mode: %d", is_recovery_mode);
1033
1034         __bt_core_set_status(BT_DEACTIVATED);
1035         __bt_core_set_le_status(BT_LE_DEACTIVATED);
1036         if (vconf_set_int(VCONFKEY_BT_STATUS, VCONFKEY_BT_STATUS_OFF) != 0)
1037                 BT_ERR("Set vconf failed");
1038         if (vconf_set_int(VCONFKEY_BT_LE_STATUS, VCONFKEY_BT_LE_STATUS_OFF) != 0)
1039                 BT_ERR("Set vconf failed");
1040
1041         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_STATE,
1042                                                 EVT_VAL_BT_OFF) != ES_R_OK)
1043                 BT_ERR("Fail to set value");
1044
1045         if (__bt_eventsystem_set_value(SYS_EVENT_BT_STATE, EVT_KEY_BT_LE_STATE,
1046                                                 EVT_VAL_BT_LE_OFF) != ES_R_OK)
1047                 BT_ERR("Fail to set value");
1048
1049         if (is_recovery_mode == TRUE) {
1050                 if (timer_id < 0)
1051                         timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_recovery_cb, NULL);
1052                 return;
1053         }
1054
1055         if (vconf_get_int(BT_OFF_DUE_TO_FLIGHT_MODE, &flight_mode_value) != 0)
1056                 BT_ERR("Fail to get the flight_mode_deactivated value");
1057
1058         if (vconf_get_int(BT_OFF_DUE_TO_POWER_SAVING_MODE, &power_saving_mode) != 0)
1059                 BT_ERR("Fail to get the ps_mode_deactivated value");
1060
1061         flight_mode_status = _bt_core_is_flight_mode_enabled();
1062
1063         if (flight_mode_status == FALSE && _bt_is_flightmode_request() == TRUE) {
1064                 _bt_set_flightmode_request(FALSE);
1065                 if (timer_id < 0)
1066                         timer_id = g_timeout_add(2000, (GSourceFunc)__bt_core_enable_timeout_cb, NULL);
1067                 return;
1068         }
1069         _bt_set_flightmode_request(FALSE);
1070
1071         if (flight_mode_value == 1 || power_saving_mode == 1) {
1072                 BT_DBG("Bt Core not terminated");
1073                 return;
1074         }
1075
1076         _bt_core_terminate();
1077 }