Tizen 2.1 base
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-telephony.c
1 /*
2  * bluetooth-frwk
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <dbus/dbus.h>
24 #include <dbus/dbus-glib-bindings.h>
25 #include <unistd.h>
26 #include <vconf.h>
27 #include <vconf-keys.h>
28
29 #include "bt-common.h"
30 #include "bluetooth-telephony-api.h"
31 #include "marshal.h"
32
33 typedef struct {
34         DBusGConnection *conn;
35         DBusGProxy *proxy;
36         DBusGProxy *dbus_proxy;
37         DBusGProxy *manager_proxy;
38 } telephony_dbus_info_t;
39
40 typedef struct {
41         bt_telephony_func_ptr cb;
42         unsigned int call_count;
43         char *obj_path;
44         char address[BT_ADDRESS_STR_LEN];
45         char call_path[BT_AUDIO_CALL_PATH_LEN];
46         bluetooth_headset_state_t headset_state;
47         void *user_data;
48 } bt_telephony_info_t;
49
50 #define BLUETOOTH_TELEPHONY_ERROR (__bluetooth_telephony_error_quark())
51
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"
57
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"
61
62 #define CSD_CALL_APP_PATH "/org/tizen/csd/%d"
63 #define HFP_NREC_STATUS_CHANGE "NrecStatusChanged"
64
65 #define BT_TELEPHONY_CHECK_ENABLED() \
66         do { \
67                 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) \
68                 { \
69                         BT_ERR("BT is not enabled"); \
70                         return BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED; \
71                 } \
72         } while (0)
73
74 static gboolean is_initialized = FALSE;
75 #define BT_TELEPHONY_CHECK_INITIALIZED() \
76         do { \
77                 if (is_initialized == FALSE) \
78                 { \
79                         BT_ERR("Bluetooth telephony not initilized"); \
80                         return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED; \
81                 } \
82         } while (0)
83
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))
88
89 #define BLUETOOTH_TELEPHONY_METHOD_IS_OBJECT(obj) \
90                 (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
91                 BLUETOOTH_TELEPHONY_METHOD))
92
93 #define BLUETOOTH_TELEPHONY_METHOD_CLASS(class) \
94                 (G_TYPE_CHECK_CLASS_CAST((class), \
95                 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))
96
97 #define BLUETOOTH_TELEPHONY_METHOD_GET_AGENT_CLASS(obj) \
98                 (G_TYPE_INSTANCE_GET_CLASS((obj), \
99                 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))
100
101 #define BLUETOOTH_TELEPHONY_METHOD_IS_AGENT_CLASS(class) \
102                 (G_TYPE_CHECK_CLASS_TYPE((class), BLUETOOTH_TELEPHONY_METHOD))
103
104 #define BLUETOOTH_TELEPHONY_METHOD_AGENT_GET_PRIVATE(obj) \
105                 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
106                 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodPrivate))
107
108 typedef struct _BluetoothTelephonyMethod BluetoothTelephonyMethod;
109 typedef struct _BluetoothTelephonyMethodClass BluetoothTelephonyMethodClass;
110
111 struct _BluetoothTelephonyMethod {
112         GObject parent;
113 };
114
115 struct _BluetoothTelephonyMethodClass {
116         GObjectClass parent_class;
117 };
118
119 BluetoothTelephonyMethod *bluetooth_telephony_method_new(void);
120 GType bluetooth_telephony_method_get_type(void);
121
122 G_DEFINE_TYPE(BluetoothTelephonyMethod, bluetooth_telephony_method, G_TYPE_OBJECT)
123
124
125 static gboolean bluetooth_telephony_method_answer(BluetoothTelephonyMethod *object,
126                                 guint callid,
127                                 DBusGMethodInvocation *context);
128
129 static gboolean bluetooth_telephony_method_release(
130                                 BluetoothTelephonyMethod *object, guint callid,
131                                 DBusGMethodInvocation *context);
132
133 static gboolean bluetooth_telephony_method_reject(BluetoothTelephonyMethod  *object,
134                                 guint callid, DBusGMethodInvocation *context);
135
136 static gboolean bluetooth_telephony_method_threeway(
137                                 BluetoothTelephonyMethod *object, guint value,
138                                 DBusGMethodInvocation *context);
139
140 static gboolean bluetooth_telephony_method_send_dtmf(
141                                 BluetoothTelephonyMethod *object,
142                                 gchar *dtmf, DBusGMethodInvocation *context);
143
144 #include "bt-telephony-glue.h"
145
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;
150
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);
162
163 static DBusHandlerResult __bluetooth_telephony_event_filter(
164                                                 DBusConnection *conn,
165                                                 DBusMessage *msg, void *data);
166
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,
174                                                         char *path);
175 static int __bluetooth_telephony_get_connected_device(void);
176 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void);
177
178 /*Function Definition*/
179 static int __bt_telephony_get_error(const char *error_message)
180 {
181         if (error_message == NULL) {
182                 BT_DBG("Error message NULL\n");
183                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
184         }
185
186         BT_DBG("Error message = %s \n", error_message);
187         if (g_strcmp0(error_message, "NotAvailable") == 0)
188                 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
189         else if (g_strcmp0(error_message, "NotConnected") == 0)
190                 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
191         else if (g_strcmp0(error_message, "InProgress") == 0)
192                 return BLUETOOTH_TELEPHONY_ERROR_BUSY;
193         else if (g_strcmp0(error_message, "InvalidArguments") == 0)
194                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
195         else if (g_strcmp0(error_message, "AlreadyExists") == 0)
196                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST;
197         else if (g_strcmp0(error_message, "Already Connected") == 0)
198                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
199         else if (g_strcmp0(error_message, "No memory") == 0)
200                 return BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY;
201         else if (g_strcmp0(error_message, "I/O error") == 0)
202                 return BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR;
203         else if (g_strcmp0(error_message, "Operation currently not available") == 0)
204                 return BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE;
205         else
206                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
207 }
208
209 static void __bt_telephony_event_cb(int event, int result, void *param_data)
210 {
211         telephony_event_param_t bt_event = { 0, };
212
213         bt_event.event = event;
214         bt_event.result = result;
215         bt_event.param_data = param_data;
216
217         ret_if(telephony_info.cb == NULL);
218         telephony_info.cb(bt_event.event, &bt_event, telephony_info.user_data);
219         return;
220 }
221
222 static GQuark __bluetooth_telephony_error_quark(void)
223 {
224         static GQuark quark = 0;
225
226         quark = g_quark_from_static_string("telephony");
227
228         return quark;
229 }
230
231 static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path,
232                         const char *interface, const char *method, DBusError *err,  int type, ...)
233 {
234         DBusMessage *msg;
235         DBusMessage *reply;
236         va_list args;
237
238         BT_DBG("+");
239
240         msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
241                         path, interface, method);
242         if (!msg) {
243                 BT_ERR("Unable to allocate new D-Bus %s message \n", method);
244                 return NULL;
245         }
246
247         va_start(args, type);
248
249         if (!dbus_message_append_args_valist(msg, type, args)) {
250                 dbus_message_unref(msg);
251                 va_end(args);
252                 return NULL;
253         }
254
255         va_end(args);
256
257         dbus_error_init(err);
258
259         reply = dbus_connection_send_with_reply_and_block(
260                 dbus_g_connection_get_connection(telephony_dbus_info.conn),
261                 msg, -1, err);
262         dbus_message_unref(msg);
263
264         BT_DBG("-");
265         return reply;
266 }
267
268 static int __bluetooth_telephony_send_call_status(
269                         bt_telephony_call_status_t call_status,
270                         unsigned int call_id)
271 {
272         DBusMessage *reply;
273         DBusError err;
274         char *path = g_strdup(telephony_info.call_path);
275         int ret;
276
277         BT_DBG("+");
278
279         reply = __bluetooth_telephony_dbus_method_send(
280                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
281                         "ChangeCallStatus", &err, DBUS_TYPE_STRING, &path,
282                         DBUS_TYPE_INT32, &call_status,
283                         DBUS_TYPE_INT32, &call_id, DBUS_TYPE_INVALID);
284         g_free(path);
285
286         if (!reply) {
287                 BT_ERR("Error returned in method call\n");
288                 if (dbus_error_is_set(&err)) {
289                         ret = __bt_telephony_get_error(err.message);
290                         dbus_error_free(&err);
291                         return ret;
292                 }
293                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
294         }
295
296         dbus_message_unref(reply);
297
298         return BLUETOOTH_TELEPHONY_ERROR_NONE;
299 }
300
301 static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
302                                         const char *err_msg)
303 {
304         return g_error_new(BLUETOOTH_TELEPHONY_ERROR, error, err_msg, NULL);
305 }
306
307 static void bluetooth_telephony_method_init(BluetoothTelephonyMethod *object)
308 {
309         BT_DBG("+");
310         BT_DBG("agent %p\n", object);
311         BT_DBG("-");
312 }
313
314 static void __bluetooth_telephony_method_finalize(
315                                         BluetoothTelephonyMethod *object)
316 {
317         BT_DBG("+");
318         G_OBJECT_CLASS(bluetooth_telephony_method_parent_class)->finalize((
319                                                         GObject *)object);
320         BT_DBG("-");
321 }
322
323 static BluetoothTelephonyMethod *__bluetooth_telephony_method_new(void)
324 {
325         BluetoothTelephonyMethod *obj;
326
327         BT_DBG("+");
328         obj = g_object_new(BLUETOOTH_TELEPHONY_METHOD, NULL);
329         BT_DBG("-");
330
331         return obj;
332 }
333
334 static void bluetooth_telephony_method_class_init(
335                                         BluetoothTelephonyMethodClass *klass)
336 {
337         GObjectClass *object_class = NULL;
338         BT_DBG("+");
339
340         object_class = G_OBJECT_CLASS(klass);
341         object_class->finalize = (void *)__bluetooth_telephony_method_finalize;
342
343         /*Registration of the Framework methods */
344         dbus_g_object_type_install_info(BLUETOOTH_TELEPHONY_METHOD,
345                         &dbus_glib_bluetooth_telephony_method_object_info);
346         BT_DBG("-");
347         return;
348 }
349
350 static gboolean bluetooth_telephony_method_answer(
351                                 BluetoothTelephonyMethod *object,
352                                 guint callid, DBusGMethodInvocation *context)
353 {
354         telephony_event_callid_t call_data = { 0, };
355
356         BT_DBG("+");
357         BT_DBG("call_id = [%d]", callid);
358
359         call_data.callid = callid;
360
361         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL,
362                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
363                                         (void *)&call_data);
364
365         dbus_g_method_return(context);
366         BT_DBG("-");
367         return TRUE;
368 }
369
370 static gboolean bluetooth_telephony_method_release(
371                                 BluetoothTelephonyMethod *object,
372                                 guint callid, DBusGMethodInvocation *context)
373 {
374         telephony_event_callid_t call_data = { 0, };
375
376         BT_DBG("+");
377         BT_DBG("call_id = [%d]\n", callid);
378
379         call_data.callid = callid;
380
381         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL,
382                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
383                                         (void *)&call_data);
384
385         dbus_g_method_return(context);
386         BT_DBG("-");
387         return TRUE;
388
389 }
390
391 static gboolean bluetooth_telephony_method_reject(
392                                 BluetoothTelephonyMethod *object,
393                                 guint callid, DBusGMethodInvocation *context)
394 {
395         telephony_event_callid_t call_data = { 0, };
396
397         BT_DBG("+");
398         BT_DBG("call_id = [%d]", callid);
399
400         call_data.callid = callid;
401
402         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_REJECT_CALL,
403                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
404                                         (void  *)&call_data);
405
406         dbus_g_method_return(context);
407         BT_DBG("-");
408         return TRUE;
409 }
410
411 static gboolean bluetooth_telephony_method_threeway(
412                                 BluetoothTelephonyMethod *object,
413                                 guint value, DBusGMethodInvocation *context)
414 {
415         int event = 0;
416         GError *err;
417
418         BT_DBG("+");
419         BT_DBG("chld value  = [%d]", value);
420
421         switch (value) {
422         case 0:
423                 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL;
424                 break;
425         case 1:
426                 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL;
427                 break;
428         case 2:
429                 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL;
430                 break;
431         case 3:
432                 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL;
433                 break;
434         default:
435                 BT_ERR("Invalid CHLD command");
436                 err = __bluetooth_telephony_error(
437                         BLUETOOTH_TELEPHONY_ERROR_INVALID_CHLD_INDEX,
438                         "Invalid chld command");
439                 dbus_g_method_return_error(context, err);
440                 g_error_free(err);
441                 return FALSE;
442         }
443
444         BT_DBG("event  = [%d]", event);
445
446         __bt_telephony_event_cb(event,
447                         BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
448         dbus_g_method_return(context);
449         BT_DBG("-");
450         return TRUE;
451 }
452
453 static gboolean bluetooth_telephony_method_send_dtmf(
454                                 BluetoothTelephonyMethod *object,
455                                 gchar *dtmf, DBusGMethodInvocation *context)
456 {
457         telephony_event_dtmf_t call_data = { 0, };
458         GError *err;
459
460         BT_DBG("+");
461
462         if (dtmf == NULL) {
463                 BT_DBG("Number dial failed\n");
464                 err = __bluetooth_telephony_error(
465                                 BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF,
466                                 "Invalid dtmf");
467                 dbus_g_method_return_error(context, err);
468                 g_error_free(err);
469                 return FALSE;
470         }
471
472         BT_DBG("Dtmf = %s \n", dtmf);
473
474         call_data.dtmf = g_strdup(dtmf);
475
476         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF,
477                 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&call_data);
478
479         dbus_g_method_return(context);
480         g_free(call_data.dtmf);
481         BT_DBG("-");
482         return TRUE;
483 }
484
485 static void __bluetooth_handle_nrec_status_change(DBusMessage *msg)
486 {
487         gboolean status = FALSE;
488
489         if (!dbus_message_get_args(msg, NULL,
490                                 DBUS_TYPE_BOOLEAN, &status,
491                                 DBUS_TYPE_INVALID)) {
492                 BT_DBG("Error Getting parameters\n");
493                 return;
494         }
495         BT_DBG("NREC status = %d\n", status);
496
497         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED,
498                 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&status);
499
500 }
501
502 static DBusHandlerResult __bluetooth_telephony_event_filter(
503                                                 DBusConnection *conn,
504                                                 DBusMessage *msg, void *data)
505 {
506         const char *path = dbus_message_get_path(msg);
507         char *dev_addr = NULL;
508         DBusMessageIter item_iter;
509         DBusMessageIter value_iter;
510         const char *property;
511
512         /* Check NREC status change Signal*/
513         if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
514                                 HFP_NREC_STATUS_CHANGE)) {
515                 __bluetooth_handle_nrec_status_change(msg);
516                 return DBUS_HANDLER_RESULT_HANDLED;
517         }
518
519         if (!dbus_message_has_interface(msg, BLUEZ_HEADSET_INTERFACE))
520                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
521
522         if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
523                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
524
525         dbus_message_iter_init(msg, &item_iter);
526         if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
527                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
528         }
529
530         dbus_message_iter_get_basic(&item_iter, &property);
531
532         if (property == NULL)
533                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
534
535         BT_DBG("Property (%s)\n", property);
536
537         if (g_strcmp0(property, "State") == 0) {
538                 char *state = NULL;
539                 dbus_message_iter_next(&item_iter);
540                 dbus_message_iter_recurse(&item_iter, &value_iter);
541                 dbus_message_iter_get_basic(&value_iter, &state);
542                 if (NULL == state) {
543                         BT_ERR("State is null\n");
544                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
545                 }
546                 BT_DBG("State %s\n", state);
547
548                 if (g_strcmp0(state, "connected") == 0) {
549                         telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
550                 } else if (g_strcmp0(state, "playing") == 0) {
551                         telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
552                 } else if (g_strcmp0(state, "disconnected") == 0) {
553                         /* Headset state: playing -> disconnected */
554                         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) {
555                                 if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, FALSE)) {
556                                         BT_DBG("SVCONFKEY_BT_HEADSET_SCO - Set to FALSE\n");
557                                 } else {
558                                          BT_DBG("vconf_set_bool - Failed\n");
559                                 }
560
561                                 __bt_telephony_event_cb(
562                                          BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
563                                          BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
564                         }
565
566                         telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
567                 }
568
569                 return DBUS_HANDLER_RESULT_HANDLED;
570         }
571
572         if (g_strcmp0(property, "Connected") == 0) {
573                 gboolean connected = FALSE;
574                 dbus_message_iter_next(&item_iter);
575                 dbus_message_iter_recurse(&item_iter, &value_iter);
576                 dbus_message_iter_get_basic(&value_iter, &connected);
577                 BT_DBG("Connected %d\n", connected);
578
579                 if (connected) {
580                         /*Get device address*/
581                         if (path != NULL)
582                                 dev_addr = strstr(path, "dev_");
583
584                         if (dev_addr != NULL) {
585                                 dev_addr += 4;
586                                 g_strlcpy(telephony_info.address,
587                                         dev_addr,
588                                         sizeof(telephony_info.address));
589                                 g_strdelimit(telephony_info.address, "_", ':');
590                                 BT_DBG("address is %s",
591                                         telephony_info.address);
592
593                                 telephony_info.headset_state =
594                                                 BLUETOOTH_STATE_CONNECTED;
595
596                                 if (telephony_dbus_info.proxy != NULL) {
597                                         g_object_unref(telephony_dbus_info.proxy);
598                                         telephony_dbus_info.proxy = NULL;
599                                 }
600
601                                 telephony_dbus_info.proxy =
602                                                 __bluetooth_telephony_get_connected_device_proxy();
603
604                                 BT_DBG("Headset Connected");
605
606                                  __bt_telephony_event_cb(
607                                                 BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED,
608                                                 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
609                         }
610                 } else { /*Device disconnected*/
611                         memset(telephony_info.address, 0x00,
612                                         sizeof(telephony_info.address));
613                         telephony_info.headset_state =
614                                                 BLUETOOTH_STATE_DISCONNETED;
615
616                         if (telephony_dbus_info.proxy != NULL) {
617                                 g_object_unref(telephony_dbus_info.proxy);
618                                 telephony_dbus_info.proxy = NULL;
619                         }
620
621                         BT_DBG("Headset Disconnected");
622
623                          __bt_telephony_event_cb(
624                                         BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED,
625                                         BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
626                 }
627                 return DBUS_HANDLER_RESULT_HANDLED;
628         }
629
630         if (g_strcmp0(property, "SpeakerGain") == 0) {
631                 unsigned int spkr_gain;
632                 guint16 gain;
633                 dbus_message_iter_next(&item_iter);
634                 dbus_message_iter_recurse(&item_iter, &value_iter);
635                 dbus_message_iter_get_basic(&value_iter, &gain);
636
637                 spkr_gain = (unsigned int)gain;
638                 BT_DBG("spk_gain[%d]\n", spkr_gain);
639
640                 __bt_telephony_event_cb(
641                                         BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN,
642                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
643                                         (void *)&spkr_gain);
644
645                 return DBUS_HANDLER_RESULT_HANDLED;
646         }
647
648         if (g_strcmp0(property, "MicrophoneGain") == 0) {
649                 unsigned int mic_gain;
650                 guint16 gain;
651                 dbus_message_iter_next(&item_iter);
652                 dbus_message_iter_recurse(&item_iter, &value_iter);
653                 dbus_message_iter_get_basic(&value_iter, &gain);
654
655                 mic_gain = (unsigned int)gain;
656                 BT_DBG("mic_gain[%d]\n", mic_gain);
657
658                 __bt_telephony_event_cb(
659                                         BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN,
660                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
661                                         (void *)&mic_gain);
662
663                 return DBUS_HANDLER_RESULT_HANDLED;
664         }
665
666         if (g_strcmp0(property, "Playing") == 0) {
667                 gboolean audio_sink_playing = FALSE;
668                 dbus_message_iter_next(&item_iter);
669                 dbus_message_iter_recurse(&item_iter, &value_iter);
670                 dbus_message_iter_get_basic(&value_iter, &audio_sink_playing);
671
672                 if (audio_sink_playing) {
673                         if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, TRUE)) {
674                                 BT_DBG("SVCONFKEY_BT_HEADSET_SCO -"
675                                         "Set to TRUE\n");
676                         } else {
677                                 BT_DBG("vconf_set_bool - Failed\n");
678                         }
679                         telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
680                          __bt_telephony_event_cb(
681                                 BLUETOOTH_EVENT_TELEPHONY_AUDIO_CONNECTED,
682                                 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
683                 } else {
684                         if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, FALSE)) {
685                                 BT_DBG("SVCONFKEY_BT_HEADSET_SCO -"
686                                                 "Set to FALSE\n");
687                         } else {
688                                 BT_DBG("vconf_set_bool - Failed\n");
689                         }
690                         telephony_info.headset_state =
691                                                 BLUETOOTH_STATE_CONNECTED;
692                         __bt_telephony_event_cb(
693                                 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
694                                 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
695                 }
696
697                 return DBUS_HANDLER_RESULT_HANDLED;
698         }
699         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
700 }
701
702 static void __bluetooth_telephony_adapter_added_cb(DBusGProxy *manager_proxy,
703                                 const char *adapter_path, gpointer user_data)
704 {
705         int ret;
706         DBusError dbus_error;
707         DBusConnection *conn;
708
709         BT_DBG("Adapter added [%s] \n", adapter_path);
710
711         if (strstr(adapter_path, "hci0")) {
712                 BT_DBG("BlueZ is Activated and flag need to be reset");
713                 BT_DBG("Send enabled to application\n");
714
715                 ret = __bluetooth_telephony_register();
716                 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
717                         BT_DBG("__bluetooth_telephony_register failed\n");
718                         return;
719                 }
720
721                 dbus_error_init(&dbus_error);
722                 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
723                 dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
724                                 NULL, NULL);
725
726                 dbus_bus_add_match(conn,
727                                 "type='signal',interface='" BLUEZ_HEADSET_INTERFACE
728                                 "',member='PropertyChanged'", &dbus_error);
729                 dbus_bus_add_match(conn,
730                         "type='signal',interface='"HFP_AGENT_SERVICE
731                         "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error);
732
733                 if (dbus_error_is_set(&dbus_error)) {
734                         BT_DBG("Fail to add dbus filter signal\n");
735                         dbus_error_free(&dbus_error);
736                         __bluetooth_telephony_unregister();
737                         dbus_connection_remove_filter(dbus_g_connection_get_connection(
738                                         telephony_dbus_info.conn),
739                                         __bluetooth_telephony_event_filter, NULL);
740                 }
741         }
742 }
743
744 static int __bluetooth_telephony_proxy_init(void)
745 {
746         BT_DBG("+");
747
748         object = (GObject *)__bluetooth_telephony_method_new();
749
750         if (NULL == object)
751                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
752
753         BT_DBG("telephony_object = %x", object);
754
755         dbus_g_connection_register_g_object(telephony_dbus_info.conn,
756                         telephony_info.call_path, G_OBJECT(object));
757
758         BT_DBG("-");
759         return BLUETOOTH_TELEPHONY_ERROR_NONE;
760 }
761
762 static void __bluetooth_telephony_proxy_deinit(void)
763 {
764         BT_DBG("+");
765
766         dbus_g_connection_unregister_g_object(telephony_dbus_info.conn,
767                                 G_OBJECT(object));
768
769         g_object_unref(object);
770         object = NULL;
771
772         BT_DBG("-");
773         return;
774 }
775
776 static int __bluetooth_telephony_register(void)
777 {
778         DBusMessage *reply;
779         DBusError err;
780         char *path = g_strdup(telephony_info.call_path);
781         int ret;
782
783         BT_DBG("+");
784
785         reply =  __bluetooth_telephony_dbus_method_send(
786                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
787                         "RegisterApplication", &err, DBUS_TYPE_STRING, &path,
788                         DBUS_TYPE_INVALID);
789
790         g_free(path);
791         if (!reply) {
792                 BT_ERR("Error returned in method call\n");
793                 if (dbus_error_is_set(&err)) {
794                         ret = __bt_telephony_get_error(err.message);
795                         dbus_error_free(&err);
796                         return ret;
797                 }
798                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
799         }
800
801         dbus_message_unref(reply);
802         BT_DBG("-");
803         return BLUETOOTH_TELEPHONY_ERROR_NONE;
804 }
805
806 static  int __bluetooth_telephony_unregister(void)
807 {
808         DBusMessage *reply;
809         DBusError err;
810         char *path = g_strdup(telephony_info.call_path);
811         int ret;
812
813         BT_DBG("+");
814
815         reply = __bluetooth_telephony_dbus_method_send(
816                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
817                         "UnregisterApplication", &err, DBUS_TYPE_STRING, &path,
818                         DBUS_TYPE_INVALID);
819
820         g_free(path);
821         if (!reply) {
822                 BT_ERR("Error returned in method call\n");
823                 if (dbus_error_is_set(&err)) {
824                         ret = __bt_telephony_get_error(err.message);
825                         dbus_error_free(&err);
826                         return ret;
827                 }
828                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
829         }
830
831         dbus_message_unref(reply);
832         BT_DBG("+");
833         return BLUETOOTH_TELEPHONY_ERROR_NONE;
834 }
835
836 static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
837                                                         char *path)
838 {
839         GError *err = NULL;
840         char *adapter_path = NULL;
841
842         BT_DBG("+");
843
844         if (!dbus_g_proxy_call(telephony_dbus_info.manager_proxy,
845                                 "DefaultAdapter", &err, G_TYPE_INVALID,
846                                 DBUS_TYPE_G_OBJECT_PATH, &adapter_path,
847                                 G_TYPE_INVALID)) {
848                 if (err != NULL) {
849                         BT_ERR("Getting DefaultAdapter failed: [%s]",
850                                                         err->message);
851                         g_error_free(err);
852                 }
853                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
854         }
855
856         if (adapter_path == NULL) {
857                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
858         }
859
860         if (strlen(adapter_path) >= BT_ADAPTER_PATH_LEN) {
861                 BT_ERR("Path too long.\n");
862                 g_free(adapter_path);
863                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
864         }
865
866         BT_DBG("path = %s", adapter_path);
867         g_strlcpy(path, adapter_path, BT_ADAPTER_PATH_LEN);
868         g_free(adapter_path);
869         BT_DBG("-");
870         return BLUETOOTH_TELEPHONY_ERROR_NONE;
871 }
872
873 static int __bluetooth_telephony_get_connected_device(void)
874 {
875         DBusGProxy *list_proxy = NULL;
876         DBusGProxy *device_proxy = NULL;
877         GPtrArray *gp_array = NULL;
878         GError *error = NULL;
879         gchar *gp_path = NULL;
880         GHashTable *list_hash;
881         GHashTable *device_hash;
882         GValue *value = {0};
883         gboolean playing = FALSE;
884         gboolean connected = FALSE;
885         const gchar *address;
886         char object_path[BT_ADAPTER_PATH_LEN] = {0};
887         int i = 0;
888         DBusGProxy *proxy = NULL;
889
890         BT_DBG("+");
891
892         /*Get default adapter path*/
893         if (__bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
894                         object_path) < 0)
895                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
896         /*Get List of All devices*/
897         list_proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
898                                                 BLUEZ_SERVICE_NAME, object_path,
899                                                 BLUEZ_ADAPTER_INTERFACE);
900
901         if (list_proxy == NULL)
902                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
903
904         dbus_g_proxy_call(list_proxy, "ListDevices", &error, G_TYPE_INVALID,
905                                 dbus_g_type_get_collection("GPtrArray",
906                                 DBUS_TYPE_G_OBJECT_PATH),
907                                 &gp_array, G_TYPE_INVALID);
908
909         if (error != NULL) {
910                 g_error_free(error);
911                 goto done;
912         }
913
914         if (gp_array == NULL)
915                 goto done;
916
917         /*Check for headset devices*/
918         for (i = 0; i < gp_array->len; i++) {
919                 list_hash = NULL;
920                 device_hash = NULL;
921                 gp_path = g_ptr_array_index(gp_array, i);
922
923                 if (gp_path == NULL)
924                         goto done;
925
926                 proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
927                                                 BLUEZ_SERVICE_NAME, gp_path,
928                                                 BLUEZ_DEVICE_INTERFACE);
929
930                 if (proxy == NULL)
931                         goto done;
932
933                 dbus_g_proxy_call(proxy, "GetProperties", NULL,
934                                 G_TYPE_INVALID, dbus_g_type_get_map(
935                                 "GHashTable", G_TYPE_STRING,
936                                 G_TYPE_VALUE), &list_hash, G_TYPE_INVALID);
937
938                 if (list_hash == NULL)
939                         goto done;
940
941                 /*Check for Connection*/
942                 device_proxy = dbus_g_proxy_new_for_name(
943                                 telephony_dbus_info.conn,
944                                 BLUEZ_SERVICE_NAME, gp_path,
945                                 BLUEZ_HEADSET_INTERFACE);
946
947                 if (device_proxy == NULL) {
948                         g_hash_table_destroy(list_hash);
949                         goto done;
950                 }
951
952                 dbus_g_proxy_call(device_proxy, "GetProperties",
953                                 &error, G_TYPE_INVALID,
954                                 dbus_g_type_get_map("GHashTable",
955                                 G_TYPE_STRING, G_TYPE_VALUE),
956                                 &device_hash, G_TYPE_INVALID);
957
958                 if (error == NULL) {
959                         value = g_hash_table_lookup(device_hash,
960                                         "Connected");
961                         connected = value ? g_value_get_boolean(
962                                         value) : FALSE;
963                         if (connected) {
964                                 value = g_hash_table_lookup(list_hash,
965                                                                 "Address");
966                                 address = value ? g_value_get_string(
967                                                         value) : NULL;
968                                 g_strlcpy(telephony_info.address, address,
969                                                 sizeof(telephony_info.address));
970                                 value = g_hash_table_lookup(device_hash,
971                                                                 "Playing");
972                                 playing = value ? g_value_get_boolean(
973                                                         value) : FALSE;
974                                 if (playing)
975                                         telephony_info.headset_state =
976                                                 BLUETOOTH_STATE_PLAYING;
977                                 else
978                                         telephony_info.headset_state =
979                                                 BLUETOOTH_STATE_CONNECTED;
980
981                                 g_hash_table_destroy(device_hash);
982                                 g_hash_table_destroy(list_hash);
983                                 goto done;
984                         }
985                         g_hash_table_destroy(device_hash);
986                 } else {
987                         g_error_free(error);
988                 }
989
990                 g_hash_table_destroy(list_hash);
991                 g_object_unref(proxy);
992                 proxy = NULL;
993                 g_free(gp_path);
994                 gp_path = NULL;
995         }
996 done:
997         if (list_proxy)
998                 g_object_unref(list_proxy);
999         if (device_proxy)
1000                 g_object_unref(device_proxy);
1001         if (proxy)
1002                 g_object_unref(proxy);
1003         g_free(gp_path);
1004         g_ptr_array_free(gp_array, TRUE);
1005         BT_DBG("-");
1006         return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1007 }
1008
1009 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1010 {
1011         DBusGProxy *proxy = NULL;
1012         char object_path[BT_ADAPTER_PATH_LEN] = {0};
1013         GError *error = NULL;
1014         DBusGProxy *default_proxy;
1015
1016         BT_DBG("+");
1017
1018         /*Get default adapter path*/
1019         if (__bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
1020                         object_path) < 0)
1021                 return NULL;
1022
1023         /*Get List of All devices*/
1024         default_proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
1025                                                 BLUEZ_SERVICE_NAME, object_path,
1026                                                 BLUEZ_ADAPTER_INTERFACE);
1027
1028         if (default_proxy == NULL)
1029                 return NULL;
1030
1031         if (strlen(telephony_info.address) == 0)
1032                 __bluetooth_telephony_get_connected_device();
1033
1034         if (strlen(telephony_info.address) == 0) {
1035                 g_object_unref(default_proxy);
1036                 return NULL;
1037         }
1038
1039         if (telephony_info.obj_path) {
1040                 g_free(telephony_info.obj_path);
1041                 telephony_info.obj_path = NULL;
1042         }
1043
1044         dbus_g_proxy_call(default_proxy, "FindDevice", &error,
1045                         G_TYPE_STRING, telephony_info.address,
1046                         G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH,
1047                         &telephony_info.obj_path,
1048                         G_TYPE_INVALID);
1049         if (error != NULL) {
1050                 BT_ERR("dbus_g_proxy_call Failed!\n");
1051                 g_error_free(error);
1052                 g_object_unref(default_proxy);
1053                 return NULL;
1054         }
1055
1056         if (telephony_info.obj_path == NULL) {
1057                 g_object_unref(default_proxy);
1058                 return NULL;
1059         }
1060
1061         proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
1062                         BLUEZ_SERVICE_NAME, telephony_info.obj_path,
1063                         BLUEZ_HEADSET_INTERFACE);
1064
1065         g_object_unref(default_proxy);
1066
1067         return proxy;
1068 }
1069
1070 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1071                                                         void  *user_data)
1072 {
1073         DBusError dbus_error;
1074         DBusConnection *conn;
1075         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1076         GError *error = NULL;
1077         char object_path[BT_ADAPTER_PATH_LEN] = {0};
1078         BT_DBG("+");
1079
1080         g_type_init();
1081
1082         if (is_initialized == TRUE) {
1083                 BT_ERR("Bluetooth telephony already initilized");
1084                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_INITIALIZED;
1085         }
1086
1087         is_initialized = TRUE;
1088
1089         telephony_dbus_info.conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
1090         if (!telephony_dbus_info.conn) {
1091                 if (NULL != error) {
1092                         BT_ERR("dbus_g_bus_get() failed:[%d:%s]\n",
1093                                         error->code, error->message);
1094                         g_error_free(error);
1095                 }
1096                 is_initialized = FALSE;
1097                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1098         }
1099
1100         /* Call Path */
1101         snprintf(telephony_info.call_path, sizeof(telephony_info.call_path),
1102                                         CSD_CALL_APP_PATH, getpid());
1103         BT_DBG("Call Path = %s", telephony_info.call_path);
1104         memset(telephony_info.address, 0x00, sizeof(telephony_info.address));
1105
1106         if (__bluetooth_telephony_proxy_init()) {
1107                 BT_ERR("__bluetooth_telephony_proxy_init failed\n");
1108                 dbus_g_connection_unref(telephony_dbus_info.conn);
1109                 telephony_dbus_info.conn = NULL;
1110                 is_initialized = FALSE;
1111                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1112         }
1113
1114         telephony_dbus_info.manager_proxy = dbus_g_proxy_new_for_name(
1115                                                 telephony_dbus_info.conn,
1116                                                 BLUEZ_SERVICE_NAME,
1117                                                 "/", BLUEZ_MANAGER_INTERFACE);
1118
1119         if (telephony_dbus_info.manager_proxy == NULL) {
1120                 BT_ERR("Could not create a manager proxy\n");
1121                 __bluetooth_telephony_proxy_deinit();
1122                 dbus_g_connection_unref(telephony_dbus_info.conn);
1123                 telephony_dbus_info.conn = NULL;
1124                 is_initialized = FALSE;
1125                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1126         }
1127
1128         telephony_dbus_info.dbus_proxy = dbus_g_proxy_new_for_name(
1129                         telephony_dbus_info.conn, DBUS_SERVICE_DBUS,
1130                         DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
1131
1132         if (NULL == telephony_dbus_info.dbus_proxy) {
1133                 __bluetooth_telephony_proxy_deinit();
1134                 dbus_g_connection_unref(telephony_dbus_info.conn);
1135                 telephony_dbus_info.conn = NULL;
1136                 g_object_unref(telephony_dbus_info.manager_proxy);
1137                 telephony_dbus_info.manager_proxy = NULL;
1138                 is_initialized = FALSE;
1139                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1140         }
1141
1142         /*Add Signal callback for BT enabled*/
1143         dbus_g_proxy_add_signal(telephony_dbus_info.manager_proxy,
1144                                 "AdapterAdded",
1145                                 DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
1146         dbus_g_proxy_connect_signal(telephony_dbus_info.manager_proxy,
1147                         "AdapterAdded",
1148                         G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
1149                         NULL, NULL);
1150
1151         /*Callback and user applicaton data*/
1152         telephony_info.cb = cb;
1153         telephony_info.user_data = user_data;
1154
1155         dbus_error_init(&dbus_error);
1156         conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1157         dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
1158                                 NULL, NULL);
1159
1160         dbus_bus_add_match(conn,
1161                         "type='signal',interface='" BLUEZ_HEADSET_INTERFACE
1162                         "',member='PropertyChanged'", &dbus_error);
1163         dbus_bus_add_match(conn,
1164                         "type='signal',interface='"HFP_AGENT_SERVICE
1165                         "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error);
1166
1167         if (dbus_error_is_set(&dbus_error)) {
1168                 BT_ERR("Fail to add dbus filter signal\n");
1169                 dbus_error_free(&dbus_error);
1170                 dbus_connection_remove_filter(dbus_g_connection_get_connection(
1171                                 telephony_dbus_info.conn),
1172                                 __bluetooth_telephony_event_filter, NULL);
1173                 goto fail;
1174         }
1175
1176         /*Check for BT status*/
1177         ret = __bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
1178                                                                 object_path);
1179         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1180                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1181
1182         /*Bluetooth is active, therefore set the flag */
1183         is_active = TRUE;
1184
1185         ret = __bluetooth_telephony_register();
1186         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1187                 BT_ERR("__bluetooth_telephony_register failed\n");
1188                 goto fail;
1189         }
1190
1191         BT_DBG("-");
1192         return ret;
1193 fail:
1194         telephony_info.cb = NULL;
1195         telephony_info.user_data = NULL;
1196         telephony_info.call_count = 0;
1197
1198         __bluetooth_telephony_proxy_deinit();
1199
1200         /*Remove BT enabled signal*/
1201         dbus_g_proxy_disconnect_signal(
1202                 telephony_dbus_info.manager_proxy,
1203                 "AdapterAdded",
1204                 G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
1205                 NULL);
1206
1207         dbus_g_connection_unref(telephony_dbus_info.conn);
1208         telephony_dbus_info.conn = NULL;
1209         g_object_unref(telephony_dbus_info.manager_proxy);
1210         telephony_dbus_info.manager_proxy = NULL;
1211         g_object_unref(telephony_dbus_info.dbus_proxy);
1212         telephony_dbus_info.dbus_proxy = NULL;
1213         is_initialized = FALSE;
1214         return ret;
1215 }
1216
1217 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1218 {
1219         BT_DBG("+");
1220
1221         BT_TELEPHONY_CHECK_INITIALIZED();
1222
1223         is_initialized = FALSE;
1224
1225         dbus_connection_remove_filter(dbus_g_connection_get_connection(
1226                                 telephony_dbus_info.conn),
1227                                 __bluetooth_telephony_event_filter, NULL);
1228
1229         if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_ENABLED)
1230                 __bluetooth_telephony_unregister();
1231
1232         __bluetooth_telephony_proxy_deinit();
1233
1234         telephony_info.cb = NULL;
1235         telephony_info.user_data = NULL;
1236         telephony_info.call_count = 0;
1237
1238         /*Remove BT enabled signal*/
1239         dbus_g_proxy_disconnect_signal(
1240                 telephony_dbus_info.manager_proxy,
1241                 "AdapterAdded",
1242                 G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
1243                 NULL);
1244
1245         g_object_unref(telephony_dbus_info.manager_proxy);
1246         telephony_dbus_info.manager_proxy = NULL;
1247
1248         dbus_g_connection_unref(telephony_dbus_info.conn);
1249         telephony_dbus_info.conn = NULL;
1250
1251         g_object_unref(telephony_dbus_info.dbus_proxy);
1252         telephony_dbus_info.dbus_proxy = NULL;
1253
1254         BT_DBG("-");
1255         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1256 }
1257
1258 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1259 {
1260         BT_DBG("+");
1261
1262         if (telephony_dbus_info.conn == NULL) {
1263                 BT_ERR("Bluetooth telephony not initilized");
1264                 return FALSE;
1265         }
1266
1267         /* To get the headset state */
1268         if (telephony_dbus_info.proxy == NULL)
1269                 telephony_dbus_info.proxy =
1270                         __bluetooth_telephony_get_connected_device_proxy();
1271
1272         if (telephony_dbus_info.proxy == NULL)
1273                 return FALSE;
1274
1275         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1276                 return TRUE;
1277
1278         BT_DBG("-");
1279         return FALSE;
1280 }
1281
1282 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1283 {
1284         DBusMessage* reply;
1285         DBusError err;
1286         DBusMessageIter reply_iter;
1287         DBusMessageIter reply_iter_entry;
1288         const char *property;
1289
1290         BT_DBG("+");
1291
1292         BT_TELEPHONY_CHECK_INITIALIZED();
1293         BT_TELEPHONY_CHECK_ENABLED();
1294
1295         if (status == NULL)
1296                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1297
1298         reply = __bluetooth_telephony_dbus_method_send(
1299                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1300                         "GetProperties", &err, DBUS_TYPE_INVALID);
1301
1302         if (!reply) {
1303                 BT_ERR("Error returned in method call\n");
1304                 if (dbus_error_is_set(&err)) {
1305                         BT_DBG("Error message = %s \n", err.message);
1306                         dbus_error_free(&err);
1307                 }
1308                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1309         }
1310
1311         dbus_message_iter_init(reply, &reply_iter);
1312
1313         if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
1314                 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY\n");
1315                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1316         }
1317
1318         dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
1319
1320         /*Parse the dict */
1321         while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
1322                                                 DBUS_TYPE_DICT_ENTRY) {
1323
1324                 DBusMessageIter dict_entry, dict_entry_val;
1325                 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
1326                 dbus_message_iter_get_basic(&dict_entry, &property);
1327                 BT_DBG("String received = %s\n", property);
1328
1329                 if (g_strcmp0("nrec", property) == 0) {
1330                         dbus_message_iter_next(&dict_entry);
1331                         dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1332                         if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
1333                                                 DBUS_TYPE_BOOLEAN)
1334                                 continue;
1335
1336                         dbus_message_iter_get_basic(&dict_entry_val, status);
1337                         BT_DBG("NREC status = [%d]", *status);
1338                 }
1339                 dbus_message_iter_next(&reply_iter_entry);
1340         }
1341         dbus_message_unref(reply);
1342         BT_DBG("-");
1343         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1344 }
1345
1346 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1347 {
1348         GError *error = NULL;
1349         int ret;
1350
1351         BT_DBG("+");
1352
1353         BT_TELEPHONY_CHECK_INITIALIZED();
1354         BT_TELEPHONY_CHECK_ENABLED();
1355
1356         if (telephony_dbus_info.proxy == NULL)
1357                 telephony_dbus_info.proxy =
1358                         __bluetooth_telephony_get_connected_device_proxy();
1359
1360         if (telephony_dbus_info.proxy == NULL)
1361                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1362
1363         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1364                         &error, G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID,
1365                         G_TYPE_INVALID)) {
1366                 if (error != NULL) {
1367                         ret = __bt_telephony_get_error(error->message);
1368                         g_error_free(error);
1369                         return ret;
1370                 }
1371         }
1372
1373         BT_DBG("-");
1374         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1375 }
1376
1377 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1378 {
1379         GError *error = NULL;
1380         int ret;
1381
1382         BT_DBG("+");
1383
1384         BT_TELEPHONY_CHECK_INITIALIZED();
1385         BT_TELEPHONY_CHECK_ENABLED();
1386
1387         if (telephony_dbus_info.proxy == NULL)
1388                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1389
1390         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1391                                 &error, G_TYPE_BOOLEAN,
1392                                 FALSE, G_TYPE_INVALID, G_TYPE_INVALID)) {
1393                 BT_ERR("Dbus Call Failed!\n");
1394                 if (error != NULL) {
1395                         ret = __bt_telephony_get_error(error->message);
1396                         g_error_free(error);
1397                         return ret;
1398                 }
1399         }
1400
1401         BT_DBG("-");
1402         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1403 }
1404
1405 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1406 {
1407         GError *error = NULL;
1408         int ret;
1409
1410         BT_DBG("+");
1411
1412         BT_TELEPHONY_CHECK_INITIALIZED();
1413         BT_TELEPHONY_CHECK_ENABLED();
1414
1415         if (telephony_dbus_info.proxy == NULL)
1416                 telephony_dbus_info.proxy =
1417                         __bluetooth_telephony_get_connected_device_proxy();
1418
1419         if (telephony_dbus_info.proxy == NULL)
1420                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1421
1422         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1423                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1424
1425         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Play", &error,
1426                                         G_TYPE_INVALID, G_TYPE_INVALID)) {
1427                 BT_ERR("Dbus Call Failed!");
1428                 if (error != NULL) {
1429                         ret = __bt_telephony_get_error(error->message);
1430                         g_error_free(error);
1431                         return ret;
1432                 }
1433         }
1434         BT_DBG("-");
1435         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1436 }
1437
1438 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1439 {
1440         GError *error = NULL;
1441         int ret;
1442
1443         BT_DBG("+");
1444
1445         BT_TELEPHONY_CHECK_INITIALIZED();
1446         BT_TELEPHONY_CHECK_ENABLED();
1447
1448         if (telephony_dbus_info.proxy == NULL)
1449                 telephony_dbus_info.proxy =
1450                         __bluetooth_telephony_get_connected_device_proxy();
1451
1452         if (telephony_dbus_info.proxy == NULL)
1453                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1454
1455         if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING) {
1456                 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1457         }
1458
1459         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Stop", &error,
1460                         G_TYPE_INVALID, G_TYPE_INVALID)) {
1461                 BT_ERR("Dbus Call Failed");
1462                 if (error != NULL) {
1463                         ret = __bt_telephony_get_error(error->message);
1464                         g_error_free(error);
1465                         return ret;
1466                 }
1467         }
1468
1469         BT_DBG("-");
1470         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1471 }
1472
1473 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1474 {
1475         int ret;
1476
1477         BT_TELEPHONY_CHECK_INITIALIZED();
1478         BT_TELEPHONY_CHECK_ENABLED();
1479
1480         BT_DBG("+");
1481
1482         /*Make sure SCO is already connected */
1483         ret = __bluetooth_telephony_send_call_status(
1484                                 CSD_CALL_STATUS_MO_ALERTING, call_id);
1485         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1486                 BT_ERR("send call status Failed = [%d]", ret);
1487                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1488         }
1489         BT_DBG("-");
1490         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1491 }
1492
1493 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
1494                                                         unsigned int bt_audio)
1495 {
1496         int ret;
1497         BT_DBG("+");
1498
1499         BT_TELEPHONY_CHECK_INITIALIZED();
1500         BT_TELEPHONY_CHECK_ENABLED();
1501
1502         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1503                                                                 call_id);
1504         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1505                 BT_ERR("send call status Failed = [%d]", ret);
1506                 return ret;
1507         }
1508
1509         if (bt_audio) {
1510                 if (!bluetooth_telephony_is_sco_connected()) {
1511                         ret = bluetooth_telephony_audio_open();
1512                         if (ret != 0) {
1513                                 BT_ERR("Audio connection call Failed = %d", ret);
1514                                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1515                         }
1516                 }
1517         }
1518
1519         BT_DBG("-");
1520         return ret;
1521 }
1522
1523 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
1524 {
1525         int ret;
1526         BT_DBG("+");
1527
1528         BT_TELEPHONY_CHECK_INITIALIZED();
1529         BT_TELEPHONY_CHECK_ENABLED();
1530
1531         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
1532                                                                 call_id);
1533         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1534                 BT_ERR("send call status Failed = [%d]", ret);
1535                 return ret;
1536         }
1537         if (telephony_info.call_count > 0)
1538                 telephony_info.call_count = telephony_info.call_count - 1;
1539
1540         if (telephony_info.call_count  == 0) {
1541                 if (bluetooth_telephony_is_sco_connected()) {
1542                         ret = bluetooth_telephony_audio_close();
1543                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1544                                 BT_ERR(" Failed = [%d]", ret);
1545                                 return ret;
1546                         }
1547                 }
1548         }
1549         BT_DBG("-");
1550         return ret;
1551 }
1552
1553 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
1554 {
1555         int ret;
1556         BT_DBG("+");
1557
1558         BT_TELEPHONY_CHECK_INITIALIZED();
1559         BT_TELEPHONY_CHECK_ENABLED();
1560
1561         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
1562                                                                 call_id);
1563         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1564                 BT_ERR("send call status Failed = [%d]", ret);
1565         }
1566         BT_DBG("-");
1567         return ret;
1568 }
1569
1570 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
1571 {
1572         int ret;
1573         BT_DBG("+");
1574
1575         BT_TELEPHONY_CHECK_INITIALIZED();
1576         BT_TELEPHONY_CHECK_ENABLED();
1577
1578         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1579                                                                 call_id);
1580         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1581                 BT_ERR("send call status Failed = [%d]", ret);
1582         }
1583         BT_DBG("-");
1584         return ret;
1585 }
1586
1587 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
1588                                 unsigned int call_count)
1589 {
1590         int i;
1591         int ret;
1592         GList *list = call_list;
1593         bt_telephony_call_status_info_t *call_status;
1594
1595         BT_DBG("+");
1596
1597         BT_TELEPHONY_CHECK_INITIALIZED();
1598         BT_TELEPHONY_CHECK_ENABLED();
1599
1600         if (NULL == list) {
1601                 BT_ERR("call_list is invalid");
1602                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1603         }
1604
1605         BT_DBG(" call_count = [%d]", call_count);
1606
1607         for (i = 0; i < call_count; i++) {
1608                 call_status = g_list_nth_data(list, i);
1609
1610                 if (NULL == call_status)
1611                         continue;
1612
1613                 BT_DBG(" %d : Call id [%d] status[%d]", i,
1614                                         call_status->call_id,
1615                                         call_status->call_status);
1616
1617                 switch (call_status->call_status) {
1618                 case BLUETOOTH_CALL_STATE_HELD:
1619                         ret = __bluetooth_telephony_send_call_status(
1620                                                 CSD_CALL_STATUS_HOLD,
1621                                                 call_status->call_id);
1622                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1623                                 BT_ERR("Failed = %d", ret);
1624                                 return ret;
1625                         }
1626                 break;
1627
1628                 case BLUETOOTH_CALL_STATE_CONNECTED:
1629                         ret = __bluetooth_telephony_send_call_status(
1630                                         CSD_CALL_STATUS_ACTIVE,
1631                                         call_status->call_id);
1632                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1633                                 BT_ERR("Failed = [%d]", ret);
1634                                 return ret;
1635                         }
1636                 break;
1637
1638                 default:
1639                         if ((call_status->call_status < BLUETOOTH_CALL_STATE_NONE) ||
1640                                 (call_status->call_status >= BLUETOOTH_CALL_STATE_ERROR)) {
1641                                 BT_ERR("Unknown Call state");
1642                                 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
1643                         }
1644                 }
1645         }
1646
1647         BT_DBG("-");
1648         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1649 }
1650
1651 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
1652                                 unsigned int call_count)
1653 {
1654         int ret;
1655
1656         BT_DBG("+");
1657
1658         ret = bluetooth_telephony_call_swapped(call_list, call_count);
1659
1660         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1661                 BT_ERR("Failed = [%d]", ret);
1662                 return ret;
1663         }
1664
1665         telephony_info.call_count = call_count;
1666
1667         BT_DBG("-");
1668         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1669 }
1670
1671 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
1672                         const char *ph_number, unsigned int call_id,
1673                         unsigned int bt_audio)
1674 {
1675         DBusMessage *reply;
1676         DBusError err;
1677         const char *path = telephony_info.call_path;
1678         int ret;
1679
1680         BT_DBG("+");
1681
1682         BT_TELEPHONY_CHECK_INITIALIZED();
1683         BT_TELEPHONY_CHECK_ENABLED();
1684
1685         if (NULL == ph_number)
1686                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1687
1688         reply = __bluetooth_telephony_dbus_method_send(
1689                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1690                         "OutgoingCall", &err, DBUS_TYPE_STRING, &path,
1691                         DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1692                         &call_id, DBUS_TYPE_INVALID);
1693
1694         if (!reply) {
1695                 BT_ERR("Error returned in method call\n");
1696                 if (dbus_error_is_set(&err)) {
1697                         ret = __bt_telephony_get_error(err.message);
1698                         dbus_error_free(&err);
1699                         return ret;
1700                 }
1701                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1702         }
1703
1704         dbus_message_unref(reply);
1705
1706         telephony_info.call_count++;
1707         BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
1708
1709         if (bt_audio) {
1710                 if (!bluetooth_telephony_is_sco_connected()) {
1711                         ret = bluetooth_telephony_audio_open();
1712                         if (ret != 0) {
1713                                 BT_ERR(" Audio connection call Failed = %d", ret);
1714                                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1715                         }
1716                 }
1717         }
1718
1719         BT_DBG("-");
1720         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1721 }
1722
1723 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
1724                 const char *ph_number, unsigned int call_id)
1725 {
1726         DBusMessage *reply;
1727         DBusError err;
1728         const char *path = telephony_info.call_path;
1729         int ret;
1730
1731         BT_DBG("+");
1732
1733         BT_TELEPHONY_CHECK_INITIALIZED();
1734         BT_TELEPHONY_CHECK_ENABLED();
1735
1736         if (NULL == ph_number)
1737                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1738
1739         reply = __bluetooth_telephony_dbus_method_send(
1740                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1741                         "IncomingCall", &err, DBUS_TYPE_STRING, &path,
1742                         DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1743                         &call_id, DBUS_TYPE_INVALID);
1744
1745         if (!reply) {
1746                 BT_ERR("Error returned in method call\n");
1747                 if (dbus_error_is_set(&err)) {
1748                         ret = __bt_telephony_get_error(err.message);
1749                         dbus_error_free(&err);
1750                         return ret;
1751                 }
1752                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1753         }
1754
1755         dbus_message_unref(reply);
1756
1757         telephony_info.call_count++;
1758         BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
1759         BT_DBG("-");
1760         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1761 }
1762
1763 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(unsigned short speaker_gain)
1764 {
1765         DBusMessage *msg;
1766         DBusMessageIter iter;
1767         DBusMessageIter value;
1768         DBusConnection *conn;
1769         char *spkr_gain_str = "SpeakerGain";
1770         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1771
1772         BT_DBG("+");
1773         BT_DBG("set speaker_gain= [%d]", speaker_gain);
1774
1775         BT_TELEPHONY_CHECK_INITIALIZED();
1776         BT_TELEPHONY_CHECK_ENABLED();
1777
1778         conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1779
1780         if (telephony_info.obj_path == NULL)
1781                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1782
1783         msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME,
1784                         telephony_info.obj_path, BLUEZ_HEADSET_INTERFACE,
1785                         "SetProperty");
1786
1787         if (NULL != msg) {
1788                 char sig[2] = {DBUS_TYPE_UINT16, '\0'};
1789
1790                 dbus_message_iter_init_append(msg, &iter);
1791                 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
1792                                 &spkr_gain_str);
1793                 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1794                                 sig, &value);
1795                 dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT16,
1796                                 &speaker_gain);
1797                 dbus_message_iter_close_container(&iter, &value);
1798
1799                 if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
1800                         dbus_message_set_no_reply(msg, TRUE);
1801                 if (!dbus_connection_send(conn, msg, NULL)) {
1802                         BT_ERR("bluetooth_telephony_set_speaker_gain : dbus sending failed");
1803                         ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1804                 }
1805                 dbus_message_unref(msg);
1806         } else
1807                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1808
1809         BT_DBG("-");
1810         return ret;
1811 }
1812
1813 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(unsigned int *speaker_gain)
1814 {
1815         GHashTable *hash = NULL;
1816         GValue *value = NULL;
1817         GError *error = NULL;
1818         int ret;
1819
1820         BT_DBG("+");
1821         BT_TELEPHONY_CHECK_INITIALIZED();
1822         BT_TELEPHONY_CHECK_ENABLED();
1823
1824         if (telephony_dbus_info.proxy == NULL)
1825                 telephony_dbus_info.proxy =
1826                         __bluetooth_telephony_get_connected_device_proxy();
1827
1828         if (telephony_dbus_info.proxy == NULL)
1829                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1830
1831         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "GetProperties", &error,
1832                           G_TYPE_INVALID,
1833                           dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
1834                           &hash, G_TYPE_INVALID)) {
1835                 BT_ERR("Dbus Call Failed!");
1836                 if (error != NULL) {
1837                         ret = __bt_telephony_get_error(error->message);
1838                         g_error_free(error);
1839                         return ret;
1840                 }
1841         }
1842
1843         if (hash == NULL)
1844                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1845
1846         value = g_hash_table_lookup(hash, "SpeakerGain");
1847         *speaker_gain = g_value_get_uint(value);
1848         g_hash_table_destroy(hash);
1849         BT_DBG("-");
1850         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1851 }