JIRA issue S1-13098 - Fix dbus add match rule overflow
[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
1175         dbus_error_init(&dbus_error);
1176         conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1177         dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
1178                                 NULL, NULL);
1179
1180         dbus_bus_add_match(conn,
1181                         "type='signal',interface='" BLUEZ_HEADSET_INTERFACE
1182                         "',member='PropertyChanged'", &dbus_error);
1183         dbus_bus_add_match(conn,
1184                         "type='signal',interface='"HFP_AGENT_SERVICE
1185                         "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error);
1186
1187         if (dbus_error_is_set(&dbus_error)) {
1188                 BT_ERR("Fail to add dbus filter signal\n");
1189                 dbus_error_free(&dbus_error);
1190                 goto fail;
1191         }
1192
1193         /*Check for BT status*/
1194         ret = __bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
1195                                                                 object_path);
1196         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1197                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1198
1199         /*Bluetooth is active, therefore set the flag */
1200         is_active = TRUE;
1201
1202         ret = __bluetooth_telephony_register();
1203         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1204                 BT_ERR("__bluetooth_telephony_register failed\n");
1205                 goto fail;
1206         }
1207
1208         BT_DBG("-");
1209         return ret;
1210 fail:
1211         bluetooth_telephony_deinit();
1212         return ret;
1213 }
1214
1215 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1216 {
1217         BT_DBG("+");
1218         DBusConnection *conn;
1219
1220         BT_TELEPHONY_CHECK_INITIALIZED();
1221
1222         is_initialized = FALSE;
1223
1224         conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1225
1226         dbus_bus_remove_match(conn,
1227                                 "type='signal',interface='" BLUEZ_HEADSET_INTERFACE
1228                                 "',member='PropertyChanged'", NULL);
1229
1230         dbus_bus_remove_match(conn,
1231                         "type='signal',interface='"HFP_AGENT_SERVICE
1232                         "',member='"HFP_NREC_STATUS_CHANGE"'", NULL);
1233
1234         dbus_connection_remove_filter(conn, __bluetooth_telephony_event_filter,
1235                  NULL);
1236
1237         if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_ENABLED)
1238                 __bluetooth_telephony_unregister();
1239
1240         __bluetooth_telephony_proxy_deinit();
1241
1242         telephony_info.cb = NULL;
1243         telephony_info.user_data = NULL;
1244         telephony_info.call_count = 0;
1245
1246         /*Remove BT enabled signal*/
1247         dbus_g_proxy_disconnect_signal(
1248                 telephony_dbus_info.manager_proxy,
1249                 "AdapterAdded",
1250                 G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
1251                 NULL);
1252
1253         g_object_unref(telephony_dbus_info.manager_proxy);
1254         telephony_dbus_info.manager_proxy = NULL;
1255
1256         dbus_g_connection_unref(telephony_dbus_info.conn);
1257         telephony_dbus_info.conn = NULL;
1258
1259         g_object_unref(telephony_dbus_info.dbus_proxy);
1260         telephony_dbus_info.dbus_proxy = NULL;
1261
1262         BT_DBG("-");
1263         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1264 }
1265
1266 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1267 {
1268         BT_DBG("+");
1269
1270         if (telephony_dbus_info.conn == NULL) {
1271                 BT_ERR("Bluetooth telephony not initilized");
1272                 return FALSE;
1273         }
1274
1275         /* To get the headset state */
1276         if (telephony_dbus_info.proxy == NULL)
1277                 telephony_dbus_info.proxy =
1278                         __bluetooth_telephony_get_connected_device_proxy();
1279
1280         if (telephony_dbus_info.proxy == NULL)
1281                 return FALSE;
1282
1283         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1284                 return TRUE;
1285
1286         BT_DBG("-");
1287         return FALSE;
1288 }
1289
1290 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1291 {
1292         DBusMessage* reply;
1293         DBusError err;
1294         DBusMessageIter reply_iter;
1295         DBusMessageIter reply_iter_entry;
1296         const char *property;
1297
1298         BT_DBG("+");
1299
1300         BT_TELEPHONY_CHECK_INITIALIZED();
1301         BT_TELEPHONY_CHECK_ENABLED();
1302
1303         if (status == NULL)
1304                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1305
1306         reply = __bluetooth_telephony_dbus_method_send(
1307                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1308                         "GetProperties", &err, DBUS_TYPE_INVALID);
1309
1310         if (!reply) {
1311                 BT_ERR("Error returned in method call\n");
1312                 if (dbus_error_is_set(&err)) {
1313                         BT_DBG("Error message = %s \n", err.message);
1314                         dbus_error_free(&err);
1315                 }
1316                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1317         }
1318
1319         dbus_message_iter_init(reply, &reply_iter);
1320
1321         if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
1322                 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY\n");
1323                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1324         }
1325
1326         dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
1327
1328         /*Parse the dict */
1329         while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
1330                                                 DBUS_TYPE_DICT_ENTRY) {
1331
1332                 DBusMessageIter dict_entry, dict_entry_val;
1333                 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
1334                 dbus_message_iter_get_basic(&dict_entry, &property);
1335                 BT_DBG("String received = %s\n", property);
1336
1337                 if (g_strcmp0("nrec", property) == 0) {
1338                         dbus_message_iter_next(&dict_entry);
1339                         dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1340                         if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
1341                                                 DBUS_TYPE_BOOLEAN)
1342                                 continue;
1343
1344                         dbus_message_iter_get_basic(&dict_entry_val, status);
1345                         BT_DBG("NREC status = [%d]", *status);
1346                 }
1347                 dbus_message_iter_next(&reply_iter_entry);
1348         }
1349         dbus_message_unref(reply);
1350         BT_DBG("-");
1351         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1352 }
1353
1354 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1355 {
1356         GError *error = NULL;
1357         int ret;
1358
1359         BT_DBG("+");
1360
1361         BT_TELEPHONY_CHECK_INITIALIZED();
1362         BT_TELEPHONY_CHECK_ENABLED();
1363
1364         if (telephony_dbus_info.proxy == NULL)
1365                 telephony_dbus_info.proxy =
1366                         __bluetooth_telephony_get_connected_device_proxy();
1367
1368         if (telephony_dbus_info.proxy == NULL)
1369                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1370
1371         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1372                         &error, G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID,
1373                         G_TYPE_INVALID)) {
1374                 if (error != NULL) {
1375                         ret = __bt_telephony_get_error(error->message);
1376                         g_error_free(error);
1377                         return ret;
1378                 }
1379         }
1380
1381         BT_DBG("-");
1382         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1383 }
1384
1385 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1386 {
1387         GError *error = NULL;
1388         int ret;
1389
1390         BT_DBG("+");
1391
1392         BT_TELEPHONY_CHECK_INITIALIZED();
1393         BT_TELEPHONY_CHECK_ENABLED();
1394
1395         if (telephony_dbus_info.proxy == NULL)
1396                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1397
1398         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1399                                 &error, G_TYPE_BOOLEAN,
1400                                 FALSE, G_TYPE_INVALID, G_TYPE_INVALID)) {
1401                 BT_ERR("Dbus Call Failed!\n");
1402                 if (error != NULL) {
1403                         ret = __bt_telephony_get_error(error->message);
1404                         g_error_free(error);
1405                         return ret;
1406                 }
1407         }
1408
1409         BT_DBG("-");
1410         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1411 }
1412
1413 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1414 {
1415         GError *error = NULL;
1416         int ret;
1417
1418         BT_DBG("+");
1419
1420         BT_TELEPHONY_CHECK_INITIALIZED();
1421         BT_TELEPHONY_CHECK_ENABLED();
1422
1423         if (telephony_dbus_info.proxy == NULL)
1424                 telephony_dbus_info.proxy =
1425                         __bluetooth_telephony_get_connected_device_proxy();
1426
1427         if (telephony_dbus_info.proxy == NULL)
1428                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1429
1430         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1431                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1432
1433         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Play", &error,
1434                                         G_TYPE_INVALID, G_TYPE_INVALID)) {
1435                 BT_ERR("Dbus Call Failed!");
1436                 if (error != NULL) {
1437                         ret = __bt_telephony_get_error(error->message);
1438                         g_error_free(error);
1439                         return ret;
1440                 }
1441         }
1442         BT_DBG("-");
1443         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1444 }
1445
1446 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1447 {
1448         GError *error = NULL;
1449         int ret;
1450
1451         BT_DBG("+");
1452
1453         BT_TELEPHONY_CHECK_INITIALIZED();
1454         BT_TELEPHONY_CHECK_ENABLED();
1455
1456         if (telephony_dbus_info.proxy == NULL)
1457                 telephony_dbus_info.proxy =
1458                         __bluetooth_telephony_get_connected_device_proxy();
1459
1460         if (telephony_dbus_info.proxy == NULL)
1461                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1462
1463         if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING) {
1464                 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1465         }
1466
1467         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Stop", &error,
1468                         G_TYPE_INVALID, G_TYPE_INVALID)) {
1469                 BT_ERR("Dbus Call Failed");
1470                 if (error != NULL) {
1471                         ret = __bt_telephony_get_error(error->message);
1472                         g_error_free(error);
1473                         return ret;
1474                 }
1475         }
1476
1477         BT_DBG("-");
1478         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1479 }
1480
1481 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1482 {
1483         int ret;
1484
1485         BT_TELEPHONY_CHECK_INITIALIZED();
1486         BT_TELEPHONY_CHECK_ENABLED();
1487
1488         BT_DBG("+");
1489
1490         /*Make sure SCO is already connected */
1491         ret = __bluetooth_telephony_send_call_status(
1492                                 CSD_CALL_STATUS_MO_ALERTING, call_id);
1493         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1494                 BT_ERR("send call status Failed = [%d]", ret);
1495                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1496         }
1497         BT_DBG("-");
1498         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1499 }
1500
1501 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
1502                                                         unsigned int bt_audio)
1503 {
1504         int ret;
1505         BT_DBG("+");
1506
1507         BT_TELEPHONY_CHECK_INITIALIZED();
1508         BT_TELEPHONY_CHECK_ENABLED();
1509
1510         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1511                                                                 call_id);
1512         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1513                 BT_ERR("send call status Failed = [%d]", ret);
1514                 return ret;
1515         }
1516
1517         if (bt_audio) {
1518                 if (!bluetooth_telephony_is_sco_connected()) {
1519                         ret = bluetooth_telephony_audio_open();
1520                         if (ret != 0) {
1521                                 BT_ERR("Audio connection call Failed = %d", ret);
1522                                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1523                         }
1524                 }
1525         }
1526
1527         BT_DBG("-");
1528         return ret;
1529 }
1530
1531 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
1532 {
1533         int ret;
1534         BT_DBG("+");
1535
1536         BT_TELEPHONY_CHECK_INITIALIZED();
1537         BT_TELEPHONY_CHECK_ENABLED();
1538
1539         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
1540                                                                 call_id);
1541         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1542                 BT_ERR("send call status Failed = [%d]", ret);
1543                 return ret;
1544         }
1545         if (telephony_info.call_count > 0)
1546                 telephony_info.call_count = telephony_info.call_count - 1;
1547
1548         if (telephony_info.call_count  == 0) {
1549                 if (bluetooth_telephony_is_sco_connected()) {
1550                         ret = bluetooth_telephony_audio_close();
1551                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1552                                 BT_ERR(" Failed = [%d]", ret);
1553                                 return ret;
1554                         }
1555                 }
1556         }
1557         BT_DBG("-");
1558         return ret;
1559 }
1560
1561 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
1562 {
1563         int ret;
1564         BT_DBG("+");
1565
1566         BT_TELEPHONY_CHECK_INITIALIZED();
1567         BT_TELEPHONY_CHECK_ENABLED();
1568
1569         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
1570                                                                 call_id);
1571         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1572                 BT_ERR("send call status Failed = [%d]", ret);
1573         }
1574         BT_DBG("-");
1575         return ret;
1576 }
1577
1578 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
1579 {
1580         int ret;
1581         BT_DBG("+");
1582
1583         BT_TELEPHONY_CHECK_INITIALIZED();
1584         BT_TELEPHONY_CHECK_ENABLED();
1585
1586         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1587                                                                 call_id);
1588         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1589                 BT_ERR("send call status Failed = [%d]", ret);
1590         }
1591         BT_DBG("-");
1592         return ret;
1593 }
1594
1595 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
1596                                 unsigned int call_count)
1597 {
1598         int i;
1599         int ret;
1600         GList *list = call_list;
1601         bt_telephony_call_status_info_t *call_status;
1602
1603         BT_DBG("+");
1604
1605         BT_TELEPHONY_CHECK_INITIALIZED();
1606         BT_TELEPHONY_CHECK_ENABLED();
1607
1608         if (NULL == list) {
1609                 BT_ERR("call_list is invalid");
1610                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1611         }
1612
1613         BT_DBG(" call_count = [%d]", call_count);
1614
1615         for (i = 0; i < call_count; i++) {
1616                 call_status = g_list_nth_data(list, i);
1617
1618                 if (NULL == call_status)
1619                         continue;
1620
1621                 BT_DBG(" %d : Call id [%d] status[%d]", i,
1622                                         call_status->call_id,
1623                                         call_status->call_status);
1624
1625                 switch (call_status->call_status) {
1626                 case BLUETOOTH_CALL_STATE_HELD:
1627                         ret = __bluetooth_telephony_send_call_status(
1628                                                 CSD_CALL_STATUS_HOLD,
1629                                                 call_status->call_id);
1630                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1631                                 BT_ERR("Failed = %d", ret);
1632                                 return ret;
1633                         }
1634                 break;
1635
1636                 case BLUETOOTH_CALL_STATE_CONNECTED:
1637                         ret = __bluetooth_telephony_send_call_status(
1638                                         CSD_CALL_STATUS_ACTIVE,
1639                                         call_status->call_id);
1640                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1641                                 BT_ERR("Failed = [%d]", ret);
1642                                 return ret;
1643                         }
1644                 break;
1645
1646                 default:
1647                         if ((call_status->call_status < BLUETOOTH_CALL_STATE_NONE) ||
1648                                 (call_status->call_status >= BLUETOOTH_CALL_STATE_ERROR)) {
1649                                 BT_ERR("Unknown Call state");
1650                                 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
1651                         }
1652                 }
1653         }
1654
1655         BT_DBG("-");
1656         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1657 }
1658
1659 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
1660                                 unsigned int call_count)
1661 {
1662         int ret;
1663
1664         BT_DBG("+");
1665
1666         ret = bluetooth_telephony_call_swapped(call_list, call_count);
1667
1668         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1669                 BT_ERR("Failed = [%d]", ret);
1670                 return ret;
1671         }
1672
1673         telephony_info.call_count = call_count;
1674
1675         BT_DBG("-");
1676         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1677 }
1678
1679 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
1680                         const char *ph_number, unsigned int call_id,
1681                         unsigned int bt_audio)
1682 {
1683         DBusMessage *reply;
1684         DBusError err;
1685         const char *path = telephony_info.call_path;
1686         int ret;
1687
1688         BT_DBG("+");
1689
1690         BT_TELEPHONY_CHECK_INITIALIZED();
1691         BT_TELEPHONY_CHECK_ENABLED();
1692
1693         if (NULL == ph_number)
1694                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1695
1696         reply = __bluetooth_telephony_dbus_method_send(
1697                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1698                         "OutgoingCall", &err, DBUS_TYPE_STRING, &path,
1699                         DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1700                         &call_id, DBUS_TYPE_INVALID);
1701
1702         if (!reply) {
1703                 BT_ERR("Error returned in method call\n");
1704                 if (dbus_error_is_set(&err)) {
1705                         ret = __bt_telephony_get_error(err.message);
1706                         dbus_error_free(&err);
1707                         return ret;
1708                 }
1709                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1710         }
1711
1712         dbus_message_unref(reply);
1713
1714         telephony_info.call_count++;
1715         BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
1716
1717         if (bt_audio) {
1718                 if (!bluetooth_telephony_is_sco_connected()) {
1719                         ret = bluetooth_telephony_audio_open();
1720                         if (ret != 0) {
1721                                 BT_ERR(" Audio connection call Failed = %d", ret);
1722                                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1723                         }
1724                 }
1725         }
1726
1727         BT_DBG("-");
1728         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1729 }
1730
1731 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
1732                 const char *ph_number, unsigned int call_id)
1733 {
1734         DBusMessage *reply;
1735         DBusError err;
1736         const char *path = telephony_info.call_path;
1737         int ret;
1738
1739         BT_DBG("+");
1740
1741         BT_TELEPHONY_CHECK_INITIALIZED();
1742         BT_TELEPHONY_CHECK_ENABLED();
1743
1744         if (NULL == ph_number)
1745                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1746
1747         reply = __bluetooth_telephony_dbus_method_send(
1748                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1749                         "IncomingCall", &err, DBUS_TYPE_STRING, &path,
1750                         DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1751                         &call_id, DBUS_TYPE_INVALID);
1752
1753         if (!reply) {
1754                 BT_ERR("Error returned in method call\n");
1755                 if (dbus_error_is_set(&err)) {
1756                         ret = __bt_telephony_get_error(err.message);
1757                         dbus_error_free(&err);
1758                         return ret;
1759                 }
1760                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1761         }
1762
1763         dbus_message_unref(reply);
1764
1765         telephony_info.call_count++;
1766         BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
1767         BT_DBG("-");
1768         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1769 }
1770
1771 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(unsigned short speaker_gain)
1772 {
1773         DBusMessage *msg;
1774         DBusMessageIter iter;
1775         DBusMessageIter value;
1776         DBusConnection *conn;
1777         char *spkr_gain_str = "SpeakerGain";
1778         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1779
1780         BT_DBG("+");
1781         BT_DBG("set speaker_gain= [%d]", speaker_gain);
1782
1783         BT_TELEPHONY_CHECK_INITIALIZED();
1784         BT_TELEPHONY_CHECK_ENABLED();
1785
1786         conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1787
1788         if (telephony_info.obj_path == NULL)
1789                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1790
1791         msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME,
1792                         telephony_info.obj_path, BLUEZ_HEADSET_INTERFACE,
1793                         "SetProperty");
1794
1795         if (NULL != msg) {
1796                 char sig[2] = {DBUS_TYPE_UINT16, '\0'};
1797
1798                 dbus_message_iter_init_append(msg, &iter);
1799                 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
1800                                 &spkr_gain_str);
1801                 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1802                                 sig, &value);
1803                 dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT16,
1804                                 &speaker_gain);
1805                 dbus_message_iter_close_container(&iter, &value);
1806
1807                 if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
1808                         dbus_message_set_no_reply(msg, TRUE);
1809                 if (!dbus_connection_send(conn, msg, NULL)) {
1810                         BT_ERR("bluetooth_telephony_set_speaker_gain : dbus sending failed");
1811                         ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1812                 }
1813                 dbus_message_unref(msg);
1814         } else
1815                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1816
1817         BT_DBG("-");
1818         return ret;
1819 }
1820
1821 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(unsigned int *speaker_gain)
1822 {
1823         GHashTable *hash = NULL;
1824         GValue *value = NULL;
1825         GError *error = NULL;
1826         int ret;
1827
1828         BT_DBG("+");
1829         BT_TELEPHONY_CHECK_INITIALIZED();
1830         BT_TELEPHONY_CHECK_ENABLED();
1831
1832         if (telephony_dbus_info.proxy == NULL)
1833                 telephony_dbus_info.proxy =
1834                         __bluetooth_telephony_get_connected_device_proxy();
1835
1836         if (telephony_dbus_info.proxy == NULL)
1837                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1838
1839         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "GetProperties", &error,
1840                           G_TYPE_INVALID,
1841                           dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
1842                           &hash, G_TYPE_INVALID)) {
1843                 BT_ERR("Dbus Call Failed!");
1844                 if (error != NULL) {
1845                         ret = __bt_telephony_get_error(error->message);
1846                         g_error_free(error);
1847                         return ret;
1848                 }
1849         }
1850
1851         if (hash == NULL)
1852                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1853
1854         value = g_hash_table_lookup(hash, "SpeakerGain");
1855         *speaker_gain = g_value_get_uint(value);
1856         g_hash_table_destroy(hash);
1857         BT_DBG("-");
1858         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1859 }