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 CSD_CALL_APP_PATH "/org/tizen/csd/%d"
71 #define HFP_NREC_STATUS_CHANGE "NrecStatusChanged"
72 #define HFP_ANSWER_CALL "Answer"
73 #define HFP_REJECT_CALL "Reject"
74 #define HFP_RELEASE_CALL "Release"
75 #define HFP_THREEWAY_CALL "Threeway"
77 #define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
79 /*Below Inrospection data is exposed to bluez from agent*/
80 static const gchar bt_telephony_introspection_xml[] =
82 " <interface name='org.tizen.csd.Call.Instance'>"
83 " <method name='SendDtmf'>"
84 " <arg type='s' name='dtmf' direction='in'/>"
86 " <method name='VendorCmd'>"
87 " <arg type='s' name='vendor' direction='in'/>"
92 #define BT_TELEPHONY_CHECK_ENABLED() \
94 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) { \
95 BT_ERR("BT is not enabled"); \
96 return BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED; \
100 static gboolean is_initialized = FALSE;
101 #define BT_TELEPHONY_CHECK_INITIALIZED() \
103 if (is_initialized == FALSE) { \
104 BT_ERR("Bluetooth telephony not initilized"); \
105 return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED; \
109 static void __bt_telephony_adapter_filter(GDBusConnection *connection,
110 const gchar *sender_name,
111 const gchar *object_path,
112 const gchar *interface_name,
113 const gchar *signal_name,
114 GVariant *parameters,
117 static int __bt_telephony_get_src_addr(GVariant *value);
119 static bt_telephony_info_t telephony_info;
120 static telephony_dbus_info_t telephony_dbus_info;
121 static gboolean is_active = FALSE;
123 /*Function Declaration*/
124 static int __bt_telephony_get_error(const char *error_message);
125 static void __bt_telephony_event_cb(int event, int result, void *param_data);
126 static GQuark __bluetooth_telephony_error_quark(void);
127 static GVariant *__bluetooth_telephony_dbus_method_send(const char *path,
128 const char *interface, const char *method,
129 GError **err, GVariant *parameters);
130 static int __bluetooth_telephony_send_call_status(
131 bt_telephony_call_status_t call_status,
132 unsigned int call_id, const char *ph_number);
133 static void __bluetooth_telephony_error(GDBusMethodInvocation *invocation,
134 bluetooth_telephony_error_t error, const char *err_msg);
136 static void __bluetooth_telephony_event_filter(GDBusConnection *connection,
137 const gchar *sender_name,
138 const gchar *object_path,
139 const gchar *interface_name,
140 const gchar *signal_name,
141 GVariant *parameters,
144 static int __bluetooth_telephony_register(void);
145 static int __bluetooth_telephony_unregister(void);
147 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class);
148 static int __bluetooth_telephony_get_connected_device(void);
149 static GDBusProxy *__bluetooth_telephony_get_connected_device_proxy(void);
151 /*Function Definition*/
152 static void __bt_telephony_method(GDBusConnection *connection,
154 const gchar *object_path,
155 const gchar *interface_name,
156 const gchar *method_name,
157 GVariant *parameters,
158 GDBusMethodInvocation *invocation,
163 BT_INFO("method %s", method_name);
164 BT_INFO("object_path %s", object_path);
166 if (g_strcmp0(method_name, "SendDtmf") == 0) {
168 telephony_event_dtmf_t call_data = { 0, };
170 g_variant_get(parameters, "(&s)", &dtmf);
173 BT_ERR("Number dial failed");
174 __bluetooth_telephony_error(invocation,
175 BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF,
178 DBG_SECURE("Dtmf = %s", dtmf);
180 call_data.dtmf = g_strdup(dtmf);
181 __bt_telephony_event_cb(
182 BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF,
183 BLUETOOTH_TELEPHONY_ERROR_NONE,
186 g_free(call_data.dtmf);
188 g_dbus_method_invocation_return_value(invocation, NULL);
190 } else if (g_strcmp0(method_name, "VendorCmd") == 0) {
193 g_variant_get(parameters, "(&s)", &at_cmd);
194 BT_INFO("Vendor %s", at_cmd);
195 if (at_cmd == NULL) {
196 BT_ERR("Vendor command is NULL\n");
197 __bluetooth_telephony_error(invocation,
198 BLUETOOTH_TELEPHONY_ERROR_APPLICATION,
199 "Invalid at vendor cmd");
201 DBG_SECURE("Vendor AT cmd = %s", at_cmd);
203 __bt_telephony_event_cb(
204 BLUETOOTH_EVENT_TELEPHONY_VENDOR_AT_CMD,
205 BLUETOOTH_TELEPHONY_ERROR_NONE,
208 g_dbus_method_invocation_return_value(invocation, NULL);
215 static const GDBusInterfaceVTable method_table = {
216 __bt_telephony_method,
221 static int __bt_telephony_get_error(const char *error_message)
223 if (error_message == NULL) {
224 BT_ERR("Error message NULL");
225 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
228 BT_ERR("Error message = %s", error_message);
229 if (g_strcmp0(error_message, "NotAvailable") == 0)
230 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
231 else if (g_strcmp0(error_message, "NotConnected") == 0)
232 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
233 else if (g_strcmp0(error_message, "InProgress") == 0)
234 return BLUETOOTH_TELEPHONY_ERROR_BUSY;
235 else if (g_strcmp0(error_message, "InvalidArguments") == 0)
236 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
237 else if (g_strcmp0(error_message, "AlreadyExists") == 0)
238 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST;
239 else if (g_strcmp0(error_message, "Already Connected") == 0)
240 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
241 else if (g_strcmp0(error_message, "No memory") == 0)
242 return BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY;
243 else if (g_strcmp0(error_message, "I/O error") == 0)
244 return BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR;
245 else if (g_strcmp0(error_message,
246 "Operation currently not available") == 0)
247 return BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE;
248 else if (g_strrstr(error_message, BT_ACCESS_DENIED_MSG))
249 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
251 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
254 static int __bt_telephony_check_privilege(void)
261 reply = __bluetooth_telephony_dbus_method_send(
262 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
263 "CheckPrivilege", &err, NULL);
266 BT_ERR("Error returned in method call");
268 g_dbus_error_strip_remote_error(err);
269 ret = __bt_telephony_get_error(err->message);
273 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
275 g_variant_unref(reply);
278 return BLUETOOTH_TELEPHONY_ERROR_NONE;
281 static void __bt_telephony_event_cb(int event, int result, void *param_data)
283 telephony_event_param_t bt_event = { 0, };
285 bt_event.event = event;
286 bt_event.result = result;
287 bt_event.param_data = param_data;
289 ret_if(telephony_info.cb == NULL);
290 telephony_info.cb(bt_event.event, &bt_event, telephony_info.user_data);
294 static GQuark __bluetooth_telephony_error_quark(void)
296 static GQuark quark = 0;
298 quark = g_quark_from_static_string("telephony");
303 static GVariant *__bluetooth_telephony_dbus_method_send(const char *path,
304 const char *interface, const char *method,
305 GError **err, GVariant *parameters)
309 if (TIZEN_PROFILE_WEARABLE || TIZEN_PROFILE_IVI)
314 GDBusConnection *conn;
318 conn = telephony_dbus_info.conn;
319 retv_if(conn == NULL, NULL);
321 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
322 NULL, HFP_AGENT_SERVICE, path, interface, NULL, err);
324 BT_ERR("Unable to allocate new proxy");
328 reply = g_dbus_proxy_call_sync(proxy, method, parameters,
329 G_DBUS_CALL_FLAGS_NONE, timeout, NULL, err);
331 g_object_unref(proxy);
336 static int __bluetooth_telephony_send_call_status(
337 bt_telephony_call_status_t call_status,
338 unsigned int call_id, const char *ph_number)
343 char *path = g_strdup(telephony_info.call_path);
349 if (NULL == ph_number)
350 phone_number = g_strdup("");
352 phone_number = g_strdup(ph_number);
354 param = g_variant_new("(ssii)", path, phone_number,
355 call_status, call_id);
356 reply = __bluetooth_telephony_dbus_method_send(
357 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
358 "ChangeCallStatus", &err, param);
361 g_free(phone_number);
364 BT_ERR("Error returned in method call");
366 g_dbus_error_strip_remote_error(err);
367 ret = __bt_telephony_get_error(err->message);
371 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
374 g_variant_unref(reply);
376 return BLUETOOTH_TELEPHONY_ERROR_NONE;
379 static void __bluetooth_telephony_error(GDBusMethodInvocation *invocation,
380 bluetooth_telephony_error_t error, const char *err_msg)
382 g_dbus_method_invocation_return_error(invocation,
383 BLUETOOTH_TELEPHONY_ERROR, error,
387 static void __bluetooth_telephony_answer_call(GVariant *var)
389 telephony_event_callid_t call_data = { 0, };
394 g_variant_get(var, "(u)", &callid);
395 BT_DBG("call_id = [%d]", callid);
396 call_data.callid = callid;
398 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL,
399 BLUETOOTH_TELEPHONY_ERROR_NONE,
404 static void __bluetooth_telephony_release_call(GVariant *var)
406 telephony_event_callid_t call_data = { 0, };
411 g_variant_get(var, "(u)", &callid);
412 BT_DBG("call_id = [%d]", callid);
413 call_data.callid = callid;
415 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL,
416 BLUETOOTH_TELEPHONY_ERROR_NONE,
421 static void __bluetooth_telephony_reject_call(GVariant *var)
423 telephony_event_callid_t call_data = { 0, };
428 g_variant_get(var, "(u)", &callid);
429 BT_DBG("call_id = [%d]", callid);
430 call_data.callid = callid;
432 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_REJECT_CALL,
433 BLUETOOTH_TELEPHONY_ERROR_NONE,
438 static void __bluetooth_telephony_threeway_call(GVariant *var)
441 unsigned int chld_value;
445 g_variant_get(var, "(u)", &chld_value);
446 BT_DBG("chld value = [%d]", chld_value);
448 switch (chld_value) {
450 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL;
453 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL;
456 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL;
459 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL;
462 BT_ERR("Invalid CHLD command");
466 __bt_telephony_event_cb(event,
467 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
471 static void __bluetooth_handle_nrec_status_change(GVariant *var)
473 gboolean status = FALSE;
475 g_variant_get(var, "(b)", &status);
476 BT_INFO("NREC status = %d", status);
478 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED,
479 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&status);
483 static void __bluetooth_telephony_event_filter(GDBusConnection *connection,
484 const gchar *sender_name,
485 const gchar *object_path,
486 const gchar *interface_name,
487 const gchar *signal_name,
488 GVariant *parameters,
493 if (strcasecmp(interface_name, HFP_AGENT_SERVICE) == 0) {
494 if (strcasecmp(signal_name, HFP_NREC_STATUS_CHANGE) == 0)
495 __bluetooth_handle_nrec_status_change(parameters);
496 else if (strcasecmp(signal_name, HFP_ANSWER_CALL) == 0)
497 __bluetooth_telephony_answer_call(parameters);
498 else if (strcasecmp(signal_name, HFP_REJECT_CALL) == 0)
499 __bluetooth_telephony_reject_call(parameters);
500 else if (strcasecmp(signal_name, HFP_RELEASE_CALL) == 0)
501 __bluetooth_telephony_release_call(parameters);
502 else if (strcasecmp(signal_name, HFP_THREEWAY_CALL) == 0)
503 __bluetooth_telephony_threeway_call(parameters);
504 } else if (strcasecmp(interface_name, BLUEZ_HEADSET_INTERFACE) == 0) {
505 if (strcasecmp(signal_name, "PropertyChanged") == 0) {
509 g_variant_get(parameters, "(&sv)", &property, &values);
510 BT_DBG("Property: %s", property);
512 if (strcasecmp(property, "State") == 0) {
514 state = (gchar *)g_variant_get_string(values, NULL);
517 BT_ERR("State is null");
520 BT_DBG("state: %s", state);
521 if (g_strcmp0(state, "connected") == 0) {
522 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
523 } else if (g_strcmp0(state, "playing") == 0) {
524 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
525 } else if (g_strcmp0(state, "disconnected") == 0) {
526 /* Headset state: playing -> disconnected */
527 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) {
528 __bt_telephony_event_cb(
529 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
530 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
533 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
535 } else if (strcasecmp(property, "Connected") == 0) {
536 gboolean connected = FALSE;
537 char *dev_addr = NULL;
538 connected = g_variant_get_boolean(values);
539 BT_INFO("connected %d", connected);
541 /*Get device address*/
542 if (object_path != NULL)
543 dev_addr = strstr(object_path, "dev_");
545 if (dev_addr != NULL) {
547 g_strlcpy(telephony_info.address,
549 sizeof(telephony_info.address));
550 g_strdelimit(telephony_info.address, "_", ':');
551 BT_DBG("address is %s",
552 telephony_info.address);
554 telephony_info.headset_state =
555 BLUETOOTH_STATE_CONNECTED;
557 if (telephony_dbus_info.proxy != NULL) {
558 g_object_unref(telephony_dbus_info.proxy);
559 telephony_dbus_info.proxy = NULL;
562 telephony_dbus_info.proxy =
563 __bluetooth_telephony_get_connected_device_proxy();
565 BT_INFO("Headset Connected");
567 __bt_telephony_event_cb(
568 BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED,
569 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
571 } else { /*Device disconnected*/
572 memset(telephony_info.address, 0x00,
573 sizeof(telephony_info.address));
574 telephony_info.headset_state =
575 BLUETOOTH_STATE_DISCONNETED;
577 if (telephony_dbus_info.proxy != NULL) {
578 g_object_unref(telephony_dbus_info.proxy);
579 telephony_dbus_info.proxy = NULL;
582 BT_INFO("Headset Disconnected");
584 __bt_telephony_event_cb(
585 BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED,
586 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
588 } else if (strcasecmp(property, "SpeakerGain") == 0) {
589 unsigned int spkr_gain;
590 guint16 gain = g_variant_get_uint16(values);
592 spkr_gain = (unsigned int)gain;
593 BT_DBG("spk_gain[%d]", spkr_gain);
595 __bt_telephony_event_cb(
596 BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN,
597 BLUETOOTH_TELEPHONY_ERROR_NONE,
599 } else if (strcasecmp(property, "MicrophoneGain") == 0) {
600 unsigned int mic_gain;
601 guint16 gain = g_variant_get_uint16(values);
603 mic_gain = (unsigned int)gain;
604 BT_DBG("mic_gain[%d]", mic_gain);
606 __bt_telephony_event_cb(
607 BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN,
608 BLUETOOTH_TELEPHONY_ERROR_NONE,
610 } else if (strcasecmp(property, "Playing") == 0) {
611 gboolean audio_sink_playing;
613 audio_sink_playing = g_variant_get_boolean(values);
614 if (audio_sink_playing) {
615 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
616 __bt_telephony_event_cb(
617 BLUETOOTH_EVENT_TELEPHONY_AUDIO_CONNECTED,
618 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
620 telephony_info.headset_state =
621 BLUETOOTH_STATE_CONNECTED;
622 __bt_telephony_event_cb(
623 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
624 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
628 g_variant_unref(values);
634 static GDBusNodeInfo *__bt_telephony_create_method_node_info
635 (const gchar *introspection_data)
638 GDBusNodeInfo *node_info = NULL;
640 if (introspection_data == NULL)
643 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
646 BT_ERR("Unable to create node: %s", err->message);
653 int __bluetooth_telephony_register_object(int reg, GDBusNodeInfo *node_info)
655 static guint bt_tel_id = 0;
656 GError *error = NULL;
660 if (node_info == NULL)
661 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
663 path = g_strdup(telephony_info.call_path);
664 BT_DBG("path is [%s]", path);
666 bt_tel_id = g_dbus_connection_register_object(telephony_dbus_info.conn,
667 path, node_info->interfaces[0],
672 if (bt_tel_id == 0) {
673 BT_ERR("Failed to register: %s", error->message);
675 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
679 g_dbus_connection_unregister_object(telephony_dbus_info.conn,
685 return BLUETOOTH_TELEPHONY_ERROR_NONE;
688 static int __bluetooth_telephony_proxy_init(void)
691 GDBusNodeInfo *node_info;
694 name = g_strdup_printf("org.tizen.csd.Call.Instance.p%d", getpid());
695 BT_DBG("well-known name: %s", name);
697 owner_id = g_bus_own_name_on_connection(telephony_dbus_info.conn,
698 name, G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL);
699 BT_DBG("owner_id: %d", owner_id);
702 node_info = __bt_telephony_create_method_node_info(
703 bt_telephony_introspection_xml);
704 if (node_info == NULL) {
705 BT_ERR("node_info NULL");
706 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
708 if (__bluetooth_telephony_register_object(TRUE, node_info) !=
709 BLUETOOTH_TELEPHONY_ERROR_NONE) {
710 BT_ERR("Registation of Method Failed");
711 g_dbus_node_info_unref(node_info);
712 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
716 g_dbus_node_info_unref(node_info);
717 return BLUETOOTH_TELEPHONY_ERROR_NONE;
720 static void __bluetooth_telephony_proxy_deinit(void)
724 __bluetooth_telephony_register_object(FALSE, NULL);
725 g_bus_unown_name(owner_id);
730 static int __bluetooth_telephony_register(void)
735 char *path = g_strdup(telephony_info.call_path);
740 param = g_variant_new("(ss)", path, src_addr);
741 BT_DBG("Path[%s] Src_Address[%s]", path, src_addr);
743 reply = __bluetooth_telephony_dbus_method_send(
744 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
745 "RegisterApplication", &err, param);
750 BT_ERR("Error returned in method call");
752 g_dbus_error_strip_remote_error(err);
753 ret = __bt_telephony_get_error(err->message);
754 BT_ERR("Error here %d\n", ret);
758 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
761 g_variant_unref(reply);
762 BT_DBG("__bluetooth_telephony_register completed");
764 return BLUETOOTH_TELEPHONY_ERROR_NONE;
767 static int __bluetooth_telephony_unregister(void)
772 char *path = g_strdup(telephony_info.call_path);
777 param = g_variant_new("(s)", path);
778 reply = __bluetooth_telephony_dbus_method_send(
779 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
780 "UnregisterApplication", &err, param);
785 BT_ERR("Error returned in method call");
787 g_dbus_error_strip_remote_error(err);
788 ret = __bt_telephony_get_error(err->message);
792 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
795 g_variant_unref(reply);
796 BT_DBG("__bluetooth_telephony_unregister completed");
798 return BLUETOOTH_TELEPHONY_ERROR_NONE;
801 static void __bluetooth_telephony_init_headset_state(void)
805 gboolean status = FALSE;
809 if (telephony_dbus_info.conn == NULL) {
810 BT_ERR("Bluetooth telephony not initilized");
814 reply = __bluetooth_telephony_dbus_method_send(
815 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
816 "IsConnected", &err, NULL);
818 BT_ERR("Error returned in method call\n");
820 BT_ERR("Error message = %s", err->message);
826 g_variant_get(reply, "(b)", &status);
827 g_variant_unref(reply);
829 BT_INFO("Headset Connected Status = [%d]", status);
831 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
835 if (bluetooth_telephony_is_sco_connected())
836 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
841 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
843 gboolean flag = FALSE;
846 switch ((device_class & 0x1f00) >> 8) {
848 switch ((device_class & 0xfc) >> 2) {
866 /* Tizen Wearable device */
868 switch ((device_class & 0xfc) >> 2) {
869 case 0x01: /* Wrist Watch */
877 BT_DBG("[%d]", flag);
882 static gboolean __bluetooth_telephony_is_headset_by_uuid(gchar **uuids)
886 unsigned int service = 0;
890 retv_if(uuids == NULL, FALSE);
892 for (i = 0; uuids[i] != NULL; i++) {
893 parts = g_strsplit(uuids[i], "-", -1);
895 if (parts == NULL || parts[0] == NULL) {
900 service = g_ascii_strtoull(parts[0], NULL, 16);
903 if (service == BLUETOOTH_HS_PROFILE_UUID ||
904 service == BLUETOOTH_HF_PROFILE_UUID)
913 static int __bluetooth_telephony_get_connected_device(void)
915 GDBusConnection *conn;
916 GDBusProxy *headset_agent_proxy = NULL;
917 GDBusProxy *manager_proxy = NULL;
918 GDBusProxy *proxy = NULL;
919 GVariant *reply = NULL;
920 GVariant *getall = NULL;
921 GVariant *isPlayingReply = NULL;
922 GVariant *isConnectedReply = NULL;
923 GVariant *param = NULL;
924 GVariant *var_path = NULL;
925 GVariant *path_values = NULL;
926 GVariant *value = NULL;
927 GError *error = NULL;
929 GVariantIter iter_path;
930 GVariantIter property_iter;
931 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
934 conn = _bt_gdbus_get_system_gconn();
935 retv_if(conn == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
937 manager_proxy = g_dbus_proxy_new_sync(
938 conn, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
939 BLUEZ_SERVICE_NAME, "/",
940 BLUEZ_MANAGER_INTERFACE, NULL, &error);
941 if (manager_proxy == NULL) {
942 BT_ERR("Unable to allocate new proxy \n");
943 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
945 g_dbus_error_strip_remote_error(error);
946 ret = __bt_telephony_get_error(error->message);
947 BT_ERR("Error here %d\n", ret);
953 /* Synchronous call */
954 reply = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects", NULL,
955 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
956 g_object_unref(manager_proxy);
959 BT_ERR("Can't get managed objects");
960 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
962 g_dbus_error_strip_remote_error(error);
963 ret = __bt_telephony_get_error(error->message);
964 BT_ERR("Error here %d\n", ret);
970 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
971 g_variant_iter_init(&iter, reply);
973 while ((param = g_variant_iter_next_value(&iter))) {
974 g_variant_iter_init(&iter_path, param);
976 while ((var_path = g_variant_iter_next_value(&iter_path))) {
978 uint32_t device_class = 0;
979 gboolean playing = FALSE;
980 gboolean connected = FALSE;
981 char *object_path = NULL;
982 gchar *address = NULL;
984 gchar **uuids = NULL;
985 GVariant *getall_param = NULL;
987 g_variant_get(var_path, "{&o*}", &object_path,
989 g_variant_unref(path_values); /* path_values unused*/
991 proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
992 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
993 BLUEZ_SERVICE_NAME, object_path,
994 BLUEZ_PROPERTIES_INTERFACE, NULL, &error);
996 BT_ERR("Unable to allocate new proxy \n");
997 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
999 g_dbus_error_strip_remote_error(error);
1000 ret = __bt_telephony_get_error(error->message);
1001 BT_ERR("Error here %d\n", ret);
1002 g_error_free(error);
1008 getall_param = g_variant_new("s", BLUEZ_DEVICE_INTERFACE);
1009 getall = g_dbus_proxy_call_sync(proxy,
1010 "GetAll", getall_param,
1011 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1012 g_object_unref(proxy);
1015 BT_ERR("Can't get managed objects");
1016 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1018 g_dbus_error_strip_remote_error(error);
1019 ret = __bt_telephony_get_error(error->message);
1020 BT_ERR("Error here %d\n", ret);
1021 g_error_free(error);
1026 g_variant_iter_init(&property_iter, getall);
1028 while (g_variant_iter_loop(&property_iter, "{&sv}", &key, &value)) {
1029 if (!g_strcmp0(key, "Class")) {
1030 device_class = g_variant_get_uint32(value);
1031 BT_DBG("Device Class: %d", device_class);
1032 } else if (!g_strcmp0(key, "UUID")) {
1034 uuids = (gchar **)g_variant_get_strv(value, &len);
1035 BT_DBG_UUID(uuids, len, i);
1036 } else if (!g_strcmp0(key, "Address")) {
1037 address = (gchar *)g_variant_get_string(
1040 BT_DBG("Device Class: %s", address);
1042 g_variant_unref(value);
1044 g_variant_unref(getall);
1046 if (device_class == 0) {
1047 BT_DBG("COD is NULL (maybe paired by nfc)... Checking UUIDs");
1048 if (!__bluetooth_telephony_is_headset_by_uuid(uuids)) {
1049 BT_DBG("UUID checking completed. None HF device");
1052 BT_DBG("UUID checking completed. HF device");
1054 if (!__bluetooth_telephony_is_headset(device_class))
1058 /* this is headset; Check for Connection */
1059 headset_agent_proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
1060 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1061 HFP_AGENT_SERVICE, object_path,
1062 HFP_AGENT_INTERFACE, NULL, &error);
1063 if (headset_agent_proxy == NULL) {
1064 BT_ERR("Unable to allocate new headset_agent_proxy");
1065 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1067 g_dbus_error_strip_remote_error(error);
1068 ret = __bt_telephony_get_error(error->message);
1069 BT_ERR("Error here %d\n", ret);
1070 g_error_free(error);
1075 isConnectedReply = g_dbus_proxy_call_sync(headset_agent_proxy,
1076 "IsConnected", NULL,
1077 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1080 if (!isConnectedReply) {
1081 BT_ERR("Can't get managed objects");
1082 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1084 g_dbus_error_strip_remote_error(error);
1085 ret = __bt_telephony_get_error(error->message);
1086 BT_ERR("Error here %d\n", ret);
1087 g_error_free(error);
1091 connected = g_variant_get_boolean(isConnectedReply);
1092 g_variant_unref(isConnectedReply);
1095 g_strlcpy(telephony_info.address,
1097 sizeof(telephony_info.address));
1099 isPlayingReply = g_dbus_proxy_call_sync(headset_agent_proxy,
1101 G_DBUS_CALL_FLAGS_NONE,
1103 if (!isPlayingReply) {
1104 BT_ERR("Can't get managed objects");
1105 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1107 g_dbus_error_strip_remote_error(error);
1108 ret = __bt_telephony_get_error(error->message);
1109 BT_ERR("Error here %d\n", ret);
1110 g_error_free(error);
1113 playing = g_variant_get_boolean(isPlayingReply);
1114 g_variant_unref(isPlayingReply);
1117 telephony_info.headset_state =
1118 BLUETOOTH_STATE_PLAYING;
1120 telephony_info.headset_state =
1121 BLUETOOTH_STATE_CONNECTED;
1128 g_object_unref(headset_agent_proxy);
1129 g_variant_unref(var_path);
1131 g_variant_unref(param);
1135 if (headset_agent_proxy)
1136 g_object_unref(headset_agent_proxy);
1138 g_variant_unref(reply);
1140 g_variant_unref(var_path);
1142 g_variant_unref(param);
1147 static GDBusProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1149 GDBusProxy *proxy = NULL;
1150 GError *error = NULL;
1154 if (strlen(telephony_info.address) == 0)
1155 __bluetooth_telephony_get_connected_device();
1157 if (strlen(telephony_info.address) == 0)
1160 proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
1161 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1162 HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1163 HFP_AGENT_INTERFACE, NULL, &error);
1164 if (proxy == NULL) {
1165 BT_ERR("Unable to allocate new proxy");
1167 g_dbus_error_strip_remote_error(error);
1168 ret = __bt_telephony_get_error(error->message);
1169 BT_ERR("Error here %d\n", ret);
1170 g_error_free(error);
1179 int __bt_telephony_subscribe_adapter_signal(GDBusConnection *conn,
1185 static guint subscribe_adapter_id = 0;
1187 if (subscribe == TRUE) {
1188 if (subscribe_adapter_id == 0) {
1189 subscribe_adapter_id = g_dbus_connection_signal_subscribe(conn,
1190 NULL, "org.freedesktop.DBus.ObjectManager",
1191 "InterfacesAdded", NULL, NULL, 0,
1192 __bt_telephony_adapter_filter,
1195 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1197 if (subscribe_adapter_id > 0) {
1198 g_dbus_connection_signal_unsubscribe(conn,
1199 subscribe_adapter_id);
1200 subscribe_adapter_id = 0;
1202 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1206 int __bt_telephony_event_subscribe_signal(GDBusConnection *conn,
1212 static guint subscribe_event1_id = 0;
1213 static guint subscribe_event2_id = 0;
1214 static guint subscribe_event3_id = 0;
1215 static guint subscribe_event4_id = 0;
1216 static guint subscribe_event5_id = 0;
1217 static guint subscribe_event6_id = 0;
1219 if (subscribe == TRUE) {
1220 if (subscribe_event1_id == 0) {
1221 subscribe_event1_id = g_dbus_connection_signal_subscribe(conn,
1222 NULL, BLUEZ_HEADSET_INTERFACE,
1223 "PropertyChanged", NULL, NULL, 0,
1224 __bluetooth_telephony_event_filter,
1227 if (subscribe_event2_id == 0) {
1228 subscribe_event2_id = g_dbus_connection_signal_subscribe(conn,
1229 NULL, HFP_AGENT_SERVICE,
1230 HFP_NREC_STATUS_CHANGE, NULL, NULL, 0,
1231 __bluetooth_telephony_event_filter,
1235 if (subscribe_event3_id == 0) {
1236 subscribe_event3_id = g_dbus_connection_signal_subscribe(conn,
1237 NULL, HFP_AGENT_SERVICE,
1238 HFP_ANSWER_CALL, NULL, NULL, 0,
1239 __bluetooth_telephony_event_filter,
1242 if (subscribe_event4_id == 0) {
1243 subscribe_event4_id = g_dbus_connection_signal_subscribe(conn,
1244 NULL, HFP_AGENT_SERVICE,
1245 HFP_REJECT_CALL, NULL, NULL, 0,
1246 __bluetooth_telephony_event_filter,
1249 if (subscribe_event5_id == 0) {
1250 subscribe_event5_id = g_dbus_connection_signal_subscribe(conn,
1251 NULL, HFP_AGENT_SERVICE,
1252 HFP_RELEASE_CALL, NULL, NULL, 0,
1253 __bluetooth_telephony_event_filter,
1256 if (subscribe_event6_id == 0) {
1257 subscribe_event6_id = g_dbus_connection_signal_subscribe(conn,
1258 NULL, HFP_AGENT_SERVICE,
1259 HFP_THREEWAY_CALL, NULL, NULL, 0,
1260 __bluetooth_telephony_event_filter,
1264 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1266 if (subscribe_event1_id > 0) {
1267 g_dbus_connection_signal_unsubscribe(conn,
1268 subscribe_event1_id);
1269 subscribe_event1_id = 0;
1271 if (subscribe_event2_id > 0) {
1272 g_dbus_connection_signal_unsubscribe(conn,
1273 subscribe_event2_id);
1274 subscribe_event2_id = 0;
1276 if (subscribe_event3_id > 0) {
1277 g_dbus_connection_signal_unsubscribe(conn,
1278 subscribe_event3_id);
1279 subscribe_event3_id = 0;
1281 if (subscribe_event4_id > 0) {
1282 g_dbus_connection_signal_unsubscribe(conn,
1283 subscribe_event4_id);
1284 subscribe_event4_id = 0;
1286 if (subscribe_event5_id > 0) {
1287 g_dbus_connection_signal_unsubscribe(conn,
1288 subscribe_event5_id);
1289 subscribe_event5_id = 0;
1291 if (subscribe_event6_id > 0) {
1292 g_dbus_connection_signal_unsubscribe(conn,
1293 subscribe_event6_id);
1294 subscribe_event6_id = 0;
1296 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1300 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1303 bluetooth_device_address_t loc_address = { {0} };
1304 char src_address[BT_ADDRESS_STRING_SIZE] = { 0 };
1305 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1306 GError *error = NULL;
1310 if (is_initialized == TRUE) {
1311 BT_ERR("Bluetooth telephony already initilized");
1312 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1315 is_initialized = TRUE;
1317 /* As a result of discussion with system team, private connection is not
1318 * suitable in here. It is better to use shared connection. */
1319 //telephony_dbus_info.conn = _bt_gdbus_init_system_gconn();
1320 telephony_dbus_info.conn = _bt_init_system_gdbus_conn();
1321 if (!telephony_dbus_info.conn) {
1322 is_initialized = FALSE;
1323 BT_ERR("Could not get DBus Connection");
1324 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1328 snprintf(telephony_info.call_path, sizeof(telephony_info.call_path),
1329 CSD_CALL_APP_PATH, getpid());
1330 BT_INFO("Call Path = %s", telephony_info.call_path);
1331 memset(telephony_info.address, 0x00, sizeof(telephony_info.address));
1333 if (__bluetooth_telephony_proxy_init()) {
1334 BT_ERR("__bluetooth_telephony_proxy_init failed\n");
1335 telephony_dbus_info.conn = NULL;
1336 is_initialized = FALSE;
1337 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1340 telephony_dbus_info.manager_proxy = g_dbus_proxy_new_sync(
1341 telephony_dbus_info.conn,
1342 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1343 BLUEZ_SERVICE_NAME, "/",
1344 BLUEZ_MANAGER_INTERFACE, NULL, &error);
1345 if (telephony_dbus_info.manager_proxy == NULL) {
1346 BT_ERR("Could not create a manager proxy");
1347 __bluetooth_telephony_proxy_deinit();
1348 telephony_dbus_info.conn = NULL;
1349 is_initialized = FALSE;
1351 g_dbus_error_strip_remote_error(error);
1352 ret = __bt_telephony_get_error(error->message);
1353 BT_ERR("Error here %d\n", ret);
1354 g_error_free(error);
1357 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1360 telephony_dbus_info.dbus_proxy = g_dbus_proxy_new_sync(
1361 telephony_dbus_info.conn,
1362 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1363 BT_EVENT_FREEDESKTOP, BT_FREEDESKTOP_PATH,
1364 BT_EVENT_FREEDESKTOP, NULL, &error);
1365 if (NULL == telephony_dbus_info.dbus_proxy) {
1366 __bluetooth_telephony_proxy_deinit();
1367 telephony_dbus_info.conn = NULL;
1368 g_object_unref(telephony_dbus_info.manager_proxy);
1369 telephony_dbus_info.manager_proxy = NULL;
1370 is_initialized = FALSE;
1371 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1374 if (__bt_telephony_subscribe_adapter_signal(telephony_dbus_info.conn, TRUE) != 0) {
1375 BT_ERR("Fail to Subscribe Adapter Signal");
1379 /*Callback and user applicaton data*/
1380 telephony_info.cb = cb;
1381 telephony_info.user_data = user_data;
1382 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1384 if (__bt_telephony_event_subscribe_signal(telephony_dbus_info.conn, TRUE) != 0) {
1385 BT_ERR("Fail to Subscribe telephony event Signal");
1389 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED)
1390 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1392 /*Bluetooth is active, therefore set the flag */
1395 ret = bluetooth_get_local_address(&loc_address);
1396 if (ret != BLUETOOTH_ERROR_NONE) {
1397 BT_ERR("Fail to get local address\n");
1398 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1401 _bt_convert_addr_type_to_string(src_address, loc_address.addr);
1402 src_addr = g_strdup(src_address);
1404 ret = __bluetooth_telephony_register();
1405 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1406 BT_ERR("__bluetooth_telephony_register failed\n");
1410 if (TIZEN_PROFILE_WEARABLE || TIZEN_PROFILE_IVI)
1411 __bluetooth_telephony_init_headset_state();
1416 bluetooth_telephony_deinit();
1420 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1423 BT_TELEPHONY_CHECK_INITIALIZED();
1425 is_initialized = FALSE;
1427 if (__bt_telephony_event_subscribe_signal(telephony_dbus_info.conn, FALSE) != 0)
1428 BT_ERR("Fail to UnSubscribe telephony event Signal");
1430 if (bluetooth_check_adapter() != BLUETOOTH_ADAPTER_DISABLED ||
1431 bluetooth_check_adapter_le() != BLUETOOTH_ADAPTER_LE_DISABLED)
1432 __bluetooth_telephony_unregister();
1434 __bluetooth_telephony_proxy_deinit();
1436 telephony_info.cb = NULL;
1437 telephony_info.user_data = NULL;
1438 telephony_info.call_count = 0;
1439 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1441 /* Remove BT enabled signal */
1442 if (__bt_telephony_subscribe_adapter_signal(telephony_dbus_info.conn, FALSE) != 0)
1443 BT_ERR("Fail to UnSubscribe Adapter event Signal");
1448 if (telephony_dbus_info.manager_proxy != NULL) {
1449 g_object_unref(telephony_dbus_info.manager_proxy);
1450 telephony_dbus_info.manager_proxy = NULL;
1453 if (telephony_dbus_info.conn != NULL)
1454 telephony_dbus_info.conn = NULL;
1456 if (telephony_dbus_info.dbus_proxy != NULL) {
1457 g_object_unref(telephony_dbus_info.dbus_proxy);
1458 telephony_dbus_info.dbus_proxy = NULL;
1462 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1465 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1469 gboolean status = FALSE;
1473 retv_if(is_initialized == FALSE, FALSE);
1474 retv_if(bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED, FALSE);
1476 reply = __bluetooth_telephony_dbus_method_send(
1477 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1478 "IsPlaying", &err, NULL);
1481 BT_ERR("Error returned in method call\n");
1483 BT_ERR("Error message = %s", err->message);
1488 g_variant_get(reply, "(b)", &status);
1489 g_variant_unref(reply);
1491 if (TIZEN_PROFILE_WEARABLE || TIZEN_PROFILE_IVI)
1492 if (status == TRUE && telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1493 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
1495 BT_INFO("SCO Connected Status = [%d]", status);
1499 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1504 GVariant *param_inner;
1508 BT_TELEPHONY_CHECK_INITIALIZED();
1509 BT_TELEPHONY_CHECK_ENABLED();
1512 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1514 if (telephony_info.headset_state == BLUETOOTH_STATE_DISCONNETED)
1515 return BLUETOOTH_TELEPHONY_ERROR_AUDIO_NOT_CONNECTED;
1517 reply = __bluetooth_telephony_dbus_method_send(
1518 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1519 "GetProperties", &err, NULL);
1522 BT_ERR("Error returned in method call\n");
1524 BT_DBG("Error message = %s", err->message);
1527 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1530 g_variant_iter_init(&iter, reply);
1531 while ((param_inner = g_variant_iter_next_value(&iter))) {
1534 value = g_variant_lookup_value(param_inner,
1535 "nrec", G_VARIANT_TYPE_BOOLEAN);
1537 BT_DBG("Property NREC Found");
1538 *status = g_variant_get_boolean(value);
1539 BT_DBG("NREC status = [%d]", *status);
1540 g_variant_unref(value);
1541 g_variant_unref(param_inner);
1544 g_variant_unref(param_inner);
1546 BT_DBG("NREC status = [%d]", *status);
1547 g_variant_unref(reply);
1550 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1553 BT_EXPORT_API int bluetooth_telephony_is_wbs_mode(gboolean *status)
1559 GVariant *param_inner;
1563 BT_TELEPHONY_CHECK_INITIALIZED();
1564 BT_TELEPHONY_CHECK_ENABLED();
1567 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1571 reply = __bluetooth_telephony_dbus_method_send(
1572 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1573 "GetProperties", &err, NULL);
1576 BT_ERR("Error returned in method call");
1578 BT_ERR("Error message = %s", err->message);
1581 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1584 g_variant_iter_init(&iter, reply);
1585 while ((param_inner = g_variant_iter_next_value(&iter))) {
1588 value = g_variant_lookup_value(param_inner,
1589 "codec", G_VARIANT_TYPE_UINT32);
1591 BT_DBG("Property CODEC Found");
1592 codec = g_variant_get_uint32(value);
1593 g_variant_unref(value);
1594 BT_DBG("Codec = [%d]", codec);
1596 *status = codec == BT_MSBC_CODEC_ID ? TRUE : FALSE;
1597 BT_DBG("NREC status = [%d]", *status);
1598 g_variant_unref(value);
1599 g_variant_unref(param_inner);
1602 g_variant_unref(param_inner);
1605 g_variant_unref(reply);
1606 BT_DBG("MSBC status = [%d]", *status);
1609 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1612 BT_EXPORT_API int bluetooth_telephony_send_vendor_cmd(const char *cmd)
1614 GError *error = NULL;
1615 GVariant *reply, *parameters;
1616 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1620 BT_TELEPHONY_CHECK_INITIALIZED();
1621 BT_TELEPHONY_CHECK_ENABLED();
1623 BT_DBG("Send Vendor %s", cmd);
1625 if (telephony_dbus_info.proxy == NULL)
1626 telephony_dbus_info.proxy =
1627 __bluetooth_telephony_get_connected_device_proxy();
1629 if (telephony_dbus_info.proxy == NULL)
1630 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1632 parameters = g_variant_new("s", cmd);
1633 reply = g_dbus_proxy_call_sync(telephony_dbus_info.proxy,
1634 "SendVendorAtCmd", parameters,
1635 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1637 g_variant_unref(reply);
1640 g_dbus_error_strip_remote_error(error);
1641 ret = __bt_telephony_get_error(error->message);
1642 BT_ERR("Error here %d\n", ret);
1643 g_error_free(error);
1650 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1656 gboolean state = TRUE;
1660 BT_TELEPHONY_CHECK_INITIALIZED();
1661 BT_TELEPHONY_CHECK_ENABLED();
1663 param = g_variant_new("(b)", &state);
1664 reply = __bluetooth_telephony_dbus_method_send(
1665 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1666 "SetVoiceDial", &err, param);
1669 BT_ERR("Error returned in method call\n");
1671 g_dbus_error_strip_remote_error(err);
1672 ret = __bt_telephony_get_error(err->message);
1676 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1679 g_variant_unref(reply);
1681 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1684 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1690 gboolean state = FALSE;
1694 BT_TELEPHONY_CHECK_INITIALIZED();
1695 BT_TELEPHONY_CHECK_ENABLED();
1697 param = g_variant_new("(b)", &state);
1698 reply = __bluetooth_telephony_dbus_method_send(
1699 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1700 "SetVoiceDial", &err, param);
1703 BT_ERR("Error returned in method call\n");
1705 g_dbus_error_strip_remote_error(err);
1706 ret = __bt_telephony_get_error(err->message);
1710 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1713 g_variant_unref(reply);
1716 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1719 static void __bluetooth_telephony_sco_start_cb(GDBusProxy *proxy,
1720 GAsyncResult *res, gpointer user_data)
1722 GError *error = NULL;
1723 GVariant *value = NULL;
1725 value = g_dbus_proxy_call_finish(proxy, res, &error);
1726 if (value == NULL) {
1727 if (error != NULL) {
1728 BT_ERR("sco_close_cb error. errCode[%x],message[%s]",
1729 error->code, error->message);
1730 g_clear_error(&error);
1732 BT_ERR("SCo Start Failed");
1734 g_object_unref(proxy);
1738 BT_DBG("sco_start_cb : -");
1739 g_object_unref(proxy);
1740 g_variant_unref(value);
1743 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1745 GDBusConnection *conn;
1752 BT_TELEPHONY_CHECK_INITIALIZED();
1753 BT_TELEPHONY_CHECK_ENABLED();
1755 /* Because this API is async call, so can't use dbus SMACK */
1756 if (__bt_telephony_check_privilege() ==
1757 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1758 BT_ERR("Don't have a privilege to use this API");
1759 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1762 conn = _bt_gdbus_get_system_gconn();
1764 BT_DBG("No System Bus found\n");
1765 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1768 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1769 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1771 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1772 HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1773 HFP_AGENT_INTERFACE, NULL, &err);
1774 if (proxy == NULL) {
1775 BT_ERR("Unable to allocate new proxy");
1777 g_dbus_error_strip_remote_error(err);
1778 ret = __bt_telephony_get_error(err->message);
1779 BT_ERR("Error here %d\n", ret);
1783 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1786 g_dbus_proxy_call(proxy, "Play", NULL, G_DBUS_CALL_FLAGS_NONE,
1787 -1, NULL, (GAsyncReadyCallback)__bluetooth_telephony_sco_start_cb, NULL);
1790 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1793 static void __bluetooth_telephony_sco_close_cb(GDBusProxy *proxy,
1794 GAsyncResult *res, gpointer user_data)
1796 GError *error = NULL;
1797 GVariant *value = NULL;
1799 value = g_dbus_proxy_call_finish(proxy, res, &error);
1800 if (value == NULL) {
1801 if (error != NULL) {
1802 BT_ERR("sco_close_cb error. errCode[%x],message[%s]",
1803 error->code, error->message);
1804 g_clear_error(&error);
1806 BT_ERR("SCo close Failed");
1808 g_object_unref(proxy);
1812 BT_DBG("sco_close_cb : -");
1813 g_object_unref(proxy);
1814 g_variant_unref(value);
1816 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1818 GDBusConnection *conn;
1825 BT_TELEPHONY_CHECK_INITIALIZED();
1826 BT_TELEPHONY_CHECK_ENABLED();
1828 /* Because this API is async call, so can't use dbus SMACK */
1829 if (__bt_telephony_check_privilege() ==
1830 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1831 BT_ERR("Don't have a privilege to use this API");
1832 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1835 conn = _bt_gdbus_get_system_gconn();
1837 BT_DBG("No System Bus found\n");
1838 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1841 if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1842 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1844 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1845 HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1846 HFP_AGENT_INTERFACE, NULL, &err);
1847 if (proxy == NULL) {
1848 BT_ERR("Unable to allocate new proxy");
1850 g_dbus_error_strip_remote_error(err);
1851 ret = __bt_telephony_get_error(err->message);
1852 BT_ERR("Error here %d\n", ret);
1856 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1859 g_dbus_proxy_call(proxy, "Stop", NULL, G_DBUS_CALL_FLAGS_NONE,
1860 -1, NULL, (GAsyncReadyCallback)__bluetooth_telephony_sco_close_cb, NULL);
1862 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
1865 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1868 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1872 BT_TELEPHONY_CHECK_INITIALIZED();
1873 BT_TELEPHONY_CHECK_ENABLED();
1876 BT_DBG("call_id = [%d]", call_id);
1878 /*Make sure SCO is already connected */
1879 ret = __bluetooth_telephony_send_call_status(
1880 CSD_CALL_STATUS_MO_ALERTING, call_id, NULL);
1882 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1883 BT_ERR("send call status Failed = [%d]", ret);
1889 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
1890 unsigned int bt_audio)
1895 BT_DBG("call_id = [%d]", call_id);
1897 BT_TELEPHONY_CHECK_INITIALIZED();
1898 BT_TELEPHONY_CHECK_ENABLED();
1900 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1902 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1903 BT_ERR("send call status Failed = [%d]", ret);
1908 if (!bluetooth_telephony_is_sco_connected()) {
1909 ret = bluetooth_telephony_audio_open();
1910 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1911 BT_ERR("Audio connection call Failed[%d]", ret);
1919 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
1924 BT_DBG("call_id = [%d]", call_id);
1926 BT_TELEPHONY_CHECK_INITIALIZED();
1927 BT_TELEPHONY_CHECK_ENABLED();
1929 if (telephony_info.call_count > 0)
1930 telephony_info.call_count = telephony_info.call_count - 1;
1932 if (telephony_info.call_count == 0) {
1933 if (bluetooth_telephony_is_sco_connected()) {
1934 ret = bluetooth_telephony_audio_close();
1935 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1936 BT_ERR(" Failed = [%d]", ret);
1940 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
1942 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1943 BT_ERR("send call status Failed = [%d]", ret);
1949 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
1954 BT_DBG("call_id = [%d]", call_id);
1956 BT_TELEPHONY_CHECK_INITIALIZED();
1957 BT_TELEPHONY_CHECK_ENABLED();
1959 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
1961 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1962 BT_ERR("send call status Failed = [%d]", ret);
1968 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
1973 BT_DBG("call_id = [%d]", call_id);
1975 BT_TELEPHONY_CHECK_INITIALIZED();
1976 BT_TELEPHONY_CHECK_ENABLED();
1978 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1980 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1981 BT_ERR("send call status Failed = [%d]", ret);
1987 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
1988 unsigned int call_count)
1992 GList *list = call_list;
1993 bt_telephony_call_status_info_t *call_status;
1997 BT_TELEPHONY_CHECK_INITIALIZED();
1998 BT_TELEPHONY_CHECK_ENABLED();
2001 BT_ERR("call_list is invalid");
2002 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2005 /* Because this API is async call, so can't use dbus SMACK */
2006 if (__bt_telephony_check_privilege() ==
2007 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
2008 BT_ERR("Don't have a privilege to use this API");
2009 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
2012 BT_DBG(" call_count = [%d]", call_count);
2014 for (i = 0; i < call_count; i++) {
2015 call_status = g_list_nth_data(list, i);
2017 if (NULL == call_status)
2020 BT_DBG(" %d : Call id [%d] status[%d]", i,
2021 call_status->call_id,
2022 call_status->call_status);
2024 if (NULL != call_status->phone_number)
2025 DBG_SECURE("Number [%s]", call_status->phone_number);
2027 switch (call_status->call_status) {
2028 case BLUETOOTH_CALL_STATE_HELD:
2029 ret = __bluetooth_telephony_send_call_status(
2030 CSD_CALL_STATUS_HOLD,
2031 call_status->call_id,
2032 call_status->phone_number);
2033 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2034 BT_ERR("Failed = %d", ret);
2039 case BLUETOOTH_CALL_STATE_CONNECTED:
2040 ret = __bluetooth_telephony_send_call_status(
2041 CSD_CALL_STATUS_ACTIVE,
2042 call_status->call_id,
2043 call_status->phone_number);
2044 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2045 BT_ERR("Failed = [%d]", ret);
2051 if ((call_status->call_status <
2052 BLUETOOTH_CALL_STATE_NONE) ||
2053 (call_status->call_status >=
2054 BLUETOOTH_CALL_STATE_ERROR)) {
2055 BT_ERR("Unknown Call state");
2056 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
2062 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2065 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
2066 unsigned int call_count)
2072 ret = bluetooth_telephony_call_swapped(call_list, call_count);
2074 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2075 BT_ERR("Failed = [%d]", ret);
2079 telephony_info.call_count = call_count;
2082 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2085 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
2086 const char *ph_number, unsigned int call_id,
2087 unsigned int bt_audio)
2092 const char *path = telephony_info.call_path;
2093 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
2097 BT_TELEPHONY_CHECK_INITIALIZED();
2098 BT_TELEPHONY_CHECK_ENABLED();
2100 if (NULL == ph_number)
2101 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2103 param = g_variant_new("(ssi)", path, ph_number, call_id);
2104 reply = __bluetooth_telephony_dbus_method_send(
2105 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2106 "OutgoingCall", &err, param);
2109 BT_ERR("Error returned in method call\n");
2111 g_dbus_error_strip_remote_error(err);
2112 ret = __bt_telephony_get_error(err->message);
2116 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2119 g_variant_unref(reply);
2121 telephony_info.call_count++;
2122 BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
2125 if (!bluetooth_telephony_is_sco_connected()) {
2126 ret = bluetooth_telephony_audio_open();
2128 BT_ERR(" Audio connection Failed = %d", ret);
2136 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
2137 const char *ph_number, unsigned int call_id)
2142 const char *path = telephony_info.call_path;
2147 BT_TELEPHONY_CHECK_INITIALIZED();
2148 BT_TELEPHONY_CHECK_ENABLED();
2150 if (NULL == ph_number)
2151 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2153 param = g_variant_new("(ssi)", path, ph_number, call_id);
2154 reply = __bluetooth_telephony_dbus_method_send(
2155 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2156 "IncomingCall", &err, param);
2159 BT_ERR("Error returned in method call\n");
2161 g_dbus_error_strip_remote_error(err);
2162 ret = __bt_telephony_get_error(err->message);
2166 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2169 g_variant_unref(reply);
2170 telephony_info.call_count++;
2171 BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
2173 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2176 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(
2177 unsigned short speaker_gain)
2186 BT_TELEPHONY_CHECK_INITIALIZED();
2187 BT_TELEPHONY_CHECK_ENABLED();
2189 BT_DBG("set speaker_gain= [%d]", speaker_gain);
2191 param = g_variant_new("(q)", speaker_gain);
2192 reply = __bluetooth_telephony_dbus_method_send(
2193 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2194 "SetSpeakerGain", &err, param);
2197 BT_ERR("Error returned in method call\n");
2199 g_dbus_error_strip_remote_error(err);
2200 ret = __bt_telephony_get_error(err->message);
2204 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2207 g_variant_unref(reply);
2209 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2212 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(
2213 unsigned int *speaker_gain)
2222 BT_TELEPHONY_CHECK_INITIALIZED();
2223 BT_TELEPHONY_CHECK_ENABLED();
2225 reply = __bluetooth_telephony_dbus_method_send(
2226 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2227 "GetSpeakerGain", &err, NULL);
2230 BT_ERR("Error returned in method call\n");
2232 g_dbus_error_strip_remote_error(err);
2233 ret = __bt_telephony_get_error(err->message);
2237 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2239 g_variant_get(reply, "(q)", &gain);
2240 *speaker_gain = gain;
2241 BT_DBG("Get speaker_gain= [%d]", *speaker_gain);
2243 g_variant_unref(reply);
2246 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2249 BT_EXPORT_API int bluetooth_telephony_is_connected(gboolean *ag_connected)
2254 gboolean ag_connected_from_bt_agent;
2256 BT_CHECK_ENABLED(return);
2258 reply = __bluetooth_telephony_dbus_method_send(
2259 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2260 "IsConnected", &err, NULL);
2263 BT_ERR("Error returned in method call\n");
2265 g_dbus_error_strip_remote_error(err);
2266 ret = __bt_telephony_get_error(err->message);
2270 return BLUETOOTH_ERROR_INTERNAL;
2272 g_variant_get(reply, "(b)", &ag_connected_from_bt_agent);
2273 *ag_connected = ag_connected_from_bt_agent;
2275 BT_DBG("Conn Status: %s", *ag_connected ? "Connected" : "Disconnected");
2277 g_variant_unref(reply);
2279 return BLUETOOTH_ERROR_NONE;
2282 BT_EXPORT_API int bluetooth_telephony_set_active_headset(const char *remote_addr)
2284 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
2290 BT_CHECK_ENABLED(return);
2292 if (NULL == remote_addr)
2293 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2295 param = g_variant_new("(s)", remote_addr);
2296 reply = __bluetooth_telephony_dbus_method_send(
2297 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2298 "SwapHeadset", &err, param);
2301 BT_ERR("Error returned in method call\n");
2303 g_dbus_error_strip_remote_error(err);
2304 ret = __bt_telephony_get_error(err->message);
2308 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2311 g_variant_unref(reply);
2312 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2314 return BLUETOOTH_ERROR_NOT_SUPPORT;
2318 static void __bt_telephony_adapter_filter(GDBusConnection *connection,
2319 const gchar *sender_name,
2320 const gchar *object_path,
2321 const gchar *interface_name,
2322 const gchar *signal_name,
2323 GVariant *parameters,
2330 if (strcasecmp(signal_name, "InterfacesAdded") == 0) {
2331 GVariant *optional_param = NULL;
2333 g_variant_get(parameters, "(&o@a{sa{sv}})",
2334 &path, &optional_param);
2337 BT_ERR("Invalid adapter path");
2341 BT_INFO("Adapter Path = [%s]", path);
2342 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
2343 if (__bt_telephony_get_src_addr(optional_param))
2344 BT_ERR("Fail to get the local adapter address");
2346 ret = __bluetooth_telephony_register();
2347 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2348 BT_ERR("__bluetooth_telephony_register failed");
2351 g_variant_unref(optional_param);
2357 static int __bt_telephony_get_src_addr(GVariant *value)
2360 GVariant *param = NULL;
2363 /* signature a{sa{sv}} */
2364 g_variant_iter_init(&iter, value);
2365 while ((param = g_variant_iter_next_value(&iter))) {
2366 char *interface_name;
2367 GVariant *interface_var = NULL;
2368 GVariant *param_inner = NULL;
2370 g_variant_get(param, "{&s*}", &interface_name, &interface_var);
2371 g_variant_unref(param);
2373 BT_DBG("interface_name: %s", interface_name);
2374 /* format of interface_var: a{sv}*/
2375 if (strcasecmp(interface_name, BLUEZ_ADAPTER_INTERFACE) == 0) {
2376 GVariantIter iter_inner;
2378 g_variant_iter_init(&iter_inner, interface_var);
2379 while ((param_inner = g_variant_iter_next_value(&iter_inner))) {
2380 char *property_name;
2381 GVariant *property_var;
2383 g_variant_get(param_inner, "{&sv}",
2386 g_variant_unref(param_inner);
2388 if (strcasecmp(property_name, "Address") == 0) {
2389 const gchar *bd_addr;
2391 bd_addr = g_variant_get_string(
2394 src_addr = g_strdup(bd_addr);
2395 BT_DBG("Address: %s", src_addr);
2397 g_variant_unref(interface_var);
2398 g_variant_unref(property_var);
2401 g_variant_unref(property_var);
2404 g_variant_unref(interface_var);
2408 return BLUETOOTH_ERROR_NONE;