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