4 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
23 #include <dbus/dbus.h>
24 #include <dbus/dbus-glib-bindings.h>
27 #include <vconf-keys.h>
29 #include "bt-common.h"
30 #include "bluetooth-telephony-api.h"
34 DBusGConnection *conn;
36 DBusGProxy *dbus_proxy;
37 DBusGProxy *manager_proxy;
38 } telephony_dbus_info_t;
41 bt_telephony_func_ptr cb;
42 unsigned int call_count;
44 char address[BT_ADDRESS_STR_LEN];
45 char call_path[BT_AUDIO_CALL_PATH_LEN];
46 bluetooth_headset_state_t headset_state;
48 } bt_telephony_info_t;
50 #define BLUETOOTH_TELEPHONY_ERROR (__bluetooth_telephony_error_quark())
52 #define BLUEZ_SERVICE_NAME "org.bluez"
53 #define BLUEZ_HEADSET_INTERFACE "org.bluez.Headset"
54 #define BLUEZ_MANAGER_INTERFACE "org.bluez.Manager"
55 #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter"
56 #define BLUEZ_DEVICE_INTERFACE "org.bluez.Device"
58 #define HFP_AGENT_SERVICE "org.bluez.hfp_agent"
59 #define HFP_AGENT_PATH "/org/bluez/hfp_agent"
60 #define HFP_AGENT_INTERFACE "Org.Hfp.App.Interface"
62 #define CSD_CALL_APP_PATH "/org/tizen/csd/%d"
63 #define HFP_NREC_STATUS_CHANGE "NrecStatusChanged"
65 #define BT_TELEPHONY_CHECK_ENABLED() \
67 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) \
69 BT_ERR("BT is not enabled"); \
70 return BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED; \
74 static gboolean is_initialized = FALSE;
75 #define BT_TELEPHONY_CHECK_INITIALIZED() \
77 if (is_initialized == FALSE) \
79 BT_ERR("Bluetooth telephony not initilized"); \
80 return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED; \
84 #define BLUETOOTH_TELEPHONY_METHOD (bluetooth_telephony_method_get_type())
85 #define BLUETOOTH_TELEPHONY_METHOD_GET_OBJECT(obj) \
86 (G_TYPE_CHECK_INSTANCE_CAST((obj), \
87 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethod))
89 #define BLUETOOTH_TELEPHONY_METHOD_IS_OBJECT(obj) \
90 (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
91 BLUETOOTH_TELEPHONY_METHOD))
93 #define BLUETOOTH_TELEPHONY_METHOD_CLASS(class) \
94 (G_TYPE_CHECK_CLASS_CAST((class), \
95 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))
97 #define BLUETOOTH_TELEPHONY_METHOD_GET_AGENT_CLASS(obj) \
98 (G_TYPE_INSTANCE_GET_CLASS((obj), \
99 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))
101 #define BLUETOOTH_TELEPHONY_METHOD_IS_AGENT_CLASS(class) \
102 (G_TYPE_CHECK_CLASS_TYPE((class), BLUETOOTH_TELEPHONY_METHOD))
104 #define BLUETOOTH_TELEPHONY_METHOD_AGENT_GET_PRIVATE(obj) \
105 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
106 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodPrivate))
108 typedef struct _BluetoothTelephonyMethod BluetoothTelephonyMethod;
109 typedef struct _BluetoothTelephonyMethodClass BluetoothTelephonyMethodClass;
111 struct _BluetoothTelephonyMethod {
115 struct _BluetoothTelephonyMethodClass {
116 GObjectClass parent_class;
119 BluetoothTelephonyMethod *bluetooth_telephony_method_new(void);
120 GType bluetooth_telephony_method_get_type(void);
122 G_DEFINE_TYPE(BluetoothTelephonyMethod, bluetooth_telephony_method, G_TYPE_OBJECT)
125 static gboolean bluetooth_telephony_method_answer(BluetoothTelephonyMethod *object,
127 DBusGMethodInvocation *context);
129 static gboolean bluetooth_telephony_method_release(
130 BluetoothTelephonyMethod *object, guint callid,
131 DBusGMethodInvocation *context);
133 static gboolean bluetooth_telephony_method_reject(BluetoothTelephonyMethod *object,
134 guint callid, DBusGMethodInvocation *context);
136 static gboolean bluetooth_telephony_method_threeway(
137 BluetoothTelephonyMethod *object, guint value,
138 DBusGMethodInvocation *context);
140 static gboolean bluetooth_telephony_method_send_dtmf(
141 BluetoothTelephonyMethod *object,
142 gchar *dtmf, DBusGMethodInvocation *context);
144 #include "bt-telephony-glue.h"
146 static GObject *object;
147 static bt_telephony_info_t telephony_info;
148 static telephony_dbus_info_t telephony_dbus_info;
149 static gboolean is_active = FALSE;
151 /*Function Declaration*/
152 static int __bt_telephony_get_error(const char *error_message);
153 static void __bt_telephony_event_cb(int event, int result, void *param_data);
154 static GQuark __bluetooth_telephony_error_quark(void);
155 static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path,
156 const char *interface, const char *method, DBusError *err, int type, ...);
157 static int __bluetooth_telephony_send_call_status(
158 bt_telephony_call_status_t call_status,
159 unsigned int call_id);
160 static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
161 const char *err_msg);
163 static DBusHandlerResult __bluetooth_telephony_event_filter(
164 DBusConnection *conn,
165 DBusMessage *msg, void *data);
167 static void __bluetooth_telephony_adapter_added_cb(DBusGProxy *manager_proxy,
168 const char *adapter_path, gpointer user_data);
169 static int __bluetooth_telephony_proxy_init(void);
170 static void __bluetooth_telephony_proxy_deinit(void);
171 static int __bluetooth_telephony_register(void);
172 static int __bluetooth_telephony_unregister(void);
173 static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
175 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class);
176 static int __bluetooth_telephony_get_connected_device(void);
177 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void);
179 /*Function Definition*/
180 static int __bt_telephony_get_error(const char *error_message)
182 if (error_message == NULL) {
183 BT_DBG("Error message NULL\n");
184 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
187 BT_DBG("Error message = %s \n", error_message);
188 if (g_strcmp0(error_message, "NotAvailable") == 0)
189 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
190 else if (g_strcmp0(error_message, "NotConnected") == 0)
191 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
192 else if (g_strcmp0(error_message, "InProgress") == 0)
193 return BLUETOOTH_TELEPHONY_ERROR_BUSY;
194 else if (g_strcmp0(error_message, "InvalidArguments") == 0)
195 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
196 else if (g_strcmp0(error_message, "AlreadyExists") == 0)
197 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST;
198 else if (g_strcmp0(error_message, "Already Connected") == 0)
199 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
200 else if (g_strcmp0(error_message, "No memory") == 0)
201 return BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY;
202 else if (g_strcmp0(error_message, "I/O error") == 0)
203 return BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR;
204 else if (g_strcmp0(error_message, "Operation currently not available") == 0)
205 return BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE;
207 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
210 static void __bt_telephony_event_cb(int event, int result, void *param_data)
212 telephony_event_param_t bt_event = { 0, };
214 bt_event.event = event;
215 bt_event.result = result;
216 bt_event.param_data = param_data;
218 ret_if(telephony_info.cb == NULL);
219 telephony_info.cb(bt_event.event, &bt_event, telephony_info.user_data);
223 static GQuark __bluetooth_telephony_error_quark(void)
225 static GQuark quark = 0;
227 quark = g_quark_from_static_string("telephony");
232 static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path,
233 const char *interface, const char *method, DBusError *err, int type, ...)
241 msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
242 path, interface, method);
244 BT_ERR("Unable to allocate new D-Bus %s message \n", method);
248 va_start(args, type);
250 if (!dbus_message_append_args_valist(msg, type, args)) {
251 dbus_message_unref(msg);
258 dbus_error_init(err);
260 reply = dbus_connection_send_with_reply_and_block(
261 dbus_g_connection_get_connection(telephony_dbus_info.conn),
263 dbus_message_unref(msg);
269 static int __bluetooth_telephony_send_call_status(
270 bt_telephony_call_status_t call_status,
271 unsigned int call_id)
275 char *path = g_strdup(telephony_info.call_path);
280 reply = __bluetooth_telephony_dbus_method_send(
281 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
282 "ChangeCallStatus", &err, DBUS_TYPE_STRING, &path,
283 DBUS_TYPE_INT32, &call_status,
284 DBUS_TYPE_INT32, &call_id, DBUS_TYPE_INVALID);
288 BT_ERR("Error returned in method call\n");
289 if (dbus_error_is_set(&err)) {
290 ret = __bt_telephony_get_error(err.message);
291 dbus_error_free(&err);
294 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
297 dbus_message_unref(reply);
299 return BLUETOOTH_TELEPHONY_ERROR_NONE;
302 static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
305 return g_error_new(BLUETOOTH_TELEPHONY_ERROR, error, err_msg, NULL);
308 static void bluetooth_telephony_method_init(BluetoothTelephonyMethod *object)
311 BT_DBG("agent %p\n", object);
315 static void __bluetooth_telephony_method_finalize(
316 BluetoothTelephonyMethod *object)
319 G_OBJECT_CLASS(bluetooth_telephony_method_parent_class)->finalize((
324 static BluetoothTelephonyMethod *__bluetooth_telephony_method_new(void)
326 BluetoothTelephonyMethod *obj;
329 obj = g_object_new(BLUETOOTH_TELEPHONY_METHOD, NULL);
335 static void bluetooth_telephony_method_class_init(
336 BluetoothTelephonyMethodClass *klass)
338 GObjectClass *object_class = NULL;
341 object_class = G_OBJECT_CLASS(klass);
342 object_class->finalize = (void *)__bluetooth_telephony_method_finalize;
344 /*Registration of the Framework methods */
345 dbus_g_object_type_install_info(BLUETOOTH_TELEPHONY_METHOD,
346 &dbus_glib_bluetooth_telephony_method_object_info);
351 static gboolean bluetooth_telephony_method_answer(
352 BluetoothTelephonyMethod *object,
353 guint callid, DBusGMethodInvocation *context)
355 telephony_event_callid_t call_data = { 0, };
358 BT_DBG("call_id = [%d]", callid);
360 call_data.callid = callid;
362 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL,
363 BLUETOOTH_TELEPHONY_ERROR_NONE,
366 dbus_g_method_return(context);
371 static gboolean bluetooth_telephony_method_release(
372 BluetoothTelephonyMethod *object,
373 guint callid, DBusGMethodInvocation *context)
375 telephony_event_callid_t call_data = { 0, };
378 BT_DBG("call_id = [%d]\n", callid);
380 call_data.callid = callid;
382 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL,
383 BLUETOOTH_TELEPHONY_ERROR_NONE,
386 dbus_g_method_return(context);
392 static gboolean bluetooth_telephony_method_reject(
393 BluetoothTelephonyMethod *object,
394 guint callid, DBusGMethodInvocation *context)
396 telephony_event_callid_t call_data = { 0, };
399 BT_DBG("call_id = [%d]", callid);
401 call_data.callid = callid;
403 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_REJECT_CALL,
404 BLUETOOTH_TELEPHONY_ERROR_NONE,
407 dbus_g_method_return(context);
412 static gboolean bluetooth_telephony_method_threeway(
413 BluetoothTelephonyMethod *object,
414 guint value, DBusGMethodInvocation *context)
420 BT_DBG("chld value = [%d]", value);
424 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL;
427 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL;
430 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL;
433 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL;
436 BT_ERR("Invalid CHLD command");
437 err = __bluetooth_telephony_error(
438 BLUETOOTH_TELEPHONY_ERROR_INVALID_CHLD_INDEX,
439 "Invalid chld command");
440 dbus_g_method_return_error(context, err);
445 BT_DBG("event = [%d]", event);
447 __bt_telephony_event_cb(event,
448 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
449 dbus_g_method_return(context);
454 static gboolean bluetooth_telephony_method_send_dtmf(
455 BluetoothTelephonyMethod *object,
456 gchar *dtmf, DBusGMethodInvocation *context)
458 telephony_event_dtmf_t call_data = { 0, };
464 BT_DBG("Number dial failed\n");
465 err = __bluetooth_telephony_error(
466 BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF,
468 dbus_g_method_return_error(context, err);
473 BT_DBG("Dtmf = %s \n", dtmf);
475 call_data.dtmf = g_strdup(dtmf);
477 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF,
478 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&call_data);
480 dbus_g_method_return(context);
481 g_free(call_data.dtmf);
486 static void __bluetooth_handle_nrec_status_change(DBusMessage *msg)
488 gboolean status = FALSE;
490 if (!dbus_message_get_args(msg, NULL,
491 DBUS_TYPE_BOOLEAN, &status,
492 DBUS_TYPE_INVALID)) {
493 BT_DBG("Error Getting parameters\n");
496 BT_DBG("NREC status = %d\n", status);
498 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED,
499 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&status);
503 static DBusHandlerResult __bluetooth_telephony_event_filter(
504 DBusConnection *conn,
505 DBusMessage *msg, void *data)
507 const char *path = dbus_message_get_path(msg);
508 char *dev_addr = NULL;
509 DBusMessageIter item_iter;
510 DBusMessageIter value_iter;
511 const char *property;
513 /* Check NREC status change Signal*/
514 if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
515 HFP_NREC_STATUS_CHANGE)) {
516 __bluetooth_handle_nrec_status_change(msg);
517 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
520 if (!dbus_message_has_interface(msg, BLUEZ_HEADSET_INTERFACE))
521 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
523 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
524 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
526 dbus_message_iter_init(msg, &item_iter);
527 if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
528 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
531 dbus_message_iter_get_basic(&item_iter, &property);
533 if (property == NULL)
534 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
536 BT_DBG("Property (%s)\n", property);
538 if (g_strcmp0(property, "State") == 0) {
540 dbus_message_iter_next(&item_iter);
541 dbus_message_iter_recurse(&item_iter, &value_iter);
542 dbus_message_iter_get_basic(&value_iter, &state);
544 BT_ERR("State is null\n");
545 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
547 BT_DBG("State %s\n", state);
549 if (g_strcmp0(state, "connected") == 0) {
550 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
551 } else if (g_strcmp0(state, "playing") == 0) {
552 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
553 } else if (g_strcmp0(state, "disconnected") == 0) {
554 /* Headset state: playing -> disconnected */
555 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) {
556 if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, FALSE)) {
557 BT_DBG("SVCONFKEY_BT_HEADSET_SCO - Set to FALSE\n");
559 BT_DBG("vconf_set_bool - Failed\n");
562 __bt_telephony_event_cb(
563 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
564 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
567 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
570 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
573 if (g_strcmp0(property, "Connected") == 0) {
574 gboolean connected = FALSE;
575 dbus_message_iter_next(&item_iter);
576 dbus_message_iter_recurse(&item_iter, &value_iter);
577 dbus_message_iter_get_basic(&value_iter, &connected);
578 BT_DBG("Connected %d\n", connected);
581 /*Get device address*/
583 dev_addr = strstr(path, "dev_");
585 if (dev_addr != NULL) {
587 g_strlcpy(telephony_info.address,
589 sizeof(telephony_info.address));
590 g_strdelimit(telephony_info.address, "_", ':');
591 BT_DBG("address is %s",
592 telephony_info.address);
594 telephony_info.headset_state =
595 BLUETOOTH_STATE_CONNECTED;
597 if (telephony_dbus_info.proxy != NULL) {
598 g_object_unref(telephony_dbus_info.proxy);
599 telephony_dbus_info.proxy = NULL;
602 telephony_dbus_info.proxy =
603 __bluetooth_telephony_get_connected_device_proxy();
605 BT_DBG("Headset Connected");
607 __bt_telephony_event_cb(
608 BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED,
609 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
611 } else { /*Device disconnected*/
612 memset(telephony_info.address, 0x00,
613 sizeof(telephony_info.address));
614 telephony_info.headset_state =
615 BLUETOOTH_STATE_DISCONNETED;
617 if (telephony_dbus_info.proxy != NULL) {
618 g_object_unref(telephony_dbus_info.proxy);
619 telephony_dbus_info.proxy = NULL;
622 BT_DBG("Headset Disconnected");
624 __bt_telephony_event_cb(
625 BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED,
626 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
628 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
631 if (g_strcmp0(property, "SpeakerGain") == 0) {
632 unsigned int spkr_gain;
634 dbus_message_iter_next(&item_iter);
635 dbus_message_iter_recurse(&item_iter, &value_iter);
636 dbus_message_iter_get_basic(&value_iter, &gain);
638 spkr_gain = (unsigned int)gain;
639 BT_DBG("spk_gain[%d]\n", spkr_gain);
641 __bt_telephony_event_cb(
642 BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN,
643 BLUETOOTH_TELEPHONY_ERROR_NONE,
646 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
649 if (g_strcmp0(property, "MicrophoneGain") == 0) {
650 unsigned int mic_gain;
652 dbus_message_iter_next(&item_iter);
653 dbus_message_iter_recurse(&item_iter, &value_iter);
654 dbus_message_iter_get_basic(&value_iter, &gain);
656 mic_gain = (unsigned int)gain;
657 BT_DBG("mic_gain[%d]\n", mic_gain);
659 __bt_telephony_event_cb(
660 BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN,
661 BLUETOOTH_TELEPHONY_ERROR_NONE,
664 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
667 if (g_strcmp0(property, "Playing") == 0) {
668 gboolean audio_sink_playing = FALSE;
669 dbus_message_iter_next(&item_iter);
670 dbus_message_iter_recurse(&item_iter, &value_iter);
671 dbus_message_iter_get_basic(&value_iter, &audio_sink_playing);
673 if (audio_sink_playing) {
674 if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, TRUE)) {
675 BT_DBG("SVCONFKEY_BT_HEADSET_SCO -"
678 BT_DBG("vconf_set_bool - Failed\n");
680 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
681 __bt_telephony_event_cb(
682 BLUETOOTH_EVENT_TELEPHONY_AUDIO_CONNECTED,
683 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
685 if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, FALSE)) {
686 BT_DBG("SVCONFKEY_BT_HEADSET_SCO -"
689 BT_DBG("vconf_set_bool - Failed\n");
691 telephony_info.headset_state =
692 BLUETOOTH_STATE_CONNECTED;
693 __bt_telephony_event_cb(
694 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
695 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
698 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
700 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
703 static void __bluetooth_telephony_adapter_added_cb(DBusGProxy *manager_proxy,
704 const char *adapter_path, gpointer user_data)
707 DBusError dbus_error;
708 DBusConnection *conn;
710 BT_DBG("Adapter added [%s] \n", adapter_path);
712 if (strstr(adapter_path, "hci0")) {
713 BT_DBG("BlueZ is Activated and flag need to be reset");
714 BT_DBG("Send enabled to application\n");
716 ret = __bluetooth_telephony_register();
717 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
718 BT_DBG("__bluetooth_telephony_register failed\n");
722 dbus_error_init(&dbus_error);
723 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
724 dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
727 dbus_bus_add_match(conn,
728 "type='signal',interface='" BLUEZ_HEADSET_INTERFACE
729 "',member='PropertyChanged'", &dbus_error);
730 dbus_bus_add_match(conn,
731 "type='signal',interface='"HFP_AGENT_SERVICE
732 "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error);
734 if (dbus_error_is_set(&dbus_error)) {
735 BT_DBG("Fail to add dbus filter signal\n");
736 dbus_error_free(&dbus_error);
737 __bluetooth_telephony_unregister();
738 dbus_connection_remove_filter(dbus_g_connection_get_connection(
739 telephony_dbus_info.conn),
740 __bluetooth_telephony_event_filter, NULL);
745 static int __bluetooth_telephony_proxy_init(void)
749 object = (GObject *)__bluetooth_telephony_method_new();
752 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
754 BT_DBG("telephony_object = %x", object);
756 dbus_g_connection_register_g_object(telephony_dbus_info.conn,
757 telephony_info.call_path, G_OBJECT(object));
760 return BLUETOOTH_TELEPHONY_ERROR_NONE;
763 static void __bluetooth_telephony_proxy_deinit(void)
767 dbus_g_connection_unregister_g_object(telephony_dbus_info.conn,
770 g_object_unref(object);
777 static int __bluetooth_telephony_register(void)
781 char *path = g_strdup(telephony_info.call_path);
786 reply = __bluetooth_telephony_dbus_method_send(
787 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
788 "RegisterApplication", &err, DBUS_TYPE_STRING, &path,
793 BT_ERR("Error returned in method call\n");
794 if (dbus_error_is_set(&err)) {
795 ret = __bt_telephony_get_error(err.message);
796 dbus_error_free(&err);
799 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
802 dbus_message_unref(reply);
804 return BLUETOOTH_TELEPHONY_ERROR_NONE;
807 static int __bluetooth_telephony_unregister(void)
811 char *path = g_strdup(telephony_info.call_path);
816 reply = __bluetooth_telephony_dbus_method_send(
817 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
818 "UnregisterApplication", &err, DBUS_TYPE_STRING, &path,
823 BT_ERR("Error returned in method call\n");
824 if (dbus_error_is_set(&err)) {
825 ret = __bt_telephony_get_error(err.message);
826 dbus_error_free(&err);
829 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
832 dbus_message_unref(reply);
834 return BLUETOOTH_TELEPHONY_ERROR_NONE;
837 static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
841 char *adapter_path = NULL;
845 if (!dbus_g_proxy_call(telephony_dbus_info.manager_proxy,
846 "DefaultAdapter", &err, G_TYPE_INVALID,
847 DBUS_TYPE_G_OBJECT_PATH, &adapter_path,
850 BT_ERR("Getting DefaultAdapter failed: [%s]",
854 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
857 if (adapter_path == NULL) {
858 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
861 if (strlen(adapter_path) >= BT_ADAPTER_PATH_LEN) {
862 BT_ERR("Path too long.\n");
863 g_free(adapter_path);
864 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
867 BT_DBG("path = %s", adapter_path);
868 g_strlcpy(path, adapter_path, BT_ADAPTER_PATH_LEN);
869 g_free(adapter_path);
871 return BLUETOOTH_TELEPHONY_ERROR_NONE;
874 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
876 gboolean flag = FALSE;
879 switch ((device_class & 0x1f00) >> 8) {
881 switch ((device_class & 0xfc) >> 2) {
903 static int __bluetooth_telephony_get_connected_device(void)
905 DBusGProxy *list_proxy = NULL;
906 DBusGProxy *device_proxy = NULL;
907 GPtrArray *gp_array = NULL;
908 GError *error = NULL;
909 gchar *gp_path = NULL;
910 GHashTable *list_hash;
911 GHashTable *device_hash;
913 uint32_t device_class;
914 gboolean playing = FALSE;
915 gboolean connected = FALSE;
916 const gchar *address;
917 char object_path[BT_ADAPTER_PATH_LEN] = {0};
919 DBusGProxy *proxy = NULL;
923 /*Get default adapter path*/
924 if (__bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
926 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
927 /*Get List of All devices*/
928 list_proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
929 BLUEZ_SERVICE_NAME, object_path,
930 BLUEZ_ADAPTER_INTERFACE);
932 if (list_proxy == NULL)
933 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
935 dbus_g_proxy_call(list_proxy, "ListDevices", &error, G_TYPE_INVALID,
936 dbus_g_type_get_collection("GPtrArray",
937 DBUS_TYPE_G_OBJECT_PATH),
938 &gp_array, G_TYPE_INVALID);
945 if (gp_array == NULL)
948 /*Check for headset devices*/
949 for (i = 0; i < gp_array->len; i++) {
952 gp_path = g_ptr_array_index(gp_array, i);
957 proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
958 BLUEZ_SERVICE_NAME, gp_path,
959 BLUEZ_DEVICE_INTERFACE);
964 dbus_g_proxy_call(proxy, "GetProperties", NULL,
965 G_TYPE_INVALID, dbus_g_type_get_map(
966 "GHashTable", G_TYPE_STRING,
967 G_TYPE_VALUE), &list_hash, G_TYPE_INVALID);
969 if (list_hash == NULL)
972 value = g_hash_table_lookup(list_hash, "Class");
973 device_class = value ? g_value_get_uint(value) : 0;
975 if (!__bluetooth_telephony_is_headset(device_class)) {
976 g_object_unref(proxy);
980 g_hash_table_destroy(list_hash);
984 /*Check for Connection*/
985 device_proxy = dbus_g_proxy_new_for_name(
986 telephony_dbus_info.conn,
987 BLUEZ_SERVICE_NAME, gp_path,
988 BLUEZ_HEADSET_INTERFACE);
990 if (device_proxy == NULL) {
991 g_hash_table_destroy(list_hash);
995 dbus_g_proxy_call(device_proxy, "GetProperties",
996 &error, G_TYPE_INVALID,
997 dbus_g_type_get_map("GHashTable",
998 G_TYPE_STRING, G_TYPE_VALUE),
999 &device_hash, G_TYPE_INVALID);
1001 if (error == NULL) {
1002 value = g_hash_table_lookup(device_hash,
1004 connected = value ? g_value_get_boolean(
1007 value = g_hash_table_lookup(list_hash,
1009 address = value ? g_value_get_string(
1011 g_strlcpy(telephony_info.address, address,
1012 sizeof(telephony_info.address));
1013 value = g_hash_table_lookup(device_hash,
1015 playing = value ? g_value_get_boolean(
1018 telephony_info.headset_state =
1019 BLUETOOTH_STATE_PLAYING;
1021 telephony_info.headset_state =
1022 BLUETOOTH_STATE_CONNECTED;
1024 g_hash_table_destroy(device_hash);
1025 g_hash_table_destroy(list_hash);
1028 g_hash_table_destroy(device_hash);
1030 g_error_free(error);
1033 g_hash_table_destroy(list_hash);
1034 g_object_unref(proxy);
1041 g_object_unref(list_proxy);
1043 g_object_unref(device_proxy);
1045 g_object_unref(proxy);
1047 g_ptr_array_free(gp_array, TRUE);
1049 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1052 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1054 DBusGProxy *proxy = NULL;
1055 char object_path[BT_ADAPTER_PATH_LEN] = {0};
1056 GError *error = NULL;
1057 DBusGProxy *default_proxy;
1061 /*Get default adapter path*/
1062 if (__bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
1066 /*Get List of All devices*/
1067 default_proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
1068 BLUEZ_SERVICE_NAME, object_path,
1069 BLUEZ_ADAPTER_INTERFACE);
1071 if (default_proxy == NULL)
1074 if (strlen(telephony_info.address) == 0)
1075 __bluetooth_telephony_get_connected_device();
1077 if (strlen(telephony_info.address) == 0) {
1078 g_object_unref(default_proxy);
1082 if (telephony_info.obj_path) {
1083 g_free(telephony_info.obj_path);
1084 telephony_info.obj_path = NULL;
1087 dbus_g_proxy_call(default_proxy, "FindDevice", &error,
1088 G_TYPE_STRING, telephony_info.address,
1089 G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH,
1090 &telephony_info.obj_path,
1092 if (error != NULL) {
1093 BT_ERR("dbus_g_proxy_call Failed!\n");
1094 g_error_free(error);
1095 g_object_unref(default_proxy);
1099 if (telephony_info.obj_path == NULL) {
1100 g_object_unref(default_proxy);
1104 proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
1105 BLUEZ_SERVICE_NAME, telephony_info.obj_path,
1106 BLUEZ_HEADSET_INTERFACE);
1108 g_object_unref(default_proxy);
1113 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1116 DBusError dbus_error;
1117 DBusConnection *conn;
1118 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1119 GError *error = NULL;
1120 char object_path[BT_ADAPTER_PATH_LEN] = {0};
1125 if (is_initialized == TRUE) {
1126 BT_ERR("Bluetooth telephony already initilized");
1127 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_INITIALIZED;
1130 is_initialized = TRUE;
1132 telephony_dbus_info.conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
1133 if (!telephony_dbus_info.conn) {
1134 if (NULL != error) {
1135 BT_ERR("dbus_g_bus_get() failed:[%d:%s]\n",
1136 error->code, error->message);
1137 g_error_free(error);
1139 is_initialized = FALSE;
1140 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1144 snprintf(telephony_info.call_path, sizeof(telephony_info.call_path),
1145 CSD_CALL_APP_PATH, getpid());
1146 BT_DBG("Call Path = %s", telephony_info.call_path);
1147 memset(telephony_info.address, 0x00, sizeof(telephony_info.address));
1149 if (__bluetooth_telephony_proxy_init()) {
1150 BT_ERR("__bluetooth_telephony_proxy_init failed\n");
1151 dbus_g_connection_unref(telephony_dbus_info.conn);
1152 telephony_dbus_info.conn = NULL;
1153 is_initialized = FALSE;
1154 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1157 telephony_dbus_info.manager_proxy = dbus_g_proxy_new_for_name(
1158 telephony_dbus_info.conn,
1160 "/", BLUEZ_MANAGER_INTERFACE);
1162 if (telephony_dbus_info.manager_proxy == NULL) {
1163 BT_ERR("Could not create a manager proxy\n");
1164 __bluetooth_telephony_proxy_deinit();
1165 dbus_g_connection_unref(telephony_dbus_info.conn);
1166 telephony_dbus_info.conn = NULL;
1167 is_initialized = FALSE;
1168 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1171 telephony_dbus_info.dbus_proxy = dbus_g_proxy_new_for_name(
1172 telephony_dbus_info.conn, DBUS_SERVICE_DBUS,
1173 DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
1175 if (NULL == telephony_dbus_info.dbus_proxy) {
1176 __bluetooth_telephony_proxy_deinit();
1177 dbus_g_connection_unref(telephony_dbus_info.conn);
1178 telephony_dbus_info.conn = NULL;
1179 g_object_unref(telephony_dbus_info.manager_proxy);
1180 telephony_dbus_info.manager_proxy = NULL;
1181 is_initialized = FALSE;
1182 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1185 /*Add Signal callback for BT enabled*/
1186 dbus_g_proxy_add_signal(telephony_dbus_info.manager_proxy,
1188 DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
1189 dbus_g_proxy_connect_signal(telephony_dbus_info.manager_proxy,
1191 G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
1194 /*Callback and user applicaton data*/
1195 telephony_info.cb = cb;
1196 telephony_info.user_data = user_data;
1198 dbus_error_init(&dbus_error);
1199 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1200 dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
1203 dbus_bus_add_match(conn,
1204 "type='signal',interface='" BLUEZ_HEADSET_INTERFACE
1205 "',member='PropertyChanged'", &dbus_error);
1206 dbus_bus_add_match(conn,
1207 "type='signal',interface='"HFP_AGENT_SERVICE
1208 "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error);
1210 if (dbus_error_is_set(&dbus_error)) {
1211 BT_ERR("Fail to add dbus filter signal\n");
1212 dbus_error_free(&dbus_error);
1213 dbus_connection_remove_filter(dbus_g_connection_get_connection(
1214 telephony_dbus_info.conn),
1215 __bluetooth_telephony_event_filter, NULL);
1219 /*Check for BT status*/
1220 ret = __bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
1222 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1223 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1225 /*Bluetooth is active, therefore set the flag */
1228 ret = __bluetooth_telephony_register();
1229 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1230 BT_ERR("__bluetooth_telephony_register failed\n");
1237 telephony_info.cb = NULL;
1238 telephony_info.user_data = NULL;
1239 telephony_info.call_count = 0;
1241 __bluetooth_telephony_proxy_deinit();
1243 /*Remove BT enabled signal*/
1244 dbus_g_proxy_disconnect_signal(
1245 telephony_dbus_info.manager_proxy,
1247 G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
1250 dbus_g_connection_unref(telephony_dbus_info.conn);
1251 telephony_dbus_info.conn = NULL;
1252 g_object_unref(telephony_dbus_info.manager_proxy);
1253 telephony_dbus_info.manager_proxy = NULL;
1254 g_object_unref(telephony_dbus_info.dbus_proxy);
1255 telephony_dbus_info.dbus_proxy = NULL;
1256 is_initialized = FALSE;
1260 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1264 BT_TELEPHONY_CHECK_INITIALIZED();
1266 is_initialized = FALSE;
1268 dbus_connection_remove_filter(dbus_g_connection_get_connection(
1269 telephony_dbus_info.conn),
1270 __bluetooth_telephony_event_filter, NULL);
1272 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_ENABLED)
1273 __bluetooth_telephony_unregister();
1275 __bluetooth_telephony_proxy_deinit();
1277 telephony_info.cb = NULL;
1278 telephony_info.user_data = NULL;
1279 telephony_info.call_count = 0;
1281 /*Remove BT enabled signal*/
1282 dbus_g_proxy_disconnect_signal(
1283 telephony_dbus_info.manager_proxy,
1285 G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
1288 g_object_unref(telephony_dbus_info.manager_proxy);
1289 telephony_dbus_info.manager_proxy = NULL;
1291 dbus_g_connection_unref(telephony_dbus_info.conn);
1292 telephony_dbus_info.conn = NULL;
1294 g_object_unref(telephony_dbus_info.dbus_proxy);
1295 telephony_dbus_info.dbus_proxy = NULL;
1298 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1301 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1305 if (telephony_dbus_info.conn == NULL) {
1306 BT_ERR("Bluetooth telephony not initilized");
1310 /* To get the headset state */
1311 if (telephony_dbus_info.proxy == NULL)
1312 telephony_dbus_info.proxy =
1313 __bluetooth_telephony_get_connected_device_proxy();
1315 if (telephony_dbus_info.proxy == NULL)
1318 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1325 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1329 DBusMessageIter reply_iter;
1330 DBusMessageIter reply_iter_entry;
1331 const char *property;
1335 BT_TELEPHONY_CHECK_INITIALIZED();
1336 BT_TELEPHONY_CHECK_ENABLED();
1339 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1341 reply = __bluetooth_telephony_dbus_method_send(
1342 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1343 "GetProperties", &err, DBUS_TYPE_INVALID);
1346 BT_ERR("Error returned in method call\n");
1347 if (dbus_error_is_set(&err)) {
1348 BT_DBG("Error message = %s \n", err.message);
1349 dbus_error_free(&err);
1351 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1354 dbus_message_iter_init(reply, &reply_iter);
1356 if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
1357 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY\n");
1358 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1361 dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
1364 while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
1365 DBUS_TYPE_DICT_ENTRY) {
1367 DBusMessageIter dict_entry, dict_entry_val;
1368 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
1369 dbus_message_iter_get_basic(&dict_entry, &property);
1370 BT_DBG("String received = %s\n", property);
1372 if (g_strcmp0("nrec", property) == 0) {
1373 dbus_message_iter_next(&dict_entry);
1374 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1375 if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
1379 dbus_message_iter_get_basic(&dict_entry_val, status);
1380 BT_DBG("NREC status = [%d]", *status);
1382 dbus_message_iter_next(&reply_iter_entry);
1384 dbus_message_unref(reply);
1386 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1389 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1391 GError *error = NULL;
1396 BT_TELEPHONY_CHECK_INITIALIZED();
1397 BT_TELEPHONY_CHECK_ENABLED();
1399 if (telephony_dbus_info.proxy == NULL)
1400 telephony_dbus_info.proxy =
1401 __bluetooth_telephony_get_connected_device_proxy();
1403 if (telephony_dbus_info.proxy == NULL)
1404 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1406 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1407 &error, G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID,
1409 if (error != NULL) {
1410 ret = __bt_telephony_get_error(error->message);
1411 g_error_free(error);
1417 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1420 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1422 GError *error = NULL;
1427 BT_TELEPHONY_CHECK_INITIALIZED();
1428 BT_TELEPHONY_CHECK_ENABLED();
1430 if (telephony_dbus_info.proxy == NULL)
1431 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1433 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1434 &error, G_TYPE_BOOLEAN,
1435 FALSE, G_TYPE_INVALID, G_TYPE_INVALID)) {
1436 BT_ERR("Dbus Call Failed!\n");
1437 if (error != NULL) {
1438 ret = __bt_telephony_get_error(error->message);
1439 g_error_free(error);
1445 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1448 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1450 GError *error = NULL;
1455 BT_TELEPHONY_CHECK_INITIALIZED();
1456 BT_TELEPHONY_CHECK_ENABLED();
1458 if (telephony_dbus_info.proxy == NULL)
1459 telephony_dbus_info.proxy =
1460 __bluetooth_telephony_get_connected_device_proxy();
1462 if (telephony_dbus_info.proxy == NULL)
1463 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1465 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1466 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1468 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Play", &error,
1469 G_TYPE_INVALID, G_TYPE_INVALID)) {
1470 BT_ERR("Dbus Call Failed!");
1471 if (error != NULL) {
1472 ret = __bt_telephony_get_error(error->message);
1473 g_error_free(error);
1478 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1481 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1483 GError *error = NULL;
1488 BT_TELEPHONY_CHECK_INITIALIZED();
1489 BT_TELEPHONY_CHECK_ENABLED();
1491 if (telephony_dbus_info.proxy == NULL)
1492 telephony_dbus_info.proxy =
1493 __bluetooth_telephony_get_connected_device_proxy();
1495 if (telephony_dbus_info.proxy == NULL)
1496 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1498 if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING) {
1499 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1502 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Stop", &error,
1503 G_TYPE_INVALID, G_TYPE_INVALID)) {
1504 BT_ERR("Dbus Call Failed");
1505 if (error != NULL) {
1506 ret = __bt_telephony_get_error(error->message);
1507 g_error_free(error);
1513 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1516 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1520 BT_TELEPHONY_CHECK_INITIALIZED();
1521 BT_TELEPHONY_CHECK_ENABLED();
1525 /*Make sure SCO is already connected */
1526 ret = __bluetooth_telephony_send_call_status(
1527 CSD_CALL_STATUS_MO_ALERTING, call_id);
1528 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1529 BT_ERR("send call status Failed = [%d]", ret);
1530 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1533 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1536 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
1537 unsigned int bt_audio)
1542 BT_TELEPHONY_CHECK_INITIALIZED();
1543 BT_TELEPHONY_CHECK_ENABLED();
1545 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1547 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1548 BT_ERR("send call status Failed = [%d]", ret);
1553 if (!bluetooth_telephony_is_sco_connected()) {
1554 ret = bluetooth_telephony_audio_open();
1556 BT_ERR("Audio connection call Failed = %d", ret);
1557 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1566 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
1571 BT_TELEPHONY_CHECK_INITIALIZED();
1572 BT_TELEPHONY_CHECK_ENABLED();
1574 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
1576 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1577 BT_ERR("send call status Failed = [%d]", ret);
1580 if (telephony_info.call_count > 0)
1581 telephony_info.call_count = telephony_info.call_count - 1;
1583 if (telephony_info.call_count == 0) {
1584 if (bluetooth_telephony_is_sco_connected()) {
1585 ret = bluetooth_telephony_audio_close();
1586 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1587 BT_ERR(" Failed = [%d]", ret);
1596 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
1601 BT_TELEPHONY_CHECK_INITIALIZED();
1602 BT_TELEPHONY_CHECK_ENABLED();
1604 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
1606 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1607 BT_ERR("send call status Failed = [%d]", ret);
1613 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
1618 BT_TELEPHONY_CHECK_INITIALIZED();
1619 BT_TELEPHONY_CHECK_ENABLED();
1621 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1623 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1624 BT_ERR("send call status Failed = [%d]", ret);
1630 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
1631 unsigned int call_count)
1635 GList *list = call_list;
1636 bt_telephony_call_status_info_t *call_status;
1640 BT_TELEPHONY_CHECK_INITIALIZED();
1641 BT_TELEPHONY_CHECK_ENABLED();
1644 BT_ERR("call_list is invalid");
1645 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1648 BT_DBG(" call_count = [%d]", call_count);
1650 for (i = 0; i < call_count; i++) {
1651 call_status = g_list_nth_data(list, i);
1653 if (NULL == call_status)
1656 BT_DBG(" %d : Call id [%d] status[%d]", i,
1657 call_status->call_id,
1658 call_status->call_status);
1660 switch (call_status->call_status) {
1661 case BLUETOOTH_CALL_STATE_HELD:
1662 ret = __bluetooth_telephony_send_call_status(
1663 CSD_CALL_STATUS_HOLD,
1664 call_status->call_id);
1665 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1666 BT_ERR("Failed = %d", ret);
1671 case BLUETOOTH_CALL_STATE_CONNECTED:
1672 ret = __bluetooth_telephony_send_call_status(
1673 CSD_CALL_STATUS_ACTIVE,
1674 call_status->call_id);
1675 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1676 BT_ERR("Failed = [%d]", ret);
1682 if ((call_status->call_status < BLUETOOTH_CALL_STATE_NONE) ||
1683 (call_status->call_status >= BLUETOOTH_CALL_STATE_ERROR)) {
1684 BT_ERR("Unknown Call state");
1685 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
1691 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1694 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
1695 unsigned int call_count)
1701 ret = bluetooth_telephony_call_swapped(call_list, call_count);
1703 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1704 BT_ERR("Failed = [%d]", ret);
1708 telephony_info.call_count = call_count;
1711 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1714 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
1715 const char *ph_number, unsigned int call_id,
1716 unsigned int bt_audio)
1720 const char *path = telephony_info.call_path;
1725 BT_TELEPHONY_CHECK_INITIALIZED();
1726 BT_TELEPHONY_CHECK_ENABLED();
1728 if (NULL == ph_number)
1729 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1731 reply = __bluetooth_telephony_dbus_method_send(
1732 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1733 "OutgoingCall", &err, DBUS_TYPE_STRING, &path,
1734 DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1735 &call_id, DBUS_TYPE_INVALID);
1738 BT_ERR("Error returned in method call\n");
1739 if (dbus_error_is_set(&err)) {
1740 ret = __bt_telephony_get_error(err.message);
1741 dbus_error_free(&err);
1744 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1747 dbus_message_unref(reply);
1749 telephony_info.call_count++;
1750 BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
1753 if (!bluetooth_telephony_is_sco_connected()) {
1754 ret = bluetooth_telephony_audio_open();
1756 BT_ERR(" Audio connection call Failed = %d", ret);
1757 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1763 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1766 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
1767 const char *ph_number, unsigned int call_id)
1771 const char *path = telephony_info.call_path;
1776 BT_TELEPHONY_CHECK_INITIALIZED();
1777 BT_TELEPHONY_CHECK_ENABLED();
1779 if (NULL == ph_number)
1780 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1782 reply = __bluetooth_telephony_dbus_method_send(
1783 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1784 "IncomingCall", &err, DBUS_TYPE_STRING, &path,
1785 DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1786 &call_id, DBUS_TYPE_INVALID);
1789 BT_ERR("Error returned in method call\n");
1790 if (dbus_error_is_set(&err)) {
1791 ret = __bt_telephony_get_error(err.message);
1792 dbus_error_free(&err);
1795 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1798 dbus_message_unref(reply);
1800 telephony_info.call_count++;
1801 BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
1803 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1806 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(unsigned short speaker_gain)
1809 DBusMessageIter iter;
1810 DBusMessageIter value;
1811 DBusConnection *conn;
1812 char *spkr_gain_str = "SpeakerGain";
1813 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1816 BT_DBG("set speaker_gain= [%d]", speaker_gain);
1818 BT_TELEPHONY_CHECK_INITIALIZED();
1819 BT_TELEPHONY_CHECK_ENABLED();
1821 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1823 if (telephony_info.obj_path == NULL)
1824 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1826 msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME,
1827 telephony_info.obj_path, BLUEZ_HEADSET_INTERFACE,
1831 char sig[2] = {DBUS_TYPE_UINT16, '\0'};
1833 dbus_message_iter_init_append(msg, &iter);
1834 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
1836 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1838 dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT16,
1840 dbus_message_iter_close_container(&iter, &value);
1842 if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
1843 dbus_message_set_no_reply(msg, TRUE);
1844 if (!dbus_connection_send(conn, msg, NULL)) {
1845 BT_ERR("bluetooth_telephony_set_speaker_gain : dbus sending failed");
1846 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1848 dbus_message_unref(msg);
1850 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1856 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(unsigned int *speaker_gain)
1858 GHashTable *hash = NULL;
1859 GValue *value = NULL;
1860 GError *error = NULL;
1864 BT_TELEPHONY_CHECK_INITIALIZED();
1865 BT_TELEPHONY_CHECK_ENABLED();
1867 if (telephony_dbus_info.proxy == NULL)
1868 telephony_dbus_info.proxy =
1869 __bluetooth_telephony_get_connected_device_proxy();
1871 if (telephony_dbus_info.proxy == NULL)
1872 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1874 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "GetProperties", &error,
1876 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
1877 &hash, G_TYPE_INVALID)) {
1878 BT_ERR("Dbus Call Failed!");
1879 if (error != NULL) {
1880 ret = __bt_telephony_get_error(error->message);
1881 g_error_free(error);
1887 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1889 value = g_hash_table_lookup(hash, "SpeakerGain");
1890 *speaker_gain = g_value_get_uint(value);
1891 g_hash_table_destroy(hash);
1893 return BLUETOOTH_TELEPHONY_ERROR_NONE;