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