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