8bc75f32729c7c83f74c73c14a7e0e5c0fd947e6
[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 static char *src_addr = NULL;
53 static 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, BLUEZ_HEADSET_INTERFACE) == 0) {
494                 if (strcasecmp(signal_name, "PropertyChanged") == 0) {
495                         GVariant *values;
496                         gchar *property;
497
498                         g_variant_get(parameters, "(&sv)", &property, &values);
499                         BT_DBG("Property: %s", property);
500
501                         if (strcasecmp(property, "State") == 0) {
502                                 gchar *state;
503                                 state = (gchar *)g_variant_get_string(values, NULL);
504
505                                 if (NULL == state) {
506                                         BT_ERR("State is null");
507                                         return;
508                                 }
509                                 BT_DBG("state: %s", state);
510                                 if (g_strcmp0(state, "connected") == 0) {
511                                         telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
512                                 } else if (g_strcmp0(state, "playing") == 0) {
513                                         telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
514                                 } else if (g_strcmp0(state, "disconnected") == 0) {
515                                         /* Headset state: playing -> disconnected */
516                                         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) {
517                                                 __bt_telephony_event_cb(
518                                                                 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
519                                                                 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
520                                         }
521
522                                         telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
523                                 }
524                         } else if (strcasecmp(property, "Connected") == 0) {
525                                 gboolean connected = FALSE;
526                                 char *dev_addr = NULL;
527                                 connected = g_variant_get_boolean(values);
528                                 BT_INFO("connected %d", connected);
529                                 if (connected) {
530                                         /*Get device address*/
531                                         if (object_path != NULL)
532                                                 dev_addr = strstr(object_path, "dev_");
533
534                                         if (dev_addr != NULL) {
535                                                 dev_addr += 4;
536                                                 g_strlcpy(telephony_info.address,
537                                                                 dev_addr,
538                                                                 sizeof(telephony_info.address));
539                                                 g_strdelimit(telephony_info.address, "_", ':');
540                                                 BT_DBG("address is %s",
541                                                                 telephony_info.address);
542
543                                                 telephony_info.headset_state =
544                                                                 BLUETOOTH_STATE_CONNECTED;
545
546                                                 if (telephony_dbus_info.proxy != NULL) {
547                                                         g_object_unref(telephony_dbus_info.proxy);
548                                                         telephony_dbus_info.proxy = NULL;
549                                                 }
550
551                                                 telephony_dbus_info.proxy =
552                                                                 __bluetooth_telephony_get_connected_device_proxy();
553
554                                                 BT_INFO("Headset Connected");
555
556                                                 __bt_telephony_event_cb(
557                                                                 BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED,
558                                                                 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
559                                         }
560                                 } else { /*Device disconnected*/
561                                         memset(telephony_info.address, 0x00,
562                                                         sizeof(telephony_info.address));
563                                         telephony_info.headset_state =
564                                                         BLUETOOTH_STATE_DISCONNETED;
565
566                                         if (telephony_dbus_info.proxy != NULL) {
567                                                 g_object_unref(telephony_dbus_info.proxy);
568                                                 telephony_dbus_info.proxy = NULL;
569                                         }
570
571                                         BT_INFO("Headset Disconnected");
572
573                                         __bt_telephony_event_cb(
574                                                         BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED,
575                                                         BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
576                                 }
577                         } else if (strcasecmp(property, "SpeakerGain") == 0) {
578                                 unsigned int spkr_gain;
579                                 guint16 gain = g_variant_get_uint16(values);
580
581                                 spkr_gain = (unsigned int)gain;
582                                 BT_DBG("spk_gain[%d]", spkr_gain);
583
584                                 __bt_telephony_event_cb(
585                                                 BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN,
586                                                 BLUETOOTH_TELEPHONY_ERROR_NONE,
587                                                 (void *)&spkr_gain);
588                         } else if (strcasecmp(property, "MicrophoneGain") == 0) {
589                                 unsigned int mic_gain;
590                                 guint16 gain = g_variant_get_uint16(values);
591
592                                 mic_gain = (unsigned int)gain;
593                                 BT_DBG("mic_gain[%d]", mic_gain);
594
595                                 __bt_telephony_event_cb(
596                                                 BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN,
597                                                 BLUETOOTH_TELEPHONY_ERROR_NONE,
598                                                 (void *)&mic_gain);
599                         } else if (strcasecmp(property, "Playing") == 0) {
600                                 gboolean audio_sink_playing;
601
602                                 audio_sink_playing = g_variant_get_boolean(values);
603                                 if (audio_sink_playing) {
604                                         telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
605                                         __bt_telephony_event_cb(
606                                                         BLUETOOTH_EVENT_TELEPHONY_AUDIO_CONNECTED,
607                                                         BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
608                                 } else {
609                                         telephony_info.headset_state =
610                                                         BLUETOOTH_STATE_CONNECTED;
611                                         __bt_telephony_event_cb(
612                                                         BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
613                                                         BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
614                                 }
615                         }
616
617                         g_variant_unref(values);
618                 } else if (strcasecmp(signal_name, HFP_NREC_STATUS_CHANGE) == 0)
619                         __bluetooth_handle_nrec_status_change(parameters);
620                 else if (strcasecmp(signal_name, HFP_ANSWER_CALL) == 0)
621                         __bluetooth_telephony_answer_call(parameters);
622                 else if (strcasecmp(signal_name, HFP_REJECT_CALL) == 0)
623                         __bluetooth_telephony_reject_call(parameters);
624                 else if (strcasecmp(signal_name, HFP_RELEASE_CALL) == 0)
625                         __bluetooth_telephony_release_call(parameters);
626                 else if (strcasecmp(signal_name, HFP_THREEWAY_CALL) == 0)
627                         __bluetooth_telephony_threeway_call(parameters);
628         }
629         BT_DBG("-");
630 }
631
632 static GDBusNodeInfo *__bt_telephony_create_method_node_info
633                                         (const gchar *introspection_data)
634 {
635         GError *err = NULL;
636         GDBusNodeInfo *node_info = NULL;
637
638         if (introspection_data == NULL)
639                 return NULL;
640
641         node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
642
643         if (err) {
644                 BT_ERR("Unable to create node: %s", err->message);
645                 g_clear_error(&err);
646         }
647         return node_info;
648 }
649
650
651 int __bluetooth_telephony_register_object(int reg, GDBusNodeInfo *node_info)
652 {
653         static guint bt_tel_id = 0;
654         GError *error =  NULL;
655         gchar *path;
656
657         if (reg == TRUE) {
658                 if (node_info == NULL)
659                         return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
660
661                 path = g_strdup(telephony_info.call_path);
662                 BT_DBG("path is [%s]", path);
663
664                 bt_tel_id = g_dbus_connection_register_object(telephony_dbus_info.conn,
665                                 path, node_info->interfaces[0],
666                                 &method_table,
667                                 NULL, NULL, &error);
668
669                 g_free(path);
670                 if (bt_tel_id == 0) {
671                         BT_ERR("Failed to register: %s", error->message);
672                         g_error_free(error);
673                         return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
674                 }
675         } else {
676                 if (bt_tel_id > 0) {
677                         g_dbus_connection_unregister_object(telephony_dbus_info.conn,
678                                         bt_tel_id);
679                         bt_tel_id = 0;
680                 }
681         }
682
683         return BLUETOOTH_TELEPHONY_ERROR_NONE;
684 }
685
686 static int __bluetooth_telephony_proxy_init(void)
687 {
688         FN_START;
689         GDBusNodeInfo *node_info;
690         gchar *name;
691
692         name = g_strdup_printf("org.tizen.csd.Call.Instance.p%d", getpid());
693         BT_DBG("well-known name: %s", name);
694
695         owner_id = g_bus_own_name_on_connection(telephony_dbus_info.conn,
696                                 name, G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL);
697         BT_DBG("owner_id: %d", owner_id);
698         g_free(name);
699
700         node_info = __bt_telephony_create_method_node_info(
701                                 bt_telephony_introspection_xml);
702         if (node_info == NULL) {
703                 BT_ERR("node_info NULL");
704                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
705         }
706         if (__bluetooth_telephony_register_object(TRUE, node_info) !=
707                         BLUETOOTH_TELEPHONY_ERROR_NONE) {
708                 BT_ERR("Registation of Method Failed");
709                 g_dbus_node_info_unref(node_info);
710                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
711         }
712
713         FN_END;
714         g_dbus_node_info_unref(node_info);
715         return BLUETOOTH_TELEPHONY_ERROR_NONE;
716 }
717
718 static void __bluetooth_telephony_proxy_deinit(void)
719 {
720         FN_START;
721
722         __bluetooth_telephony_register_object(FALSE, NULL);
723         g_bus_unown_name(owner_id);
724
725         FN_END;
726 }
727
728 static int __bluetooth_telephony_register(void)
729 {
730         GVariant *reply;
731         GVariant *param;
732         GError *err = NULL;
733         char *path = g_strdup(telephony_info.call_path);
734         int ret;
735
736         FN_START;
737
738         param = g_variant_new("(ss)", path, src_addr);
739         BT_DBG("Path[%s] Src_Address[%s]", path, src_addr);
740
741         reply =  __bluetooth_telephony_dbus_method_send(
742                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
743                         "RegisterApplication", &err, param);
744
745         g_free(path);
746
747         if (!reply) {
748                 BT_ERR("Error returned in method call");
749                 if (err) {
750                         g_dbus_error_strip_remote_error(err);
751                         ret = __bt_telephony_get_error(err->message);
752                         BT_ERR("Error here %d\n", ret);
753                         g_error_free(err);
754                         return ret;
755                 }
756                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
757         }
758
759         g_variant_unref(reply);
760         BT_DBG("__bluetooth_telephony_register completed");
761         FN_END;
762         return BLUETOOTH_TELEPHONY_ERROR_NONE;
763 }
764
765 static  int __bluetooth_telephony_unregister(void)
766 {
767         GVariant *reply;
768         GVariant *param;
769         GError *err = NULL;
770         char *path = g_strdup(telephony_info.call_path);
771         int ret;
772
773         FN_START;
774
775         param = g_variant_new("(s)", path);
776         reply = __bluetooth_telephony_dbus_method_send(
777                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
778                         "UnregisterApplication", &err, param);
779
780         g_free(path);
781
782         if (!reply) {
783                 BT_ERR("Error returned in method call");
784                 if (err) {
785                         g_dbus_error_strip_remote_error(err);
786                         ret = __bt_telephony_get_error(err->message);
787                         g_error_free(err);
788                         return ret;
789                 }
790                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
791         }
792
793         g_variant_unref(reply);
794         BT_DBG("__bluetooth_telephony_unregister completed");
795         FN_END;
796         return BLUETOOTH_TELEPHONY_ERROR_NONE;
797 }
798
799 static void __bluetooth_telephony_init_headset_state(void)
800 {
801         GVariant *reply;
802         GError *err = NULL;
803         gboolean status = FALSE;
804
805         FN_START;
806
807         if (telephony_dbus_info.conn == NULL) {
808                 BT_ERR("Bluetooth telephony not initilized");
809                 return;
810         }
811
812         reply = __bluetooth_telephony_dbus_method_send(
813                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
814                         "IsConnected", &err, NULL);
815         if (!reply) {
816                 BT_ERR("Error returned in method call\n");
817                 if (err) {
818                         BT_ERR("Error message = %s", err->message);
819                         g_error_free(err);
820                 }
821                 return;
822         }
823
824         g_variant_get(reply, "(b)", &status);
825         g_variant_unref(reply);
826
827         BT_INFO("Headset Connected Status = [%d]", status);
828         if (status)
829                 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
830         else
831                 return;
832
833         if (bluetooth_telephony_is_sco_connected())
834                 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
835
836         FN_END;
837 }
838
839 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
840 {
841         gboolean flag = FALSE;
842         FN_START;
843
844         switch ((device_class & 0x1f00) >> 8) {
845         case 0x04:
846                 switch ((device_class & 0xfc) >> 2) {
847                 case 0x01:
848                 case 0x02:
849                         flag = TRUE;
850                         break;
851                 case 0x06:
852                         flag = TRUE;
853                         break;
854                 case 0x0b:
855                 case 0x0c:
856                 case 0x0d:
857                         break;
858                 default:
859                         flag = TRUE;
860                         break;
861                 }
862                 break;
863
864         /* Tizen Wearable device */
865         case 0x07:
866                 switch ((device_class & 0xfc) >> 2) {
867                 case 0x01: /* Wrist Watch */
868                         flag = TRUE;
869                         break;
870                 default:
871                         break;
872                 }
873                 break;
874         }
875         BT_DBG("[%d]", flag);
876         FN_END;
877         return flag;
878 }
879
880 static gboolean __bluetooth_telephony_is_headset_by_uuid(gchar **uuids)
881 {
882         int i;
883         char **parts;
884         unsigned int service = 0;
885
886         FN_START;
887
888         retv_if(uuids == NULL, FALSE);
889
890         for (i = 0; uuids[i] != NULL; i++) {
891                 parts = g_strsplit(uuids[i], "-", -1);
892
893                 if (parts == NULL || parts[0] == NULL) {
894                         g_strfreev(parts);
895                         continue;
896                 }
897
898                 service = g_ascii_strtoull(parts[0], NULL, 16);
899                 g_strfreev(parts);
900
901                 if (service == BLUETOOTH_HS_PROFILE_UUID ||
902                                 service == BLUETOOTH_HF_PROFILE_UUID)
903                         return TRUE;
904         }
905
906         FN_END;
907         return FALSE;
908 }
909
910
911 static int __bluetooth_telephony_get_connected_device(void)
912 {
913         GDBusConnection *conn;
914         GDBusProxy *headset_agent_proxy = NULL;
915         GDBusProxy *manager_proxy = NULL;
916         GDBusProxy *proxy = NULL;
917         GVariant *reply = NULL;
918         GVariant *getall = NULL;
919         GVariant *isPlayingReply = NULL;
920         GVariant *isConnectedReply = NULL;
921         GVariant *param = NULL;
922         GVariant *var_path = NULL;
923         GVariant *path_values = NULL;
924         GVariant *value = NULL;
925         GError *error = NULL;
926         GVariantIter iter;
927         GVariantIter iter_path;
928         GVariantIter property_iter;
929         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
930
931         FN_START;
932         conn = _bt_get_system_private_conn();
933         retv_if(conn == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
934
935         manager_proxy = g_dbus_proxy_new_sync(
936                         conn, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
937                         BLUEZ_SERVICE_NAME, "/",
938                         BLUEZ_MANAGER_INTERFACE, NULL, &error);
939         if (manager_proxy == NULL) {
940                 BT_ERR("Unable to allocate new proxy \n");
941                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
942                 if (error) {
943                         g_dbus_error_strip_remote_error(error);
944                         ret = __bt_telephony_get_error(error->message);
945                         BT_ERR("Error here %d\n", ret);
946                         g_error_free(error);
947                 }
948                 goto done;
949         }
950
951         /* Synchronous call */
952         reply = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects", NULL,
953                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
954         g_object_unref(manager_proxy);
955
956         if (!reply) {
957                 BT_ERR("Can't get managed objects");
958                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
959                 if (error) {
960                         g_dbus_error_strip_remote_error(error);
961                         ret = __bt_telephony_get_error(error->message);
962                         BT_ERR("Error here %d\n", ret);
963                         g_error_free(error);
964                 }
965                 goto done;
966         }
967
968         /* signature of GetManagedObjects:      a{oa{sa{sv}}} */
969         g_variant_iter_init(&iter, reply);
970
971         while ((param = g_variant_iter_next_value(&iter))) {
972                 g_variant_iter_init(&iter_path, param);
973
974                 while ((var_path = g_variant_iter_next_value(&iter_path))) {
975                         gsize len;
976                         uint32_t device_class = 0;
977                         gboolean playing = FALSE;
978                         gboolean connected = FALSE;
979                         char *object_path = NULL;
980                         gchar *address = NULL;
981                         const gchar *key;
982                         gchar **uuids = NULL;
983                         GVariant *getall_param = NULL;
984
985                         g_variant_get(var_path, "{&o*}", &object_path,
986                                         &path_values);
987                         g_variant_unref(path_values); /* path_values unused*/
988
989                         proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
990                                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
991                                         BLUEZ_SERVICE_NAME, object_path,
992                                         BLUEZ_PROPERTIES_INTERFACE, NULL, &error);
993                         if (proxy == NULL) {
994                                 BT_ERR("Unable to allocate new proxy \n");
995                                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
996                                 if (error) {
997                                         g_dbus_error_strip_remote_error(error);
998                                         ret = __bt_telephony_get_error(error->message);
999                                         BT_ERR("Error here %d\n", ret);
1000                                         g_error_free(error);
1001                                 }
1002                                 goto done;
1003                         }
1004
1005
1006                         getall_param = g_variant_new("s", BLUEZ_DEVICE_INTERFACE);
1007                         getall = g_dbus_proxy_call_sync(proxy,
1008                                         "GetAll", getall_param,
1009                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1010                         g_object_unref(proxy);
1011
1012                         if (!getall) {
1013                                 BT_ERR("Can't get managed objects");
1014                                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1015                                 if (error) {
1016                                         g_dbus_error_strip_remote_error(error);
1017                                         ret = __bt_telephony_get_error(error->message);
1018                                         BT_ERR("Error here %d\n", ret);
1019                                         g_error_free(error);
1020                                 }
1021                                 goto done;
1022                         }
1023
1024                         g_variant_iter_init(&property_iter, getall);
1025
1026                         while (g_variant_iter_loop(&property_iter, "{&sv}", &key, &value)) {
1027                                 if (!g_strcmp0(key, "Class")) {
1028                                         device_class = g_variant_get_uint32(value);
1029                                         BT_DBG("Device Class: %d", device_class);
1030                                 } else if (!g_strcmp0(key, "UUID")) {
1031                                         int i = 0;
1032                                         uuids = (gchar **)g_variant_get_strv(value, &len);
1033                                         BT_DBG_UUID(uuids, len, i);
1034                                 } else if (!g_strcmp0(key, "Address")) {
1035                                         address = (gchar *)g_variant_get_string(
1036                                                                         value,
1037                                                                         NULL);
1038                                         BT_DBG("Device Class: %s", address);
1039                                 }
1040                                 g_variant_unref(value);
1041                         }
1042                         g_variant_unref(getall);
1043
1044                         if (device_class == 0) {
1045                                 BT_DBG("COD is NULL (maybe paired by nfc)...  Checking UUIDs");
1046                                 if (!__bluetooth_telephony_is_headset_by_uuid(uuids)) {
1047                                         BT_DBG("UUID checking completed. None HF device");
1048                                         continue;
1049                                 }
1050                                 BT_DBG("UUID checking completed. HF device");
1051                         } else {
1052                                 if (!__bluetooth_telephony_is_headset(device_class))
1053                                         continue;
1054                         }
1055
1056                         /* this is headset; Check for Connection */
1057                         headset_agent_proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
1058                                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1059                                         HFP_AGENT_SERVICE, object_path,
1060                                         HFP_AGENT_INTERFACE, NULL, &error);
1061                         if (headset_agent_proxy == NULL) {
1062                                 BT_ERR("Unable to allocate new headset_agent_proxy");
1063                                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1064                                 if (error) {
1065                                         g_dbus_error_strip_remote_error(error);
1066                                         ret = __bt_telephony_get_error(error->message);
1067                                         BT_ERR("Error here %d\n", ret);
1068                                         g_error_free(error);
1069                                 }
1070                                 goto done;
1071                         }
1072
1073                         isConnectedReply = g_dbus_proxy_call_sync(headset_agent_proxy,
1074                                         "IsConnected", NULL,
1075                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1076
1077
1078                         if (!isConnectedReply) {
1079                                 BT_ERR("Can't get managed objects");
1080                                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1081                                 if (error) {
1082                                         g_dbus_error_strip_remote_error(error);
1083                                         ret = __bt_telephony_get_error(error->message);
1084                                         BT_ERR("Error here %d\n", ret);
1085                                         g_error_free(error);
1086                                 }
1087                                 goto done;
1088                         } else {
1089                                 connected = g_variant_get_boolean(isConnectedReply);
1090                                 g_variant_unref(isConnectedReply);
1091
1092                                 if (connected) {
1093                                         g_strlcpy(telephony_info.address,
1094                                                         address,
1095                                                         sizeof(telephony_info.address));
1096
1097                                         isPlayingReply = g_dbus_proxy_call_sync(headset_agent_proxy,
1098                                                         "IsPlaying", NULL,
1099                                                         G_DBUS_CALL_FLAGS_NONE,
1100                                                         -1, NULL, &error);
1101                                         if (!isPlayingReply) {
1102                                                 BT_ERR("Can't get managed objects");
1103                                                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1104                                                 if (error) {
1105                                                         g_dbus_error_strip_remote_error(error);
1106                                                         ret = __bt_telephony_get_error(error->message);
1107                                                         BT_ERR("Error here %d\n", ret);
1108                                                         g_error_free(error);
1109                                                 }
1110                                         } else {
1111                                                 playing = g_variant_get_boolean(isPlayingReply);
1112                                                 g_variant_unref(isPlayingReply);
1113
1114                                                 if (playing)
1115                                                         telephony_info.headset_state =
1116                                                                 BLUETOOTH_STATE_PLAYING;
1117                                                 else
1118                                                         telephony_info.headset_state =
1119                                                                 BLUETOOTH_STATE_CONNECTED;
1120                                         }
1121
1122                                         goto done;
1123                                 }
1124                         }
1125
1126                         g_object_unref(headset_agent_proxy);
1127                         g_variant_unref(var_path);
1128                 }
1129                 g_variant_unref(param);
1130         }
1131
1132 done:
1133         if (headset_agent_proxy)
1134                 g_object_unref(headset_agent_proxy);
1135         if (reply)
1136                 g_variant_unref(reply);
1137         if (var_path)
1138                 g_variant_unref(var_path);
1139         if (param)
1140                 g_variant_unref(param);
1141         FN_END;
1142         return ret;
1143 }
1144
1145 static GDBusProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1146 {
1147         GDBusProxy *proxy = NULL;
1148         GError *error = NULL;
1149         int ret;
1150         FN_START;
1151
1152         if (strlen(telephony_info.address) == 0)
1153                 __bluetooth_telephony_get_connected_device();
1154
1155         if (strlen(telephony_info.address) == 0)
1156                 return NULL;
1157
1158         proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
1159                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1160                         HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1161                         HFP_AGENT_INTERFACE, NULL, &error);
1162         if (proxy == NULL) {
1163                 BT_ERR("Unable to allocate new proxy");
1164                 if (error) {
1165                         g_dbus_error_strip_remote_error(error);
1166                         ret = __bt_telephony_get_error(error->message);
1167                         BT_ERR("Error here %d\n", ret);
1168                         g_error_free(error);
1169                 }
1170                 return NULL;
1171         }
1172
1173         FN_END;
1174         return proxy;
1175 }
1176
1177 int __bt_telephony_subscribe_adapter_signal(GDBusConnection *conn,
1178                 int subscribe)
1179 {
1180         if (conn == NULL)
1181                 return -1;
1182
1183         static guint subscribe_adapter_id = 0;
1184
1185         if (subscribe == TRUE) {
1186                 if (subscribe_adapter_id == 0) {
1187                         subscribe_adapter_id = g_dbus_connection_signal_subscribe(conn,
1188                                         NULL, "org.freedesktop.DBus.ObjectManager",
1189                                         "InterfacesAdded", NULL, NULL, 0,
1190                                         __bt_telephony_adapter_filter,
1191                                         NULL, NULL);
1192                 }
1193                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1194         } else {
1195                 if (subscribe_adapter_id > 0) {
1196                         g_dbus_connection_signal_unsubscribe(conn,
1197                                         subscribe_adapter_id);
1198                         subscribe_adapter_id = 0;
1199                 }
1200                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1201         }
1202 }
1203
1204 int __bt_telephony_event_subscribe_signal(GDBusConnection *conn,
1205                 int subscribe)
1206 {
1207         if (conn == NULL)
1208                 return -1;
1209
1210         static guint event_id = 0;
1211
1212         if (subscribe == TRUE) {
1213                 if (event_id == 0) {
1214                         event_id = g_dbus_connection_signal_subscribe(conn,
1215                                         NULL, BLUEZ_HEADSET_INTERFACE,
1216                                         NULL, NULL, NULL, 0,
1217                                         __bluetooth_telephony_event_filter,
1218                                         NULL, NULL);
1219                 }
1220                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1221         } else {
1222                 if (event_id > 0) {
1223                         g_dbus_connection_signal_unsubscribe(conn,
1224                                         event_id);
1225                         event_id = 0;
1226                 }
1227                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1228         }
1229 }
1230
1231 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1232                                                         void  *user_data)
1233 {
1234         bluetooth_device_address_t loc_address = { {0} };
1235         char src_address[BT_ADDRESS_STRING_SIZE] = { 0 };
1236         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1237         GError *error = NULL;
1238
1239         FN_START;
1240
1241         if (is_initialized == TRUE) {
1242                 BT_ERR("Bluetooth telephony already initilized");
1243                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1244         }
1245
1246         is_initialized = TRUE;
1247
1248         /* As a result of discussion with system team, private connection is not
1249          * suitable in here. It is better to use shared connection. */
1250         //telephony_dbus_info.conn = _bt_gdbus_init_system_gconn();
1251         telephony_dbus_info.conn = _bt_get_system_shared_conn();
1252         if (!telephony_dbus_info.conn) {
1253                 is_initialized = FALSE;
1254                 BT_ERR("Could not get DBus Connection");
1255                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1256         }
1257
1258         /* Call Path */
1259         snprintf(telephony_info.call_path, sizeof(telephony_info.call_path),
1260                                         CSD_CALL_APP_PATH, getpid());
1261         BT_INFO("Call Path = %s", telephony_info.call_path);
1262         memset(telephony_info.address, 0x00, sizeof(telephony_info.address));
1263
1264         if (__bluetooth_telephony_proxy_init()) {
1265                 BT_ERR("__bluetooth_telephony_proxy_init failed\n");
1266                 telephony_dbus_info.conn = NULL;
1267                 is_initialized = FALSE;
1268                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1269         }
1270
1271         telephony_dbus_info.manager_proxy = g_dbus_proxy_new_sync(
1272                         telephony_dbus_info.conn,
1273                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1274                         BLUEZ_SERVICE_NAME, "/",
1275                         BLUEZ_MANAGER_INTERFACE, NULL, &error);
1276         if (telephony_dbus_info.manager_proxy == NULL) {
1277                 BT_ERR("Could not create a manager proxy");
1278                 __bluetooth_telephony_proxy_deinit();
1279                 telephony_dbus_info.conn = NULL;
1280                 is_initialized = FALSE;
1281                 if (error) {
1282                         g_dbus_error_strip_remote_error(error);
1283                         ret = __bt_telephony_get_error(error->message);
1284                         BT_ERR("Error here %d\n", ret);
1285                         g_error_free(error);
1286                         return ret;
1287                 }
1288                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1289         }
1290
1291         telephony_dbus_info.dbus_proxy = g_dbus_proxy_new_sync(
1292                         telephony_dbus_info.conn,
1293                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1294                         BT_EVENT_FREEDESKTOP, BT_FREEDESKTOP_PATH,
1295                         BT_EVENT_FREEDESKTOP, NULL, &error);
1296         if (NULL == telephony_dbus_info.dbus_proxy) {
1297                 __bluetooth_telephony_proxy_deinit();
1298                 telephony_dbus_info.conn = NULL;
1299                 g_object_unref(telephony_dbus_info.manager_proxy);
1300                 telephony_dbus_info.manager_proxy = NULL;
1301                 is_initialized = FALSE;
1302                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1303         }
1304
1305         if (__bt_telephony_subscribe_adapter_signal(telephony_dbus_info.conn, TRUE) != 0) {
1306                 BT_ERR("Fail to Subscribe Adapter Signal");
1307                 goto fail;
1308         }
1309
1310         /*Callback and user applicaton data*/
1311         telephony_info.cb = cb;
1312         telephony_info.user_data = user_data;
1313         telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1314
1315         if (__bt_telephony_event_subscribe_signal(telephony_dbus_info.conn, TRUE) != 0) {
1316                 BT_ERR("Fail to Subscribe telephony event Signal");
1317                 goto fail;
1318         }
1319
1320         if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED)
1321                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1322
1323         /*Bluetooth is active, therefore set the flag */
1324         is_active = TRUE;
1325         if (!src_addr) {
1326                 ret = bluetooth_get_local_address(&loc_address);
1327                 if (ret != BLUETOOTH_ERROR_NONE) {
1328                         BT_ERR("Fail to get local address\n");
1329                         ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1330                         goto fail;
1331                 }
1332                 _bt_convert_addr_type_to_string(src_address, loc_address.addr);
1333                 src_addr = g_strdup(src_address);
1334         }
1335         ret = __bluetooth_telephony_register();
1336         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1337                 BT_ERR("__bluetooth_telephony_register failed\n");
1338                 goto fail;
1339         }
1340
1341         if (TIZEN_PROFILE_WEARABLE || TIZEN_PROFILE_IVI)
1342                 __bluetooth_telephony_init_headset_state();
1343
1344         FN_END;
1345         return ret;
1346 fail:
1347         bluetooth_telephony_deinit();
1348         return ret;
1349 }
1350
1351 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1352 {
1353         FN_START;
1354         BT_TELEPHONY_CHECK_INITIALIZED();
1355
1356         is_initialized = FALSE;
1357
1358         if (__bt_telephony_event_subscribe_signal(telephony_dbus_info.conn, FALSE) != 0)
1359                 BT_ERR("Fail to UnSubscribe telephony event Signal");
1360
1361         if (bluetooth_check_adapter() != BLUETOOTH_ADAPTER_DISABLED ||
1362                 bluetooth_check_adapter_le() != BLUETOOTH_ADAPTER_LE_DISABLED)
1363                 __bluetooth_telephony_unregister();
1364
1365         __bluetooth_telephony_proxy_deinit();
1366
1367         telephony_info.cb = NULL;
1368         telephony_info.user_data = NULL;
1369         telephony_info.call_count = 0;
1370         telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1371
1372         /* Remove BT enabled signal */
1373         if (__bt_telephony_subscribe_adapter_signal(telephony_dbus_info.conn, FALSE) != 0)
1374                 BT_ERR("Fail to UnSubscribe Adapter event Signal");
1375
1376         g_free(src_addr);
1377         src_addr = NULL;
1378
1379         if (telephony_dbus_info.manager_proxy != NULL) {
1380                 g_object_unref(telephony_dbus_info.manager_proxy);
1381                 telephony_dbus_info.manager_proxy = NULL;
1382         }
1383
1384         if (telephony_dbus_info.conn != NULL)
1385                 telephony_dbus_info.conn = NULL;
1386
1387         if (telephony_dbus_info.dbus_proxy != NULL) {
1388                 g_object_unref(telephony_dbus_info.dbus_proxy);
1389                 telephony_dbus_info.dbus_proxy = NULL;
1390         }
1391
1392         FN_END;
1393         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1394 }
1395
1396 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1397 {
1398         GVariant *reply;
1399         GError *err = NULL;
1400         gboolean status = FALSE;
1401
1402         FN_START;
1403
1404         retv_if(is_initialized == FALSE, FALSE);
1405         retv_if(bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED, FALSE);
1406
1407         reply = __bluetooth_telephony_dbus_method_send(
1408                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1409                         "IsPlaying", &err, NULL);
1410
1411         if (!reply) {
1412                 BT_ERR("Error returned in method call\n");
1413                 if (err) {
1414                         BT_ERR("Error message = %s", err->message);
1415                         g_error_free(err);
1416                 }
1417                 return FALSE;
1418         }
1419         g_variant_get(reply, "(b)", &status);
1420         g_variant_unref(reply);
1421
1422         if (TIZEN_PROFILE_WEARABLE || TIZEN_PROFILE_IVI)
1423                 if (status == TRUE && telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1424                         telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
1425
1426         BT_INFO("SCO Connected Status = [%d]", status);
1427         return status;
1428 }
1429
1430 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1431 {
1432         GVariant *reply;
1433         GError *err = NULL;
1434         GVariantIter iter;
1435         GVariant *param_inner;
1436
1437         FN_START;
1438
1439         BT_TELEPHONY_CHECK_INITIALIZED();
1440         BT_TELEPHONY_CHECK_ENABLED();
1441
1442         if (status == NULL)
1443                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1444
1445         if (telephony_info.headset_state == BLUETOOTH_STATE_DISCONNETED)
1446                 return BLUETOOTH_TELEPHONY_ERROR_AUDIO_NOT_CONNECTED;
1447
1448         reply = __bluetooth_telephony_dbus_method_send(
1449                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1450                         "GetProperties", &err, NULL);
1451
1452         if (!reply) {
1453                 BT_ERR("Error returned in method call\n");
1454                 if (err) {
1455                         BT_DBG("Error message = %s", err->message);
1456                         g_error_free(err);
1457                 }
1458                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1459         }
1460
1461         g_variant_iter_init(&iter, reply);
1462         while ((param_inner = g_variant_iter_next_value(&iter))) {
1463                 GVariant *value;
1464
1465                 value = g_variant_lookup_value(param_inner,
1466                                         "nrec", G_VARIANT_TYPE_BOOLEAN);
1467                 if (value) {
1468                         BT_DBG("Property NREC Found");
1469                         *status = g_variant_get_boolean(value);
1470                         BT_DBG("NREC status = [%d]", *status);
1471                         g_variant_unref(value);
1472                         g_variant_unref(param_inner);
1473                         break;
1474                 }
1475                 g_variant_unref(param_inner);
1476         }
1477         BT_DBG("NREC status = [%d]", *status);
1478         g_variant_unref(reply);
1479
1480         FN_END;
1481         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1482 }
1483
1484 BT_EXPORT_API int bluetooth_telephony_is_wbs_mode(gboolean *status)
1485 {
1486         GVariant *reply;
1487         GError *err = NULL;
1488         unsigned int codec;
1489         GVariantIter iter;
1490         GVariant *param_inner;
1491
1492         FN_START;
1493
1494         BT_TELEPHONY_CHECK_INITIALIZED();
1495         BT_TELEPHONY_CHECK_ENABLED();
1496
1497         if (status == NULL)
1498                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1499
1500         *status = FALSE;
1501
1502         reply = __bluetooth_telephony_dbus_method_send(
1503                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1504                         "GetProperties", &err, NULL);
1505
1506         if (!reply) {
1507                 BT_ERR("Error returned in method call");
1508                 if (err) {
1509                         BT_ERR("Error message = %s", err->message);
1510                         g_error_free(err);
1511                 }
1512                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1513         }
1514
1515         g_variant_iter_init(&iter, reply);
1516         while ((param_inner = g_variant_iter_next_value(&iter))) {
1517                 GVariant *value;
1518
1519                 value = g_variant_lookup_value(param_inner,
1520                                         "codec", G_VARIANT_TYPE_UINT32);
1521                 if (value) {
1522                         BT_DBG("Property CODEC Found");
1523                         codec = g_variant_get_uint32(value);
1524                         g_variant_unref(value);
1525                         BT_DBG("Codec = [%d]", codec);
1526
1527                         *status = codec == BT_MSBC_CODEC_ID ? TRUE : FALSE;
1528                         BT_DBG("NREC status = [%d]", *status);
1529                         g_variant_unref(value);
1530                         g_variant_unref(param_inner);
1531                         break;
1532                 }
1533                 g_variant_unref(param_inner);
1534         }
1535
1536         g_variant_unref(reply);
1537         BT_DBG("MSBC status = [%d]", *status);
1538
1539         FN_END;
1540         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1541 }
1542
1543 BT_EXPORT_API int bluetooth_telephony_send_vendor_cmd(const char *cmd)
1544 {
1545         GError *error = NULL;
1546         GVariant *reply, *parameters;
1547         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1548
1549         FN_START;
1550
1551         BT_TELEPHONY_CHECK_INITIALIZED();
1552         BT_TELEPHONY_CHECK_ENABLED();
1553
1554         BT_DBG("Send Vendor %s", cmd);
1555
1556         if (telephony_dbus_info.proxy == NULL)
1557                 telephony_dbus_info.proxy =
1558                         __bluetooth_telephony_get_connected_device_proxy();
1559
1560         if (telephony_dbus_info.proxy == NULL)
1561                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1562
1563         parameters = g_variant_new("s", cmd);
1564         reply = g_dbus_proxy_call_sync(telephony_dbus_info.proxy,
1565                         "SendVendorAtCmd", parameters,
1566                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1567
1568         g_variant_unref(reply);
1569
1570         if (error) {
1571                 g_dbus_error_strip_remote_error(error);
1572                 ret = __bt_telephony_get_error(error->message);
1573                 BT_ERR("Error here %d\n", ret);
1574                 g_error_free(error);
1575         }
1576
1577         FN_END;
1578         return ret;
1579 }
1580
1581 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1582 {
1583         GVariant *reply;
1584         GVariant *param;
1585         GError *err = NULL;
1586         int ret;
1587         gboolean state = TRUE;
1588
1589         FN_START;
1590
1591         BT_TELEPHONY_CHECK_INITIALIZED();
1592         BT_TELEPHONY_CHECK_ENABLED();
1593
1594         param = g_variant_new("(b)", &state);
1595         reply = __bluetooth_telephony_dbus_method_send(
1596                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1597                         "SetVoiceDial", &err, param);
1598
1599         if (!reply) {
1600                 BT_ERR("Error returned in method call\n");
1601                 if (err) {
1602                         g_dbus_error_strip_remote_error(err);
1603                         ret = __bt_telephony_get_error(err->message);
1604                         g_error_free(err);
1605                         return ret;
1606                 }
1607                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1608         }
1609
1610         g_variant_unref(reply);
1611         FN_END;
1612         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1613 }
1614
1615 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1616 {
1617         GVariant *reply;
1618         GVariant *param;
1619         GError *err = NULL;
1620         int ret;
1621         gboolean state = FALSE;
1622
1623         FN_START;
1624
1625         BT_TELEPHONY_CHECK_INITIALIZED();
1626         BT_TELEPHONY_CHECK_ENABLED();
1627
1628         param = g_variant_new("(b)", &state);
1629         reply = __bluetooth_telephony_dbus_method_send(
1630                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1631                         "SetVoiceDial", &err, param);
1632
1633         if (!reply) {
1634                 BT_ERR("Error returned in method call\n");
1635                 if (err) {
1636                         g_dbus_error_strip_remote_error(err);
1637                         ret = __bt_telephony_get_error(err->message);
1638                         g_error_free(err);
1639                         return ret;
1640                 }
1641                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1642         }
1643
1644         g_variant_unref(reply);
1645
1646         FN_END;
1647         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1648 }
1649
1650 static void __bluetooth_telephony_sco_start_cb(GDBusProxy *proxy,
1651                 GAsyncResult *res, gpointer user_data)
1652 {
1653         GError *error = NULL;
1654         GVariant *value = NULL;
1655
1656         value = g_dbus_proxy_call_finish(proxy, res, &error);
1657         if (value == NULL) {
1658                 if (error != NULL) {
1659                         BT_ERR("sco_close_cb error. errCode[%x],message[%s]",
1660                                         error->code, error->message);
1661                         g_clear_error(&error);
1662                 } else {
1663                         BT_ERR("SCo Start Failed");
1664                 }
1665                 g_object_unref(proxy);
1666                 return;
1667         }
1668
1669         BT_DBG("sco_start_cb : -");
1670         g_object_unref(proxy);
1671         g_variant_unref(value);
1672 }
1673
1674 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1675 {
1676         GDBusConnection *conn;
1677         GDBusProxy *proxy;
1678         GError *err = NULL;
1679         int ret;
1680
1681         FN_START;
1682
1683         BT_TELEPHONY_CHECK_INITIALIZED();
1684         BT_TELEPHONY_CHECK_ENABLED();
1685
1686         /* Because this API is async call, so can't use dbus SMACK */
1687         if (__bt_telephony_check_privilege() ==
1688                                 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1689                 BT_ERR("Don't have a privilege to use this API");
1690                 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1691         }
1692
1693         conn = _bt_get_system_private_conn();
1694         if (!conn) {
1695                 BT_DBG("No System Bus found\n");
1696                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1697         }
1698
1699         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1700                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1701
1702         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1703                         HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1704                         HFP_AGENT_INTERFACE, NULL, &err);
1705         if (proxy == NULL) {
1706                 BT_ERR("Unable to allocate new proxy");
1707                 if (err) {
1708                         g_dbus_error_strip_remote_error(err);
1709                         ret = __bt_telephony_get_error(err->message);
1710                         BT_ERR("Error here %d\n", ret);
1711                         g_error_free(err);
1712                         return ret;
1713                 }
1714                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1715         }
1716
1717         g_dbus_proxy_call(proxy, "Play", NULL, G_DBUS_CALL_FLAGS_NONE,
1718                         -1, NULL, (GAsyncReadyCallback)__bluetooth_telephony_sco_start_cb, NULL);
1719
1720         FN_END;
1721         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1722 }
1723
1724 static void __bluetooth_telephony_sco_close_cb(GDBusProxy *proxy,
1725                 GAsyncResult *res, gpointer user_data)
1726 {
1727         GError *error = NULL;
1728         GVariant *value = NULL;
1729
1730         value = g_dbus_proxy_call_finish(proxy, res, &error);
1731         if (value == NULL) {
1732                 if (error != NULL) {
1733                         BT_ERR("sco_close_cb error. errCode[%x],message[%s]",
1734                                         error->code, error->message);
1735                         g_clear_error(&error);
1736                 } else {
1737                         BT_ERR("SCo close Failed");
1738                 }
1739                 g_object_unref(proxy);
1740                 return;
1741         }
1742
1743         BT_DBG("sco_close_cb : -");
1744         g_object_unref(proxy);
1745         g_variant_unref(value);
1746 }
1747 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1748 {
1749         GDBusConnection *conn;
1750         GDBusProxy *proxy;
1751         GError *err = NULL;
1752         int ret;
1753
1754         FN_START;
1755
1756         BT_TELEPHONY_CHECK_INITIALIZED();
1757         BT_TELEPHONY_CHECK_ENABLED();
1758
1759         /* Because this API is async call, so can't use dbus SMACK */
1760         if (__bt_telephony_check_privilege() ==
1761                                 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1762                 BT_ERR("Don't have a privilege to use this API");
1763                 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1764         }
1765
1766         conn = _bt_get_system_private_conn();
1767         if (!conn) {
1768                 BT_DBG("No System Bus found\n");
1769                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1770         }
1771
1772         if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1773                 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1774
1775         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
1776                         HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1777                         HFP_AGENT_INTERFACE, NULL, &err);
1778         if (proxy == NULL) {
1779                 BT_ERR("Unable to allocate new proxy");
1780                 if (err) {
1781                         g_dbus_error_strip_remote_error(err);
1782                         ret = __bt_telephony_get_error(err->message);
1783                         BT_ERR("Error here %d\n", ret);
1784                         g_error_free(err);
1785                         return ret;
1786                 }
1787                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1788         }
1789
1790         g_dbus_proxy_call(proxy, "Stop", NULL, G_DBUS_CALL_FLAGS_NONE,
1791                         -1, NULL, (GAsyncReadyCallback)__bluetooth_telephony_sco_close_cb, NULL);
1792
1793         telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
1794
1795         FN_END;
1796         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1797 }
1798
1799 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1800 {
1801         int ret;
1802
1803         BT_TELEPHONY_CHECK_INITIALIZED();
1804         BT_TELEPHONY_CHECK_ENABLED();
1805
1806         FN_START;
1807         BT_DBG("call_id = [%d]", call_id);
1808
1809         /*Make sure SCO is already connected */
1810         ret = __bluetooth_telephony_send_call_status(
1811                                 CSD_CALL_STATUS_MO_ALERTING, call_id, NULL);
1812
1813         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1814                 BT_ERR("send call status Failed = [%d]", ret);
1815
1816         FN_END;
1817         return ret;
1818 }
1819
1820 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
1821                                                         unsigned int bt_audio)
1822 {
1823         int ret;
1824
1825         FN_START;
1826         BT_DBG("call_id = [%d]", call_id);
1827
1828         BT_TELEPHONY_CHECK_INITIALIZED();
1829         BT_TELEPHONY_CHECK_ENABLED();
1830
1831         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1832                                                                 call_id, NULL);
1833         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1834                 BT_ERR("send call status Failed = [%d]", ret);
1835                 return ret;
1836         }
1837
1838         if (bt_audio) {
1839                 if (!bluetooth_telephony_is_sco_connected()) {
1840                         ret = bluetooth_telephony_audio_open();
1841                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1842                                 BT_ERR("Audio connection call Failed[%d]", ret);
1843                 }
1844         }
1845
1846         FN_END;
1847         return ret;
1848 }
1849
1850 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
1851 {
1852         int ret;
1853
1854         FN_START;
1855         BT_DBG("call_id = [%d]", call_id);
1856
1857         BT_TELEPHONY_CHECK_INITIALIZED();
1858         BT_TELEPHONY_CHECK_ENABLED();
1859
1860         if (telephony_info.call_count > 0)
1861                 telephony_info.call_count = telephony_info.call_count - 1;
1862
1863         if (telephony_info.call_count  == 0) {
1864                 if (bluetooth_telephony_is_sco_connected()) {
1865                         ret = bluetooth_telephony_audio_close();
1866                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1867                                 BT_ERR(" Failed = [%d]", ret);
1868                 }
1869         }
1870
1871         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
1872                                                                 call_id, NULL);
1873         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1874                 BT_ERR("send call status Failed = [%d]", ret);
1875
1876         FN_END;
1877         return ret;
1878 }
1879
1880 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
1881 {
1882         int ret;
1883
1884         FN_START;
1885         BT_DBG("call_id = [%d]", call_id);
1886
1887         BT_TELEPHONY_CHECK_INITIALIZED();
1888         BT_TELEPHONY_CHECK_ENABLED();
1889
1890         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
1891                                                                 call_id, NULL);
1892         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1893                 BT_ERR("send call status Failed = [%d]", ret);
1894
1895         FN_END;
1896         return ret;
1897 }
1898
1899 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
1900 {
1901         int ret;
1902
1903         FN_START;
1904         BT_DBG("call_id = [%d]", call_id);
1905
1906         BT_TELEPHONY_CHECK_INITIALIZED();
1907         BT_TELEPHONY_CHECK_ENABLED();
1908
1909         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1910                                                                 call_id, NULL);
1911         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1912                 BT_ERR("send call status Failed = [%d]", ret);
1913
1914         FN_END;
1915         return ret;
1916 }
1917
1918 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
1919                                 unsigned int call_count)
1920 {
1921         int i;
1922         int ret;
1923         GList *list = call_list;
1924         bt_telephony_call_status_info_t *call_status;
1925
1926         FN_START;
1927
1928         BT_TELEPHONY_CHECK_INITIALIZED();
1929         BT_TELEPHONY_CHECK_ENABLED();
1930
1931         if (NULL == list) {
1932                 BT_ERR("call_list is invalid");
1933                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1934         }
1935
1936         /* Because this API is async call, so can't use dbus SMACK */
1937         if (__bt_telephony_check_privilege() ==
1938                                 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1939                 BT_ERR("Don't have a privilege to use this API");
1940                 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1941         }
1942
1943         BT_DBG(" call_count = [%d]", call_count);
1944
1945         for (i = 0; i < call_count; i++) {
1946                 call_status = g_list_nth_data(list, i);
1947
1948                 if (NULL == call_status)
1949                         continue;
1950
1951                 BT_DBG(" %d : Call id [%d] status[%d]", i,
1952                                         call_status->call_id,
1953                                         call_status->call_status);
1954
1955                 if (NULL != call_status->phone_number)
1956                         DBG_SECURE("Number [%s]", call_status->phone_number);
1957
1958                 switch (call_status->call_status) {
1959                 case BLUETOOTH_CALL_STATE_HELD:
1960                         ret = __bluetooth_telephony_send_call_status(
1961                                                 CSD_CALL_STATUS_HOLD,
1962                                                 call_status->call_id,
1963                                                 call_status->phone_number);
1964                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1965                                 BT_ERR("Failed = %d", ret);
1966                                 return ret;
1967                         }
1968                 break;
1969
1970                 case BLUETOOTH_CALL_STATE_CONNECTED:
1971                         ret = __bluetooth_telephony_send_call_status(
1972                                         CSD_CALL_STATUS_ACTIVE,
1973                                         call_status->call_id,
1974                                         call_status->phone_number);
1975                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1976                                 BT_ERR("Failed = [%d]", ret);
1977                                 return ret;
1978                         }
1979                 break;
1980
1981                 default:
1982                         if ((call_status->call_status <
1983                                         BLUETOOTH_CALL_STATE_NONE) ||
1984                                 (call_status->call_status >=
1985                                         BLUETOOTH_CALL_STATE_ERROR)) {
1986                                 BT_ERR("Unknown Call state");
1987                                 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
1988                         }
1989                 }
1990         }
1991
1992         FN_END;
1993         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1994 }
1995
1996 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
1997                                 unsigned int call_count)
1998 {
1999         int ret;
2000
2001         FN_START;
2002
2003         ret = bluetooth_telephony_call_swapped(call_list, call_count);
2004
2005         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2006                 BT_ERR("Failed = [%d]", ret);
2007                 return ret;
2008         }
2009
2010         telephony_info.call_count = call_count;
2011
2012         FN_END;
2013         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2014 }
2015
2016 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
2017                         const char *ph_number, unsigned int call_id,
2018                         unsigned int bt_audio)
2019 {
2020         GVariant *reply;
2021         GVariant *param;
2022         GError *err = NULL;
2023         const char *path = telephony_info.call_path;
2024         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
2025
2026         FN_START;
2027
2028         BT_TELEPHONY_CHECK_INITIALIZED();
2029         BT_TELEPHONY_CHECK_ENABLED();
2030
2031         if (NULL == ph_number)
2032                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2033
2034         param = g_variant_new("(ssi)", path, ph_number, call_id);
2035         reply = __bluetooth_telephony_dbus_method_send(
2036                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2037                         "OutgoingCall", &err, param);
2038
2039         if (!reply) {
2040                 BT_ERR("Error returned in method call\n");
2041                 if (err) {
2042                         g_dbus_error_strip_remote_error(err);
2043                         ret = __bt_telephony_get_error(err->message);
2044                         g_error_free(err);
2045                         return ret;
2046                 }
2047                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2048         }
2049
2050         g_variant_unref(reply);
2051
2052         telephony_info.call_count++;
2053         BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
2054
2055         if (bt_audio) {
2056                 if (!bluetooth_telephony_is_sco_connected()) {
2057                         ret = bluetooth_telephony_audio_open();
2058                         if (ret != 0)
2059                                 BT_ERR(" Audio connection Failed = %d", ret);
2060                 }
2061         }
2062
2063         FN_END;
2064         return ret;
2065 }
2066
2067 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
2068                 const char *ph_number, unsigned int call_id)
2069 {
2070         GVariant *reply;
2071         GVariant *param;
2072         GError *err = NULL;
2073         const char *path = telephony_info.call_path;
2074         int ret;
2075
2076         FN_START;
2077
2078         BT_TELEPHONY_CHECK_INITIALIZED();
2079         BT_TELEPHONY_CHECK_ENABLED();
2080
2081         if (NULL == ph_number)
2082                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2083
2084         param = g_variant_new("(ssi)", path, ph_number, call_id);
2085         reply = __bluetooth_telephony_dbus_method_send(
2086                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2087                         "IncomingCall", &err, param);
2088
2089         if (!reply) {
2090                 BT_ERR("Error returned in method call\n");
2091                 if (err) {
2092                         g_dbus_error_strip_remote_error(err);
2093                         ret = __bt_telephony_get_error(err->message);
2094                         g_error_free(err);
2095                         return ret;
2096                 }
2097                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2098         }
2099
2100         g_variant_unref(reply);
2101         telephony_info.call_count++;
2102         BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
2103         FN_END;
2104         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2105 }
2106
2107 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(
2108                                                 unsigned short speaker_gain)
2109 {
2110         GVariant *reply;
2111         GVariant *param;
2112         GError *err = NULL;
2113         int ret;
2114
2115         FN_START;
2116
2117         BT_TELEPHONY_CHECK_INITIALIZED();
2118         BT_TELEPHONY_CHECK_ENABLED();
2119
2120         BT_DBG("set speaker_gain= [%d]", speaker_gain);
2121
2122         param = g_variant_new("(q)", speaker_gain);
2123         reply = __bluetooth_telephony_dbus_method_send(
2124                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2125                         "SetSpeakerGain", &err, param);
2126
2127         if (!reply) {
2128                 BT_ERR("Error returned in method call\n");
2129                 if (err) {
2130                         g_dbus_error_strip_remote_error(err);
2131                         ret = __bt_telephony_get_error(err->message);
2132                         g_error_free(err);
2133                         return ret;
2134                 }
2135                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2136         }
2137
2138         g_variant_unref(reply);
2139         FN_END;
2140         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2141 }
2142
2143 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(
2144                                                 unsigned int *speaker_gain)
2145 {
2146         GVariant *reply;
2147         GError *err = NULL;
2148         int ret;
2149         guint16 gain;
2150
2151         FN_START;
2152
2153         BT_TELEPHONY_CHECK_INITIALIZED();
2154         BT_TELEPHONY_CHECK_ENABLED();
2155
2156         reply = __bluetooth_telephony_dbus_method_send(
2157                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2158                         "GetSpeakerGain", &err, NULL);
2159
2160         if (!reply) {
2161                 BT_ERR("Error returned in method call\n");
2162                 if (err) {
2163                         g_dbus_error_strip_remote_error(err);
2164                         ret = __bt_telephony_get_error(err->message);
2165                         g_error_free(err);
2166                         return ret;
2167                 }
2168                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2169         }
2170         g_variant_get(reply, "(q)", &gain);
2171         *speaker_gain = gain;
2172         BT_DBG("Get speaker_gain= [%d]", *speaker_gain);
2173
2174         g_variant_unref(reply);
2175
2176         FN_END;
2177         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2178 }
2179
2180 BT_EXPORT_API int bluetooth_telephony_is_connected(gboolean *ag_connected)
2181 {
2182         GVariant *reply;
2183         GError *err = NULL;
2184         int ret;
2185         gboolean ag_connected_from_bt_agent;
2186
2187         BT_CHECK_ENABLED(return);
2188
2189         reply = __bluetooth_telephony_dbus_method_send(
2190                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2191                         "IsConnected", &err, NULL);
2192
2193         if (!reply) {
2194                 BT_ERR("Error returned in method call\n");
2195                 if (err) {
2196                         g_dbus_error_strip_remote_error(err);
2197                         ret = __bt_telephony_get_error(err->message);
2198                         g_error_free(err);
2199                         return ret;
2200                 }
2201                 return BLUETOOTH_ERROR_INTERNAL;
2202         }
2203         g_variant_get(reply, "(b)", &ag_connected_from_bt_agent);
2204         *ag_connected = ag_connected_from_bt_agent;
2205
2206         BT_DBG("Conn Status: %s", *ag_connected ? "Connected" : "Disconnected");
2207
2208         g_variant_unref(reply);
2209
2210         return BLUETOOTH_ERROR_NONE;
2211 }
2212
2213 BT_EXPORT_API int bluetooth_telephony_set_active_headset(const char *remote_addr)
2214 {
2215 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
2216         GVariant *reply;
2217         GVariant *param;
2218         GError *err = NULL;
2219         int ret;
2220
2221         BT_CHECK_ENABLED(return);
2222
2223         if (NULL == remote_addr)
2224                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2225
2226         param = g_variant_new("(s)", remote_addr);
2227         reply = __bluetooth_telephony_dbus_method_send(
2228                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2229                         "SwapHeadset", &err, param);
2230
2231         if (!reply) {
2232                 BT_ERR("Error returned in method call\n");
2233                 if (err) {
2234                         g_dbus_error_strip_remote_error(err);
2235                         ret = __bt_telephony_get_error(err->message);
2236                         g_error_free(err);
2237                         return ret;
2238                 }
2239                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2240         }
2241
2242         g_variant_unref(reply);
2243         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2244 #else
2245         return BLUETOOTH_ERROR_NOT_SUPPORT;
2246 #endif
2247 }
2248
2249 static void __bt_telephony_adapter_filter(GDBusConnection *connection,
2250                                         const gchar *sender_name,
2251                                         const gchar *object_path,
2252                                         const gchar *interface_name,
2253                                         const gchar *signal_name,
2254                                         GVariant *parameters,
2255                                         gpointer user_data)
2256 {
2257         FN_START;
2258         int ret;
2259         char *path = NULL;
2260
2261         if (strcasecmp(signal_name, "InterfacesAdded") == 0) {
2262                 GVariant *optional_param = NULL;
2263
2264                 g_variant_get(parameters, "(&o@a{sa{sv}})",
2265                                                         &path, &optional_param);
2266
2267                 if (!path) {
2268                         BT_ERR("Invalid adapter path");
2269                         return;
2270                 }
2271
2272                 BT_INFO("Adapter Path = [%s]", path);
2273                 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
2274                         if (__bt_telephony_get_src_addr(optional_param))
2275                                 BT_ERR("Fail to get the local adapter address");
2276
2277                         ret = __bluetooth_telephony_register();
2278                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2279                                 BT_ERR("__bluetooth_telephony_register failed");
2280                 }
2281
2282                 g_variant_unref(optional_param);
2283         }
2284
2285         FN_END;
2286 }
2287
2288 static int __bt_telephony_get_src_addr(GVariant *value)
2289 {
2290         GVariantIter iter;
2291         GVariant *param = NULL;
2292         FN_START;
2293
2294         /* signature a{sa{sv}} */
2295         g_variant_iter_init(&iter, value);
2296         while ((param = g_variant_iter_next_value(&iter))) {
2297                 char *interface_name;
2298                 GVariant *interface_var = NULL;
2299                 GVariant *param_inner = NULL;
2300
2301                 g_variant_get(param, "{&s*}", &interface_name, &interface_var);
2302                 g_variant_unref(param);
2303
2304                 BT_DBG("interface_name: %s", interface_name);
2305                 /* format of interface_var: a{sv}*/
2306                 if (strcasecmp(interface_name, BLUEZ_ADAPTER_INTERFACE) == 0) {
2307                         GVariantIter iter_inner;
2308
2309                         g_variant_iter_init(&iter_inner, interface_var);
2310                         while ((param_inner = g_variant_iter_next_value(&iter_inner))) {
2311                                 char *property_name;
2312                                 GVariant *property_var;
2313
2314                                 g_variant_get(param_inner, "{&sv}",
2315                                                 &property_name,
2316                                                 &property_var);
2317                                 g_variant_unref(param_inner);
2318
2319                                 if (strcasecmp(property_name, "Address") == 0) {
2320                                         const gchar *bd_addr;
2321
2322                                         bd_addr = g_variant_get_string(
2323                                                                 property_var,
2324                                                                 NULL);
2325                                         src_addr = g_strdup(bd_addr);
2326                                         BT_DBG("Address: %s", src_addr);
2327
2328                                         g_variant_unref(interface_var);
2329                                         g_variant_unref(property_var);
2330                                         goto done;
2331                                 }
2332                                 g_variant_unref(property_var);
2333                         }
2334                 }
2335                 g_variant_unref(interface_var);
2336         }
2337
2338 done:
2339         return BLUETOOTH_ERROR_NONE;
2340 }