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