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