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)
708 BT_DBG("Adapter added [%s] \n", adapter_path);
710 if (strstr(adapter_path, "hci0")) {
711 BT_DBG("BlueZ is Activated and flag need to be reset");
712 BT_DBG("Send enabled to application\n");
714 ret = __bluetooth_telephony_register();
715 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
716 BT_DBG("__bluetooth_telephony_register failed\n");
722 static int __bluetooth_telephony_proxy_init(void)
726 object = (GObject *)__bluetooth_telephony_method_new();
729 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
731 BT_DBG("telephony_object = %x", object);
733 dbus_g_connection_register_g_object(telephony_dbus_info.conn,
734 telephony_info.call_path, G_OBJECT(object));
737 return BLUETOOTH_TELEPHONY_ERROR_NONE;
740 static void __bluetooth_telephony_proxy_deinit(void)
744 dbus_g_connection_unregister_g_object(telephony_dbus_info.conn,
747 g_object_unref(object);
754 static int __bluetooth_telephony_register(void)
758 char *path = g_strdup(telephony_info.call_path);
763 reply = __bluetooth_telephony_dbus_method_send(
764 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
765 "RegisterApplication", &err, DBUS_TYPE_STRING, &path,
770 BT_ERR("Error returned in method call\n");
771 if (dbus_error_is_set(&err)) {
772 ret = __bt_telephony_get_error(err.message);
773 dbus_error_free(&err);
776 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
779 dbus_message_unref(reply);
781 return BLUETOOTH_TELEPHONY_ERROR_NONE;
784 static int __bluetooth_telephony_unregister(void)
788 char *path = g_strdup(telephony_info.call_path);
793 reply = __bluetooth_telephony_dbus_method_send(
794 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
795 "UnregisterApplication", &err, DBUS_TYPE_STRING, &path,
800 BT_ERR("Error returned in method call\n");
801 if (dbus_error_is_set(&err)) {
802 ret = __bt_telephony_get_error(err.message);
803 dbus_error_free(&err);
806 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
809 dbus_message_unref(reply);
811 return BLUETOOTH_TELEPHONY_ERROR_NONE;
814 static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
818 char *adapter_path = NULL;
822 if (!dbus_g_proxy_call(telephony_dbus_info.manager_proxy,
823 "DefaultAdapter", &err, G_TYPE_INVALID,
824 DBUS_TYPE_G_OBJECT_PATH, &adapter_path,
827 BT_ERR("Getting DefaultAdapter failed: [%s]",
831 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
834 if (adapter_path == NULL) {
835 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
838 if (strlen(adapter_path) >= BT_ADAPTER_PATH_LEN) {
839 BT_ERR("Path too long.\n");
840 g_free(adapter_path);
841 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
844 BT_DBG("path = %s", adapter_path);
845 g_strlcpy(path, adapter_path, BT_ADAPTER_PATH_LEN);
846 g_free(adapter_path);
848 return BLUETOOTH_TELEPHONY_ERROR_NONE;
851 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
853 gboolean flag = FALSE;
856 switch ((device_class & 0x1f00) >> 8) {
858 switch ((device_class & 0xfc) >> 2) {
880 static int __bluetooth_telephony_get_connected_device(void)
882 DBusGProxy *list_proxy = NULL;
883 DBusGProxy *device_proxy = NULL;
884 GPtrArray *gp_array = NULL;
885 GError *error = NULL;
886 gchar *gp_path = NULL;
887 GHashTable *list_hash;
888 GHashTable *device_hash;
890 uint32_t device_class;
891 gboolean playing = FALSE;
892 gboolean connected = FALSE;
893 const gchar *address;
894 char object_path[BT_ADAPTER_PATH_LEN] = {0};
896 DBusGProxy *proxy = NULL;
900 /*Get default adapter path*/
901 if (__bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
903 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
904 /*Get List of All devices*/
905 list_proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
906 BLUEZ_SERVICE_NAME, object_path,
907 BLUEZ_ADAPTER_INTERFACE);
909 if (list_proxy == NULL)
910 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
912 dbus_g_proxy_call(list_proxy, "ListDevices", &error, G_TYPE_INVALID,
913 dbus_g_type_get_collection("GPtrArray",
914 DBUS_TYPE_G_OBJECT_PATH),
915 &gp_array, G_TYPE_INVALID);
922 if (gp_array == NULL)
925 /*Check for headset devices*/
926 for (i = 0; i < gp_array->len; i++) {
929 gp_path = g_ptr_array_index(gp_array, i);
934 proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
935 BLUEZ_SERVICE_NAME, gp_path,
936 BLUEZ_DEVICE_INTERFACE);
941 dbus_g_proxy_call(proxy, "GetProperties", NULL,
942 G_TYPE_INVALID, dbus_g_type_get_map(
943 "GHashTable", G_TYPE_STRING,
944 G_TYPE_VALUE), &list_hash, G_TYPE_INVALID);
946 if (list_hash == NULL)
949 value = g_hash_table_lookup(list_hash, "Class");
950 device_class = value ? g_value_get_uint(value) : 0;
952 if (!__bluetooth_telephony_is_headset(device_class)) {
953 g_object_unref(proxy);
957 g_hash_table_destroy(list_hash);
961 /*Check for Connection*/
962 device_proxy = dbus_g_proxy_new_for_name(
963 telephony_dbus_info.conn,
964 BLUEZ_SERVICE_NAME, gp_path,
965 BLUEZ_HEADSET_INTERFACE);
967 if (device_proxy == NULL) {
968 g_hash_table_destroy(list_hash);
972 dbus_g_proxy_call(device_proxy, "GetProperties",
973 &error, G_TYPE_INVALID,
974 dbus_g_type_get_map("GHashTable",
975 G_TYPE_STRING, G_TYPE_VALUE),
976 &device_hash, G_TYPE_INVALID);
979 value = g_hash_table_lookup(device_hash,
981 connected = value ? g_value_get_boolean(
984 value = g_hash_table_lookup(list_hash,
986 address = value ? g_value_get_string(
988 g_strlcpy(telephony_info.address, address,
989 sizeof(telephony_info.address));
990 value = g_hash_table_lookup(device_hash,
992 playing = value ? g_value_get_boolean(
995 telephony_info.headset_state =
996 BLUETOOTH_STATE_PLAYING;
998 telephony_info.headset_state =
999 BLUETOOTH_STATE_CONNECTED;
1001 g_hash_table_destroy(device_hash);
1002 g_hash_table_destroy(list_hash);
1005 g_hash_table_destroy(device_hash);
1007 g_error_free(error);
1010 g_hash_table_destroy(list_hash);
1011 g_object_unref(proxy);
1018 g_object_unref(list_proxy);
1020 g_object_unref(device_proxy);
1022 g_object_unref(proxy);
1024 g_ptr_array_free(gp_array, TRUE);
1026 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1029 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1031 DBusGProxy *proxy = NULL;
1032 char object_path[BT_ADAPTER_PATH_LEN] = {0};
1033 GError *error = NULL;
1034 DBusGProxy *default_proxy;
1038 /*Get default adapter path*/
1039 if (__bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
1043 /*Get List of All devices*/
1044 default_proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
1045 BLUEZ_SERVICE_NAME, object_path,
1046 BLUEZ_ADAPTER_INTERFACE);
1048 if (default_proxy == NULL)
1051 if (strlen(telephony_info.address) == 0)
1052 __bluetooth_telephony_get_connected_device();
1054 if (strlen(telephony_info.address) == 0) {
1055 g_object_unref(default_proxy);
1059 if (telephony_info.obj_path) {
1060 g_free(telephony_info.obj_path);
1061 telephony_info.obj_path = NULL;
1064 dbus_g_proxy_call(default_proxy, "FindDevice", &error,
1065 G_TYPE_STRING, telephony_info.address,
1066 G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH,
1067 &telephony_info.obj_path,
1069 if (error != NULL) {
1070 BT_ERR("dbus_g_proxy_call Failed!\n");
1071 g_error_free(error);
1072 g_object_unref(default_proxy);
1076 if (telephony_info.obj_path == NULL) {
1077 g_object_unref(default_proxy);
1081 proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
1082 BLUEZ_SERVICE_NAME, telephony_info.obj_path,
1083 BLUEZ_HEADSET_INTERFACE);
1085 g_object_unref(default_proxy);
1090 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1093 DBusError dbus_error;
1094 DBusConnection *conn;
1095 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1096 GError *error = NULL;
1097 char object_path[BT_ADAPTER_PATH_LEN] = {0};
1102 if (is_initialized == TRUE) {
1103 BT_ERR("Bluetooth telephony already initilized");
1104 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_INITIALIZED;
1107 is_initialized = TRUE;
1109 telephony_dbus_info.conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
1110 if (!telephony_dbus_info.conn) {
1111 if (NULL != error) {
1112 BT_ERR("dbus_g_bus_get() failed:[%d:%s]\n",
1113 error->code, error->message);
1114 g_error_free(error);
1116 is_initialized = FALSE;
1117 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1121 snprintf(telephony_info.call_path, sizeof(telephony_info.call_path),
1122 CSD_CALL_APP_PATH, getpid());
1123 BT_DBG("Call Path = %s", telephony_info.call_path);
1124 memset(telephony_info.address, 0x00, sizeof(telephony_info.address));
1126 if (__bluetooth_telephony_proxy_init()) {
1127 BT_ERR("__bluetooth_telephony_proxy_init failed\n");
1128 dbus_g_connection_unref(telephony_dbus_info.conn);
1129 telephony_dbus_info.conn = NULL;
1130 is_initialized = FALSE;
1131 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1134 telephony_dbus_info.manager_proxy = dbus_g_proxy_new_for_name(
1135 telephony_dbus_info.conn,
1137 "/", BLUEZ_MANAGER_INTERFACE);
1139 if (telephony_dbus_info.manager_proxy == NULL) {
1140 BT_ERR("Could not create a manager proxy\n");
1141 __bluetooth_telephony_proxy_deinit();
1142 dbus_g_connection_unref(telephony_dbus_info.conn);
1143 telephony_dbus_info.conn = NULL;
1144 is_initialized = FALSE;
1145 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1148 telephony_dbus_info.dbus_proxy = dbus_g_proxy_new_for_name(
1149 telephony_dbus_info.conn, DBUS_SERVICE_DBUS,
1150 DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
1152 if (NULL == telephony_dbus_info.dbus_proxy) {
1153 __bluetooth_telephony_proxy_deinit();
1154 dbus_g_connection_unref(telephony_dbus_info.conn);
1155 telephony_dbus_info.conn = NULL;
1156 g_object_unref(telephony_dbus_info.manager_proxy);
1157 telephony_dbus_info.manager_proxy = NULL;
1158 is_initialized = FALSE;
1159 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1162 /*Add Signal callback for BT enabled*/
1163 dbus_g_proxy_add_signal(telephony_dbus_info.manager_proxy,
1165 DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
1166 dbus_g_proxy_connect_signal(telephony_dbus_info.manager_proxy,
1168 G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
1171 /*Callback and user applicaton data*/
1172 telephony_info.cb = cb;
1173 telephony_info.user_data = user_data;
1175 dbus_error_init(&dbus_error);
1176 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1177 dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
1180 dbus_bus_add_match(conn,
1181 "type='signal',interface='" BLUEZ_HEADSET_INTERFACE
1182 "',member='PropertyChanged'", &dbus_error);
1183 dbus_bus_add_match(conn,
1184 "type='signal',interface='"HFP_AGENT_SERVICE
1185 "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error);
1187 if (dbus_error_is_set(&dbus_error)) {
1188 BT_ERR("Fail to add dbus filter signal\n");
1189 dbus_error_free(&dbus_error);
1193 /*Check for BT status*/
1194 ret = __bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
1196 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1197 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1199 /*Bluetooth is active, therefore set the flag */
1202 ret = __bluetooth_telephony_register();
1203 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1204 BT_ERR("__bluetooth_telephony_register failed\n");
1211 bluetooth_telephony_deinit();
1215 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1218 DBusConnection *conn;
1220 BT_TELEPHONY_CHECK_INITIALIZED();
1222 is_initialized = FALSE;
1224 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1226 dbus_bus_remove_match(conn,
1227 "type='signal',interface='" BLUEZ_HEADSET_INTERFACE
1228 "',member='PropertyChanged'", NULL);
1230 dbus_bus_remove_match(conn,
1231 "type='signal',interface='"HFP_AGENT_SERVICE
1232 "',member='"HFP_NREC_STATUS_CHANGE"'", NULL);
1234 dbus_connection_remove_filter(conn, __bluetooth_telephony_event_filter,
1237 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_ENABLED)
1238 __bluetooth_telephony_unregister();
1240 __bluetooth_telephony_proxy_deinit();
1242 telephony_info.cb = NULL;
1243 telephony_info.user_data = NULL;
1244 telephony_info.call_count = 0;
1246 /*Remove BT enabled signal*/
1247 dbus_g_proxy_disconnect_signal(
1248 telephony_dbus_info.manager_proxy,
1250 G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
1253 g_object_unref(telephony_dbus_info.manager_proxy);
1254 telephony_dbus_info.manager_proxy = NULL;
1256 dbus_g_connection_unref(telephony_dbus_info.conn);
1257 telephony_dbus_info.conn = NULL;
1259 g_object_unref(telephony_dbus_info.dbus_proxy);
1260 telephony_dbus_info.dbus_proxy = NULL;
1263 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1266 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1270 if (telephony_dbus_info.conn == NULL) {
1271 BT_ERR("Bluetooth telephony not initilized");
1275 /* To get the headset state */
1276 if (telephony_dbus_info.proxy == NULL)
1277 telephony_dbus_info.proxy =
1278 __bluetooth_telephony_get_connected_device_proxy();
1280 if (telephony_dbus_info.proxy == NULL)
1283 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1290 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1294 DBusMessageIter reply_iter;
1295 DBusMessageIter reply_iter_entry;
1296 const char *property;
1300 BT_TELEPHONY_CHECK_INITIALIZED();
1301 BT_TELEPHONY_CHECK_ENABLED();
1304 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1306 reply = __bluetooth_telephony_dbus_method_send(
1307 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1308 "GetProperties", &err, DBUS_TYPE_INVALID);
1311 BT_ERR("Error returned in method call\n");
1312 if (dbus_error_is_set(&err)) {
1313 BT_DBG("Error message = %s \n", err.message);
1314 dbus_error_free(&err);
1316 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1319 dbus_message_iter_init(reply, &reply_iter);
1321 if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
1322 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY\n");
1323 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1326 dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
1329 while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
1330 DBUS_TYPE_DICT_ENTRY) {
1332 DBusMessageIter dict_entry, dict_entry_val;
1333 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
1334 dbus_message_iter_get_basic(&dict_entry, &property);
1335 BT_DBG("String received = %s\n", property);
1337 if (g_strcmp0("nrec", property) == 0) {
1338 dbus_message_iter_next(&dict_entry);
1339 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1340 if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
1344 dbus_message_iter_get_basic(&dict_entry_val, status);
1345 BT_DBG("NREC status = [%d]", *status);
1347 dbus_message_iter_next(&reply_iter_entry);
1349 dbus_message_unref(reply);
1351 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1354 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1356 GError *error = NULL;
1361 BT_TELEPHONY_CHECK_INITIALIZED();
1362 BT_TELEPHONY_CHECK_ENABLED();
1364 if (telephony_dbus_info.proxy == NULL)
1365 telephony_dbus_info.proxy =
1366 __bluetooth_telephony_get_connected_device_proxy();
1368 if (telephony_dbus_info.proxy == NULL)
1369 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1371 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1372 &error, G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID,
1374 if (error != NULL) {
1375 ret = __bt_telephony_get_error(error->message);
1376 g_error_free(error);
1382 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1385 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1387 GError *error = NULL;
1392 BT_TELEPHONY_CHECK_INITIALIZED();
1393 BT_TELEPHONY_CHECK_ENABLED();
1395 if (telephony_dbus_info.proxy == NULL)
1396 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1398 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1399 &error, G_TYPE_BOOLEAN,
1400 FALSE, G_TYPE_INVALID, G_TYPE_INVALID)) {
1401 BT_ERR("Dbus Call Failed!\n");
1402 if (error != NULL) {
1403 ret = __bt_telephony_get_error(error->message);
1404 g_error_free(error);
1410 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1413 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1415 GError *error = NULL;
1420 BT_TELEPHONY_CHECK_INITIALIZED();
1421 BT_TELEPHONY_CHECK_ENABLED();
1423 if (telephony_dbus_info.proxy == NULL)
1424 telephony_dbus_info.proxy =
1425 __bluetooth_telephony_get_connected_device_proxy();
1427 if (telephony_dbus_info.proxy == NULL)
1428 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1430 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1431 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1433 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Play", &error,
1434 G_TYPE_INVALID, G_TYPE_INVALID)) {
1435 BT_ERR("Dbus Call Failed!");
1436 if (error != NULL) {
1437 ret = __bt_telephony_get_error(error->message);
1438 g_error_free(error);
1443 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1446 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1448 GError *error = NULL;
1453 BT_TELEPHONY_CHECK_INITIALIZED();
1454 BT_TELEPHONY_CHECK_ENABLED();
1456 if (telephony_dbus_info.proxy == NULL)
1457 telephony_dbus_info.proxy =
1458 __bluetooth_telephony_get_connected_device_proxy();
1460 if (telephony_dbus_info.proxy == NULL)
1461 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1463 if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING) {
1464 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1467 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Stop", &error,
1468 G_TYPE_INVALID, G_TYPE_INVALID)) {
1469 BT_ERR("Dbus Call Failed");
1470 if (error != NULL) {
1471 ret = __bt_telephony_get_error(error->message);
1472 g_error_free(error);
1478 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1481 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1485 BT_TELEPHONY_CHECK_INITIALIZED();
1486 BT_TELEPHONY_CHECK_ENABLED();
1490 /*Make sure SCO is already connected */
1491 ret = __bluetooth_telephony_send_call_status(
1492 CSD_CALL_STATUS_MO_ALERTING, call_id);
1493 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1494 BT_ERR("send call status Failed = [%d]", ret);
1495 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1498 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1501 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
1502 unsigned int bt_audio)
1507 BT_TELEPHONY_CHECK_INITIALIZED();
1508 BT_TELEPHONY_CHECK_ENABLED();
1510 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1512 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1513 BT_ERR("send call status Failed = [%d]", ret);
1518 if (!bluetooth_telephony_is_sco_connected()) {
1519 ret = bluetooth_telephony_audio_open();
1521 BT_ERR("Audio connection call Failed = %d", ret);
1522 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1531 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
1536 BT_TELEPHONY_CHECK_INITIALIZED();
1537 BT_TELEPHONY_CHECK_ENABLED();
1539 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
1541 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1542 BT_ERR("send call status Failed = [%d]", ret);
1545 if (telephony_info.call_count > 0)
1546 telephony_info.call_count = telephony_info.call_count - 1;
1548 if (telephony_info.call_count == 0) {
1549 if (bluetooth_telephony_is_sco_connected()) {
1550 ret = bluetooth_telephony_audio_close();
1551 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1552 BT_ERR(" Failed = [%d]", ret);
1561 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
1566 BT_TELEPHONY_CHECK_INITIALIZED();
1567 BT_TELEPHONY_CHECK_ENABLED();
1569 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
1571 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1572 BT_ERR("send call status Failed = [%d]", ret);
1578 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
1583 BT_TELEPHONY_CHECK_INITIALIZED();
1584 BT_TELEPHONY_CHECK_ENABLED();
1586 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1588 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1589 BT_ERR("send call status Failed = [%d]", ret);
1595 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
1596 unsigned int call_count)
1600 GList *list = call_list;
1601 bt_telephony_call_status_info_t *call_status;
1605 BT_TELEPHONY_CHECK_INITIALIZED();
1606 BT_TELEPHONY_CHECK_ENABLED();
1609 BT_ERR("call_list is invalid");
1610 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1613 BT_DBG(" call_count = [%d]", call_count);
1615 for (i = 0; i < call_count; i++) {
1616 call_status = g_list_nth_data(list, i);
1618 if (NULL == call_status)
1621 BT_DBG(" %d : Call id [%d] status[%d]", i,
1622 call_status->call_id,
1623 call_status->call_status);
1625 switch (call_status->call_status) {
1626 case BLUETOOTH_CALL_STATE_HELD:
1627 ret = __bluetooth_telephony_send_call_status(
1628 CSD_CALL_STATUS_HOLD,
1629 call_status->call_id);
1630 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1631 BT_ERR("Failed = %d", ret);
1636 case BLUETOOTH_CALL_STATE_CONNECTED:
1637 ret = __bluetooth_telephony_send_call_status(
1638 CSD_CALL_STATUS_ACTIVE,
1639 call_status->call_id);
1640 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1641 BT_ERR("Failed = [%d]", ret);
1647 if ((call_status->call_status < BLUETOOTH_CALL_STATE_NONE) ||
1648 (call_status->call_status >= BLUETOOTH_CALL_STATE_ERROR)) {
1649 BT_ERR("Unknown Call state");
1650 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
1656 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1659 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
1660 unsigned int call_count)
1666 ret = bluetooth_telephony_call_swapped(call_list, call_count);
1668 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1669 BT_ERR("Failed = [%d]", ret);
1673 telephony_info.call_count = call_count;
1676 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1679 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
1680 const char *ph_number, unsigned int call_id,
1681 unsigned int bt_audio)
1685 const char *path = telephony_info.call_path;
1690 BT_TELEPHONY_CHECK_INITIALIZED();
1691 BT_TELEPHONY_CHECK_ENABLED();
1693 if (NULL == ph_number)
1694 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1696 reply = __bluetooth_telephony_dbus_method_send(
1697 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1698 "OutgoingCall", &err, DBUS_TYPE_STRING, &path,
1699 DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1700 &call_id, DBUS_TYPE_INVALID);
1703 BT_ERR("Error returned in method call\n");
1704 if (dbus_error_is_set(&err)) {
1705 ret = __bt_telephony_get_error(err.message);
1706 dbus_error_free(&err);
1709 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1712 dbus_message_unref(reply);
1714 telephony_info.call_count++;
1715 BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
1718 if (!bluetooth_telephony_is_sco_connected()) {
1719 ret = bluetooth_telephony_audio_open();
1721 BT_ERR(" Audio connection call Failed = %d", ret);
1722 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1728 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1731 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
1732 const char *ph_number, unsigned int call_id)
1736 const char *path = telephony_info.call_path;
1741 BT_TELEPHONY_CHECK_INITIALIZED();
1742 BT_TELEPHONY_CHECK_ENABLED();
1744 if (NULL == ph_number)
1745 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1747 reply = __bluetooth_telephony_dbus_method_send(
1748 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1749 "IncomingCall", &err, DBUS_TYPE_STRING, &path,
1750 DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1751 &call_id, DBUS_TYPE_INVALID);
1754 BT_ERR("Error returned in method call\n");
1755 if (dbus_error_is_set(&err)) {
1756 ret = __bt_telephony_get_error(err.message);
1757 dbus_error_free(&err);
1760 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1763 dbus_message_unref(reply);
1765 telephony_info.call_count++;
1766 BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
1768 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1771 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(unsigned short speaker_gain)
1774 DBusMessageIter iter;
1775 DBusMessageIter value;
1776 DBusConnection *conn;
1777 char *spkr_gain_str = "SpeakerGain";
1778 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1781 BT_DBG("set speaker_gain= [%d]", speaker_gain);
1783 BT_TELEPHONY_CHECK_INITIALIZED();
1784 BT_TELEPHONY_CHECK_ENABLED();
1786 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1788 if (telephony_info.obj_path == NULL)
1789 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1791 msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME,
1792 telephony_info.obj_path, BLUEZ_HEADSET_INTERFACE,
1796 char sig[2] = {DBUS_TYPE_UINT16, '\0'};
1798 dbus_message_iter_init_append(msg, &iter);
1799 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
1801 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1803 dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT16,
1805 dbus_message_iter_close_container(&iter, &value);
1807 if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
1808 dbus_message_set_no_reply(msg, TRUE);
1809 if (!dbus_connection_send(conn, msg, NULL)) {
1810 BT_ERR("bluetooth_telephony_set_speaker_gain : dbus sending failed");
1811 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1813 dbus_message_unref(msg);
1815 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1821 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(unsigned int *speaker_gain)
1823 GHashTable *hash = NULL;
1824 GValue *value = NULL;
1825 GError *error = NULL;
1829 BT_TELEPHONY_CHECK_INITIALIZED();
1830 BT_TELEPHONY_CHECK_ENABLED();
1832 if (telephony_dbus_info.proxy == NULL)
1833 telephony_dbus_info.proxy =
1834 __bluetooth_telephony_get_connected_device_proxy();
1836 if (telephony_dbus_info.proxy == NULL)
1837 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1839 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "GetProperties", &error,
1841 dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
1842 &hash, G_TYPE_INVALID)) {
1843 BT_ERR("Dbus Call Failed!");
1844 if (error != NULL) {
1845 ret = __bt_telephony_get_error(error->message);
1846 g_error_free(error);
1852 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1854 value = g_hash_table_lookup(hash, "SpeakerGain");
1855 *speaker_gain = g_value_get_uint(value);
1856 g_hash_table_destroy(hash);
1858 return BLUETOOTH_TELEPHONY_ERROR_NONE;