Upgrade Bluetooth-frwk to match Bluez5.X
[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 #define BLUEZ_SERVICE_NAME "org.bluez"
52 #define BLUEZ_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager"
53 #define BLUEZ_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
54 #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1"
55 #define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1"
56
57 #define HFP_AGENT_SERVICE "org.bluez.hfp_agent"
58 #define HFP_AGENT_PATH "/org/bluez/hfp_ag"
59 #define HFP_AGENT_INTERFACE "Org.Hfp.App.Interface"
60
61 #define CSD_CALL_APP_PATH "/org/tizen/csd/%d"
62 #define HFP_NREC_STATUS_CHANGE "NrecStatusChanged"
63
64 #define BT_TELEPHONY_CHECK_ENABLED() \
65         do { \
66                 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) \
67                 { \
68                         BT_ERR("BT is not enabled"); \
69                         return BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED; \
70                 } \
71         } while (0)
72
73 static gboolean is_initialized = FALSE;
74 #define BT_TELEPHONY_CHECK_INITIALIZED() \
75         do { \
76                 if (is_initialized == FALSE) \
77                 { \
78                         BT_ERR("Bluetooth telephony not initilized"); \
79                         return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED; \
80                 } \
81         } while (0)
82
83 #define BLUETOOTH_TELEPHONY_METHOD (bluetooth_telephony_method_get_type())
84 #define BLUETOOTH_TELEPHONY_METHOD_GET_OBJECT(obj) \
85                 (G_TYPE_CHECK_INSTANCE_CAST((obj), \
86                 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethod))
87
88 #define BLUETOOTH_TELEPHONY_METHOD_IS_OBJECT(obj) \
89                 (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
90                 BLUETOOTH_TELEPHONY_METHOD))
91
92 #define BLUETOOTH_TELEPHONY_METHOD_CLASS(class) \
93                 (G_TYPE_CHECK_CLASS_CAST((class), \
94                 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))
95
96 #define BLUETOOTH_TELEPHONY_METHOD_GET_AGENT_CLASS(obj) \
97                 (G_TYPE_INSTANCE_GET_CLASS((obj), \
98                 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))
99
100 #define BLUETOOTH_TELEPHONY_METHOD_IS_AGENT_CLASS(class) \
101                 (G_TYPE_CHECK_CLASS_TYPE((class), BLUETOOTH_TELEPHONY_METHOD))
102
103 #define BLUETOOTH_TELEPHONY_METHOD_AGENT_GET_PRIVATE(obj) \
104                 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
105                 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodPrivate))
106
107 typedef struct _BluetoothTelephonyMethod BluetoothTelephonyMethod;
108 typedef struct _BluetoothTelephonyMethodClass BluetoothTelephonyMethodClass;
109
110 struct _BluetoothTelephonyMethod {
111         GObject parent;
112 };
113
114 struct _BluetoothTelephonyMethodClass {
115         GObjectClass parent_class;
116 };
117
118 BluetoothTelephonyMethod *bluetooth_telephony_method_new(void);
119 GType bluetooth_telephony_method_get_type(void);
120
121 G_DEFINE_TYPE(BluetoothTelephonyMethod, bluetooth_telephony_method, G_TYPE_OBJECT)
122
123 static DBusHandlerResult __bt_telephony_adapter_filter(DBusConnection *conn,
124            DBusMessage *msg, void *data);
125
126 static int __bt_telephony_get_object_path(DBusMessage *msg, char **path);
127
128 static char *__bt_extract_device_path(DBusMessageIter *msg_iter, char *address);
129
130 static char *_bt_get_device_object_path(char *address);
131
132 static void _bt_convert_device_path_to_address(const char *device_path,
133                                                 char *device_address);
134
135 static char *__bt_get_default_adapter_path(DBusMessageIter *msg_iter);
136
137 static gboolean bluetooth_telephony_method_answer(BluetoothTelephonyMethod *object,
138                                 guint callid,
139                                 DBusGMethodInvocation *context);
140
141 static gboolean bluetooth_telephony_method_release(
142                                 BluetoothTelephonyMethod *object, guint callid,
143                                 DBusGMethodInvocation *context);
144
145 static gboolean bluetooth_telephony_method_reject(BluetoothTelephonyMethod  *object,
146                                 guint callid, DBusGMethodInvocation *context);
147
148 static gboolean bluetooth_telephony_method_threeway(
149                                 BluetoothTelephonyMethod *object, guint value,
150                                 DBusGMethodInvocation *context);
151
152 static gboolean bluetooth_telephony_method_send_dtmf(
153                                 BluetoothTelephonyMethod *object,
154                                 gchar *dtmf, DBusGMethodInvocation *context);
155
156 #include "bt-telephony-glue.h"
157
158 static GObject *object;
159 static bt_telephony_info_t telephony_info;
160 static telephony_dbus_info_t telephony_dbus_info;
161 static gboolean is_active = FALSE;
162
163 /*Function Declaration*/
164 static int __bt_telephony_get_error(const char *error_message);
165 static void __bt_telephony_event_cb(int event, int result, void *param_data);
166 static GQuark __bluetooth_telephony_error_quark(void);
167 static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path,
168                         const char *interface, const char *method, DBusError *err,  int type, ...);
169 static int __bluetooth_telephony_send_call_status(
170                         bt_telephony_call_status_t call_status,
171                         unsigned int call_id);
172 static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
173                                         const char *err_msg);
174
175 static DBusHandlerResult __bluetooth_telephony_event_filter(
176                                                 DBusConnection *conn,
177                                                 DBusMessage *msg, void *data);
178
179 static int __bluetooth_telephony_proxy_init(void);
180 static void __bluetooth_telephony_proxy_deinit(void);
181 static int __bluetooth_telephony_register(void);
182 static int __bluetooth_telephony_unregister(void);
183 static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
184                                                         char *path);
185 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class);
186 static int __bluetooth_telephony_get_connected_device(void);
187 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void);
188
189 /*Function Definition*/
190 static int __bt_telephony_get_error(const char *error_message)
191 {
192         if (error_message == NULL) {
193                 BT_DBG("Error message NULL\n");
194                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
195         }
196
197         BT_DBG("Error message = %s \n", error_message);
198         if (g_strcmp0(error_message, "NotAvailable") == 0)
199                 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
200         else if (g_strcmp0(error_message, "NotConnected") == 0)
201                 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
202         else if (g_strcmp0(error_message, "InProgress") == 0)
203                 return BLUETOOTH_TELEPHONY_ERROR_BUSY;
204         else if (g_strcmp0(error_message, "InvalidArguments") == 0)
205                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
206         else if (g_strcmp0(error_message, "AlreadyExists") == 0)
207                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST;
208         else if (g_strcmp0(error_message, "Already Connected") == 0)
209                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
210         else if (g_strcmp0(error_message, "No memory") == 0)
211                 return BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY;
212         else if (g_strcmp0(error_message, "I/O error") == 0)
213                 return BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR;
214         else if (g_strcmp0(error_message, "Operation currently not available") == 0)
215                 return BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE;
216         else
217                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
218 }
219
220 static void __bt_telephony_event_cb(int event, int result, void *param_data)
221 {
222         telephony_event_param_t bt_event = { 0, };
223
224         bt_event.event = event;
225         bt_event.result = result;
226         bt_event.param_data = param_data;
227
228         ret_if(telephony_info.cb == NULL);
229         telephony_info.cb(bt_event.event, &bt_event, telephony_info.user_data);
230         return;
231 }
232
233 static GQuark __bluetooth_telephony_error_quark(void)
234 {
235         static GQuark quark = 0;
236
237         quark = g_quark_from_static_string("telephony");
238
239         return quark;
240 }
241
242 static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path,
243                         const char *interface, const char *method, DBusError *err,  int type, ...)
244 {
245         DBusMessage *msg;
246         DBusMessage *reply;
247         va_list args;
248
249         BT_DBG("+");
250
251         msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
252                         path, interface, method);
253         if (!msg) {
254                 BT_ERR("Unable to allocate new D-Bus %s message \n", method);
255                 return NULL;
256         }
257
258         va_start(args, type);
259
260         if (!dbus_message_append_args_valist(msg, type, args)) {
261                 dbus_message_unref(msg);
262                 va_end(args);
263                 return NULL;
264         }
265
266         va_end(args);
267
268         dbus_error_init(err);
269
270         reply = dbus_connection_send_with_reply_and_block(
271                 dbus_g_connection_get_connection(telephony_dbus_info.conn),
272                 msg, -1, err);
273
274         dbus_message_unref(msg);
275
276         BT_DBG("-");
277         return reply;
278 }
279
280 static int __bluetooth_telephony_send_call_status(
281                         bt_telephony_call_status_t call_status,
282                         unsigned int call_id)
283 {
284         DBusMessage *reply;
285         DBusError err;
286         char *path = g_strdup(telephony_info.call_path);
287         int ret;
288
289         BT_DBG("+");
290
291         reply = __bluetooth_telephony_dbus_method_send(
292                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
293                         "ChangeCallStatus", &err, DBUS_TYPE_STRING, &path,
294                         DBUS_TYPE_INT32, &call_status,
295                         DBUS_TYPE_INT32, &call_id, DBUS_TYPE_INVALID);
296         g_free(path);
297
298         if (!reply) {
299                 BT_ERR("Error returned in method call\n");
300                 if (dbus_error_is_set(&err)) {
301                         ret = __bt_telephony_get_error(err.message);
302                         dbus_error_free(&err);
303                         return ret;
304                 }
305                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
306         }
307
308         dbus_message_unref(reply);
309
310         return BLUETOOTH_TELEPHONY_ERROR_NONE;
311 }
312
313 static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
314                                         const char *err_msg)
315 {
316         return g_error_new(BLUETOOTH_TELEPHONY_ERROR, error, err_msg, NULL);
317 }
318
319 static void bluetooth_telephony_method_init(BluetoothTelephonyMethod *object)
320 {
321         BT_DBG("+");
322         BT_DBG("agent %p\n", object);
323         BT_DBG("-");
324 }
325
326 static void __bluetooth_telephony_method_finalize(
327                                         BluetoothTelephonyMethod *object)
328 {
329         BT_DBG("+");
330         G_OBJECT_CLASS(bluetooth_telephony_method_parent_class)->finalize((
331                                                         GObject *)object);
332         BT_DBG("-");
333 }
334
335 static BluetoothTelephonyMethod *__bluetooth_telephony_method_new(void)
336 {
337         BluetoothTelephonyMethod *obj;
338
339         BT_DBG("+");
340         obj = g_object_new(BLUETOOTH_TELEPHONY_METHOD, NULL);
341         BT_DBG("-");
342
343         return obj;
344 }
345
346 static void bluetooth_telephony_method_class_init(
347                                         BluetoothTelephonyMethodClass *klass)
348 {
349         GObjectClass *object_class = NULL;
350         BT_DBG("+");
351
352         object_class = G_OBJECT_CLASS(klass);
353         object_class->finalize = (void *)__bluetooth_telephony_method_finalize;
354
355         /*Registration of the Framework methods */
356         dbus_g_object_type_install_info(BLUETOOTH_TELEPHONY_METHOD,
357                         &dbus_glib_bluetooth_telephony_method_object_info);
358         BT_DBG("-");
359         return;
360 }
361
362 static gboolean bluetooth_telephony_method_answer(
363                                 BluetoothTelephonyMethod *object,
364                                 guint callid, DBusGMethodInvocation *context)
365 {
366         telephony_event_callid_t call_data = { 0, };
367
368         BT_DBG("+");
369         BT_DBG("call_id = [%d]", callid);
370
371         call_data.callid = callid;
372
373         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL,
374                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
375                                         (void *)&call_data);
376
377         dbus_g_method_return(context);
378         BT_DBG("-");
379         return TRUE;
380 }
381
382 static gboolean bluetooth_telephony_method_release(
383                                 BluetoothTelephonyMethod *object,
384                                 guint callid, DBusGMethodInvocation *context)
385 {
386         telephony_event_callid_t call_data = { 0, };
387
388         BT_DBG("+");
389         BT_DBG("call_id = [%d]\n", callid);
390
391         call_data.callid = callid;
392
393         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL,
394                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
395                                         (void *)&call_data);
396
397         dbus_g_method_return(context);
398         BT_DBG("-");
399         return TRUE;
400
401 }
402
403 static gboolean bluetooth_telephony_method_reject(
404                                 BluetoothTelephonyMethod *object,
405                                 guint callid, DBusGMethodInvocation *context)
406 {
407         telephony_event_callid_t call_data = { 0, };
408
409         BT_DBG("+");
410         BT_DBG("call_id = [%d]", callid);
411
412         call_data.callid = callid;
413
414         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_REJECT_CALL,
415                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
416                                         (void  *)&call_data);
417
418         dbus_g_method_return(context);
419         BT_DBG("-");
420         return TRUE;
421 }
422
423 static gboolean bluetooth_telephony_method_threeway(
424                                 BluetoothTelephonyMethod *object,
425                                 guint value, DBusGMethodInvocation *context)
426 {
427         int event = 0;
428         GError *err;
429
430         BT_DBG("+");
431         BT_DBG("chld value  = [%d]", value);
432
433         switch (value) {
434         case 0:
435                 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL;
436                 break;
437         case 1:
438                 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL;
439                 break;
440         case 2:
441                 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL;
442                 break;
443         case 3:
444                 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL;
445                 break;
446         default:
447                 BT_ERR("Invalid CHLD command");
448                 err = __bluetooth_telephony_error(
449                         BLUETOOTH_TELEPHONY_ERROR_INVALID_CHLD_INDEX,
450                         "Invalid chld command");
451                 dbus_g_method_return_error(context, err);
452                 g_error_free(err);
453                 return FALSE;
454         }
455
456         BT_DBG("event  = [%d]", event);
457
458         __bt_telephony_event_cb(event,
459                         BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
460         dbus_g_method_return(context);
461         BT_DBG("-");
462         return TRUE;
463 }
464
465 static gboolean bluetooth_telephony_method_send_dtmf(
466                                 BluetoothTelephonyMethod *object,
467                                 gchar *dtmf, DBusGMethodInvocation *context)
468 {
469         telephony_event_dtmf_t call_data = { 0, };
470         GError *err;
471
472         BT_DBG("+");
473
474         if (dtmf == NULL) {
475                 BT_DBG("Number dial failed\n");
476                 err = __bluetooth_telephony_error(
477                                 BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF,
478                                 "Invalid dtmf");
479                 dbus_g_method_return_error(context, err);
480                 g_error_free(err);
481                 return FALSE;
482         }
483
484         BT_DBG("Dtmf = %s \n", dtmf);
485
486         call_data.dtmf = g_strdup(dtmf);
487
488         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF,
489                 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&call_data);
490
491         dbus_g_method_return(context);
492         g_free(call_data.dtmf);
493         BT_DBG("-");
494         return TRUE;
495 }
496
497 static void __bluetooth_handle_nrec_status_change(DBusMessage *msg)
498 {
499         gboolean status = FALSE;
500
501         if (!dbus_message_get_args(msg, NULL,
502                                 DBUS_TYPE_BOOLEAN, &status,
503                                 DBUS_TYPE_INVALID)) {
504                 BT_DBG("Error Getting parameters\n");
505                 return;
506         }
507         BT_DBG("NREC status = %d\n", status);
508
509         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED,
510                 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&status);
511
512 }
513
514 static DBusHandlerResult __bluetooth_telephony_event_filter(
515                                                 DBusConnection *conn,
516                                                 DBusMessage *msg, void *data)
517 {
518         const char *path = dbus_message_get_path(msg);
519         char *dev_addr = NULL;
520         DBusMessageIter item_iter;
521         DBusMessageIter value_iter;
522         const char *property;
523
524         /* Check NREC status change Signal*/
525         if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
526                                 HFP_NREC_STATUS_CHANGE)) {
527                 __bluetooth_handle_nrec_status_change(msg);
528                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
529         }
530
531         if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
532                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
533
534         dbus_message_iter_init(msg, &item_iter);
535         if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
536                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
537         }
538
539         dbus_message_iter_get_basic(&item_iter, &property);
540
541         if (property == NULL)
542                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
543
544         BT_DBG("Property (%s)\n", property);
545
546         if (g_strcmp0(property, "State") == 0) {
547                 char *state = NULL;
548                 dbus_message_iter_next(&item_iter);
549                 dbus_message_iter_recurse(&item_iter, &value_iter);
550                 dbus_message_iter_get_basic(&value_iter, &state);
551                 if (NULL == state) {
552                         BT_ERR("State is null\n");
553                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
554                 }
555                 BT_DBG("State %s\n", state);
556
557                 if (g_strcmp0(state, "connected") == 0) {
558                         telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
559                 } else if (g_strcmp0(state, "playing") == 0) {
560                         telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
561                 } else if (g_strcmp0(state, "disconnected") == 0) {
562                         /* Headset state: playing -> disconnected */
563                         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) {
564                                 if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, FALSE)) {
565                                         BT_DBG("SVCONFKEY_BT_HEADSET_SCO - Set to FALSE\n");
566                                 } else {
567                                          BT_DBG("vconf_set_bool - Failed\n");
568                                 }
569
570                                 __bt_telephony_event_cb(
571                                          BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
572                                          BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
573                         }
574
575                         telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
576                 }
577
578                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
579         }
580
581         if (g_strcmp0(property, "Connected") == 0) {
582                 gboolean connected = FALSE;
583                 dbus_message_iter_next(&item_iter);
584                 dbus_message_iter_recurse(&item_iter, &value_iter);
585                 dbus_message_iter_get_basic(&value_iter, &connected);
586                 BT_DBG("Connected %d\n", connected);
587
588                 if (connected) {
589                         /*Get device address*/
590                         if (path != NULL)
591                                 dev_addr = strstr(path, "dev_");
592
593                         if (dev_addr != NULL) {
594                                 dev_addr += 4;
595                                 g_strlcpy(telephony_info.address,
596                                         dev_addr,
597                                         sizeof(telephony_info.address));
598                                 g_strdelimit(telephony_info.address, "_", ':');
599                                 BT_DBG("address is %s",
600                                         telephony_info.address);
601
602                                 telephony_info.headset_state =
603                                                 BLUETOOTH_STATE_CONNECTED;
604
605                                 if (telephony_dbus_info.proxy != NULL) {
606                                         g_object_unref(telephony_dbus_info.proxy);
607                                         telephony_dbus_info.proxy = NULL;
608                                 }
609
610                                 telephony_dbus_info.proxy =
611                                                 __bluetooth_telephony_get_connected_device_proxy();
612
613                                 BT_DBG("Headset Connected");
614
615                                  __bt_telephony_event_cb(
616                                                 BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED,
617                                                 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
618                         }
619                 } else { /*Device disconnected*/
620                         memset(telephony_info.address, 0x00,
621                                         sizeof(telephony_info.address));
622                         telephony_info.headset_state =
623                                                 BLUETOOTH_STATE_DISCONNETED;
624
625                         if (telephony_dbus_info.proxy != NULL) {
626                                 g_object_unref(telephony_dbus_info.proxy);
627                                 telephony_dbus_info.proxy = NULL;
628                         }
629
630                         BT_DBG("Headset Disconnected");
631
632                          __bt_telephony_event_cb(
633                                         BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED,
634                                         BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
635                 }
636                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
637         }
638
639         if (g_strcmp0(property, "SpeakerGain") == 0) {
640                 unsigned int spkr_gain;
641                 guint16 gain;
642                 dbus_message_iter_next(&item_iter);
643                 dbus_message_iter_recurse(&item_iter, &value_iter);
644                 dbus_message_iter_get_basic(&value_iter, &gain);
645
646                 spkr_gain = (unsigned int)gain;
647                 BT_DBG("spk_gain[%d]\n", spkr_gain);
648
649                 __bt_telephony_event_cb(
650                                         BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN,
651                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
652                                         (void *)&spkr_gain);
653
654                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
655         }
656
657         if (g_strcmp0(property, "MicrophoneGain") == 0) {
658                 unsigned int mic_gain;
659                 guint16 gain;
660                 dbus_message_iter_next(&item_iter);
661                 dbus_message_iter_recurse(&item_iter, &value_iter);
662                 dbus_message_iter_get_basic(&value_iter, &gain);
663
664                 mic_gain = (unsigned int)gain;
665                 BT_DBG("mic_gain[%d]\n", mic_gain);
666
667                 __bt_telephony_event_cb(
668                                         BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN,
669                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
670                                         (void *)&mic_gain);
671
672                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
673         }
674
675         if (g_strcmp0(property, "Playing") == 0) {
676                 gboolean audio_sink_playing = FALSE;
677                 dbus_message_iter_next(&item_iter);
678                 dbus_message_iter_recurse(&item_iter, &value_iter);
679                 dbus_message_iter_get_basic(&value_iter, &audio_sink_playing);
680
681                 if (audio_sink_playing) {
682                         if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, TRUE)) {
683                                 BT_DBG("SVCONFKEY_BT_HEADSET_SCO -"
684                                         "Set to TRUE\n");
685                         } else {
686                                 BT_DBG("vconf_set_bool - Failed\n");
687                         }
688                         telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
689                          __bt_telephony_event_cb(
690                                 BLUETOOTH_EVENT_TELEPHONY_AUDIO_CONNECTED,
691                                 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
692                 } else {
693                         if (!vconf_set_bool(VCONFKEY_BT_HEADSET_SCO, FALSE)) {
694                                 BT_DBG("SVCONFKEY_BT_HEADSET_SCO -"
695                                                 "Set to FALSE\n");
696                         } else {
697                                 BT_DBG("vconf_set_bool - Failed\n");
698                         }
699                         telephony_info.headset_state =
700                                                 BLUETOOTH_STATE_CONNECTED;
701                         __bt_telephony_event_cb(
702                                 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
703                                 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
704                 }
705
706                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
707         }
708         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
709 }
710
711 static int __bluetooth_telephony_proxy_init(void)
712 {
713         BT_DBG("+");
714
715         object = (GObject *)__bluetooth_telephony_method_new();
716
717         if (NULL == object)
718                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
719
720         BT_DBG("telephony_object = %x", object);
721
722         dbus_g_connection_register_g_object(telephony_dbus_info.conn,
723                         telephony_info.call_path, G_OBJECT(object));
724
725         BT_DBG("-");
726         return BLUETOOTH_TELEPHONY_ERROR_NONE;
727 }
728
729 static void __bluetooth_telephony_proxy_deinit(void)
730 {
731         BT_DBG("+");
732
733         dbus_g_connection_unregister_g_object(telephony_dbus_info.conn,
734                                 G_OBJECT(object));
735
736         g_object_unref(object);
737         object = NULL;
738
739         BT_DBG("-");
740         return;
741 }
742
743 static int __bluetooth_telephony_register(void)
744 {
745         DBusMessage *reply;
746         DBusError err;
747         char *path = g_strdup(telephony_info.call_path);
748         int ret;
749
750         BT_DBG("+");
751
752         reply =  __bluetooth_telephony_dbus_method_send(
753                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
754                         "RegisterApplication", &err, DBUS_TYPE_STRING, &path,
755                         DBUS_TYPE_INVALID);
756
757         g_free(path);
758         if (!reply) {
759                 BT_ERR("Error returned in method call\n");
760                 if (dbus_error_is_set(&err)) {
761                         ret = __bt_telephony_get_error(err.message);
762                         BT_ERR("Error here %d\n", ret);
763                         dbus_error_free(&err);
764                         return ret;
765                 }
766                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
767         }
768
769         dbus_message_unref(reply);
770         BT_DBG("-");
771         return BLUETOOTH_TELEPHONY_ERROR_NONE;
772 }
773
774 static  int __bluetooth_telephony_unregister(void)
775 {
776         DBusMessage *reply;
777         DBusError err;
778         char *path = g_strdup(telephony_info.call_path);
779         int ret;
780
781         BT_DBG("+");
782
783         reply = __bluetooth_telephony_dbus_method_send(
784                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
785                         "UnregisterApplication", &err, DBUS_TYPE_STRING, &path,
786                         DBUS_TYPE_INVALID);
787
788         g_free(path);
789         if (!reply) {
790                 BT_ERR("Error returned in method call\n");
791                 if (dbus_error_is_set(&err)) {
792                         ret = __bt_telephony_get_error(err.message);
793                         dbus_error_free(&err);
794                         return ret;
795                 }
796                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
797         }
798
799         dbus_message_unref(reply);
800         BT_DBG("+");
801         return BLUETOOTH_TELEPHONY_ERROR_NONE;
802 }
803
804 static int __bluetooth_get_default_adapter_path(DBusGConnection *GConn,
805                                                         char *path)
806 {
807         DBusMessage *msg;
808         DBusMessage *reply;
809         DBusMessageIter reply_iter;
810         DBusMessageIter value_iter;
811         DBusError err;
812         DBusConnection *conn;
813         char *adapter_path = NULL;
814
815         BT_DBG("+");
816
817         conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
818
819         retv_if(conn == NULL, NULL);
820
821         msg = dbus_message_new_method_call(BT_BLUEZ_NAME, BT_MANAGER_PATH,
822                         BT_MANAGER_INTERFACE,
823                         "GetManagedObjects");
824
825         retv_if(msg == NULL, NULL);
826         /* Synchronous call */
827         dbus_error_init(&err);
828         reply = dbus_connection_send_with_reply_and_block(
829                                 conn, msg, -1, &err);
830         dbus_message_unref(msg);
831
832         if (!reply) {
833                 BT_ERR("Can't get managed objects");
834
835                 if (dbus_error_is_set(&err)) {
836                         BT_ERR("%s", err.message);
837                         dbus_error_free(&err);
838                 }
839                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
840         }
841
842         if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
843         BT_ERR("Fail to iterate the reply");
844         return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
845         }
846
847         dbus_message_iter_recurse(&reply_iter, &value_iter);
848
849         /* signature of GetManagedObjects:  a{oa{sa{sv}}} */
850         while (dbus_message_iter_get_arg_type(&value_iter) ==
851                                 DBUS_TYPE_DICT_ENTRY) {
852                 DBusMessageIter msg_iter;
853
854                 dbus_message_iter_recurse(&value_iter, &msg_iter);
855
856                 adapter_path = __bt_get_default_adapter_path(&msg_iter);
857                 if (adapter_path != NULL) {
858                         BT_DBG("Found the adapter path");
859                         break;
860                 }
861                 dbus_message_iter_next(&value_iter);
862         }
863
864         if (adapter_path == NULL) {
865                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
866         }
867
868         if (strlen(adapter_path) >= BT_ADAPTER_PATH_LEN) {
869                 BT_ERR("Path too long.\n");
870                 g_free(adapter_path);
871                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
872         }
873
874         BT_DBG("object path = %s", adapter_path);
875         g_strlcpy(path, adapter_path, BT_ADAPTER_PATH_LEN);
876         g_free(adapter_path);
877         BT_DBG("-");
878         return BLUETOOTH_TELEPHONY_ERROR_NONE;
879 }
880
881 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
882 {
883         gboolean flag = FALSE;
884         BT_DBG("+");
885
886         switch ((device_class & 0x1f00) >> 8) {
887         case 0x04:
888                 switch ((device_class & 0xfc) >> 2) {
889                 case 0x01:
890                 case 0x02:
891                         flag = TRUE;
892                         break;
893                 case 0x06:
894                         flag = TRUE;
895                         break;
896                 case 0x0b:
897                 case 0x0c:
898                 case 0x0d:
899                         break;
900                 default:
901                         flag = TRUE;
902                         break;
903                 }
904                 break;
905         }
906         BT_DBG("-");
907         return flag;
908 }
909
910 static int __bluetooth_telephony_get_connected_device(void)
911 {
912         DBusMessage *msg;
913         DBusMessage *reply;
914         DBusMessageIter reply_iter;
915         DBusMessageIter value_iter;
916         DBusError err;
917         DBusConnection *conn;
918         DBusGProxy *headset_agent_proxy = NULL;
919
920         GError *error = NULL;
921         uint32_t device_class;
922         gboolean playing = FALSE;
923         gboolean connected = FALSE;
924         GHashTable *list_hash;
925         GValue *value = {0};
926         char *object_path = NULL;
927         DBusGProxy *proxy = NULL;
928         const gchar *address;
929
930         conn = _bt_get_system_conn();
931         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
932
933         msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME, "/",
934                                                 BLUEZ_MANAGER_INTERFACE,
935                                                 "GetManagedObjects");
936
937         retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
938
939         /* Synchronous call */
940         dbus_error_init(&err);
941         reply = dbus_connection_send_with_reply_and_block(
942                                         conn, msg,
943                                         -1, &err);
944         dbus_message_unref(msg);
945
946         if (!reply) {
947                 BT_ERR("Can't get managed objects");
948
949                 if (dbus_error_is_set(&err)) {
950                         BT_ERR("%s", err.message);
951                         dbus_error_free(&err);
952                 }
953                 return BLUETOOTH_ERROR_INTERNAL;
954         }
955
956         if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
957                 BT_ERR("Fail to iterate the reply");
958                 return BLUETOOTH_ERROR_INTERNAL;
959         }
960
961         dbus_message_iter_recurse(&reply_iter, &value_iter);
962
963         /* signature of GetManagedObjects:      a{oa{sa{sv}}} */
964         while (dbus_message_iter_get_arg_type(&value_iter) ==
965                                                 DBUS_TYPE_DICT_ENTRY) {
966                 DBusMessageIter msg_iter;
967
968                 dbus_message_iter_recurse(&value_iter, &msg_iter);
969
970                 /* Parse the signature: oa{sa{sv}}} */
971                 retv_if(dbus_message_iter_get_arg_type(&msg_iter) !=
972                                 DBUS_TYPE_OBJECT_PATH, NULL);
973
974                 dbus_message_iter_get_basic(&msg_iter, &object_path);
975
976
977                 if (object_path) {
978                         proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
979                                           BLUEZ_SERVICE_NAME, object_path,
980                       BLUEZ_PROPERTIES_INTERFACE);
981
982                         if (proxy == NULL)
983                                 goto done;
984
985                         dbus_g_proxy_call(proxy, "GetAll", &err,
986                                                 G_TYPE_STRING, BLUEZ_DEVICE_INTERFACE,
987                                                 G_TYPE_INVALID,
988                                                 dbus_g_type_get_map("GHashTable", G_TYPE_STRING,
989                                                 G_TYPE_VALUE), &list_hash, G_TYPE_INVALID);
990
991                         if (list_hash != NULL) {
992                                 value = g_hash_table_lookup(list_hash, "Class");
993                                 device_class = value ? g_value_get_uint(value) : 0;
994                         }
995
996                         if (!__bluetooth_telephony_is_headset(device_class)) {
997                                 g_object_unref(proxy);
998                                 proxy = NULL;
999                                 g_hash_table_destroy(list_hash);
1000                                 dbus_message_iter_next(&value_iter);
1001                                 continue;
1002                         }
1003                         /* this is headset; Check for Connection */
1004                         headset_agent_proxy = dbus_g_proxy_new_for_name(
1005                                                 telephony_dbus_info.conn,
1006                                                 HFP_AGENT_SERVICE, object_path,
1007                                                 HFP_AGENT_INTERFACE);
1008
1009                         if (headset_agent_proxy == NULL) {
1010                                 g_hash_table_destroy(list_hash);
1011                                 goto done;
1012                         }
1013
1014                         dbus_g_proxy_call(headset_agent_proxy, "IsConnected",
1015                                         &error, G_TYPE_INVALID,
1016                                         &connected, G_TYPE_INVALID);
1017
1018                         if (error == NULL) {
1019                                 if (connected) {
1020                                         value = g_hash_table_lookup(list_hash,
1021                                                                         "Address");
1022                                         address = value ? g_value_get_string(
1023                                                                          value) : NULL;
1024
1025                                         g_strlcpy(telephony_info.address, address,
1026                                                                         sizeof(telephony_info.address));
1027                                         dbus_g_proxy_call(headset_agent_proxy, "IsPlaying",
1028                                                                         &error, G_TYPE_INVALID,
1029                                                                         &playing, G_TYPE_INVALID);
1030
1031                                         if (playing)
1032                                                 telephony_info.headset_state =
1033                                                         BLUETOOTH_STATE_PLAYING;
1034                                         else
1035                                                 telephony_info.headset_state =
1036                                                         BLUETOOTH_STATE_CONNECTED;
1037
1038                                         g_hash_table_destroy(list_hash);
1039                                         goto done;
1040                                 }
1041                         } else {
1042                                 g_error_free(error);
1043                         }
1044
1045                         g_hash_table_destroy(list_hash);
1046                         g_object_unref(proxy);
1047                         proxy = NULL;
1048                 } /* end of if(object_path) */
1049
1050         dbus_message_iter_next(&value_iter);
1051         } /* end of while */
1052
1053 done:
1054         if (proxy)
1055                 g_object_unref(proxy);
1056         BT_DBG("-");
1057         return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1058 }
1059
1060 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1061 {
1062         DBusGProxy *proxy = NULL;
1063         char *object_path = NULL;
1064
1065         BT_DBG("+");
1066
1067         if (strlen(telephony_info.address) == 0)
1068                 __bluetooth_telephony_get_connected_device();
1069
1070         if (strlen(telephony_info.address) == 0) {
1071                 return NULL;
1072         }
1073
1074         if (telephony_info.obj_path) {
1075                 g_free(telephony_info.obj_path);
1076                 telephony_info.obj_path = NULL;
1077         }
1078
1079         object_path = _bt_get_device_object_path(telephony_info.address);
1080         g_strlcpy(telephony_info.obj_path, object_path, BT_ADAPTER_PATH_LEN);
1081
1082         proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
1083                         HFP_AGENT_SERVICE, telephony_info.obj_path,
1084                         HFP_AGENT_INTERFACE);
1085
1086         return proxy;
1087 }
1088
1089 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1090                                                         void  *user_data)
1091 {
1092         DBusError dbus_error;
1093         DBusConnection *conn;
1094         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1095         GError *error = NULL;
1096         char object_path[BT_ADAPTER_PATH_LEN] = {0};
1097         BT_DBG("+");
1098         DBusConnection *dbus_conn;
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         dbus_conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1163
1164         /*Add Signal callback for BT enabled*/
1165         if (!dbus_connection_add_filter(dbus_conn, __bt_telephony_adapter_filter,
1166                                         NULL, NULL)) {
1167                 BT_ERR("Fail to add filter");
1168                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1169         }
1170
1171         dbus_error_init(&dbus_error);
1172
1173         dbus_bus_add_match(dbus_conn,
1174                         "type='signal',interface='org.freedesktop.DBus.ObjectManager'"
1175                         ",member='InterfacesAdded'",
1176                         &dbus_error);
1177
1178         if (dbus_error_is_set(&dbus_error)) {
1179                 BT_ERR("Fail to add match: %s\n", dbus_error.message);
1180                 dbus_error_free(&dbus_error);
1181                 goto fail;
1182         }
1183
1184         /*Callback and user applicaton data*/
1185         telephony_info.cb = cb;
1186         telephony_info.user_data = user_data;
1187         telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1188
1189         dbus_error_init(&dbus_error);
1190         conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1191         dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
1192                                 NULL, NULL);
1193
1194         dbus_bus_add_match(conn,
1195                         "type='signal',interface='"HFP_AGENT_SERVICE
1196                         "',member='PropertyChanged'", &dbus_error);
1197         dbus_bus_add_match(conn,
1198                         "type='signal',interface='"HFP_AGENT_SERVICE
1199                         "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error);
1200
1201         if (dbus_error_is_set(&dbus_error)) {
1202                 BT_ERR("Fail to add dbus filter signal\n");
1203                 dbus_error_free(&dbus_error);
1204                 goto fail;
1205         }
1206
1207         /*Check for BT status*/
1208         ret = __bluetooth_get_default_adapter_path(telephony_dbus_info.conn,
1209                                                                 object_path);
1210         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1211                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1212
1213         /*Bluetooth is active, therefore set the flag */
1214         is_active = TRUE;
1215
1216         ret = __bluetooth_telephony_register();
1217         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1218                 BT_ERR("__bluetooth_telephony_register failed\n");
1219                 goto fail;
1220         }
1221
1222         BT_DBG("-");
1223         return ret;
1224
1225 fail:
1226         bluetooth_telephony_deinit();
1227         return ret;
1228 }
1229
1230 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1231 {
1232         DBusConnection *conn;
1233         DBusError error;
1234
1235         BT_DBG("+");
1236
1237         BT_TELEPHONY_CHECK_INITIALIZED();
1238
1239         is_initialized = FALSE;
1240         conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1241
1242         dbus_error_init(&error);
1243
1244         dbus_bus_remove_match(conn,
1245                         "type='signal',interface='"HFP_AGENT_SERVICE
1246                         "',member='PropertyChanged'", &error);
1247         dbus_bus_remove_match(conn,
1248                         "type='signal',interface='"HFP_AGENT_SERVICE
1249                         "',member='"HFP_NREC_STATUS_CHANGE"'", &error);
1250         if (dbus_error_is_set(&error)) {
1251                 BT_ERR("Fail to remove dbus filter signal\n");
1252                 dbus_error_free(&error);
1253         }
1254
1255         dbus_connection_remove_filter(conn, __bluetooth_telephony_event_filter,
1256          NULL);
1257
1258         if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_ENABLED)
1259                 __bluetooth_telephony_unregister();
1260
1261         __bluetooth_telephony_proxy_deinit();
1262
1263         telephony_info.cb = NULL;
1264         telephony_info.user_data = NULL;
1265         telephony_info.call_count = 0;
1266         telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1267
1268         /*Remove BT enabled signal*/
1269         dbus_bus_remove_match(conn,
1270                         "type='signal',interface='org.freedesktop.DBus.ObjectManager'"
1271                         ",member='InterfacesAdded'",
1272                         &error);
1273         if (dbus_error_is_set(&error)) {
1274                 BT_ERR("Fail to remove dbus filter signal\n");
1275                 dbus_error_free(&error);
1276         }
1277
1278         dbus_connection_remove_filter(dbus_g_connection_get_connection(
1279                                 telephony_dbus_info.conn), __bt_telephony_adapter_filter,
1280                  NULL);
1281
1282         g_object_unref(telephony_dbus_info.manager_proxy);
1283         telephony_dbus_info.manager_proxy = NULL;
1284
1285         dbus_g_connection_unref(telephony_dbus_info.conn);
1286         telephony_dbus_info.conn = NULL;
1287
1288         g_object_unref(telephony_dbus_info.dbus_proxy);
1289         telephony_dbus_info.dbus_proxy = NULL;
1290
1291         BT_DBG("-");
1292         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1293 }
1294
1295 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1296 {
1297         BT_DBG("+");
1298
1299         if (telephony_dbus_info.conn == NULL) {
1300                 BT_ERR("Bluetooth telephony not initilized");
1301                 return FALSE;
1302         }
1303
1304         /* To get the headset state */
1305         if (telephony_dbus_info.proxy == NULL)
1306                 telephony_dbus_info.proxy =
1307                         __bluetooth_telephony_get_connected_device_proxy();
1308
1309         if (telephony_dbus_info.proxy == NULL)
1310                 return FALSE;
1311
1312         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1313                 return TRUE;
1314
1315         BT_DBG("-");
1316         return FALSE;
1317 }
1318
1319 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1320 {
1321         DBusMessage* reply;
1322         DBusError err;
1323         DBusMessageIter reply_iter;
1324         DBusMessageIter reply_iter_entry;
1325         const char *property;
1326
1327         BT_DBG("+");
1328
1329         BT_TELEPHONY_CHECK_INITIALIZED();
1330         BT_TELEPHONY_CHECK_ENABLED();
1331
1332         if (status == NULL)
1333                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1334
1335         reply = __bluetooth_telephony_dbus_method_send(
1336                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1337                         "GetProperties", &err, DBUS_TYPE_INVALID);
1338
1339         if (!reply) {
1340                 BT_ERR("Error returned in method call\n");
1341                 if (dbus_error_is_set(&err)) {
1342                         BT_DBG("Error message = %s \n", err.message);
1343                         dbus_error_free(&err);
1344                 }
1345                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1346         }
1347
1348         dbus_message_iter_init(reply, &reply_iter);
1349
1350         if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
1351                 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY\n");
1352                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1353         }
1354
1355         dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
1356
1357         /*Parse the dict */
1358         while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
1359                                                 DBUS_TYPE_DICT_ENTRY) {
1360
1361                 DBusMessageIter dict_entry, dict_entry_val;
1362                 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
1363                 dbus_message_iter_get_basic(&dict_entry, &property);
1364                 BT_DBG("String received = %s\n", property);
1365
1366                 if (g_strcmp0("nrec", property) == 0) {
1367                         dbus_message_iter_next(&dict_entry);
1368                         dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1369                         if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
1370                                                 DBUS_TYPE_BOOLEAN)
1371                                 continue;
1372
1373                         dbus_message_iter_get_basic(&dict_entry_val, status);
1374                         BT_DBG("NREC status = [%d]", *status);
1375                 }
1376                 dbus_message_iter_next(&reply_iter_entry);
1377         }
1378         dbus_message_unref(reply);
1379         BT_DBG("-");
1380         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1381 }
1382
1383 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1384 {
1385         GError *error = NULL;
1386         int ret;
1387
1388         BT_DBG("+");
1389
1390         BT_TELEPHONY_CHECK_INITIALIZED();
1391         BT_TELEPHONY_CHECK_ENABLED();
1392
1393         if (telephony_dbus_info.proxy == NULL)
1394                 telephony_dbus_info.proxy =
1395                         __bluetooth_telephony_get_connected_device_proxy();
1396
1397         if (telephony_dbus_info.proxy == NULL)
1398                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1399
1400         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1401                         &error, G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID,
1402                         G_TYPE_INVALID)) {
1403                 if (error != NULL) {
1404                         ret = __bt_telephony_get_error(error->message);
1405                         g_error_free(error);
1406                         return ret;
1407                 }
1408         }
1409
1410         BT_DBG("-");
1411         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1412 }
1413
1414 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1415 {
1416         GError *error = NULL;
1417         int ret;
1418
1419         BT_DBG("+");
1420
1421         BT_TELEPHONY_CHECK_INITIALIZED();
1422         BT_TELEPHONY_CHECK_ENABLED();
1423
1424         if (telephony_dbus_info.proxy == NULL)
1425                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1426
1427         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SetVoiceDial",
1428                                 &error, G_TYPE_BOOLEAN,
1429                                 FALSE, G_TYPE_INVALID, G_TYPE_INVALID)) {
1430                 BT_ERR("Dbus Call Failed!\n");
1431                 if (error != NULL) {
1432                         ret = __bt_telephony_get_error(error->message);
1433                         g_error_free(error);
1434                         return ret;
1435                 }
1436         }
1437
1438         BT_DBG("-");
1439         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1440 }
1441
1442 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1443 {
1444         GError *error = NULL;
1445         int ret;
1446
1447         BT_DBG("+");
1448
1449         BT_TELEPHONY_CHECK_INITIALIZED();
1450         BT_TELEPHONY_CHECK_ENABLED();
1451
1452         if (telephony_dbus_info.proxy == NULL)
1453                 telephony_dbus_info.proxy =
1454                         __bluetooth_telephony_get_connected_device_proxy();
1455
1456         if (telephony_dbus_info.proxy == NULL)
1457                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1458
1459         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1460                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1461
1462         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Play", &error,
1463                                         G_TYPE_INVALID, G_TYPE_INVALID)) {
1464                 BT_ERR("Dbus Call Failed!");
1465                 if (error != NULL) {
1466                         ret = __bt_telephony_get_error(error->message);
1467                         g_error_free(error);
1468                         return ret;
1469                 }
1470         }
1471         BT_DBG("-");
1472         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1473 }
1474
1475 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1476 {
1477         GError *error = NULL;
1478         int ret;
1479
1480         BT_DBG("+");
1481
1482         BT_TELEPHONY_CHECK_INITIALIZED();
1483         BT_TELEPHONY_CHECK_ENABLED();
1484
1485         if (telephony_dbus_info.proxy == NULL)
1486                 telephony_dbus_info.proxy =
1487                         __bluetooth_telephony_get_connected_device_proxy();
1488
1489         if (telephony_dbus_info.proxy == NULL)
1490                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1491
1492         if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING) {
1493                 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1494         }
1495
1496         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "Stop", &error,
1497                         G_TYPE_INVALID, G_TYPE_INVALID)) {
1498                 BT_ERR("Dbus Call Failed");
1499                 if (error != NULL) {
1500                         ret = __bt_telephony_get_error(error->message);
1501                         g_error_free(error);
1502                         return ret;
1503                 }
1504         }
1505
1506         BT_DBG("-");
1507         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1508 }
1509
1510 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1511 {
1512         int ret;
1513
1514         BT_TELEPHONY_CHECK_INITIALIZED();
1515         BT_TELEPHONY_CHECK_ENABLED();
1516
1517         BT_DBG("+");
1518
1519         /*Make sure SCO is already connected */
1520         ret = __bluetooth_telephony_send_call_status(
1521                                 CSD_CALL_STATUS_MO_ALERTING, call_id);
1522         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1523                 BT_ERR("send call status Failed = [%d]", ret);
1524                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1525         }
1526         BT_DBG("-");
1527         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1528 }
1529
1530 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
1531                                                         unsigned int bt_audio)
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_ACTIVE,
1540                                                                 call_id);
1541         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1542                 BT_ERR("send call status Failed = [%d]", ret);
1543                 return ret;
1544         }
1545
1546         if (bt_audio) {
1547                 if (!bluetooth_telephony_is_sco_connected()) {
1548                         ret = bluetooth_telephony_audio_open();
1549                         if (ret != 0) {
1550                                 BT_ERR("Audio connection call Failed = %d", ret);
1551                                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1552                         }
1553                 }
1554         }
1555
1556         BT_DBG("-");
1557         return ret;
1558 }
1559
1560 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
1561 {
1562         int ret;
1563         BT_DBG("+");
1564
1565         BT_TELEPHONY_CHECK_INITIALIZED();
1566         BT_TELEPHONY_CHECK_ENABLED();
1567
1568         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
1569                                                                 call_id);
1570         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1571                 BT_ERR("send call status Failed = [%d]", ret);
1572                 return ret;
1573         }
1574         if (telephony_info.call_count > 0)
1575                 telephony_info.call_count = telephony_info.call_count - 1;
1576
1577         if (telephony_info.call_count  == 0) {
1578                 if (bluetooth_telephony_is_sco_connected()) {
1579                         ret = bluetooth_telephony_audio_close();
1580                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1581                                 BT_ERR(" Failed = [%d]", ret);
1582                                 return ret;
1583                         }
1584                 }
1585         }
1586         BT_DBG("-");
1587         return ret;
1588 }
1589
1590 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
1591 {
1592         int ret;
1593         BT_DBG("+");
1594
1595         BT_TELEPHONY_CHECK_INITIALIZED();
1596         BT_TELEPHONY_CHECK_ENABLED();
1597
1598         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
1599                                                                 call_id);
1600         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1601                 BT_ERR("send call status Failed = [%d]", ret);
1602         }
1603         BT_DBG("-");
1604         return ret;
1605 }
1606
1607 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
1608 {
1609         int ret;
1610         BT_DBG("+");
1611
1612         BT_TELEPHONY_CHECK_INITIALIZED();
1613         BT_TELEPHONY_CHECK_ENABLED();
1614
1615         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1616                                                                 call_id);
1617         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1618                 BT_ERR("send call status Failed = [%d]", ret);
1619         }
1620         BT_DBG("-");
1621         return ret;
1622 }
1623
1624 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
1625                                 unsigned int call_count)
1626 {
1627         int i;
1628         int ret;
1629         GList *list = call_list;
1630         bt_telephony_call_status_info_t *call_status;
1631
1632         BT_DBG("+");
1633
1634         BT_TELEPHONY_CHECK_INITIALIZED();
1635         BT_TELEPHONY_CHECK_ENABLED();
1636
1637         if (NULL == list) {
1638                 BT_ERR("call_list is invalid");
1639                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1640         }
1641
1642         BT_DBG(" call_count = [%d]", call_count);
1643
1644         for (i = 0; i < call_count; i++) {
1645                 call_status = g_list_nth_data(list, i);
1646
1647                 if (NULL == call_status)
1648                         continue;
1649
1650                 BT_DBG(" %d : Call id [%d] status[%d]", i,
1651                                         call_status->call_id,
1652                                         call_status->call_status);
1653
1654                 switch (call_status->call_status) {
1655                 case BLUETOOTH_CALL_STATE_HELD:
1656                         ret = __bluetooth_telephony_send_call_status(
1657                                                 CSD_CALL_STATUS_HOLD,
1658                                                 call_status->call_id);
1659                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1660                                 BT_ERR("Failed = %d", ret);
1661                                 return ret;
1662                         }
1663                 break;
1664
1665                 case BLUETOOTH_CALL_STATE_CONNECTED:
1666                         ret = __bluetooth_telephony_send_call_status(
1667                                         CSD_CALL_STATUS_ACTIVE,
1668                                         call_status->call_id);
1669                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1670                                 BT_ERR("Failed = [%d]", ret);
1671                                 return ret;
1672                         }
1673                 break;
1674
1675                 default:
1676                         if ((call_status->call_status < BLUETOOTH_CALL_STATE_NONE) ||
1677                                 (call_status->call_status >= BLUETOOTH_CALL_STATE_ERROR)) {
1678                                 BT_ERR("Unknown Call state");
1679                                 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
1680                         }
1681                 }
1682         }
1683
1684         BT_DBG("-");
1685         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1686 }
1687
1688 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
1689                                 unsigned int call_count)
1690 {
1691         int ret;
1692
1693         BT_DBG("+");
1694
1695         ret = bluetooth_telephony_call_swapped(call_list, call_count);
1696
1697         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1698                 BT_ERR("Failed = [%d]", ret);
1699                 return ret;
1700         }
1701
1702         telephony_info.call_count = call_count;
1703
1704         BT_DBG("-");
1705         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1706 }
1707
1708 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
1709                         const char *ph_number, unsigned int call_id,
1710                         unsigned int bt_audio)
1711 {
1712         DBusMessage *reply;
1713         DBusError err;
1714         const char *path = telephony_info.call_path;
1715         int ret;
1716
1717         BT_DBG("+");
1718
1719         BT_TELEPHONY_CHECK_INITIALIZED();
1720         BT_TELEPHONY_CHECK_ENABLED();
1721
1722         if (NULL == ph_number)
1723                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1724
1725         reply = __bluetooth_telephony_dbus_method_send(
1726                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1727                         "OutgoingCall", &err, DBUS_TYPE_STRING, &path,
1728                         DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1729                         &call_id, DBUS_TYPE_INVALID);
1730
1731         if (!reply) {
1732                 BT_ERR("Error returned in method call\n");
1733                 if (dbus_error_is_set(&err)) {
1734                         ret = __bt_telephony_get_error(err.message);
1735                         dbus_error_free(&err);
1736                         return ret;
1737                 }
1738                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1739         }
1740
1741         dbus_message_unref(reply);
1742
1743         telephony_info.call_count++;
1744         BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
1745
1746         if (bt_audio) {
1747                 if (!bluetooth_telephony_is_sco_connected()) {
1748                         ret = bluetooth_telephony_audio_open();
1749                         if (ret != 0) {
1750                                 BT_ERR(" Audio connection call Failed = %d", ret);
1751                                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1752                         }
1753                 }
1754         }
1755
1756         BT_DBG("-");
1757         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1758 }
1759
1760 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
1761                 const char *ph_number, unsigned int call_id)
1762 {
1763         DBusMessage *reply;
1764         DBusError err;
1765         const char *path = telephony_info.call_path;
1766         int ret;
1767
1768         BT_DBG("+");
1769
1770         BT_TELEPHONY_CHECK_INITIALIZED();
1771         BT_TELEPHONY_CHECK_ENABLED();
1772
1773         if (NULL == ph_number)
1774                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1775
1776         reply = __bluetooth_telephony_dbus_method_send(
1777                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1778                         "IncomingCall", &err, DBUS_TYPE_STRING, &path,
1779                         DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
1780                         &call_id, DBUS_TYPE_INVALID);
1781
1782         if (!reply) {
1783                 BT_ERR("Error returned in method call\n");
1784                 if (dbus_error_is_set(&err)) {
1785                         ret = __bt_telephony_get_error(err.message);
1786                         dbus_error_free(&err);
1787                         return ret;
1788                 }
1789                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1790         }
1791
1792         dbus_message_unref(reply);
1793
1794         telephony_info.call_count++;
1795         BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
1796         BT_DBG("-");
1797         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1798 }
1799
1800 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(unsigned short speaker_gain)
1801 {
1802         GError *error = NULL;
1803         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1804         DBusGProxy *headset_agent_proxy = NULL;
1805         BT_DBG("+");
1806         BT_DBG("set speaker_gain= [%d]", speaker_gain);
1807
1808         BT_TELEPHONY_CHECK_INITIALIZED();
1809         BT_TELEPHONY_CHECK_ENABLED();
1810
1811         if (telephony_info.obj_path == NULL)
1812                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1813
1814         if (telephony_dbus_info.proxy == NULL)
1815                 telephony_dbus_info.proxy =
1816                         __bluetooth_telephony_get_connected_device_proxy();
1817
1818         if (telephony_dbus_info.proxy == NULL)
1819                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1820
1821         if (!dbus_g_proxy_call(headset_agent_proxy, "SetSpeakerGain",
1822                                         &error, G_TYPE_UINT, speaker_gain, G_TYPE_INVALID,
1823                                         G_TYPE_INVALID)) {
1824                         if (error != NULL) {
1825                         BT_ERR("Calling SetSpeakerGain failed: [%s]",
1826                                                         error->message);
1827                         g_error_free(error);
1828                 }
1829         }
1830
1831         BT_DBG("-");
1832         return ret;
1833 }
1834
1835 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(unsigned int *speaker_gain)
1836 {
1837         DBusGProxy *headset_agent_proxy = NULL;
1838         GError *error = NULL;
1839
1840         BT_DBG("+");
1841         BT_TELEPHONY_CHECK_INITIALIZED();
1842         BT_TELEPHONY_CHECK_ENABLED();
1843
1844         if (telephony_dbus_info.proxy == NULL)
1845                 telephony_dbus_info.proxy =
1846                         __bluetooth_telephony_get_connected_device_proxy();
1847
1848         if (telephony_dbus_info.proxy == NULL)
1849                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1850
1851         if (telephony_info.obj_path == NULL)
1852                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1853
1854         if (telephony_dbus_info.proxy == NULL)
1855                 telephony_dbus_info.proxy =
1856                         __bluetooth_telephony_get_connected_device_proxy();
1857
1858         if (telephony_dbus_info.proxy == NULL)
1859                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1860
1861         if (!dbus_g_proxy_call(headset_agent_proxy, "GetSpeakerGain",
1862                                         &error, G_TYPE_INVALID, G_TYPE_UINT, &speaker_gain,
1863                                         G_TYPE_INVALID)) {
1864                         if (error != NULL) {
1865                         BT_ERR("Calling G`etSpeakerGain failed: [%s]",
1866                                                         error->message);
1867                         g_error_free(error);
1868                 }
1869         }
1870
1871         BT_DBG("-");
1872         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1873 }
1874
1875 static char *_bt_get_device_object_path(char *address)
1876 {
1877         DBusMessage *msg;
1878         DBusMessage *reply;
1879         DBusMessageIter reply_iter;
1880         DBusMessageIter value_iter;
1881         DBusError err;
1882         DBusConnection *conn;
1883         char *object_path = NULL;
1884         BT_DBG("+");
1885
1886         conn = _bt_get_system_conn();
1887         retv_if(conn == NULL, NULL);
1888
1889         msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME, BT_MANAGER_PATH,
1890                                                 BLUEZ_MANAGER_INTERFACE,
1891                                                 "GetManagedObjects");
1892
1893         retv_if(msg == NULL, NULL);
1894
1895         /* Synchronous call */
1896         dbus_error_init(&err);
1897         reply = dbus_connection_send_with_reply_and_block(
1898                                         conn, msg,
1899                                         -1, &err);
1900         dbus_message_unref(msg);
1901
1902         if (!reply) {
1903                 BT_ERR("Can't get managed objects");
1904
1905                 if (dbus_error_is_set(&err)) {
1906                         BT_ERR("%s", err.message);
1907                         dbus_error_free(&err);
1908                 }
1909                 return NULL;
1910         }
1911
1912         if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
1913                         BT_ERR("Fail to iterate the reply");
1914                         return NULL;
1915         }
1916
1917         dbus_message_iter_recurse(&reply_iter, &value_iter);
1918
1919         /* signature of GetManagedObjects:      a{oa{sa{sv}}} */
1920         while (dbus_message_iter_get_arg_type(&value_iter) ==
1921                                                 DBUS_TYPE_DICT_ENTRY) {
1922                 DBusMessageIter msg_iter;
1923
1924                 dbus_message_iter_recurse(&value_iter, &msg_iter);
1925
1926                 object_path = __bt_extract_device_path(&msg_iter, address);
1927                 if (object_path != NULL) {
1928                         BT_DBG("Found the device path");
1929                         break;
1930                 }
1931
1932                 dbus_message_iter_next(&value_iter);
1933         }
1934         BT_DBG("-");
1935         return object_path;
1936 }
1937
1938 static char *__bt_extract_device_path(DBusMessageIter *msg_iter, char *address)
1939 {
1940         char *object_path = NULL;
1941         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
1942         BT_DBG("+");
1943
1944         /* Parse the signature: oa{sa{sv}}} */
1945         retv_if(dbus_message_iter_get_arg_type(msg_iter) !=
1946                                 DBUS_TYPE_OBJECT_PATH, NULL);
1947
1948         dbus_message_iter_get_basic(msg_iter, &object_path);
1949         retv_if(object_path == NULL, NULL);
1950
1951         _bt_convert_device_path_to_address(object_path, device_address);
1952
1953         if (g_strcmp0(address, device_address) == 0) {
1954                 return g_strdup(object_path);
1955         }
1956         BT_DBG("-");
1957         return NULL;
1958 }
1959
1960 static DBusHandlerResult __bt_telephony_adapter_filter(DBusConnection *conn,
1961                                                  DBusMessage *msg, void *data)
1962 {
1963         int ret;
1964         char *object_path = NULL;
1965         const char *member = dbus_message_get_member(msg);
1966         BT_DBG("+");
1967
1968         if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
1969                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1970
1971         if (member == NULL)
1972                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1973
1974         if (strcasecmp(member, "InterfacesAdded") == 0) {
1975                 if (__bt_telephony_get_object_path(msg, &object_path)) {
1976                         BT_ERR("Fail to get the path");
1977                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1978                 }
1979
1980                 if (strcasecmp(object_path, "/org/bluez/hci0") == 0) {
1981                         BT_DBG("Adapter added [%s] \n", object_path);
1982                         BT_DBG("BlueZ is Activated and flag need to be reset");
1983                         BT_DBG("Send enabled to application\n");
1984
1985                         ret = __bluetooth_telephony_register();
1986                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1987                                 BT_DBG("__bluetooth_telephony_register failed\n");
1988                         }
1989                 }
1990         }
1991         BT_DBG("-");
1992         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1993 }
1994
1995 static int __bt_telephony_get_object_path(DBusMessage *msg, char **path)
1996 {
1997         DBusMessageIter item_iter;
1998         dbus_message_iter_init(msg, &item_iter);
1999         BT_DBG("+");
2000
2001         if (dbus_message_iter_get_arg_type(&item_iter)
2002                                         != DBUS_TYPE_OBJECT_PATH) {
2003                 BT_ERR("This is bad format dbus\n");
2004                 return BLUETOOTH_ERROR_INTERNAL;
2005         }
2006
2007         dbus_message_iter_get_basic(&item_iter, path);
2008
2009         if (*path == NULL)
2010                 return BLUETOOTH_ERROR_INTERNAL;
2011
2012         BT_DBG("-");
2013         return BLUETOOTH_ERROR_NONE;
2014 }
2015
2016 static void _bt_convert_device_path_to_address(const char *device_path,
2017                                                 char *device_address)
2018 {
2019         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
2020         char *dev_addr;
2021         BT_DBG("+");
2022
2023         ret_if(device_path == NULL);
2024         ret_if(device_address == NULL);
2025
2026         dev_addr = strstr(device_path, "dev_");
2027         if (dev_addr != NULL) {
2028                 char *pos = NULL;
2029                 dev_addr += 4;
2030                 g_strlcpy(address, dev_addr, sizeof(address));
2031
2032                 while ((pos = strchr(address, '_')) != NULL) {
2033                         *pos = ':';
2034                 }
2035                 g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE);
2036         }
2037         BT_DBG("-");
2038 }
2039
2040 static char *__bt_get_default_adapter_path(DBusMessageIter *msg_iter)
2041 {
2042         char *object_path = NULL;
2043         DBusMessageIter value_iter;
2044         BT_DBG("+");
2045
2046         /* Parse the signature:  oa{sa{sv}}} */
2047         retv_if(dbus_message_iter_get_arg_type(msg_iter) !=
2048                         DBUS_TYPE_OBJECT_PATH, NULL);
2049
2050         dbus_message_iter_get_basic(msg_iter, &object_path);
2051
2052         retv_if(dbus_message_iter_next(msg_iter) == FALSE, NULL);
2053         retv_if(dbus_message_iter_get_arg_type(msg_iter) !=
2054                         DBUS_TYPE_ARRAY, NULL);
2055
2056         dbus_message_iter_recurse(msg_iter, &value_iter);
2057
2058         while (dbus_message_iter_get_arg_type(&value_iter) ==
2059                   DBUS_TYPE_DICT_ENTRY) {
2060                 char *interface_name = NULL;
2061                 DBusMessageIter interface_iter;
2062
2063                 dbus_message_iter_recurse(&value_iter, &interface_iter);
2064
2065                 retv_if(dbus_message_iter_get_arg_type(&interface_iter) !=
2066                                 DBUS_TYPE_STRING, NULL);
2067
2068                 dbus_message_iter_get_basic(&interface_iter, &interface_name);
2069
2070                 if (g_strcmp0(interface_name, "org.bluez.Adapter1") == 0) {
2071                         return g_strdup(object_path);
2072                 }
2073         dbus_message_iter_next(&value_iter);
2074         }
2075         BT_DBG("Adapter Not Found");
2076         BT_DBG("-");
2077         return NULL;
2078 }
2079