Code Sync [Tizen3.0]: Merged the tizen_2.4 Spin code to tizen.org
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-telephony.c
1 /*
2  * Bluetooth-telephony
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:     Hocheol Seo <hocheol.seo@samsung.com>
7  *              GirishAshok Joshi <girish.joshi@samsung.com>
8  *              Chanyeol Park <chanyeol.park@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <dbus/dbus.h>
28 #include <dbus/dbus-glib-bindings.h>
29 #include <unistd.h>
30 #include <vconf.h>
31 #include <vconf-keys.h>
32
33 #include "bt-common.h"
34 #include "bluetooth-telephony-api.h"
35 #include "marshal.h"
36
37 #define BT_SCO_TIMEOUT 3000
38
39 #define BT_CVSD_CODEC_ID 1
40 #define BT_MSBC_CODEC_ID 2
41
42 typedef struct {
43         DBusGConnection *conn;
44         DBusGProxy *proxy;
45         DBusGProxy *dbus_proxy;
46         DBusGProxy *manager_proxy;
47 } telephony_dbus_info_t;
48
49 typedef struct {
50         bt_telephony_func_ptr cb;
51         unsigned int call_count;
52         char *obj_path;
53         char address[BT_ADDRESS_STR_LEN];
54         char call_path[BT_AUDIO_CALL_PATH_LEN];
55         bluetooth_headset_state_t headset_state;
56         void *user_data;
57 } bt_telephony_info_t;
58
59
60 char *src_addr = NULL;
61
62
63
64 #define BLUETOOTH_TELEPHONY_ERROR (__bluetooth_telephony_error_quark())
65
66 #define BLUEZ_SERVICE_NAME "org.bluez"
67 #define BLUEZ_HEADSET_INTERFACE "org.bluez.Headset"
68
69 #define BLUEZ_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager"
70 #define BLUEZ_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
71 #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1"
72 #define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1"
73 #define HFP_AGENT_SERVICE "org.bluez.ag_agent"
74
75
76 #define HFP_AGENT_PATH "/org/bluez/hfp_agent"
77 #define HFP_AGENT_INTERFACE "Org.Hfp.App.Interface"
78
79 #define CSD_CALL_APP_PATH "/org/tizen/csd/%d"
80 #define HFP_NREC_STATUS_CHANGE "NrecStatusChanged"
81 #define HFP_ANSWER_CALL "Answer"
82 #define HFP_REJECT_CALL "Reject"
83 #define HFP_RELEASE_CALL "Release"
84 #define HFP_THREEWAY_CALL "Threeway"
85
86 #define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
87
88
89 #define BT_TELEPHONY_CHECK_ENABLED() \
90         do { \
91                 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) \
92                 { \
93                         BT_ERR("BT is not enabled"); \
94                         return BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED; \
95                 } \
96         } while (0)
97
98 static gboolean is_initialized = FALSE;
99 #define BT_TELEPHONY_CHECK_INITIALIZED() \
100         do { \
101                 if (is_initialized == FALSE) \
102                 { \
103                         BT_ERR("Bluetooth telephony not initilized"); \
104                         return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED; \
105                 } \
106         } while (0)
107
108 #define BLUETOOTH_TELEPHONY_METHOD (bluetooth_telephony_method_get_type())
109 #define BLUETOOTH_TELEPHONY_METHOD_GET_OBJECT(obj) \
110                 (G_TYPE_CHECK_INSTANCE_CAST((obj), \
111                 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethod))
112
113 #define BLUETOOTH_TELEPHONY_METHOD_IS_OBJECT(obj) \
114                 (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
115                 BLUETOOTH_TELEPHONY_METHOD))
116
117 #define BLUETOOTH_TELEPHONY_METHOD_CLASS(class) \
118                 (G_TYPE_CHECK_CLASS_CAST((class), \
119                 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))
120
121 #define BLUETOOTH_TELEPHONY_METHOD_GET_AGENT_CLASS(obj) \
122                 (G_TYPE_INSTANCE_GET_CLASS((obj), \
123                 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodClass))
124
125 #define BLUETOOTH_TELEPHONY_METHOD_IS_AGENT_CLASS(class) \
126                 (G_TYPE_CHECK_CLASS_TYPE((class), BLUETOOTH_TELEPHONY_METHOD))
127
128 #define BLUETOOTH_TELEPHONY_METHOD_AGENT_GET_PRIVATE(obj) \
129                 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
130                 BLUETOOTH_TELEPHONY_METHOD, BluetoothTelephonyMethodPrivate))
131
132 typedef struct _BluetoothTelephonyMethod BluetoothTelephonyMethod;
133 typedef struct _BluetoothTelephonyMethodClass BluetoothTelephonyMethodClass;
134
135 struct _BluetoothTelephonyMethod {
136         GObject parent;
137 };
138
139 struct _BluetoothTelephonyMethodClass {
140         GObjectClass parent_class;
141 };
142
143 BluetoothTelephonyMethod *bluetooth_telephony_method_new(void);
144 GType bluetooth_telephony_method_get_type(void);
145
146 G_DEFINE_TYPE(BluetoothTelephonyMethod, bluetooth_telephony_method, G_TYPE_OBJECT)
147
148
149 static DBusHandlerResult __bt_telephony_adapter_filter(DBusConnection *conn,
150                         DBusMessage *msg, void *data);
151
152 static int __bt_telephony_get_object_path(DBusMessage *msg, char **path);
153
154 static int __bt_telephony_get_src_addr(DBusMessage *msg);
155
156 static gboolean bluetooth_telephony_method_send_dtmf(
157                                 BluetoothTelephonyMethod *object,
158                                 gchar *dtmf, DBusGMethodInvocation *context);
159
160 static gboolean bluetooth_telephony_method_vendor_cmd(
161                                 BluetoothTelephonyMethod *object,
162                                 gchar *at_cmd, DBusGMethodInvocation *context);
163 #include "bt-telephony-glue.h"
164
165 static GObject *object;
166 static bt_telephony_info_t telephony_info;
167 static telephony_dbus_info_t telephony_dbus_info;
168 static gboolean is_active = FALSE;
169
170 /*Function Declaration*/
171 static int __bt_telephony_get_error(const char *error_message);
172 static void __bt_telephony_event_cb(int event, int result, void *param_data);
173 static GQuark __bluetooth_telephony_error_quark(void);
174 static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path,
175                         const char *interface, const char *method, DBusError *err,  int type, ...);
176 static int __bluetooth_telephony_send_call_status(
177                         bt_telephony_call_status_t call_status,
178                         unsigned int call_id, const char *ph_number);
179 static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
180                                         const char *err_msg);
181
182 static DBusHandlerResult __bluetooth_telephony_event_filter(
183                                                 DBusConnection *conn,
184                                                 DBusMessage *msg, void *data);
185
186 static int __bluetooth_telephony_proxy_init(void);
187 static void __bluetooth_telephony_proxy_deinit(void);
188 static int __bluetooth_telephony_register(void);
189 static int __bluetooth_telephony_unregister(void);
190
191 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class);
192 static int __bluetooth_telephony_get_connected_device(void);
193 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void);
194
195 /*Function Definition*/
196 static int __bt_telephony_get_error(const char *error_message)
197 {
198         if (error_message == NULL) {
199                 BT_ERR("Error message NULL");
200                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
201         }
202
203         BT_ERR("Error message = %s", error_message);
204         if (g_strcmp0(error_message, "NotAvailable") == 0)
205                 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
206         else if (g_strcmp0(error_message, "NotConnected") == 0)
207                 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
208         else if (g_strcmp0(error_message, "InProgress") == 0)
209                 return BLUETOOTH_TELEPHONY_ERROR_BUSY;
210         else if (g_strcmp0(error_message, "InvalidArguments") == 0)
211                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
212         else if (g_strcmp0(error_message, "AlreadyExists") == 0)
213                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST;
214         else if (g_strcmp0(error_message, "Already Connected") == 0)
215                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
216         else if (g_strcmp0(error_message, "No memory") == 0)
217                 return BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY;
218         else if (g_strcmp0(error_message, "I/O error") == 0)
219                 return BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR;
220         else if (g_strcmp0(error_message, "Operation currently not available") == 0)
221                 return BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE;
222         else if (g_strrstr(error_message, BT_ACCESS_DENIED_MSG))
223                 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
224         else
225                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
226 }
227
228 static int __bt_telephony_check_privilege(void)
229 {
230         DBusMessage *msg;
231         DBusMessage *reply;
232         DBusError err;
233         DBusConnection *conn;
234         int ret;
235
236         conn = _bt_get_system_conn();
237         retv_if(conn == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
238
239         msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
240                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
241                         "CheckPrivilege");
242         if (!msg) {
243                 BT_ERR("Unable to allocate new D-Bus message \n");
244                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
245         }
246
247         dbus_error_init(&err);
248
249         reply = dbus_connection_send_with_reply_and_block(conn,
250                                                 msg, -1, &err);
251
252         dbus_message_unref(msg);
253
254         if (!reply) {
255                 BT_ERR("Error returned in method call");
256                 if (dbus_error_is_set(&err)) {
257                         ret = __bt_telephony_get_error(err.message);
258                         BT_ERR("Error here %d\n", ret);
259                         dbus_error_free(&err);
260                         return ret;
261                 }
262                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
263         }
264
265         dbus_message_unref(reply);
266
267         return BLUETOOTH_TELEPHONY_ERROR_NONE;
268 }
269
270 static void __bt_telephony_event_cb(int event, int result, void *param_data)
271 {
272         telephony_event_param_t bt_event = { 0, };
273
274         bt_event.event = event;
275         bt_event.result = result;
276         bt_event.param_data = param_data;
277
278         ret_if(telephony_info.cb == NULL);
279         telephony_info.cb(bt_event.event, &bt_event, telephony_info.user_data);
280         return;
281 }
282
283 static GQuark __bluetooth_telephony_error_quark(void)
284 {
285         static GQuark quark = 0;
286
287         quark = g_quark_from_static_string("telephony");
288
289         return quark;
290 }
291
292 static DBusMessage* __bluetooth_telephony_dbus_method_send(const char *path,
293                         const char *interface, const char *method, DBusError *err,  int type, ...)
294 {
295         DBusMessage *msg;
296         DBusMessage *reply;
297         va_list args;
298 #ifdef TIZEN_WEARABLE
299         int timeout = 4000;
300 #else
301         int timeout = -1;
302 #endif
303
304         FN_START;
305
306         msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
307                         path, interface, method);
308         if (!msg) {
309                 BT_ERR("Unable to allocate new D-Bus %s message \n", method);
310                 return NULL;
311         }
312
313         va_start(args, type);
314
315         if (!dbus_message_append_args_valist(msg, type, args)) {
316                 dbus_message_unref(msg);
317                 va_end(args);
318                 return NULL;
319         }
320
321         va_end(args);
322
323         dbus_error_init(err);
324
325         reply = dbus_connection_send_with_reply_and_block(
326                 dbus_g_connection_get_connection(telephony_dbus_info.conn),
327                 msg, timeout, err);
328         dbus_message_unref(msg);
329
330         FN_END;
331         return reply;
332 }
333
334 static int __bluetooth_telephony_send_call_status(
335                         bt_telephony_call_status_t call_status,
336                         unsigned int call_id, const char *ph_number)
337 {
338         DBusMessage *reply;
339         DBusError err;
340         char *path = g_strdup(telephony_info.call_path);
341         char *phone_number;
342         int ret;
343
344         FN_START;
345
346         if (NULL == ph_number)
347                 phone_number = g_strdup("");
348         else
349                 phone_number = g_strdup(ph_number);
350
351         reply = __bluetooth_telephony_dbus_method_send(
352                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
353                         "ChangeCallStatus", &err, DBUS_TYPE_STRING, &path,
354                         DBUS_TYPE_STRING, &phone_number,
355                         DBUS_TYPE_INT32, &call_status,
356                         DBUS_TYPE_INT32, &call_id, DBUS_TYPE_INVALID);
357
358         g_free(path);
359         g_free(phone_number);
360
361         if (!reply) {
362                 BT_ERR("Error returned in method call\n");
363                 if (dbus_error_is_set(&err)) {
364                         ret = __bt_telephony_get_error(err.message);
365                         dbus_error_free(&err);
366                         return ret;
367                 }
368                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
369         }
370
371         dbus_message_unref(reply);
372
373         return BLUETOOTH_TELEPHONY_ERROR_NONE;
374 }
375
376 static GError *__bluetooth_telephony_error(bluetooth_telephony_error_t error,
377                                         const char *err_msg)
378 {
379         return g_error_new(BLUETOOTH_TELEPHONY_ERROR, error, err_msg, NULL);
380 }
381
382 static void bluetooth_telephony_method_init(BluetoothTelephonyMethod *object)
383 {
384         FN_START;
385         BT_DBG("agent %p\n", object);
386         FN_END;
387 }
388
389 static void __bluetooth_telephony_method_finalize(
390                                         BluetoothTelephonyMethod *object)
391 {
392         FN_START;
393         G_OBJECT_CLASS(bluetooth_telephony_method_parent_class)->finalize((
394                                                         GObject *)object);
395         FN_END;
396 }
397
398 static BluetoothTelephonyMethod *__bluetooth_telephony_method_new(void)
399 {
400         BluetoothTelephonyMethod *obj;
401
402         FN_START;
403         obj = g_object_new(BLUETOOTH_TELEPHONY_METHOD, NULL);
404         FN_END;
405
406         return obj;
407 }
408
409 static void bluetooth_telephony_method_class_init(
410                                         BluetoothTelephonyMethodClass *klass)
411 {
412         GObjectClass *object_class = NULL;
413         FN_START;
414
415         object_class = G_OBJECT_CLASS(klass);
416         object_class->finalize = (void *)__bluetooth_telephony_method_finalize;
417
418         /*Registration of the Framework methods */
419         dbus_g_object_type_install_info(BLUETOOTH_TELEPHONY_METHOD,
420                         &dbus_glib_bluetooth_telephony_method_object_info);
421         FN_END;
422         return;
423 }
424
425 static void __bluetooth_telephony_answer_call(DBusMessage *msg)
426 {
427         telephony_event_callid_t call_data = { 0, };
428         unsigned int callid;
429
430         FN_START;
431         if (!dbus_message_get_args(msg, NULL,
432                                 DBUS_TYPE_UINT32, &callid,
433                                 DBUS_TYPE_INVALID)) {
434                 BT_ERR("Error Getting parameters");
435                 return;
436         }
437
438         BT_DBG("call_id = [%d]", callid);
439         call_data.callid = callid;
440
441         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL,
442                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
443                                         (void *)&call_data);
444         FN_END;
445 }
446
447 static void __bluetooth_telephony_release_call(DBusMessage *msg)
448 {
449         telephony_event_callid_t call_data = { 0, };
450         unsigned int callid;
451
452         FN_START;
453         if (!dbus_message_get_args(msg, NULL,
454                                 DBUS_TYPE_UINT32, &callid,
455                                 DBUS_TYPE_INVALID)) {
456                 BT_ERR("Error Getting parameters");
457                 return;
458         }
459
460         BT_DBG("call_id = [%d]", callid);
461         call_data.callid = callid;
462
463         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL,
464                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
465                                         (void *)&call_data);
466         FN_END;
467 }
468
469 static void __bluetooth_telephony_reject_call(DBusMessage *msg)
470 {
471         telephony_event_callid_t call_data = { 0, };
472         unsigned int callid;
473
474         FN_START;
475         if (!dbus_message_get_args(msg, NULL,
476                                 DBUS_TYPE_UINT32, &callid,
477                                 DBUS_TYPE_INVALID)) {
478                 BT_ERR("Error Getting parameters");
479                 return;
480         }
481
482         BT_DBG("call_id = [%d]", callid);
483         call_data.callid = callid;
484
485         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_REJECT_CALL,
486                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
487                                         (void  *)&call_data);
488         FN_END;
489 }
490
491 static void __bluetooth_telephony_threeway_call(DBusMessage *msg)
492 {
493         int event = 0;
494         unsigned int chld_value;
495
496         FN_START;
497         if (!dbus_message_get_args(msg, NULL,
498                                 DBUS_TYPE_UINT32, &chld_value,
499                                 DBUS_TYPE_INVALID)) {
500                 BT_ERR("Error Getting parameters");
501                 return;
502         }
503
504         BT_DBG("chld value  = [%d]", chld_value);
505
506         switch (chld_value) {
507         case 0:
508                 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL;
509                 break;
510         case 1:
511                 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL;
512                 break;
513         case 2:
514                 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL;
515                 break;
516         case 3:
517                 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL;
518                 break;
519         default:
520                 BT_ERR("Invalid CHLD command");
521                 return;
522         }
523
524         __bt_telephony_event_cb(event,
525                         BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
526         FN_END;
527 }
528
529 static gboolean bluetooth_telephony_method_send_dtmf(
530                                 BluetoothTelephonyMethod *object,
531                                 gchar *dtmf, DBusGMethodInvocation *context)
532 {
533         telephony_event_dtmf_t call_data = { 0, };
534         GError *err;
535
536         FN_START;
537
538         if (dtmf == NULL) {
539                 BT_ERR("Number dial failed");
540                 err = __bluetooth_telephony_error(
541                                 BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF,
542                                 "Invalid dtmf");
543                 dbus_g_method_return_error(context, err);
544                 g_error_free(err);
545                 return FALSE;
546         }
547
548         DBG_SECURE("Dtmf = %s", dtmf);
549
550         call_data.dtmf = g_strdup(dtmf);
551
552         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF,
553                 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&call_data);
554
555         dbus_g_method_return(context);
556         g_free(call_data.dtmf);
557         FN_END;
558         return TRUE;
559 }
560
561 static gboolean bluetooth_telephony_method_vendor_cmd(
562                                 BluetoothTelephonyMethod *object,
563                                 gchar *at_cmd, DBusGMethodInvocation *context)
564 {
565         GError *err;
566
567         FN_START;
568
569         if (at_cmd == NULL) {
570                 BT_ERR("Vendor command is NULL\n");
571                 err = __bluetooth_telephony_error(
572                                 BLUETOOTH_TELEPHONY_ERROR_APPLICATION,
573                                 "Invalid at vendor cmd");
574                 dbus_g_method_return_error(context, err);
575                 g_error_free(err);
576                 return FALSE;
577         }
578
579         DBG_SECURE("Vendor AT cmd = %s", at_cmd);
580
581         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_VENDOR_AT_CMD,
582                 BLUETOOTH_TELEPHONY_ERROR_NONE, at_cmd);
583
584         dbus_g_method_return(context);
585         FN_END;
586         return TRUE;
587 }
588
589 static void __bluetooth_handle_nrec_status_change(DBusMessage *msg)
590 {
591         gboolean status = FALSE;
592
593         if (!dbus_message_get_args(msg, NULL,
594                                 DBUS_TYPE_BOOLEAN, &status,
595                                 DBUS_TYPE_INVALID)) {
596                 BT_ERR("Error Getting parameters");
597                 return;
598         }
599         BT_INFO("NREC status = %d", status);
600
601         __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED,
602                 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&status);
603
604 }
605
606 static DBusHandlerResult __bluetooth_telephony_event_filter(
607                                                 DBusConnection *conn,
608                                                 DBusMessage *msg, void *data)
609 {
610         const char *path = dbus_message_get_path(msg);
611         char *dev_addr = NULL;
612         DBusMessageIter item_iter;
613         DBusMessageIter value_iter;
614         const char *property;
615
616         /* Check NREC status change Signal*/
617         if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
618                                 HFP_NREC_STATUS_CHANGE)) {
619                 __bluetooth_handle_nrec_status_change(msg);
620                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
621         }
622
623         if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
624                                 HFP_ANSWER_CALL)) {
625                 __bluetooth_telephony_answer_call(msg);
626                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
627         }
628
629         if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
630                                 HFP_REJECT_CALL)) {
631                 __bluetooth_telephony_reject_call(msg);
632                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
633         }
634
635         if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
636                                 HFP_RELEASE_CALL)) {
637                 __bluetooth_telephony_release_call(msg);
638                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
639         }
640
641         if (dbus_message_is_signal(msg, HFP_AGENT_SERVICE,
642                                 HFP_THREEWAY_CALL)) {
643                 __bluetooth_telephony_threeway_call(msg);
644                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
645         }
646
647         if (!dbus_message_has_interface(msg, BLUEZ_HEADSET_INTERFACE))
648                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
649
650         if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
651                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
652
653         dbus_message_iter_init(msg, &item_iter);
654         if (dbus_message_iter_get_arg_type(&item_iter) != DBUS_TYPE_STRING) {
655                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
656         }
657
658         dbus_message_iter_get_basic(&item_iter, &property);
659
660         if (property == NULL)
661                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
662
663         BT_DBG("Property (%s)", property);
664
665         if (g_strcmp0(property, "State") == 0) {
666                 char *state = NULL;
667                 dbus_message_iter_next(&item_iter);
668                 dbus_message_iter_recurse(&item_iter, &value_iter);
669                 dbus_message_iter_get_basic(&value_iter, &state);
670                 if (NULL == state) {
671                         BT_ERR("State is null");
672                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
673                 }
674                 BT_DBG("State : %s", state);
675
676                 if (g_strcmp0(state, "connected") == 0) {
677                         telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
678                 } else if (g_strcmp0(state, "playing") == 0) {
679                         telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
680                 } else if (g_strcmp0(state, "disconnected") == 0) {
681                         /* Headset state: playing -> disconnected */
682                         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) {
683                                 __bt_telephony_event_cb(
684                                          BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
685                                          BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
686                         }
687
688                         telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
689                 }
690
691                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
692         }
693
694         if (g_strcmp0(property, "Connected") == 0) {
695                 gboolean connected = FALSE;
696                 dbus_message_iter_next(&item_iter);
697                 dbus_message_iter_recurse(&item_iter, &value_iter);
698                 dbus_message_iter_get_basic(&value_iter, &connected);
699                 BT_DBG("Connected : %d", connected);
700
701                 if (connected) {
702                         /*Get device address*/
703                         if (path != NULL)
704                                 dev_addr = strstr(path, "dev_");
705
706                         if (dev_addr != NULL) {
707                                 dev_addr += 4;
708                                 g_strlcpy(telephony_info.address,
709                                         dev_addr,
710                                         sizeof(telephony_info.address));
711                                 g_strdelimit(telephony_info.address, "_", ':');
712                                 BT_DBG("address is %s",
713                                         telephony_info.address);
714
715                                 telephony_info.headset_state =
716                                                 BLUETOOTH_STATE_CONNECTED;
717
718                                 if (telephony_dbus_info.proxy != NULL) {
719                                         g_object_unref(telephony_dbus_info.proxy);
720                                         telephony_dbus_info.proxy = NULL;
721                                 }
722
723                                 telephony_dbus_info.proxy =
724                                                 __bluetooth_telephony_get_connected_device_proxy();
725
726                                 BT_INFO("Headset Connected");
727
728                                  __bt_telephony_event_cb(
729                                                 BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED,
730                                                 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
731                         }
732                 } else { /*Device disconnected*/
733                         memset(telephony_info.address, 0x00,
734                                         sizeof(telephony_info.address));
735                         telephony_info.headset_state =
736                                                 BLUETOOTH_STATE_DISCONNETED;
737
738                         if (telephony_dbus_info.proxy != NULL) {
739                                 g_object_unref(telephony_dbus_info.proxy);
740                                 telephony_dbus_info.proxy = NULL;
741                         }
742
743                         BT_INFO("Headset Disconnected");
744
745                          __bt_telephony_event_cb(
746                                         BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED,
747                                         BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
748                 }
749                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
750         }
751
752         if (g_strcmp0(property, "SpeakerGain") == 0) {
753                 unsigned int spkr_gain;
754                 guint16 gain;
755                 dbus_message_iter_next(&item_iter);
756                 dbus_message_iter_recurse(&item_iter, &value_iter);
757                 dbus_message_iter_get_basic(&value_iter, &gain);
758
759                 spkr_gain = (unsigned int)gain;
760                 BT_DBG("spk_gain[%d]", spkr_gain);
761
762                 __bt_telephony_event_cb(
763                                         BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN,
764                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
765                                         (void *)&spkr_gain);
766
767                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
768         }
769
770         if (g_strcmp0(property, "MicrophoneGain") == 0) {
771                 unsigned int mic_gain;
772                 guint16 gain;
773                 dbus_message_iter_next(&item_iter);
774                 dbus_message_iter_recurse(&item_iter, &value_iter);
775                 dbus_message_iter_get_basic(&value_iter, &gain);
776
777                 mic_gain = (unsigned int)gain;
778                 BT_DBG("mic_gain[%d]", mic_gain);
779
780                 __bt_telephony_event_cb(
781                                         BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN,
782                                         BLUETOOTH_TELEPHONY_ERROR_NONE,
783                                         (void *)&mic_gain);
784
785                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
786         }
787
788         if (g_strcmp0(property, "Playing") == 0) {
789                 gboolean audio_sink_playing = FALSE;
790                 dbus_message_iter_next(&item_iter);
791                 dbus_message_iter_recurse(&item_iter, &value_iter);
792                 dbus_message_iter_get_basic(&value_iter, &audio_sink_playing);
793
794                 if (audio_sink_playing) {
795                         telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
796                          __bt_telephony_event_cb(
797                                 BLUETOOTH_EVENT_TELEPHONY_AUDIO_CONNECTED,
798                                 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
799                 } else {
800                         telephony_info.headset_state =
801                                                 BLUETOOTH_STATE_CONNECTED;
802                         __bt_telephony_event_cb(
803                                 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
804                                 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
805                 }
806
807                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
808         }
809         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
810 }
811
812
813 static int __bluetooth_telephony_proxy_init(void)
814 {
815         FN_START;
816
817         object = (GObject *)__bluetooth_telephony_method_new();
818
819         if (NULL == object)
820                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
821
822         BT_DBG("telephony_object = %x", object);
823
824         dbus_g_connection_register_g_object(telephony_dbus_info.conn,
825                         telephony_info.call_path, G_OBJECT(object));
826
827         FN_END;
828         return BLUETOOTH_TELEPHONY_ERROR_NONE;
829 }
830
831 static void __bluetooth_telephony_proxy_deinit(void)
832 {
833         FN_START;
834
835         dbus_g_connection_unregister_g_object(telephony_dbus_info.conn,
836                                 G_OBJECT(object));
837
838         g_object_unref(object);
839         object = NULL;
840
841         FN_END;
842         return;
843 }
844
845 static int __bluetooth_telephony_register(void)
846 {
847         DBusMessage *reply;
848         DBusError err;
849         char *path = g_strdup(telephony_info.call_path);
850         int ret;
851
852         FN_START;
853
854         reply =  __bluetooth_telephony_dbus_method_send(
855                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
856                         "RegisterApplication", &err, DBUS_TYPE_STRING, &path,
857                         DBUS_TYPE_STRING, &src_addr,
858                         DBUS_TYPE_INVALID);
859
860         g_free(path);
861         if (!reply) {
862                 BT_ERR("Error returned in method call");
863                 if (dbus_error_is_set(&err)) {
864                         ret = __bt_telephony_get_error(err.message);
865                         BT_ERR("Error here %d\n", ret);
866                         dbus_error_free(&err);
867                         return ret;
868                 }
869                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
870         }
871
872         dbus_message_unref(reply);
873         BT_DBG("__bluetooth_telephony_register completed");
874         FN_END;
875         return BLUETOOTH_TELEPHONY_ERROR_NONE;
876 }
877
878 static  int __bluetooth_telephony_unregister(void)
879 {
880         DBusMessage *reply;
881         DBusError err;
882         char *path = g_strdup(telephony_info.call_path);
883         int ret;
884
885         FN_START;
886
887         reply = __bluetooth_telephony_dbus_method_send(
888                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
889                         "UnregisterApplication", &err, DBUS_TYPE_STRING, &path,
890                         DBUS_TYPE_INVALID);
891
892         g_free(path);
893         if (!reply) {
894                 BT_ERR("Error returned in method call");
895                 if (dbus_error_is_set(&err)) {
896                         ret = __bt_telephony_get_error(err.message);
897                         dbus_error_free(&err);
898                         return ret;
899                 }
900                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
901         }
902
903         dbus_message_unref(reply);
904         BT_DBG("__bluetooth_telephony_unregister completed");
905         FN_END;
906         return BLUETOOTH_TELEPHONY_ERROR_NONE;
907 }
908
909 #ifndef TIZEN_WEARABLE
910 static void __bluetooth_telephony_init_headset_state(void)
911 {
912         DBusMessage *reply;
913         DBusError err;
914
915         gboolean status = FALSE;
916
917         FN_START;
918
919         if (telephony_dbus_info.conn == NULL) {
920                 BT_ERR("Bluetooth telephony not initilized");
921                 return;
922         }
923         reply = __bluetooth_telephony_dbus_method_send(
924                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
925                         "IsConnected", &err, DBUS_TYPE_INVALID);
926
927         if (!reply) {
928                 BT_ERR("Error returned in method call\n");
929                 if (dbus_error_is_set(&err)) {
930                         __bt_telephony_get_error(err.message);
931                         dbus_error_free(&err);
932                 }
933                 return;
934         }
935
936         if (!dbus_message_get_args(reply, &err,
937                         DBUS_TYPE_BOOLEAN, &status,
938                         DBUS_TYPE_INVALID)) {
939                 BT_ERR("Error to get features");
940                 if (dbus_error_is_set(&err)) {
941                         BT_ERR("error message: %s", err.message);
942                         dbus_error_free(&err);
943                 }
944                 dbus_message_unref(reply);
945                 return;
946         }
947
948         BT_INFO("Headset Connected Status = [%d]", status);
949         if (status)
950                 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
951         else
952                 return;
953
954         if (bluetooth_telephony_is_sco_connected())
955                 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
956
957         FN_END;
958 }
959 #endif
960
961 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
962 {
963         gboolean flag = FALSE;
964         FN_START;
965
966         switch ((device_class & 0x1f00) >> 8) {
967         case 0x04:
968                 switch ((device_class & 0xfc) >> 2) {
969                 case 0x01:
970                 case 0x02:
971                         flag = TRUE;
972                         break;
973                 case 0x06:
974                         flag = TRUE;
975                         break;
976                 case 0x0b:
977                 case 0x0c:
978                 case 0x0d:
979                         break;
980                 default:
981                         flag = TRUE;
982                         break;
983                 }
984                 break;
985
986         /* Tizen Wearable device */
987         case 0x07:
988                 switch ((device_class & 0xfc) >> 2) {
989                 case 0x01: /* Wrist Watch */
990                         flag = TRUE;
991                         break;
992                 default:
993                         break;
994                 }
995                 break;
996         }
997         BT_DBG("[%d]", flag);
998         FN_END;
999         return flag;
1000 }
1001
1002 static gboolean __bluetooth_telephony_is_headset_by_uuid(GValue *value)
1003 {
1004         int i;
1005         char **uuids;
1006         char **parts;
1007         unsigned int service = 0;
1008
1009         FN_START;
1010
1011         retv_if(value == NULL, FALSE);
1012
1013         uuids = g_value_get_boxed(value);
1014         retv_if(uuids == NULL, FALSE);
1015
1016         for (i = 0; uuids[i] != NULL; i++) {
1017                 parts = g_strsplit(uuids[i], "-", -1);
1018
1019                 if (parts == NULL || parts[0] == NULL) {
1020                         g_strfreev(parts);
1021                         continue;
1022                 }
1023
1024                 service = g_ascii_strtoull(parts[0], NULL, 16);
1025                 g_strfreev(parts);
1026
1027                 if (service == BLUETOOTH_HS_PROFILE_UUID ||
1028                                 service == BLUETOOTH_HF_PROFILE_UUID)
1029                         return TRUE;
1030         }
1031
1032         FN_END;
1033         return FALSE;
1034 }
1035
1036
1037 static int __bluetooth_telephony_get_connected_device(void)
1038 {
1039         DBusMessage *msg;
1040         DBusMessage *reply;
1041         DBusMessageIter reply_iter;
1042         DBusMessageIter value_iter;
1043         DBusError err;
1044         DBusConnection *conn;
1045         DBusGProxy *headset_agent_proxy = NULL;
1046
1047         GError *error = NULL;
1048         uint32_t device_class;
1049         gboolean playing = FALSE;
1050         gboolean connected = FALSE;
1051         GHashTable *list_hash = NULL;
1052         GValue *value = {0};
1053         char *object_path = NULL;
1054         DBusGProxy *proxy = NULL;
1055         const gchar *address;
1056
1057         FN_START;
1058         conn = _bt_get_system_conn();
1059         retv_if(conn == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
1060
1061         msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME, "/",
1062                                                 BLUEZ_MANAGER_INTERFACE,
1063                                                 "GetManagedObjects");
1064
1065         retv_if(msg == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
1066
1067         /* Synchronous call */
1068         dbus_error_init(&err);
1069         reply = dbus_connection_send_with_reply_and_block(
1070                                         conn, msg,
1071                                         -1, &err);
1072         dbus_message_unref(msg);
1073
1074         if (!reply) {
1075                 BT_ERR("Can't get managed objects");
1076
1077                 if (dbus_error_is_set(&err)) {
1078                         BT_ERR("%s", err.message);
1079                         dbus_error_free(&err);
1080                 }
1081                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1082         }
1083
1084         if (dbus_message_iter_init(reply, &reply_iter) == FALSE) {
1085                 BT_ERR("Fail to iterate the reply");
1086                 dbus_message_unref(reply);
1087                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1088         }
1089
1090         dbus_message_iter_recurse(&reply_iter, &value_iter);
1091
1092         /* signature of GetManagedObjects:      a{oa{sa{sv}}} */
1093         while (dbus_message_iter_get_arg_type(&value_iter) ==
1094                                                 DBUS_TYPE_DICT_ENTRY) {
1095                 DBusMessageIter msg_iter;
1096
1097                 dbus_message_iter_recurse(&value_iter, &msg_iter);
1098
1099                 /* Parse the signature: oa{sa{sv}}} */
1100                 retv_if(dbus_message_iter_get_arg_type(&msg_iter) !=
1101                                 DBUS_TYPE_OBJECT_PATH,
1102                                 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
1103
1104                 dbus_message_iter_get_basic(&msg_iter, &object_path);
1105
1106                 if (object_path) {
1107                         proxy = dbus_g_proxy_new_for_name(
1108                                                 telephony_dbus_info.conn,
1109                                                 BLUEZ_SERVICE_NAME,
1110                                                 object_path,
1111                                                 BLUEZ_PROPERTIES_INTERFACE);
1112                         if (proxy == NULL)
1113                                 goto done;
1114
1115                         dbus_g_proxy_call(proxy, "GetAll", &error,
1116                                                 G_TYPE_STRING,
1117                                                 BLUEZ_DEVICE_INTERFACE,
1118                                                 G_TYPE_INVALID,
1119                                                 dbus_g_type_get_map("GHashTable",
1120                                                         G_TYPE_STRING,
1121                                                         G_TYPE_VALUE),
1122                                                 &list_hash,
1123                                                 G_TYPE_INVALID);
1124                         if (list_hash == NULL)
1125                                 goto done;
1126
1127                         if (error) {
1128                                 BT_ERR("error in GetBasicProperties [%s]\n", error->message);
1129                                 g_error_free(error);
1130                                 goto done;
1131                         }
1132
1133                         value = g_hash_table_lookup(list_hash, "Class");
1134                         device_class = value ? g_value_get_uint(value) : 0;
1135
1136                         if (device_class == 0) {
1137                                 BT_DBG("COD is NULL (maybe paired by nfc)...  Checking UUIDs");
1138                                 value = g_hash_table_lookup(list_hash, "UUIDs");
1139                                 if (!__bluetooth_telephony_is_headset_by_uuid(value)) {
1140                                         BT_DBG("UUID checking completed. None HF device");
1141                                         g_object_unref(proxy);
1142                                         proxy = NULL;
1143                                         g_hash_table_destroy(list_hash);
1144                                         dbus_message_iter_next(&value_iter);
1145                                         continue;
1146                                 }
1147                                 BT_DBG("UUID checking completed. HF device");
1148                         } else {
1149                                 if (!__bluetooth_telephony_is_headset(device_class)) {
1150                                         g_object_unref(proxy);
1151                                         proxy = NULL;
1152                                         g_hash_table_destroy(list_hash);
1153                                         dbus_message_iter_next(&value_iter);
1154                                         continue;
1155                                 }
1156                         }
1157
1158                         /* this is headset; Check for Connection */
1159                         headset_agent_proxy = dbus_g_proxy_new_for_name(
1160                                                 telephony_dbus_info.conn,
1161                                                 HFP_AGENT_SERVICE, object_path,
1162                                                 HFP_AGENT_INTERFACE);
1163
1164                         if (headset_agent_proxy == NULL) {
1165                                 g_hash_table_destroy(list_hash);
1166                                 goto done;
1167                         }
1168
1169                         dbus_g_proxy_call(headset_agent_proxy, "IsConnected",
1170                                         &error, G_TYPE_INVALID,
1171                                         G_TYPE_BOOLEAN, &connected,
1172                                         G_TYPE_INVALID);
1173
1174                         if (error == NULL) {
1175                                 if (connected) {
1176                                         value = g_hash_table_lookup(list_hash,
1177                                                                         "Address");
1178                                         address = value ? g_value_get_string(
1179                                                                 value) : NULL;
1180
1181                                         g_strlcpy(telephony_info.address,
1182                                                         address,
1183                                                         sizeof(telephony_info.address));
1184                                         dbus_g_proxy_call(headset_agent_proxy,
1185                                                                 "IsPlaying",
1186                                                                 &error,
1187                                                                 G_TYPE_INVALID,
1188                                                                 G_TYPE_BOOLEAN,
1189                                                                 &playing,
1190                                                                 G_TYPE_INVALID);
1191                                         if (playing)
1192                                                 telephony_info.headset_state =
1193                                                         BLUETOOTH_STATE_PLAYING;
1194                                         else
1195                                                 telephony_info.headset_state =
1196                                                         BLUETOOTH_STATE_CONNECTED;
1197
1198                                         g_hash_table_destroy(list_hash);
1199                                         goto done;
1200                                 }
1201                         } else {
1202                                 g_error_free(error);
1203                         }
1204
1205                         g_hash_table_destroy(list_hash);
1206                         g_object_unref(proxy);
1207                         proxy = NULL;
1208                 } /* end of if(object_path) */
1209
1210         dbus_message_iter_next(&value_iter);
1211         } /* end of while */
1212
1213 done:
1214         if (proxy)
1215                 g_object_unref(proxy);
1216
1217         dbus_message_unref(reply);
1218
1219         FN_END;
1220         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1221 }
1222
1223 static DBusGProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1224 {
1225         DBusGProxy *proxy = NULL;
1226
1227         FN_START;
1228
1229         if (strlen(telephony_info.address) == 0)
1230                 __bluetooth_telephony_get_connected_device();
1231
1232         if (strlen(telephony_info.address) == 0)
1233                 return NULL;
1234
1235         proxy = dbus_g_proxy_new_for_name(telephony_dbus_info.conn,
1236                         HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1237                         HFP_AGENT_INTERFACE);
1238
1239         FN_END;
1240         return proxy;
1241 }
1242
1243
1244 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1245                                                         void  *user_data)
1246 {
1247         DBusError dbus_error;
1248         DBusConnection *conn;
1249         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1250         GError *error = NULL;
1251
1252         DBusConnection *dbus_conn;
1253         bluetooth_device_address_t loc_address = { {0} };
1254         char src_address[BT_ADDRESS_STRING_SIZE] = { 0 };
1255
1256
1257         FN_START;
1258         g_type_init();
1259
1260         if (is_initialized == TRUE) {
1261                 BT_ERR("Bluetooth telephony already initilized");
1262                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_INITIALIZED;
1263         }
1264
1265         is_initialized = TRUE;
1266
1267         telephony_dbus_info.conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
1268         if (!telephony_dbus_info.conn) {
1269                 if (NULL != error) {
1270                         BT_ERR("dbus_g_bus_get() failed:[%d:%s]\n",
1271                                         error->code, error->message);
1272                         g_error_free(error);
1273                 }
1274                 is_initialized = FALSE;
1275                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1276         }
1277
1278         /* Call Path */
1279         snprintf(telephony_info.call_path, sizeof(telephony_info.call_path),
1280                                         CSD_CALL_APP_PATH, getpid());
1281         BT_DBG("Call Path = %s", telephony_info.call_path);
1282         memset(telephony_info.address, 0x00, sizeof(telephony_info.address));
1283
1284         if (__bluetooth_telephony_proxy_init()) {
1285                 BT_ERR("__bluetooth_telephony_proxy_init failed\n");
1286                 dbus_g_connection_unref(telephony_dbus_info.conn);
1287                 telephony_dbus_info.conn = NULL;
1288                 is_initialized = FALSE;
1289                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1290         }
1291
1292         telephony_dbus_info.manager_proxy = dbus_g_proxy_new_for_name(
1293                                                 telephony_dbus_info.conn,
1294                                                 BLUEZ_SERVICE_NAME,
1295                                                 "/", BLUEZ_MANAGER_INTERFACE);
1296
1297         if (telephony_dbus_info.manager_proxy == NULL) {
1298                 BT_ERR("Could not create a manager proxy\n");
1299                 __bluetooth_telephony_proxy_deinit();
1300                 dbus_g_connection_unref(telephony_dbus_info.conn);
1301                 telephony_dbus_info.conn = NULL;
1302                 is_initialized = FALSE;
1303                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1304         }
1305
1306         telephony_dbus_info.dbus_proxy = dbus_g_proxy_new_for_name(
1307                         telephony_dbus_info.conn, DBUS_SERVICE_DBUS,
1308                         DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
1309
1310         if (NULL == telephony_dbus_info.dbus_proxy) {
1311                 __bluetooth_telephony_proxy_deinit();
1312                 dbus_g_connection_unref(telephony_dbus_info.conn);
1313                 telephony_dbus_info.conn = NULL;
1314                 g_object_unref(telephony_dbus_info.manager_proxy);
1315                 telephony_dbus_info.manager_proxy = NULL;
1316                 is_initialized = FALSE;
1317                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1318         }
1319
1320         dbus_conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1321
1322         /*Add Signal callback for BT enabled*/
1323         if (!dbus_connection_add_filter(dbus_conn,
1324                                 __bt_telephony_adapter_filter,
1325                                 NULL, NULL)) {
1326                 BT_ERR("Fail to add filter");
1327                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1328         }
1329
1330         dbus_error_init(&dbus_error);
1331         dbus_bus_add_match(dbus_conn,
1332                         "type='signal',interface='org.freedesktop.DBus.ObjectManager'"
1333                         ",member='InterfacesAdded'",
1334                         &dbus_error);
1335         if (dbus_error_is_set(&dbus_error)) {
1336                 BT_ERR("Fail to add match: %s\n", dbus_error.message);
1337                 dbus_error_free(&dbus_error);
1338                 goto fail;
1339         }
1340
1341         /*Callback and user applicaton data*/
1342         telephony_info.cb = cb;
1343         telephony_info.user_data = user_data;
1344         telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1345
1346         dbus_error_init(&dbus_error);
1347         conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1348         dbus_connection_add_filter(conn, __bluetooth_telephony_event_filter,
1349                                 NULL, NULL);
1350         dbus_bus_add_match(conn,
1351                         "type='signal',interface='"BLUEZ_HEADSET_INTERFACE
1352                         "',member='PropertyChanged'", &dbus_error);
1353         if (dbus_error_is_set(&dbus_error)) {
1354                 BT_ERR("Fail to add dbus filter signal\n");
1355                 dbus_error_free(&dbus_error);
1356                 goto fail;
1357         }
1358
1359         dbus_error_init(&dbus_error);
1360         dbus_bus_add_match(conn,
1361                         "type='signal',interface='"HFP_AGENT_SERVICE
1362                         "',member='"HFP_NREC_STATUS_CHANGE"'" , &dbus_error);
1363         if (dbus_error_is_set(&dbus_error)) {
1364                 BT_ERR("Fail to add dbus filter signal\n");
1365                 dbus_error_free(&dbus_error);
1366                 goto fail;
1367         }
1368
1369         dbus_error_init(&dbus_error);
1370         dbus_bus_add_match(conn,
1371                         "type='signal',interface='"HFP_AGENT_SERVICE
1372                         "',member='"HFP_ANSWER_CALL"'" , &dbus_error);
1373         if (dbus_error_is_set(&dbus_error)) {
1374                 BT_ERR("Fail to add dbus filter signal\n");
1375                 dbus_error_free(&dbus_error);
1376                 goto fail;
1377         }
1378
1379         dbus_error_init(&dbus_error);
1380         dbus_bus_add_match(conn,
1381                         "type='signal',interface='"HFP_AGENT_SERVICE
1382                         "',member='"HFP_REJECT_CALL"'" , &dbus_error);
1383         if (dbus_error_is_set(&dbus_error)) {
1384                 BT_ERR("Fail to add dbus filter signal\n");
1385                 dbus_error_free(&dbus_error);
1386                 goto fail;
1387         }
1388
1389         dbus_error_init(&dbus_error);
1390         dbus_bus_add_match(conn,
1391                         "type='signal',interface='"HFP_AGENT_SERVICE
1392                         "',member='"HFP_RELEASE_CALL"'" , &dbus_error);
1393         if (dbus_error_is_set(&dbus_error)) {
1394                 BT_ERR("Fail to add dbus filter signal\n");
1395                 dbus_error_free(&dbus_error);
1396                 goto fail;
1397         }
1398
1399         dbus_error_init(&dbus_error);
1400         dbus_bus_add_match(conn,
1401                         "type='signal',interface='"HFP_AGENT_SERVICE
1402                         "',member='"HFP_THREEWAY_CALL"'" , &dbus_error);
1403         if (dbus_error_is_set(&dbus_error)) {
1404                 BT_ERR("Fail to add dbus filter signal\n");
1405                 dbus_error_free(&dbus_error);
1406                 goto fail;
1407         }
1408
1409         if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED)
1410                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1411
1412         /*Bluetooth is active, therefore set the flag */
1413         is_active = TRUE;
1414         if (!src_addr) {
1415                 ret = bluetooth_get_local_address(&loc_address);
1416                 if (ret != BLUETOOTH_ERROR_NONE) {
1417                         BT_ERR("Fail to get local address\n");
1418                         ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1419                         goto fail;
1420                 }
1421                 _bt_convert_addr_type_to_string(src_address, loc_address.addr);
1422                 src_addr = g_strdup(src_address);
1423         }
1424         ret = __bluetooth_telephony_register();
1425         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1426                 BT_ERR("__bluetooth_telephony_register failed\n");
1427                 goto fail;
1428         }
1429
1430 #ifndef TIZEN_WEARABLE
1431         __bluetooth_telephony_init_headset_state();
1432 #endif
1433
1434         FN_END;
1435         return ret;
1436 fail:
1437         bluetooth_telephony_deinit();
1438         return ret;
1439 }
1440
1441 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1442 {
1443         DBusConnection *conn;
1444         DBusError error;
1445
1446         FN_START;
1447         BT_TELEPHONY_CHECK_INITIALIZED();
1448
1449         is_initialized = FALSE;
1450
1451         conn = dbus_g_connection_get_connection(telephony_dbus_info.conn);
1452
1453         dbus_error_init(&error);
1454         dbus_bus_remove_match(conn,
1455                         "type='signal',interface='"BLUEZ_HEADSET_INTERFACE
1456                         "',member='PropertyChanged'", &error);
1457         if (dbus_error_is_set(&error)) {
1458                 BT_ERR("Fail to remove dbus filter signal\n");
1459                 dbus_error_free(&error);
1460                 /* Need to re initilize before use */
1461                 dbus_error_init(&error);
1462         }
1463
1464         dbus_error_init(&error);
1465         dbus_bus_remove_match(conn,
1466                         "type='signal',interface='"HFP_AGENT_SERVICE
1467                         "',member='"HFP_NREC_STATUS_CHANGE"'", &error);
1468         if (dbus_error_is_set(&error)) {
1469                 BT_ERR("Fail to remove dbus filter signal\n");
1470                 dbus_error_free(&error);
1471         }
1472
1473         dbus_error_init(&error);
1474         dbus_bus_remove_match(conn,
1475                         "type='signal',interface='"HFP_AGENT_SERVICE
1476                         "',member='"HFP_ANSWER_CALL"'", &error);
1477         if (dbus_error_is_set(&error)) {
1478                 BT_ERR("Fail to remove dbus filter signal\n");
1479                 dbus_error_free(&error);
1480         }
1481
1482         dbus_error_init(&error);
1483         dbus_bus_remove_match(conn,
1484                         "type='signal',interface='"HFP_AGENT_SERVICE
1485                         "',member='"HFP_REJECT_CALL"'", &error);
1486         if (dbus_error_is_set(&error)) {
1487                 BT_ERR("Fail to remove dbus filter signal\n");
1488                 dbus_error_free(&error);
1489         }
1490
1491         dbus_error_init(&error);
1492         dbus_bus_remove_match(conn,
1493                         "type='signal',interface='"HFP_AGENT_SERVICE
1494                         "',member='"HFP_RELEASE_CALL"'", &error);
1495         if (dbus_error_is_set(&error)) {
1496                 BT_ERR("Fail to remove dbus filter signal\n");
1497                 dbus_error_free(&error);
1498         }
1499
1500         dbus_error_init(&error);
1501         dbus_bus_remove_match(conn,
1502                         "type='signal',interface='"HFP_AGENT_SERVICE
1503                         "',member='"HFP_THREEWAY_CALL"'", &error);
1504         if (dbus_error_is_set(&error)) {
1505                 BT_ERR("Fail to remove dbus filter signal\n");
1506                 dbus_error_free(&error);
1507         }
1508
1509         dbus_connection_remove_filter(conn,
1510                                 __bluetooth_telephony_event_filter,
1511                                 NULL);
1512
1513         if (bluetooth_check_adapter() != BLUETOOTH_ADAPTER_DISABLED ||
1514                 bluetooth_check_adapter_le() != BLUETOOTH_ADAPTER_LE_DISABLED)
1515                 __bluetooth_telephony_unregister();
1516
1517         __bluetooth_telephony_proxy_deinit();
1518
1519         telephony_info.cb = NULL;
1520         telephony_info.user_data = NULL;
1521         telephony_info.call_count = 0;
1522         telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1523
1524         /* Remove BT enabled signal */
1525         dbus_error_init(&error);
1526         dbus_bus_remove_match(conn,
1527                         "type='signal',interface='org.freedesktop.DBus.ObjectManager'"
1528                         ",member='InterfacesAdded'",
1529                         &error);
1530         if (dbus_error_is_set(&error)) {
1531                 BT_ERR("Fail to remove dbus filter signal\n");
1532                 dbus_error_free(&error);
1533         }
1534
1535         dbus_connection_remove_filter(dbus_g_connection_get_connection(
1536                                 telephony_dbus_info.conn),
1537                                 __bt_telephony_adapter_filter,
1538                                 NULL);
1539         g_free(src_addr);
1540         src_addr = NULL;
1541
1542         if (telephony_dbus_info.manager_proxy != NULL) {
1543                 g_object_unref(telephony_dbus_info.manager_proxy);
1544                 telephony_dbus_info.manager_proxy = NULL;
1545         }
1546
1547         if (telephony_dbus_info.conn != NULL) {
1548                 dbus_g_connection_unref(telephony_dbus_info.conn);
1549                 telephony_dbus_info.conn = NULL;
1550         }
1551
1552         if (telephony_dbus_info.dbus_proxy != NULL) {
1553                 g_object_unref(telephony_dbus_info.dbus_proxy);
1554                 telephony_dbus_info.dbus_proxy = NULL;
1555         }
1556
1557         FN_END;
1558         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1559 }
1560
1561 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1562 {
1563         DBusMessage *reply;
1564         DBusError err;
1565
1566         gboolean status = FALSE;
1567
1568         FN_START;
1569
1570         retv_if(is_initialized == FALSE, FALSE);
1571         retv_if(bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED, FALSE);
1572
1573         reply = __bluetooth_telephony_dbus_method_send(
1574                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1575                         "IsPlaying", &err, DBUS_TYPE_INVALID);
1576
1577         if (!reply) {
1578                 BT_ERR("Error returned in method call\n");
1579                 if (dbus_error_is_set(&err)) {
1580                         __bt_telephony_get_error(err.message);
1581                         dbus_error_free(&err);
1582                 }
1583                 return FALSE;
1584         }
1585
1586         if (!dbus_message_get_args(reply, &err,
1587                         DBUS_TYPE_BOOLEAN, &status,
1588                         DBUS_TYPE_INVALID)) {
1589                 BT_ERR("Error to get features");
1590                 if (dbus_error_is_set(&err)) {
1591                         BT_ERR("error message: %s", err.message);
1592                         dbus_error_free(&err);
1593                 }
1594                 dbus_message_unref(reply);
1595                 return FALSE;
1596         }
1597
1598 #ifdef TIZEN_WEARABLE
1599         if (status == TRUE && telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1600                 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
1601 #endif
1602
1603         BT_INFO("SCO Connected Status = [%d]", status);
1604         return status;
1605 }
1606
1607 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1608 {
1609         DBusMessage *reply;
1610         DBusError err;
1611         DBusMessageIter reply_iter;
1612         DBusMessageIter reply_iter_entry;
1613         const char *property;
1614
1615         FN_START;
1616
1617         BT_TELEPHONY_CHECK_INITIALIZED();
1618         BT_TELEPHONY_CHECK_ENABLED();
1619
1620         if (status == NULL)
1621                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1622
1623         if (telephony_info.headset_state == BLUETOOTH_STATE_DISCONNETED)
1624                 return BLUETOOTH_TELEPHONY_ERROR_AUDIO_NOT_CONNECTED;
1625
1626         reply = __bluetooth_telephony_dbus_method_send(
1627                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1628                         "GetProperties", &err, DBUS_TYPE_INVALID);
1629
1630         if (!reply) {
1631                 BT_ERR("Error returned in method call\n");
1632                 if (dbus_error_is_set(&err)) {
1633                         BT_DBG("Error message = %s", err.message);
1634                         dbus_error_free(&err);
1635                 }
1636                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1637         }
1638
1639         dbus_message_iter_init(reply, &reply_iter);
1640
1641         if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
1642                 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY");
1643                 dbus_message_unref(reply);
1644                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1645         }
1646
1647         dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
1648
1649         /*Parse the dict */
1650         while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
1651                                                 DBUS_TYPE_DICT_ENTRY) {
1652
1653                 DBusMessageIter dict_entry, dict_entry_val;
1654                 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
1655                 dbus_message_iter_get_basic(&dict_entry, &property);
1656                 BT_DBG("String received = %s", property);
1657
1658                 if (g_strcmp0("nrec", property) == 0) {
1659                         dbus_message_iter_next(&dict_entry);
1660                         dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1661                         if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
1662                                                 DBUS_TYPE_BOOLEAN)
1663                                 continue;
1664
1665                         dbus_message_iter_get_basic(&dict_entry_val, status);
1666                         BT_DBG("NREC status = [%d]", *status);
1667                 }
1668                 dbus_message_iter_next(&reply_iter_entry);
1669         }
1670         dbus_message_unref(reply);
1671         FN_END;
1672         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1673 }
1674
1675 BT_EXPORT_API int bluetooth_telephony_is_wbs_mode(gboolean *status)
1676 {
1677         DBusMessage *reply;
1678         DBusError err;
1679         DBusMessageIter reply_iter;
1680         DBusMessageIter reply_iter_entry;
1681         unsigned int codec;
1682         const char *property;
1683
1684         FN_START;
1685
1686         BT_TELEPHONY_CHECK_INITIALIZED();
1687         BT_TELEPHONY_CHECK_ENABLED();
1688
1689         if (status == NULL)
1690                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1691
1692         *status = FALSE;
1693
1694         reply = __bluetooth_telephony_dbus_method_send(
1695                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1696                         "GetProperties", &err, DBUS_TYPE_INVALID);
1697
1698         if (!reply) {
1699                 BT_ERR("Error returned in method call");
1700                 if (dbus_error_is_set(&err)) {
1701                         BT_ERR("Error message = %s", err.message);
1702                         dbus_error_free(&err);
1703                 }
1704                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1705         }
1706
1707         dbus_message_iter_init(reply, &reply_iter);
1708
1709         if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
1710                 BT_ERR("Can't get reply arguments - DBUS_TYPE_ARRAY");
1711                 dbus_message_unref(reply);
1712                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1713         }
1714
1715         dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
1716
1717         /*Parse the dict */
1718         while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
1719                                                 DBUS_TYPE_DICT_ENTRY) {
1720
1721                 DBusMessageIter dict_entry, dict_entry_val;
1722                 dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
1723                 dbus_message_iter_get_basic(&dict_entry, &property);
1724                 BT_DBG("String received = %s", property);
1725
1726                 if (g_strcmp0("codec", property) == 0) {
1727                         dbus_message_iter_next(&dict_entry);
1728                         dbus_message_iter_recurse(&dict_entry, &dict_entry_val);
1729                         if (dbus_message_iter_get_arg_type(&dict_entry_val) !=
1730                                                 DBUS_TYPE_UINT32)
1731                                 continue;
1732
1733                         dbus_message_iter_get_basic(&dict_entry_val, &codec);
1734                         BT_DBG("Codec = [%d]", codec);
1735                         *status = codec == BT_MSBC_CODEC_ID ? TRUE : FALSE;
1736                 }
1737                 dbus_message_iter_next(&reply_iter_entry);
1738         }
1739         dbus_message_unref(reply);
1740         FN_END;
1741         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1742 }
1743
1744 BT_EXPORT_API int bluetooth_telephony_send_vendor_cmd(const char *cmd)
1745 {
1746         GError *error = NULL;
1747         int ret;
1748
1749         FN_START;
1750
1751         BT_TELEPHONY_CHECK_INITIALIZED();
1752         BT_TELEPHONY_CHECK_ENABLED();
1753
1754         BT_DBG("Send Vendor %s", cmd);
1755
1756         if (telephony_dbus_info.proxy == NULL)
1757                 telephony_dbus_info.proxy =
1758                         __bluetooth_telephony_get_connected_device_proxy();
1759
1760         if (telephony_dbus_info.proxy == NULL)
1761                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1762
1763         if (!dbus_g_proxy_call(telephony_dbus_info.proxy, "SendVendorAtCmd",
1764                         &error,
1765                         G_TYPE_STRING, cmd,
1766                         G_TYPE_INVALID, G_TYPE_INVALID)) {
1767                 if (error != NULL) {
1768                         ret = __bt_telephony_get_error(error->message);
1769                         g_error_free(error);
1770                         return ret;
1771                 }
1772
1773         }
1774         FN_END;
1775         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1776 }
1777
1778 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1779 {
1780         DBusMessage *reply;
1781         DBusError err;
1782         int ret;
1783         gboolean state = TRUE;
1784
1785         FN_START;
1786
1787         BT_TELEPHONY_CHECK_INITIALIZED();
1788         BT_TELEPHONY_CHECK_ENABLED();
1789
1790         reply = __bluetooth_telephony_dbus_method_send(
1791                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1792                         "SetVoiceDial", &err, DBUS_TYPE_BOOLEAN, &state,
1793                         DBUS_TYPE_INVALID);
1794
1795         if (!reply) {
1796                 BT_ERR("Error returned in method call\n");
1797                 if (dbus_error_is_set(&err)) {
1798                         ret = __bt_telephony_get_error(err.message);
1799                         dbus_error_free(&err);
1800                         return ret;
1801                 }
1802                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1803         }
1804
1805         dbus_message_unref(reply);
1806
1807         FN_END;
1808         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1809 }
1810
1811 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1812 {
1813         DBusMessage *reply;
1814         DBusError err;
1815         int ret;
1816         gboolean state = FALSE;
1817
1818         FN_START;
1819
1820         BT_TELEPHONY_CHECK_INITIALIZED();
1821         BT_TELEPHONY_CHECK_ENABLED();
1822
1823         reply = __bluetooth_telephony_dbus_method_send(
1824                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1825                         "SetVoiceDial", &err, DBUS_TYPE_BOOLEAN, &state,
1826                         DBUS_TYPE_INVALID);
1827
1828         if (!reply) {
1829                 BT_ERR("Error returned in method call\n");
1830                 if (dbus_error_is_set(&err)) {
1831                         ret = __bt_telephony_get_error(err.message);
1832                         dbus_error_free(&err);
1833                         return ret;
1834                 }
1835                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1836         }
1837
1838         dbus_message_unref(reply);
1839
1840         FN_END;
1841         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1842 }
1843
1844 static void __bluetooth_telephony_sco_start_cb(
1845                         DBusPendingCall *call, gpointer user_data)
1846 {
1847         DBusMessage *reply;
1848         DBusError derr;
1849         DBusMessage *msg = user_data;
1850
1851         reply = dbus_pending_call_steal_reply(call);
1852         dbus_error_init(&derr);
1853
1854         if (dbus_set_error_from_message(&derr, reply)) {
1855                 BT_ERR("hs_sco_cb error: %s, %s",
1856                         derr.name, derr.message);
1857                 dbus_error_free(&derr);
1858                 goto done;
1859         }
1860         dbus_pending_call_unref(call);
1861 done:
1862         BT_DBG("sco_start_cb : -");
1863         dbus_message_unref(msg);
1864         dbus_message_unref(reply);
1865 }
1866
1867 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1868 {
1869         DBusConnection *conn;
1870         DBusMessage *msg;
1871         DBusPendingCall *c;
1872
1873         FN_START;
1874
1875         BT_TELEPHONY_CHECK_INITIALIZED();
1876         BT_TELEPHONY_CHECK_ENABLED();
1877
1878         /* Because this API is async call, so can't use dbus SMACK */
1879         if (__bt_telephony_check_privilege() ==
1880                                 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1881                 BT_ERR("Don't have a privilege to use this API");
1882                 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1883         }
1884
1885         conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
1886         if (!conn) {
1887                 BT_DBG("No System Bus found\n");
1888                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1889         }
1890
1891         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1892                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1893
1894         msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
1895                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1896                         "Play");
1897         if (msg == NULL) {
1898                 BT_ERR("dbus method call failed");
1899                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1900         }
1901
1902         if (dbus_connection_send_with_reply(conn, msg, &c, -1) == FALSE) {
1903                 BT_DBG("HFP_AGENT: send with reply failed");
1904                 dbus_message_unref(msg);
1905                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1906         }
1907         dbus_pending_call_set_notify(c, __bluetooth_telephony_sco_start_cb,
1908                                 msg, NULL);
1909
1910         FN_END;
1911         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1912 }
1913
1914 static void __bluetooth_telephony_sco_close_cb(DBusPendingCall *call, gpointer user_data)
1915 {
1916         DBusMessage *reply;
1917         DBusError derr;
1918         DBusMessage *msg = user_data;
1919
1920         reply = dbus_pending_call_steal_reply(call);
1921         dbus_error_init(&derr);
1922
1923         if (dbus_set_error_from_message(&derr, reply)) {
1924                 BT_ERR("sco_close_cb error: %s, %s",
1925                         derr.name, derr.message);
1926                 dbus_error_free(&derr);
1927                 goto done;
1928         }
1929
1930         dbus_pending_call_unref(call);
1931 done:
1932         BT_DBG("sco_close_cb : -");
1933         dbus_message_unref(msg);
1934         dbus_message_unref(reply);
1935 }
1936 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1937 {
1938         DBusConnection *conn;
1939         DBusMessage *msg;
1940         DBusPendingCall *c;
1941
1942         FN_START;
1943
1944         BT_TELEPHONY_CHECK_INITIALIZED();
1945         BT_TELEPHONY_CHECK_ENABLED();
1946
1947         /* Because this API is async call, so can't use dbus SMACK */
1948         if (__bt_telephony_check_privilege() ==
1949                                 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1950                 BT_ERR("Don't have a privilege to use this API");
1951                 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1952         }
1953
1954         conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
1955         if (!conn) {
1956                 BT_DBG("No System Bus found\n");
1957                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1958         }
1959
1960         if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1961                 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1962
1963         msg = dbus_message_new_method_call(HFP_AGENT_SERVICE,
1964                                 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1965                                 "Stop");
1966         if (msg == NULL) {
1967                 BT_ERR("dbus method call failed");
1968                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1969         }
1970
1971         if (dbus_connection_send_with_reply(conn, msg, &c, -1) == FALSE) {
1972                 BT_DBG("HFP_AGENT: send with reply failed");
1973                 dbus_message_unref(msg);
1974                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1975         }
1976         telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
1977
1978         dbus_pending_call_set_notify(c, __bluetooth_telephony_sco_close_cb,
1979                                                                 msg, NULL);
1980
1981         FN_END;
1982         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1983 }
1984
1985 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1986 {
1987         int ret;
1988
1989         BT_TELEPHONY_CHECK_INITIALIZED();
1990         BT_TELEPHONY_CHECK_ENABLED();
1991
1992         FN_START;
1993         BT_DBG("call_id = [%d]", call_id);
1994
1995         /*Make sure SCO is already connected */
1996         ret = __bluetooth_telephony_send_call_status(
1997                                 CSD_CALL_STATUS_MO_ALERTING, call_id, NULL);
1998         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1999                 BT_ERR("send call status Failed = [%d]", ret);
2000                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2001         }
2002         FN_END;
2003         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2004 }
2005
2006 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
2007                                                         unsigned int bt_audio)
2008 {
2009         int ret;
2010
2011         FN_START;
2012         BT_DBG("call_id = [%d]", call_id);
2013
2014         BT_TELEPHONY_CHECK_INITIALIZED();
2015         BT_TELEPHONY_CHECK_ENABLED();
2016
2017         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
2018                                                                 call_id, NULL);
2019         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2020                 BT_ERR("send call status Failed = [%d]", ret);
2021                 return ret;
2022         }
2023
2024         if (bt_audio) {
2025                 if (!bluetooth_telephony_is_sco_connected()) {
2026                         ret = bluetooth_telephony_audio_open();
2027                         if (ret != 0) {
2028                                 BT_ERR("Audio connection call Failed = %d", ret);
2029                                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2030                         }
2031                 }
2032         }
2033
2034         FN_END;
2035         return ret;
2036 }
2037
2038 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
2039 {
2040         int ret;
2041
2042         FN_START;
2043         BT_DBG("call_id = [%d]", call_id);
2044
2045         BT_TELEPHONY_CHECK_INITIALIZED();
2046         BT_TELEPHONY_CHECK_ENABLED();
2047
2048         if (telephony_info.call_count > 0)
2049                 telephony_info.call_count = telephony_info.call_count - 1;
2050
2051         if (telephony_info.call_count  == 0) {
2052                 if (bluetooth_telephony_is_sco_connected()) {
2053                         ret = bluetooth_telephony_audio_close();
2054                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2055                                 BT_ERR(" Failed = [%d]", ret);
2056                 }
2057         }
2058
2059         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
2060                                                                 call_id, NULL);
2061         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2062                 BT_ERR("send call status Failed = [%d]", ret);
2063                 return ret;
2064         }
2065
2066         FN_END;
2067         return ret;
2068 }
2069
2070 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
2071 {
2072         int ret;
2073
2074         FN_START;
2075         BT_DBG("call_id = [%d]", call_id);
2076
2077         BT_TELEPHONY_CHECK_INITIALIZED();
2078         BT_TELEPHONY_CHECK_ENABLED();
2079
2080         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
2081                                                                 call_id, NULL);
2082         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2083                 BT_ERR("send call status Failed = [%d]", ret);
2084
2085         FN_END;
2086         return ret;
2087 }
2088
2089 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
2090 {
2091         int ret;
2092
2093         FN_START;
2094         BT_DBG("call_id = [%d]", call_id);
2095
2096         BT_TELEPHONY_CHECK_INITIALIZED();
2097         BT_TELEPHONY_CHECK_ENABLED();
2098
2099         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
2100                                                                 call_id, NULL);
2101         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2102                 BT_ERR("send call status Failed = [%d]", ret);
2103
2104         FN_END;
2105         return ret;
2106 }
2107
2108 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
2109                                 unsigned int call_count)
2110 {
2111         int i;
2112         int ret;
2113         GList *list = call_list;
2114         bt_telephony_call_status_info_t *call_status;
2115
2116         FN_START;
2117
2118         BT_TELEPHONY_CHECK_INITIALIZED();
2119         BT_TELEPHONY_CHECK_ENABLED();
2120
2121         if (NULL == list) {
2122                 BT_ERR("call_list is invalid");
2123                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2124         }
2125
2126         /* Because this API is async call, so can't use dbus SMACK */
2127         if (__bt_telephony_check_privilege() ==
2128                                 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
2129                 BT_ERR("Don't have a privilege to use this API");
2130                 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
2131         }
2132
2133         BT_DBG(" call_count = [%d]", call_count);
2134
2135         for (i = 0; i < call_count; i++) {
2136                 call_status = g_list_nth_data(list, i);
2137
2138                 if (NULL == call_status)
2139                         continue;
2140
2141                 BT_DBG(" %d : Call id [%d] status[%d]", i,
2142                                         call_status->call_id,
2143                                         call_status->call_status);
2144
2145                 if (NULL != call_status->phone_number)
2146                         DBG_SECURE(" call number [%s]", call_status->phone_number);
2147
2148                 switch (call_status->call_status) {
2149                 case BLUETOOTH_CALL_STATE_HELD:
2150                         ret = __bluetooth_telephony_send_call_status(
2151                                                 CSD_CALL_STATUS_HOLD,
2152                                                 call_status->call_id,
2153                                                 call_status->phone_number);
2154                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2155                                 BT_ERR("Failed = %d", ret);
2156                                 return ret;
2157                         }
2158                 break;
2159
2160                 case BLUETOOTH_CALL_STATE_CONNECTED:
2161                         ret = __bluetooth_telephony_send_call_status(
2162                                         CSD_CALL_STATUS_ACTIVE,
2163                                         call_status->call_id,
2164                                         call_status->phone_number);
2165                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2166                                 BT_ERR("Failed = [%d]", ret);
2167                                 return ret;
2168                         }
2169                 break;
2170
2171                 default:
2172                         if ((call_status->call_status < BLUETOOTH_CALL_STATE_NONE) ||
2173                                 (call_status->call_status >= BLUETOOTH_CALL_STATE_ERROR)) {
2174                                 BT_ERR("Unknown Call state");
2175                                 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
2176                         }
2177                 }
2178         }
2179
2180         FN_END;
2181         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2182 }
2183
2184 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
2185                                 unsigned int call_count)
2186 {
2187         int ret;
2188
2189         FN_START;
2190
2191         ret = bluetooth_telephony_call_swapped(call_list, call_count);
2192
2193         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2194                 BT_ERR("Failed = [%d]", ret);
2195                 return ret;
2196         }
2197
2198         telephony_info.call_count = call_count;
2199
2200         FN_END;
2201         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2202 }
2203
2204 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
2205                         const char *ph_number, unsigned int call_id,
2206                         unsigned int bt_audio)
2207 {
2208         DBusMessage *reply;
2209         DBusError err;
2210         const char *path = telephony_info.call_path;
2211         int ret;
2212
2213         FN_START;
2214
2215         BT_TELEPHONY_CHECK_INITIALIZED();
2216         BT_TELEPHONY_CHECK_ENABLED();
2217
2218         if (NULL == ph_number)
2219                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2220
2221         reply = __bluetooth_telephony_dbus_method_send(
2222                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2223                         "OutgoingCall", &err, DBUS_TYPE_STRING, &path,
2224                         DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
2225                         &call_id, DBUS_TYPE_INVALID);
2226
2227         if (!reply) {
2228                 BT_ERR("Error returned in method call\n");
2229                 if (dbus_error_is_set(&err)) {
2230                         ret = __bt_telephony_get_error(err.message);
2231                         dbus_error_free(&err);
2232                         return ret;
2233                 }
2234                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2235         }
2236
2237         dbus_message_unref(reply);
2238
2239         telephony_info.call_count++;
2240         BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
2241
2242         if (bt_audio) {
2243                 if (!bluetooth_telephony_is_sco_connected()) {
2244                         ret = bluetooth_telephony_audio_open();
2245                         if (ret != 0) {
2246                                 BT_ERR(" Audio connection Failed = %d", ret);
2247                                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2248                         }
2249                 }
2250         }
2251
2252         FN_END;
2253         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2254 }
2255
2256 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
2257                 const char *ph_number, unsigned int call_id)
2258 {
2259         DBusMessage *reply;
2260         DBusError err;
2261         const char *path = telephony_info.call_path;
2262         int ret;
2263
2264         FN_START;
2265
2266         BT_TELEPHONY_CHECK_INITIALIZED();
2267         BT_TELEPHONY_CHECK_ENABLED();
2268
2269         if (NULL == ph_number)
2270                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2271
2272         reply = __bluetooth_telephony_dbus_method_send(
2273                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2274                         "IncomingCall", &err, DBUS_TYPE_STRING, &path,
2275                         DBUS_TYPE_STRING, &ph_number, DBUS_TYPE_INT32,
2276                         &call_id, DBUS_TYPE_INVALID);
2277
2278         if (!reply) {
2279                 BT_ERR("Error returned in method call\n");
2280                 if (dbus_error_is_set(&err)) {
2281                         ret = __bt_telephony_get_error(err.message);
2282                         dbus_error_free(&err);
2283                         return ret;
2284                 }
2285                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2286         }
2287
2288         dbus_message_unref(reply);
2289
2290         telephony_info.call_count++;
2291         BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
2292         FN_END;
2293         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2294 }
2295
2296 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(
2297                                                 unsigned short speaker_gain)
2298 {
2299         DBusMessage *reply;
2300         DBusError err;
2301         int ret;
2302
2303         FN_START;
2304
2305         BT_TELEPHONY_CHECK_INITIALIZED();
2306         BT_TELEPHONY_CHECK_ENABLED();
2307
2308         BT_DBG("set speaker_gain= [%d]", speaker_gain);
2309
2310         reply = __bluetooth_telephony_dbus_method_send(
2311                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2312                         "SetSpeakerGain", &err, DBUS_TYPE_UINT16,
2313                         &speaker_gain, DBUS_TYPE_INVALID);
2314
2315         if (!reply) {
2316                 BT_ERR("Error returned in method call\n");
2317                 if (dbus_error_is_set(&err)) {
2318                         ret = __bt_telephony_get_error(err.message);
2319                         dbus_error_free(&err);
2320                         return ret;
2321                 }
2322                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2323         }
2324
2325         dbus_message_unref(reply);
2326         FN_END;
2327
2328         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2329 }
2330
2331 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(
2332                                                 unsigned int *speaker_gain)
2333 {
2334         DBusMessage *reply;
2335         DBusError err;
2336         int ret;
2337         guint16 gain;
2338
2339         FN_START;
2340
2341         BT_TELEPHONY_CHECK_INITIALIZED();
2342         BT_TELEPHONY_CHECK_ENABLED();
2343
2344         reply = __bluetooth_telephony_dbus_method_send(
2345                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2346                         "GetSpeakerGain", &err, DBUS_TYPE_INVALID);
2347
2348         if (!reply) {
2349                 BT_ERR("Error returned in method call\n");
2350                 if (dbus_error_is_set(&err)) {
2351                         ret = __bt_telephony_get_error(err.message);
2352                         dbus_error_free(&err);
2353                         return ret;
2354                 }
2355                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2356         }
2357
2358         if (!dbus_message_get_args(reply, &err,
2359                         DBUS_TYPE_UINT16, &gain,
2360                         DBUS_TYPE_INVALID)) {
2361                 BT_ERR("Error to get features");
2362                 if (dbus_error_is_set(&err)) {
2363                         BT_ERR("error message: %s", err.message);
2364                         dbus_error_free(&err);
2365                 }
2366                 dbus_message_unref(reply);
2367                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2368         }
2369         *speaker_gain = gain;
2370         BT_DBG("Get speaker_gain= [%d]", *speaker_gain);
2371
2372         dbus_message_unref(reply);
2373         FN_END;
2374         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2375 }
2376
2377 static DBusHandlerResult __bt_telephony_adapter_filter(DBusConnection *conn,
2378                                                 DBusMessage *msg, void *data)
2379 {
2380         int ret;
2381         char *object_path = NULL;
2382         const char *member = dbus_message_get_member(msg);
2383         FN_START;
2384
2385         if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL)
2386                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2387
2388         if (member == NULL)
2389                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2390
2391         if (strcasecmp(member, "InterfacesAdded") == 0) {
2392                 if (__bt_telephony_get_object_path(msg, &object_path)) {
2393                         BT_ERR("Fail to get the path");
2394                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2395                 }
2396
2397                 if (strcasecmp(object_path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
2398
2399                         BT_DBG("Adapter added [%s]", object_path);
2400                         BT_DBG("BlueZ is Activated and flag need to be reset");
2401                         BT_DBG("Send enabled to application");
2402
2403                         if (__bt_telephony_get_src_addr(msg)) {
2404                                 BT_ERR("Fail to get the local adapter address");
2405                                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2406                         }
2407
2408                         ret = __bluetooth_telephony_register();
2409                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2410                                 BT_ERR("__bluetooth_telephony_register failed");
2411                 }
2412         }
2413
2414         FN_END;
2415         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2416 }
2417
2418 static int __bt_telephony_get_object_path(DBusMessage *msg, char **path)
2419 {
2420         DBusMessageIter item_iter;
2421         dbus_message_iter_init(msg, &item_iter);
2422         FN_START;
2423
2424         if (dbus_message_iter_get_arg_type(&item_iter)
2425                                         != DBUS_TYPE_OBJECT_PATH) {
2426                 BT_ERR("This is bad format dbus");
2427                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2428         }
2429
2430         dbus_message_iter_get_basic(&item_iter, path);
2431
2432         if (*path == NULL)
2433                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2434
2435         FN_END;
2436         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2437 }
2438
2439
2440 static int __bt_telephony_get_src_addr(DBusMessage *msg)
2441 {
2442         char *object_path;
2443         const char *property = NULL;
2444         char *interface_name;
2445         DBusMessageIter item_iter;
2446         DBusMessageIter value_iter;
2447         DBusMessageIter msg_iter, dict_iter;
2448         DBusMessageIter in_iter, in2_iter;
2449         char *bd_addr;
2450         FN_START;
2451
2452         dbus_message_iter_init(msg, &item_iter);
2453
2454         /* signature of InterfacesAdded signal is oa{sa{sv}} */
2455         if (dbus_message_iter_get_arg_type(&item_iter)
2456                                 != DBUS_TYPE_OBJECT_PATH) {
2457                 BT_ERR("This is bad format dbus");
2458                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2459         }
2460
2461         dbus_message_iter_get_basic(&item_iter, &object_path);
2462         retv_if(object_path == NULL,
2463                                 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2464
2465         if (strcasecmp(object_path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
2466                 /* get address from here */
2467                 retv_if(dbus_message_iter_next(&item_iter) == FALSE,
2468                                 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2469
2470                 /* signature a{sa{sv}} */
2471                 retv_if(dbus_message_iter_get_arg_type(&item_iter) !=
2472                                 DBUS_TYPE_ARRAY,
2473                                 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2474                 dbus_message_iter_recurse(&item_iter, &value_iter);
2475                 while (dbus_message_iter_get_arg_type(&value_iter) ==
2476                                         DBUS_TYPE_DICT_ENTRY) {
2477                         dbus_message_iter_recurse(&value_iter, &msg_iter);
2478                         if (dbus_message_iter_get_arg_type(&msg_iter)
2479                                         != DBUS_TYPE_STRING) {
2480                                 BT_ERR("This is bad format dbus");
2481                                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2482                         }
2483
2484                         dbus_message_iter_get_basic(&msg_iter, &interface_name);
2485                         retv_if(interface_name == NULL,
2486                                 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2487
2488                         BT_DBG("interface name is %s", interface_name);
2489
2490                         if (strcasecmp(interface_name, BLUEZ_ADAPTER_INTERFACE) == 0) {
2491                                 retv_if(!dbus_message_iter_next(&msg_iter),
2492                                         BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2493                                 dbus_message_iter_recurse(&msg_iter, &in_iter);
2494
2495                                 if (dbus_message_iter_get_arg_type(&in_iter)
2496                                                 != DBUS_TYPE_DICT_ENTRY) {
2497                                         BT_ERR("This is bad format dbus");
2498                                         return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2499                                 }
2500
2501                                 dbus_message_iter_recurse(&in_iter, &dict_iter);
2502                                 dbus_message_iter_get_basic(
2503                                                         &dict_iter, &property);
2504
2505                                 retv_if(property == NULL,
2506                                 BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2507                                 retv_if(!dbus_message_iter_next(&dict_iter),
2508                                         BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
2509
2510                                 if (strcasecmp(property, "Address") == 0) {
2511                                         dbus_message_iter_recurse
2512                                                 (&dict_iter, &in2_iter);
2513                                         dbus_message_iter_get_basic
2514                                                 (&in2_iter, &bd_addr);
2515                                         src_addr = g_strdup(bd_addr);
2516                                         break;
2517                                 }
2518                         }
2519                         dbus_message_iter_next(&value_iter);
2520                 }
2521         }
2522         BT_DBG("default adapter address is src_addr = %s", src_addr);
2523         FN_END;
2524         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2525 }