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);
48 static void __bt_core_set_status(bt_status_t status)
50 adapter_status = status;
53 static bt_status_t __bt_core_get_status(void)
55 return adapter_status;
58 static gboolean bt_core_enable_adapter(BtCore *agent,
59 DBusGMethodInvocation *context);
61 static gboolean bt_core_disable_adapter(BtCore *agent,
62 DBusGMethodInvocation *context);
64 static gboolean bt_core_reset_adapter(BtCore *agent,
65 DBusGMethodInvocation *context);
67 #include "bt_core_glue.h"
69 GType bt_core_get_type (void);
72 G_DEFINE_TYPE(BtCore, bt_core, G_TYPE_OBJECT);
74 /*This is part of platform provided code skeleton for client server model*/
75 static void bt_core_class_init (BtCoreClass *bt_core_class)
77 dbus_g_object_type_install_info(G_TYPE_FROM_CLASS(bt_core_class),
78 &dbus_glib_bt_core_object_info);
81 /*This is part of platform provided code skeleton for client server model*/
82 static void bt_core_init (BtCore *core)
89 BT_CORE_ERROR_TIMEOUT,
92 #define BT_CORE_ERROR (bt_core_error_quark())
94 static GQuark bt_core_error_quark(void)
96 static GQuark quark = 0;
98 quark = g_quark_from_static_string("BtCore");
103 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
105 static GError *bt_core_error(BtCoreError error, const char *err_msg)
107 return g_error_new(BT_CORE_ERROR, error, err_msg, NULL);
110 static int __bt_enable_adapter(void)
117 status = __bt_core_get_status();
118 if (status != BT_DEACTIVATED) {
119 BT_DBG("Invalid state %d", status);
123 __bt_core_set_status(BT_ACTIVATING);
125 ret = system("/usr/etc/bluetooth/bt-stack-up.sh &");
127 BT_DBG("running script failed");
128 ret = system("/usr/etc/bluetooth/bt-dev-end.sh &");
129 __bt_core_set_status(BT_DEACTIVATED);
136 static int __bt_disable_adapter(void)
142 status = __bt_core_get_status();
143 if (status == BT_ACTIVATING) {
144 /* Forcely terminate */
145 if (system("/usr/etc/bluetooth/bt-stack-down.sh &") < 0) {
146 BT_DBG("running script failed");
148 __bt_core_terminate();
150 } else if (status != BT_ACTIVATED) {
151 BT_DBG("Invalid state %d", status);
155 __bt_core_set_status(BT_DEACTIVATING);
157 if (system("/usr/etc/bluetooth/bt-stack-down.sh &") < 0) {
158 BT_DBG("running script failed");
159 __bt_core_set_status( BT_ACTIVATED);
166 static gboolean bt_core_enable_adapter(BtCore *agent,
167 DBusGMethodInvocation *context)
169 char *sender = dbus_g_method_get_sender(context);
175 ret = __bt_enable_adapter();
177 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
178 "Activation failed");
179 dbus_g_method_return_error(context, error);
184 dbus_g_method_return(context);
191 static gboolean bt_core_disable_adapter(BtCore *agent,
192 DBusGMethodInvocation *context)
194 char *sender = dbus_g_method_get_sender(context);
200 ret = __bt_disable_adapter();
202 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
203 "Deactivation failed");
204 dbus_g_method_return_error(context, error);
209 dbus_g_method_return(context);
216 static int __bt_reset_adapter(void)
218 /* Forcely terminate */
219 if (system("/usr/etc/bluetooth/bt-reset-env.sh &") < 0) {
220 BT_DBG("running script failed");
222 __bt_core_terminate();
226 static gboolean bt_core_reset_adapter(BtCore *agent,
227 DBusGMethodInvocation *context)
229 char *sender = dbus_g_method_get_sender(context);
235 ret = __bt_reset_adapter();
237 GError *error = bt_core_error(BT_CORE_ERROR_REJECT,
238 "Deactivation failed");
239 dbus_g_method_return_error(context, error);
244 dbus_g_method_return(context);
251 static void __name_owner_changed(DBusGProxy *object, const char *name,
252 const char *prev, const char *new,
255 if (g_strcmp0(name, "org.bluez") == 0 && *new == '\0') {
256 BT_DBG("BlueZ is terminated");
257 __bt_disable_adapter();
258 __bt_core_terminate();
259 } else if (g_strcmp0(name, "org.projectx.bt") == 0 && *new == '\0') {
260 BT_DBG("bt-service is terminated abnormally");
261 __bt_disable_adapter();
265 static DBusGProxy * __bt_core_register(DBusGConnection *conn, BtCore *bt_core)
271 proxy = dbus_g_proxy_new_for_name(conn, DBUS_SERVICE_DBUS,
272 DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
274 BT_ERR("proxy is NULL");
278 if (!dbus_g_proxy_call(proxy, "RequestName", &err, G_TYPE_STRING,
279 BT_CORE_NAME, G_TYPE_UINT, 0, G_TYPE_INVALID,
280 G_TYPE_UINT, &result, G_TYPE_INVALID)) {
282 BT_ERR("RequestName RPC failed[%s]\n", err->message);
285 g_object_unref(proxy);
289 if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
290 BT_ERR("Failed to get the primary well-known name.\n");
291 g_object_unref(proxy);
295 dbus_g_proxy_add_signal(proxy, "NameOwnerChanged", G_TYPE_STRING,
296 G_TYPE_STRING, G_TYPE_STRING,
299 dbus_g_proxy_connect_signal(proxy, "NameOwnerChanged",
300 G_CALLBACK(__name_owner_changed),
303 dbus_g_connection_register_g_object(conn, BT_CORE_PATH,
309 static void __bt_core_unregister(DBusGConnection *conn, BtCore *bt_core,
310 DBusGProxy *dbus_proxy)
312 if (!bt_core || !dbus_proxy)
315 dbus_g_proxy_disconnect_signal(dbus_proxy, "NameOwnerChanged",
316 G_CALLBACK(__name_owner_changed),
319 dbus_g_connection_unregister_g_object(conn, G_OBJECT(bt_core));
321 g_object_unref(bt_core);
322 g_object_unref(dbus_proxy);
326 static void __adapter_added_cb(DBusGProxy *manager_proxy,
327 const char *adapter_path,
332 __bt_core_set_status(BT_ACTIVATED);
335 static void __adapter_removed_cb(DBusGProxy *manager_proxy,
336 const char *adapter_path,
341 __bt_core_set_status(BT_DEACTIVATED);
343 __bt_core_terminate();
346 static DBusGProxy *__bt_core_manager_init(DBusGConnection *conn)
348 DBusGProxy *manager_proxy;
350 manager_proxy = dbus_g_proxy_new_for_name(conn, "org.bluez", "/",
351 "org.bluez.Manager");
352 if (manager_proxy == NULL) {
353 BT_ERR("ERROR: Can't make manager proxy");
357 dbus_g_proxy_add_signal(manager_proxy, "AdapterAdded",
358 DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
359 dbus_g_proxy_connect_signal(manager_proxy, "AdapterAdded",
360 G_CALLBACK(__adapter_added_cb),
363 dbus_g_proxy_add_signal(manager_proxy, "AdapterRemoved",
364 DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
365 dbus_g_proxy_connect_signal(manager_proxy, "AdapterRemoved",
366 G_CALLBACK(__adapter_removed_cb),
369 return manager_proxy;
374 static void __bt_core_manager_exit(DBusGProxy *manager_proxy)
379 dbus_g_proxy_disconnect_signal(manager_proxy, "AdapterAdded",
380 G_CALLBACK(__adapter_added_cb),
383 dbus_g_proxy_disconnect_signal(manager_proxy, "AdapterRemoved",
384 G_CALLBACK(__adapter_removed_cb),
387 g_object_unref(manager_proxy);
390 static void __bt_core_sigterm_handler(int signo)
392 BT_DBG("Got the signal: %d", signo);
394 __bt_core_terminate();
399 DBusGConnection *conn = NULL;
400 GError *error = NULL;
402 DBusGProxy *manager_proxy = NULL;
403 DBusGProxy *dbus_proxy = NULL;
410 conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
412 BT_ERR("ERROR: Can't get on system bus [%s]", error->message);
417 bt_core = g_object_new(BT_CORE_TYPE, NULL);
418 if (bt_core == NULL) {
419 BT_ERR("bt_service is NULL");
423 dbus_proxy = __bt_core_register(conn, bt_core);
425 BT_ERR("__bt_core_register failed");
426 g_object_unref(bt_core);
431 manager_proxy = __bt_core_manager_init(conn);
432 if (!manager_proxy) {
433 BT_ERR("__bt_core_manager_init failed");
437 main_loop = g_main_loop_new(NULL, FALSE);
439 memset(&sa, 0, sizeof(sa));
440 sa.sa_handler = __bt_core_sigterm_handler;
441 sigaction(SIGINT, &sa, NULL);
442 sigaction(SIGTERM, &sa, NULL);
444 g_main_loop_run(main_loop);
447 __bt_core_unregister(conn, bt_core, dbus_proxy);
449 __bt_core_manager_exit(manager_proxy);
452 g_main_loop_unref(main_loop);
454 dbus_g_connection_unref(conn);