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