4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Girishashok Joshi <girish.joshi@samsung.com>
8 * Chanyeol Park <chanyeol.park@samsung.com>
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
26 #include <vconf-keys.h>
28 #include "bt-core-adapter.h"
29 #include "bt-core-common.h"
30 #include "bt-core-dbus-handler.h"
31 #include "bt-internal-types.h"
32 #include "bt-core-noti-handler.h"
33 #include "bt-core-main.h"
35 #define BT_SERVICE_NAME "org.projectx.bt"
36 #define BT_SERVICE_PATH "/org/projectx/bt_service"
38 static GDBusConnection *service_gconn;
39 static GDBusProxy *service_gproxy;
41 void _bt_core_fill_garray_from_variant(GVariant *var, GArray *param)
46 size = g_variant_get_size(var);
48 data = (char *)g_variant_get_data(var);
50 param = g_array_append_vals(param, data, size);
55 GDBusConnection * _bt_core_get_gdbus_connection(void)
59 if (service_gconn == NULL)
60 service_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
64 BT_ERR("Unable to connect to dbus: %s", err->message);
73 static GDBusProxy *__bt_core_gdbus_init_service_proxy(void)
77 GDBusConnection *conn;
81 conn = _bt_core_get_gdbus_connection();
85 proxy = g_dbus_proxy_new_sync(conn,
86 G_DBUS_PROXY_FLAGS_NONE, NULL,
93 BT_ERR("Unable to create proxy: %s", err->message);
100 service_gproxy = proxy;
105 GDBusProxy *_bt_core_gdbus_get_service_proxy(void)
107 return (service_gproxy) ? service_gproxy : __bt_core_gdbus_init_service_proxy();
110 void _bt_core_gdbus_deinit_proxys(void)
114 if (service_gproxy) {
115 g_object_unref(service_gproxy);
116 service_gproxy = NULL;
120 g_object_unref(service_gconn);
121 service_gconn = NULL;
125 int _bt_core_service_request(int service_type, int service_function,
126 GArray *in_param1, GArray *in_param2,
127 GArray *in_param3, GArray *in_param4,
138 int result = BLUETOOTH_ERROR_NONE;
139 GError *error = NULL;
140 GArray *in_param5 = NULL;
141 GArray *out_param2 = NULL;
143 proxy = _bt_core_gdbus_get_service_proxy();
145 return BLUETOOTH_ERROR_INTERNAL;
146 in_param5 = g_array_new(TRUE, TRUE, sizeof(gchar));
148 param1 = g_variant_new_from_data((const GVariantType *)"ay",
149 in_param1->data, in_param1->len,
151 param2 = g_variant_new_from_data((const GVariantType *)"ay",
152 in_param2->data, in_param2->len,
154 param3 = g_variant_new_from_data((const GVariantType *)"ay",
155 in_param3->data, in_param3->len,
157 param4 = g_variant_new_from_data((const GVariantType *)"ay",
158 in_param4->data, in_param4->len,
160 param5 = g_variant_new_from_data((const GVariantType *)"ay",
161 in_param5->data, in_param5->len,
164 ret = g_dbus_proxy_call_sync(proxy, "service_request",
165 g_variant_new("(iii@ay@ay@ay@ay@ay)",
166 service_type, service_function,
170 G_DBUS_CALL_FLAGS_NONE, -1,
173 g_array_free(in_param5, TRUE);
176 /* dBUS-RPC is failed */
177 BT_ERR("dBUS-RPC is failed");
180 /* dBUS gives error cause */
181 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
182 error->code, error->message);
184 g_clear_error(&error);
186 /* dBUS does not give error cause dBUS-RPC is failed */
187 BT_ERR("error returned was NULL");
190 return BLUETOOTH_ERROR_INTERNAL;
196 g_variant_get(ret, "(@ay@ay)", ¶m1, ¶m2);
199 *out_param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
200 _bt_core_fill_garray_from_variant(param1, *out_param1);
201 g_variant_unref(param1);
205 out_param2 = g_array_new(TRUE, TRUE, sizeof(gchar));
206 _bt_core_fill_garray_from_variant(param2, out_param2);
207 result = g_array_index(out_param2, int, 0);
208 g_variant_unref(param2);
209 g_array_free(out_param2, TRUE);
211 result = BLUETOOTH_ERROR_INTERNAL;
214 g_variant_unref(ret);
219 static const gchar bt_core_introspection_xml[] =
221 " <interface name='org.projectx.btcore'>"
222 " <method name='EnableAdapter'>"
224 " <method name='DisableAdapter'>"
226 " <method name='RecoverAdapter'>"
228 " <method name='ResetAdapter'>"
230 " <method name='EnableAdapterLe'>"
232 " <method name='DisableAdapterLe'>"
234 " <method name='EnableCore'>"
236 " <method name='FactoryTestMode'>"
237 " <arg type='s' name='type' direction='in'/>"
238 " <arg type='s' name='arg' direction='in'/>"
239 " <arg type='i' name='ret' direction='out'/>"
244 static guint obj_id, sig_id1, sig_id2, sig_id3;
246 static void __bt_core_dbus_method(GDBusConnection *connection,
248 const gchar *object_path,
249 const gchar *interface_name,
250 const gchar *method_name,
251 GVariant *parameters,
252 GDBusMethodInvocation *invocation,
257 BT_DBG("method %s", method_name);
259 if (g_strcmp0(method_name, "EnableAdapter") == 0) {
260 ret = _bt_core_enable_adapter();
261 } else if (g_strcmp0(method_name, "DisableAdapter") == 0) {
262 ret = _bt_core_disable_adapter();
263 } else if (g_strcmp0(method_name, "RecoverAdapter") == 0) {
264 ret = _bt_core_recover_adapter();
265 } else if (g_strcmp0(method_name, "ResetAdapter") == 0) {
266 ret = __bt_core_reset_adapter();
267 } else if (g_strcmp0(method_name, "EnableAdapterLe") == 0) {
268 ret = _bt_core_enable_adapter_le();
269 } else if (g_strcmp0(method_name, "DisableAdapterLe") == 0) {
270 ret = _bt_core_disable_adapter_le();
271 } else if (g_strcmp0(method_name, "EnableCore") == 0) {
272 ret = _bt_core_enable_core();
273 } else if (g_strcmp0(method_name, "FactoryTestMode") == 0) {
274 const char *type = NULL;
275 const char *arg = NULL;
277 g_variant_get(parameters, "(&s&s)", &type, &arg);
278 ret = _bt_core_factory_test_mode(type, arg);
279 g_dbus_method_invocation_return_value(invocation,
280 g_variant_new("(i)", ret));
287 GQuark quark = g_quark_from_string("bt-core");
288 GError *err = g_error_new(quark, 0, "Failed");
289 g_dbus_method_invocation_return_gerror(invocation, err);
292 g_dbus_method_invocation_return_value(invocation, NULL);
298 static const GDBusInterfaceVTable method_table = {
299 __bt_core_dbus_method,
304 static GDBusNodeInfo *__bt_core_create_node_info(
305 const gchar *introspection_data)
308 GDBusNodeInfo *node_info = NULL;
310 if (introspection_data == NULL)
313 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
316 BT_ERR("Unable to create node: %s", err->message);
322 gboolean __is_interface_and_signal_valid(const gchar *interface_name,
323 const gchar *signal_name)
325 if (g_strcmp0(interface_name, "org.freedesktop.DBus") &&
326 g_strcmp0(interface_name, "org.freedesktop.DBus.ObjectManager"))
329 if (g_strcmp0(signal_name, "NameOwnerChanged") &&
330 g_strcmp0(signal_name, "InterfacesAdded") &&
331 g_strcmp0(signal_name, "InterfacesRemoved"))
337 static void __handle_name_owner_changed(const char *name)
339 gboolean flight_mode_status;
343 flight_mode_status = _bt_core_is_flight_mode_enabled();
345 if (flight_mode_status == FALSE && _bt_is_flightmode_request() == TRUE) {
346 BT_DBG("flightmode requested");
350 if ((g_strcmp0(name, "org.bluez") == 0) ||
351 (g_strcmp0(name, "org.projectx.bt") == 0)) {
352 BT_DBG("%s is terminated", name);
353 if (_bt_check_terminating_condition() == TRUE) {
354 _bt_disable_adapter();
355 _bt_disable_adapter_le();
356 _bt_core_terminate();
361 static void __bt_core_event_filter(GDBusConnection *connection,
362 const gchar *sender_name,
363 const gchar *object_path,
364 const gchar *interface_name,
365 const gchar *signal_name,
366 GVariant *parameters,
369 if (!__is_interface_and_signal_valid(interface_name, signal_name))
372 if (!g_strcmp0(signal_name, "InterfacesAdded")) {
373 char *obj_path = NULL;
374 GVariant *optional_param;
376 g_variant_get(parameters, "(&o@a{sa{sv}})",
377 &obj_path, &optional_param);
379 if (g_strcmp0(obj_path, "/org/bluez/hci0") == 0) {
380 _bt_core_adapter_added_cb();
382 } else if (!g_strcmp0(signal_name, "InterfacesRemoved")) {
383 char *obj_path = NULL;
384 GVariant *optional_param;
386 g_variant_get(parameters, "(&o@as)", &obj_path,
389 if (g_strcmp0(obj_path, "/org/bluez/hci0") == 0) {
390 _bt_core_adapter_removed_cb();
392 } else { /* NameOwnerChanged */
393 const char *name = NULL;
394 const char *old_owner = NULL;
395 const char *new_owner = NULL;
397 g_variant_get(parameters, "(&s&s&s)", &name, &old_owner,
400 if (new_owner != NULL && *new_owner == '\0')
401 __handle_name_owner_changed(name);
405 gboolean _bt_core_register_dbus(void)
407 GError *error = NULL;
409 GDBusNodeInfo *node_info;
411 GDBusConnection *conn;
413 conn = _bt_core_get_gdbus_connection();
417 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
419 G_BUS_NAME_OWNER_FLAGS_NONE,
423 BT_DBG("owner_id is [%d]", owner_id);
425 node_info = __bt_core_create_node_info(bt_core_introspection_xml);
426 if (node_info == NULL)
429 path = g_strdup(BT_CORE_PATH);
430 BT_DBG("path is [%s]", path);
432 obj_id = g_dbus_connection_register_object(conn, path,
433 node_info->interfaces[0],
437 BT_ERR("Failed to register: %s", error->message);
445 sig_id1 = g_dbus_connection_signal_subscribe(conn,
446 NULL, "org.freedesktop.DBus",
447 "NameOwnerChanged", NULL, NULL, 0,
448 __bt_core_event_filter, NULL, NULL);
449 sig_id2 = g_dbus_connection_signal_subscribe(conn,
450 NULL, "org.freedesktop.DBus.ObjectManager",
451 "InterfacesAdded", NULL, NULL,
452 0, __bt_core_event_filter, NULL, NULL);
453 sig_id2 = g_dbus_connection_signal_subscribe(conn,
454 NULL, "org.freedesktop.DBus.ObjectManager",
455 "InterfacesRemoved", NULL,
456 NULL, 0, __bt_core_event_filter, NULL, NULL);
461 void _bt_core_unregister_dbus(void)
463 GDBusConnection *conn;
467 conn = _bt_core_get_gdbus_connection();
472 g_dbus_connection_unregister_object(conn, obj_id);
477 g_dbus_connection_signal_unsubscribe(conn, sig_id1);
481 g_dbus_connection_signal_unsubscribe(conn, sig_id2);
485 g_dbus_connection_signal_unsubscribe(conn, sig_id3);