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