Handle the privilege permission error for agent methods
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-telephony.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <vconf.h>
23 #include <vconf-keys.h>
24
25 #include "bt-common.h"
26 #include "bluetooth-telephony-api.h"
27 #include "marshal.h"
28 #include "bt-internal-types.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         int timeout = -1;
312
313         if (TIZEN_PROFILE_WEARABLE || TIZEN_PROFILE_IVI)
314                 timeout = 4000;
315
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         if (node_info == NULL) {
708                 BT_ERR("node_info NULL");
709                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
710         }
711         if (__bluetooth_telephony_register_object(TRUE, node_info) !=
712                         BLUETOOTH_TELEPHONY_ERROR_NONE) {
713                 BT_ERR("Registation of Method Failed");
714                 g_dbus_node_info_unref(node_info);
715                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
716         }
717
718         FN_END;
719         g_dbus_node_info_unref(node_info);
720         return BLUETOOTH_TELEPHONY_ERROR_NONE;
721 }
722
723 static void __bluetooth_telephony_proxy_deinit(void)
724 {
725         FN_START;
726
727         __bluetooth_telephony_register_object(FALSE, NULL);
728
729         FN_END;
730         return;
731 }
732
733 static int __bluetooth_telephony_register(void)
734 {
735         GVariant *reply;
736         GVariant *param;
737         GError *err = NULL;
738         char *path = g_strdup(telephony_info.call_path);
739         int ret;
740
741         FN_START;
742
743         param = g_variant_new("(ss)", path, src_addr);
744         BT_DBG("Path[%s] Src_Address[%s]", path, src_addr);
745
746         reply =  __bluetooth_telephony_dbus_method_send(
747                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
748                         "RegisterApplication", &err, param);
749
750         g_free(path);
751
752         if (!reply) {
753                 BT_ERR("Error returned in method call");
754                 if (err) {
755                         g_dbus_error_strip_remote_error(err);
756                         ret = __bt_telephony_get_error(err->message);
757                         BT_ERR("Error here %d\n", ret);
758                         g_error_free(err);
759                         return ret;
760                 }
761                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
762         }
763
764         g_variant_unref(reply);
765         BT_DBG("__bluetooth_telephony_register completed");
766         FN_END;
767         return BLUETOOTH_TELEPHONY_ERROR_NONE;
768 }
769
770 static  int __bluetooth_telephony_unregister(void)
771 {
772         GVariant *reply;
773         GVariant *param;
774         GError *err = NULL;
775         char *path = g_strdup(telephony_info.call_path);
776         int ret;
777
778         FN_START;
779
780         param = g_variant_new("(s)", path);
781         reply = __bluetooth_telephony_dbus_method_send(
782                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
783                         "UnregisterApplication", &err, param);
784
785         g_free(path);
786
787         if (!reply) {
788                 BT_ERR("Error returned in method call");
789                 if (err) {
790                         g_dbus_error_strip_remote_error(err);
791                         ret = __bt_telephony_get_error(err->message);
792                         g_error_free(err);
793                         return ret;
794                 }
795                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
796         }
797
798         g_variant_unref(reply);
799         BT_DBG("__bluetooth_telephony_unregister completed");
800         FN_END;
801         return BLUETOOTH_TELEPHONY_ERROR_NONE;
802 }
803
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
844 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
845 {
846         gboolean flag = FALSE;
847         FN_START;
848
849         switch ((device_class & 0x1f00) >> 8) {
850         case 0x04:
851                 switch ((device_class & 0xfc) >> 2) {
852                 case 0x01:
853                 case 0x02:
854                         flag = TRUE;
855                         break;
856                 case 0x06:
857                         flag = TRUE;
858                         break;
859                 case 0x0b:
860                 case 0x0c:
861                 case 0x0d:
862                         break;
863                 default:
864                         flag = TRUE;
865                         break;
866                 }
867                 break;
868
869         /* Tizen Wearable device */
870         case 0x07:
871                 switch ((device_class & 0xfc) >> 2) {
872                 case 0x01: /* Wrist Watch */
873                         flag = TRUE;
874                         break;
875                 default:
876                         break;
877                 }
878                 break;
879         }
880         BT_DBG("[%d]", flag);
881         FN_END;
882         return flag;
883 }
884
885 static gboolean __bluetooth_telephony_is_headset_by_uuid(gchar **uuids)
886 {
887         int i;
888         char **parts;
889         unsigned int service = 0;
890
891         FN_START;
892
893         retv_if(uuids == NULL, FALSE);
894
895         for (i = 0; uuids[i] != NULL; i++) {
896                 parts = g_strsplit(uuids[i], "-", -1);
897
898                 if (parts == NULL || parts[0] == NULL) {
899                         g_strfreev(parts);
900                         continue;
901                 }
902
903                 service = g_ascii_strtoull(parts[0], NULL, 16);
904                 g_strfreev(parts);
905
906                 if (service == BLUETOOTH_HS_PROFILE_UUID ||
907                                 service == BLUETOOTH_HF_PROFILE_UUID)
908                         return TRUE;
909         }
910
911         FN_END;
912         return FALSE;
913 }
914
915
916 static int __bluetooth_telephony_get_connected_device(void)
917 {
918         GDBusConnection *conn;
919         GDBusProxy *headset_agent_proxy = NULL;
920         GDBusProxy *manager_proxy = NULL;
921         GDBusProxy *proxy = NULL;
922         GVariant *reply = NULL;
923         GVariant *getall = NULL;
924         GVariant *isPlayingReply = NULL;
925         GVariant *isConnectedReply = NULL;
926         GVariant *param = NULL;
927         GVariant *var_path = NULL;
928         GVariant *path_values = NULL;
929         GVariant *value = NULL;
930         GError *error = NULL;
931         GVariantIter iter;
932         GVariantIter iter_path;
933         GVariantIter property_iter;
934         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
935
936         FN_START;
937         conn = _bt_gdbus_get_system_gconn();
938         retv_if(conn == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
939
940         manager_proxy = g_dbus_proxy_new_sync(
941                         conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
942                         BLUEZ_SERVICE_NAME, "/",
943                         BLUEZ_MANAGER_INTERFACE, NULL, &error);
944         if (manager_proxy == NULL) {
945                 BT_ERR("Unable to allocate new proxy \n");
946                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
947                 if (error) {
948                         g_dbus_error_strip_remote_error(error);
949                         ret = __bt_telephony_get_error(error->message);
950                         BT_ERR("Error here %d\n", ret);
951                         g_error_free(error);
952                 }
953                 goto done;
954         }
955
956         /* Synchronous call */
957         reply = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects", NULL,
958                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
959         g_object_unref(manager_proxy);
960
961         if (!reply) {
962                 BT_ERR("Can't get managed objects");
963                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
964                 if (error) {
965                         g_dbus_error_strip_remote_error(error);
966                         ret = __bt_telephony_get_error(error->message);
967                         BT_ERR("Error here %d\n", ret);
968                         g_error_free(error);
969                 }
970                 goto done;
971         }
972
973         /* signature of GetManagedObjects:      a{oa{sa{sv}}} */
974         g_variant_iter_init(&iter, reply);
975
976         while ((param = g_variant_iter_next_value(&iter))) {
977                 g_variant_iter_init(&iter_path, param);
978
979                 while ((var_path = g_variant_iter_next_value(&iter_path))) {
980                         gsize len;
981                         uint32_t device_class = 0;
982                         gboolean playing = FALSE;
983                         gboolean connected = FALSE;
984                         char *object_path = NULL;
985                         gchar *address = NULL;
986                         const gchar *key;
987                         gchar **uuids = NULL;
988                         GVariant *getall_param = NULL;
989
990                         g_variant_get(var_path, "{&o*}", &object_path,
991                                         &path_values);
992                         g_variant_unref(path_values); /* path_values unused*/
993
994                         proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
995                                         G_DBUS_PROXY_FLAGS_NONE, NULL,
996                                         BLUEZ_SERVICE_NAME, object_path,
997                                         BLUEZ_PROPERTIES_INTERFACE, NULL, &error);
998                         if (proxy == NULL) {
999                                 BT_ERR("Unable to allocate new proxy \n");
1000                                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1001                                 if (error) {
1002                                         g_dbus_error_strip_remote_error(error);
1003                                         ret = __bt_telephony_get_error(error->message);
1004                                         BT_ERR("Error here %d\n", ret);
1005                                         g_error_free(error);
1006                                 }
1007                                 goto done;
1008                         }
1009
1010
1011                         getall_param = g_variant_new("s", BLUEZ_DEVICE_INTERFACE);
1012                         getall = g_dbus_proxy_call_sync(proxy,
1013                                         "GetAll", getall_param,
1014                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1015                         g_object_unref(proxy);
1016
1017                         if (!getall) {
1018                                 BT_ERR("Can't get managed objects");
1019                                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1020                                 if (error) {
1021                                         g_dbus_error_strip_remote_error(error);
1022                                         ret = __bt_telephony_get_error(error->message);
1023                                         BT_ERR("Error here %d\n", ret);
1024                                         g_error_free(error);
1025                                 }
1026                                 goto done;
1027                         }
1028
1029                         g_variant_iter_init(&property_iter, getall);
1030
1031                         while (g_variant_iter_loop(&property_iter, "{&sv}", &key, &value)) {
1032                                 if (!g_strcmp0(key, "Class")) {
1033                                         device_class = g_variant_get_uint32(value);
1034                                         BT_DBG("Device Class: %d", device_class);
1035                                 } else if (!g_strcmp0(key, "UUID")) {
1036                                         int i = 0;
1037                                         uuids = (gchar **)g_variant_get_strv(value, &len);
1038                                         BT_DBG_UUID(uuids, len, i);
1039                                 } else if (!g_strcmp0(key, "Address")) {
1040                                         address = (gchar *)g_variant_get_string(
1041                                                                         value,
1042                                                                         NULL);
1043                                         BT_DBG("Device Class: %s", address);
1044                                 }
1045                                 g_variant_unref(value);
1046                         }
1047                         g_variant_unref(getall);
1048
1049                         if (device_class == 0) {
1050                                 BT_DBG("COD is NULL (maybe paired by nfc)...  Checking UUIDs");
1051                                 if (!__bluetooth_telephony_is_headset_by_uuid(uuids)) {
1052                                         BT_DBG("UUID checking completed. None HF device");
1053                                         continue;
1054                                 }
1055                                 BT_DBG("UUID checking completed. HF device");
1056                         } else {
1057                                 if (!__bluetooth_telephony_is_headset(device_class))
1058                                         continue;
1059                         }
1060
1061                         /* this is headset; Check for Connection */
1062                         headset_agent_proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
1063                                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1064                                         HFP_AGENT_SERVICE, object_path,
1065                                         HFP_AGENT_INTERFACE, NULL, &error);
1066                         if (headset_agent_proxy == NULL) {
1067                                 BT_ERR("Unable to allocate new headset_agent_proxy");
1068                                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1069                                 if (error) {
1070                                         g_dbus_error_strip_remote_error(error);
1071                                         ret = __bt_telephony_get_error(error->message);
1072                                         BT_ERR("Error here %d\n", ret);
1073                                         g_error_free(error);
1074                                 }
1075                                 goto done;
1076                         }
1077
1078                         isConnectedReply = g_dbus_proxy_call_sync(headset_agent_proxy,
1079                                         "IsConnected", NULL,
1080                                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1081
1082
1083                         if (!isConnectedReply) {
1084                                 BT_ERR("Can't get managed objects");
1085                                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1086                                 if (error) {
1087                                         g_dbus_error_strip_remote_error(error);
1088                                         ret = __bt_telephony_get_error(error->message);
1089                                         BT_ERR("Error here %d\n", ret);
1090                                         g_error_free(error);
1091                                 }
1092                                 goto done;
1093                         } else {
1094                                 connected = g_variant_get_boolean(isConnectedReply);
1095                                 g_variant_unref(isConnectedReply);
1096
1097                                 if (connected) {
1098                                         g_strlcpy(telephony_info.address,
1099                                                         address,
1100                                                         sizeof(telephony_info.address));
1101
1102                                         isPlayingReply = g_dbus_proxy_call_sync(headset_agent_proxy,
1103                                                         "IsPlaying", NULL,
1104                                                         G_DBUS_CALL_FLAGS_NONE,
1105                                                         -1, NULL, &error);
1106                                         if (!isPlayingReply) {
1107                                                 BT_ERR("Can't get managed objects");
1108                                                 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1109                                                 if (error) {
1110                                                         g_dbus_error_strip_remote_error(error);
1111                                                         ret = __bt_telephony_get_error(error->message);
1112                                                         BT_ERR("Error here %d\n", ret);
1113                                                         g_error_free(error);
1114                                                 }
1115                                         } else {
1116                                                 playing = g_variant_get_boolean(isPlayingReply);
1117                                                 g_variant_unref(isPlayingReply);
1118
1119                                                 if (playing)
1120                                                         telephony_info.headset_state =
1121                                                                 BLUETOOTH_STATE_PLAYING;
1122                                                 else
1123                                                         telephony_info.headset_state =
1124                                                                 BLUETOOTH_STATE_CONNECTED;
1125                                         }
1126
1127                                         goto done;
1128                                 }
1129                         }
1130
1131                         g_object_unref(headset_agent_proxy);
1132                         g_variant_unref(var_path);
1133                 }
1134                 g_variant_unref(param);
1135         }
1136
1137 done:
1138         if (headset_agent_proxy)
1139                 g_object_unref(headset_agent_proxy);
1140         if (reply)
1141                 g_variant_unref(reply);
1142         if (var_path)
1143                 g_variant_unref(var_path);
1144         if (param)
1145                 g_variant_unref(param);
1146         FN_END;
1147         return ret;
1148 }
1149
1150 static GDBusProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1151 {
1152         GDBusProxy *proxy = NULL;
1153         GError *error = NULL;
1154         int ret;
1155         FN_START;
1156
1157         if (strlen(telephony_info.address) == 0)
1158                 __bluetooth_telephony_get_connected_device();
1159
1160         if (strlen(telephony_info.address) == 0)
1161                 return NULL;
1162
1163         proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
1164                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1165                         HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1166                         HFP_AGENT_INTERFACE, NULL, &error);
1167         if (proxy == NULL) {
1168                 BT_ERR("Unable to allocate new proxy");
1169                 if (error) {
1170                         g_dbus_error_strip_remote_error(error);
1171                         ret = __bt_telephony_get_error(error->message);
1172                         BT_ERR("Error here %d\n", ret);
1173                         g_error_free(error);
1174                 }
1175                 return NULL;
1176         }
1177
1178         FN_END;
1179         return proxy;
1180 }
1181
1182 int __bt_telephony_subscribe_adapter_signal(GDBusConnection *conn,
1183                 int subscribe)
1184 {
1185         if (conn == NULL)
1186                 return -1;
1187
1188         static guint subscribe_adapter_id = 0;
1189
1190         if (subscribe == TRUE) {
1191                 if (subscribe_adapter_id == 0) {
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 > 0) {
1201                         g_dbus_connection_signal_unsubscribe(conn,
1202                                         subscribe_adapter_id);
1203                         subscribe_adapter_id = 0;
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 guint subscribe_event1_id = 0;
1216         static guint subscribe_event2_id = 0;
1217         static guint subscribe_event3_id = 0;
1218         static guint subscribe_event4_id = 0;
1219         static guint subscribe_event5_id = 0;
1220         static guint subscribe_event6_id = 0;
1221
1222         if (subscribe == TRUE) {
1223                 if (subscribe_event1_id == 0) {
1224                         subscribe_event1_id = g_dbus_connection_signal_subscribe(conn,
1225                                         NULL, BLUEZ_HEADSET_INTERFACE,
1226                                         "PropertyChanged", NULL, NULL, 0,
1227                                         __bluetooth_telephony_event_filter,
1228                                         NULL, NULL);
1229                 }
1230                 if (subscribe_event2_id == 0) {
1231                         subscribe_event2_id = g_dbus_connection_signal_subscribe(conn,
1232                                         NULL, HFP_AGENT_SERVICE,
1233                                         HFP_NREC_STATUS_CHANGE, NULL, NULL, 0,
1234                                         __bluetooth_telephony_event_filter,
1235                                         NULL, NULL);
1236                 }
1237
1238                 if (subscribe_event3_id == 0) {
1239                         subscribe_event3_id = g_dbus_connection_signal_subscribe(conn,
1240                                         NULL, HFP_AGENT_SERVICE,
1241                                         HFP_ANSWER_CALL, NULL, NULL, 0,
1242                                         __bluetooth_telephony_event_filter,
1243                                         NULL, NULL);
1244                 }
1245                 if (subscribe_event4_id == 0) {
1246                         subscribe_event4_id = g_dbus_connection_signal_subscribe(conn,
1247                                         NULL, HFP_AGENT_SERVICE,
1248                                         HFP_REJECT_CALL, NULL, NULL, 0,
1249                                         __bluetooth_telephony_event_filter,
1250                                         NULL, NULL);
1251                 }
1252                 if (subscribe_event5_id == 0) {
1253                         subscribe_event5_id = g_dbus_connection_signal_subscribe(conn,
1254                                         NULL, HFP_AGENT_SERVICE,
1255                                         HFP_RELEASE_CALL, NULL, NULL, 0,
1256                                         __bluetooth_telephony_event_filter,
1257                                         NULL, NULL);
1258                 }
1259                 if (subscribe_event6_id == 0) {
1260                         subscribe_event6_id = g_dbus_connection_signal_subscribe(conn,
1261                                         NULL, HFP_AGENT_SERVICE,
1262                                         HFP_THREEWAY_CALL, NULL, NULL, 0,
1263                                         __bluetooth_telephony_event_filter,
1264                                         NULL, NULL);
1265                 }
1266
1267                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1268         } else {
1269                 if (subscribe_event1_id > 0) {
1270                         g_dbus_connection_signal_unsubscribe(conn,
1271                                         subscribe_event1_id);
1272                         subscribe_event1_id = 0;
1273                 }
1274                 if (subscribe_event2_id > 0) {
1275                         g_dbus_connection_signal_unsubscribe(conn,
1276                                         subscribe_event2_id);
1277                         subscribe_event2_id = 0;
1278                 }
1279                 if (subscribe_event3_id > 0) {
1280                         g_dbus_connection_signal_unsubscribe(conn,
1281                                         subscribe_event3_id);
1282                         subscribe_event3_id = 0;
1283                 }
1284                 if (subscribe_event4_id > 0) {
1285                         g_dbus_connection_signal_unsubscribe(conn,
1286                                         subscribe_event4_id);
1287                         subscribe_event4_id = 0;
1288                 }
1289                 if (subscribe_event5_id > 0) {
1290                         g_dbus_connection_signal_unsubscribe(conn,
1291                                         subscribe_event5_id);
1292                         subscribe_event5_id = 0;
1293                 }
1294                 if (subscribe_event6_id > 0) {
1295                         g_dbus_connection_signal_unsubscribe(conn,
1296                                         subscribe_event6_id);
1297                         subscribe_event6_id = 0;
1298                 }
1299                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1300         }
1301 }
1302
1303 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1304                                                         void  *user_data)
1305 {
1306         bluetooth_device_address_t loc_address = { {0} };
1307         char src_address[BT_ADDRESS_STRING_SIZE] = { 0 };
1308         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1309         GError *error = NULL;
1310
1311         FN_START;
1312
1313         if (is_initialized == TRUE) {
1314                 BT_ERR("Bluetooth telephony already initilized");
1315                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1316         }
1317
1318         is_initialized = TRUE;
1319
1320         telephony_dbus_info.conn = _bt_gdbus_init_system_gconn();
1321         if (!telephony_dbus_info.conn) {
1322                 is_initialized = FALSE;
1323                 BT_ERR("Could not get DBus Connection");
1324                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1325         }
1326
1327         /* Call Path */
1328         snprintf(telephony_info.call_path, sizeof(telephony_info.call_path),
1329                                         CSD_CALL_APP_PATH, getpid());
1330         BT_INFO("Call Path = %s", telephony_info.call_path);
1331         memset(telephony_info.address, 0x00, sizeof(telephony_info.address));
1332
1333         if (__bluetooth_telephony_proxy_init()) {
1334                 BT_ERR("__bluetooth_telephony_proxy_init failed\n");
1335                 telephony_dbus_info.conn = NULL;
1336                 is_initialized = FALSE;
1337                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1338         }
1339
1340         telephony_dbus_info.manager_proxy = g_dbus_proxy_new_sync(
1341                         telephony_dbus_info.conn,
1342                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1343                         BLUEZ_SERVICE_NAME, "/",
1344                         BLUEZ_MANAGER_INTERFACE, NULL, &error);
1345         if (telephony_dbus_info.manager_proxy == NULL) {
1346                 BT_ERR("Could not create a manager proxy");
1347                 __bluetooth_telephony_proxy_deinit();
1348                 telephony_dbus_info.conn = NULL;
1349                 is_initialized = FALSE;
1350                 if (error) {
1351                         g_dbus_error_strip_remote_error(error);
1352                         ret = __bt_telephony_get_error(error->message);
1353                         BT_ERR("Error here %d\n", ret);
1354                         g_error_free(error);
1355                         return ret;
1356                 }
1357                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1358         }
1359
1360         telephony_dbus_info.dbus_proxy = g_dbus_proxy_new_sync(
1361                         telephony_dbus_info.conn,
1362                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1363                         BT_EVENT_FREEDESKTOP, BT_FREEDESKTOP_PATH,
1364                         BT_EVENT_FREEDESKTOP, NULL, &error);
1365         if (NULL == telephony_dbus_info.dbus_proxy) {
1366                 __bluetooth_telephony_proxy_deinit();
1367                 telephony_dbus_info.conn = NULL;
1368                 g_object_unref(telephony_dbus_info.manager_proxy);
1369                 telephony_dbus_info.manager_proxy = NULL;
1370                 is_initialized = FALSE;
1371                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1372         }
1373
1374         if (__bt_telephony_subscribe_adapter_signal(telephony_dbus_info.conn, TRUE) != 0) {
1375                 BT_ERR("Fail to Subscribe Adapter Signal");
1376                 goto fail;
1377         }
1378
1379         /*Callback and user applicaton data*/
1380         telephony_info.cb = cb;
1381         telephony_info.user_data = user_data;
1382         telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1383
1384         if (__bt_telephony_event_subscribe_signal(telephony_dbus_info.conn, TRUE) != 0) {
1385                 BT_ERR("Fail to Subscribe telephony event Signal");
1386                 goto fail;
1387         }
1388
1389         if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED)
1390                 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1391
1392         /*Bluetooth is active, therefore set the flag */
1393         is_active = TRUE;
1394         if (!src_addr) {
1395                 ret = bluetooth_get_local_address(&loc_address);
1396                 if (ret != BLUETOOTH_ERROR_NONE) {
1397                         BT_ERR("Fail to get local address\n");
1398                         ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1399                         goto fail;
1400                 }
1401                 _bt_convert_addr_type_to_string(src_address, loc_address.addr);
1402                 src_addr = g_strdup(src_address);
1403         }
1404         ret = __bluetooth_telephony_register();
1405         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1406                 BT_ERR("__bluetooth_telephony_register failed\n");
1407                 goto fail;
1408         }
1409
1410         if (TIZEN_PROFILE_WEARABLE || TIZEN_PROFILE_IVI)
1411                 __bluetooth_telephony_init_headset_state();
1412
1413         FN_END;
1414         return ret;
1415 fail:
1416         bluetooth_telephony_deinit();
1417         return ret;
1418 }
1419
1420 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1421 {
1422         FN_START;
1423         BT_TELEPHONY_CHECK_INITIALIZED();
1424
1425         is_initialized = FALSE;
1426
1427         if (__bt_telephony_event_subscribe_signal(telephony_dbus_info.conn, FALSE) != 0)
1428                 BT_ERR("Fail to UnSubscribe telephony event Signal");
1429
1430         if (bluetooth_check_adapter() != BLUETOOTH_ADAPTER_DISABLED ||
1431                 bluetooth_check_adapter_le() != BLUETOOTH_ADAPTER_LE_DISABLED)
1432                 __bluetooth_telephony_unregister();
1433
1434         __bluetooth_telephony_proxy_deinit();
1435
1436         telephony_info.cb = NULL;
1437         telephony_info.user_data = NULL;
1438         telephony_info.call_count = 0;
1439         telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1440
1441         /* Remove BT enabled signal */
1442         if (__bt_telephony_subscribe_adapter_signal(telephony_dbus_info.conn, FALSE) != 0)
1443                 BT_ERR("Fail to UnSubscribe Adapter event Signal");
1444
1445         g_free(src_addr);
1446         src_addr = NULL;
1447
1448         if (telephony_dbus_info.manager_proxy != NULL) {
1449                 g_object_unref(telephony_dbus_info.manager_proxy);
1450                 telephony_dbus_info.manager_proxy = NULL;
1451         }
1452
1453         if (telephony_dbus_info.conn != NULL)
1454                 telephony_dbus_info.conn = NULL;
1455
1456         if (telephony_dbus_info.dbus_proxy != NULL) {
1457                 g_object_unref(telephony_dbus_info.dbus_proxy);
1458                 telephony_dbus_info.dbus_proxy = NULL;
1459         }
1460
1461         FN_END;
1462         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1463 }
1464
1465 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1466 {
1467         GVariant *reply;
1468         GError *err = NULL;
1469         gboolean status = FALSE;
1470
1471         FN_START;
1472
1473         retv_if(is_initialized == FALSE, FALSE);
1474         retv_if(bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED, FALSE);
1475
1476         reply = __bluetooth_telephony_dbus_method_send(
1477                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1478                         "IsPlaying", &err, NULL);
1479
1480         if (!reply) {
1481                 BT_ERR("Error returned in method call\n");
1482                 if (err) {
1483                         BT_ERR("Error message = %s", err->message);
1484                         g_error_free(err);
1485                 }
1486                 return FALSE;
1487         }
1488         g_variant_get(reply, "(b)", &status);
1489         g_variant_unref(reply);
1490
1491         if (TIZEN_PROFILE_WEARABLE || TIZEN_PROFILE_IVI)
1492                 if (status == TRUE && telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1493                         telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
1494
1495         BT_INFO("SCO Connected Status = [%d]", status);
1496         return status;
1497 }
1498
1499 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1500 {
1501         GVariant *reply;
1502         GError *err = NULL;
1503         GVariantIter iter;
1504         GVariant *param_inner;
1505
1506         FN_START;
1507
1508         BT_TELEPHONY_CHECK_INITIALIZED();
1509         BT_TELEPHONY_CHECK_ENABLED();
1510
1511         if (status == NULL)
1512                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1513
1514         if (telephony_info.headset_state == BLUETOOTH_STATE_DISCONNETED)
1515                 return BLUETOOTH_TELEPHONY_ERROR_AUDIO_NOT_CONNECTED;
1516
1517         reply = __bluetooth_telephony_dbus_method_send(
1518                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1519                         "GetProperties", &err, NULL);
1520
1521         if (!reply) {
1522                 BT_ERR("Error returned in method call\n");
1523                 if (err) {
1524                         BT_DBG("Error message = %s", err->message);
1525                         g_error_free(err);
1526                 }
1527                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1528         }
1529
1530         g_variant_iter_init(&iter, reply);
1531         while ((param_inner = g_variant_iter_next_value(&iter))) {
1532                 GVariant *value;
1533
1534                 value = g_variant_lookup_value(param_inner,
1535                                         "nrec", G_VARIANT_TYPE_BOOLEAN);
1536                 if (value) {
1537                         BT_DBG("Property NREC Found");
1538                         *status = g_variant_get_boolean(value);
1539                         BT_DBG("NREC status = [%d]", *status);
1540                         g_variant_unref(value);
1541                         g_variant_unref(param_inner);
1542                         break;
1543                 }
1544                 g_variant_unref(param_inner);
1545         }
1546         BT_DBG("NREC status = [%d]", *status);
1547         g_variant_unref(reply);
1548
1549         FN_END;
1550         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1551 }
1552
1553 BT_EXPORT_API int bluetooth_telephony_is_wbs_mode(gboolean *status)
1554 {
1555         GVariant *reply;
1556         GError *err = NULL;
1557         unsigned int codec;
1558         GVariantIter iter;
1559         GVariant *param_inner;
1560
1561         FN_START;
1562
1563         BT_TELEPHONY_CHECK_INITIALIZED();
1564         BT_TELEPHONY_CHECK_ENABLED();
1565
1566         if (status == NULL)
1567                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1568
1569         *status = FALSE;
1570
1571         reply = __bluetooth_telephony_dbus_method_send(
1572                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1573                         "GetProperties", &err, NULL);
1574
1575         if (!reply) {
1576                 BT_ERR("Error returned in method call");
1577                 if (err) {
1578                         BT_ERR("Error message = %s", err->message);
1579                         g_error_free(err);
1580                 }
1581                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1582         }
1583
1584         g_variant_iter_init(&iter, reply);
1585         while ((param_inner = g_variant_iter_next_value(&iter))) {
1586                 GVariant *value;
1587
1588                 value = g_variant_lookup_value(param_inner,
1589                                         "codec", G_VARIANT_TYPE_UINT32);
1590                 if (value) {
1591                         BT_DBG("Property CODEC Found");
1592                         codec = g_variant_get_uint32(value);
1593                         g_variant_unref(value);
1594                         BT_DBG("Codec = [%d]", codec);
1595
1596                         *status = codec == BT_MSBC_CODEC_ID ? TRUE : FALSE;
1597                         BT_DBG("NREC status = [%d]", *status);
1598                         g_variant_unref(value);
1599                         g_variant_unref(param_inner);
1600                         break;
1601                 }
1602                 g_variant_unref(param_inner);
1603         }
1604
1605         g_variant_unref(reply);
1606         BT_DBG("MSBC status = [%d]", *status);
1607
1608         FN_END;
1609         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1610 }
1611
1612 BT_EXPORT_API int bluetooth_telephony_send_vendor_cmd(const char *cmd)
1613 {
1614         GError *error = NULL;
1615         GVariant *reply, *parameters;
1616         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1617
1618         FN_START;
1619
1620         BT_TELEPHONY_CHECK_INITIALIZED();
1621         BT_TELEPHONY_CHECK_ENABLED();
1622
1623         BT_DBG("Send Vendor %s", cmd);
1624
1625         if (telephony_dbus_info.proxy == NULL)
1626                 telephony_dbus_info.proxy =
1627                         __bluetooth_telephony_get_connected_device_proxy();
1628
1629         if (telephony_dbus_info.proxy == NULL)
1630                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1631
1632         parameters = g_variant_new("s", cmd);
1633         reply = g_dbus_proxy_call_sync(telephony_dbus_info.proxy,
1634                         "SendVendorAtCmd", parameters,
1635                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1636
1637         g_variant_unref(reply);
1638
1639         if (error) {
1640                 g_dbus_error_strip_remote_error(error);
1641                 ret = __bt_telephony_get_error(error->message);
1642                 BT_ERR("Error here %d\n", ret);
1643                 g_error_free(error);
1644         }
1645
1646         FN_END;
1647         return ret;
1648 }
1649
1650 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1651 {
1652         GVariant *reply;
1653         GVariant *param;
1654         GError *err = NULL;
1655         int ret;
1656         gboolean state = TRUE;
1657
1658         FN_START;
1659
1660         BT_TELEPHONY_CHECK_INITIALIZED();
1661         BT_TELEPHONY_CHECK_ENABLED();
1662
1663         param = g_variant_new("(b)", &state);
1664         reply = __bluetooth_telephony_dbus_method_send(
1665                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1666                         "SetVoiceDial", &err, param);
1667
1668         if (!reply) {
1669                 BT_ERR("Error returned in method call\n");
1670                 if (err) {
1671                         g_dbus_error_strip_remote_error(err);
1672                         ret = __bt_telephony_get_error(err->message);
1673                         g_error_free(err);
1674                         return ret;
1675                 }
1676                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1677         }
1678
1679         g_variant_unref(reply);
1680         FN_END;
1681         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1682 }
1683
1684 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1685 {
1686         GVariant *reply;
1687         GVariant *param;
1688         GError *err = NULL;
1689         int ret;
1690         gboolean state = FALSE;
1691
1692         FN_START;
1693
1694         BT_TELEPHONY_CHECK_INITIALIZED();
1695         BT_TELEPHONY_CHECK_ENABLED();
1696
1697         param = g_variant_new("(b)", &state);
1698         reply = __bluetooth_telephony_dbus_method_send(
1699                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1700                         "SetVoiceDial", &err, param);
1701
1702         if (!reply) {
1703                 BT_ERR("Error returned in method call\n");
1704                 if (err) {
1705                         g_dbus_error_strip_remote_error(err);
1706                         ret = __bt_telephony_get_error(err->message);
1707                         g_error_free(err);
1708                         return ret;
1709                 }
1710                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1711         }
1712
1713         g_variant_unref(reply);
1714
1715         FN_END;
1716         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1717 }
1718
1719 static void __bluetooth_telephony_sco_start_cb(GDBusProxy *proxy,
1720                 GAsyncResult *res, gpointer user_data)
1721 {
1722         GError *error = NULL;
1723         GVariant *value = NULL;
1724
1725         value = g_dbus_proxy_call_finish(proxy, res, &error);
1726         if (value == NULL) {
1727                 if (error != NULL) {
1728                         BT_ERR("sco_close_cb error. errCode[%x],message[%s]",
1729                                         error->code, error->message);
1730                         g_clear_error(&error);
1731                 } else {
1732                         BT_ERR("SCo Start Failed");
1733                 }
1734                 g_object_unref(proxy);
1735                 return;
1736         }
1737
1738         BT_DBG("sco_start_cb : -");
1739         g_object_unref(proxy);
1740         g_variant_unref(value);
1741 }
1742
1743 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1744 {
1745         GDBusConnection *conn;
1746         GDBusProxy *proxy;
1747         GError *err = NULL;
1748         int ret;
1749
1750         FN_START;
1751
1752         BT_TELEPHONY_CHECK_INITIALIZED();
1753         BT_TELEPHONY_CHECK_ENABLED();
1754
1755         /* Because this API is async call, so can't use dbus SMACK */
1756         if (__bt_telephony_check_privilege() ==
1757                                 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1758                 BT_ERR("Don't have a privilege to use this API");
1759                 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1760         }
1761
1762         conn = _bt_gdbus_get_system_gconn();
1763         if (!conn) {
1764                 BT_DBG("No System Bus found\n");
1765                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1766         }
1767
1768         if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1769                 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1770
1771         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
1772                         HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1773                         HFP_AGENT_INTERFACE, NULL, &err);
1774         if (proxy == NULL) {
1775                 BT_ERR("Unable to allocate new proxy");
1776                 if (err) {
1777                         g_dbus_error_strip_remote_error(err);
1778                         ret = __bt_telephony_get_error(err->message);
1779                         BT_ERR("Error here %d\n", ret);
1780                         g_error_free(err);
1781                         return ret;
1782                 }
1783                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1784         }
1785
1786         g_dbus_proxy_call(proxy, "Play", NULL, G_DBUS_CALL_FLAGS_NONE,
1787                         -1, NULL, (GAsyncReadyCallback)__bluetooth_telephony_sco_start_cb, NULL);
1788
1789         FN_END;
1790         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1791 }
1792
1793 static void __bluetooth_telephony_sco_close_cb(GDBusProxy *proxy,
1794                 GAsyncResult *res, gpointer user_data)
1795 {
1796         GError *error = NULL;
1797         GVariant *value = NULL;
1798
1799         value = g_dbus_proxy_call_finish(proxy, res, &error);
1800         if (value == NULL) {
1801                 if (error != NULL) {
1802                         BT_ERR("sco_close_cb error. errCode[%x],message[%s]",
1803                                         error->code, error->message);
1804                         g_clear_error(&error);
1805                 } else {
1806                         BT_ERR("SCo close Failed");
1807                 }
1808                 g_object_unref(proxy);
1809                 return;
1810         }
1811
1812         BT_DBG("sco_close_cb : -");
1813         g_object_unref(proxy);
1814         g_variant_unref(value);
1815 }
1816 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1817 {
1818         GDBusConnection *conn;
1819         GDBusProxy *proxy;
1820         GError *err = NULL;
1821         int ret;
1822
1823         FN_START;
1824
1825         BT_TELEPHONY_CHECK_INITIALIZED();
1826         BT_TELEPHONY_CHECK_ENABLED();
1827
1828         /* Because this API is async call, so can't use dbus SMACK */
1829         if (__bt_telephony_check_privilege() ==
1830                                 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1831                 BT_ERR("Don't have a privilege to use this API");
1832                 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1833         }
1834
1835         conn = _bt_gdbus_get_system_gconn();
1836         if (!conn) {
1837                 BT_DBG("No System Bus found\n");
1838                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1839         }
1840
1841         if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1842                 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1843
1844         proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
1845                         HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1846                         HFP_AGENT_INTERFACE, NULL, &err);
1847         if (proxy == NULL) {
1848                 BT_ERR("Unable to allocate new proxy");
1849                 if (err) {
1850                         g_dbus_error_strip_remote_error(err);
1851                         ret = __bt_telephony_get_error(err->message);
1852                         BT_ERR("Error here %d\n", ret);
1853                         g_error_free(err);
1854                         return ret;
1855                 }
1856                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1857         }
1858
1859         g_dbus_proxy_call(proxy, "Stop", NULL, G_DBUS_CALL_FLAGS_NONE,
1860                         -1, NULL, (GAsyncReadyCallback)__bluetooth_telephony_sco_close_cb, NULL);
1861
1862         telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
1863
1864         FN_END;
1865         return BLUETOOTH_TELEPHONY_ERROR_NONE;
1866 }
1867
1868 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1869 {
1870         int ret;
1871
1872         BT_TELEPHONY_CHECK_INITIALIZED();
1873         BT_TELEPHONY_CHECK_ENABLED();
1874
1875         FN_START;
1876         BT_DBG("call_id = [%d]", call_id);
1877
1878         /*Make sure SCO is already connected */
1879         ret = __bluetooth_telephony_send_call_status(
1880                                 CSD_CALL_STATUS_MO_ALERTING, call_id, NULL);
1881
1882         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1883                 BT_ERR("send call status Failed = [%d]", ret);
1884
1885         FN_END;
1886         return ret;
1887 }
1888
1889 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
1890                                                         unsigned int bt_audio)
1891 {
1892         int ret;
1893
1894         FN_START;
1895         BT_DBG("call_id = [%d]", call_id);
1896
1897         BT_TELEPHONY_CHECK_INITIALIZED();
1898         BT_TELEPHONY_CHECK_ENABLED();
1899
1900         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1901                                                                 call_id, NULL);
1902         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1903                 BT_ERR("send call status Failed = [%d]", ret);
1904                 return ret;
1905         }
1906
1907         if (bt_audio) {
1908                 if (!bluetooth_telephony_is_sco_connected()) {
1909                         ret = bluetooth_telephony_audio_open();
1910                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1911                                 BT_ERR("Audio connection call Failed[%d]", ret);
1912                 }
1913         }
1914
1915         FN_END;
1916         return ret;
1917 }
1918
1919 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
1920 {
1921         int ret;
1922
1923         FN_START;
1924         BT_DBG("call_id = [%d]", call_id);
1925
1926         BT_TELEPHONY_CHECK_INITIALIZED();
1927         BT_TELEPHONY_CHECK_ENABLED();
1928
1929         if (telephony_info.call_count > 0)
1930                 telephony_info.call_count = telephony_info.call_count - 1;
1931
1932         if (telephony_info.call_count  == 0) {
1933                 if (bluetooth_telephony_is_sco_connected()) {
1934                         ret = bluetooth_telephony_audio_close();
1935                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1936                                 BT_ERR(" Failed = [%d]", ret);
1937                 }
1938         }
1939
1940         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
1941                                                                 call_id, NULL);
1942         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1943                 BT_ERR("send call status Failed = [%d]", ret);
1944
1945         FN_END;
1946         return ret;
1947 }
1948
1949 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
1950 {
1951         int ret;
1952
1953         FN_START;
1954         BT_DBG("call_id = [%d]", call_id);
1955
1956         BT_TELEPHONY_CHECK_INITIALIZED();
1957         BT_TELEPHONY_CHECK_ENABLED();
1958
1959         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
1960                                                                 call_id, NULL);
1961         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1962                 BT_ERR("send call status Failed = [%d]", ret);
1963
1964         FN_END;
1965         return ret;
1966 }
1967
1968 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
1969 {
1970         int ret;
1971
1972         FN_START;
1973         BT_DBG("call_id = [%d]", call_id);
1974
1975         BT_TELEPHONY_CHECK_INITIALIZED();
1976         BT_TELEPHONY_CHECK_ENABLED();
1977
1978         ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1979                                                                 call_id, NULL);
1980         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1981                 BT_ERR("send call status Failed = [%d]", ret);
1982
1983         FN_END;
1984         return ret;
1985 }
1986
1987 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
1988                                 unsigned int call_count)
1989 {
1990         int i;
1991         int ret;
1992         GList *list = call_list;
1993         bt_telephony_call_status_info_t *call_status;
1994
1995         FN_START;
1996
1997         BT_TELEPHONY_CHECK_INITIALIZED();
1998         BT_TELEPHONY_CHECK_ENABLED();
1999
2000         if (NULL == list) {
2001                 BT_ERR("call_list is invalid");
2002                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2003         }
2004
2005         /* Because this API is async call, so can't use dbus SMACK */
2006         if (__bt_telephony_check_privilege() ==
2007                                 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
2008                 BT_ERR("Don't have a privilege to use this API");
2009                 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
2010         }
2011
2012         BT_DBG(" call_count = [%d]", call_count);
2013
2014         for (i = 0; i < call_count; i++) {
2015                 call_status = g_list_nth_data(list, i);
2016
2017                 if (NULL == call_status)
2018                         continue;
2019
2020                 BT_DBG(" %d : Call id [%d] status[%d]", i,
2021                                         call_status->call_id,
2022                                         call_status->call_status);
2023
2024                 if (NULL != call_status->phone_number)
2025                         DBG_SECURE("Number [%s]", call_status->phone_number);
2026
2027                 switch (call_status->call_status) {
2028                 case BLUETOOTH_CALL_STATE_HELD:
2029                         ret = __bluetooth_telephony_send_call_status(
2030                                                 CSD_CALL_STATUS_HOLD,
2031                                                 call_status->call_id,
2032                                                 call_status->phone_number);
2033                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2034                                 BT_ERR("Failed = %d", ret);
2035                                 return ret;
2036                         }
2037                 break;
2038
2039                 case BLUETOOTH_CALL_STATE_CONNECTED:
2040                         ret = __bluetooth_telephony_send_call_status(
2041                                         CSD_CALL_STATUS_ACTIVE,
2042                                         call_status->call_id,
2043                                         call_status->phone_number);
2044                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2045                                 BT_ERR("Failed = [%d]", ret);
2046                                 return ret;
2047                         }
2048                 break;
2049
2050                 default:
2051                         if ((call_status->call_status <
2052                                         BLUETOOTH_CALL_STATE_NONE) ||
2053                                 (call_status->call_status >=
2054                                         BLUETOOTH_CALL_STATE_ERROR)) {
2055                                 BT_ERR("Unknown Call state");
2056                                 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
2057                         }
2058                 }
2059         }
2060
2061         FN_END;
2062         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2063 }
2064
2065 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
2066                                 unsigned int call_count)
2067 {
2068         int ret;
2069
2070         FN_START;
2071
2072         ret = bluetooth_telephony_call_swapped(call_list, call_count);
2073
2074         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2075                 BT_ERR("Failed = [%d]", ret);
2076                 return ret;
2077         }
2078
2079         telephony_info.call_count = call_count;
2080
2081         FN_END;
2082         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2083 }
2084
2085 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
2086                         const char *ph_number, unsigned int call_id,
2087                         unsigned int bt_audio)
2088 {
2089         GVariant *reply;
2090         GVariant *param;
2091         GError *err = NULL;
2092         const char *path = telephony_info.call_path;
2093         int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
2094
2095         FN_START;
2096
2097         BT_TELEPHONY_CHECK_INITIALIZED();
2098         BT_TELEPHONY_CHECK_ENABLED();
2099
2100         if (NULL == ph_number)
2101                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2102
2103         param = g_variant_new("(ssi)", path, ph_number, call_id);
2104         reply = __bluetooth_telephony_dbus_method_send(
2105                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2106                         "OutgoingCall", &err, param);
2107
2108         if (!reply) {
2109                 BT_ERR("Error returned in method call\n");
2110                 if (err) {
2111                         g_dbus_error_strip_remote_error(err);
2112                         ret = __bt_telephony_get_error(err->message);
2113                         g_error_free(err);
2114                         return ret;
2115                 }
2116                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2117         }
2118
2119         g_variant_unref(reply);
2120
2121         telephony_info.call_count++;
2122         BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
2123
2124         if (bt_audio) {
2125                 if (!bluetooth_telephony_is_sco_connected()) {
2126                         ret = bluetooth_telephony_audio_open();
2127                         if (ret != 0)
2128                                 BT_ERR(" Audio connection Failed = %d", ret);
2129                 }
2130         }
2131
2132         FN_END;
2133         return ret;
2134 }
2135
2136 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
2137                 const char *ph_number, unsigned int call_id)
2138 {
2139         GVariant *reply;
2140         GVariant *param;
2141         GError *err = NULL;
2142         const char *path = telephony_info.call_path;
2143         int ret;
2144
2145         FN_START;
2146
2147         BT_TELEPHONY_CHECK_INITIALIZED();
2148         BT_TELEPHONY_CHECK_ENABLED();
2149
2150         if (NULL == ph_number)
2151                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2152
2153         param = g_variant_new("(ssi)", path, ph_number, call_id);
2154         reply = __bluetooth_telephony_dbus_method_send(
2155                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2156                         "IncomingCall", &err, param);
2157
2158         if (!reply) {
2159                 BT_ERR("Error returned in method call\n");
2160                 if (err) {
2161                         g_dbus_error_strip_remote_error(err);
2162                         ret = __bt_telephony_get_error(err->message);
2163                         g_error_free(err);
2164                         return ret;
2165                 }
2166                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2167         }
2168
2169         g_variant_unref(reply);
2170         telephony_info.call_count++;
2171         BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
2172         FN_END;
2173         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2174 }
2175
2176 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(
2177                                                 unsigned short speaker_gain)
2178 {
2179         GVariant *reply;
2180         GVariant *param;
2181         GError *err = NULL;
2182         int ret;
2183
2184         FN_START;
2185
2186         BT_TELEPHONY_CHECK_INITIALIZED();
2187         BT_TELEPHONY_CHECK_ENABLED();
2188
2189         BT_DBG("set speaker_gain= [%d]", speaker_gain);
2190
2191         param = g_variant_new("(q)", speaker_gain);
2192         reply = __bluetooth_telephony_dbus_method_send(
2193                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2194                         "SetSpeakerGain", &err, param);
2195
2196         if (!reply) {
2197                 BT_ERR("Error returned in method call\n");
2198                 if (err) {
2199                         g_dbus_error_strip_remote_error(err);
2200                         ret = __bt_telephony_get_error(err->message);
2201                         g_error_free(err);
2202                         return ret;
2203                 }
2204                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2205         }
2206
2207         g_variant_unref(reply);
2208         FN_END;
2209         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2210 }
2211
2212 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(
2213                                                 unsigned int *speaker_gain)
2214 {
2215         GVariant *reply;
2216         GError *err = NULL;
2217         int ret;
2218         guint16 gain;
2219
2220         FN_START;
2221
2222         BT_TELEPHONY_CHECK_INITIALIZED();
2223         BT_TELEPHONY_CHECK_ENABLED();
2224
2225         reply = __bluetooth_telephony_dbus_method_send(
2226                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2227                         "GetSpeakerGain", &err, NULL);
2228
2229         if (!reply) {
2230                 BT_ERR("Error returned in method call\n");
2231                 if (err) {
2232                         g_dbus_error_strip_remote_error(err);
2233                         ret = __bt_telephony_get_error(err->message);
2234                         g_error_free(err);
2235                         return ret;
2236                 }
2237                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2238         }
2239         g_variant_get(reply, "(q)", &gain);
2240         *speaker_gain = gain;
2241         BT_DBG("Get speaker_gain= [%d]", *speaker_gain);
2242
2243         g_variant_unref(reply);
2244
2245         FN_END;
2246         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2247 }
2248
2249 BT_EXPORT_API int bluetooth_telephony_is_connected(gboolean *ag_connected)
2250 {
2251         GVariant *reply;
2252         GError *err = NULL;
2253         int ret;
2254         gboolean ag_connected_from_bt_agent;
2255
2256         BT_CHECK_ENABLED(return);
2257
2258         reply = __bluetooth_telephony_dbus_method_send(
2259                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2260                         "IsConnected", &err, NULL);
2261
2262         if (!reply) {
2263                 BT_ERR("Error returned in method call\n");
2264                 if (err) {
2265                         g_dbus_error_strip_remote_error(err);
2266                         ret = __bt_telephony_get_error(err->message);
2267                         g_error_free(err);
2268                         return ret;
2269                 }
2270                 return BLUETOOTH_ERROR_INTERNAL;
2271         }
2272         g_variant_get(reply, "(b)", &ag_connected_from_bt_agent);
2273         *ag_connected = ag_connected_from_bt_agent;
2274
2275         BT_DBG("Conn Status: %s", *ag_connected ? "Connected" : "Disconnected");
2276
2277         g_variant_unref(reply);
2278
2279         return BLUETOOTH_ERROR_NONE;
2280 }
2281
2282 BT_EXPORT_API int bluetooth_telephony_set_active_headset(const char *remote_addr)
2283 {
2284 #ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
2285         GVariant *reply;
2286         GVariant *param;
2287         GError *err = NULL;
2288         int ret;
2289
2290         BT_CHECK_ENABLED(return);
2291
2292         if (NULL == remote_addr)
2293                 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2294
2295         param = g_variant_new("(s)", remote_addr);
2296         reply = __bluetooth_telephony_dbus_method_send(
2297                         HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2298                         "SwapHeadset", &err, param);
2299
2300         if (!reply) {
2301                 BT_ERR("Error returned in method call\n");
2302                 if (err) {
2303                         g_dbus_error_strip_remote_error(err);
2304                         ret = __bt_telephony_get_error(err->message);
2305                         g_error_free(err);
2306                         return ret;
2307                 }
2308                 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2309         }
2310
2311         g_variant_unref(reply);
2312         return BLUETOOTH_TELEPHONY_ERROR_NONE;
2313 #else
2314         return BLUETOOTH_ERROR_NOT_SUPPORT;
2315 #endif
2316 }
2317
2318 static void __bt_telephony_adapter_filter(GDBusConnection *connection,
2319                                         const gchar *sender_name,
2320                                         const gchar *object_path,
2321                                         const gchar *interface_name,
2322                                         const gchar *signal_name,
2323                                         GVariant *parameters,
2324                                         gpointer user_data)
2325 {
2326         FN_START;
2327         int ret;
2328         char *path = NULL;
2329
2330         if (strcasecmp(signal_name, "InterfacesAdded") == 0) {
2331                 GVariant *optional_param = NULL;
2332
2333                 g_variant_get(parameters, "(&o@a{sa{sv}})",
2334                                                         &path, &optional_param);
2335
2336                 if (!path) {
2337                         BT_ERR("Invalid adapter path");
2338                         return;
2339                 }
2340
2341                 BT_INFO("Adapter Path = [%s]", path);
2342                 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
2343                         if (__bt_telephony_get_src_addr(optional_param))
2344                                 BT_ERR("Fail to get the local adapter address");
2345
2346                         ret = __bluetooth_telephony_register();
2347                         if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2348                                 BT_ERR("__bluetooth_telephony_register failed");
2349                 }
2350         }
2351
2352         FN_END;
2353 }
2354
2355 static int __bt_telephony_get_src_addr(GVariant *value)
2356 {
2357         GVariantIter iter;
2358         GVariant *param = NULL;
2359         FN_START;
2360
2361         /* signature a{sa{sv}} */
2362         g_variant_iter_init(&iter, value);
2363         while ((param = g_variant_iter_next_value(&iter))) {
2364                 char *interface_name;
2365                 GVariant *interface_var = NULL;
2366                 GVariant *param_inner = NULL;
2367
2368                 g_variant_get(param, "{&s*}", &interface_name, &interface_var);
2369                 g_variant_unref(param);
2370
2371                 BT_DBG("interface_name: %s", interface_name);
2372                 /* format of interface_var: a{sv}*/
2373                 if (strcasecmp(interface_name, BLUEZ_ADAPTER_INTERFACE) == 0) {
2374                         GVariantIter iter_inner;
2375
2376                         g_variant_iter_init(&iter_inner, interface_var);
2377                         while ((param_inner = g_variant_iter_next_value(&iter_inner))) {
2378                                 char *property_name;
2379                                 GVariant *property_var;
2380
2381                                 g_variant_get(param_inner, "{&sv}",
2382                                                 &property_name,
2383                                                 &property_var);
2384                                 g_variant_unref(param_inner);
2385
2386                                 if (strcasecmp(property_name, "Address") == 0) {
2387                                         const gchar *bd_addr;
2388
2389                                         bd_addr = g_variant_get_string(
2390                                                                 property_var,
2391                                                                 NULL);
2392                                         src_addr = g_strdup(bd_addr);
2393                                         BT_DBG("Address: %s", src_addr);
2394
2395                                         g_variant_unref(interface_var);
2396                                         g_variant_unref(property_var);
2397                                         goto done;
2398                                 }
2399                                 g_variant_unref(property_var);
2400                         }
2401                 }
2402                 g_variant_unref(interface_var);
2403         }
2404
2405 done:
2406         return BLUETOOTH_ERROR_NONE;
2407 }