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())
51 #define BLUEZ_SERVICE_NAME "org.bluez"
52 #define BLUEZ_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager"
53 #define BLUEZ_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
54 #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1"
55 #define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1"
57 #define HFP_AGENT_SERVICE "org.bluez.hfp_agent"
58 #define HFP_AGENT_PATH "/org/bluez/hfp_ag"
59 #define HFP_AGENT_INTERFACE "Org.Hfp.App.Interface"
61 #define CSD_CALL_APP_PATH "/org/tizen/csd/%d"
62 #define HFP_NREC_STATUS_CHANGE "NrecStatusChanged"
64 #define BT_TELEPHONY_CHECK_ENABLED() \
66 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) \
68 BT_ERR("BT is not enabled"); \
69 return BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED; \
73 static gboolean is_initialized = FALSE;
74 #define BT_TELEPHONY_CHECK_INITIALIZED() \
76 if (is_initialized == FALSE) \
78 BT_ERR("Bluetooth telephony not initilized"); \
79 return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED; \
83 #define BLUETOOTH_TELEPHONY_METHOD (bluetooth_telephony_method_get_type())
84 #define BLUETOOTH_TELEPHONY_METHOD_GET_OBJECT(obj) \
85 (G_TYPE_CHECK_INSTANCE_CAST((obj), \
86 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethod))
88 #define BLUETOOTH_TELEPHONY_METHOD_IS_OBJECT(obj) \
89 (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
90 BLUETOOTH_TELEPHONY_METHOD))
92 #define BLUETOOTH_TELEPHONY_METHOD_CLASS(class) \
93 (G_TYPE_CHECK_CLASS_CAST((class), \
94 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))
96 #define BLUETOOTH_TELEPHONY_METHOD_GET_AGENT_CLASS(obj) \
97 (G_TYPE_INSTANCE_GET_CLASS((obj), \
98 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))
100 #define BLUETOOTH_TELEPHONY_METHOD_IS_AGENT_CLASS(class) \
101 (G_TYPE_CHECK_CLASS_TYPE((class), BLUETOOTH_TELEPHONY_METHOD))
103 #define BLUETOOTH_TELEPHONY_METHOD_AGENT_GET_PRIVATE(obj) \
104 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
105 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodPrivate))
107 typedef struct _BluetoothTelephonyMethod BluetoothTelephonyMethod;
108 typedef struct _BluetoothTelephonyMethodClass BluetoothTelephonyMethodClass;
110 struct _BluetoothTelephonyMethod {
114 struct _BluetoothTelephonyMethodClass {
115 GObjectClass parent_class;
118 BluetoothTelephonyMethod *bluetooth_telephony_method_new(void);
119 GType bluetooth_telephony_method_get_type(void);
121 G_DEFINE_TYPE(BluetoothTelephonyMethod, bluetooth_telephony_method, G_TYPE_OBJECT)
123 static DBusHandlerResult __bt_telephony_adapter_filter(DBusConnection *conn,
124 DBusMessage *msg, void *data);
126 static int __bt_telephony_get_object_path(DBusMessage *msg, char **path);
128 static char *__bt_extract_device_path(DBusMessageIter *msg_iter, char *address);
130 static char *_bt_get_device_object_path(char *address);
132 static void _bt_convert_device_path_to_address(const char *device_path,
133 char *device_address);
135 static char *__bt_get_default_adapter_path(DBusMessageIter *msg_iter);
137 static gboolean bluetooth_telephony_method_answer(BluetoothTelephonyMethod *object,
139 DBusGMethodInvocation *context);
141 static gboolean bluetooth_telephony_method_release(
142 BluetoothTelephonyMethod *object, guint callid,
143 DBusGMethodInvocation *context);
145 static gboolean bluetooth_telephony_method_reject(BluetoothTelephonyMethod *object,
146 guint callid, DBusGMethodInvocation *context);
148 static gboolean bluetooth_telephony_method_threeway(
149 BluetoothTelephonyMethod *object, guint value,
150 DBusGMethodInvocation *context);
152 static gboolean bluetooth_telephony_method_send_dtmf(
153 BluetoothTelephonyMethod *object,
154 gchar *dtmf, DBusGMethodInvocation *context);
156 #include "bt-telephony-glue.h"
158 static GObject *object;
159 static bt_telephony_info_t telephony_info;
160 static telephony_dbus_info_t telephony_dbus_info;
161 static gboolean is_active = FALSE;
163 /*Function Declaration*/
164 static int __bt_telephony_get_error(const char *error_message);
165 static void __bt_telephony_event_cb(int event, int result, void *param_data);
166 static GQuark __bluetooth_telephony_error_quark(void);
167 static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path,
168 const char *interface, const char *method, DBusError *err, int type, ...);
169 static int __bluetooth_telephony_send_call_status(
170 bt_telephony_call_status_t call_status,
171 unsigned int call_id);
172 static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
173 const char *err_msg);
175 static DBusHandlerResult __bluetooth_telephony_event_filter(
176 DBusConnection *conn,
177 DBusMessage *msg, void *data);
179 static int __bluetooth_telephony_proxy_init(void);
180 static void __bluetooth_telephony_proxy_deinit(void);
181 static int __bluetooth_telephony_register(void);
182 static int __bluetooth_telephony_unregister(void);
183 static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
185 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class);
186 static int __bluetooth_telephony_get_connected_device(void);
187 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void);
189 /*Function Definition*/
190 static int __bt_telephony_get_error(const char *error_message)
192 if (error_message == NULL) {
193 BT_DBG("Error message NULL\n");
194 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
197 BT_DBG("Error message = %s \n", error_message);
198 if (g_strcmp0(error_message, "NotAvailable") == 0)
199 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
200 else if (g_strcmp0(error_message, "NotConnected") == 0)
201 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
202 else if (g_strcmp0(error_message, "InProgress") == 0)
203 return BLUETOOTH_TELEPHONY_ERROR_BUSY;
204 else if (g_strcmp0(error_message, "InvalidArguments") == 0)
205 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
206 else if (g_strcmp0(error_message, "AlreadyExists") == 0)
207 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST;
208 else if (g_strcmp0(error_message, "Already Connected") == 0)
209 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
210 else if (g_strcmp0(error_message, "No memory") == 0)
211 return BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY;
212 else if (g_strcmp0(error_message, "I/O error") == 0)
213 return BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR;
214 else if (g_strcmp0(error_message, "Operation currently not available") == 0)
215 return BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE;
217 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
220 static void __bt_telephony_event_cb(int event, int result, void *param_data)
222 telephony_event_param_t bt_event = { 0, };
224 bt_event.event = event;
225 bt_event.result = result;
226 bt_event.param_data = param_data;
228 ret_if(telephony_info.cb == NULL);
229 telephony_info.cb(bt_event.event, &bt_event, telephony_info.user_data);
233 static GQuark __bluetooth_telephony_error_quark(void)
235 static GQuark quark = 0;
237 quark = g_quark_from_static_string("telephony");
242 static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path,
243 const char *interface, const char *method, DBusError *err, int type, ...)
251 msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
252 path, interface, method);
254 BT_ERR("Unable to allocate new D-Bus %s message \n", method);
258 va_start(args, type);
260 if (!dbus_message_append_args_valist(msg, type, args)) {
261 dbus_message_unref(msg);
268 dbus_error_init(err);
270 reply = dbus_connection_send_with_reply_and_block(
271 dbus_g_connection_get_connection(telephony_dbus_info.conn),
274 dbus_message_unref(msg);
280 static int __bluetooth_telephony_send_call_status(
281 bt_telephony_call_status_t call_status,
282 unsigned int call_id)
286 char *path = g_strdup(telephony_info.call_path);
291 reply = __bluetooth_telephony_dbus_method_send(
292 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
293 "ChangeCallStatus", &err, DBUS_TYPE_STRING, &path,
294 DBUS_TYPE_INT32, &call_status,
295 DBUS_TYPE_INT32, &call_id, DBUS_TYPE_INVALID);
299 BT_ERR("Error returned in method call\n");
300 if (dbus_error_is_set(&err)) {
301 ret = __bt_telephony_get_error(err.message);
302 dbus_error_free(&err);
305 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
308 dbus_message_unref(reply);
310 return BLUETOOTH_TELEPHONY_ERROR_NONE;
313 static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
316 return g_error_new(BLUETOOTH_TELEPHONY_ERROR, error, err_msg, NULL);
319 static void bluetooth_telephony_method_init(BluetoothTelephonyMethod *object)
322 BT_DBG("agent %p\n", object);
326 static void __bluetooth_telephony_method_finalize(
327 BluetoothTelephonyMethod *object)
330 G_OBJECT_CLASS(bluetooth_telephony_method_parent_class)->finalize((
335 static BluetoothTelephonyMethod *__bluetooth_telephony_method_new(void)
337 BluetoothTelephonyMethod *obj;
340 obj = g_object_new(BLUETOOTH_TELEPHONY_METHOD, NULL);
346 static void bluetooth_telephony_method_class_init(
347 BluetoothTelephonyMethodClass *klass)
349 GObjectClass *object_class = NULL;
352 object_class = G_OBJECT_CLASS(klass);
353 object_class->finalize = (void *)__bluetooth_telephony_method_finalize;
355 /*Registration of the Framework methods */
356 dbus_g_object_type_install_info(BLUETOOTH_TELEPHONY_METHOD,
357 &dbus_glib_bluetooth_telephony_method_object_info);
362 static gboolean bluetooth_telephony_method_answer(
363 BluetoothTelephonyMethod *object,
364 guint callid, DBusGMethodInvocation *context)
366 telephony_event_callid_t call_data = { 0, };
369 BT_DBG("call_id = [%d]", callid);
371 call_data.callid = callid;
373 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL,
374 BLUETOOTH_TELEPHONY_ERROR_NONE,
377 dbus_g_method_return(context);
382 static gboolean bluetooth_telephony_method_release(
383 BluetoothTelephonyMethod *object,
384 guint callid, DBusGMethodInvocation *context)
386 telephony_event_callid_t call_data = { 0, };
389 BT_DBG("call_id = [%d]\n", callid);
391 call_data.callid = callid;
393 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL,
394 BLUETOOTH_TELEPHONY_ERROR_NONE,
397 dbus_g_method_return(context);
403 static gboolean bluetooth_telephony_method_reject(
404 BluetoothTelephonyMethod *object,
405 guint callid, DBusGMethodInvocation *context)
407 telephony_event_callid_t call_data = { 0, };
410 BT_DBG("call_id = [%d]", callid);
412 call_data.callid = callid;
414 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_REJECT_CALL,
415 BLUETOOTH_TELEPHONY_ERROR_NONE,
418 dbus_g_method_return(context);
423 static gboolean bluetooth_telephony_method_threeway(
424 BluetoothTelephonyMethod *object,
425 guint value, DBusGMethodInvocation *context)
431 BT_DBG("chld value = [%d]", value);
435 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL;
438 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL;
441 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL;
444 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL;
447 BT_ERR("Invalid CHLD command");
448 err = __bluetooth_telephony_error(
449 BLUETOOTH_TELEPHONY_ERROR_INVALID_CHLD_INDEX,
450 "Invalid chld command");
451 dbus_g_method_return_error(context, err);
456 BT_DBG("event = [%d]", event);
458 __bt_telephony_event_cb(event,
459 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
460 dbus_g_method_return(context);
465 static gboolean bluetooth_telephony_method_send_dtmf(
466 BluetoothTelephonyMethod *object,
467 gchar *dtmf, DBusGMethodInvocation *context)
469 telephony_event_dtmf_t call_data = { 0, };
475 BT_DBG("Number dial failed\n");
476 err = __bluetooth_telephony_error(
477 BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF,
479 dbus_g_method_return_error(context, err);
484 BT_DBG("Dtmf = %s \n", dtmf);
486 call_data.dtmf = g_strdup(dtmf);
488 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF,
489 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&call_data);
491 dbus_g_method_return(context);
492 g_free(call_data.dtmf);
497 static void __bluetooth_handle_nrec_status_change(DBusMessage *msg)
499 gboolean status = FALSE;
501 if (!dbus_message_get_args(msg, NULL,
502 DBUS_TYPE_BOOLEAN, &status,
503 DBUS_TYPE_INVALID)) {
504 BT_DBG("Error Getting parameters\n");
507 BT_DBG("NREC status = %d\n", status);
509 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED,
510 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&status);
514 static DBusHandlerResult __bluetooth_telephony_event_filter(
515 DBusConnection *conn,
516 DBusMessage *msg, void *data)
518 const char *path = dbus_message_get_path(msg);
519 char *dev_addr = NULL;
520 DBusMessageIter item_iter;
521 DBusMessageIter value_iter;
522 const char *property;
524 /* Check NREC status change Signal*/
525 if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
526 HFP_NREC_STATUS_CHANGE)) {
527 __bluetooth_handle_nrec_status_change(msg);
528 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
531 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
532 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
534 dbus_message_iter_init(msg, &item_iter);
535 if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
536 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
539 dbus_message_iter_get_basic(&item_iter, &property);
541 if (property == NULL)
542 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
544 BT_DBG("Property (%s)\n", property);
546 if (g_strcmp0(property, "State") == 0) {
548 dbus_message_iter_next(&item_iter);
549 dbus_message_iter_recurse(&item_iter, &value_iter);
550 dbus_message_iter_get_basic(&value_iter, &state);
552 BT_ERR("State is null\n");
553 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
555 BT_DBG("State %s\n", state);
557 if (g_strcmp0(state, "connected") == 0) {
558 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
559 } else if (g_strcmp0(state, "playing") == 0) {
560 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
561 } else if (g_strcmp0(state, "disconnected") == 0) {
562 /* Headset state: playing -> disconnected */
563 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) {
564 if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, FALSE)) {
565 BT_DBG("SVCONFKEY_BT_HEADSET_SCO - Set to FALSE\n");
567 BT_DBG("vconf_set_bool - Failed\n");
570 __bt_telephony_event_cb(
571 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
572 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
575 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
578 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
581 if (g_strcmp0(property, "Connected") == 0) {
582 gboolean connected = FALSE;
583 dbus_message_iter_next(&item_iter);
584 dbus_message_iter_recurse(&item_iter, &value_iter);
585 dbus_message_iter_get_basic(&value_iter, &connected);
586 BT_DBG("Connected %d\n", connected);
589 /*Get device address*/
591 dev_addr = strstr(path, "dev_");
593 if (dev_addr != NULL) {
595 g_strlcpy(telephony_info.address,
597 sizeof(telephony_info.address));
598 g_strdelimit(telephony_info.address, "_", ':');
599 BT_DBG("address is %s",
600 telephony_info.address);
602 telephony_info.headset_state =
603 BLUETOOTH_STATE_CONNECTED;
605 if (telephony_dbus_info.proxy != NULL) {
606 g_object_unref(telephony_dbus_info.proxy);
607 telephony_dbus_info.proxy = NULL;
610 telephony_dbus_info.proxy =
611 __bluetooth_telephony_get_connected_device_proxy();
613 BT_DBG("Headset Connected");
615 __bt_telephony_event_cb(
616 BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED,
617 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
619 } else { /*Device disconnected*/
620 memset(telephony_info.address, 0x00,
621 sizeof(telephony_info.address));
622 telephony_info.headset_state =
623 BLUETOOTH_STATE_DISCONNETED;
625 if (telephony_dbus_info.proxy != NULL) {
626 g_object_unref(telephony_dbus_info.proxy);
627 telephony_dbus_info.proxy = NULL;
630 BT_DBG("Headset Disconnected");
632 __bt_telephony_event_cb(
633 BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED,
634 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
636 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
639 if (g_strcmp0(property, "SpeakerGain") == 0) {
640 unsigned int spkr_gain;
642 dbus_message_iter_next(&item_iter);
643 dbus_message_iter_recurse(&item_iter, &value_iter);
644 dbus_message_iter_get_basic(&value_iter, &gain);
646 spkr_gain = (unsigned int)gain;
647 BT_DBG("spk_gain[%d]\n", spkr_gain);
649 __bt_telephony_event_cb(
650 BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN,
651 BLUETOOTH_TELEPHONY_ERROR_NONE,
654 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
657 if (g_strcmp0(property, "MicrophoneGain") == 0) {
658 unsigned int mic_gain;
660 dbus_message_iter_next(&item_iter);
661 dbus_message_iter_recurse(&item_iter, &value_iter);
662 dbus_message_iter_get_basic(&value_iter, &gain);
664 mic_gain = (unsigned int)gain;
665 BT_DBG("mic_gain[%d]\n", mic_gain);
667 __bt_telephony_event_cb(
668 BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN,
669 BLUETOOTH_TELEPHONY_ERROR_NONE,
672 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
675 if (g_strcmp0(property, "Playing") == 0) {
676 gboolean audio_sink_playing = FALSE;
677 dbus_message_iter_next(&item_iter);
678 dbus_message_iter_recurse(&item_iter, &value_iter);
679 dbus_message_iter_get_basic(&value_iter, &audio_sink_playing);
681 if (audio_sink_playing) {
682 if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, TRUE)) {
683 BT_DBG("SVCONFKEY_BT_HEADSET_SCO -"
686 BT_DBG("vconf_set_bool - Failed\n");
688 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
689 __bt_telephony_event_cb(
690 BLUETOOTH_EVENT_TELEPHONY_AUDIO_CONNECTED,
691 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
693 if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, FALSE)) {
694 BT_DBG("SVCONFKEY_BT_HEADSET_SCO -"
697 BT_DBG("vconf_set_bool - Failed\n");
699 telephony_info.headset_state =
700 BLUETOOTH_STATE_CONNECTED;
701 __bt_telephony_event_cb(
702 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
703 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
706 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
708 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
711 static int __bluetooth_telephony_proxy_init(void)
715 object = (GObject *)__bluetooth_telephony_method_new();
718 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
720 BT_DBG("telephony_object = %x", object);
722 dbus_g_connection_register_g_object(telephony_dbus_info.conn,
723 telephony_info.call_path, G_OBJECT(object));
726 return BLUETOOTH_TELEPHONY_ERROR_NONE;
729 static void __bluetooth_telephony_proxy_deinit(void)
733 dbus_g_connection_unregister_g_object(telephony_dbus_info.conn,
736 g_object_unref(object);
743 static int __bluetooth_telephony_register(void)
747 char *path = g_strdup(telephony_info.call_path);
752 reply = __bluetooth_telephony_dbus_method_send(
753 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
754 "RegisterApplication", &err, DBUS_TYPE_STRING, &path,
759 BT_ERR("Error returned in method call\n");
760 if (dbus_error_is_set(&err)) {
761 ret = __bt_telephony_get_error(err.message);
762 BT_ERR("Error here %d\n", ret);
763 dbus_error_free(&err);
766 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
769 dbus_message_unref(reply);
771 return BLUETOOTH_TELEPHONY_ERROR_NONE;
774 static int __bluetooth_telephony_unregister(void)
778 char *path = g_strdup(telephony_info.call_path);
783 reply = __bluetooth_telephony_dbus_method_send(
784 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
785 "UnregisterApplication", &err, DBUS_TYPE_STRING, &path,
790 BT_ERR("Error returned in method call\n");
791 if (dbus_error_is_set(&err)) {
792 ret = __bt_telephony_get_error(err.message);
793 dbus_error_free(&err);
796 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
799 dbus_message_unref(reply);
801 return BLUETOOTH_TELEPHONY_ERROR_NONE;
804 static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
809 DBusMessageIter reply_iter;
810 DBusMessageIter value_iter;
812 DBusConnection *conn;
813 char *adapter_path = NULL;
817 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
819 retv_if(conn == NULL, NULL);
821 msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH,
822 BT_MANAGER_INTERFACE,
823 "GetManagedObjects");
825 retv_if(msg == NULL, NULL);
826 /* Synchronous call */
827 dbus_error_init(&err);
828 reply = dbus_connection_send_with_reply_and_block(
829 conn, msg, -1, &err);
830 dbus_message_unref(msg);
833 BT_ERR("Can't get managed objects");
835 if (dbus_error_is_set(&err)) {
836 BT_ERR("%s", err.message);
837 dbus_error_free(&err);
839 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
842 if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
843 BT_ERR("Fail to iterate the reply");
844 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
847 dbus_message_iter_recurse(&reply_iter, &value_iter);
849 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
850 while (dbus_message_iter_get_arg_type(&value_iter) ==
851 DBUS_TYPE_DICT_ENTRY) {
852 DBusMessageIter msg_iter;
854 dbus_message_iter_recurse(&value_iter, &msg_iter);
856 adapter_path = __bt_get_default_adapter_path(&msg_iter);
857 if (adapter_path != NULL) {
858 BT_DBG("Found the adapter path");
861 dbus_message_iter_next(&value_iter);
864 if (adapter_path == NULL) {
865 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
868 if (strlen(adapter_path) >= BT_ADAPTER_PATH_LEN) {
869 BT_ERR("Path too long.\n");
870 g_free(adapter_path);
871 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
874 BT_DBG("object path = %s", adapter_path);
875 g_strlcpy(path, adapter_path, BT_ADAPTER_PATH_LEN);
876 g_free(adapter_path);
878 return BLUETOOTH_TELEPHONY_ERROR_NONE;
881 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
883 gboolean flag = FALSE;
886 switch ((device_class & 0x1f00) >> 8) {
888 switch ((device_class & 0xfc) >> 2) {
910 static int __bluetooth_telephony_get_connected_device(void)
914 DBusMessageIter reply_iter;
915 DBusMessageIter value_iter;
917 DBusConnection *conn;
918 DBusGProxy *headset_agent_proxy = NULL;
920 GError *error = NULL;
921 uint32_t device_class;
922 gboolean playing = FALSE;
923 gboolean connected = FALSE;
924 GHashTable *list_hash;
926 char *object_path = NULL;
927 DBusGProxy *proxy = NULL;
928 const gchar *address;
930 conn = _bt_get_system_conn();
931 retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
933 msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME, "/",
934 BLUEZ_MANAGER_INTERFACE,
935 "GetManagedObjects");
937 retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
939 /* Synchronous call */
940 dbus_error_init(&err);
941 reply = dbus_connection_send_with_reply_and_block(
944 dbus_message_unref(msg);
947 BT_ERR("Can't get managed objects");
949 if (dbus_error_is_set(&err)) {
950 BT_ERR("%s", err.message);
951 dbus_error_free(&err);
953 return BLUETOOTH_ERROR_INTERNAL;
956 if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
957 BT_ERR("Fail to iterate the reply");
958 return BLUETOOTH_ERROR_INTERNAL;
961 dbus_message_iter_recurse(&reply_iter, &value_iter);
963 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
964 while (dbus_message_iter_get_arg_type(&value_iter) ==
965 DBUS_TYPE_DICT_ENTRY) {
966 DBusMessageIter msg_iter;
968 dbus_message_iter_recurse(&value_iter, &msg_iter);
970 /* Parse the signature: oa{sa{sv}}} */
971 retv_if(dbus_message_iter_get_arg_type(&msg_iter) !=
972 DBUS_TYPE_OBJECT_PATH, NULL);
974 dbus_message_iter_get_basic(&msg_iter, &object_path);
978 proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
979 BLUEZ_SERVICE_NAME, object_path,
980 BLUEZ_PROPERTIES_INTERFACE);
985 dbus_g_proxy_call(proxy, "GetAll", &err,
986 G_TYPE_STRING, BLUEZ_DEVICE_INTERFACE,
988 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
989 G_TYPE_VALUE), &list_hash, G_TYPE_INVALID);
991 if (list_hash != NULL) {
992 value = g_hash_table_lookup(list_hash, "Class");
993 device_class = value ? g_value_get_uint(value) : 0;
996 if (!__bluetooth_telephony_is_headset(device_class)) {
997 g_object_unref(proxy);
999 g_hash_table_destroy(list_hash);
1000 dbus_message_iter_next(&value_iter);
1003 /* this is headset; Check for Connection */
1004 headset_agent_proxy = dbus_g_proxy_new_for_name(
1005 telephony_dbus_info.conn,
1006 HFP_AGENT_SERVICE, object_path,
1007 HFP_AGENT_INTERFACE);
1009 if (headset_agent_proxy == NULL) {
1010 g_hash_table_destroy(list_hash);
1014 dbus_g_proxy_call(headset_agent_proxy, "IsConnected",
1015 &error, G_TYPE_INVALID,
1016 &connected, G_TYPE_INVALID);
1018 if (error == NULL) {
1020 value = g_hash_table_lookup(list_hash,
1022 address = value ? g_value_get_string(
1025 g_strlcpy(telephony_info.address, address,
1026 sizeof(telephony_info.address));
1027 dbus_g_proxy_call(headset_agent_proxy, "IsPlaying",
1028 &error, G_TYPE_INVALID,
1029 &playing, G_TYPE_INVALID);
1032 telephony_info.headset_state =
1033 BLUETOOTH_STATE_PLAYING;
1035 telephony_info.headset_state =
1036 BLUETOOTH_STATE_CONNECTED;
1038 g_hash_table_destroy(list_hash);
1042 g_error_free(error);
1045 g_hash_table_destroy(list_hash);
1046 g_object_unref(proxy);
1048 } /* end of if(object_path) */
1050 dbus_message_iter_next(&value_iter);
1051 } /* end of while */
1055 g_object_unref(proxy);
1057 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1060 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1062 DBusGProxy *proxy = NULL;
1063 char *object_path = NULL;
1067 if (strlen(telephony_info.address) == 0)
1068 __bluetooth_telephony_get_connected_device();
1070 if (strlen(telephony_info.address) == 0) {
1074 if (telephony_info.obj_path) {
1075 g_free(telephony_info.obj_path);
1076 telephony_info.obj_path = NULL;
1079 object_path = _bt_get_device_object_path(telephony_info.address);
1080 g_strlcpy(telephony_info.obj_path, object_path, BT_ADAPTER_PATH_LEN);
1082 proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
1083 HFP_AGENT_SERVICE, telephony_info.obj_path,
1084 HFP_AGENT_INTERFACE);
1089 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1092 DBusError dbus_error;
1093 DBusConnection *conn;
1094 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1095 GError *error = NULL;
1096 char object_path[BT_ADAPTER_PATH_LEN] = {0};
1098 DBusConnection *dbus_conn;
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 dbus_conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1164 /*Add Signal callback for BT enabled*/
1165 if (!dbus_connection_add_filter(dbus_conn, __bt_telephony_adapter_filter,
1167 BT_ERR("Fail to add filter");
1168 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1171 dbus_error_init(&dbus_error);
1173 dbus_bus_add_match(dbus_conn,
1174 "type='signal',interface='org.freedesktop.DBus.ObjectManager'"
1175 ",member='InterfacesAdded'",
1178 if (dbus_error_is_set(&dbus_error)) {
1179 BT_ERR("Fail to add match: %s\n", dbus_error.message);
1180 dbus_error_free(&dbus_error);
1184 /*Callback and user applicaton data*/
1185 telephony_info.cb = cb;
1186 telephony_info.user_data = user_data;
1187 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1189 dbus_error_init(&dbus_error);
1190 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1191 dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
1194 dbus_bus_add_match(conn,
1195 "type='signal',interface='"HFP_AGENT_SERVICE
1196 "',member='PropertyChanged'", &dbus_error);
1197 dbus_bus_add_match(conn,
1198 "type='signal',interface='"HFP_AGENT_SERVICE
1199 "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error);
1201 if (dbus_error_is_set(&dbus_error)) {
1202 BT_ERR("Fail to add dbus filter signal\n");
1203 dbus_error_free(&dbus_error);
1207 /*Check for BT status*/
1208 ret = __bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
1210 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1211 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1213 /*Bluetooth is active, therefore set the flag */
1216 ret = __bluetooth_telephony_register();
1217 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1218 BT_ERR("__bluetooth_telephony_register failed\n");
1226 bluetooth_telephony_deinit();
1230 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1232 DBusConnection *conn;
1237 BT_TELEPHONY_CHECK_INITIALIZED();
1239 is_initialized = FALSE;
1240 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1242 dbus_error_init(&error);
1244 dbus_bus_remove_match(conn,
1245 "type='signal',interface='"HFP_AGENT_SERVICE
1246 "',member='PropertyChanged'", &error);
1247 dbus_bus_remove_match(conn,
1248 "type='signal',interface='"HFP_AGENT_SERVICE
1249 "',member='"HFP_NREC_STATUS_CHANGE"'", &error);
1250 if (dbus_error_is_set(&error)) {
1251 BT_ERR("Fail to remove dbus filter signal\n");
1252 dbus_error_free(&error);
1255 dbus_connection_remove_filter(conn, __bluetooth_telephony_event_filter,
1258 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_ENABLED)
1259 __bluetooth_telephony_unregister();
1261 __bluetooth_telephony_proxy_deinit();
1263 telephony_info.cb = NULL;
1264 telephony_info.user_data = NULL;
1265 telephony_info.call_count = 0;
1266 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1268 /*Remove BT enabled signal*/
1269 dbus_bus_remove_match(conn,
1270 "type='signal',interface='org.freedesktop.DBus.ObjectManager'"
1271 ",member='InterfacesAdded'",
1273 if (dbus_error_is_set(&error)) {
1274 BT_ERR("Fail to remove dbus filter signal\n");
1275 dbus_error_free(&error);
1278 dbus_connection_remove_filter(dbus_g_connection_get_connection(
1279 telephony_dbus_info.conn), __bt_telephony_adapter_filter,
1282 g_object_unref(telephony_dbus_info.manager_proxy);
1283 telephony_dbus_info.manager_proxy = NULL;
1285 dbus_g_connection_unref(telephony_dbus_info.conn);
1286 telephony_dbus_info.conn = NULL;
1288 g_object_unref(telephony_dbus_info.dbus_proxy);
1289 telephony_dbus_info.dbus_proxy = NULL;
1292 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1295 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1299 if (telephony_dbus_info.conn == NULL) {
1300 BT_ERR("Bluetooth telephony not initilized");
1304 /* To get the headset state */
1305 if (telephony_dbus_info.proxy == NULL)
1306 telephony_dbus_info.proxy =
1307 __bluetooth_telephony_get_connected_device_proxy();
1309 if (telephony_dbus_info.proxy == NULL)
1312 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1319 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1323 DBusMessageIter reply_iter;
1324 DBusMessageIter reply_iter_entry;
1325 const char *property;
1329 BT_TELEPHONY_CHECK_INITIALIZED();
1330 BT_TELEPHONY_CHECK_ENABLED();
1333 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1335 reply = __bluetooth_telephony_dbus_method_send(
1336 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1337 "GetProperties", &err, DBUS_TYPE_INVALID);
1340 BT_ERR("Error returned in method call\n");
1341 if (dbus_error_is_set(&err)) {
1342 BT_DBG("Error message = %s \n", err.message);
1343 dbus_error_free(&err);
1345 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1348 dbus_message_iter_init(reply, &reply_iter);
1350 if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
1351 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY\n");
1352 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1355 dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
1358 while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
1359 DBUS_TYPE_DICT_ENTRY) {
1361 DBusMessageIter dict_entry, dict_entry_val;
1362 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
1363 dbus_message_iter_get_basic(&dict_entry, &property);
1364 BT_DBG("String received = %s\n", property);
1366 if (g_strcmp0("nrec", property) == 0) {
1367 dbus_message_iter_next(&dict_entry);
1368 dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1369 if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
1373 dbus_message_iter_get_basic(&dict_entry_val, status);
1374 BT_DBG("NREC status = [%d]", *status);
1376 dbus_message_iter_next(&reply_iter_entry);
1378 dbus_message_unref(reply);
1380 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1383 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1385 GError *error = NULL;
1390 BT_TELEPHONY_CHECK_INITIALIZED();
1391 BT_TELEPHONY_CHECK_ENABLED();
1393 if (telephony_dbus_info.proxy == NULL)
1394 telephony_dbus_info.proxy =
1395 __bluetooth_telephony_get_connected_device_proxy();
1397 if (telephony_dbus_info.proxy == NULL)
1398 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1400 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1401 &error, G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID,
1403 if (error != NULL) {
1404 ret = __bt_telephony_get_error(error->message);
1405 g_error_free(error);
1411 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1414 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1416 GError *error = NULL;
1421 BT_TELEPHONY_CHECK_INITIALIZED();
1422 BT_TELEPHONY_CHECK_ENABLED();
1424 if (telephony_dbus_info.proxy == NULL)
1425 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1427 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1428 &error, G_TYPE_BOOLEAN,
1429 FALSE, G_TYPE_INVALID, G_TYPE_INVALID)) {
1430 BT_ERR("Dbus Call Failed!\n");
1431 if (error != NULL) {
1432 ret = __bt_telephony_get_error(error->message);
1433 g_error_free(error);
1439 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1442 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1444 GError *error = NULL;
1449 BT_TELEPHONY_CHECK_INITIALIZED();
1450 BT_TELEPHONY_CHECK_ENABLED();
1452 if (telephony_dbus_info.proxy == NULL)
1453 telephony_dbus_info.proxy =
1454 __bluetooth_telephony_get_connected_device_proxy();
1456 if (telephony_dbus_info.proxy == NULL)
1457 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1459 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1460 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1462 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Play", &error,
1463 G_TYPE_INVALID, G_TYPE_INVALID)) {
1464 BT_ERR("Dbus Call Failed!");
1465 if (error != NULL) {
1466 ret = __bt_telephony_get_error(error->message);
1467 g_error_free(error);
1472 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1475 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1477 GError *error = NULL;
1482 BT_TELEPHONY_CHECK_INITIALIZED();
1483 BT_TELEPHONY_CHECK_ENABLED();
1485 if (telephony_dbus_info.proxy == NULL)
1486 telephony_dbus_info.proxy =
1487 __bluetooth_telephony_get_connected_device_proxy();
1489 if (telephony_dbus_info.proxy == NULL)
1490 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1492 if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING) {
1493 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1496 if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Stop", &error,
1497 G_TYPE_INVALID, G_TYPE_INVALID)) {
1498 BT_ERR("Dbus Call Failed");
1499 if (error != NULL) {
1500 ret = __bt_telephony_get_error(error->message);
1501 g_error_free(error);
1507 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1510 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1514 BT_TELEPHONY_CHECK_INITIALIZED();
1515 BT_TELEPHONY_CHECK_ENABLED();
1519 /*Make sure SCO is already connected */
1520 ret = __bluetooth_telephony_send_call_status(
1521 CSD_CALL_STATUS_MO_ALERTING, call_id);
1522 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1523 BT_ERR("send call status Failed = [%d]", ret);
1524 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1527 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1530 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
1531 unsigned int bt_audio)
1536 BT_TELEPHONY_CHECK_INITIALIZED();
1537 BT_TELEPHONY_CHECK_ENABLED();
1539 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1541 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1542 BT_ERR("send call status Failed = [%d]", ret);
1547 if (!bluetooth_telephony_is_sco_connected()) {
1548 ret = bluetooth_telephony_audio_open();
1550 BT_ERR("Audio connection call Failed = %d", ret);
1551 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1560 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
1565 BT_TELEPHONY_CHECK_INITIALIZED();
1566 BT_TELEPHONY_CHECK_ENABLED();
1568 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
1570 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1571 BT_ERR("send call status Failed = [%d]", ret);
1574 if (telephony_info.call_count > 0)
1575 telephony_info.call_count = telephony_info.call_count - 1;
1577 if (telephony_info.call_count == 0) {
1578 if (bluetooth_telephony_is_sco_connected()) {
1579 ret = bluetooth_telephony_audio_close();
1580 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1581 BT_ERR(" Failed = [%d]", ret);
1590 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
1595 BT_TELEPHONY_CHECK_INITIALIZED();
1596 BT_TELEPHONY_CHECK_ENABLED();
1598 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
1600 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1601 BT_ERR("send call status Failed = [%d]", ret);
1607 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
1612 BT_TELEPHONY_CHECK_INITIALIZED();
1613 BT_TELEPHONY_CHECK_ENABLED();
1615 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1617 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1618 BT_ERR("send call status Failed = [%d]", ret);
1624 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
1625 unsigned int call_count)
1629 GList *list = call_list;
1630 bt_telephony_call_status_info_t *call_status;
1634 BT_TELEPHONY_CHECK_INITIALIZED();
1635 BT_TELEPHONY_CHECK_ENABLED();
1638 BT_ERR("call_list is invalid");
1639 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1642 BT_DBG(" call_count = [%d]", call_count);
1644 for (i = 0; i < call_count; i++) {
1645 call_status = g_list_nth_data(list, i);
1647 if (NULL == call_status)
1650 BT_DBG(" %d : Call id [%d] status[%d]", i,
1651 call_status->call_id,
1652 call_status->call_status);
1654 switch (call_status->call_status) {
1655 case BLUETOOTH_CALL_STATE_HELD:
1656 ret = __bluetooth_telephony_send_call_status(
1657 CSD_CALL_STATUS_HOLD,
1658 call_status->call_id);
1659 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1660 BT_ERR("Failed = %d", ret);
1665 case BLUETOOTH_CALL_STATE_CONNECTED:
1666 ret = __bluetooth_telephony_send_call_status(
1667 CSD_CALL_STATUS_ACTIVE,
1668 call_status->call_id);
1669 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1670 BT_ERR("Failed = [%d]", ret);
1676 if ((call_status->call_status < BLUETOOTH_CALL_STATE_NONE) ||
1677 (call_status->call_status >= BLUETOOTH_CALL_STATE_ERROR)) {
1678 BT_ERR("Unknown Call state");
1679 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
1685 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1688 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
1689 unsigned int call_count)
1695 ret = bluetooth_telephony_call_swapped(call_list, call_count);
1697 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1698 BT_ERR("Failed = [%d]", ret);
1702 telephony_info.call_count = call_count;
1705 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1708 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
1709 const char *ph_number, unsigned int call_id,
1710 unsigned int bt_audio)
1714 const char *path = telephony_info.call_path;
1719 BT_TELEPHONY_CHECK_INITIALIZED();
1720 BT_TELEPHONY_CHECK_ENABLED();
1722 if (NULL == ph_number)
1723 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1725 reply = __bluetooth_telephony_dbus_method_send(
1726 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1727 "OutgoingCall", &err, DBUS_TYPE_STRING, &path,
1728 DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1729 &call_id, DBUS_TYPE_INVALID);
1732 BT_ERR("Error returned in method call\n");
1733 if (dbus_error_is_set(&err)) {
1734 ret = __bt_telephony_get_error(err.message);
1735 dbus_error_free(&err);
1738 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1741 dbus_message_unref(reply);
1743 telephony_info.call_count++;
1744 BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
1747 if (!bluetooth_telephony_is_sco_connected()) {
1748 ret = bluetooth_telephony_audio_open();
1750 BT_ERR(" Audio connection call Failed = %d", ret);
1751 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1757 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1760 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
1761 const char *ph_number, unsigned int call_id)
1765 const char *path = telephony_info.call_path;
1770 BT_TELEPHONY_CHECK_INITIALIZED();
1771 BT_TELEPHONY_CHECK_ENABLED();
1773 if (NULL == ph_number)
1774 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1776 reply = __bluetooth_telephony_dbus_method_send(
1777 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1778 "IncomingCall", &err, DBUS_TYPE_STRING, &path,
1779 DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1780 &call_id, DBUS_TYPE_INVALID);
1783 BT_ERR("Error returned in method call\n");
1784 if (dbus_error_is_set(&err)) {
1785 ret = __bt_telephony_get_error(err.message);
1786 dbus_error_free(&err);
1789 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1792 dbus_message_unref(reply);
1794 telephony_info.call_count++;
1795 BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
1797 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1800 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(unsigned short speaker_gain)
1802 GError *error = NULL;
1803 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1804 DBusGProxy *headset_agent_proxy = NULL;
1806 BT_DBG("set speaker_gain= [%d]", speaker_gain);
1808 BT_TELEPHONY_CHECK_INITIALIZED();
1809 BT_TELEPHONY_CHECK_ENABLED();
1811 if (telephony_info.obj_path == NULL)
1812 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1814 if (telephony_dbus_info.proxy == NULL)
1815 telephony_dbus_info.proxy =
1816 __bluetooth_telephony_get_connected_device_proxy();
1818 if (telephony_dbus_info.proxy == NULL)
1819 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1821 if (!dbus_g_proxy_call(headset_agent_proxy, "SetSpeakerGain",
1822 &error, G_TYPE_UINT, speaker_gain, G_TYPE_INVALID,
1824 if (error != NULL) {
1825 BT_ERR("Calling SetSpeakerGain failed: [%s]",
1827 g_error_free(error);
1835 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(unsigned int *speaker_gain)
1837 DBusGProxy *headset_agent_proxy = NULL;
1838 GError *error = NULL;
1841 BT_TELEPHONY_CHECK_INITIALIZED();
1842 BT_TELEPHONY_CHECK_ENABLED();
1844 if (telephony_dbus_info.proxy == NULL)
1845 telephony_dbus_info.proxy =
1846 __bluetooth_telephony_get_connected_device_proxy();
1848 if (telephony_dbus_info.proxy == NULL)
1849 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1851 if (telephony_info.obj_path == NULL)
1852 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1854 if (telephony_dbus_info.proxy == NULL)
1855 telephony_dbus_info.proxy =
1856 __bluetooth_telephony_get_connected_device_proxy();
1858 if (telephony_dbus_info.proxy == NULL)
1859 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1861 if (!dbus_g_proxy_call(headset_agent_proxy, "GetSpeakerGain",
1862 &error, G_TYPE_INVALID, G_TYPE_UINT, &speaker_gain,
1864 if (error != NULL) {
1865 BT_ERR("Calling G`etSpeakerGain failed: [%s]",
1867 g_error_free(error);
1872 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1875 static char *_bt_get_device_object_path(char *address)
1879 DBusMessageIter reply_iter;
1880 DBusMessageIter value_iter;
1882 DBusConnection *conn;
1883 char *object_path = NULL;
1886 conn = _bt_get_system_conn();
1887 retv_if(conn == NULL, NULL);
1889 msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME, BT_MANAGER_PATH,
1890 BLUEZ_MANAGER_INTERFACE,
1891 "GetManagedObjects");
1893 retv_if(msg == NULL, NULL);
1895 /* Synchronous call */
1896 dbus_error_init(&err);
1897 reply = dbus_connection_send_with_reply_and_block(
1900 dbus_message_unref(msg);
1903 BT_ERR("Can't get managed objects");
1905 if (dbus_error_is_set(&err)) {
1906 BT_ERR("%s", err.message);
1907 dbus_error_free(&err);
1912 if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
1913 BT_ERR("Fail to iterate the reply");
1917 dbus_message_iter_recurse(&reply_iter, &value_iter);
1919 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
1920 while (dbus_message_iter_get_arg_type(&value_iter) ==
1921 DBUS_TYPE_DICT_ENTRY) {
1922 DBusMessageIter msg_iter;
1924 dbus_message_iter_recurse(&value_iter, &msg_iter);
1926 object_path = __bt_extract_device_path(&msg_iter, address);
1927 if (object_path != NULL) {
1928 BT_DBG("Found the device path");
1932 dbus_message_iter_next(&value_iter);
1938 static char *__bt_extract_device_path(DBusMessageIter *msg_iter, char *address)
1940 char *object_path = NULL;
1941 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
1944 /* Parse the signature: oa{sa{sv}}} */
1945 retv_if(dbus_message_iter_get_arg_type(msg_iter) !=
1946 DBUS_TYPE_OBJECT_PATH, NULL);
1948 dbus_message_iter_get_basic(msg_iter, &object_path);
1949 retv_if(object_path == NULL, NULL);
1951 _bt_convert_device_path_to_address(object_path, device_address);
1953 if (g_strcmp0(address, device_address) == 0) {
1954 return g_strdup(object_path);
1960 static DBusHandlerResult __bt_telephony_adapter_filter(DBusConnection *conn,
1961 DBusMessage *msg, void *data)
1964 char *object_path = NULL;
1965 const char *member = dbus_message_get_member(msg);
1968 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
1969 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1972 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1974 if (strcasecmp(member, "InterfacesAdded") == 0) {
1975 if (__bt_telephony_get_object_path(msg, &object_path)) {
1976 BT_ERR("Fail to get the path");
1977 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1980 if (strcasecmp(object_path, "/org/bluez/hci0") == 0) {
1981 BT_DBG("Adapter added [%s] \n", object_path);
1982 BT_DBG("BlueZ is Activated and flag need to be reset");
1983 BT_DBG("Send enabled to application\n");
1985 ret = __bluetooth_telephony_register();
1986 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1987 BT_DBG("__bluetooth_telephony_register failed\n");
1992 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1995 static int __bt_telephony_get_object_path(DBusMessage *msg, char **path)
1997 DBusMessageIter item_iter;
1998 dbus_message_iter_init(msg, &item_iter);
2001 if (dbus_message_iter_get_arg_type(&item_iter)
2002 != DBUS_TYPE_OBJECT_PATH) {
2003 BT_ERR("This is bad format dbus\n");
2004 return BLUETOOTH_ERROR_INTERNAL;
2007 dbus_message_iter_get_basic(&item_iter, path);
2010 return BLUETOOTH_ERROR_INTERNAL;
2013 return BLUETOOTH_ERROR_NONE;
2016 static void _bt_convert_device_path_to_address(const char *device_path,
2017 char *device_address)
2019 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
2023 ret_if(device_path == NULL);
2024 ret_if(device_address == NULL);
2026 dev_addr = strstr(device_path, "dev_");
2027 if (dev_addr != NULL) {
2030 g_strlcpy(address, dev_addr, sizeof(address));
2032 while ((pos = strchr(address, '_')) != NULL) {
2035 g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE);
2040 static char *__bt_get_default_adapter_path(DBusMessageIter *msg_iter)
2042 char *object_path = NULL;
2043 DBusMessageIter value_iter;
2046 /* Parse the signature: oa{sa{sv}}} */
2047 retv_if(dbus_message_iter_get_arg_type(msg_iter) !=
2048 DBUS_TYPE_OBJECT_PATH, NULL);
2050 dbus_message_iter_get_basic(msg_iter, &object_path);
2052 retv_if(dbus_message_iter_next(msg_iter) == FALSE, NULL);
2053 retv_if(dbus_message_iter_get_arg_type(msg_iter) !=
2054 DBUS_TYPE_ARRAY, NULL);
2056 dbus_message_iter_recurse(msg_iter, &value_iter);
2058 while (dbus_message_iter_get_arg_type(&value_iter) ==
2059 DBUS_TYPE_DICT_ENTRY) {
2060 char *interface_name = NULL;
2061 DBusMessageIter interface_iter;
2063 dbus_message_iter_recurse(&value_iter, &interface_iter);
2065 retv_if(dbus_message_iter_get_arg_type(&interface_iter) !=
2066 DBUS_TYPE_STRING, NULL);
2068 dbus_message_iter_get_basic(&interface_iter, &interface_name);
2070 if (g_strcmp0(interface_name, "org.bluez.Adapter1") == 0) {
2071 return g_strdup(object_path);
2073 dbus_message_iter_next(&value_iter);
2075 BT_DBG("Adapter Not Found");