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