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