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