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