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.
23 #include <vconf-keys.h>
25 #include "bt-common.h"
26 #include "bluetooth-telephony-api.h"
27 #include "bt-internal-types.h"
29 #define BT_SCO_TIMEOUT 3000
31 #define BT_CVSD_CODEC_ID 1
32 #define BT_MSBC_CODEC_ID 2
35 GDBusConnection *conn;
37 GDBusProxy *dbus_proxy;
38 GDBusProxy *manager_proxy;
39 } telephony_dbus_info_t;
42 bt_telephony_func_ptr cb;
43 unsigned int call_count;
45 char address[BT_ADDRESS_STR_LEN];
46 char call_path[BT_AUDIO_CALL_PATH_LEN];
47 bluetooth_headset_state_t headset_state;
49 } bt_telephony_info_t;
52 char *src_addr = NULL;
55 #define BLUETOOTH_TELEPHONY_ERROR (__bluetooth_telephony_error_quark())
57 #define BLUEZ_SERVICE_NAME "org.bluez"
58 #define BLUEZ_HEADSET_INTERFACE "org.bluez.Headset"
60 #define BLUEZ_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager"
61 #define BLUEZ_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
62 #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1"
63 #define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1"
64 #define HFP_AGENT_SERVICE "org.bluez.ag_agent"
67 #define HFP_AGENT_PATH "/org/bluez/hfp_agent"
68 #define HFP_AGENT_INTERFACE "Org.Hfp.App.Interface"
70 #define TELEPHONY_APP_INTERFACE "org.tizen.csd.Call.Instance"
71 #define CSD_CALL_APP_PATH "/org/tizen/csd/%d"
72 #define HFP_NREC_STATUS_CHANGE "NrecStatusChanged"
73 #define HFP_ANSWER_CALL "Answer"
74 #define HFP_REJECT_CALL "Reject"
75 #define HFP_RELEASE_CALL "Release"
76 #define HFP_THREEWAY_CALL "Threeway"
78 #define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
80 /*Below Inrospection data is exposed to bluez from agent*/
81 static const gchar bt_telephony_introspection_xml[] =
83 " <interface name='org.tizen.csd.Call.Instance'>"
84 " <method name='SendDtmf'>"
85 " <arg type='s' name='dtmf' direction='in'/>"
87 " <method name='VendorCmd'>"
88 " <arg type='s' name='vendor' direction='in'/>"
93 #define BT_TELEPHONY_CHECK_ENABLED() \
95 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) { \
96 BT_ERR("BT is not enabled"); \
97 return BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED; \
101 static gboolean is_initialized = FALSE;
102 #define BT_TELEPHONY_CHECK_INITIALIZED() \
104 if (is_initialized == FALSE) { \
105 BT_ERR("Bluetooth telephony not initilized"); \
106 return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED; \
110 static void __bt_telephony_adapter_filter(GDBusConnection *connection,
111 const gchar *sender_name,
112 const gchar *object_path,
113 const gchar *interface_name,
114 const gchar *signal_name,
115 GVariant *parameters,
118 static int __bt_telephony_get_src_addr(GVariant *value);
120 static bt_telephony_info_t telephony_info;
121 static telephony_dbus_info_t telephony_dbus_info;
122 static gboolean is_active = FALSE;
124 /*Function Declaration*/
125 static int __bt_telephony_get_error(const char *error_message);
126 static void __bt_telephony_event_cb(int event, int result, void *param_data);
127 static GQuark __bluetooth_telephony_error_quark(void);
128 static GVariant *__bluetooth_telephony_dbus_method_send(const char *path,
129 const char *interface, const char *method,
130 GError **err, GVariant *parameters);
131 static int __bluetooth_telephony_send_call_status(
132 bt_telephony_call_status_t call_status,
133 unsigned int call_id, const char *ph_number);
134 static void __bluetooth_telephony_error(GDBusMethodInvocation *invocation,
135 bluetooth_telephony_error_t error, const char *err_msg);
137 static void __bluetooth_telephony_event_filter(GDBusConnection *connection,
138 const gchar *sender_name,
139 const gchar *object_path,
140 const gchar *interface_name,
141 const gchar *signal_name,
142 GVariant *parameters,
145 static int __bluetooth_telephony_proxy_init(void);
146 static void __bluetooth_telephony_proxy_deinit(void);
147 static int __bluetooth_telephony_register(void);
148 static int __bluetooth_telephony_unregister(void);
150 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class);
151 static int __bluetooth_telephony_get_connected_device(void);
152 static GDBusProxy *__bluetooth_telephony_get_connected_device_proxy(void);
154 /*Function Definition*/
155 static void __bt_telephony_method(GDBusConnection *connection,
157 const gchar *object_path,
158 const gchar *interface_name,
159 const gchar *method_name,
160 GVariant *parameters,
161 GDBusMethodInvocation *invocation,
166 BT_INFO("method %s", method_name);
167 BT_INFO("object_path %s", object_path);
169 if (g_strcmp0(method_name, "SendDtmf") == 0) {
171 telephony_event_dtmf_t call_data = { 0, };
173 g_variant_get(parameters, "(&s)", &dtmf);
176 BT_ERR("Number dial failed");
177 __bluetooth_telephony_error(invocation,
178 BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF,
181 DBG_SECURE("Dtmf = %s", dtmf);
183 call_data.dtmf = g_strdup(dtmf);
184 __bt_telephony_event_cb(
185 BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF,
186 BLUETOOTH_TELEPHONY_ERROR_NONE,
189 g_free(call_data.dtmf);
191 g_dbus_method_invocation_return_value(invocation, NULL);
193 } else if (g_strcmp0(method_name, "VendorCmd") == 0) {
196 g_variant_get(parameters, "(&s)", &at_cmd);
197 BT_INFO("Vendor %s", at_cmd);
198 if (at_cmd == NULL) {
199 BT_ERR("Vendor command is NULL\n");
200 __bluetooth_telephony_error(invocation,
201 BLUETOOTH_TELEPHONY_ERROR_APPLICATION,
202 "Invalid at vendor cmd");
204 DBG_SECURE("Vendor AT cmd = %s", at_cmd);
206 __bt_telephony_event_cb(
207 BLUETOOTH_EVENT_TELEPHONY_VENDOR_AT_CMD,
208 BLUETOOTH_TELEPHONY_ERROR_NONE,
211 g_dbus_method_invocation_return_value(invocation, NULL);
218 static const GDBusInterfaceVTable method_table = {
219 __bt_telephony_method,
224 static int __bt_telephony_get_error(const char *error_message)
226 if (error_message == NULL) {
227 BT_ERR("Error message NULL");
228 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
231 BT_ERR("Error message = %s", error_message);
232 if (g_strcmp0(error_message, "NotAvailable") == 0)
233 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
234 else if (g_strcmp0(error_message, "NotConnected") == 0)
235 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
236 else if (g_strcmp0(error_message, "InProgress") == 0)
237 return BLUETOOTH_TELEPHONY_ERROR_BUSY;
238 else if (g_strcmp0(error_message, "InvalidArguments") == 0)
239 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
240 else if (g_strcmp0(error_message, "AlreadyExists") == 0)
241 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST;
242 else if (g_strcmp0(error_message, "Already Connected") == 0)
243 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
244 else if (g_strcmp0(error_message, "No memory") == 0)
245 return BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY;
246 else if (g_strcmp0(error_message, "I/O error") == 0)
247 return BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR;
248 else if (g_strcmp0(error_message,
249 "Operation currently not available") == 0)
250 return BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE;
251 else if (g_strrstr(error_message, BT_ACCESS_DENIED_MSG))
252 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
254 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
257 static int __bt_telephony_check_privilege(void)
264 reply = __bluetooth_telephony_dbus_method_send(
265 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
266 "CheckPrivilege", &err, NULL);
269 BT_ERR("Error returned in method call");
271 g_dbus_error_strip_remote_error(err);
272 ret = __bt_telephony_get_error(err->message);
276 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
278 g_variant_unref(reply);
281 return BLUETOOTH_TELEPHONY_ERROR_NONE;
284 static void __bt_telephony_event_cb(int event, int result, void *param_data)
286 telephony_event_param_t bt_event = { 0, };
288 bt_event.event = event;
289 bt_event.result = result;
290 bt_event.param_data = param_data;
292 ret_if(telephony_info.cb == NULL);
293 telephony_info.cb(bt_event.event, &bt_event, telephony_info.user_data);
297 static GQuark __bluetooth_telephony_error_quark(void)
299 static GQuark quark = 0;
301 quark = g_quark_from_static_string("telephony");
306 static GVariant *__bluetooth_telephony_dbus_method_send(const char *path,
307 const char *interface, const char *method,
308 GError **err, GVariant *parameters)
312 if (TIZEN_PROFILE_WEARABLE || TIZEN_PROFILE_IVI)
317 GDBusConnection *conn;
321 conn = telephony_dbus_info.conn;
322 retv_if(conn == NULL, NULL);
324 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
325 NULL, HFP_AGENT_SERVICE, path, interface, NULL, err);
327 BT_ERR("Unable to allocate new proxy");
331 reply = g_dbus_proxy_call_sync(proxy, method, parameters,
332 G_DBUS_CALL_FLAGS_NONE, timeout, NULL, err);
334 g_object_unref(proxy);
339 static int __bluetooth_telephony_send_call_status(
340 bt_telephony_call_status_t call_status,
341 unsigned int call_id, const char *ph_number)
346 char *path = g_strdup(telephony_info.call_path);
352 if (NULL == ph_number)
353 phone_number = g_strdup("");
355 phone_number = g_strdup(ph_number);
357 param = g_variant_new("(ssii)", path, phone_number,
358 call_status, call_id);
359 reply = __bluetooth_telephony_dbus_method_send(
360 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
361 "ChangeCallStatus", &err, param);
364 g_free(phone_number);
367 BT_ERR("Error returned in method call");
369 g_dbus_error_strip_remote_error(err);
370 ret = __bt_telephony_get_error(err->message);
374 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
377 g_variant_unref(reply);
379 return BLUETOOTH_TELEPHONY_ERROR_NONE;
382 static void __bluetooth_telephony_error(GDBusMethodInvocation *invocation,
383 bluetooth_telephony_error_t error, const char *err_msg)
385 g_dbus_method_invocation_return_error(invocation,
386 BLUETOOTH_TELEPHONY_ERROR, error,
390 static void __bluetooth_telephony_answer_call(GVariant *var)
392 telephony_event_callid_t call_data = { 0, };
397 g_variant_get(var, "(u)", &callid);
398 BT_DBG("call_id = [%d]", callid);
399 call_data.callid = callid;
401 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL,
402 BLUETOOTH_TELEPHONY_ERROR_NONE,
407 static void __bluetooth_telephony_release_call(GVariant *var)
409 telephony_event_callid_t call_data = { 0, };
414 g_variant_get(var, "(u)", &callid);
415 BT_DBG("call_id = [%d]", callid);
416 call_data.callid = callid;
418 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL,
419 BLUETOOTH_TELEPHONY_ERROR_NONE,
424 static void __bluetooth_telephony_reject_call(GVariant *var)
426 telephony_event_callid_t call_data = { 0, };
431 g_variant_get(var, "(u)", &callid);
432 BT_DBG("call_id = [%d]", callid);
433 call_data.callid = callid;
435 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_REJECT_CALL,
436 BLUETOOTH_TELEPHONY_ERROR_NONE,
441 static void __bluetooth_telephony_threeway_call(GVariant *var)
444 unsigned int chld_value;
448 g_variant_get(var, "(u)", &chld_value);
449 BT_DBG("chld value = [%d]", chld_value);
451 switch (chld_value) {
453 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL;
456 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL;
459 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL;
462 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL;
465 BT_ERR("Invalid CHLD command");
469 __bt_telephony_event_cb(event,
470 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
474 static void __bluetooth_handle_nrec_status_change(GVariant *var)
476 gboolean status = FALSE;
478 g_variant_get(var, "(b)", &status);
479 BT_INFO("NREC status = %d", status);
481 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED,
482 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&status);
486 static void __bluetooth_telephony_event_filter(GDBusConnection *connection,
487 const gchar *sender_name,
488 const gchar *object_path,
489 const gchar *interface_name,
490 const gchar *signal_name,
491 GVariant *parameters,
496 if (strcasecmp(interface_name, HFP_AGENT_SERVICE) == 0) {
497 if (strcasecmp(signal_name, HFP_NREC_STATUS_CHANGE) == 0)
498 __bluetooth_handle_nrec_status_change(parameters);
499 else if (strcasecmp(signal_name, HFP_ANSWER_CALL) == 0)
500 __bluetooth_telephony_answer_call(parameters);
501 else if (strcasecmp(signal_name, HFP_REJECT_CALL) == 0)
502 __bluetooth_telephony_reject_call(parameters);
503 else if (strcasecmp(signal_name, HFP_RELEASE_CALL) == 0)
504 __bluetooth_telephony_release_call(parameters);
505 else if (strcasecmp(signal_name, HFP_THREEWAY_CALL) == 0)
506 __bluetooth_telephony_threeway_call(parameters);
507 } else if (strcasecmp(interface_name, BLUEZ_HEADSET_INTERFACE) == 0) {
508 if (strcasecmp(signal_name, "PropertyChanged") == 0) {
512 g_variant_get(parameters, "(&sv)", &property, &values);
513 BT_DBG("Property: %s", property);
515 if (strcasecmp(property, "State") == 0) {
517 state = (gchar *)g_variant_get_string(values, NULL);
520 BT_ERR("State is null");
523 BT_DBG("state: %s", state);
524 if (g_strcmp0(state, "connected") == 0) {
525 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
526 } else if (g_strcmp0(state, "playing") == 0) {
527 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
528 } else if (g_strcmp0(state, "disconnected") == 0) {
529 /* Headset state: playing -> disconnected */
530 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) {
531 __bt_telephony_event_cb(
532 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
533 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
536 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
538 } else if (strcasecmp(property, "Connected") == 0) {
539 gboolean connected = FALSE;
540 char *dev_addr = NULL;
541 connected = g_variant_get_boolean(values);
542 BT_INFO("connected %d", connected);
544 /*Get device address*/
545 if (object_path != NULL)
546 dev_addr = strstr(object_path, "dev_");
548 if (dev_addr != NULL) {
550 g_strlcpy(telephony_info.address,
552 sizeof(telephony_info.address));
553 g_strdelimit(telephony_info.address, "_", ':');
554 BT_DBG("address is %s",
555 telephony_info.address);
557 telephony_info.headset_state =
558 BLUETOOTH_STATE_CONNECTED;
560 if (telephony_dbus_info.proxy != NULL) {
561 g_object_unref(telephony_dbus_info.proxy);
562 telephony_dbus_info.proxy = NULL;
565 telephony_dbus_info.proxy =
566 __bluetooth_telephony_get_connected_device_proxy();
568 BT_INFO("Headset Connected");
570 __bt_telephony_event_cb(
571 BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED,
572 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
574 } else { /*Device disconnected*/
575 memset(telephony_info.address, 0x00,
576 sizeof(telephony_info.address));
577 telephony_info.headset_state =
578 BLUETOOTH_STATE_DISCONNETED;
580 if (telephony_dbus_info.proxy != NULL) {
581 g_object_unref(telephony_dbus_info.proxy);
582 telephony_dbus_info.proxy = NULL;
585 BT_INFO("Headset Disconnected");
587 __bt_telephony_event_cb(
588 BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED,
589 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
591 } else if (strcasecmp(property, "SpeakerGain") == 0) {
592 unsigned int spkr_gain;
593 guint16 gain = g_variant_get_uint16(values);
595 spkr_gain = (unsigned int)gain;
596 BT_DBG("spk_gain[%d]", spkr_gain);
598 __bt_telephony_event_cb(
599 BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN,
600 BLUETOOTH_TELEPHONY_ERROR_NONE,
602 } else if (strcasecmp(property, "MicrophoneGain") == 0) {
603 unsigned int mic_gain;
604 guint16 gain = g_variant_get_uint16(values);
606 mic_gain = (unsigned int)gain;
607 BT_DBG("mic_gain[%d]", mic_gain);
609 __bt_telephony_event_cb(
610 BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN,
611 BLUETOOTH_TELEPHONY_ERROR_NONE,
613 } else if (strcasecmp(property, "Playing") == 0) {
614 gboolean audio_sink_playing;
616 audio_sink_playing = g_variant_get_boolean(values);
617 if (audio_sink_playing) {
618 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
619 __bt_telephony_event_cb(
620 BLUETOOTH_EVENT_TELEPHONY_AUDIO_CONNECTED,
621 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
623 telephony_info.headset_state =
624 BLUETOOTH_STATE_CONNECTED;
625 __bt_telephony_event_cb(
626 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
627 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
631 g_variant_unref(values);
637 static GDBusNodeInfo *__bt_telephony_create_method_node_info
638 (const gchar *introspection_data)
641 GDBusNodeInfo *node_info = NULL;
643 if (introspection_data == NULL)
646 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
649 BT_ERR("Unable to create node: %s", err->message);
656 int __bluetooth_telephony_register_object(int reg, GDBusNodeInfo *node_info)
658 static guint bt_tel_id = 0;
659 GError *error = NULL;
663 if (node_info == NULL)
664 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
666 path = g_strdup(telephony_info.call_path);
667 BT_DBG("path is [%s]", path);
669 bt_tel_id = g_dbus_connection_register_object(telephony_dbus_info.conn,
670 path, node_info->interfaces[0],
675 if (bt_tel_id == 0) {
676 BT_ERR("Failed to register: %s", error->message);
678 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
682 g_dbus_connection_unregister_object(telephony_dbus_info.conn,
688 return BLUETOOTH_TELEPHONY_ERROR_NONE;
691 static int __bluetooth_telephony_proxy_init(void)
695 GDBusNodeInfo *node_info;
697 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
698 TELEPHONY_APP_INTERFACE,
699 G_BUS_NAME_OWNER_FLAGS_NONE,
702 BT_DBG("owner_id is [%d]", owner_id);
704 node_info = __bt_telephony_create_method_node_info(
705 bt_telephony_introspection_xml);
706 if (node_info == NULL) {
707 BT_ERR("node_info NULL");
708 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
710 if (__bluetooth_telephony_register_object(TRUE, node_info) !=
711 BLUETOOTH_TELEPHONY_ERROR_NONE) {
712 BT_ERR("Registation of Method Failed");
713 g_dbus_node_info_unref(node_info);
714 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
718 g_dbus_node_info_unref(node_info);
719 return BLUETOOTH_TELEPHONY_ERROR_NONE;
722 static void __bluetooth_telephony_proxy_deinit(void)
726 __bluetooth_telephony_register_object(FALSE, NULL);
732 static int __bluetooth_telephony_register(void)
737 char *path = g_strdup(telephony_info.call_path);
742 param = g_variant_new("(ss)", path, src_addr);
743 BT_DBG("Path[%s] Src_Address[%s]", path, src_addr);
745 reply = __bluetooth_telephony_dbus_method_send(
746 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
747 "RegisterApplication", &err, param);
752 BT_ERR("Error returned in method call");
754 g_dbus_error_strip_remote_error(err);
755 ret = __bt_telephony_get_error(err->message);
756 BT_ERR("Error here %d\n", ret);
760 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
763 g_variant_unref(reply);
764 BT_DBG("__bluetooth_telephony_register completed");
766 return BLUETOOTH_TELEPHONY_ERROR_NONE;
769 static int __bluetooth_telephony_unregister(void)
774 char *path = g_strdup(telephony_info.call_path);
779 param = g_variant_new("(s)", path);
780 reply = __bluetooth_telephony_dbus_method_send(
781 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
782 "UnregisterApplication", &err, param);
787 BT_ERR("Error returned in method call");
789 g_dbus_error_strip_remote_error(err);
790 ret = __bt_telephony_get_error(err->message);
794 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
797 g_variant_unref(reply);
798 BT_DBG("__bluetooth_telephony_unregister completed");
800 return BLUETOOTH_TELEPHONY_ERROR_NONE;
803 static void __bluetooth_telephony_init_headset_state(void)
807 gboolean status = FALSE;
811 if (telephony_dbus_info.conn == NULL) {
812 BT_ERR("Bluetooth telephony not initilized");
816 reply = __bluetooth_telephony_dbus_method_send(
817 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
818 "IsConnected", &err, NULL);
820 BT_ERR("Error returned in method call\n");
822 BT_ERR("Error message = %s", err->message);
828 g_variant_get(reply, "(b)", &status);
829 g_variant_unref(reply);
831 BT_INFO("Headset Connected Status = [%d]", status);
833 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
837 if (bluetooth_telephony_is_sco_connected())
838 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
843 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
845 gboolean flag = FALSE;
848 switch ((device_class & 0x1f00) >> 8) {
850 switch ((device_class & 0xfc) >> 2) {
868 /* Tizen Wearable device */
870 switch ((device_class & 0xfc) >> 2) {
871 case 0x01: /* Wrist Watch */
879 BT_DBG("[%d]", flag);
884 static gboolean __bluetooth_telephony_is_headset_by_uuid(gchar **uuids)
888 unsigned int service = 0;
892 retv_if(uuids == NULL, FALSE);
894 for (i = 0; uuids[i] != NULL; i++) {
895 parts = g_strsplit(uuids[i], "-", -1);
897 if (parts == NULL || parts[0] == NULL) {
902 service = g_ascii_strtoull(parts[0], NULL, 16);
905 if (service == BLUETOOTH_HS_PROFILE_UUID ||
906 service == BLUETOOTH_HF_PROFILE_UUID)
915 static int __bluetooth_telephony_get_connected_device(void)
917 GDBusConnection *conn;
918 GDBusProxy *headset_agent_proxy = NULL;
919 GDBusProxy *manager_proxy = NULL;
920 GDBusProxy *proxy = NULL;
921 GVariant *reply = NULL;
922 GVariant *getall = NULL;
923 GVariant *isPlayingReply = NULL;
924 GVariant *isConnectedReply = NULL;
925 GVariant *param = NULL;
926 GVariant *var_path = NULL;
927 GVariant *path_values = NULL;
928 GVariant *value = NULL;
929 GError *error = NULL;
931 GVariantIter iter_path;
932 GVariantIter property_iter;
933 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
936 conn = _bt_gdbus_get_system_gconn();
937 retv_if(conn == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
939 manager_proxy = g_dbus_proxy_new_sync(
940 conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
941 BLUEZ_SERVICE_NAME, "/",
942 BLUEZ_MANAGER_INTERFACE, NULL, &error);
943 if (manager_proxy == NULL) {
944 BT_ERR("Unable to allocate new proxy \n");
945 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
947 g_dbus_error_strip_remote_error(error);
948 ret = __bt_telephony_get_error(error->message);
949 BT_ERR("Error here %d\n", ret);
955 /* Synchronous call */
956 reply = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects", NULL,
957 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
958 g_object_unref(manager_proxy);
961 BT_ERR("Can't get managed objects");
962 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
964 g_dbus_error_strip_remote_error(error);
965 ret = __bt_telephony_get_error(error->message);
966 BT_ERR("Error here %d\n", ret);
972 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
973 g_variant_iter_init(&iter, reply);
975 while ((param = g_variant_iter_next_value(&iter))) {
976 g_variant_iter_init(&iter_path, param);
978 while ((var_path = g_variant_iter_next_value(&iter_path))) {
980 uint32_t device_class = 0;
981 gboolean playing = FALSE;
982 gboolean connected = FALSE;
983 char *object_path = NULL;
984 gchar *address = NULL;
986 gchar **uuids = NULL;
987 GVariant *getall_param = NULL;
989 g_variant_get(var_path, "{&o*}", &object_path,
991 g_variant_unref(path_values); /* path_values unused*/
993 proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
994 G_DBUS_PROXY_FLAGS_NONE, NULL,
995 BLUEZ_SERVICE_NAME, object_path,
996 BLUEZ_PROPERTIES_INTERFACE, NULL, &error);
998 BT_ERR("Unable to allocate new proxy \n");
999 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1001 g_dbus_error_strip_remote_error(error);
1002 ret = __bt_telephony_get_error(error->message);
1003 BT_ERR("Error here %d\n", ret);
1004 g_error_free(error);
1010 getall_param = g_variant_new("s", BLUEZ_DEVICE_INTERFACE);
1011 getall = g_dbus_proxy_call_sync(proxy,
1012 "GetAll", getall_param,
1013 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1014 g_object_unref(proxy);
1017 BT_ERR("Can't get managed objects");
1018 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1020 g_dbus_error_strip_remote_error(error);
1021 ret = __bt_telephony_get_error(error->message);
1022 BT_ERR("Error here %d\n", ret);
1023 g_error_free(error);
1028 g_variant_iter_init(&property_iter, getall);
1030 while (g_variant_iter_loop(&property_iter, "{&sv}", &key, &value)) {
1031 if (!g_strcmp0(key, "Class")) {
1032 device_class = g_variant_get_uint32(value);
1033 BT_DBG("Device Class: %d", device_class);
1034 } else if (!g_strcmp0(key, "UUID")) {
1036 uuids = (gchar **)g_variant_get_strv(value, &len);
1037 BT_DBG_UUID(uuids, len, i);
1038 } else if (!g_strcmp0(key, "Address")) {
1039 address = (gchar *)g_variant_get_string(
1042 BT_DBG("Device Class: %s", address);
1044 g_variant_unref(value);
1046 g_variant_unref(getall);
1048 if (device_class == 0) {
1049 BT_DBG("COD is NULL (maybe paired by nfc)... Checking UUIDs");
1050 if (!__bluetooth_telephony_is_headset_by_uuid(uuids)) {
1051 BT_DBG("UUID checking completed. None HF device");
1054 BT_DBG("UUID checking completed. HF device");
1056 if (!__bluetooth_telephony_is_headset(device_class))
1060 /* this is headset; Check for Connection */
1061 headset_agent_proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
1062 G_DBUS_PROXY_FLAGS_NONE, NULL,
1063 HFP_AGENT_SERVICE, object_path,
1064 HFP_AGENT_INTERFACE, NULL, &error);
1065 if (headset_agent_proxy == NULL) {
1066 BT_ERR("Unable to allocate new headset_agent_proxy");
1067 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1069 g_dbus_error_strip_remote_error(error);
1070 ret = __bt_telephony_get_error(error->message);
1071 BT_ERR("Error here %d\n", ret);
1072 g_error_free(error);
1077 isConnectedReply = g_dbus_proxy_call_sync(headset_agent_proxy,
1078 "IsConnected", NULL,
1079 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1082 if (!isConnectedReply) {
1083 BT_ERR("Can't get managed objects");
1084 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1086 g_dbus_error_strip_remote_error(error);
1087 ret = __bt_telephony_get_error(error->message);
1088 BT_ERR("Error here %d\n", ret);
1089 g_error_free(error);
1093 connected = g_variant_get_boolean(isConnectedReply);
1094 g_variant_unref(isConnectedReply);
1097 g_strlcpy(telephony_info.address,
1099 sizeof(telephony_info.address));
1101 isPlayingReply = g_dbus_proxy_call_sync(headset_agent_proxy,
1103 G_DBUS_CALL_FLAGS_NONE,
1105 if (!isPlayingReply) {
1106 BT_ERR("Can't get managed objects");
1107 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1109 g_dbus_error_strip_remote_error(error);
1110 ret = __bt_telephony_get_error(error->message);
1111 BT_ERR("Error here %d\n", ret);
1112 g_error_free(error);
1115 playing = g_variant_get_boolean(isPlayingReply);
1116 g_variant_unref(isPlayingReply);
1119 telephony_info.headset_state =
1120 BLUETOOTH_STATE_PLAYING;
1122 telephony_info.headset_state =
1123 BLUETOOTH_STATE_CONNECTED;
1130 g_object_unref(headset_agent_proxy);
1131 g_variant_unref(var_path);
1133 g_variant_unref(param);
1137 if (headset_agent_proxy)
1138 g_object_unref(headset_agent_proxy);
1140 g_variant_unref(reply);
1142 g_variant_unref(var_path);
1144 g_variant_unref(param);
1149 static GDBusProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1151 GDBusProxy *proxy = NULL;
1152 GError *error = NULL;
1156 if (strlen(telephony_info.address) == 0)
1157 __bluetooth_telephony_get_connected_device();
1159 if (strlen(telephony_info.address) == 0)
1162 proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
1163 G_DBUS_PROXY_FLAGS_NONE, NULL,
1164 HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1165 HFP_AGENT_INTERFACE, NULL, &error);
1166 if (proxy == NULL) {
1167 BT_ERR("Unable to allocate new proxy");
1169 g_dbus_error_strip_remote_error(error);
1170 ret = __bt_telephony_get_error(error->message);
1171 BT_ERR("Error here %d\n", ret);
1172 g_error_free(error);
1181 int __bt_telephony_subscribe_adapter_signal(GDBusConnection *conn,
1187 static guint subscribe_adapter_id = 0;
1189 if (subscribe == TRUE) {
1190 if (subscribe_adapter_id == 0) {
1191 subscribe_adapter_id = g_dbus_connection_signal_subscribe(conn,
1192 NULL, "org.freedesktop.DBus.ObjectManager",
1193 "InterfacesAdded", NULL, NULL, 0,
1194 __bt_telephony_adapter_filter,
1197 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1199 if (subscribe_adapter_id > 0) {
1200 g_dbus_connection_signal_unsubscribe(conn,
1201 subscribe_adapter_id);
1202 subscribe_adapter_id = 0;
1204 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1208 int __bt_telephony_event_subscribe_signal(GDBusConnection *conn,
1214 static guint subscribe_event1_id = 0;
1215 static guint subscribe_event2_id = 0;
1216 static guint subscribe_event3_id = 0;
1217 static guint subscribe_event4_id = 0;
1218 static guint subscribe_event5_id = 0;
1219 static guint subscribe_event6_id = 0;
1221 if (subscribe == TRUE) {
1222 if (subscribe_event1_id == 0) {
1223 subscribe_event1_id = g_dbus_connection_signal_subscribe(conn,
1224 NULL, BLUEZ_HEADSET_INTERFACE,
1225 "PropertyChanged", NULL, NULL, 0,
1226 __bluetooth_telephony_event_filter,
1229 if (subscribe_event2_id == 0) {
1230 subscribe_event2_id = g_dbus_connection_signal_subscribe(conn,
1231 NULL, HFP_AGENT_SERVICE,
1232 HFP_NREC_STATUS_CHANGE, NULL, NULL, 0,
1233 __bluetooth_telephony_event_filter,
1237 if (subscribe_event3_id == 0) {
1238 subscribe_event3_id = g_dbus_connection_signal_subscribe(conn,
1239 NULL, HFP_AGENT_SERVICE,
1240 HFP_ANSWER_CALL, NULL, NULL, 0,
1241 __bluetooth_telephony_event_filter,
1244 if (subscribe_event4_id == 0) {
1245 subscribe_event4_id = g_dbus_connection_signal_subscribe(conn,
1246 NULL, HFP_AGENT_SERVICE,
1247 HFP_REJECT_CALL, NULL, NULL, 0,
1248 __bluetooth_telephony_event_filter,
1251 if (subscribe_event5_id == 0) {
1252 subscribe_event5_id = g_dbus_connection_signal_subscribe(conn,
1253 NULL, HFP_AGENT_SERVICE,
1254 HFP_RELEASE_CALL, NULL, NULL, 0,
1255 __bluetooth_telephony_event_filter,
1258 if (subscribe_event6_id == 0) {
1259 subscribe_event6_id = g_dbus_connection_signal_subscribe(conn,
1260 NULL, HFP_AGENT_SERVICE,
1261 HFP_THREEWAY_CALL, NULL, NULL, 0,
1262 __bluetooth_telephony_event_filter,
1266 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1268 if (subscribe_event1_id > 0) {
1269 g_dbus_connection_signal_unsubscribe(conn,
1270 subscribe_event1_id);
1271 subscribe_event1_id = 0;
1273 if (subscribe_event2_id > 0) {
1274 g_dbus_connection_signal_unsubscribe(conn,
1275 subscribe_event2_id);
1276 subscribe_event2_id = 0;
1278 if (subscribe_event3_id > 0) {
1279 g_dbus_connection_signal_unsubscribe(conn,
1280 subscribe_event3_id);
1281 subscribe_event3_id = 0;
1283 if (subscribe_event4_id > 0) {
1284 g_dbus_connection_signal_unsubscribe(conn,
1285 subscribe_event4_id);
1286 subscribe_event4_id = 0;
1288 if (subscribe_event5_id > 0) {
1289 g_dbus_connection_signal_unsubscribe(conn,
1290 subscribe_event5_id);
1291 subscribe_event5_id = 0;
1293 if (subscribe_event6_id > 0) {
1294 g_dbus_connection_signal_unsubscribe(conn,
1295 subscribe_event6_id);
1296 subscribe_event6_id = 0;
1298 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1302 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1305 bluetooth_device_address_t loc_address = { {0} };
1306 char src_address[BT_ADDRESS_STRING_SIZE] = { 0 };
1307 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1308 GError *error = NULL;
1312 if (is_initialized == TRUE) {
1313 BT_ERR("Bluetooth telephony already initilized");
1314 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1317 is_initialized = TRUE;
1319 telephony_dbus_info.conn = _bt_gdbus_init_system_gconn();
1320 if (!telephony_dbus_info.conn) {
1321 is_initialized = FALSE;
1322 BT_ERR("Could not get DBus Connection");
1323 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1327 snprintf(telephony_info.call_path, sizeof(telephony_info.call_path),
1328 CSD_CALL_APP_PATH, getpid());
1329 BT_INFO("Call Path = %s", telephony_info.call_path);
1330 memset(telephony_info.address, 0x00, sizeof(telephony_info.address));
1332 if (__bluetooth_telephony_proxy_init()) {
1333 BT_ERR("__bluetooth_telephony_proxy_init failed\n");
1334 telephony_dbus_info.conn = NULL;
1335 is_initialized = FALSE;
1336 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1339 telephony_dbus_info.manager_proxy = g_dbus_proxy_new_sync(
1340 telephony_dbus_info.conn,
1341 G_DBUS_PROXY_FLAGS_NONE, NULL,
1342 BLUEZ_SERVICE_NAME, "/",
1343 BLUEZ_MANAGER_INTERFACE, NULL, &error);
1344 if (telephony_dbus_info.manager_proxy == NULL) {
1345 BT_ERR("Could not create a manager proxy");
1346 __bluetooth_telephony_proxy_deinit();
1347 telephony_dbus_info.conn = NULL;
1348 is_initialized = FALSE;
1350 g_dbus_error_strip_remote_error(error);
1351 ret = __bt_telephony_get_error(error->message);
1352 BT_ERR("Error here %d\n", ret);
1353 g_error_free(error);
1356 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1359 telephony_dbus_info.dbus_proxy = g_dbus_proxy_new_sync(
1360 telephony_dbus_info.conn,
1361 G_DBUS_PROXY_FLAGS_NONE, NULL,
1362 BT_EVENT_FREEDESKTOP, BT_FREEDESKTOP_PATH,
1363 BT_EVENT_FREEDESKTOP, NULL, &error);
1364 if (NULL == telephony_dbus_info.dbus_proxy) {
1365 __bluetooth_telephony_proxy_deinit();
1366 telephony_dbus_info.conn = NULL;
1367 g_object_unref(telephony_dbus_info.manager_proxy);
1368 telephony_dbus_info.manager_proxy = NULL;
1369 is_initialized = FALSE;
1370 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1373 if (__bt_telephony_subscribe_adapter_signal(telephony_dbus_info.conn, TRUE) != 0) {
1374 BT_ERR("Fail to Subscribe Adapter Signal");
1378 /*Callback and user applicaton data*/
1379 telephony_info.cb = cb;
1380 telephony_info.user_data = user_data;
1381 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1383 if (__bt_telephony_event_subscribe_signal(telephony_dbus_info.conn, TRUE) != 0) {
1384 BT_ERR("Fail to Subscribe telephony event Signal");
1388 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED)
1389 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1391 /*Bluetooth is active, therefore set the flag */
1394 ret = bluetooth_get_local_address(&loc_address);
1395 if (ret != BLUETOOTH_ERROR_NONE) {
1396 BT_ERR("Fail to get local address\n");
1397 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1400 _bt_convert_addr_type_to_string(src_address, loc_address.addr);
1401 src_addr = g_strdup(src_address);
1403 ret = __bluetooth_telephony_register();
1404 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1405 BT_ERR("__bluetooth_telephony_register failed\n");
1409 if (TIZEN_PROFILE_WEARABLE || TIZEN_PROFILE_IVI)
1410 __bluetooth_telephony_init_headset_state();
1415 bluetooth_telephony_deinit();
1419 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1422 BT_TELEPHONY_CHECK_INITIALIZED();
1424 is_initialized = FALSE;
1426 if (__bt_telephony_event_subscribe_signal(telephony_dbus_info.conn, FALSE) != 0)
1427 BT_ERR("Fail to UnSubscribe telephony event Signal");
1429 if (bluetooth_check_adapter() != BLUETOOTH_ADAPTER_DISABLED ||
1430 bluetooth_check_adapter_le() != BLUETOOTH_ADAPTER_LE_DISABLED)
1431 __bluetooth_telephony_unregister();
1433 __bluetooth_telephony_proxy_deinit();
1435 telephony_info.cb = NULL;
1436 telephony_info.user_data = NULL;
1437 telephony_info.call_count = 0;
1438 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1440 /* Remove BT enabled signal */
1441 if (__bt_telephony_subscribe_adapter_signal(telephony_dbus_info.conn, FALSE) != 0)
1442 BT_ERR("Fail to UnSubscribe Adapter event Signal");
1447 if (telephony_dbus_info.manager_proxy != NULL) {
1448 g_object_unref(telephony_dbus_info.manager_proxy);
1449 telephony_dbus_info.manager_proxy = NULL;
1452 if (telephony_dbus_info.conn != NULL)
1453 telephony_dbus_info.conn = NULL;
1455 if (telephony_dbus_info.dbus_proxy != NULL) {
1456 g_object_unref(telephony_dbus_info.dbus_proxy);
1457 telephony_dbus_info.dbus_proxy = NULL;
1461 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1464 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1468 gboolean status = FALSE;
1472 retv_if(is_initialized == FALSE, FALSE);
1473 retv_if(bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED, FALSE);
1475 reply = __bluetooth_telephony_dbus_method_send(
1476 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1477 "IsPlaying", &err, NULL);
1480 BT_ERR("Error returned in method call\n");
1482 BT_ERR("Error message = %s", err->message);
1487 g_variant_get(reply, "(b)", &status);
1488 g_variant_unref(reply);
1490 if (TIZEN_PROFILE_WEARABLE || TIZEN_PROFILE_IVI)
1491 if (status == TRUE && telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1492 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
1494 BT_INFO("SCO Connected Status = [%d]", status);
1498 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1503 GVariant *param_inner;
1507 BT_TELEPHONY_CHECK_INITIALIZED();
1508 BT_TELEPHONY_CHECK_ENABLED();
1511 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1513 if (telephony_info.headset_state == BLUETOOTH_STATE_DISCONNETED)
1514 return BLUETOOTH_TELEPHONY_ERROR_AUDIO_NOT_CONNECTED;
1516 reply = __bluetooth_telephony_dbus_method_send(
1517 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1518 "GetProperties", &err, NULL);
1521 BT_ERR("Error returned in method call\n");
1523 BT_DBG("Error message = %s", err->message);
1526 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1529 g_variant_iter_init(&iter, reply);
1530 while ((param_inner = g_variant_iter_next_value(&iter))) {
1533 value = g_variant_lookup_value(param_inner,
1534 "nrec", G_VARIANT_TYPE_BOOLEAN);
1536 BT_DBG("Property NREC Found");
1537 *status = g_variant_get_boolean(value);
1538 BT_DBG("NREC status = [%d]", *status);
1539 g_variant_unref(value);
1540 g_variant_unref(param_inner);
1543 g_variant_unref(param_inner);
1545 BT_DBG("NREC status = [%d]", *status);
1546 g_variant_unref(reply);
1549 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1552 BT_EXPORT_API int bluetooth_telephony_is_wbs_mode(gboolean *status)
1558 GVariant *param_inner;
1562 BT_TELEPHONY_CHECK_INITIALIZED();
1563 BT_TELEPHONY_CHECK_ENABLED();
1566 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1570 reply = __bluetooth_telephony_dbus_method_send(
1571 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1572 "GetProperties", &err, NULL);
1575 BT_ERR("Error returned in method call");
1577 BT_ERR("Error message = %s", err->message);
1580 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1583 g_variant_iter_init(&iter, reply);
1584 while ((param_inner = g_variant_iter_next_value(&iter))) {
1587 value = g_variant_lookup_value(param_inner,
1588 "codec", G_VARIANT_TYPE_UINT32);
1590 BT_DBG("Property CODEC Found");
1591 codec = g_variant_get_uint32(value);
1592 g_variant_unref(value);
1593 BT_DBG("Codec = [%d]", codec);
1595 *status = codec == BT_MSBC_CODEC_ID ? TRUE : FALSE;
1596 BT_DBG("NREC status = [%d]", *status);
1597 g_variant_unref(value);
1598 g_variant_unref(param_inner);
1601 g_variant_unref(param_inner);
1604 g_variant_unref(reply);
1605 BT_DBG("MSBC status = [%d]", *status);
1608 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1611 BT_EXPORT_API int bluetooth_telephony_send_vendor_cmd(const char *cmd)
1613 GError *error = NULL;
1614 GVariant *reply, *parameters;
1615 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1619 BT_TELEPHONY_CHECK_INITIALIZED();
1620 BT_TELEPHONY_CHECK_ENABLED();
1622 BT_DBG("Send Vendor %s", cmd);
1624 if (telephony_dbus_info.proxy == NULL)
1625 telephony_dbus_info.proxy =
1626 __bluetooth_telephony_get_connected_device_proxy();
1628 if (telephony_dbus_info.proxy == NULL)
1629 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1631 parameters = g_variant_new("s", cmd);
1632 reply = g_dbus_proxy_call_sync(telephony_dbus_info.proxy,
1633 "SendVendorAtCmd", parameters,
1634 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1636 g_variant_unref(reply);
1639 g_dbus_error_strip_remote_error(error);
1640 ret = __bt_telephony_get_error(error->message);
1641 BT_ERR("Error here %d\n", ret);
1642 g_error_free(error);
1649 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1655 gboolean state = TRUE;
1659 BT_TELEPHONY_CHECK_INITIALIZED();
1660 BT_TELEPHONY_CHECK_ENABLED();
1662 param = g_variant_new("(b)", &state);
1663 reply = __bluetooth_telephony_dbus_method_send(
1664 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1665 "SetVoiceDial", &err, param);
1668 BT_ERR("Error returned in method call\n");
1670 g_dbus_error_strip_remote_error(err);
1671 ret = __bt_telephony_get_error(err->message);
1675 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1678 g_variant_unref(reply);
1680 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1683 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1689 gboolean state = FALSE;
1693 BT_TELEPHONY_CHECK_INITIALIZED();
1694 BT_TELEPHONY_CHECK_ENABLED();
1696 param = g_variant_new("(b)", &state);
1697 reply = __bluetooth_telephony_dbus_method_send(
1698 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1699 "SetVoiceDial", &err, param);
1702 BT_ERR("Error returned in method call\n");
1704 g_dbus_error_strip_remote_error(err);
1705 ret = __bt_telephony_get_error(err->message);
1709 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1712 g_variant_unref(reply);
1715 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1718 static void __bluetooth_telephony_sco_start_cb(GDBusProxy *proxy,
1719 GAsyncResult *res, gpointer user_data)
1721 GError *error = NULL;
1722 GVariant *value = NULL;
1724 value = g_dbus_proxy_call_finish(proxy, res, &error);
1725 if (value == NULL) {
1726 if (error != NULL) {
1727 BT_ERR("sco_close_cb error. errCode[%x],message[%s]",
1728 error->code, error->message);
1729 g_clear_error(&error);
1731 BT_ERR("SCo Start Failed");
1733 g_object_unref(proxy);
1737 BT_DBG("sco_start_cb : -");
1738 g_object_unref(proxy);
1739 g_variant_unref(value);
1742 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1744 GDBusConnection *conn;
1751 BT_TELEPHONY_CHECK_INITIALIZED();
1752 BT_TELEPHONY_CHECK_ENABLED();
1754 /* Because this API is async call, so can't use dbus SMACK */
1755 if (__bt_telephony_check_privilege() ==
1756 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1757 BT_ERR("Don't have a privilege to use this API");
1758 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1761 conn = _bt_gdbus_get_system_gconn();
1763 BT_DBG("No System Bus found\n");
1764 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1767 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1768 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1770 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
1771 HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1772 HFP_AGENT_INTERFACE, NULL, &err);
1773 if (proxy == NULL) {
1774 BT_ERR("Unable to allocate new proxy");
1776 g_dbus_error_strip_remote_error(err);
1777 ret = __bt_telephony_get_error(err->message);
1778 BT_ERR("Error here %d\n", ret);
1782 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1785 g_dbus_proxy_call(proxy, "Play", NULL, G_DBUS_CALL_FLAGS_NONE,
1786 -1, NULL, (GAsyncReadyCallback)__bluetooth_telephony_sco_start_cb, NULL);
1789 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1792 static void __bluetooth_telephony_sco_close_cb(GDBusProxy *proxy,
1793 GAsyncResult *res, gpointer user_data)
1795 GError *error = NULL;
1796 GVariant *value = NULL;
1798 value = g_dbus_proxy_call_finish(proxy, res, &error);
1799 if (value == NULL) {
1800 if (error != NULL) {
1801 BT_ERR("sco_close_cb error. errCode[%x],message[%s]",
1802 error->code, error->message);
1803 g_clear_error(&error);
1805 BT_ERR("SCo close Failed");
1807 g_object_unref(proxy);
1811 BT_DBG("sco_close_cb : -");
1812 g_object_unref(proxy);
1813 g_variant_unref(value);
1815 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1817 GDBusConnection *conn;
1824 BT_TELEPHONY_CHECK_INITIALIZED();
1825 BT_TELEPHONY_CHECK_ENABLED();
1827 /* Because this API is async call, so can't use dbus SMACK */
1828 if (__bt_telephony_check_privilege() ==
1829 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1830 BT_ERR("Don't have a privilege to use this API");
1831 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1834 conn = _bt_gdbus_get_system_gconn();
1836 BT_DBG("No System Bus found\n");
1837 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1840 if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1841 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1843 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
1844 HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1845 HFP_AGENT_INTERFACE, NULL, &err);
1846 if (proxy == NULL) {
1847 BT_ERR("Unable to allocate new proxy");
1849 g_dbus_error_strip_remote_error(err);
1850 ret = __bt_telephony_get_error(err->message);
1851 BT_ERR("Error here %d\n", ret);
1855 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1858 g_dbus_proxy_call(proxy, "Stop", NULL, G_DBUS_CALL_FLAGS_NONE,
1859 -1, NULL, (GAsyncReadyCallback)__bluetooth_telephony_sco_close_cb, NULL);
1861 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
1864 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1867 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1871 BT_TELEPHONY_CHECK_INITIALIZED();
1872 BT_TELEPHONY_CHECK_ENABLED();
1875 BT_DBG("call_id = [%d]", call_id);
1877 /*Make sure SCO is already connected */
1878 ret = __bluetooth_telephony_send_call_status(
1879 CSD_CALL_STATUS_MO_ALERTING, call_id, NULL);
1881 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1882 BT_ERR("send call status Failed = [%d]", ret);
1888 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
1889 unsigned int bt_audio)
1894 BT_DBG("call_id = [%d]", call_id);
1896 BT_TELEPHONY_CHECK_INITIALIZED();
1897 BT_TELEPHONY_CHECK_ENABLED();
1899 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1901 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1902 BT_ERR("send call status Failed = [%d]", ret);
1907 if (!bluetooth_telephony_is_sco_connected()) {
1908 ret = bluetooth_telephony_audio_open();
1909 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1910 BT_ERR("Audio connection call Failed[%d]", ret);
1918 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
1923 BT_DBG("call_id = [%d]", call_id);
1925 BT_TELEPHONY_CHECK_INITIALIZED();
1926 BT_TELEPHONY_CHECK_ENABLED();
1928 if (telephony_info.call_count > 0)
1929 telephony_info.call_count = telephony_info.call_count - 1;
1931 if (telephony_info.call_count == 0) {
1932 if (bluetooth_telephony_is_sco_connected()) {
1933 ret = bluetooth_telephony_audio_close();
1934 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1935 BT_ERR(" Failed = [%d]", ret);
1939 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
1941 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1942 BT_ERR("send call status Failed = [%d]", ret);
1948 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
1953 BT_DBG("call_id = [%d]", call_id);
1955 BT_TELEPHONY_CHECK_INITIALIZED();
1956 BT_TELEPHONY_CHECK_ENABLED();
1958 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
1960 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1961 BT_ERR("send call status Failed = [%d]", ret);
1967 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
1972 BT_DBG("call_id = [%d]", call_id);
1974 BT_TELEPHONY_CHECK_INITIALIZED();
1975 BT_TELEPHONY_CHECK_ENABLED();
1977 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1979 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1980 BT_ERR("send call status Failed = [%d]", ret);
1986 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
1987 unsigned int call_count)
1991 GList *list = call_list;
1992 bt_telephony_call_status_info_t *call_status;
1996 BT_TELEPHONY_CHECK_INITIALIZED();
1997 BT_TELEPHONY_CHECK_ENABLED();
2000 BT_ERR("call_list is invalid");
2001 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2004 /* Because this API is async call, so can't use dbus SMACK */
2005 if (__bt_telephony_check_privilege() ==
2006 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
2007 BT_ERR("Don't have a privilege to use this API");
2008 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
2011 BT_DBG(" call_count = [%d]", call_count);
2013 for (i = 0; i < call_count; i++) {
2014 call_status = g_list_nth_data(list, i);
2016 if (NULL == call_status)
2019 BT_DBG(" %d : Call id [%d] status[%d]", i,
2020 call_status->call_id,
2021 call_status->call_status);
2023 if (NULL != call_status->phone_number)
2024 DBG_SECURE("Number [%s]", call_status->phone_number);
2026 switch (call_status->call_status) {
2027 case BLUETOOTH_CALL_STATE_HELD:
2028 ret = __bluetooth_telephony_send_call_status(
2029 CSD_CALL_STATUS_HOLD,
2030 call_status->call_id,
2031 call_status->phone_number);
2032 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2033 BT_ERR("Failed = %d", ret);
2038 case BLUETOOTH_CALL_STATE_CONNECTED:
2039 ret = __bluetooth_telephony_send_call_status(
2040 CSD_CALL_STATUS_ACTIVE,
2041 call_status->call_id,
2042 call_status->phone_number);
2043 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2044 BT_ERR("Failed = [%d]", ret);
2050 if ((call_status->call_status <
2051 BLUETOOTH_CALL_STATE_NONE) ||
2052 (call_status->call_status >=
2053 BLUETOOTH_CALL_STATE_ERROR)) {
2054 BT_ERR("Unknown Call state");
2055 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
2061 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2064 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
2065 unsigned int call_count)
2071 ret = bluetooth_telephony_call_swapped(call_list, call_count);
2073 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2074 BT_ERR("Failed = [%d]", ret);
2078 telephony_info.call_count = call_count;
2081 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2084 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
2085 const char *ph_number, unsigned int call_id,
2086 unsigned int bt_audio)
2091 const char *path = telephony_info.call_path;
2092 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
2096 BT_TELEPHONY_CHECK_INITIALIZED();
2097 BT_TELEPHONY_CHECK_ENABLED();
2099 if (NULL == ph_number)
2100 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2102 param = g_variant_new("(ssi)", path, ph_number, call_id);
2103 reply = __bluetooth_telephony_dbus_method_send(
2104 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2105 "OutgoingCall", &err, param);
2108 BT_ERR("Error returned in method call\n");
2110 g_dbus_error_strip_remote_error(err);
2111 ret = __bt_telephony_get_error(err->message);
2115 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2118 g_variant_unref(reply);
2120 telephony_info.call_count++;
2121 BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
2124 if (!bluetooth_telephony_is_sco_connected()) {
2125 ret = bluetooth_telephony_audio_open();
2127 BT_ERR(" Audio connection Failed = %d", ret);
2135 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
2136 const char *ph_number, unsigned int call_id)
2141 const char *path = telephony_info.call_path;
2146 BT_TELEPHONY_CHECK_INITIALIZED();
2147 BT_TELEPHONY_CHECK_ENABLED();
2149 if (NULL == ph_number)
2150 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2152 param = g_variant_new("(ssi)", path, ph_number, call_id);
2153 reply = __bluetooth_telephony_dbus_method_send(
2154 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2155 "IncomingCall", &err, param);
2158 BT_ERR("Error returned in method call\n");
2160 g_dbus_error_strip_remote_error(err);
2161 ret = __bt_telephony_get_error(err->message);
2165 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2168 g_variant_unref(reply);
2169 telephony_info.call_count++;
2170 BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
2172 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2175 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(
2176 unsigned short speaker_gain)
2185 BT_TELEPHONY_CHECK_INITIALIZED();
2186 BT_TELEPHONY_CHECK_ENABLED();
2188 BT_DBG("set speaker_gain= [%d]", speaker_gain);
2190 param = g_variant_new("(q)", speaker_gain);
2191 reply = __bluetooth_telephony_dbus_method_send(
2192 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2193 "SetSpeakerGain", &err, param);
2196 BT_ERR("Error returned in method call\n");
2198 g_dbus_error_strip_remote_error(err);
2199 ret = __bt_telephony_get_error(err->message);
2203 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2206 g_variant_unref(reply);
2208 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2211 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(
2212 unsigned int *speaker_gain)
2221 BT_TELEPHONY_CHECK_INITIALIZED();
2222 BT_TELEPHONY_CHECK_ENABLED();
2224 reply = __bluetooth_telephony_dbus_method_send(
2225 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2226 "GetSpeakerGain", &err, NULL);
2229 BT_ERR("Error returned in method call\n");
2231 g_dbus_error_strip_remote_error(err);
2232 ret = __bt_telephony_get_error(err->message);
2236 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2238 g_variant_get(reply, "(q)", &gain);
2239 *speaker_gain = gain;
2240 BT_DBG("Get speaker_gain= [%d]", *speaker_gain);
2242 g_variant_unref(reply);
2245 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2248 BT_EXPORT_API int bluetooth_telephony_is_connected(gboolean *ag_connected)
2253 gboolean ag_connected_from_bt_agent;
2255 BT_CHECK_ENABLED(return);
2257 reply = __bluetooth_telephony_dbus_method_send(
2258 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2259 "IsConnected", &err, NULL);
2262 BT_ERR("Error returned in method call\n");
2264 g_dbus_error_strip_remote_error(err);
2265 ret = __bt_telephony_get_error(err->message);
2269 return BLUETOOTH_ERROR_INTERNAL;
2271 g_variant_get(reply, "(b)", &ag_connected_from_bt_agent);
2272 *ag_connected = ag_connected_from_bt_agent;
2274 BT_DBG("Conn Status: %s", *ag_connected ? "Connected" : "Disconnected");
2276 g_variant_unref(reply);
2278 return BLUETOOTH_ERROR_NONE;
2281 BT_EXPORT_API int bluetooth_telephony_set_active_headset(const char *remote_addr)
2283 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
2289 BT_CHECK_ENABLED(return);
2291 if (NULL == remote_addr)
2292 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2294 param = g_variant_new("(s)", remote_addr);
2295 reply = __bluetooth_telephony_dbus_method_send(
2296 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2297 "SwapHeadset", &err, param);
2300 BT_ERR("Error returned in method call\n");
2302 g_dbus_error_strip_remote_error(err);
2303 ret = __bt_telephony_get_error(err->message);
2307 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2310 g_variant_unref(reply);
2311 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2313 return BLUETOOTH_ERROR_NOT_SUPPORT;
2317 static void __bt_telephony_adapter_filter(GDBusConnection *connection,
2318 const gchar *sender_name,
2319 const gchar *object_path,
2320 const gchar *interface_name,
2321 const gchar *signal_name,
2322 GVariant *parameters,
2329 if (strcasecmp(signal_name, "InterfacesAdded") == 0) {
2330 GVariant *optional_param = NULL;
2332 g_variant_get(parameters, "(&o@a{sa{sv}})",
2333 &path, &optional_param);
2336 BT_ERR("Invalid adapter path");
2340 BT_INFO("Adapter Path = [%s]", path);
2341 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
2342 if (__bt_telephony_get_src_addr(optional_param))
2343 BT_ERR("Fail to get the local adapter address");
2345 ret = __bluetooth_telephony_register();
2346 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2347 BT_ERR("__bluetooth_telephony_register failed");
2350 g_variant_unref(optional_param);
2356 static int __bt_telephony_get_src_addr(GVariant *value)
2359 GVariant *param = NULL;
2362 /* signature a{sa{sv}} */
2363 g_variant_iter_init(&iter, value);
2364 while ((param = g_variant_iter_next_value(&iter))) {
2365 char *interface_name;
2366 GVariant *interface_var = NULL;
2367 GVariant *param_inner = NULL;
2369 g_variant_get(param, "{&s*}", &interface_name, &interface_var);
2370 g_variant_unref(param);
2372 BT_DBG("interface_name: %s", interface_name);
2373 /* format of interface_var: a{sv}*/
2374 if (strcasecmp(interface_name, BLUEZ_ADAPTER_INTERFACE) == 0) {
2375 GVariantIter iter_inner;
2377 g_variant_iter_init(&iter_inner, interface_var);
2378 while ((param_inner = g_variant_iter_next_value(&iter_inner))) {
2379 char *property_name;
2380 GVariant *property_var;
2382 g_variant_get(param_inner, "{&sv}",
2385 g_variant_unref(param_inner);
2387 if (strcasecmp(property_name, "Address") == 0) {
2388 const gchar *bd_addr;
2390 bd_addr = g_variant_get_string(
2393 src_addr = g_strdup(bd_addr);
2394 BT_DBG("Address: %s", src_addr);
2396 g_variant_unref(interface_var);
2397 g_variant_unref(property_var);
2400 g_variant_unref(property_var);
2403 g_variant_unref(interface_var);
2407 return BLUETOOTH_ERROR_NONE;