2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <vconf-keys.h>
22 #include "bt-core-adapter.h"
23 #include "bt-core-common.h"
24 #include "bt-core-dbus-handler.h"
25 #include "bt-internal-types.h"
26 #include "bt-core-noti-handler.h"
27 #include "bt-core-main.h"
29 #define BT_SERVICE_NAME "org.projectx.bt"
30 #define BT_SERVICE_PATH "/org/projectx/bt_service"
32 #ifdef TIZEN_FEATURE_BT_HPS
33 #define BT_HPS_SERVICE_NAME "org.projectx.httpproxy"
34 #define BT_HPS_OBJECT_PATH "/org/projectx/httpproxy"
35 #define BT_HPS_INTERFACE_NAME "org.projectx.httpproxy_service"
38 #ifdef TIZEN_FEATURE_BT_OTP
39 #define BT_OTP_SERVICE_NAME "org.projectx.otp"
40 #define BT_OTP_OBJECT_PATH "/org/projectx/otp"
41 #define BT_OTP_INTERFACE_NAME "org.projectx.otp_service"
44 static GDBusConnection *service_gconn;
45 static GDBusProxy *service_gproxy;
46 #ifdef TIZEN_FEATURE_BT_HPS
47 static GDBusProxy *hps_gproxy;
50 #ifdef TIZEN_FEATURE_BT_OTP
51 static GDBusProxy *otp_gproxy;
54 void _bt_core_fill_garray_from_variant(GVariant *var, GArray *param)
59 size = g_variant_get_size(var);
61 data = (char *)g_variant_get_data(var);
63 param = g_array_append_vals(param, data, size);
68 GDBusConnection * _bt_core_get_gdbus_connection(void)
72 if (service_gconn == NULL)
73 service_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
77 BT_ERR("Unable to connect to dbus: %s", err->message);
86 static GDBusProxy *__bt_core_gdbus_init_service_proxy(void)
90 GDBusConnection *conn;
92 conn = _bt_core_get_gdbus_connection();
96 proxy = g_dbus_proxy_new_sync(conn,
97 G_DBUS_PROXY_FLAGS_NONE, NULL,
104 BT_ERR("Unable to create proxy: %s", err->message);
111 service_gproxy = proxy;
116 GDBusProxy *_bt_core_gdbus_get_service_proxy(void)
118 return (service_gproxy) ? service_gproxy : __bt_core_gdbus_init_service_proxy();
121 #ifdef TIZEN_FEATURE_BT_HPS
122 int _bt_core_start_httpproxy(void)
124 GVariant *variant = NULL;
125 unsigned char enabled;
129 hps_gproxy = _bt_core_gdbus_get_hps_proxy();
131 BT_DBG("Couldn't get service proxy");
135 variant = g_dbus_proxy_call_sync(hps_gproxy, "enable",
136 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
138 BT_ERR("Error : %s" , err->message);
142 g_variant_get(variant, "(y)", &enabled);
143 BT_ERR("HPS enabled status 0x%x", enabled);
148 int _bt_core_stop_httpproxy(void)
150 GVariant *variant = NULL;
151 unsigned char enabled;
155 hps_gproxy = _bt_core_gdbus_get_hps_proxy();
157 BT_DBG("Couldn't get service proxy");
161 variant = g_dbus_proxy_call_sync(hps_gproxy, "disable",
162 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
164 BT_ERR("Error : %s" , err->message);
168 g_variant_get(variant, "(y)", &enabled);
169 BT_ERR("HPS disabled status 0x%x", enabled);
174 static GDBusProxy *_bt_core_gdbus_init_hps_proxy(void)
178 GDBusConnection *conn;
182 conn = _bt_core_get_gdbus_connection();
186 proxy = g_dbus_proxy_new_sync(conn,
187 G_DBUS_PROXY_FLAGS_NONE, NULL,
190 BT_HPS_INTERFACE_NAME,
194 BT_ERR("Unable to create proxy: %s", err->message);
205 GDBusProxy *_bt_core_gdbus_get_hps_proxy(void)
207 return (hps_gproxy) ? hps_gproxy : _bt_core_gdbus_init_hps_proxy();
211 #ifdef TIZEN_FEATURE_BT_OTP
212 static GDBusProxy *_bt_core_gdbus_init_otp_proxy(void)
216 GDBusConnection *conn;
220 conn = _bt_core_get_gdbus_connection();
224 proxy = g_dbus_proxy_new_sync(conn,
225 G_DBUS_PROXY_FLAGS_NONE, NULL,
228 BT_OTP_INTERFACE_NAME,
232 BT_ERR("Unable to create proxy: %s", err->message);
243 GDBusProxy *_bt_core_gdbus_get_otp_proxy(void)
245 return (otp_gproxy) ? otp_gproxy : _bt_core_gdbus_init_otp_proxy();
248 int _bt_core_stop_otp(void)
250 GVariant *variant = NULL;
251 unsigned char enabled;
255 otp_gproxy = _bt_core_gdbus_get_otp_proxy();
257 BT_DBG("Couldn't get service proxy");
261 variant = g_dbus_proxy_call_sync(otp_gproxy, "disable",
262 NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
264 BT_ERR("Error : %s" , err->message);
268 g_variant_get(variant, "(y)", &enabled);
269 BT_ERR("OTP disabled status 0x%x", enabled);
274 void _bt_core_gdbus_deinit_proxys(void)
278 if (service_gproxy) {
279 g_object_unref(service_gproxy);
280 service_gproxy = NULL;
283 #ifdef TIZEN_FEATURE_BT_HPS
285 g_object_unref(hps_gproxy);
290 #ifdef TIZEN_FEATURE_BT_OTP
292 g_object_unref(otp_gproxy);
298 g_object_unref(service_gconn);
299 service_gconn = NULL;
303 int _bt_core_service_request(int service_type, int service_function,
304 GArray *in_param1, GArray *in_param2,
305 GArray *in_param3, GArray *in_param4,
309 GVariant *ret = NULL;
316 int result = BLUETOOTH_ERROR_NONE;
317 GError *error = NULL;
318 GArray *in_param5 = NULL;
322 proxy = _bt_core_gdbus_get_service_proxy();
324 return BLUETOOTH_ERROR_INTERNAL;
325 in_param5 = g_array_new(TRUE, TRUE, sizeof(gchar));
327 while (--retry >= 0) {
328 param1 = g_variant_new_from_data((const GVariantType *)"ay",
329 in_param1->data, in_param1->len,
331 param2 = g_variant_new_from_data((const GVariantType *)"ay",
332 in_param2->data, in_param2->len,
334 param3 = g_variant_new_from_data((const GVariantType *)"ay",
335 in_param3->data, in_param3->len,
337 param4 = g_variant_new_from_data((const GVariantType *)"ay",
338 in_param4->data, in_param4->len,
340 param5 = g_variant_new_from_data((const GVariantType *)"ay",
341 in_param5->data, in_param5->len,
344 ret = g_dbus_proxy_call_sync(proxy, "service_request",
345 g_variant_new("(iii@ay@ay@ay@ay@ay)",
346 service_type, service_function,
350 G_DBUS_CALL_FLAGS_NONE, 2000,
352 if (ret == NULL && error != NULL) {
353 if (error->code == G_IO_ERROR_TIMED_OUT) {
354 BT_ERR("D-Bus Timed out.");
355 g_clear_error(&error);
363 g_array_free(in_param5, TRUE);
366 /* dBUS-RPC is failed */
367 BT_ERR("dBUS-RPC is failed");
370 /* dBUS gives error cause */
371 BT_ERR("D-Bus API failure: errCode[%x], message[%s]",
372 error->code, error->message);
374 g_clear_error(&error);
376 /* dBUS does not give error cause dBUS-RPC is failed */
377 BT_ERR("error returned was NULL");
380 return BLUETOOTH_ERROR_INTERNAL;
385 g_variant_get(ret, "(iv)", &result, ¶m1);
388 *out_param1 = g_array_new(TRUE, TRUE, sizeof(gchar));
389 _bt_core_fill_garray_from_variant(param1, *out_param1);
390 g_variant_unref(param1);
393 g_variant_unref(ret);
398 static const gchar bt_core_introspection_xml[] =
400 " <interface name='org.projectx.btcore'>"
401 " <method name='EnableAdapter'>"
403 " <method name='DisableAdapter'>"
405 " <method name='RecoverAdapter'>"
407 " <method name='ResetAdapter'>"
409 " <method name='EnableAdapterLe'>"
411 " <method name='DisableAdapterLe'>"
413 " <method name='EnableCore'>"
415 " <method name='SetTransferValue'>"
416 " <arg type='b' name='value' direction='in'/>"
418 " <method name='FactoryTestMode'>"
419 " <arg type='s' name='type' direction='in'/>"
420 " <arg type='s' name='arg' direction='in'/>"
421 " <arg type='i' name='ret' direction='out'/>"
426 static guint obj_id, sig_id1, sig_id2, sig_id3;
428 static void __bt_core_dbus_method(GDBusConnection *connection,
430 const gchar *object_path,
431 const gchar *interface_name,
432 const gchar *method_name,
433 GVariant *parameters,
434 GDBusMethodInvocation *invocation,
439 BT_DBG("method %s", method_name);
441 if (g_strcmp0(method_name, "EnableAdapter") == 0) {
442 ret = _bt_core_enable_adapter();
443 } else if (g_strcmp0(method_name, "DisableAdapter") == 0) {
444 ret = _bt_core_disable_adapter();
445 } else if (g_strcmp0(method_name, "RecoverAdapter") == 0) {
446 ret = _bt_core_recover_adapter();
447 } else if (g_strcmp0(method_name, "ResetAdapter") == 0) {
448 ret = __bt_core_reset_adapter();
449 } else if (g_strcmp0(method_name, "EnableAdapterLe") == 0) {
450 ret = _bt_core_enable_adapter_le();
451 } else if (g_strcmp0(method_name, "DisableAdapterLe") == 0) {
452 ret = _bt_core_disable_adapter_le();
453 } else if (g_strcmp0(method_name, "EnableCore") == 0) {
454 ret = _bt_core_enable_core();
455 } else if (g_strcmp0(method_name, "SetTransferValue") == 0) {
456 gboolean value = FALSE;
458 g_variant_get(parameters, "(b)", &value);
459 BT_DBG("Transfer value: %d", value);
461 ret = _bt_core_set_transfer_value(value);
462 } else if (g_strcmp0(method_name, "FactoryTestMode") == 0) {
463 const char *type = NULL;
464 const char *arg = NULL;
466 g_variant_get(parameters, "(&s&s)", &type, &arg);
467 ret = _bt_core_factory_test_mode(type, arg);
468 g_dbus_method_invocation_return_value(invocation,
469 g_variant_new("(i)", ret));
476 GQuark quark = g_quark_from_string("bt-core");
477 GError *err = g_error_new(quark, 0, "Failed");
478 g_dbus_method_invocation_return_gerror(invocation, err);
481 g_dbus_method_invocation_return_value(invocation, NULL);
487 static const GDBusInterfaceVTable method_table = {
488 __bt_core_dbus_method,
493 static GDBusNodeInfo *__bt_core_create_node_info(
494 const gchar *introspection_data)
497 GDBusNodeInfo *node_info = NULL;
499 if (introspection_data == NULL)
502 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
505 BT_ERR("Unable to create node: %s", err->message);
511 gboolean __is_interface_and_signal_valid(const gchar *interface_name,
512 const gchar *signal_name)
514 if (g_strcmp0(interface_name, "org.freedesktop.DBus") &&
515 g_strcmp0(interface_name, "org.freedesktop.DBus.ObjectManager"))
518 if (g_strcmp0(signal_name, "NameOwnerChanged") &&
519 g_strcmp0(signal_name, "InterfacesAdded") &&
520 g_strcmp0(signal_name, "InterfacesRemoved"))
526 static void __handle_name_owner_changed(const char *name)
528 gboolean flight_mode_status;
532 flight_mode_status = _bt_core_is_flight_mode_enabled();
534 if (flight_mode_status == FALSE && _bt_is_flightmode_request() == TRUE) {
535 BT_DBG("flightmode requested");
539 if ((g_strcmp0(name, "org.bluez") == 0) ||
540 (g_strcmp0(name, "org.projectx.bt") == 0)) {
541 BT_DBG("%s is terminated", name);
542 if (_bt_check_terminating_condition() == TRUE) {
543 _bt_disable_adapter();
544 _bt_disable_adapter_le();
545 _bt_core_terminate();
550 static void __bt_core_event_filter(GDBusConnection *connection,
551 const gchar *sender_name,
552 const gchar *object_path,
553 const gchar *interface_name,
554 const gchar *signal_name,
555 GVariant *parameters,
558 if (!__is_interface_and_signal_valid(interface_name, signal_name))
561 if (!g_strcmp0(signal_name, "InterfacesAdded")) {
562 char *obj_path = NULL;
563 GVariant *optional_param;
565 g_variant_get(parameters, "(&o@a{sa{sv}})",
566 &obj_path, &optional_param);
568 if (g_strcmp0(obj_path, "/org/bluez/hci0") == 0)
569 _bt_core_adapter_added_cb();
571 } else if (!g_strcmp0(signal_name, "InterfacesRemoved")) {
572 char *obj_path = NULL;
573 GVariant *optional_param;
575 g_variant_get(parameters, "(&o@as)", &obj_path,
578 if (g_strcmp0(obj_path, "/org/bluez/hci0") == 0)
579 _bt_core_adapter_removed_cb();
581 } else { /* NameOwnerChanged */
582 const char *name = NULL;
583 const char *old_owner = NULL;
584 const char *new_owner = NULL;
586 g_variant_get(parameters, "(&s&s&s)", &name, &old_owner,
589 if (new_owner != NULL && *new_owner == '\0')
590 __handle_name_owner_changed(name);
594 gboolean _bt_core_register_dbus(void)
596 GError *error = NULL;
598 GDBusNodeInfo *node_info;
600 GDBusConnection *conn;
602 conn = _bt_core_get_gdbus_connection();
606 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
608 G_BUS_NAME_OWNER_FLAGS_NONE,
612 BT_DBG("owner_id is [%d]", owner_id);
614 node_info = __bt_core_create_node_info(bt_core_introspection_xml);
615 if (node_info == NULL)
618 path = g_strdup(BT_CORE_PATH);
619 BT_DBG("path is [%s]", path);
621 obj_id = g_dbus_connection_register_object(conn, path,
622 node_info->interfaces[0],
625 g_dbus_node_info_unref(node_info);
627 BT_ERR("Failed to register: %s", error->message);
635 sig_id1 = g_dbus_connection_signal_subscribe(conn,
636 NULL, "org.freedesktop.DBus",
637 "NameOwnerChanged", NULL, NULL, 0,
638 __bt_core_event_filter, NULL, NULL);
639 sig_id2 = g_dbus_connection_signal_subscribe(conn,
640 NULL, "org.freedesktop.DBus.ObjectManager",
641 "InterfacesAdded", NULL, NULL,
642 0, __bt_core_event_filter, NULL, NULL);
643 sig_id2 = g_dbus_connection_signal_subscribe(conn,
644 NULL, "org.freedesktop.DBus.ObjectManager",
645 "InterfacesRemoved", NULL,
646 NULL, 0, __bt_core_event_filter, NULL, NULL);
651 void _bt_core_unregister_dbus(void)
653 GDBusConnection *conn;
657 conn = _bt_core_get_gdbus_connection();
662 g_dbus_connection_unregister_object(conn, obj_id);
667 g_dbus_connection_signal_unsubscribe(conn, sig_id1);
671 g_dbus_connection_signal_unsubscribe(conn, sig_id2);
675 g_dbus_connection_signal_unsubscribe(conn, sig_id3);