4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * GirishAshok Joshi <girish.joshi@samsung.com>
8 * Chanyeol Park <chanyeol.park@samsung.com>
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
27 #include <dbus/dbus.h>
28 #include <dbus/dbus-glib-bindings.h>
31 #include <vconf-keys.h>
33 #include "bt-common.h"
34 #include "bluetooth-telephony-api.h"
37 #define BT_SCO_TIMEOUT 3000
39 #define BT_CVSD_CODEC_ID 1
40 #define BT_MSBC_CODEC_ID 2
43 DBusGConnection *conn;
45 DBusGProxy *dbus_proxy;
46 DBusGProxy *manager_proxy;
47 } telephony_dbus_info_t;
50 bt_telephony_func_ptr cb;
51 unsigned int call_count;
53 char address[BT_ADDRESS_STR_LEN];
54 char call_path[BT_AUDIO_CALL_PATH_LEN];
55 bluetooth_headset_state_t headset_state;
57 } bt_telephony_info_t;
60 char *src_addr = NULL;
64 #define BLUETOOTH_TELEPHONY_ERROR (__bluetooth_telephony_error_quark())
66 #define BLUEZ_SERVICE_NAME "org.bluez"
67 #define BLUEZ_HEADSET_INTERFACE "org.bluez.Headset"
69 #define BLUEZ_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager"
70 #define BLUEZ_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
71 #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1"
72 #define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1"
73 #define HFP_AGENT_SERVICE "org.bluez.ag_agent"
76 #define HFP_AGENT_PATH "/org/bluez/hfp_ag"
77 #define HFP_AGENT_INTERFACE "Org.Hfp.App.Interface"
79 #define CSD_CALL_APP_PATH "/org/tizen/csd/%d"
80 #define HFP_NREC_STATUS_CHANGE "NrecStatusChanged"
81 #define HFP_ANSWER_CALL "Answer"
82 #define HFP_REJECT_CALL "Reject"
83 #define HFP_RELEASE_CALL "Release"
84 #define HFP_THREEWAY_CALL "Threeway"
86 #define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
89 #define BT_TELEPHONY_CHECK_ENABLED() \
91 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) \
93 BT_ERR("BT is not enabled"); \
94 return BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED; \
98 static gboolean is_initialized = FALSE;
99 #define BT_TELEPHONY_CHECK_INITIALIZED() \
101 if (is_initialized == FALSE) \
103 BT_ERR("Bluetooth telephony not initilized"); \
104 return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED; \
108 #define BLUETOOTH_TELEPHONY_METHOD (bluetooth_telephony_method_get_type())
109 #define BLUETOOTH_TELEPHONY_METHOD_GET_OBJECT(obj) \
110 (G_TYPE_CHECK_INSTANCE_CAST((obj), \
111 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethod))
113 #define BLUETOOTH_TELEPHONY_METHOD_IS_OBJECT(obj) \
114 (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
115 BLUETOOTH_TELEPHONY_METHOD))
117 #define BLUETOOTH_TELEPHONY_METHOD_CLASS(class) \
118 (G_TYPE_CHECK_CLASS_CAST((class), \
119 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))
121 #define BLUETOOTH_TELEPHONY_METHOD_GET_AGENT_CLASS(obj) \
122 (G_TYPE_INSTANCE_GET_CLASS((obj), \
123 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))
125 #define BLUETOOTH_TELEPHONY_METHOD_IS_AGENT_CLASS(class) \
126 (G_TYPE_CHECK_CLASS_TYPE((class), BLUETOOTH_TELEPHONY_METHOD))
128 #define BLUETOOTH_TELEPHONY_METHOD_AGENT_GET_PRIVATE(obj) \
129 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
130 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodPrivate))
132 typedef struct _BluetoothTelephonyMethod BluetoothTelephonyMethod;
133 typedef struct _BluetoothTelephonyMethodClass BluetoothTelephonyMethodClass;
135 struct _BluetoothTelephonyMethod {
139 struct _BluetoothTelephonyMethodClass {
140 GObjectClass parent_class;
143 BluetoothTelephonyMethod *bluetooth_telephony_method_new(void);
144 GType bluetooth_telephony_method_get_type(void);
146 G_DEFINE_TYPE(BluetoothTelephonyMethod, bluetooth_telephony_method, G_TYPE_OBJECT)
149 static DBusHandlerResult __bt_telephony_adapter_filter(DBusConnection *conn,
150 DBusMessage *msg, void *data);
152 static int __bt_telephony_get_object_path(DBusMessage *msg, char **path);
154 static char *__bt_extract_device_path(DBusMessageIter *msg_iter, char *address);
156 static char *__bt_get_default_adapter_path(DBusMessageIter *msg_iter);
158 static int __bt_telephony_get_src_addr(DBusMessage *msg);
160 static gboolean bluetooth_telephony_method_send_dtmf(
161 BluetoothTelephonyMethod *object,
162 gchar *dtmf, DBusGMethodInvocation *context);
164 static gboolean bluetooth_telephony_method_vendor_cmd(
165 BluetoothTelephonyMethod *object,
166 gchar *at_cmd, DBusGMethodInvocation *context);
167 #include "bt-telephony-glue.h"
169 static GObject *object;
170 static bt_telephony_info_t telephony_info;
171 static telephony_dbus_info_t telephony_dbus_info;
172 static gboolean is_active = FALSE;
174 /*Function Declaration*/
175 static int __bt_telephony_get_error(const char *error_message);
176 static void __bt_telephony_event_cb(int event, int result, void *param_data);
177 static GQuark __bluetooth_telephony_error_quark(void);
178 static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path,
179 const char *interface, const char *method, DBusError *err, int type, ...);
180 static int __bluetooth_telephony_send_call_status(
181 bt_telephony_call_status_t call_status,
182 unsigned int call_id, const char *ph_number);
183 static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
184 const char *err_msg);
186 static DBusHandlerResult __bluetooth_telephony_event_filter(
187 DBusConnection *conn,
188 DBusMessage *msg, void *data);
190 static int __bluetooth_telephony_proxy_init(void);
191 static void __bluetooth_telephony_proxy_deinit(void);
192 static int __bluetooth_telephony_register(void);
193 static int __bluetooth_telephony_unregister(void);
194 static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
196 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class);
197 static int __bluetooth_telephony_get_connected_device(void);
198 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void);
200 /*Function Definition*/
201 static int __bt_telephony_get_error(const char *error_message)
203 if (error_message == NULL) {
204 BT_ERR("Error message NULL");
205 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
208 BT_ERR("Error message = %s", error_message);
209 if (g_strcmp0(error_message, "NotAvailable") == 0)
210 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
211 else if (g_strcmp0(error_message, "NotConnected") == 0)
212 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
213 else if (g_strcmp0(error_message, "InProgress") == 0)
214 return BLUETOOTH_TELEPHONY_ERROR_BUSY;
215 else if (g_strcmp0(error_message, "InvalidArguments") == 0)
216 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
217 else if (g_strcmp0(error_message, "AlreadyExists") == 0)
218 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST;
219 else if (g_strcmp0(error_message, "Already Connected") == 0)
220 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
221 else if (g_strcmp0(error_message, "No memory") == 0)
222 return BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY;
223 else if (g_strcmp0(error_message, "I/O error") == 0)
224 return BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR;
225 else if (g_strcmp0(error_message, "Operation currently not available") == 0)
226 return BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE;
227 else if (g_strrstr(error_message, BT_ACCESS_DENIED_MSG))
228 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
230 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
233 static int __bt_telephony_check_privilege(void)
238 DBusConnection *conn;
241 conn = _bt_get_system_conn();
242 retv_if(conn == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
244 msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
245 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
248 BT_ERR("Unable to allocate new D-Bus message \n");
249 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
252 dbus_error_init(&err);
254 reply = dbus_connection_send_with_reply_and_block(conn,
257 dbus_message_unref(msg);
260 BT_ERR("Error returned in method call");
261 if (dbus_error_is_set(&err)) {
262 ret = __bt_telephony_get_error(err.message);
263 BT_ERR("Error here %d\n", ret);
264 dbus_error_free(&err);
267 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
270 dbus_message_unref(reply);
272 return BLUETOOTH_TELEPHONY_ERROR_NONE;
275 static void __bt_telephony_event_cb(int event, int result, void *param_data)
277 telephony_event_param_t bt_event = { 0, };
279 bt_event.event = event;
280 bt_event.result = result;
281 bt_event.param_data = param_data;
283 ret_if(telephony_info.cb == NULL);
284 telephony_info.cb(bt_event.event, &bt_event, telephony_info.user_data);
288 static GQuark __bluetooth_telephony_error_quark(void)
290 static GQuark quark = 0;
292 quark = g_quark_from_static_string("telephony");
297 static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path,
298 const char *interface, const char *method, DBusError *err, int type, ...)
303 #ifdef TIZEN_WEARABLE
311 msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
312 path, interface, method);
314 BT_ERR("Unable to allocate new D-Bus %s message \n", method);
318 va_start(args, type);
320 if (!dbus_message_append_args_valist(msg, type, args)) {
321 dbus_message_unref(msg);
328 dbus_error_init(err);
330 reply = dbus_connection_send_with_reply_and_block(
331 dbus_g_connection_get_connection(telephony_dbus_info.conn),
333 dbus_message_unref(msg);
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)
345 char *path = g_strdup(telephony_info.call_path);
351 if (NULL == ph_number)
352 phone_number = g_strdup("");
354 phone_number = g_strdup(ph_number);
356 reply = __bluetooth_telephony_dbus_method_send(
357 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
358 "ChangeCallStatus", &err, DBUS_TYPE_STRING, &path,
359 DBUS_TYPE_STRING, &phone_number,
360 DBUS_TYPE_INT32, &call_status,
361 DBUS_TYPE_INT32, &call_id, DBUS_TYPE_INVALID);
364 g_free(phone_number);
367 BT_ERR("Error returned in method call\n");
368 if (dbus_error_is_set(&err)) {
369 ret = __bt_telephony_get_error(err.message);
370 dbus_error_free(&err);
373 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
376 dbus_message_unref(reply);
378 return BLUETOOTH_TELEPHONY_ERROR_NONE;
381 static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
384 return g_error_new(BLUETOOTH_TELEPHONY_ERROR, error, err_msg, NULL);
387 static void bluetooth_telephony_method_init(BluetoothTelephonyMethod *object)
390 BT_DBG("agent %p\n", object);
394 static void __bluetooth_telephony_method_finalize(
395 BluetoothTelephonyMethod *object)
398 G_OBJECT_CLASS(bluetooth_telephony_method_parent_class)->finalize((
403 static BluetoothTelephonyMethod *__bluetooth_telephony_method_new(void)
405 BluetoothTelephonyMethod *obj;
408 obj = g_object_new(BLUETOOTH_TELEPHONY_METHOD, NULL);
414 static void bluetooth_telephony_method_class_init(
415 BluetoothTelephonyMethodClass *klass)
417 GObjectClass *object_class = NULL;
420 object_class = G_OBJECT_CLASS(klass);
421 object_class->finalize = (void *)__bluetooth_telephony_method_finalize;
423 /*Registration of the Framework methods */
424 dbus_g_object_type_install_info(BLUETOOTH_TELEPHONY_METHOD,
425 &dbus_glib_bluetooth_telephony_method_object_info);
430 static void __bluetooth_telephony_answer_call(DBusMessage *msg)
432 telephony_event_callid_t call_data = { 0, };
436 if (!dbus_message_get_args(msg, NULL,
437 DBUS_TYPE_UINT32, &callid,
438 DBUS_TYPE_INVALID)) {
439 BT_ERR("Error Getting parameters");
443 BT_DBG("call_id = [%d]", callid);
444 call_data.callid = callid;
446 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL,
447 BLUETOOTH_TELEPHONY_ERROR_NONE,
452 static void __bluetooth_telephony_release_call(DBusMessage *msg)
454 telephony_event_callid_t call_data = { 0, };
458 if (!dbus_message_get_args(msg, NULL,
459 DBUS_TYPE_UINT32, &callid,
460 DBUS_TYPE_INVALID)) {
461 BT_ERR("Error Getting parameters");
465 BT_DBG("call_id = [%d]", callid);
466 call_data.callid = callid;
468 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL,
469 BLUETOOTH_TELEPHONY_ERROR_NONE,
474 static void __bluetooth_telephony_reject_call(DBusMessage *msg)
476 telephony_event_callid_t call_data = { 0, };
480 if (!dbus_message_get_args(msg, NULL,
481 DBUS_TYPE_UINT32, &callid,
482 DBUS_TYPE_INVALID)) {
483 BT_ERR("Error Getting parameters");
487 BT_DBG("call_id = [%d]", callid);
488 call_data.callid = callid;
490 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_REJECT_CALL,
491 BLUETOOTH_TELEPHONY_ERROR_NONE,
496 static void __bluetooth_telephony_threeway_call(DBusMessage *msg)
499 unsigned int chld_value;
502 if (!dbus_message_get_args(msg, NULL,
503 DBUS_TYPE_UINT32, &chld_value,
504 DBUS_TYPE_INVALID)) {
505 BT_ERR("Error Getting parameters");
509 BT_DBG("chld value = [%d]", chld_value);
511 switch (chld_value) {
513 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL;
516 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL;
519 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL;
522 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL;
525 BT_ERR("Invalid CHLD command");
529 __bt_telephony_event_cb(event,
530 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
534 static gboolean bluetooth_telephony_method_send_dtmf(
535 BluetoothTelephonyMethod *object,
536 gchar *dtmf, DBusGMethodInvocation *context)
538 telephony_event_dtmf_t call_data = { 0, };
544 BT_ERR("Number dial failed");
545 err = __bluetooth_telephony_error(
546 BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF,
548 dbus_g_method_return_error(context, err);
553 DBG_SECURE("Dtmf = %s", dtmf);
555 call_data.dtmf = g_strdup(dtmf);
557 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF,
558 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&call_data);
560 dbus_g_method_return(context);
561 g_free(call_data.dtmf);
566 static gboolean bluetooth_telephony_method_vendor_cmd(
567 BluetoothTelephonyMethod *object,
568 gchar *at_cmd, DBusGMethodInvocation *context)
574 if (at_cmd == NULL) {
575 BT_ERR("Vendor command is NULL\n");
576 err = __bluetooth_telephony_error(
577 BLUETOOTH_TELEPHONY_ERROR_APPLICATION,
578 "Invalid at vendor cmd");
579 dbus_g_method_return_error(context, err);
584 DBG_SECURE("Vendor AT cmd = %s", at_cmd);
586 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_VENDOR_AT_CMD,
587 BLUETOOTH_TELEPHONY_ERROR_NONE, at_cmd);
589 dbus_g_method_return(context);
594 static void __bluetooth_handle_nrec_status_change(DBusMessage *msg)
596 gboolean status = FALSE;
598 if (!dbus_message_get_args(msg, NULL,
599 DBUS_TYPE_BOOLEAN, &status,
600 DBUS_TYPE_INVALID)) {
601 BT_ERR("Error Getting parameters");
604 BT_INFO("NREC status = %d", status);
606 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED,
607 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&status);
611 static DBusHandlerResult __bluetooth_telephony_event_filter(
612 DBusConnection *conn,
613 DBusMessage *msg, void *data)
615 const char *path = dbus_message_get_path(msg);
616 char *dev_addr = NULL;
617 DBusMessageIter item_iter;
618 DBusMessageIter value_iter;
619 const char *property;
621 /* Check NREC status change Signal*/
622 if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
623 HFP_NREC_STATUS_CHANGE)) {
624 __bluetooth_handle_nrec_status_change(msg);
625 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
628 if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
630 __bluetooth_telephony_answer_call(msg);
631 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
634 if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
636 __bluetooth_telephony_reject_call(msg);
637 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
640 if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
642 __bluetooth_telephony_release_call(msg);
643 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
646 if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
647 HFP_THREEWAY_CALL)) {
648 __bluetooth_telephony_threeway_call(msg);
649 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
652 if (!dbus_message_has_interface(msg, BLUEZ_HEADSET_INTERFACE))
653 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
655 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
656 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
658 dbus_message_iter_init(msg, &item_iter);
659 if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
660 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
663 dbus_message_iter_get_basic(&item_iter, &property);
665 if (property == NULL)
666 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
668 BT_DBG("Property (%s)", property);
670 if (g_strcmp0(property, "State") == 0) {
672 dbus_message_iter_next(&item_iter);
673 dbus_message_iter_recurse(&item_iter, &value_iter);
674 dbus_message_iter_get_basic(&value_iter, &state);
676 BT_ERR("State is null");
677 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
679 BT_DBG("State : %s", state);
681 if (g_strcmp0(state, "connected") == 0) {
682 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
683 } else if (g_strcmp0(state, "playing") == 0) {
684 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
685 } else if (g_strcmp0(state, "disconnected") == 0) {
686 /* Headset state: playing -> disconnected */
687 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) {
688 __bt_telephony_event_cb(
689 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
690 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
693 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
696 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
699 if (g_strcmp0(property, "Connected") == 0) {
700 gboolean connected = FALSE;
701 dbus_message_iter_next(&item_iter);
702 dbus_message_iter_recurse(&item_iter, &value_iter);
703 dbus_message_iter_get_basic(&value_iter, &connected);
704 BT_DBG("Connected : %d", connected);
707 /*Get device address*/
709 dev_addr = strstr(path, "dev_");
711 if (dev_addr != NULL) {
713 g_strlcpy(telephony_info.address,
715 sizeof(telephony_info.address));
716 g_strdelimit(telephony_info.address, "_", ':');
717 BT_DBG("address is %s",
718 telephony_info.address);
720 telephony_info.headset_state =
721 BLUETOOTH_STATE_CONNECTED;
723 if (telephony_dbus_info.proxy != NULL) {
724 g_object_unref(telephony_dbus_info.proxy);
725 telephony_dbus_info.proxy = NULL;
728 telephony_dbus_info.proxy =
729 __bluetooth_telephony_get_connected_device_proxy();
731 BT_INFO("Headset Connected");
733 __bt_telephony_event_cb(
734 BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED,
735 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
737 } else { /*Device disconnected*/
738 memset(telephony_info.address, 0x00,
739 sizeof(telephony_info.address));
740 telephony_info.headset_state =
741 BLUETOOTH_STATE_DISCONNETED;
743 if (telephony_dbus_info.proxy != NULL) {
744 g_object_unref(telephony_dbus_info.proxy);
745 telephony_dbus_info.proxy = NULL;
748 BT_INFO("Headset Disconnected");
750 __bt_telephony_event_cb(
751 BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED,
752 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
754 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
757 if (g_strcmp0(property, "SpeakerGain") == 0) {
758 unsigned int spkr_gain;
760 dbus_message_iter_next(&item_iter);
761 dbus_message_iter_recurse(&item_iter, &value_iter);
762 dbus_message_iter_get_basic(&value_iter, &gain);
764 spkr_gain = (unsigned int)gain;
765 BT_DBG("spk_gain[%d]", spkr_gain);
767 __bt_telephony_event_cb(
768 BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN,
769 BLUETOOTH_TELEPHONY_ERROR_NONE,
772 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
775 if (g_strcmp0(property, "MicrophoneGain") == 0) {
776 unsigned int mic_gain;
778 dbus_message_iter_next(&item_iter);
779 dbus_message_iter_recurse(&item_iter, &value_iter);
780 dbus_message_iter_get_basic(&value_iter, &gain);
782 mic_gain = (unsigned int)gain;
783 BT_DBG("mic_gain[%d]", mic_gain);
785 __bt_telephony_event_cb(
786 BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN,
787 BLUETOOTH_TELEPHONY_ERROR_NONE,
790 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
793 if (g_strcmp0(property, "Playing") == 0) {
794 gboolean audio_sink_playing = FALSE;
795 dbus_message_iter_next(&item_iter);
796 dbus_message_iter_recurse(&item_iter, &value_iter);
797 dbus_message_iter_get_basic(&value_iter, &audio_sink_playing);
799 if (audio_sink_playing) {
800 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
801 __bt_telephony_event_cb(
802 BLUETOOTH_EVENT_TELEPHONY_AUDIO_CONNECTED,
803 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
805 telephony_info.headset_state =
806 BLUETOOTH_STATE_CONNECTED;
807 __bt_telephony_event_cb(
808 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
809 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
812 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
814 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
818 static int __bluetooth_telephony_proxy_init(void)
822 object = (GObject *)__bluetooth_telephony_method_new();
825 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
827 BT_DBG("telephony_object = %x", object);
829 dbus_g_connection_register_g_object(telephony_dbus_info.conn,
830 telephony_info.call_path, G_OBJECT(object));
833 return BLUETOOTH_TELEPHONY_ERROR_NONE;
836 static void __bluetooth_telephony_proxy_deinit(void)
840 dbus_g_connection_unregister_g_object(telephony_dbus_info.conn,
843 g_object_unref(object);
850 static int __bluetooth_telephony_register(void)
854 char *path = g_strdup(telephony_info.call_path);
859 reply = __bluetooth_telephony_dbus_method_send(
860 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
861 "RegisterApplication", &err, DBUS_TYPE_STRING, &path,
862 DBUS_TYPE_STRING, &src_addr,
867 BT_ERR("Error returned in method call");
868 if (dbus_error_is_set(&err)) {
869 ret = __bt_telephony_get_error(err.message);
870 BT_ERR("Error here %d\n", ret);
871 dbus_error_free(&err);
874 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
877 dbus_message_unref(reply);
878 BT_DBG("__bluetooth_telephony_register completed");
880 return BLUETOOTH_TELEPHONY_ERROR_NONE;
883 static int __bluetooth_telephony_unregister(void)
887 char *path = g_strdup(telephony_info.call_path);
892 reply = __bluetooth_telephony_dbus_method_send(
893 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
894 "UnregisterApplication", &err, DBUS_TYPE_STRING, &path,
899 BT_ERR("Error returned in method call");
900 if (dbus_error_is_set(&err)) {
901 ret = __bt_telephony_get_error(err.message);
902 dbus_error_free(&err);
905 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
908 dbus_message_unref(reply);
909 BT_DBG("__bluetooth_telephony_unregister completed");
911 return BLUETOOTH_TELEPHONY_ERROR_NONE;
914 static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
919 DBusMessageIter reply_iter;
920 DBusMessageIter value_iter;
922 DBusConnection *conn;
923 char *adapter_path = NULL;
927 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
929 retv_if(conn == NULL, NULL);
931 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH,
932 BT_MANAGER_INTERFACE,
933 "GetManagedObjects");
935 retv_if(msg == NULL, NULL);
936 /* Synchronous call */
937 dbus_error_init(&err);
938 reply = dbus_connection_send_with_reply_and_block(
939 conn, msg, -1, &err);
940 dbus_message_unref(msg);
943 BT_ERR("Can't get managed objects");
945 if (dbus_error_is_set(&err)) {
946 BT_ERR("%s", err.message);
947 dbus_error_free(&err);
949 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
952 if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
953 BT_ERR("Fail to iterate the reply");
954 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
957 dbus_message_iter_recurse(&reply_iter, &value_iter);
959 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
960 while (dbus_message_iter_get_arg_type(&value_iter) ==
961 DBUS_TYPE_DICT_ENTRY) {
962 DBusMessageIter msg_iter;
964 dbus_message_iter_recurse(&value_iter, &msg_iter);
966 adapter_path = __bt_get_default_adapter_path(&msg_iter);
967 if (adapter_path != NULL) {
968 BT_DBG("Found the adapter path");
971 dbus_message_iter_next(&value_iter);
974 if (adapter_path == NULL) {
975 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
978 if (strlen(adapter_path) >= BT_ADAPTER_PATH_LEN) {
979 BT_ERR("Path too long.\n");
980 g_free(adapter_path);
981 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
984 BT_DBG("object path = %s", adapter_path);
985 g_strlcpy(path, adapter_path, BT_ADAPTER_PATH_LEN);
986 g_free(adapter_path);
988 return BLUETOOTH_TELEPHONY_ERROR_NONE;
991 #ifndef TIZEN_WEARABLE
992 static void __bluetooth_telephony_init_headset_state(void)
997 gboolean status = FALSE;
1001 if (telephony_dbus_info.conn == NULL) {
1002 BT_ERR("Bluetooth telephony not initilized");
1005 reply = __bluetooth_telephony_dbus_method_send(
1006 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1007 "IsConnected", &err, DBUS_TYPE_INVALID);
1010 BT_ERR("Error returned in method call\n");
1011 if (dbus_error_is_set(&err)) {
1012 __bt_telephony_get_error(err.message);
1013 dbus_error_free(&err);
1018 if (!dbus_message_get_args(reply, &err,
1019 DBUS_TYPE_BOOLEAN, &status,
1020 DBUS_TYPE_INVALID)) {
1021 BT_ERR("Error to get features");
1022 if (dbus_error_is_set(&err)) {
1023 BT_ERR("error message: %s", err.message);
1024 dbus_error_free(&err);
1026 dbus_message_unref(reply);
1030 BT_INFO("Headset Connected Status = [%d]", status);
1032 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
1036 if (bluetooth_telephony_is_sco_connected())
1037 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
1043 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
1045 gboolean flag = FALSE;
1048 switch ((device_class & 0x1f00) >> 8) {
1050 switch ((device_class & 0xfc) >> 2) {
1068 /* Tizen Wearable device */
1070 switch ((device_class & 0xfc) >> 2) {
1071 case 0x01: /* Wrist Watch */
1079 BT_DBG("[%d]", flag);
1084 static gboolean __bluetooth_telephony_is_headset_by_uuid(GValue *value)
1089 unsigned int service = 0;
1093 retv_if(value == NULL, FALSE);
1095 uuids = g_value_get_boxed(value);
1096 retv_if(uuids == NULL, FALSE);
1098 for (i = 0; uuids[i] != NULL; i++) {
1099 parts = g_strsplit(uuids[i], "-", -1);
1101 if (parts == NULL || parts[0] == NULL) {
1106 service = g_ascii_strtoull(parts[0], NULL, 16);
1109 if (service == BLUETOOTH_HS_PROFILE_UUID ||
1110 service == BLUETOOTH_HF_PROFILE_UUID)
1119 static int __bluetooth_telephony_get_connected_device(void)
1123 DBusMessageIter reply_iter;
1124 DBusMessageIter value_iter;
1126 DBusConnection *conn;
1127 DBusGProxy *headset_agent_proxy = NULL;
1129 GError *error = NULL;
1130 uint32_t device_class;
1131 gboolean playing = FALSE;
1132 gboolean connected = FALSE;
1133 GHashTable *list_hash = NULL;
1134 GValue *value = {0};
1135 char *object_path = NULL;
1136 DBusGProxy *proxy = NULL;
1137 const gchar *address;
1140 conn = _bt_get_system_conn();
1141 retv_if(conn == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
1143 msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME, "/",
1144 BLUEZ_MANAGER_INTERFACE,
1145 "GetManagedObjects");
1147 retv_if(msg == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
1149 /* Synchronous call */
1150 dbus_error_init(&err);
1151 reply = dbus_connection_send_with_reply_and_block(
1154 dbus_message_unref(msg);
1157 BT_ERR("Can't get managed objects");
1159 if (dbus_error_is_set(&err)) {
1160 BT_ERR("%s", err.message);
1161 dbus_error_free(&err);
1163 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1166 if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
1167 BT_ERR("Fail to iterate the reply");
1168 dbus_message_unref(reply);
1169 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1172 dbus_message_iter_recurse(&reply_iter, &value_iter);
1174 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
1175 while (dbus_message_iter_get_arg_type(&value_iter) ==
1176 DBUS_TYPE_DICT_ENTRY) {
1177 DBusMessageIter msg_iter;
1179 dbus_message_iter_recurse(&value_iter, &msg_iter);
1181 /* Parse the signature: oa{sa{sv}}} */
1182 retv_if(dbus_message_iter_get_arg_type(&msg_iter) !=
1183 DBUS_TYPE_OBJECT_PATH,
1184 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
1186 dbus_message_iter_get_basic(&msg_iter, &object_path);
1189 proxy = dbus_g_proxy_new_for_name(
1190 telephony_dbus_info.conn,
1193 BLUEZ_PROPERTIES_INTERFACE);
1197 dbus_g_proxy_call(proxy, "GetAll", &error,
1199 BLUEZ_DEVICE_INTERFACE,
1201 dbus_g_type_get_map("GHashTable",
1206 if (list_hash == NULL)
1210 BT_ERR("error in GetBasicProperties [%s]\n", error->message);
1211 g_error_free(error);
1215 value = g_hash_table_lookup(list_hash, "Class");
1216 device_class = value ? g_value_get_uint(value) : 0;
1218 if (device_class == 0) {
1219 BT_DBG("COD is NULL (maybe paired by nfc)... Checking UUIDs");
1220 value = g_hash_table_lookup(list_hash, "UUIDs");
1221 if (!__bluetooth_telephony_is_headset_by_uuid(value)) {
1222 BT_DBG("UUID checking completed. None HF device");
1223 g_object_unref(proxy);
1225 g_hash_table_destroy(list_hash);
1226 dbus_message_iter_next(&value_iter);
1229 BT_DBG("UUID checking completed. HF device");
1231 if (!__bluetooth_telephony_is_headset(device_class)) {
1232 g_object_unref(proxy);
1234 g_hash_table_destroy(list_hash);
1235 dbus_message_iter_next(&value_iter);
1240 /* this is headset; Check for Connection */
1241 headset_agent_proxy = dbus_g_proxy_new_for_name(
1242 telephony_dbus_info.conn,
1243 HFP_AGENT_SERVICE, object_path,
1244 HFP_AGENT_INTERFACE);
1246 if (headset_agent_proxy == NULL) {
1247 g_hash_table_destroy(list_hash);
1251 dbus_g_proxy_call(headset_agent_proxy, "IsConnected",
1252 &error, G_TYPE_INVALID,
1253 G_TYPE_BOOLEAN, &connected,
1256 if (error == NULL) {
1258 value = g_hash_table_lookup(list_hash,
1260 address = value ? g_value_get_string(
1263 g_strlcpy(telephony_info.address,
1265 sizeof(telephony_info.address));
1266 dbus_g_proxy_call(headset_agent_proxy,
1274 telephony_info.headset_state =
1275 BLUETOOTH_STATE_PLAYING;
1277 telephony_info.headset_state =
1278 BLUETOOTH_STATE_CONNECTED;
1280 g_hash_table_destroy(list_hash);
1284 g_error_free(error);
1287 g_hash_table_destroy(list_hash);
1288 g_object_unref(proxy);
1290 } /* end of if(object_path) */
1292 dbus_message_iter_next(&value_iter);
1293 } /* end of while */
1297 g_object_unref(proxy);
1299 dbus_message_unref(reply);
1302 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1305 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1307 DBusGProxy *proxy = NULL;
1308 char *object_path = NULL;
1312 if (strlen(telephony_info.address) == 0)
1313 __bluetooth_telephony_get_connected_device();
1315 if (strlen(telephony_info.address) == 0)
1318 if (telephony_info.obj_path) {
1319 g_free(telephony_info.obj_path);
1320 telephony_info.obj_path = NULL;
1323 object_path = _bt_get_device_object_path(telephony_info.address);
1324 g_strlcpy(telephony_info.obj_path, object_path, BT_ADAPTER_PATH_LEN);
1326 proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
1327 HFP_AGENT_SERVICE, telephony_info.obj_path,
1328 HFP_AGENT_INTERFACE);
1335 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1338 DBusError dbus_error;
1339 DBusConnection *conn;
1340 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1341 GError *error = NULL;
1342 char object_path[BT_ADAPTER_PATH_LEN] = {0};
1343 DBusConnection *dbus_conn;
1344 bluetooth_device_address_t loc_address = { {0} };
1345 char src_address[BT_ADDRESS_STRING_SIZE] = { 0 };
1351 if (is_initialized == TRUE) {
1352 BT_ERR("Bluetooth telephony already initilized");
1353 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_INITIALIZED;
1356 is_initialized = TRUE;
1358 telephony_dbus_info.conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
1359 if (!telephony_dbus_info.conn) {
1360 if (NULL != error) {
1361 BT_ERR("dbus_g_bus_get() failed:[%d:%s]\n",
1362 error->code, error->message);
1363 g_error_free(error);
1365 is_initialized = FALSE;
1366 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1370 snprintf(telephony_info.call_path, sizeof(telephony_info.call_path),
1371 CSD_CALL_APP_PATH, getpid());
1372 BT_DBG("Call Path = %s", telephony_info.call_path);
1373 memset(telephony_info.address, 0x00, sizeof(telephony_info.address));
1375 if (__bluetooth_telephony_proxy_init()) {
1376 BT_ERR("__bluetooth_telephony_proxy_init failed\n");
1377 dbus_g_connection_unref(telephony_dbus_info.conn);
1378 telephony_dbus_info.conn = NULL;
1379 is_initialized = FALSE;
1380 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1383 telephony_dbus_info.manager_proxy = dbus_g_proxy_new_for_name(
1384 telephony_dbus_info.conn,
1386 "/", BLUEZ_MANAGER_INTERFACE);
1388 if (telephony_dbus_info.manager_proxy == NULL) {
1389 BT_ERR("Could not create a manager proxy\n");
1390 __bluetooth_telephony_proxy_deinit();
1391 dbus_g_connection_unref(telephony_dbus_info.conn);
1392 telephony_dbus_info.conn = NULL;
1393 is_initialized = FALSE;
1394 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1397 telephony_dbus_info.dbus_proxy = dbus_g_proxy_new_for_name(
1398 telephony_dbus_info.conn, DBUS_SERVICE_DBUS,
1399 DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
1401 if (NULL == telephony_dbus_info.dbus_proxy) {
1402 __bluetooth_telephony_proxy_deinit();
1403 dbus_g_connection_unref(telephony_dbus_info.conn);
1404 telephony_dbus_info.conn = NULL;
1405 g_object_unref(telephony_dbus_info.manager_proxy);
1406 telephony_dbus_info.manager_proxy = NULL;
1407 is_initialized = FALSE;
1408 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1411 dbus_conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1413 /*Add Signal callback for BT enabled*/
1414 if (!dbus_connection_add_filter(dbus_conn,
1415 __bt_telephony_adapter_filter,
1417 BT_ERR("Fail to add filter");
1418 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1421 dbus_error_init(&dbus_error);
1422 dbus_bus_add_match(dbus_conn,
1423 "type='signal',interface='org.freedesktop.DBus.ObjectManager'"
1424 ",member='InterfacesAdded'",
1426 if (dbus_error_is_set(&dbus_error)) {
1427 BT_ERR("Fail to add match: %s\n", dbus_error.message);
1428 dbus_error_free(&dbus_error);
1432 /*Callback and user applicaton data*/
1433 telephony_info.cb = cb;
1434 telephony_info.user_data = user_data;
1435 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1437 dbus_error_init(&dbus_error);
1438 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1439 dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
1441 dbus_bus_add_match(conn,
1442 "type='signal',interface='"BLUEZ_HEADSET_INTERFACE
1443 "',member='PropertyChanged'", &dbus_error);
1444 if (dbus_error_is_set(&dbus_error)) {
1445 BT_ERR("Fail to add dbus filter signal\n");
1446 dbus_error_free(&dbus_error);
1450 dbus_error_init(&dbus_error);
1451 dbus_bus_add_match(conn,
1452 "type='signal',interface='"HFP_AGENT_SERVICE
1453 "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error);
1454 if (dbus_error_is_set(&dbus_error)) {
1455 BT_ERR("Fail to add dbus filter signal\n");
1456 dbus_error_free(&dbus_error);
1460 dbus_error_init(&dbus_error);
1461 dbus_bus_add_match(conn,
1462 "type='signal',interface='"HFP_AGENT_SERVICE
1463 "',member='"HFP_ANSWER_CALL"'" , &dbus_error);
1464 if (dbus_error_is_set(&dbus_error)) {
1465 BT_ERR("Fail to add dbus filter signal\n");
1466 dbus_error_free(&dbus_error);
1470 /*Check for BT status*/
1471 ret = __bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
1473 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1474 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1476 dbus_error_init(&dbus_error);
1477 dbus_bus_add_match(conn,
1478 "type='signal',interface='"HFP_AGENT_SERVICE
1479 "',member='"HFP_REJECT_CALL"'" , &dbus_error);
1480 if (dbus_error_is_set(&dbus_error)) {
1481 BT_ERR("Fail to add dbus filter signal\n");
1482 dbus_error_free(&dbus_error);
1486 dbus_error_init(&dbus_error);
1487 dbus_bus_add_match(conn,
1488 "type='signal',interface='"HFP_AGENT_SERVICE
1489 "',member='"HFP_RELEASE_CALL"'" , &dbus_error);
1490 if (dbus_error_is_set(&dbus_error)) {
1491 BT_ERR("Fail to add dbus filter signal\n");
1492 dbus_error_free(&dbus_error);
1496 dbus_error_init(&dbus_error);
1497 dbus_bus_add_match(conn,
1498 "type='signal',interface='"HFP_AGENT_SERVICE
1499 "',member='"HFP_THREEWAY_CALL"'" , &dbus_error);
1500 if (dbus_error_is_set(&dbus_error)) {
1501 BT_ERR("Fail to add dbus filter signal\n");
1502 dbus_error_free(&dbus_error);
1506 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED)
1507 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1509 /*Bluetooth is active, therefore set the flag */
1512 ret = bluetooth_get_local_address(&loc_address);
1513 if (ret != BLUETOOTH_ERROR_NONE) {
1514 BT_ERR("Fail to get local address\n");
1515 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1518 _bt_convert_addr_type_to_string(src_address, loc_address.addr);
1519 src_addr = g_strdup(src_address);
1521 ret = __bluetooth_telephony_register();
1522 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1523 BT_ERR("__bluetooth_telephony_register failed\n");
1527 #ifndef TIZEN_WEARABLE
1528 __bluetooth_telephony_init_headset_state();
1534 bluetooth_telephony_deinit();
1538 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1540 DBusConnection *conn;
1544 BT_TELEPHONY_CHECK_INITIALIZED();
1546 is_initialized = FALSE;
1548 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1550 dbus_error_init(&error);
1551 dbus_bus_remove_match(conn,
1552 "type='signal',interface='"BLUEZ_HEADSET_INTERFACE
1553 "',member='PropertyChanged'", &error);
1554 if (dbus_error_is_set(&error)) {
1555 BT_ERR("Fail to remove dbus filter signal\n");
1556 dbus_error_free(&error);
1557 /* Need to re initilize before use */
1558 dbus_error_init(&error);
1561 dbus_error_init(&error);
1562 dbus_bus_remove_match(conn,
1563 "type='signal',interface='"HFP_AGENT_SERVICE
1564 "',member='"HFP_NREC_STATUS_CHANGE"'", &error);
1565 if (dbus_error_is_set(&error)) {
1566 BT_ERR("Fail to remove dbus filter signal\n");
1567 dbus_error_free(&error);
1570 dbus_error_init(&error);
1571 dbus_bus_remove_match(conn,
1572 "type='signal',interface='"HFP_AGENT_SERVICE
1573 "',member='"HFP_ANSWER_CALL"'", &error);
1574 if (dbus_error_is_set(&error)) {
1575 BT_ERR("Fail to remove dbus filter signal\n");
1576 dbus_error_free(&error);
1579 dbus_error_init(&error);
1580 dbus_bus_remove_match(conn,
1581 "type='signal',interface='"HFP_AGENT_SERVICE
1582 "',member='"HFP_REJECT_CALL"'", &error);
1583 if (dbus_error_is_set(&error)) {
1584 BT_ERR("Fail to remove dbus filter signal\n");
1585 dbus_error_free(&error);
1588 dbus_error_init(&error);
1589 dbus_bus_remove_match(conn,
1590 "type='signal',interface='"HFP_AGENT_SERVICE
1591 "',member='"HFP_RELEASE_CALL"'", &error);
1592 if (dbus_error_is_set(&error)) {
1593 BT_ERR("Fail to remove dbus filter signal\n");
1594 dbus_error_free(&error);
1597 dbus_error_init(&error);
1598 dbus_bus_remove_match(conn,
1599 "type='signal',interface='"HFP_AGENT_SERVICE
1600 "',member='"HFP_THREEWAY_CALL"'", &error);
1601 if (dbus_error_is_set(&error)) {
1602 BT_ERR("Fail to remove dbus filter signal\n");
1603 dbus_error_free(&error);
1606 dbus_connection_remove_filter(conn,
1607 __bluetooth_telephony_event_filter,
1610 if (bluetooth_check_adapter() != BLUETOOTH_ADAPTER_DISABLED ||
1611 bluetooth_check_adapter_le() != BLUETOOTH_ADAPTER_LE_DISABLED)
1612 __bluetooth_telephony_unregister();
1614 __bluetooth_telephony_proxy_deinit();
1616 telephony_info.cb = NULL;
1617 telephony_info.user_data = NULL;
1618 telephony_info.call_count = 0;
1619 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1621 /* Remove BT enabled signal */
1622 dbus_error_init(&error);
1623 dbus_bus_remove_match(conn,
1624 "type='signal',interface='org.freedesktop.DBus.ObjectManager'"
1625 ",member='InterfacesAdded'",
1627 if (dbus_error_is_set(&error)) {
1628 BT_ERR("Fail to remove dbus filter signal\n");
1629 dbus_error_free(&error);
1632 dbus_connection_remove_filter(dbus_g_connection_get_connection(
1633 telephony_dbus_info.conn),
1634 __bt_telephony_adapter_filter,
1639 if (telephony_dbus_info.manager_proxy != NULL) {
1640 g_object_unref(telephony_dbus_info.manager_proxy);
1641 telephony_dbus_info.manager_proxy = NULL;
1644 if (telephony_dbus_info.conn != NULL) {
1645 dbus_g_connection_unref(telephony_dbus_info.conn);
1646 telephony_dbus_info.conn = NULL;
1649 if (telephony_dbus_info.dbus_proxy != NULL) {
1650 g_object_unref(telephony_dbus_info.dbus_proxy);
1651 telephony_dbus_info.dbus_proxy = NULL;
1655 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1658 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1663 gboolean status = FALSE;
1667 retv_if(is_initialized == FALSE, FALSE);
1668 retv_if(bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED, FALSE);
1670 reply = __bluetooth_telephony_dbus_method_send(
1671 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1672 "IsPlaying", &err, DBUS_TYPE_INVALID);
1675 BT_ERR("Error returned in method call\n");
1676 if (dbus_error_is_set(&err)) {
1677 __bt_telephony_get_error(err.message);
1678 dbus_error_free(&err);
1683 if (!dbus_message_get_args(reply, &err,
1684 DBUS_TYPE_BOOLEAN, &status,
1685 DBUS_TYPE_INVALID)) {
1686 BT_ERR("Error to get features");
1687 if (dbus_error_is_set(&err)) {
1688 BT_ERR("error message: %s", err.message);
1689 dbus_error_free(&err);
1691 dbus_message_unref(reply);
1695 #ifdef TIZEN_WEARABLE
1696 if (status == TRUE && telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1697 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
1700 BT_INFO("SCO Connected Status = [%d]", status);
1704 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1708 DBusMessageIter reply_iter;
1709 DBusMessageIter reply_iter_entry;
1710 const char *property;
1714 BT_TELEPHONY_CHECK_INITIALIZED();
1715 BT_TELEPHONY_CHECK_ENABLED();
1718 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1720 if (telephony_info.headset_state == BLUETOOTH_STATE_DISCONNETED)
1721 return BLUETOOTH_TELEPHONY_ERROR_AUDIO_NOT_CONNECTED;
1723 reply = __bluetooth_telephony_dbus_method_send(
1724 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1725 "GetProperties", &err, DBUS_TYPE_INVALID);
1728 BT_ERR("Error returned in method call\n");
1729 if (dbus_error_is_set(&err)) {
1730 BT_DBG("Error message = %s", err.message);
1731 dbus_error_free(&err);
1733 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1736 dbus_message_iter_init(reply, &reply_iter);
1738 if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
1739 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY");
1740 dbus_message_unref(reply);
1741 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1744 dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
1747 while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
1748 DBUS_TYPE_DICT_ENTRY) {
1750 DBusMessageIter dict_entry, dict_entry_val;
1751 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
1752 dbus_message_iter_get_basic(&dict_entry, &property);
1753 BT_DBG("String received = %s", property);
1755 if (g_strcmp0("nrec", property) == 0) {
1756 dbus_message_iter_next(&dict_entry);
1757 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1758 if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
1762 dbus_message_iter_get_basic(&dict_entry_val, status);
1763 BT_DBG("NREC status = [%d]", *status);
1765 dbus_message_iter_next(&reply_iter_entry);
1767 dbus_message_unref(reply);
1769 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1772 BT_EXPORT_API int bluetooth_telephony_is_wbs_mode(gboolean *status)
1776 DBusMessageIter reply_iter;
1777 DBusMessageIter reply_iter_entry;
1779 const char *property;
1783 BT_TELEPHONY_CHECK_INITIALIZED();
1784 BT_TELEPHONY_CHECK_ENABLED();
1787 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1791 reply = __bluetooth_telephony_dbus_method_send(
1792 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1793 "GetProperties", &err, DBUS_TYPE_INVALID);
1796 BT_ERR("Error returned in method call");
1797 if (dbus_error_is_set(&err)) {
1798 BT_ERR("Error message = %s", err.message);
1799 dbus_error_free(&err);
1801 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1804 dbus_message_iter_init(reply, &reply_iter);
1806 if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
1807 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY");
1808 dbus_message_unref(reply);
1809 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1812 dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
1815 while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
1816 DBUS_TYPE_DICT_ENTRY) {
1818 DBusMessageIter dict_entry, dict_entry_val;
1819 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
1820 dbus_message_iter_get_basic(&dict_entry, &property);
1821 BT_DBG("String received = %s", property);
1823 if (g_strcmp0("codec", property) == 0) {
1824 dbus_message_iter_next(&dict_entry);
1825 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1826 if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
1830 dbus_message_iter_get_basic(&dict_entry_val, &codec);
1831 BT_DBG("Codec = [%d]", codec);
1832 *status = codec == BT_MSBC_CODEC_ID ? TRUE : FALSE;
1834 dbus_message_iter_next(&reply_iter_entry);
1836 dbus_message_unref(reply);
1838 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1841 BT_EXPORT_API int bluetooth_telephony_send_vendor_cmd(const char *cmd)
1843 GError *error = NULL;
1848 BT_TELEPHONY_CHECK_INITIALIZED();
1849 BT_TELEPHONY_CHECK_ENABLED();
1851 BT_DBG("Send Vendor %s", cmd);
1853 if (telephony_dbus_info.proxy == NULL)
1854 telephony_dbus_info.proxy =
1855 __bluetooth_telephony_get_connected_device_proxy();
1857 if (telephony_dbus_info.proxy == NULL)
1858 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1860 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SendVendorAtCmd",
1863 G_TYPE_INVALID, G_TYPE_INVALID)) {
1864 if (error != NULL) {
1865 ret = __bt_telephony_get_error(error->message);
1866 g_error_free(error);
1872 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1875 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1880 gboolean state = TRUE;
1884 BT_TELEPHONY_CHECK_INITIALIZED();
1885 BT_TELEPHONY_CHECK_ENABLED();
1887 reply = __bluetooth_telephony_dbus_method_send(
1888 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1889 "SetVoiceDial", &err, DBUS_TYPE_BOOLEAN, &state,
1893 BT_ERR("Error returned in method call\n");
1894 if (dbus_error_is_set(&err)) {
1895 ret = __bt_telephony_get_error(err.message);
1896 dbus_error_free(&err);
1899 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1902 dbus_message_unref(reply);
1905 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1908 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1913 gboolean state = FALSE;
1917 BT_TELEPHONY_CHECK_INITIALIZED();
1918 BT_TELEPHONY_CHECK_ENABLED();
1920 reply = __bluetooth_telephony_dbus_method_send(
1921 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1922 "SetVoiceDial", &err, DBUS_TYPE_BOOLEAN, &state,
1926 BT_ERR("Error returned in method call\n");
1927 if (dbus_error_is_set(&err)) {
1928 ret = __bt_telephony_get_error(err.message);
1929 dbus_error_free(&err);
1932 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1935 dbus_message_unref(reply);
1938 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1941 static void __bluetooth_telephony_sco_start_cb(
1942 DBusPendingCall *call, gpointer user_data)
1946 DBusMessage *msg = user_data;
1948 reply = dbus_pending_call_steal_reply(call);
1949 dbus_error_init(&derr);
1951 if (dbus_set_error_from_message(&derr, reply)) {
1952 BT_ERR("hs_sco_cb error: %s, %s",
1953 derr.name, derr.message);
1954 dbus_error_free(&derr);
1957 dbus_pending_call_unref(call);
1959 BT_DBG("sco_start_cb : -");
1960 dbus_message_unref(msg);
1961 dbus_message_unref(reply);
1964 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1966 DBusConnection *conn;
1972 BT_TELEPHONY_CHECK_INITIALIZED();
1973 BT_TELEPHONY_CHECK_ENABLED();
1975 /* Because this API is async call, so can't use dbus SMACK */
1976 if (__bt_telephony_check_privilege() ==
1977 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1978 BT_ERR("Don't have a privilege to use this API");
1979 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1982 conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
1984 BT_DBG("No System Bus found\n");
1985 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1988 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1989 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1991 msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
1992 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1995 BT_ERR("dbus method call failed");
1996 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1999 if (dbus_connection_send_with_reply(conn, msg, &c, -1) == FALSE) {
2000 BT_DBG("HFP_AGENT: send with reply failed");
2001 dbus_message_unref(msg);
2002 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2004 dbus_pending_call_set_notify(c, __bluetooth_telephony_sco_start_cb,
2008 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2011 static void __bluetooth_telephony_sco_close_cb(DBusPendingCall *call, gpointer user_data)
2015 DBusMessage *msg = user_data;
2017 reply = dbus_pending_call_steal_reply(call);
2018 dbus_error_init(&derr);
2020 if (dbus_set_error_from_message(&derr, reply)) {
2021 BT_ERR("sco_close_cb error: %s, %s",
2022 derr.name, derr.message);
2023 dbus_error_free(&derr);
2027 dbus_pending_call_unref(call);
2029 BT_DBG("sco_close_cb : -");
2030 dbus_message_unref(msg);
2031 dbus_message_unref(reply);
2033 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
2035 DBusConnection *conn;
2041 BT_TELEPHONY_CHECK_INITIALIZED();
2042 BT_TELEPHONY_CHECK_ENABLED();
2044 /* Because this API is async call, so can't use dbus SMACK */
2045 if (__bt_telephony_check_privilege() ==
2046 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
2047 BT_ERR("Don't have a privilege to use this API");
2048 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
2051 conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
2053 BT_DBG("No System Bus found\n");
2054 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2057 if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
2058 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
2060 msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
2061 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2064 BT_ERR("dbus method call failed");
2065 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2068 if (dbus_connection_send_with_reply(conn, msg, &c, -1) == FALSE) {
2069 BT_DBG("HFP_AGENT: send with reply failed");
2070 dbus_message_unref(msg);
2071 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2073 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
2075 dbus_pending_call_set_notify(c, __bluetooth_telephony_sco_close_cb,
2079 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2082 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
2086 BT_TELEPHONY_CHECK_INITIALIZED();
2087 BT_TELEPHONY_CHECK_ENABLED();
2090 BT_DBG("call_id = [%d]", call_id);
2092 /*Make sure SCO is already connected */
2093 ret = __bluetooth_telephony_send_call_status(
2094 CSD_CALL_STATUS_MO_ALERTING, call_id, NULL);
2095 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2096 BT_ERR("send call status Failed = [%d]", ret);
2097 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2100 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2103 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
2104 unsigned int bt_audio)
2109 BT_DBG("call_id = [%d]", call_id);
2111 BT_TELEPHONY_CHECK_INITIALIZED();
2112 BT_TELEPHONY_CHECK_ENABLED();
2114 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
2116 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2117 BT_ERR("send call status Failed = [%d]", ret);
2122 if (!bluetooth_telephony_is_sco_connected()) {
2123 ret = bluetooth_telephony_audio_open();
2125 BT_ERR("Audio connection call Failed = %d", ret);
2126 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2135 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
2140 BT_DBG("call_id = [%d]", call_id);
2142 BT_TELEPHONY_CHECK_INITIALIZED();
2143 BT_TELEPHONY_CHECK_ENABLED();
2145 if (telephony_info.call_count > 0)
2146 telephony_info.call_count = telephony_info.call_count - 1;
2148 if (telephony_info.call_count == 0) {
2149 if (bluetooth_telephony_is_sco_connected()) {
2150 ret = bluetooth_telephony_audio_close();
2151 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2152 BT_ERR(" Failed = [%d]", ret);
2156 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
2158 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2159 BT_ERR("send call status Failed = [%d]", ret);
2167 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
2172 BT_DBG("call_id = [%d]", call_id);
2174 BT_TELEPHONY_CHECK_INITIALIZED();
2175 BT_TELEPHONY_CHECK_ENABLED();
2177 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
2179 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2180 BT_ERR("send call status Failed = [%d]", ret);
2186 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
2191 BT_DBG("call_id = [%d]", call_id);
2193 BT_TELEPHONY_CHECK_INITIALIZED();
2194 BT_TELEPHONY_CHECK_ENABLED();
2196 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
2198 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2199 BT_ERR("send call status Failed = [%d]", ret);
2205 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
2206 unsigned int call_count)
2210 GList *list = call_list;
2211 bt_telephony_call_status_info_t *call_status;
2215 BT_TELEPHONY_CHECK_INITIALIZED();
2216 BT_TELEPHONY_CHECK_ENABLED();
2219 BT_ERR("call_list is invalid");
2220 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2223 /* Because this API is async call, so can't use dbus SMACK */
2224 if (__bt_telephony_check_privilege() ==
2225 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
2226 BT_ERR("Don't have a privilege to use this API");
2227 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
2230 BT_DBG(" call_count = [%d]", call_count);
2232 for (i = 0; i < call_count; i++) {
2233 call_status = g_list_nth_data(list, i);
2235 if (NULL == call_status)
2238 BT_DBG(" %d : Call id [%d] status[%d]", i,
2239 call_status->call_id,
2240 call_status->call_status);
2242 if (NULL != call_status->phone_number)
2243 DBG_SECURE(" call number [%s]", call_status->phone_number);
2245 switch (call_status->call_status) {
2246 case BLUETOOTH_CALL_STATE_HELD:
2247 ret = __bluetooth_telephony_send_call_status(
2248 CSD_CALL_STATUS_HOLD,
2249 call_status->call_id,
2250 call_status->phone_number);
2251 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2252 BT_ERR("Failed = %d", ret);
2257 case BLUETOOTH_CALL_STATE_CONNECTED:
2258 ret = __bluetooth_telephony_send_call_status(
2259 CSD_CALL_STATUS_ACTIVE,
2260 call_status->call_id,
2261 call_status->phone_number);
2262 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2263 BT_ERR("Failed = [%d]", ret);
2269 if ((call_status->call_status < BLUETOOTH_CALL_STATE_NONE) ||
2270 (call_status->call_status >= BLUETOOTH_CALL_STATE_ERROR)) {
2271 BT_ERR("Unknown Call state");
2272 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
2278 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2281 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
2282 unsigned int call_count)
2288 ret = bluetooth_telephony_call_swapped(call_list, call_count);
2290 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2291 BT_ERR("Failed = [%d]", ret);
2295 telephony_info.call_count = call_count;
2298 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2301 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
2302 const char *ph_number, unsigned int call_id,
2303 unsigned int bt_audio)
2307 const char *path = telephony_info.call_path;
2312 BT_TELEPHONY_CHECK_INITIALIZED();
2313 BT_TELEPHONY_CHECK_ENABLED();
2315 if (NULL == ph_number)
2316 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2318 reply = __bluetooth_telephony_dbus_method_send(
2319 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2320 "OutgoingCall", &err, DBUS_TYPE_STRING, &path,
2321 DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
2322 &call_id, DBUS_TYPE_INVALID);
2325 BT_ERR("Error returned in method call\n");
2326 if (dbus_error_is_set(&err)) {
2327 ret = __bt_telephony_get_error(err.message);
2328 dbus_error_free(&err);
2331 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2334 dbus_message_unref(reply);
2336 telephony_info.call_count++;
2337 BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
2340 if (!bluetooth_telephony_is_sco_connected()) {
2341 ret = bluetooth_telephony_audio_open();
2343 BT_ERR(" Audio connection Failed = %d", ret);
2344 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2350 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2353 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
2354 const char *ph_number, unsigned int call_id)
2358 const char *path = telephony_info.call_path;
2363 BT_TELEPHONY_CHECK_INITIALIZED();
2364 BT_TELEPHONY_CHECK_ENABLED();
2366 if (NULL == ph_number)
2367 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2369 reply = __bluetooth_telephony_dbus_method_send(
2370 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2371 "IncomingCall", &err, DBUS_TYPE_STRING, &path,
2372 DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
2373 &call_id, DBUS_TYPE_INVALID);
2376 BT_ERR("Error returned in method call\n");
2377 if (dbus_error_is_set(&err)) {
2378 ret = __bt_telephony_get_error(err.message);
2379 dbus_error_free(&err);
2382 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2385 dbus_message_unref(reply);
2387 telephony_info.call_count++;
2388 BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
2390 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2393 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(
2394 unsigned short speaker_gain)
2402 BT_TELEPHONY_CHECK_INITIALIZED();
2403 BT_TELEPHONY_CHECK_ENABLED();
2405 BT_DBG("set speaker_gain= [%d]", speaker_gain);
2407 reply = __bluetooth_telephony_dbus_method_send(
2408 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2409 "SetSpeakerGain", &err, DBUS_TYPE_UINT16,
2410 &speaker_gain, DBUS_TYPE_INVALID);
2413 BT_ERR("Error returned in method call\n");
2414 if (dbus_error_is_set(&err)) {
2415 ret = __bt_telephony_get_error(err.message);
2416 dbus_error_free(&err);
2419 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2422 dbus_message_unref(reply);
2425 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2428 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(
2429 unsigned int *speaker_gain)
2438 BT_TELEPHONY_CHECK_INITIALIZED();
2439 BT_TELEPHONY_CHECK_ENABLED();
2441 reply = __bluetooth_telephony_dbus_method_send(
2442 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2443 "GetSpeakerGain", &err, DBUS_TYPE_INVALID);
2446 BT_ERR("Error returned in method call\n");
2447 if (dbus_error_is_set(&err)) {
2448 ret = __bt_telephony_get_error(err.message);
2449 dbus_error_free(&err);
2452 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2455 if (!dbus_message_get_args(reply, &err,
2456 DBUS_TYPE_UINT16, &gain,
2457 DBUS_TYPE_INVALID)) {
2458 BT_ERR("Error to get features");
2459 if (dbus_error_is_set(&err)) {
2460 BT_ERR("error message: %s", err.message);
2461 dbus_error_free(&err);
2463 dbus_message_unref(reply);
2464 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2466 *speaker_gain = gain;
2467 BT_DBG("Get speaker_gain= [%d]", *speaker_gain);
2469 dbus_message_unref(reply);
2471 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2474 static DBusHandlerResult __bt_telephony_adapter_filter(DBusConnection *conn,
2475 DBusMessage *msg, void *data)
2478 char *object_path = NULL;
2479 const char *member = dbus_message_get_member(msg);
2482 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
2483 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2486 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2488 if (strcasecmp(member, "InterfacesAdded") == 0) {
2489 if (__bt_telephony_get_object_path(msg, &object_path)) {
2490 BT_ERR("Fail to get the path");
2491 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2494 if (strcasecmp(object_path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
2496 BT_DBG("Adapter added [%s]", object_path);
2497 BT_DBG("BlueZ is Activated and flag need to be reset");
2498 BT_DBG("Send enabled to application");
2500 if (__bt_telephony_get_src_addr(msg)) {
2501 BT_ERR("Fail to get the local adapter address");
2502 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2505 ret = __bluetooth_telephony_register();
2506 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2507 BT_ERR("__bluetooth_telephony_register failed");
2512 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2515 static int __bt_telephony_get_object_path(DBusMessage *msg, char **path)
2517 DBusMessageIter item_iter;
2518 dbus_message_iter_init(msg, &item_iter);
2521 if (dbus_message_iter_get_arg_type(&item_iter)
2522 != DBUS_TYPE_OBJECT_PATH) {
2523 BT_ERR("This is bad format dbus");
2524 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2527 dbus_message_iter_get_basic(&item_iter, path);
2530 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2533 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2537 static int __bt_telephony_get_src_addr(DBusMessage *msg)
2540 const char *property = NULL;
2541 char *interface_name;
2542 DBusMessageIter item_iter;
2543 DBusMessageIter value_iter;
2544 DBusMessageIter msg_iter, dict_iter;
2545 DBusMessageIter in_iter, in2_iter;
2549 dbus_message_iter_init(msg, &item_iter);
2551 /* signature of InterfacesAdded signal is oa{sa{sv}} */
2552 if (dbus_message_iter_get_arg_type(&item_iter)
2553 != DBUS_TYPE_OBJECT_PATH) {
2554 BT_ERR("This is bad format dbus");
2555 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2558 dbus_message_iter_get_basic(&item_iter, &object_path);
2559 retv_if(object_path == NULL,
2560 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2562 if (strcasecmp(object_path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
2563 /* get address from here */
2564 retv_if(dbus_message_iter_next(&item_iter) == FALSE,
2565 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2567 /* signature a{sa{sv}} */
2568 retv_if(dbus_message_iter_get_arg_type(&item_iter) !=
2570 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2571 dbus_message_iter_recurse(&item_iter, &value_iter);
2572 while (dbus_message_iter_get_arg_type(&value_iter) ==
2573 DBUS_TYPE_DICT_ENTRY) {
2574 dbus_message_iter_recurse(&value_iter, &msg_iter);
2575 if (dbus_message_iter_get_arg_type(&msg_iter)
2576 != DBUS_TYPE_STRING) {
2577 BT_ERR("This is bad format dbus");
2578 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2581 dbus_message_iter_get_basic(&msg_iter, &interface_name);
2582 retv_if(interface_name == NULL,
2583 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2585 BT_DBG("interface name is %s", interface_name);
2587 if (strcasecmp(interface_name, BLUEZ_ADAPTER_INTERFACE) == 0) {
2588 retv_if(!dbus_message_iter_next(&msg_iter),
2589 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2590 dbus_message_iter_recurse(&msg_iter, &in_iter);
2592 if (dbus_message_iter_get_arg_type(&in_iter)
2593 != DBUS_TYPE_DICT_ENTRY) {
2594 BT_ERR("This is bad format dbus");
2595 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2598 dbus_message_iter_recurse(&in_iter, &dict_iter);
2599 dbus_message_iter_get_basic(
2600 &dict_iter, &property);
2602 retv_if(property == NULL,
2603 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2604 retv_if(!dbus_message_iter_next(&dict_iter),
2605 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2607 if (strcasecmp(property, "Address") == 0) {
2608 dbus_message_iter_recurse
2609 (&dict_iter, &in2_iter);
2610 dbus_message_iter_get_basic
2611 (&in2_iter, &bd_addr);
2612 src_addr = g_strdup(bd_addr);
2616 dbus_message_iter_next(&value_iter);
2619 BT_DBG("default adapter address is src_addr = %s", src_addr);
2621 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2624 static char *__bt_extract_device_path(DBusMessageIter *msg_iter, char *address)
2626 char *object_path = NULL;
2627 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
2630 /* Parse the signature: oa{sa{sv}}} */
2631 retv_if(dbus_message_iter_get_arg_type(msg_iter) !=
2632 DBUS_TYPE_OBJECT_PATH, NULL);
2634 dbus_message_iter_get_basic(msg_iter, &object_path);
2635 retv_if(object_path == NULL, NULL);
2637 _bt_convert_device_path_to_address(object_path, device_address);
2639 if (g_strcmp0(address, device_address) == 0) {
2640 return g_strdup(object_path);
2646 static char *__bt_get_default_adapter_path(DBusMessageIter *msg_iter)
2648 char *object_path = NULL;
2649 DBusMessageIter value_iter;
2652 /* Parse the signature: oa{sa{sv}}} */
2653 retv_if(dbus_message_iter_get_arg_type(msg_iter) !=
2654 DBUS_TYPE_OBJECT_PATH, NULL);
2656 dbus_message_iter_get_basic(msg_iter, &object_path);
2658 retv_if(dbus_message_iter_next(msg_iter) == FALSE, NULL);
2659 retv_if(dbus_message_iter_get_arg_type(msg_iter) !=
2660 DBUS_TYPE_ARRAY, NULL);
2662 dbus_message_iter_recurse(msg_iter, &value_iter);
2664 while (dbus_message_iter_get_arg_type(&value_iter) ==
2665 DBUS_TYPE_DICT_ENTRY) {
2666 char *interface_name = NULL;
2667 DBusMessageIter interface_iter;
2669 dbus_message_iter_recurse(&value_iter, &interface_iter);
2671 retv_if(dbus_message_iter_get_arg_type(&interface_iter) !=
2672 DBUS_TYPE_STRING, NULL);
2674 dbus_message_iter_get_basic(&interface_iter, &interface_name);
2676 if (g_strcmp0(interface_name, "org.bluez.Adapter1") == 0) {
2677 return g_strdup(object_path);
2679 dbus_message_iter_next(&value_iter);
2681 BT_DBG("Adapter Not Found");