Merge branch 'master' into tizen_2.1
[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         DBusError dbus_error;
708         DBusConnection *conn;
709
710         BT_DBG("Adapter added [%s] \n", adapter_path);
711
712         if (strstr(adapter_path, "hci0")) {
713                 BT_DBG("BlueZ is Activated and flag need to be reset");
714                 BT_DBG("Send enabled to application\n");
715
716                 ret = __bluetooth_telephony_register();
717                 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
718                         BT_DBG("__bluetooth_telephony_register failed\n");
719                         return;
720                 }
721
722                 dbus_error_init(&dbus_error);
723                 conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
724                 dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
725                                 NULL, NULL);
726
727                 dbus_bus_add_match(conn,
728                                 "type='signal',interface='" BLUEZ_HEADSET_INTERFACE
729                                 "',member='PropertyChanged'", &dbus_error);
730                 dbus_bus_add_match(conn,
731                         "type='signal',interface='"HFP_AGENT_SERVICE
732                         "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error);
733
734                 if (dbus_error_is_set(&dbus_error)) {
735                         BT_DBG("Fail to add dbus filter signal\n");
736                         dbus_error_free(&dbus_error);
737                         __bluetooth_telephony_unregister();
738                         dbus_connection_remove_filter(dbus_g_connection_get_connection(
739                                         telephony_dbus_info.conn),
740                                         __bluetooth_telephony_event_filter, NULL);
741                 }
742         }
743 }
744
745 static int __bluetooth_telephony_proxy_init(void)
746 {
747         BT_DBG("+");
748
749         object = (GObject *)__bluetooth_telephony_method_new();
750
751         if (NULL == object)
752                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
753
754         BT_DBG("telephony_object = %x", object);
755
756         dbus_g_connection_register_g_object(telephony_dbus_info.conn,
757                         telephony_info.call_path, G_OBJECT(object));
758
759         BT_DBG("-");
760         return BLUETOOTH_TELEPHONY_ERROR_NONE;
761 }
762
763 static void __bluetooth_telephony_proxy_deinit(void)
764 {
765         BT_DBG("+");
766
767         dbus_g_connection_unregister_g_object(telephony_dbus_info.conn,
768                                 G_OBJECT(object));
769
770         g_object_unref(object);
771         object = NULL;
772
773         BT_DBG("-");
774         return;
775 }
776
777 static int __bluetooth_telephony_register(void)
778 {
779         DBusMessage *reply;
780         DBusError err;
781         char *path = g_strdup(telephony_info.call_path);
782         int ret;
783
784         BT_DBG("+");
785
786         reply =  __bluetooth_telephony_dbus_method_send(
787                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
788                         "RegisterApplication", &err, DBUS_TYPE_STRING, &path,
789                         DBUS_TYPE_INVALID);
790
791         g_free(path);
792         if (!reply) {
793                 BT_ERR("Error returned in method call\n");
794                 if (dbus_error_is_set(&err)) {
795                         ret = __bt_telephony_get_error(err.message);
796                         dbus_error_free(&err);
797                         return ret;
798                 }
799                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
800         }
801
802         dbus_message_unref(reply);
803         BT_DBG("-");
804         return BLUETOOTH_TELEPHONY_ERROR_NONE;
805 }
806
807 static  int __bluetooth_telephony_unregister(void)
808 {
809         DBusMessage *reply;
810         DBusError err;
811         char *path = g_strdup(telephony_info.call_path);
812         int ret;
813
814         BT_DBG("+");
815
816         reply = __bluetooth_telephony_dbus_method_send(
817                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
818                         "UnregisterApplication", &err, DBUS_TYPE_STRING, &path,
819                         DBUS_TYPE_INVALID);
820
821         g_free(path);
822         if (!reply) {
823                 BT_ERR("Error returned in method call\n");
824                 if (dbus_error_is_set(&err)) {
825                         ret = __bt_telephony_get_error(err.message);
826                         dbus_error_free(&err);
827                         return ret;
828                 }
829                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
830         }
831
832         dbus_message_unref(reply);
833         BT_DBG("+");
834         return BLUETOOTH_TELEPHONY_ERROR_NONE;
835 }
836
837 static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
838                                                         char *path)
839 {
840         GError *err = NULL;
841         char *adapter_path = NULL;
842
843         BT_DBG("+");
844
845         if (!dbus_g_proxy_call(telephony_dbus_info.manager_proxy,
846                                 "DefaultAdapter", &err, G_TYPE_INVALID,
847                                 DBUS_TYPE_G_OBJECT_PATH, &adapter_path,
848                                 G_TYPE_INVALID)) {
849                 if (err != NULL) {
850                         BT_ERR("Getting DefaultAdapter failed: [%s]",
851                                                         err->message);
852                         g_error_free(err);
853                 }
854                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
855         }
856
857         if (adapter_path == NULL) {
858                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
859         }
860
861         if (strlen(adapter_path) >= BT_ADAPTER_PATH_LEN) {
862                 BT_ERR("Path too long.\n");
863                 g_free(adapter_path);
864                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
865         }
866
867         BT_DBG("path = %s", adapter_path);
868         g_strlcpy(path, adapter_path, BT_ADAPTER_PATH_LEN);
869         g_free(adapter_path);
870         BT_DBG("-");
871         return BLUETOOTH_TELEPHONY_ERROR_NONE;
872 }
873
874 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
875 {
876         gboolean flag = FALSE;
877         BT_DBG("+");
878
879         switch ((device_class & 0x1f00) >> 8) {
880         case 0x04:
881                 switch ((device_class & 0xfc) >> 2) {
882                 case 0x01:
883                 case 0x02:
884                         flag = TRUE;
885                         break;
886                 case 0x06:
887                         flag = TRUE;
888                         break;
889                 case 0x0b:
890                 case 0x0c:
891                 case 0x0d:
892                         break;
893                 default:
894                         flag = TRUE;
895                         break;
896                 }
897                 break;
898         }
899         BT_DBG("-");
900         return flag;
901 }
902
903 static int __bluetooth_telephony_get_connected_device(void)
904 {
905         DBusGProxy *list_proxy = NULL;
906         DBusGProxy *device_proxy = NULL;
907         GPtrArray *gp_array = NULL;
908         GError *error = NULL;
909         gchar *gp_path = NULL;
910         GHashTable *list_hash;
911         GHashTable *device_hash;
912         GValue *value = {0};
913         uint32_t device_class;
914         gboolean playing = FALSE;
915         gboolean connected = FALSE;
916         const gchar *address;
917         char object_path[BT_ADAPTER_PATH_LEN] = {0};
918         int i = 0;
919         DBusGProxy *proxy = NULL;
920
921         BT_DBG("+");
922
923         /*Get default adapter path*/
924         if (__bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
925                         object_path) < 0)
926                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
927         /*Get List of All devices*/
928         list_proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
929                                                 BLUEZ_SERVICE_NAME, object_path,
930                                                 BLUEZ_ADAPTER_INTERFACE);
931
932         if (list_proxy == NULL)
933                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
934
935         dbus_g_proxy_call(list_proxy, "ListDevices", &error, G_TYPE_INVALID,
936                                 dbus_g_type_get_collection("GPtrArray",
937                                 DBUS_TYPE_G_OBJECT_PATH),
938                                 &gp_array, G_TYPE_INVALID);
939
940         if (error != NULL) {
941                 g_error_free(error);
942                 goto done;
943         }
944
945         if (gp_array == NULL)
946                 goto done;
947
948         /*Check for headset devices*/
949         for (i = 0; i < gp_array->len; i++) {
950                 list_hash = NULL;
951                 device_hash = NULL;
952                 gp_path = g_ptr_array_index(gp_array, i);
953
954                 if (gp_path == NULL)
955                         goto done;
956
957                 proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
958                                                 BLUEZ_SERVICE_NAME, gp_path,
959                                                 BLUEZ_DEVICE_INTERFACE);
960
961                 if (proxy == NULL)
962                         goto done;
963
964                 dbus_g_proxy_call(proxy, "GetProperties", NULL,
965                                 G_TYPE_INVALID, dbus_g_type_get_map(
966                                 "GHashTable", G_TYPE_STRING,
967                                 G_TYPE_VALUE), &list_hash, G_TYPE_INVALID);
968
969                 if (list_hash == NULL)
970                         goto done;
971
972                 value = g_hash_table_lookup(list_hash, "Class");
973                 device_class = value ? g_value_get_uint(value) : 0;
974
975                 if (!__bluetooth_telephony_is_headset(device_class)) {
976                         g_object_unref(proxy);
977                         proxy = NULL;
978                         g_free(gp_path);
979                         gp_path = NULL;
980                         g_hash_table_destroy(list_hash);
981                         continue;
982                 }
983
984                 /*Check for Connection*/
985                 device_proxy = dbus_g_proxy_new_for_name(
986                                 telephony_dbus_info.conn,
987                                 BLUEZ_SERVICE_NAME, gp_path,
988                                 BLUEZ_HEADSET_INTERFACE);
989
990                 if (device_proxy == NULL) {
991                         g_hash_table_destroy(list_hash);
992                         goto done;
993                 }
994
995                 dbus_g_proxy_call(device_proxy, "GetProperties",
996                                 &error, G_TYPE_INVALID,
997                                 dbus_g_type_get_map("GHashTable",
998                                 G_TYPE_STRING, G_TYPE_VALUE),
999                                 &device_hash, G_TYPE_INVALID);
1000
1001                 if (error == NULL) {
1002                         value = g_hash_table_lookup(device_hash,
1003                                         "Connected");
1004                         connected = value ? g_value_get_boolean(
1005                                         value) : FALSE;
1006                         if (connected) {
1007                                 value = g_hash_table_lookup(list_hash,
1008                                                                 "Address");
1009                                 address = value ? g_value_get_string(
1010                                                         value) : NULL;
1011                                 g_strlcpy(telephony_info.address, address,
1012                                                 sizeof(telephony_info.address));
1013                                 value = g_hash_table_lookup(device_hash,
1014                                                                 "Playing");
1015                                 playing = value ? g_value_get_boolean(
1016                                                         value) : FALSE;
1017                                 if (playing)
1018                                         telephony_info.headset_state =
1019                                                 BLUETOOTH_STATE_PLAYING;
1020                                 else
1021                                         telephony_info.headset_state =
1022                                                 BLUETOOTH_STATE_CONNECTED;
1023
1024                                 g_hash_table_destroy(device_hash);
1025                                 g_hash_table_destroy(list_hash);
1026                                 goto done;
1027                         }
1028                         g_hash_table_destroy(device_hash);
1029                 } else {
1030                         g_error_free(error);
1031                 }
1032
1033                 g_hash_table_destroy(list_hash);
1034                 g_object_unref(proxy);
1035                 proxy = NULL;
1036                 g_free(gp_path);
1037                 gp_path = NULL;
1038         }
1039 done:
1040         if (list_proxy)
1041                 g_object_unref(list_proxy);
1042         if (device_proxy)
1043                 g_object_unref(device_proxy);
1044         if (proxy)
1045                 g_object_unref(proxy);
1046         g_free(gp_path);
1047         g_ptr_array_free(gp_array, TRUE);
1048         BT_DBG("-");
1049         return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1050 }
1051
1052 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1053 {
1054         DBusGProxy *proxy = NULL;
1055         char object_path[BT_ADAPTER_PATH_LEN] = {0};
1056         GError *error = NULL;
1057         DBusGProxy *default_proxy;
1058
1059         BT_DBG("+");
1060
1061         /*Get default adapter path*/
1062         if (__bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
1063                         object_path) < 0)
1064                 return NULL;
1065
1066         /*Get List of All devices*/
1067         default_proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
1068                                                 BLUEZ_SERVICE_NAME, object_path,
1069                                                 BLUEZ_ADAPTER_INTERFACE);
1070
1071         if (default_proxy == NULL)
1072                 return NULL;
1073
1074         if (strlen(telephony_info.address) == 0)
1075                 __bluetooth_telephony_get_connected_device();
1076
1077         if (strlen(telephony_info.address) == 0) {
1078                 g_object_unref(default_proxy);
1079                 return NULL;
1080         }
1081
1082         if (telephony_info.obj_path) {
1083                 g_free(telephony_info.obj_path);
1084                 telephony_info.obj_path = NULL;
1085         }
1086
1087         dbus_g_proxy_call(default_proxy, "FindDevice", &error,
1088                         G_TYPE_STRING, telephony_info.address,
1089                         G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH,
1090                         &telephony_info.obj_path,
1091                         G_TYPE_INVALID);
1092         if (error != NULL) {
1093                 BT_ERR("dbus_g_proxy_call Failed!\n");
1094                 g_error_free(error);
1095                 g_object_unref(default_proxy);
1096                 return NULL;
1097         }
1098
1099         if (telephony_info.obj_path == NULL) {
1100                 g_object_unref(default_proxy);
1101                 return NULL;
1102         }
1103
1104         proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
1105                         BLUEZ_SERVICE_NAME, telephony_info.obj_path,
1106                         BLUEZ_HEADSET_INTERFACE);
1107
1108         g_object_unref(default_proxy);
1109
1110         return proxy;
1111 }
1112
1113 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1114                                                         void  *user_data)
1115 {
1116         DBusError dbus_error;
1117         DBusConnection *conn;
1118         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1119         GError *error = NULL;
1120         char object_path[BT_ADAPTER_PATH_LEN] = {0};
1121         BT_DBG("+");
1122
1123         g_type_init();
1124
1125         if (is_initialized == TRUE) {
1126                 BT_ERR("Bluetooth telephony already initilized");
1127                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_INITIALIZED;
1128         }
1129
1130         is_initialized = TRUE;
1131
1132         telephony_dbus_info.conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
1133         if (!telephony_dbus_info.conn) {
1134                 if (NULL != error) {
1135                         BT_ERR("dbus_g_bus_get() failed:[%d:%s]\n",
1136                                         error->code, error->message);
1137                         g_error_free(error);
1138                 }
1139                 is_initialized = FALSE;
1140                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1141         }
1142
1143         /* Call Path */
1144         snprintf(telephony_info.call_path, sizeof(telephony_info.call_path),
1145                                         CSD_CALL_APP_PATH, getpid());
1146         BT_DBG("Call Path = %s", telephony_info.call_path);
1147         memset(telephony_info.address, 0x00, sizeof(telephony_info.address));
1148
1149         if (__bluetooth_telephony_proxy_init()) {
1150                 BT_ERR("__bluetooth_telephony_proxy_init failed\n");
1151                 dbus_g_connection_unref(telephony_dbus_info.conn);
1152                 telephony_dbus_info.conn = NULL;
1153                 is_initialized = FALSE;
1154                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1155         }
1156
1157         telephony_dbus_info.manager_proxy = dbus_g_proxy_new_for_name(
1158                                                 telephony_dbus_info.conn,
1159                                                 BLUEZ_SERVICE_NAME,
1160                                                 "/", BLUEZ_MANAGER_INTERFACE);
1161
1162         if (telephony_dbus_info.manager_proxy == NULL) {
1163                 BT_ERR("Could not create a manager proxy\n");
1164                 __bluetooth_telephony_proxy_deinit();
1165                 dbus_g_connection_unref(telephony_dbus_info.conn);
1166                 telephony_dbus_info.conn = NULL;
1167                 is_initialized = FALSE;
1168                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1169         }
1170
1171         telephony_dbus_info.dbus_proxy = dbus_g_proxy_new_for_name(
1172                         telephony_dbus_info.conn, DBUS_SERVICE_DBUS,
1173                         DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
1174
1175         if (NULL == telephony_dbus_info.dbus_proxy) {
1176                 __bluetooth_telephony_proxy_deinit();
1177                 dbus_g_connection_unref(telephony_dbus_info.conn);
1178                 telephony_dbus_info.conn = NULL;
1179                 g_object_unref(telephony_dbus_info.manager_proxy);
1180                 telephony_dbus_info.manager_proxy = NULL;
1181                 is_initialized = FALSE;
1182                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1183         }
1184
1185         /*Add Signal callback for BT enabled*/
1186         dbus_g_proxy_add_signal(telephony_dbus_info.manager_proxy,
1187                                 "AdapterAdded",
1188                                 DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
1189         dbus_g_proxy_connect_signal(telephony_dbus_info.manager_proxy,
1190                         "AdapterAdded",
1191                         G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
1192                         NULL, NULL);
1193
1194         /*Callback and user applicaton data*/
1195         telephony_info.cb = cb;
1196         telephony_info.user_data = user_data;
1197
1198         dbus_error_init(&dbus_error);
1199         conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1200         dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
1201                                 NULL, NULL);
1202
1203         dbus_bus_add_match(conn,
1204                         "type='signal',interface='" BLUEZ_HEADSET_INTERFACE
1205                         "',member='PropertyChanged'", &dbus_error);
1206         dbus_bus_add_match(conn,
1207                         "type='signal',interface='"HFP_AGENT_SERVICE
1208                         "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error);
1209
1210         if (dbus_error_is_set(&dbus_error)) {
1211                 BT_ERR("Fail to add dbus filter signal\n");
1212                 dbus_error_free(&dbus_error);
1213                 dbus_connection_remove_filter(dbus_g_connection_get_connection(
1214                                 telephony_dbus_info.conn),
1215                                 __bluetooth_telephony_event_filter, NULL);
1216                 goto fail;
1217         }
1218
1219         /*Check for BT status*/
1220         ret = __bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
1221                                                                 object_path);
1222         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1223                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1224
1225         /*Bluetooth is active, therefore set the flag */
1226         is_active = TRUE;
1227
1228         ret = __bluetooth_telephony_register();
1229         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1230                 BT_ERR("__bluetooth_telephony_register failed\n");
1231                 goto fail;
1232         }
1233
1234         BT_DBG("-");
1235         return ret;
1236 fail:
1237         telephony_info.cb = NULL;
1238         telephony_info.user_data = NULL;
1239         telephony_info.call_count = 0;
1240
1241         __bluetooth_telephony_proxy_deinit();
1242
1243         /*Remove BT enabled signal*/
1244         dbus_g_proxy_disconnect_signal(
1245                 telephony_dbus_info.manager_proxy,
1246                 "AdapterAdded",
1247                 G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
1248                 NULL);
1249
1250         dbus_g_connection_unref(telephony_dbus_info.conn);
1251         telephony_dbus_info.conn = NULL;
1252         g_object_unref(telephony_dbus_info.manager_proxy);
1253         telephony_dbus_info.manager_proxy = NULL;
1254         g_object_unref(telephony_dbus_info.dbus_proxy);
1255         telephony_dbus_info.dbus_proxy = NULL;
1256         is_initialized = FALSE;
1257         return ret;
1258 }
1259
1260 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1261 {
1262         BT_DBG("+");
1263
1264         BT_TELEPHONY_CHECK_INITIALIZED();
1265
1266         is_initialized = FALSE;
1267
1268         dbus_connection_remove_filter(dbus_g_connection_get_connection(
1269                                 telephony_dbus_info.conn),
1270                                 __bluetooth_telephony_event_filter, NULL);
1271
1272         if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_ENABLED)
1273                 __bluetooth_telephony_unregister();
1274
1275         __bluetooth_telephony_proxy_deinit();
1276
1277         telephony_info.cb = NULL;
1278         telephony_info.user_data = NULL;
1279         telephony_info.call_count = 0;
1280
1281         /*Remove BT enabled signal*/
1282         dbus_g_proxy_disconnect_signal(
1283                 telephony_dbus_info.manager_proxy,
1284                 "AdapterAdded",
1285                 G_CALLBACK(__bluetooth_telephony_adapter_added_cb),
1286                 NULL);
1287
1288         g_object_unref(telephony_dbus_info.manager_proxy);
1289         telephony_dbus_info.manager_proxy = NULL;
1290
1291         dbus_g_connection_unref(telephony_dbus_info.conn);
1292         telephony_dbus_info.conn = NULL;
1293
1294         g_object_unref(telephony_dbus_info.dbus_proxy);
1295         telephony_dbus_info.dbus_proxy = NULL;
1296
1297         BT_DBG("-");
1298         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1299 }
1300
1301 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1302 {
1303         BT_DBG("+");
1304
1305         if (telephony_dbus_info.conn == NULL) {
1306                 BT_ERR("Bluetooth telephony not initilized");
1307                 return FALSE;
1308         }
1309
1310         /* To get the headset state */
1311         if (telephony_dbus_info.proxy == NULL)
1312                 telephony_dbus_info.proxy =
1313                         __bluetooth_telephony_get_connected_device_proxy();
1314
1315         if (telephony_dbus_info.proxy == NULL)
1316                 return FALSE;
1317
1318         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1319                 return TRUE;
1320
1321         BT_DBG("-");
1322         return FALSE;
1323 }
1324
1325 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1326 {
1327         DBusMessage* reply;
1328         DBusError err;
1329         DBusMessageIter reply_iter;
1330         DBusMessageIter reply_iter_entry;
1331         const char *property;
1332
1333         BT_DBG("+");
1334
1335         BT_TELEPHONY_CHECK_INITIALIZED();
1336         BT_TELEPHONY_CHECK_ENABLED();
1337
1338         if (status == NULL)
1339                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1340
1341         reply = __bluetooth_telephony_dbus_method_send(
1342                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1343                         "GetProperties", &err, DBUS_TYPE_INVALID);
1344
1345         if (!reply) {
1346                 BT_ERR("Error returned in method call\n");
1347                 if (dbus_error_is_set(&err)) {
1348                         BT_DBG("Error message = %s \n", err.message);
1349                         dbus_error_free(&err);
1350                 }
1351                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1352         }
1353
1354         dbus_message_iter_init(reply, &reply_iter);
1355
1356         if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
1357                 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY\n");
1358                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1359         }
1360
1361         dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
1362
1363         /*Parse the dict */
1364         while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
1365                                                 DBUS_TYPE_DICT_ENTRY) {
1366
1367                 DBusMessageIter dict_entry, dict_entry_val;
1368                 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
1369                 dbus_message_iter_get_basic(&dict_entry, &property);
1370                 BT_DBG("String received = %s\n", property);
1371
1372                 if (g_strcmp0("nrec", property) == 0) {
1373                         dbus_message_iter_next(&dict_entry);
1374                         dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1375                         if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
1376                                                 DBUS_TYPE_BOOLEAN)
1377                                 continue;
1378
1379                         dbus_message_iter_get_basic(&dict_entry_val, status);
1380                         BT_DBG("NREC status = [%d]", *status);
1381                 }
1382                 dbus_message_iter_next(&reply_iter_entry);
1383         }
1384         dbus_message_unref(reply);
1385         BT_DBG("-");
1386         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1387 }
1388
1389 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1390 {
1391         GError *error = NULL;
1392         int ret;
1393
1394         BT_DBG("+");
1395
1396         BT_TELEPHONY_CHECK_INITIALIZED();
1397         BT_TELEPHONY_CHECK_ENABLED();
1398
1399         if (telephony_dbus_info.proxy == NULL)
1400                 telephony_dbus_info.proxy =
1401                         __bluetooth_telephony_get_connected_device_proxy();
1402
1403         if (telephony_dbus_info.proxy == NULL)
1404                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1405
1406         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1407                         &error, G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID,
1408                         G_TYPE_INVALID)) {
1409                 if (error != NULL) {
1410                         ret = __bt_telephony_get_error(error->message);
1411                         g_error_free(error);
1412                         return ret;
1413                 }
1414         }
1415
1416         BT_DBG("-");
1417         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1418 }
1419
1420 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1421 {
1422         GError *error = NULL;
1423         int ret;
1424
1425         BT_DBG("+");
1426
1427         BT_TELEPHONY_CHECK_INITIALIZED();
1428         BT_TELEPHONY_CHECK_ENABLED();
1429
1430         if (telephony_dbus_info.proxy == NULL)
1431                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1432
1433         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1434                                 &error, G_TYPE_BOOLEAN,
1435                                 FALSE, G_TYPE_INVALID, G_TYPE_INVALID)) {
1436                 BT_ERR("Dbus Call Failed!\n");
1437                 if (error != NULL) {
1438                         ret = __bt_telephony_get_error(error->message);
1439                         g_error_free(error);
1440                         return ret;
1441                 }
1442         }
1443
1444         BT_DBG("-");
1445         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1446 }
1447
1448 BT_EXPORT_API int bluetooth_telephony_audio_open(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_ALREADY_CONNECTED;
1467
1468         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Play", &error,
1469                                         G_TYPE_INVALID, G_TYPE_INVALID)) {
1470                 BT_ERR("Dbus Call Failed!");
1471                 if (error != NULL) {
1472                         ret = __bt_telephony_get_error(error->message);
1473                         g_error_free(error);
1474                         return ret;
1475                 }
1476         }
1477         BT_DBG("-");
1478         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1479 }
1480
1481 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1482 {
1483         GError *error = NULL;
1484         int ret;
1485
1486         BT_DBG("+");
1487
1488         BT_TELEPHONY_CHECK_INITIALIZED();
1489         BT_TELEPHONY_CHECK_ENABLED();
1490
1491         if (telephony_dbus_info.proxy == NULL)
1492                 telephony_dbus_info.proxy =
1493                         __bluetooth_telephony_get_connected_device_proxy();
1494
1495         if (telephony_dbus_info.proxy == NULL)
1496                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1497
1498         if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING) {
1499                 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1500         }
1501
1502         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Stop", &error,
1503                         G_TYPE_INVALID, G_TYPE_INVALID)) {
1504                 BT_ERR("Dbus Call Failed");
1505                 if (error != NULL) {
1506                         ret = __bt_telephony_get_error(error->message);
1507                         g_error_free(error);
1508                         return ret;
1509                 }
1510         }
1511
1512         BT_DBG("-");
1513         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1514 }
1515
1516 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1517 {
1518         int ret;
1519
1520         BT_TELEPHONY_CHECK_INITIALIZED();
1521         BT_TELEPHONY_CHECK_ENABLED();
1522
1523         BT_DBG("+");
1524
1525         /*Make sure SCO is already connected */
1526         ret = __bluetooth_telephony_send_call_status(
1527                                 CSD_CALL_STATUS_MO_ALERTING, call_id);
1528         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1529                 BT_ERR("send call status Failed = [%d]", ret);
1530                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1531         }
1532         BT_DBG("-");
1533         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1534 }
1535
1536 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
1537                                                         unsigned int bt_audio)
1538 {
1539         int ret;
1540         BT_DBG("+");
1541
1542         BT_TELEPHONY_CHECK_INITIALIZED();
1543         BT_TELEPHONY_CHECK_ENABLED();
1544
1545         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1546                                                                 call_id);
1547         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1548                 BT_ERR("send call status Failed = [%d]", ret);
1549                 return ret;
1550         }
1551
1552         if (bt_audio) {
1553                 if (!bluetooth_telephony_is_sco_connected()) {
1554                         ret = bluetooth_telephony_audio_open();
1555                         if (ret != 0) {
1556                                 BT_ERR("Audio connection call Failed = %d", ret);
1557                                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1558                         }
1559                 }
1560         }
1561
1562         BT_DBG("-");
1563         return ret;
1564 }
1565
1566 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
1567 {
1568         int ret;
1569         BT_DBG("+");
1570
1571         BT_TELEPHONY_CHECK_INITIALIZED();
1572         BT_TELEPHONY_CHECK_ENABLED();
1573
1574         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
1575                                                                 call_id);
1576         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1577                 BT_ERR("send call status Failed = [%d]", ret);
1578                 return ret;
1579         }
1580         if (telephony_info.call_count > 0)
1581                 telephony_info.call_count = telephony_info.call_count - 1;
1582
1583         if (telephony_info.call_count  == 0) {
1584                 if (bluetooth_telephony_is_sco_connected()) {
1585                         ret = bluetooth_telephony_audio_close();
1586                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1587                                 BT_ERR(" Failed = [%d]", ret);
1588                                 return ret;
1589                         }
1590                 }
1591         }
1592         BT_DBG("-");
1593         return ret;
1594 }
1595
1596 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
1597 {
1598         int ret;
1599         BT_DBG("+");
1600
1601         BT_TELEPHONY_CHECK_INITIALIZED();
1602         BT_TELEPHONY_CHECK_ENABLED();
1603
1604         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
1605                                                                 call_id);
1606         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1607                 BT_ERR("send call status Failed = [%d]", ret);
1608         }
1609         BT_DBG("-");
1610         return ret;
1611 }
1612
1613 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
1614 {
1615         int ret;
1616         BT_DBG("+");
1617
1618         BT_TELEPHONY_CHECK_INITIALIZED();
1619         BT_TELEPHONY_CHECK_ENABLED();
1620
1621         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1622                                                                 call_id);
1623         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1624                 BT_ERR("send call status Failed = [%d]", ret);
1625         }
1626         BT_DBG("-");
1627         return ret;
1628 }
1629
1630 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
1631                                 unsigned int call_count)
1632 {
1633         int i;
1634         int ret;
1635         GList *list = call_list;
1636         bt_telephony_call_status_info_t *call_status;
1637
1638         BT_DBG("+");
1639
1640         BT_TELEPHONY_CHECK_INITIALIZED();
1641         BT_TELEPHONY_CHECK_ENABLED();
1642
1643         if (NULL == list) {
1644                 BT_ERR("call_list is invalid");
1645                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1646         }
1647
1648         BT_DBG(" call_count = [%d]", call_count);
1649
1650         for (i = 0; i < call_count; i++) {
1651                 call_status = g_list_nth_data(list, i);
1652
1653                 if (NULL == call_status)
1654                         continue;
1655
1656                 BT_DBG(" %d : Call id [%d] status[%d]", i,
1657                                         call_status->call_id,
1658                                         call_status->call_status);
1659
1660                 switch (call_status->call_status) {
1661                 case BLUETOOTH_CALL_STATE_HELD:
1662                         ret = __bluetooth_telephony_send_call_status(
1663                                                 CSD_CALL_STATUS_HOLD,
1664                                                 call_status->call_id);
1665                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1666                                 BT_ERR("Failed = %d", ret);
1667                                 return ret;
1668                         }
1669                 break;
1670
1671                 case BLUETOOTH_CALL_STATE_CONNECTED:
1672                         ret = __bluetooth_telephony_send_call_status(
1673                                         CSD_CALL_STATUS_ACTIVE,
1674                                         call_status->call_id);
1675                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1676                                 BT_ERR("Failed = [%d]", ret);
1677                                 return ret;
1678                         }
1679                 break;
1680
1681                 default:
1682                         if ((call_status->call_status < BLUETOOTH_CALL_STATE_NONE) ||
1683                                 (call_status->call_status >= BLUETOOTH_CALL_STATE_ERROR)) {
1684                                 BT_ERR("Unknown Call state");
1685                                 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
1686                         }
1687                 }
1688         }
1689
1690         BT_DBG("-");
1691         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1692 }
1693
1694 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
1695                                 unsigned int call_count)
1696 {
1697         int ret;
1698
1699         BT_DBG("+");
1700
1701         ret = bluetooth_telephony_call_swapped(call_list, call_count);
1702
1703         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1704                 BT_ERR("Failed = [%d]", ret);
1705                 return ret;
1706         }
1707
1708         telephony_info.call_count = call_count;
1709
1710         BT_DBG("-");
1711         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1712 }
1713
1714 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
1715                         const char *ph_number, unsigned int call_id,
1716                         unsigned int bt_audio)
1717 {
1718         DBusMessage *reply;
1719         DBusError err;
1720         const char *path = telephony_info.call_path;
1721         int ret;
1722
1723         BT_DBG("+");
1724
1725         BT_TELEPHONY_CHECK_INITIALIZED();
1726         BT_TELEPHONY_CHECK_ENABLED();
1727
1728         if (NULL == ph_number)
1729                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1730
1731         reply = __bluetooth_telephony_dbus_method_send(
1732                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1733                         "OutgoingCall", &err, DBUS_TYPE_STRING, &path,
1734                         DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1735                         &call_id, DBUS_TYPE_INVALID);
1736
1737         if (!reply) {
1738                 BT_ERR("Error returned in method call\n");
1739                 if (dbus_error_is_set(&err)) {
1740                         ret = __bt_telephony_get_error(err.message);
1741                         dbus_error_free(&err);
1742                         return ret;
1743                 }
1744                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1745         }
1746
1747         dbus_message_unref(reply);
1748
1749         telephony_info.call_count++;
1750         BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
1751
1752         if (bt_audio) {
1753                 if (!bluetooth_telephony_is_sco_connected()) {
1754                         ret = bluetooth_telephony_audio_open();
1755                         if (ret != 0) {
1756                                 BT_ERR(" Audio connection call Failed = %d", ret);
1757                                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1758                         }
1759                 }
1760         }
1761
1762         BT_DBG("-");
1763         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1764 }
1765
1766 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
1767                 const char *ph_number, unsigned int call_id)
1768 {
1769         DBusMessage *reply;
1770         DBusError err;
1771         const char *path = telephony_info.call_path;
1772         int ret;
1773
1774         BT_DBG("+");
1775
1776         BT_TELEPHONY_CHECK_INITIALIZED();
1777         BT_TELEPHONY_CHECK_ENABLED();
1778
1779         if (NULL == ph_number)
1780                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1781
1782         reply = __bluetooth_telephony_dbus_method_send(
1783                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1784                         "IncomingCall", &err, DBUS_TYPE_STRING, &path,
1785                         DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1786                         &call_id, DBUS_TYPE_INVALID);
1787
1788         if (!reply) {
1789                 BT_ERR("Error returned in method call\n");
1790                 if (dbus_error_is_set(&err)) {
1791                         ret = __bt_telephony_get_error(err.message);
1792                         dbus_error_free(&err);
1793                         return ret;
1794                 }
1795                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1796         }
1797
1798         dbus_message_unref(reply);
1799
1800         telephony_info.call_count++;
1801         BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
1802         BT_DBG("-");
1803         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1804 }
1805
1806 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(unsigned short speaker_gain)
1807 {
1808         DBusMessage *msg;
1809         DBusMessageIter iter;
1810         DBusMessageIter value;
1811         DBusConnection *conn;
1812         char *spkr_gain_str = "SpeakerGain";
1813         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1814
1815         BT_DBG("+");
1816         BT_DBG("set speaker_gain= [%d]", speaker_gain);
1817
1818         BT_TELEPHONY_CHECK_INITIALIZED();
1819         BT_TELEPHONY_CHECK_ENABLED();
1820
1821         conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1822
1823         if (telephony_info.obj_path == NULL)
1824                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1825
1826         msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME,
1827                         telephony_info.obj_path, BLUEZ_HEADSET_INTERFACE,
1828                         "SetProperty");
1829
1830         if (NULL != msg) {
1831                 char sig[2] = {DBUS_TYPE_UINT16, '\0'};
1832
1833                 dbus_message_iter_init_append(msg, &iter);
1834                 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
1835                                 &spkr_gain_str);
1836                 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1837                                 sig, &value);
1838                 dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT16,
1839                                 &speaker_gain);
1840                 dbus_message_iter_close_container(&iter, &value);
1841
1842                 if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
1843                         dbus_message_set_no_reply(msg, TRUE);
1844                 if (!dbus_connection_send(conn, msg, NULL)) {
1845                         BT_ERR("bluetooth_telephony_set_speaker_gain : dbus sending failed");
1846                         ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1847                 }
1848                 dbus_message_unref(msg);
1849         } else
1850                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1851
1852         BT_DBG("-");
1853         return ret;
1854 }
1855
1856 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(unsigned int *speaker_gain)
1857 {
1858         GHashTable *hash = NULL;
1859         GValue *value = NULL;
1860         GError *error = NULL;
1861         int ret;
1862
1863         BT_DBG("+");
1864         BT_TELEPHONY_CHECK_INITIALIZED();
1865         BT_TELEPHONY_CHECK_ENABLED();
1866
1867         if (telephony_dbus_info.proxy == NULL)
1868                 telephony_dbus_info.proxy =
1869                         __bluetooth_telephony_get_connected_device_proxy();
1870
1871         if (telephony_dbus_info.proxy == NULL)
1872                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1873
1874         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "GetProperties", &error,
1875                           G_TYPE_INVALID,
1876                           dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
1877                           &hash, G_TYPE_INVALID)) {
1878                 BT_ERR("Dbus Call Failed!");
1879                 if (error != NULL) {
1880                         ret = __bt_telephony_get_error(error->message);
1881                         g_error_free(error);
1882                         return ret;
1883                 }
1884         }
1885
1886         if (hash == NULL)
1887                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1888
1889         value = g_hash_table_lookup(hash, "SpeakerGain");
1890         *speaker_gain = g_value_get_uint(value);
1891         g_hash_table_destroy(hash);
1892         BT_DBG("-");
1893         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1894 }