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