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