4 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 #include <vconf-keys.h>
27 #include "bt-internal-types.h"
29 static GMainLoop *main_loop = NULL;
38 static bt_status_t adapter_status = BT_DEACTIVATED;
40 static void __bt_core_terminate(void)
43 g_main_loop_quit(main_loop);
45 BT_DBG("Terminating bt-core daemon");
50 static void __bt_core_set_status(bt_status_t status)
52 adapter_status = status;
55 static bt_status_t __bt_core_get_status(void)
57 return adapter_status;
60 static gboolean bt_core_enable_adapter(BtCore *agent,
61 DBusGMethodInvocation *context);
63 static gboolean bt_core_disable_adapter(BtCore *agent,
64 DBusGMethodInvocation *context);
66 static gboolean bt_core_reset_adapter(BtCore *agent,
67 DBusGMethodInvocation *context);
69 #include "bt_core_glue.h"
71 GType bt_core_get_type (void);
74 G_DEFINE_TYPE(BtCore, bt_core, G_TYPE_OBJECT);
76 /*This is part of platform provided code skeleton for client server model*/
77 static void bt_core_class_init (BtCoreClass *bt_core_class)
79 dbus_g_object_type_install_info(G_TYPE_FROM_CLASS(bt_core_class),
80 &dbus_glib_bt_core_object_info);
83 /*This is part of platform provided code skeleton for client server model*/
84 static void bt_core_init (BtCore *core)
91 BT_CORE_ERROR_TIMEOUT,
94 #define BT_CORE_ERROR (bt_core_error_quark())
96 static GQuark bt_core_error_quark(void)
98 static GQuark quark = 0;
100 quark = g_quark_from_static_string("BtCore");
105 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
107 static GError *bt_core_error(BtCoreError error, const char *err_msg)
109 return g_error_new(BT_CORE_ERROR, error, err_msg, NULL);
112 static int __bt_enable_adapter(void)
119 status = __bt_core_get_status();
120 if (status != BT_DEACTIVATED) {
121 BT_DBG("Invalid state %d", status);
125 __bt_core_set_status(BT_ACTIVATING);
127 ret = system("/usr/etc/bluetooth/bt-stack-up.sh &");
129 BT_DBG("running script failed");
130 ret = system("/usr/etc/bluetooth/bt-dev-end.sh &");
131 __bt_core_set_status(BT_DEACTIVATED);
138 static int __bt_disable_adapter(void)
144 status = __bt_core_get_status();
145 if (status == BT_ACTIVATING) {
146 /* Forcely terminate */
147 if (system("/usr/etc/bluetooth/bt-stack-down.sh &") < 0) {
148 BT_DBG("running script failed");
150 __bt_core_terminate();
152 } else if (status != BT_ACTIVATED) {
153 BT_DBG("Invalid state %d", status);
157 __bt_core_set_status(BT_DEACTIVATING);
159 if (system("/usr/etc/bluetooth/bt-stack-down.sh &") < 0) {
160 BT_DBG("running script failed");
161 __bt_core_set_status( BT_ACTIVATED);
168 static gboolean bt_core_enable_adapter(BtCore *agent,
169 DBusGMethodInvocation *context)
171 char *sender = dbus_g_method_get_sender(context);
177 ret = __bt_enable_adapter();
179 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
180 "Activation failed");
181 dbus_g_method_return_error(context, error);
186 dbus_g_method_return(context);
193 static gboolean bt_core_disable_adapter(BtCore *agent,
194 DBusGMethodInvocation *context)
196 char *sender = dbus_g_method_get_sender(context);
202 ret = __bt_disable_adapter();
204 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
205 "Deactivation failed");
206 dbus_g_method_return_error(context, error);
211 dbus_g_method_return(context);
218 static int __bt_reset_adapter(void)
220 /* Forcely terminate */
221 if (system("/usr/etc/bluetooth/bt-reset-env.sh &") < 0) {
222 BT_DBG("running script failed");
224 __bt_core_terminate();
228 static gboolean bt_core_reset_adapter(BtCore *agent,
229 DBusGMethodInvocation *context)
231 char *sender = dbus_g_method_get_sender(context);
237 ret = __bt_reset_adapter();
239 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
240 "Deactivation failed");
241 dbus_g_method_return_error(context, error);
246 dbus_g_method_return(context);
253 static void __name_owner_changed(DBusGProxy *object, const char *name,
254 const char *prev, const char *new,
257 if (g_strcmp0(name, "org.bluez") == 0 && *new == '\0') {
258 BT_DBG("BlueZ is terminated");
259 __bt_disable_adapter();
260 __bt_core_terminate();
261 } else if (g_strcmp0(name, "org.projectx.bt") == 0 && *new == '\0') {
262 BT_DBG("bt-service is terminated abnormally");
263 __bt_disable_adapter();
267 static DBusGProxy * __bt_core_register(DBusGConnection *conn, BtCore *bt_core)
273 proxy = dbus_g_proxy_new_for_name(conn, DBUS_SERVICE_DBUS,
274 DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
276 BT_ERR("proxy is NULL");
280 if (!dbus_g_proxy_call(proxy, "RequestName", &err, G_TYPE_STRING,
281 BT_CORE_NAME, G_TYPE_UINT, 0, G_TYPE_INVALID,
282 G_TYPE_UINT, &result, G_TYPE_INVALID)) {
284 BT_ERR("RequestName RPC failed[%s]\n", err->message);
287 g_object_unref(proxy);
291 if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
292 BT_ERR("Failed to get the primary well-known name.\n");
293 g_object_unref(proxy);
297 dbus_g_proxy_add_signal(proxy, "NameOwnerChanged", G_TYPE_STRING,
298 G_TYPE_STRING, G_TYPE_STRING,
301 dbus_g_proxy_connect_signal(proxy, "NameOwnerChanged",
302 G_CALLBACK(__name_owner_changed),
305 dbus_g_connection_register_g_object(conn, BT_CORE_PATH,
311 static void __bt_core_unregister(DBusGConnection *conn, BtCore *bt_core,
312 DBusGProxy *dbus_proxy)
314 if (!bt_core || !dbus_proxy)
317 dbus_g_proxy_disconnect_signal(dbus_proxy, "NameOwnerChanged",
318 G_CALLBACK(__name_owner_changed),
321 dbus_g_connection_unregister_g_object(conn, G_OBJECT(bt_core));
323 g_object_unref(bt_core);
324 g_object_unref(dbus_proxy);
328 static void __adapter_added_cb(DBusGProxy *manager_proxy,
329 const char *adapter_path,
334 __bt_core_set_status(BT_ACTIVATED);
337 static void __adapter_removed_cb(DBusGProxy *manager_proxy,
338 const char *adapter_path,
343 __bt_core_set_status(BT_DEACTIVATED);
345 __bt_core_terminate();
348 static DBusGProxy *__bt_core_manager_init(DBusGConnection *conn)
350 DBusGProxy *manager_proxy;
352 manager_proxy = dbus_g_proxy_new_for_name(conn, "org.bluez", "/",
353 "org.bluez.Manager");
354 if (manager_proxy == NULL) {
355 BT_ERR("ERROR: Can't make manager proxy");
359 dbus_g_proxy_add_signal(manager_proxy, "AdapterAdded",
360 DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
361 dbus_g_proxy_connect_signal(manager_proxy, "AdapterAdded",
362 G_CALLBACK(__adapter_added_cb),
365 dbus_g_proxy_add_signal(manager_proxy, "AdapterRemoved",
366 DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
367 dbus_g_proxy_connect_signal(manager_proxy, "AdapterRemoved",
368 G_CALLBACK(__adapter_removed_cb),
371 return manager_proxy;
376 static void __bt_core_manager_exit(DBusGProxy *manager_proxy)
381 dbus_g_proxy_disconnect_signal(manager_proxy, "AdapterAdded",
382 G_CALLBACK(__adapter_added_cb),
385 dbus_g_proxy_disconnect_signal(manager_proxy, "AdapterRemoved",
386 G_CALLBACK(__adapter_removed_cb),
389 g_object_unref(manager_proxy);
392 static void __bt_core_sigterm_handler(int signo)
394 BT_DBG("Got the signal: %d", signo);
396 __bt_core_terminate();
401 DBusGConnection *conn = NULL;
402 GError *error = NULL;
404 DBusGProxy *manager_proxy = NULL;
405 DBusGProxy *dbus_proxy = NULL;
408 BT_DBG("Starting bt-core daemeon");
412 conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
414 BT_ERR("ERROR: Can't get on system bus [%s]", error->message);
419 bt_core = g_object_new(BT_CORE_TYPE, NULL);
421 dbus_proxy = __bt_core_register(conn, bt_core);
423 BT_ERR("__bt_core_register failed");
424 g_object_unref(bt_core);
429 manager_proxy = __bt_core_manager_init(conn);
430 if (!manager_proxy) {
431 BT_ERR("__bt_core_manager_init failed");
435 main_loop = g_main_loop_new(NULL, FALSE);
437 memset(&sa, 0, sizeof(sa));
438 sa.sa_handler = __bt_core_sigterm_handler;
439 sigaction(SIGINT, &sa, NULL);
440 sigaction(SIGTERM, &sa, NULL);
442 g_main_loop_run(main_loop);
445 __bt_core_unregister(conn, bt_core, dbus_proxy);
447 __bt_core_manager_exit(manager_proxy);
450 g_main_loop_unref(main_loop);
452 dbus_g_connection_unref(conn);
454 BT_DBG("Terminating bt-core daemon");