9555899aba26096dcbf044904e1121b7ba58c904
[platform/core/connectivity/bluetooth-agent.git] / ag-agent / bluetooth-ag-agent.c
1 /*
2  * Bluetooth-ag-agent
3  *
4  * Copyright (c) 2014 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:     Hocheol Seo <hocheol.seo@samsung.com>
7  *              Chethan T N <chethan.tn@samsung.com>
8  *              Chanyeol Park <chanyeol.park@samsung.com>
9  *              Rakesh MK <rakesh.mk@samsung.com>
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *              http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  */
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <signal.h>
27 #include <sys/poll.h>
28 #include <gio/gunixfdlist.h>
29 #include <bundle_internal.h>
30 #include "bluetooth-ag-agent.h"
31 #include "bluetooth-ag-handler.h"
32
33 #include <TapiUtility.h>
34 #include <ITapiSim.h>
35 #include <ITapiModem.h>
36 #include <TelNetwork.h>
37 #include <app.h>
38 #include <aul.h>
39 #include <system_info.h>
40
41 #include "contacts.h"
42 #include "appsvc.h"
43
44 static GMainLoop *gmain_loop = NULL;
45 static GDBusProxy *service_gproxy;
46 static int owner_sig_id = -1;
47 static int name_owner_sig_id = -1;
48 GDBusConnection *ag_dbus_conn = NULL;
49 gchar *remote_dev_path = NULL;
50 gboolean wbs_en;
51 uint16_t hfp_ver;
52 uint16_t hsp_ver;
53 static TapiHandle *tapi_handle;
54 extern wbs_options wbs_opts;
55 GSList *active_devices = NULL;
56 static gchar *local_addr = NULL;
57 static GDBusProxy *app_gproxy;
58 static gboolean call_launch_requested = FALSE;
59 static gchar* sco_owner = NULL;
60 static guint sco_open_timer_id = 0;
61 static gboolean sco_open_request = FALSE;
62 static guint hf_bluez_id;
63 static guint hs_bluez_id;
64 static guint app_id;
65 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
66 static int media_sig_id = -1;
67 static int media_state_sig_id = -1;
68 static bt_ag_media_transport_state_t transport_state;
69 #endif
70
71 #define HSP_AG_UUID "00001112-0000-1000-8000-00805f9b34fb"
72 #define HFP_AG_UUID "0000111f-0000-1000-8000-00805f9b34fb"
73 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
74 #define A2DP_SINK_UUID "0000110b-0000-1000-8000-00805f9b34fb"
75 #endif
76 #define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
77
78 #ifdef TIZEN_FEATURE_BT_LUNAR_DEVICE
79 #define VCONF_KEY_BT_LUNAR_ENABLED "db/wms/bt_loop_device_hfp_connected"
80 #endif
81
82 #if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
83 #define CALL_APP_ID "org.tizen.call-ui"
84 #endif
85
86 #if defined(TIZEN_SUPPORT_DUAL_HF)
87 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
88 #define MAX_CONNECTED_DEVICES 2
89 #else
90 #define MAX_CONNECTED_DEVICES 1
91 #endif
92
93 #define BT_AG_SIG_NUM 3
94 static struct sigaction bt_ag_sigoldact[BT_AG_SIG_NUM];
95 static int bt_ag_sig_to_handle[] = { SIGABRT, SIGSEGV, SIGTERM };
96
97 /*Below Inrospection data is exposed to bluez from agent*/
98 static const gchar ag_agent_bluez_introspection_xml[] =
99 "<node name='/'>"
100 " <interface name='org.bluez.Profile1'>"
101 "     <method name='NewConnection'>"
102 "          <arg type='o' name='device' direction='in'/>"
103 "          <arg type='h' name='fd' direction='in'/>"
104 "          <arg type='a{sv}' name='options' direction='in'/>"
105 "     </method>"
106 "     <method name='RequestDisconnection'>"
107 "          <arg type='o' name='device' direction='in'/>"
108 "     </method>"
109 " </interface>"
110 "</node>";
111
112 /*Below Introspection data is exposed to application from agent*/
113 static const gchar ag_agent_app_introspection_xml[] =
114 "<node name='/'>"
115 "  <interface name='Org.Hfp.App.Interface'>"
116 "     <method name='RegisterApplication'>"
117 "          <arg type='s' name='path' direction='in'/>"
118 "          <arg type='s' name='address' direction='in'/>"
119 "     </method>"
120 "     <method name='UnregisterApplication'>"
121 "          <arg type='s' name='path' direction='in'/>"
122 "     </method>"
123 "     <method name='IncomingCall'>"
124 "          <arg type='s' name='path' direction='in'/>"
125 "          <arg type='s' name='number' direction='in'/>"
126 "          <arg type='i' name='id' direction='in'/>"
127 "     </method>"
128 "     <method name='OutgoingCall'>"
129 "          <arg type='s' name='path' direction='in'/>"
130 "          <arg type='s' name='number' direction='in'/>"
131 "          <arg type='i' name='id' direction='in'/>"
132 "     </method>"
133 "     <method name='ChangeCallStatus'>"
134 "          <arg type='s' name='path' direction='in'/>"
135 "          <arg type='s' name='number' direction='in'/>"
136 "          <arg type='i' name='status' direction='in'/>"
137 "          <arg type='i' name='id' direction='in'/>"
138 "     </method>"
139 "     <method name='GetProperties'>"
140 "               <arg type='a{sv}' name='properties' direction='out'/>"
141 "     </method>"
142 "       <method name='Disconnect'>"
143 "       </method>"
144 "       <method name='IsConnected'>"
145 "               <arg type='b' name='connected' direction='out'/>"
146 "       </method>"
147 "       <method name='IndicateCall'>"
148 "       </method>"
149 "       <method name='CancelCall'>"
150 "       </method>"
151 "       <method name='Play'>"
152 "       </method>"
153 "       <method name='Stop'>"
154 "       </method>"
155 "       <method name='IsPlaying'>"
156 "       <arg type='b' name='playing' direction='out'/>"
157 "       </method>"
158 "       <method name='GetSpeakerGain'>"
159 "               <arg type='q' name='gain' direction='out'/>"
160 "       </method>"
161 "       <method name='GetMicrophoneGain'>"
162 "               <arg type='q' name='gain' direction='out'/>"
163 "       </method>"
164 "       <method name='SetSpeakerGain'>"
165 "               <arg type='q' name='gain' direction='in'/>"
166 "       </method>"
167 "       <method name='SetMicrophoneGain'>"
168 "               <arg type='q' name='gain' direction='in'/>"
169 "       </method>"
170 "       <method name='SetVoiceDial'>"
171 "               <arg type='b' name='enable' direction='in'/>"
172 "       </method>"
173 "       <method name='CheckPrivilege'>"
174 "       </method>"
175 "     <method name='SwapHeadset'>"
176 "          <arg type='s' name='remote_addr' direction='in'/>"
177 "     </method>"
178 "  </interface>"
179 "</node>";
180
181 struct event {
182         const char *cmd;
183         int (*callback)(bt_ag_info_t *hs, const char *buf);
184 };
185
186 struct sco_socket_addr {
187         sa_family_t     sco_family;
188         bt_addr         sco_bdaddr;
189 };
190
191 typedef struct {
192         uint16_t setting;
193 } bt_voice;
194
195 struct ag_codec {
196         bt_ag_info_t *bt_ag_info;
197         char *codec_status;
198 };
199
200 bt_ag_status_t ag = {
201         .telephony_ready = FALSE,
202         .features = 0,
203         .er_mode = 3,
204         .er_ind = 0,
205         .rh = BT_RSP_HOLD_NOT_SUPPORTED,
206         .number = NULL,
207         .number_type = 0,
208         .ring_timer = 0,
209         .sdp_features = 0,
210 };
211 static void __bt_ag_agent_sigterm_handler(int signo);
212 static gboolean __bt_ag_agent_connection(gint32 fd, const gchar *device_path,
213                                                 const gchar *object_path);
214 static gboolean __bt_ag_agent_connection_release(bt_ag_info_t *hs);
215 static gboolean __bt_ag_event_handler(GIOChannel *channel, GIOCondition cond,
216         void *user_data);
217 static int __bt_ag_sco_connect(bt_ag_info_t *hs);
218 void _bt_ag_set_headset_state(bt_ag_info_t *hs, hs_state_t state);
219 static void __bt_ag_agent_reg_sim_event(TapiHandle *handle, void *user_data);
220 static void __bt_ag_agent_dereg_sim_event(TapiHandle *handle);
221 static void __bt_ag_name_owner_changed_cb(GDBusConnection *connection,
222                                         const gchar *sender_name,
223                                         const gchar *object_path,
224                                         const gchar *interface_name,
225                                         const gchar *signal_name,
226                                         GVariant *parameters,
227                                         gpointer user_data);
228
229 static void __bt_convert_addr_type_to_rev_string(char *address,
230                                 unsigned char *addr)
231 {
232         ret_if(address == NULL);
233         ret_if(addr == NULL);
234
235         g_snprintf(address, BT_ADDRESS_STRING_SIZE,
236                         "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
237                         addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
238 }
239
240 static GDBusProxy *__bt_ag_gdbus_init_service_proxy(const gchar *service,
241                                 const gchar *path, const gchar *interface)
242 {
243         FN_START;
244
245         GDBusProxy *proxy;
246         GError *err = NULL;
247
248         if (ag_dbus_conn == NULL)
249                 ag_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
250
251         if (!ag_dbus_conn) {
252                 if (err) {
253                         ERR("Unable to connect to gdbus: %s", err->message);
254                         g_clear_error(&err);
255                 }
256                 return NULL;
257         }
258
259         proxy =  g_dbus_proxy_new_sync(ag_dbus_conn,
260                         G_DBUS_PROXY_FLAGS_NONE, NULL,
261                         service, path,
262                         interface, NULL, &err);
263
264         if (!proxy) {
265                 if (err) {
266                         ERR("Unable to create proxy: %s", err->message);
267                         g_clear_error(&err);
268                 }
269                 return NULL;
270         }
271
272         FN_END;
273         return proxy;
274 }
275
276 static GDBusProxy *__bt_ag_gdbus_get_app_proxy(const gchar *service,
277                                 const gchar *path, const gchar *interface)
278 {
279         return (app_gproxy) ? app_gproxy :
280                         __bt_ag_gdbus_init_service_proxy(service,
281                                         path, interface);
282 }
283
284 static int __bt_ag_agent_gdbus_method_send(const char *service,
285                                 const gchar *path, const char *interface,
286                                 const char *method, gboolean response,
287                                 GVariant *parameters)
288 {
289         FN_START;
290
291         GVariant *ret;
292         GDBusProxy *proxy;
293         GError *error = NULL;
294
295         proxy = __bt_ag_gdbus_get_app_proxy(service, path, interface);
296         if (!proxy)
297                 return BT_HFP_AGENT_ERROR_INTERNAL;
298
299         if (response) {
300                 ret = g_dbus_proxy_call_sync(proxy,
301                                         method, parameters,
302                                         G_DBUS_CALL_FLAGS_NONE, -1,
303                                         NULL, &error);
304                 if (ret == NULL) {
305                         /* dBUS-RPC is failed */
306                         ERR("dBUS-RPC is failed");
307                         if (error != NULL) {
308                                 /* dBUS gives error cause */
309                                 ERR("D-Bus API failure: errCode[%x], message[%s]",
310                                         error->code, error->message);
311
312                                 g_clear_error(&error);
313                         }
314                         return BT_HFP_AGENT_ERROR_INTERNAL;
315                 }
316
317                 g_variant_unref(ret);
318         } else {
319                 g_dbus_proxy_call(proxy,
320                                         method, parameters,
321                                         G_DBUS_CALL_FLAGS_NONE, 2000,
322                                         NULL, NULL, NULL);
323         }
324         return BT_HFP_AGENT_ERROR_NONE;
325 }
326
327 gboolean _bt_ag_agent_emit_signal(
328                                 GDBusConnection *connection,
329                                 const char *path,
330                                 const char *interface,
331                                 const char *name,
332                                 GVariant *property)
333 {
334         FN_START;
335
336         GError *error = NULL;
337         gboolean ret;
338         ret =  g_dbus_connection_emit_signal(connection,
339                                 NULL, path, interface,
340                                 name, property,
341                                 &error);
342         if (!ret) {
343                 if (error != NULL) {
344                         /* dBUS gives error cause */
345                         ERR("D-Bus API failure: errCode[%x], message[%s]",
346                                 error->code, error->message);
347                         g_clear_error(&error);
348                 }
349         }
350         INFO_C("Emit Signal done = [%s]", name);
351
352         FN_END;
353         return ret;
354 }
355
356 gboolean _bt_ag_agent_emit_property_changed(
357                                 GDBusConnection *connection,
358                                 const char *path,
359                                 const char *interface,
360                                 const char *name,
361                                 GVariant *property)
362 {
363         FN_START;
364
365         gboolean ret;
366         GVariant *var_data;
367
368         var_data = g_variant_new("(sv)",        name, property);
369
370         ret =  _bt_ag_agent_emit_signal(connection,
371                                 path, interface,
372                                 "PropertyChanged", var_data);
373         FN_END;
374         return ret;
375 }
376
377 static void __bt_ag_agent_start_watch(bt_ag_info_t *bt_ag_info)
378 {
379         bt_ag_info->watch_id = g_io_add_watch(bt_ag_info->io_chan,
380                         G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
381                         (GIOFunc) __bt_ag_event_handler, bt_ag_info);
382 }
383
384 static void __bt_ag_agent_remove_watch(guint *watch_id)
385 {
386         DBG("Remove IO watch ID %d", *watch_id);
387         if (*watch_id > 0) {
388                 g_source_remove(*watch_id);
389                 *watch_id = 0;
390         }
391 }
392
393 #if defined(TIZEN_SUPPORT_DUAL_HF)
394 gboolean __bt_ag_agent_is_companion_device(const char *addr)
395 {
396 #if defined(TIZEN_PROFILE_WEARABLE)
397         char *host_device_address = NULL;
398         host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
399
400         if (!host_device_address) {
401                 INFO("Failed to get a companion device address");
402                 return FALSE;
403         }
404
405         if (g_strcmp0(host_device_address, addr) == 0) {
406                 INFO("addr[%s] is companion device", addr);
407                 return TRUE;
408         }
409
410         return FALSE;
411 #else
412         /* TODO : Need to add companion device check condition for Phone models */
413         return FALSE;
414 #endif
415 }
416
417 void __bt_convert_device_path_to_address(const gchar *device_path,
418                                                 char *device_address)
419 {
420         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
421         char *dev_addr;
422
423         ret_if(device_path == NULL);
424         ret_if(device_address == NULL);
425
426         dev_addr = strstr(device_path, "dev_");
427         if (dev_addr != NULL) {
428                 char *pos = NULL;
429                 dev_addr += 4;
430                 g_strlcpy(address, dev_addr, sizeof(address));
431
432                 while ((pos = strchr(address, '_')) != NULL)
433                         *pos = ':';
434
435                 g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE);
436         }
437 }
438
439 static gboolean  __bt_ag_agent_is_companion_device_connected(void)
440 {
441         GSList *l;
442
443         for (l = active_devices ; l; l = l->next) {
444                 bt_ag_info_t *data = l->data;
445
446                 if (data->is_companion_device) {
447                         DBG("Companion device found");
448                         return TRUE;
449                 }
450         }
451
452         return FALSE;
453 }
454
455 gboolean __bt_ag_agent_check_dual_hf_condition(const gchar *device_path)
456 {
457         char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
458         gboolean is_companion_device;
459
460         __bt_convert_device_path_to_address(device_path, device_address);
461         is_companion_device = __bt_ag_agent_is_companion_device(device_address);
462
463         DBG(" device_address[%s]", device_address);
464         DBG(" is_companion_device[%d]", is_companion_device);
465
466         if (__bt_ag_agent_is_companion_device_connected()) {
467                 if (is_companion_device)
468                         return FALSE;
469         } else {
470                 if (!is_companion_device)
471                         return FALSE;
472         }
473         return TRUE;
474 }
475 #endif /* TIZEN_SUPPORT_DUAL_HF */
476
477 static gboolean __bt_is_phone_locked(int *phone_lock_state)
478 {
479         FN_START;
480         int ret;
481
482         if (NULL == phone_lock_state)
483                 return FALSE;
484
485         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, phone_lock_state);
486         if (ret != 0) {
487                 ERR("Failed to read  [%s]\n", VCONFKEY_IDLE_LOCK_STATE);
488                 return FALSE;
489         }
490
491         FN_END;
492         return TRUE;
493 }
494
495 static gboolean __bt_get_outgoing_callapp_type(int *callapp_type)
496 {
497         FN_START;
498
499         if (NULL == callapp_type)
500                 return FALSE;
501
502 #if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
503         *callapp_type = BT_VOICE_CALL;
504         FN_END;
505         return TRUE;
506 #else
507 #if 0
508         int ret;
509         ret = vconf_get_int(
510                         VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT,
511                         callapp_type);
512         if (ret != 0) {
513                 ERR("Failed to read  [%s]\n",
514                         VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT);
515                 return FALSE;
516         }
517
518         INFO(" [%s] = [%d]\n",
519                 VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT, *callapp_type);
520 #endif
521         /* The vconf value does not include in platform. */
522         *callapp_type = BT_VOICE_CALL;
523         FN_END;
524         return TRUE;
525 #endif
526 }
527
528 static gboolean __bt_get_outgoing_call_condition(int *condition)
529 {
530         FN_START;
531
532         if (NULL == condition)
533                 return FALSE;
534
535 #if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
536         *condition = BT_MO_ONLY_UNLOCKED;
537         FN_END;
538         return TRUE;
539 #else
540 #if 0
541         int ret;
542         ret = vconf_get_int(
543                         VCONFKEY_CISSAPPL_OUTGOING_CALL_CONDITIONS_INT,
544                         condition);
545         if (ret != 0) {
546                 ERR("Failed to read  [%s]\n",
547                         VCONFKEY_CISSAPPL_OUTGOING_CALL_CONDITIONS_INT);
548                 return FALSE;
549         }
550 #endif
551         /* The vconf value does not include in platform. */
552         *condition = BT_MO_ONLY_UNLOCKED;
553         FN_END;
554         return TRUE;
555 #endif
556 }
557
558 #if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_TELEPHONY_ENABLED)
559 static gboolean  __bt_ag_agent_launch_call_app(const char *number)
560 {
561         FN_START;
562         bundle *b;
563
564         DBG_SECURE("number(%s)", number);
565
566         b = bundle_create();
567         if (NULL == b) {
568                 ERR("bundle_create() Failed");
569                 return FALSE;
570         }
571
572         bundle_add(b, "launch-type", "MO");
573         bundle_add(b, "dial-type", "HEADSET");
574
575         if (strlen(number) != 0)
576                 bundle_add(b, "number", number);
577
578         aul_launch_app_async(CALL_APP_ID, b);
579         bundle_free(b);
580
581         FN_END;
582         return TRUE;
583 }
584 #endif
585
586 static void *__bt_ag_agent_launch_call_req(void *arg)
587 {
588         FN_START;
589         bundle *b = (bundle *)arg;
590         if (appsvc_run_service(b, 0, NULL, NULL) < 0)
591                 ERR("Unable to run app svc");
592         bundle_free(b);
593         call_launch_requested = FALSE;
594         FN_END;
595         return NULL;
596 }
597
598 static gboolean __bt_ag_agent_make_call(const char *number)
599 {
600         FN_START;
601
602 #if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
603         FN_END;
604         return __bt_ag_agent_launch_call_app(number);
605 #else
606         char telnum[BT_MAX_TEL_NUM_STRING];
607         bundle *b;
608         pthread_t thread_id;
609
610         if (call_launch_requested == TRUE) {
611                 DBG("Launch request is in progress");
612                 return TRUE;
613         }
614
615         b = bundle_create();
616         if (NULL == b)
617                 return FALSE;
618
619         appsvc_set_operation(b, APPSVC_OPERATION_CALL);
620         snprintf(telnum, sizeof(telnum), "tel:%s", number);
621         appsvc_set_uri(b, telnum);
622         appsvc_add_data(b, "ctindex", "-1");
623
624         call_launch_requested = TRUE;
625         if (pthread_create(&thread_id, NULL,
626                         (void *)&__bt_ag_agent_launch_call_req,
627                                         (void *)b) < 0) {
628                 ERR("pthread_create() is failed");
629                 call_launch_requested = FALSE;
630                 return FALSE;
631         }
632         if (pthread_detach(thread_id) < 0)
633                 ERR("pthread_detach() is failed");
634
635         FN_END;
636         return TRUE;
637 #endif
638 }
639
640 static gboolean __bt_ag_agent_make_video_call(const char *mo_number)
641 {
642         FN_START;
643         bundle *kb;
644
645         kb = bundle_create();
646         if (NULL == kb)
647                 return FALSE;
648
649         bundle_add(kb, "KEY_CALL_TYPE", "MO");
650         bundle_add(kb, "number", mo_number);
651         aul_launch_app("org.tizen.vtmain", kb);
652         bundle_free(kb);
653
654         FN_END;
655         return TRUE;
656 }
657
658 gboolean _bt_ag_agent_answer_call(unsigned int call_id,
659                                 const gchar *path, const gchar *sender)
660 {
661         FN_START;
662
663         if (path == NULL || sender == NULL) {
664                 DBG("Invalid Arguments");
665                 return FALSE;
666         }
667
668         DBG("Application path = %s", path);
669         DBG("Call Id = %d", call_id);
670         DBG("Sender = %s", sender);
671
672         _bt_ag_agent_emit_signal(ag_dbus_conn, path,
673                                         BT_AG_SERVICE_NAME, "Answer",
674                                         g_variant_new("(u)", call_id));
675         FN_END;
676         return TRUE;
677 }
678
679 gboolean _bt_ag_agent_reject_call(unsigned int call_id,
680                                 const gchar *path, const gchar *sender)
681 {
682         FN_START;
683
684         if (path == NULL || sender == NULL) {
685                 DBG("Invalid Arguments");
686                 return FALSE;
687         }
688
689         DBG("Application path = %s", path);
690         DBG("Call Id = %d", call_id);
691         DBG("Sender = %s", sender);
692
693         _bt_ag_agent_emit_signal(ag_dbus_conn, path,
694                                         BT_AG_SERVICE_NAME, "Reject",
695                                         g_variant_new("(u)", call_id));
696         FN_END;
697         return TRUE;
698 }
699
700 gboolean _bt_ag_agent_release_call(unsigned int call_id,
701                                 const gchar *path, const gchar *sender)
702 {
703         FN_START;
704
705         if (path == NULL || sender == NULL) {
706                 DBG("Invalid Arguments");
707                 return FALSE;
708         }
709
710         DBG("Application path = %s", path);
711         DBG("Call Id = %d", call_id);
712         DBG("Sender = %s", sender);
713
714         _bt_ag_agent_emit_signal(ag_dbus_conn, path,
715                                         BT_AG_SERVICE_NAME, "Release",
716                                         g_variant_new("(u)", call_id));
717
718         FN_END;
719         return TRUE;
720 }
721
722 bt_hfp_agent_error_t _bt_ag_agent_dial_num(const gchar *number, guint flags)
723 {
724         bt_hfp_agent_error_t error_code = BT_HFP_AGENT_ERROR_NONE;
725         int callapp_type;
726         int phone_lock_state;
727         int condition;
728
729         FN_START;
730
731         if (number == NULL) {
732                 ERR("Invalid Argument");
733                 error_code = BT_HFP_AGENT_ERROR_INVALID_PARAM;
734                 goto fail;
735         }
736
737         DBG("Number = %s", number);
738         DBG("flags = %d", flags);
739
740         if (!__bt_is_phone_locked(&phone_lock_state)) {
741                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
742                 goto fail;
743         }
744
745         if (!__bt_get_outgoing_callapp_type(&callapp_type)) {
746                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
747                 goto fail;
748         }
749
750         if (!__bt_get_outgoing_call_condition(&condition)) {
751                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
752                 goto fail;
753         }
754
755         if (condition == BT_MO_ONLY_UNLOCKED && phone_lock_state ==
756                 VCONFKEY_IDLE_LOCK) {
757                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
758                 goto fail;
759         }
760
761         if (callapp_type == BT_VIDEO_CALL) {
762                 if (!__bt_ag_agent_make_video_call(number)) {
763                         ERR("Problem launching application");
764                         error_code = BT_HFP_AGENT_ERROR_INTERNAL;
765                         goto fail;
766                 }
767         } else {
768                 if (!__bt_ag_agent_make_call(number)) {
769                         ERR("Problem launching application");
770                         error_code = BT_HFP_AGENT_ERROR_INTERNAL;
771                         goto fail;
772                 }
773         }
774
775 fail:
776         FN_END;
777         return error_code;
778 }
779
780 bt_hfp_agent_error_t _bt_ag_agent_dial_memory(unsigned int location)
781 {
782         bt_hfp_agent_error_t error_code = BT_HFP_AGENT_ERROR_NONE;
783         char *number = NULL;
784         contacts_filter_h filter = NULL;
785         contacts_query_h query = NULL;
786         contacts_list_h list = NULL;
787         contacts_record_h record = NULL;
788         unsigned int projections[] = {
789                 _contacts_speeddial.number,
790         };
791
792         FN_START;
793
794         DBG("location = %d", location);
795
796         /*Get number from contacts location*/
797         if (contacts_connect() != CONTACTS_ERROR_NONE) {
798                 ERR(" contacts_connect failed");
799                 return BT_HFP_AGENT_ERROR_INTERNAL;
800         }
801
802         contacts_filter_create(_contacts_speeddial._uri, &filter);
803
804         if (filter == NULL)
805                 goto done;
806
807         if (contacts_filter_add_int(filter,
808                 _contacts_speeddial.speeddial_number,
809                 CONTACTS_MATCH_EQUAL, location) !=
810                 CONTACTS_ERROR_NONE) {
811                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
812                 goto done;
813         }
814
815         contacts_query_create(_contacts_speeddial._uri, &query);
816
817         if (query == NULL)
818                 goto done;
819
820         contacts_query_set_filter(query, filter);
821
822         if (contacts_query_set_projection(query, projections,
823                                 sizeof(projections)/sizeof(unsigned int)) !=
824                                 CONTACTS_ERROR_NONE) {
825                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
826                 goto done;
827         }
828
829         if (contacts_db_get_records_with_query(query, 0, 1, &list) !=
830                                 CONTACTS_ERROR_NONE) {
831                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
832                 goto done;
833         }
834
835         if (contacts_list_first(list) != CONTACTS_ERROR_NONE) {
836                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
837                 goto done;
838         }
839
840         if (contacts_list_get_current_record_p(list, &record) !=
841                                 CONTACTS_ERROR_NONE) {
842                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
843                 goto done;
844         }
845
846         if (record == NULL)
847                 goto done;
848
849         if (contacts_record_get_str(record, _contacts_speeddial.number, &number)
850                 != CONTACTS_ERROR_NONE) {
851                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
852                 goto done;
853         }
854
855         if (number == NULL) {
856                 ERR("No number at the location");
857                 error_code = BT_HFP_AGENT_ERROR_INVALID_MEMORY_INDEX;
858                 goto done;
859         }
860
861         DBG("number %s", number);
862
863         /*Make Voice call*/
864         if (!__bt_ag_agent_make_call(number)) {
865                 ERR("Problem launching application");
866                 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
867         }
868
869         g_free(number);
870 done:
871         if (list != NULL)
872                 contacts_list_destroy(list, TRUE);
873
874         if (filter != NULL)
875                 contacts_filter_destroy(filter);
876
877         if (query != NULL)
878                 contacts_query_destroy(query);
879
880         contacts_disconnect();
881
882         FN_END;
883
884         return error_code;
885 }
886
887 bt_hfp_agent_error_t _bt_ag_agent_send_dtmf(const gchar *dtmf,
888                                 const gchar *path, const gchar *sender)
889 {
890         bt_hfp_agent_error_t ret;
891
892         FN_START;
893
894         if (dtmf == NULL || path == NULL || sender == NULL) {
895                 ERR("Invalid Argument");
896                 return FALSE;
897         }
898
899         DBG("Dtmf = %s", dtmf);
900         DBG("Application path = %s", path);
901         DBG("Sender = %s", sender);
902
903         ret = __bt_ag_agent_gdbus_method_send(sender,
904                                 path, TELEPHONY_APP_INTERFACE,
905                                 "SendDtmf", FALSE,
906                                 g_variant_new("(s)", dtmf));
907
908         return ret;
909 }
910
911 gboolean _bt_ag_agent_threeway_call(unsigned int chld_value,
912                                 const gchar *path, const gchar *sender)
913 {
914         FN_START;
915
916         if (path == NULL || sender == NULL) {
917                 DBG("Invalid Arguments");
918                 return FALSE;
919         }
920
921         DBG("Application path = %s", path);
922         DBG("Value = %d", chld_value);
923         DBG("Sender = %s", sender);
924
925 #if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
926         /* Check if AG supports (i.e. ag_chld_str = "0,1,2") the requested CHLD;
927         if not return FALSE */
928         if (chld_value != 0 && chld_value != 1 && chld_value != 2)
929                 return FALSE;
930 #else
931         if (chld_value != 0 && chld_value != 1 && chld_value != 2 &&
932                                 chld_value != 3)
933                 return FALSE;
934 #endif
935         _bt_ag_agent_emit_signal(ag_dbus_conn, path,
936                                         BT_AG_SERVICE_NAME, "Threeway",
937                                         g_variant_new("(u)", chld_value));
938         FN_END;
939         return TRUE;
940 }
941
942 bt_hfp_agent_error_t _bt_ag_agent_dial_last_num(void *device)
943 {
944         bt_hfp_agent_error_t err_code = BT_HFP_AGENT_ERROR_NONE;
945         char *last_num = NULL;
946         int type;
947         int callapp_type;
948         int phone_lock_state;
949         int condition;
950         contacts_list_h list = NULL;
951         contacts_query_h query = NULL;
952         contacts_filter_h filter = NULL;
953         contacts_record_h record = NULL;
954         unsigned int projections[] = {
955                 _contacts_phone_log.address,
956                 _contacts_phone_log.log_type,
957         };
958
959         FN_START;
960
961         if (contacts_connect() != CONTACTS_ERROR_NONE) {
962                 ERR(" contacts_connect failed");
963                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
964                 return err_code;
965         }
966
967         contacts_filter_create(_contacts_phone_log._uri, &filter);
968
969         if (filter == NULL)
970                 goto done;
971
972         if (contacts_filter_add_int(filter, _contacts_phone_log.log_type,
973                                 CONTACTS_MATCH_EQUAL,
974                                 CONTACTS_PLOG_TYPE_VOICE_OUTGOING) !=
975                                 CONTACTS_ERROR_NONE) {
976                 ERR(" contacts_filter_add_int failed");
977                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
978                 goto done;
979         }
980
981         if (contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_OR) !=
982                                 CONTACTS_ERROR_NONE) {
983                 ERR(" contacts_filter_add_operator failed");
984                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
985                 goto done;
986         }
987
988         if (contacts_filter_add_int(filter, _contacts_phone_log.log_type,
989                                 CONTACTS_MATCH_EQUAL,
990                                 CONTACTS_PLOG_TYPE_VIDEO_OUTGOING) !=
991                                 CONTACTS_ERROR_NONE) {
992                 ERR(" contacts_filter_add_int failed");
993                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
994                 goto done;
995         }
996
997         contacts_query_create(_contacts_phone_log._uri, &query);
998
999         if (query == NULL)
1000                 goto done;
1001
1002         contacts_query_set_filter(query, filter);
1003
1004         if (contacts_query_set_projection(query, projections,
1005                                 sizeof(projections)/sizeof(unsigned int)) !=
1006                                 CONTACTS_ERROR_NONE) {
1007                 ERR(" contacts_query_set_projection failed");
1008                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1009                 goto done;
1010         }
1011
1012         if (contacts_query_set_sort(query, _contacts_phone_log.log_time, false)
1013                 != CONTACTS_ERROR_NONE) {
1014                 ERR(" contacts_query_set_sort failed");
1015                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1016                 goto done;
1017         }
1018
1019         if (contacts_db_get_records_with_query(query, 0, 1, &list)  !=
1020                                 CONTACTS_ERROR_NONE) {
1021                 ERR(" contacts_db_get_records_with_query failed");
1022                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1023                 goto done;
1024         }
1025
1026         if (contacts_list_first(list)  != CONTACTS_ERROR_NONE) {
1027                 ERR(" contacts_list_first failed");
1028                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1029                 goto done;
1030         }
1031
1032         if (contacts_list_get_current_record_p(list, &record)  !=
1033                                 CONTACTS_ERROR_NONE) {
1034                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1035                 goto done;
1036         }
1037
1038         if (record == NULL)
1039                 goto done;
1040
1041         if (contacts_record_get_str(record, _contacts_phone_log.address,
1042                                 &last_num) != CONTACTS_ERROR_NONE) {
1043                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1044                 goto done;
1045         }
1046
1047         if (last_num == NULL) {
1048                 ERR("No last number");
1049                 err_code = BT_HFP_AGENT_ERROR_NO_CALL_LOGS;
1050                 goto done;
1051         }
1052
1053         if (!__bt_is_phone_locked(&phone_lock_state)) {
1054                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1055                 goto done;
1056         }
1057
1058         if (!__bt_get_outgoing_callapp_type(&callapp_type)) {
1059                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1060                 goto done;
1061         }
1062
1063         if (!__bt_get_outgoing_call_condition(&condition)) {
1064                 ERR(" Failed to get the call condition");
1065                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1066                 goto done;
1067         }
1068
1069         if (condition == BT_MO_ONLY_UNLOCKED &&
1070                 phone_lock_state == VCONFKEY_IDLE_LOCK) {
1071                 ERR(" call condition and phone lock state check fail");
1072                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1073                 goto done;
1074         }
1075
1076         switch (callapp_type) {
1077         case BT_VOICE_CALL:
1078                 if (!__bt_ag_agent_make_call(last_num)) {
1079                         ERR("Problem launching application");
1080                         err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1081                 }
1082                 break;
1083         case BT_VIDEO_CALL:
1084                 if (!__bt_ag_agent_make_video_call(last_num)) {
1085                         ERR("Problem launching application");
1086                         err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1087                 }
1088                 break;
1089         case BT_FOLLOW_CALL_LOG:
1090                 if (contacts_record_get_int(record,
1091                         _contacts_phone_log.log_type,
1092                         &type) != CONTACTS_ERROR_NONE) {
1093                         err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1094                         break;
1095                 }
1096                 if (type == CONTACTS_PLOG_TYPE_VOICE_OUTGOING) {
1097                         if (!__bt_ag_agent_make_call(last_num)) {
1098                                 ERR("Problem launching application");
1099                                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1100                         }
1101                 } else if (type == CONTACTS_PLOG_TYPE_VIDEO_OUTGOING) {
1102                         if (!__bt_ag_agent_make_video_call(last_num)) {
1103                                 ERR("Problem launching application");
1104                                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1105                         }
1106                 } else {
1107                                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1108                 }
1109                 break;
1110         default:
1111                 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1112                 break;
1113         }
1114
1115 done:
1116
1117         if (list != NULL)
1118                 contacts_list_destroy(list, TRUE);
1119
1120         if (filter != NULL)
1121                 contacts_filter_destroy(filter);
1122
1123         if (query != NULL)
1124                 contacts_query_destroy(query);
1125
1126         contacts_disconnect();
1127
1128         if (last_num != NULL)
1129                 g_free(last_num);
1130
1131         FN_END;
1132
1133         return err_code;
1134 }
1135
1136 bt_hfp_agent_error_t _bt_ag_agent_vendor_cmd(const gchar *cmd,
1137                 const gchar *path, const gchar *sender)
1138 {
1139         bt_hfp_agent_error_t ret;
1140
1141         FN_START;
1142
1143         if (cmd == NULL || path == NULL || sender == NULL) {
1144                 ERR("Invalid Argument");
1145                 return BT_HFP_AGENT_ERROR_INVALID_PARAM;
1146         }
1147
1148         DBG("cmd = %s", cmd);
1149         DBG("Application path = %s", path);
1150         DBG("Sender = %s", sender);
1151
1152         ret = __bt_ag_agent_gdbus_method_send(sender,
1153                                 path, TELEPHONY_APP_INTERFACE,
1154                                 "VendorCmd", FALSE,
1155                                 g_variant_new("(s)", cmd));
1156         FN_END;
1157         return ret;
1158 }
1159
1160 gboolean _bt_ag_agent_get_signal_quality(void *device)
1161 {
1162         gint rssi;
1163
1164         FN_START;
1165
1166         if (vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &rssi)) {
1167                 DBG("VCONFKEY_TELEPHONY_RSSI failed\n");
1168                 goto fail;
1169         }
1170
1171         DBG("RSSI : %d", rssi);
1172
1173         _bt_hfp_signal_quality_reply(rssi, BT_SIGNAL_QUALITY_BER,
1174                 device);
1175
1176         FN_END;
1177         return TRUE;
1178 fail:
1179         FN_END;
1180         _bt_hfp_signal_quality_reply(-1, -1, device);
1181         return FALSE;
1182 }
1183
1184 gboolean _bt_ag_agent_get_battery_status(void *device)
1185 {
1186         gint battery_chrg_status;
1187         gint battery_capacity;
1188
1189         FN_START;
1190
1191         if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
1192                                                 &battery_chrg_status)) {
1193                 DBG("VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW failed\n");
1194                 goto fail;
1195         }
1196
1197         DBG("Status : %d\n", battery_chrg_status);
1198
1199         if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
1200                                                 &battery_capacity)) {
1201                 DBG("VCONFKEY_SYSMAN_BATTERY_CAPACITY failed\n");
1202                 goto fail;
1203         }
1204
1205         DBG("Capacity : %d\n", battery_capacity);
1206
1207         _bt_hfp_battery_property_reply(device,
1208                 battery_chrg_status, battery_capacity);
1209         FN_END;
1210         return TRUE;
1211
1212 fail:
1213         _bt_hfp_battery_property_reply(device, -1, -1);
1214         FN_END;
1215         return FALSE;
1216 }
1217
1218 gboolean _bt_ag_agent_get_operator_name(void *device)
1219 {
1220         char *operator_name;
1221         FN_START;
1222
1223         operator_name = vconf_get_str(VCONFKEY_TELEPHONY_NWNAME);
1224         if (NULL == operator_name) {
1225                 DBG("vconf_get_str failed");
1226                 _bt_hfp_operator_reply(NULL, device);
1227                 return FALSE;
1228         }
1229
1230         DBG("operator_name  = [%s]", operator_name);
1231
1232         _bt_hfp_operator_reply(operator_name, device);
1233
1234         free(operator_name);
1235
1236         FN_END;
1237         return TRUE;
1238 }
1239
1240 gboolean _bt_hfp_agent_nrec_status(gboolean status,
1241                         void *t_device)
1242 {
1243         FN_START;
1244         bt_ag_info_t *hs = (bt_ag_info_t *)t_device;
1245
1246         DBG("NREC status = %d", status);
1247         if (status)
1248                 hs->nrec_status = FALSE;
1249         else
1250                 hs->nrec_status = TRUE;
1251
1252         _bt_ag_agent_emit_signal(ag_dbus_conn, hs->path,
1253                                         BT_AG_SERVICE_NAME, "NrecStatusChanged",
1254                                         g_variant_new("(b)", status));
1255         FN_END;
1256         return TRUE;
1257 }
1258
1259 gboolean _bt_ag_agent_get_imei_number(void *device)
1260 {
1261         FN_START;
1262         char *imei_number;
1263
1264         imei_number = tel_get_misc_me_imei_sync(tapi_handle);
1265         if (NULL == imei_number) {
1266                 ERR("tel_get_misc_me_imei_sync for imei_number failed");
1267                 goto fail;
1268         }
1269
1270         if (!g_utf8_validate(imei_number, -1, NULL)) {
1271                 free(imei_number);
1272                 ERR("get_imei_number : invalid UTF8");
1273                 goto fail;
1274         }
1275
1276         DBG_SECURE("imei_number  = [%s]", imei_number);
1277         _bt_hfp_get_imei_number_reply(imei_number, device);
1278         free(imei_number);
1279         FN_END;
1280         return TRUE;
1281
1282 fail:
1283         _bt_hfp_get_imei_number_reply(NULL, device);
1284         FN_END;
1285         return FALSE;
1286 }
1287
1288 void _bt_ag_agent_get_manufacturer_name(void *device)
1289 {
1290         FN_START;
1291         char *manufacturer_name;
1292         int ret;
1293
1294         ret = system_info_get_platform_string("http://tizen.org/system/manufacturer",
1295                                                 &manufacturer_name);
1296         if (SYSTEM_INFO_ERROR_NONE != ret) {
1297                 ERR("Get manufacturer_name failed : %d", ret);
1298                 if (NULL != manufacturer_name)
1299                         free(manufacturer_name);
1300
1301                 manufacturer_name = g_strdup("Unknown");
1302         } else if (!g_utf8_validate(manufacturer_name, -1, NULL)) {
1303                 free(manufacturer_name);
1304                 manufacturer_name = g_strdup("Unknown");
1305                 ERR("get_manufacturer_name : invalid UTF8");
1306         }
1307
1308         DBG_SECURE("manufacturer_name  = [%s]", manufacturer_name);
1309         _bt_hfp_get_device_manufacturer_reply(manufacturer_name, device);
1310         free(manufacturer_name);
1311         FN_END;
1312 }
1313
1314 void _bt_ag_agent_get_imsi(void *device)
1315 {
1316         FN_START;
1317         TelSimImsiInfo_t imsi;
1318         memset(&imsi, 0, sizeof(TelSimImsiInfo_t));
1319         if (tel_get_sim_imsi(tapi_handle, &imsi) != TAPI_API_SUCCESS) {
1320                 ERR("tel_get_sim_imsi failed");
1321                 goto fail;
1322         }
1323         DBG_SECURE("tapi values %s %s %s", imsi.szMcc, imsi.szMnc, imsi.szMsin);
1324
1325         _bt_hfp_get_imsi_reply(imsi.szMcc, imsi.szMnc, imsi.szMsin, device);
1326         FN_END;
1327         return;
1328 fail:
1329         _bt_hfp_get_imsi_reply(NULL, NULL, NULL, device);
1330         FN_END;
1331 }
1332
1333 int _bt_ag_agent_registration_status_convert(int result)
1334 {
1335         switch (result) {
1336         case TAPI_NETWORK_SERVICE_LEVEL_NO:
1337                 return BT_AGENT_NETWORK_REG_STATUS_NOT_REGISTER;
1338         case TAPI_NETWORK_SERVICE_LEVEL_EMERGENCY:
1339                 return BT_AGENT_NETWORK_REG_STATUS_EMERGENCY;
1340         case TAPI_NETWORK_SERVICE_LEVEL_FULL:
1341                 return BT_AGENT_NETWORK_REG_STATUS_REGISTER_HOME_NETWORK;
1342         case TAPI_NETWORK_SERVICE_LEVEL_SEARCH:
1343                 return BT_AGENT_NETWORK_REG_STATUS_SEARCH;
1344         default:
1345                 return BT_AGENT_NETWORK_REG_STATUS_UNKNOWN;
1346         }
1347         return result;
1348 }
1349
1350 void _bt_ag_agent_get_creg_status(void *device)
1351 {
1352         FN_START;
1353         int result = 0;
1354         int ret = 0;
1355         int n = 1;
1356         int registration_status = 0;
1357         int roam_status = 0;
1358
1359         ret = tel_get_property_int(tapi_handle, TAPI_PROP_NETWORK_CIRCUIT_STATUS,
1360                                 &result);
1361         if (ret != TAPI_API_SUCCESS) {
1362                 ERR("tel_get_property_int failed");
1363                 return;
1364         }
1365         registration_status =
1366                         _bt_ag_agent_registration_status_convert(result);
1367
1368         DBG_SECURE("Registration status %d", result);
1369         DBG_SECURE("Mapped Status %d", registration_status);
1370         if (registration_status ==
1371                         BT_AGENT_NETWORK_REG_STATUS_REGISTER_HOME_NETWORK) {
1372                 ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
1373                 if (ret != 0) {
1374                         ERR("Get roaming status failed err = %d\n", ret);
1375                         return;
1376                 }
1377                 DBG_SECURE("Roam status %d", roam_status);
1378                 if (roam_status == 1) {
1379                         registration_status =
1380                                         BT_AGENT_NETWORK_REG_STATUS_REGISTERED_ROAMING;
1381                 }
1382         }
1383
1384         _bt_hfp_get_creg_status_reply(n, registration_status, device);
1385
1386         FN_END;
1387         return;
1388 }
1389
1390 void _bt_ag_agent_get_model_name(void *device)
1391 {
1392         FN_START;
1393         char *model_name;
1394         int ret;
1395
1396         ret = system_info_get_platform_string("http://tizen.org/system/model_name", &model_name);
1397         if (SYSTEM_INFO_ERROR_NONE != ret) {
1398                 ERR("Get model_name failed: %d", ret);
1399                 if (NULL != model_name)
1400                         free(model_name);
1401
1402                 model_name = g_strdup("Unknown");
1403         } else if (!g_utf8_validate(model_name, -1, NULL)) {
1404                 free(model_name);
1405                 model_name = g_strdup("Unknown");
1406                 ERR("get_model_name : invalid UTF8");
1407         }
1408
1409         DBG_SECURE("model_name  = [%s]", model_name);
1410         _bt_hfp_get_model_info_reply(model_name, device);
1411         free(model_name);
1412         FN_END;
1413 }
1414
1415 void _bt_ag_agent_get_revision_information(void *device)
1416 {
1417         FN_START;
1418         char *revision_info;
1419         int ret;
1420
1421         ret = system_info_get_platform_string("http://tizen.org/system/build.string",
1422                                 &revision_info);
1423         if (SYSTEM_INFO_ERROR_NONE != ret) {
1424                 ERR("Get revision_info failed: %d", ret);
1425                 if (NULL != revision_info)
1426                         free(revision_info);
1427
1428                 revision_info = g_strdup("Unknown");
1429         } else if (!g_utf8_validate(revision_info, -1, NULL)) {
1430                         free(revision_info);
1431                         revision_info = g_strdup("Unknown");
1432                         ERR("get_revision_info: invalid UTF8");
1433                 }
1434
1435         DBG_SECURE("revision_info  = [%s]", revision_info);
1436         _bt_hfp_get_revision_info_reply(revision_info, device);
1437         free(revision_info);
1438         FN_END;
1439 }
1440
1441 #if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
1442 static gboolean __bt_ag_agent_launch_voice_dial(gboolean activate)
1443 {
1444         FN_START;
1445         bundle *b;
1446
1447         b = bundle_create();
1448         if (NULL == b) {
1449                 ERR("bundle_create() Failed");
1450                 return FALSE;
1451         }
1452
1453         bundle_add(b, "domain", "bt_headset");
1454         if (!activate)
1455                 bundle_add(b, "action_type", "deactivate");
1456
1457         aul_launch_app_async("org.tizen.svoice", b);
1458         bundle_free(b);
1459         FN_END;
1460         return TRUE;
1461 }
1462 #else
1463 static gboolean __bt_ag_agent_launch_voice_dial(gboolean activate)
1464 {
1465         FN_START;
1466         app_control_h service = NULL;
1467
1468         app_control_create(&service);
1469
1470         if (service == NULL) {
1471                 ERR("Service create failed");
1472                 return FALSE;
1473         }
1474
1475         app_control_set_app_id(service, "org.tizen.svoice");
1476         app_control_set_operation(service, APP_CONTROL_OPERATION_DEFAULT);
1477         if (app_control_add_extra_data(service, "domain", "bt_headset")
1478                                         != APP_CONTROL_ERROR_NONE) {
1479                 ERR("app_control_add_extra_data failed");
1480                 app_control_destroy(service);
1481                 return FALSE;
1482         }
1483
1484         if (!activate)
1485                 if (app_control_add_extra_data(service, "action_type", "deactivate")
1486                                         != APP_CONTROL_ERROR_NONE) {
1487                         ERR("app_control_add_extra_data failed");
1488                         app_control_destroy(service);
1489                         return FALSE;
1490                 }
1491
1492         if (app_control_send_launch_request(service, NULL, NULL) !=
1493                                                 APP_CONTROL_ERROR_NONE) {
1494                 ERR("launch failed");
1495                 app_control_destroy(service);
1496                 return FALSE;
1497         }
1498
1499         app_control_destroy(service);
1500         FN_END;
1501         return TRUE;
1502 }
1503 #endif
1504
1505 gboolean _bt_ag_agent_voice_dial(gboolean activate)
1506 {
1507         DBG("Activate = %d", activate);
1508
1509         return __bt_ag_agent_launch_voice_dial(activate);
1510 }
1511
1512 static void __bt_ag_codec_negotiation_info_reset(bt_ag_info_t *hs,
1513                                         gboolean reset)
1514 {
1515         hs->codec_info.is_negotiating = FALSE;
1516         hs->codec_info.requested_by_hf = FALSE;
1517         hs->codec_info.sending_codec = 0;
1518         if (reset) {
1519                 hs->codec_info.remote_codecs = 0;
1520                 hs->codec_info.final_codec = 0;
1521                 hs->nrec_status = FALSE;
1522         }
1523
1524         if (hs->codec_info.nego_timer) {
1525                 g_source_remove(hs->codec_info.nego_timer);
1526                 hs->codec_info.nego_timer = 0;
1527         }
1528         wbs_opts.wbs_enable = wbs_en;
1529 }
1530
1531 static gboolean __bt_ag_codec_negotiation_finished(gpointer user_data)
1532 {
1533         struct ag_codec *data = (struct ag_codec *)user_data;
1534
1535         if (g_strcmp0(data->codec_status, "finish") == 0) {
1536                 DBG("Codec negotiation finished");
1537                 __bt_ag_sco_connect(data->bt_ag_info);
1538                 __bt_ag_codec_negotiation_info_reset(data->bt_ag_info, FALSE);
1539                 g_free(data->codec_status);
1540                 g_free(data);
1541                 return TRUE;
1542         } else if (g_strcmp0(data->codec_status, "timeout") == 0) {
1543                 DBG("Timeout is occured in codec negotiation");
1544         }
1545
1546         if (data->bt_ag_info->codec_info.requested_by_hf) {
1547                 __bt_ag_codec_negotiation_info_reset(data->bt_ag_info, FALSE);
1548         } else {
1549                 __bt_ag_sco_connect(data->bt_ag_info);
1550                 __bt_ag_codec_negotiation_info_reset(data->bt_ag_info, FALSE);
1551         }
1552         g_free(data->codec_status);
1553         g_free(data);
1554
1555         return FALSE;
1556 }
1557
1558 static bt_hfp_agent_error_t __bt_ag_set_codec(void *device, char *method)
1559 {
1560         GDBusProxy *proxy;
1561         GVariant *ret;
1562         GError *err = NULL;
1563         bt_ag_info_t *bt_ag_info = (bt_ag_info_t *)device;
1564
1565         proxy =  g_dbus_proxy_new_sync(ag_dbus_conn,
1566                         G_DBUS_PROXY_FLAGS_NONE, NULL,
1567                         BLUEZ_SERVICE_NAME, DEFAULT_ADAPTER_OBJECT_PATH,
1568                         BT_ADAPTER_INTERFACE, NULL, &err);
1569
1570         if (!proxy) {
1571                 if (err) {
1572                         ERR("Unable to create proxy: %s", err->message);
1573                         g_clear_error(&err);
1574                 }
1575                 return BT_HFP_AGENT_ERROR_INTERNAL;
1576         }
1577
1578         ret = g_dbus_proxy_call_sync(proxy, method,
1579                         g_variant_new("(ss)", "Gateway", bt_ag_info->remote_addr),
1580                         G_DBUS_CALL_FLAGS_NONE, -1,
1581                         NULL, &err);
1582         if (ret == NULL) {
1583                 /* dBUS-RPC is failed */
1584                 ERR("dBUS-RPC is failed");
1585                 if (err != NULL) {
1586                         /* dBUS gives error cause */
1587                         ERR("D-Bus API failure: errCode[%x], message[%s]",
1588                                err->code, err->message);
1589
1590                         g_clear_error(&err);
1591                 }
1592                 return BT_HFP_AGENT_ERROR_INTERNAL;
1593         }
1594         g_variant_unref(ret);
1595
1596         return BT_HFP_AGENT_ERROR_NONE;
1597 }
1598
1599 static bt_hfp_agent_error_t __bt_ag_codec_selection_setup(bt_ag_info_t *hs,
1600                         uint32_t codec)
1601 {
1602         bt_hfp_agent_error_t err = BT_HFP_AGENT_ERROR_NONE;
1603
1604         DBG("Codec setup [%x]", codec);
1605
1606         /* 1. Compare sending codec & recieved code */
1607         if (hs->codec_info.sending_codec != codec)
1608                 err = BT_HFP_AGENT_ERROR_INTERNAL;
1609
1610         /* 2. Send WB or NB command */
1611         switch (codec) {
1612         case BT_CVSD_CODEC_ID:
1613                 err = __bt_ag_set_codec(hs, "SetNbParameters");
1614                 break;
1615         case BT_MSBC_CODEC_ID:
1616                 err = __bt_ag_set_codec(hs, "SetWbsParameters");
1617                 break;
1618         default:
1619                 err = BT_HFP_AGENT_ERROR_INTERNAL;
1620                 break;
1621         }
1622
1623         /* If the vendor specific calling returns error or codec is not correct,
1624          * we send CVSD Codec parameter to MM module. and also returns
1625          * normal value to HF
1626         */
1627         if (err != BT_HFP_AGENT_ERROR_NONE)
1628                 codec = BT_CVSD_CODEC_ID;
1629
1630         hs->codec_info.final_codec = codec;
1631
1632         return err;
1633 }
1634
1635 static bt_hfp_agent_error_t __bt_hfp_send_bcs_command(bt_ag_info_t *hs,
1636                         gboolean init_by_hf)
1637 {
1638         uint32_t codec;
1639         struct ag_codec *data = NULL;;
1640
1641 #ifdef TIZEN_FEATURE_BT_KIRAN_DEVICE
1642         codec = BT_CVSD_CODEC_ID;
1643 #else
1644         if (hs->codec_info.remote_codecs & BT_MSBC_CODEC_MASK)
1645                 codec = BT_MSBC_CODEC_ID;
1646         else
1647                 codec = BT_CVSD_CODEC_ID;
1648 #endif
1649
1650         if (wbs_opts.wbs_enable == FALSE)
1651                 codec = BT_CVSD_CODEC_ID;
1652
1653         hs->codec = codec;
1654
1655         if (_bt_ag_send_at(hs, "\r\n+BCS: %d\r\n", codec) < 0)
1656                 return BT_HFP_AGENT_ERROR_INTERNAL;
1657         else
1658                 DBG("Send +BCS:%d\n", codec);
1659
1660         /* Send +BCS command to HF, and wait some times */
1661         hs->codec_info.is_negotiating = TRUE;
1662         hs->codec_info.sending_codec = codec;
1663         hs->codec_info.requested_by_hf = init_by_hf;
1664         hs->codec_info.final_codec = codec;
1665
1666         data = g_new0(struct ag_codec, 1);
1667         if (data == NULL)
1668                 return BT_HFP_AGENT_ERROR_NO_MEMORY;
1669
1670         data->bt_ag_info = hs;
1671         data->codec_status = g_strdup("timeout");
1672
1673         hs->codec_info.nego_timer = g_timeout_add_seconds(
1674                         HFP_CODEC_NEGOTIATION_TIMEOUT,
1675                         (GSourceFunc)__bt_ag_codec_negotiation_finished,
1676                         data);
1677
1678         return BT_HFP_AGENT_ERROR_NONE;
1679 }
1680
1681
1682 static bt_hfp_agent_error_t __bt_hfp_codec_connection_setup(
1683                                 bt_ag_info_t *hs, gboolean init_by_hf)
1684 {
1685         DBG("Request to codec connection by %s", init_by_hf ? "HF" : "AG");
1686
1687         if (hs->state < HEADSET_STATE_CONNECTED)
1688                 return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
1689
1690         if (hs->codec_info.is_negotiating == TRUE) {
1691                 /* In codec negotiation, return and wait */
1692                 ERR("Codec nogotiation is in progress");
1693                 return BT_HFP_AGENT_ERROR_BUSY;
1694         }
1695
1696         /* Not support Codec Negotiation or Not recieved BAC command */
1697         if (!(ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) ||
1698                                 hs->codec_info.remote_codecs == 0) {
1699                 ERR("No support for Codec Negotiation or receive BAC command");
1700                 if (init_by_hf) {
1701                         return BT_HFP_AGENT_ERROR_INTERNAL;
1702                 } else {
1703                         __bt_ag_sco_connect(hs);
1704                         return BT_HFP_AGENT_ERROR_INTERNAL;
1705                 }
1706         }
1707
1708         /* If HF initiated codec connection setup, it should send OK command
1709          * before +BCS command transmission.
1710          */
1711         if (init_by_hf)
1712                 return HFP_STATE_MNGR_ERR_NONE;
1713         else
1714                 return __bt_hfp_send_bcs_command(hs, init_by_hf);
1715 }
1716
1717
1718 static int __hfp_parse_available_codecs(const char *cmd, uint32_t *codecs)
1719 {
1720         char *str = NULL;
1721         *codecs = 0x00000000;
1722
1723         str = strchr(cmd, '=');
1724         if (str == NULL)
1725                 return -EINVAL;
1726
1727         while (str != NULL) {
1728                 str++;
1729
1730                 if (atoi(str) == BT_CVSD_CODEC_ID)
1731                         *codecs |= BT_CVSD_CODEC_MASK;
1732                 else if (atoi(str) == BT_MSBC_CODEC_ID)
1733                         *codecs |= BT_MSBC_CODEC_MASK;
1734
1735                 str = strchr(str, ',');
1736         }
1737
1738         if (*codecs == 0x00000000)
1739                 return -EINVAL;
1740
1741         return 0;
1742 }
1743
1744 /* AT+BAC (Bluetooth Available Codecs) */
1745 static int __bt_hfp_available_codecs(bt_ag_info_t *hs, const char *buf)
1746 {
1747         uint32_t codecs = 0x00000000;
1748         hfp_state_manager_err_t err = HFP_STATE_MNGR_ERR_NONE;
1749
1750         if (!(ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION)) {
1751                 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1752         } else if (__hfp_parse_available_codecs(buf, &codecs) < 0) {
1753                 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1754         } else {
1755                 DBG("Update remote available codecs [%x]", codecs);
1756                 hs->codec_info.remote_codecs = codecs;
1757         }
1758
1759         _bt_ag_send_response(hs, err);
1760
1761         /* Reset codec information and
1762          * restart codec connection setup by AG
1763          */
1764         hs->codec_info.final_codec = 0;
1765         if (hs->codec_info.nego_timer) {
1766                 hs->codec_info.is_negotiating = FALSE;
1767                 hs->codec_info.requested_by_hf = FALSE;
1768                 hs->codec_info.sending_codec = 0;
1769                 g_source_remove(hs->codec_info.nego_timer);
1770                 __bt_hfp_codec_connection_setup(hs, FALSE);
1771         }
1772
1773         return 0;
1774 }
1775
1776 /* AT+BCC (Bluetooth Codec Connection) */
1777 static int __bt_hfp_codec_connection(bt_ag_info_t *hs, const char *buf)
1778 {
1779         hfp_state_manager_err_t err = HFP_STATE_MNGR_ERR_NONE;
1780
1781         err = __bt_hfp_codec_connection_setup(hs, TRUE);
1782
1783         _bt_ag_send_response(hs, err);
1784
1785         if (err == HFP_STATE_MNGR_ERR_NONE)
1786                 err = __bt_hfp_send_bcs_command(hs, TRUE);
1787
1788         if (err != HFP_STATE_MNGR_ERR_NONE)
1789                 ERR("Fail to request codec connection setup");
1790
1791         return 0;
1792 }
1793
1794 /* AT+BCS (Bluetooth Codec Selection) */
1795 static int __bt_hfp_codec_selection(bt_ag_info_t *hs, const char *buf)
1796 {
1797         uint32_t codec = 0x00000000;
1798         hfp_state_manager_err_t err = HFP_STATE_MNGR_ERR_NONE;
1799         struct ag_codec *data = g_new0(struct ag_codec, 1);
1800
1801         /* Timer reset */
1802         if (hs->codec_info.nego_timer) {
1803                 g_source_remove(hs->codec_info.nego_timer);
1804                 hs->codec_info.nego_timer = 0;
1805         }
1806
1807         if (!(ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION))
1808                 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1809         else if (__hfp_parse_available_codecs(buf, &codec) < 0)
1810                 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1811         else if (__bt_ag_codec_selection_setup(hs, codec) !=
1812                                         BT_HFP_AGENT_ERROR_NONE)
1813                 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1814
1815         data->bt_ag_info = hs;
1816         data->codec_status = g_strdup("finish");
1817         _bt_ag_send_response(hs, err);
1818         __bt_ag_codec_negotiation_finished(data);
1819
1820         return 0;
1821 }
1822
1823 static void __bt_ag_str2ba(const char *str, bt_addr *ba)
1824 {
1825         int i;
1826         for (i = 5; i >= 0; i--, str += 3)
1827                 ba->b[i] = strtol(str, NULL, 16);
1828 }
1829
1830 static const char *__bt_ag_state2str(hs_state_t state)
1831 {
1832         switch (state) {
1833         case HEADSET_STATE_DISCONNECTED:
1834                 return "disconnected";
1835         case HEADSET_STATE_CONNECTING:
1836                 return "connecting";
1837         case HEADSET_STATE_CONNECTED:
1838                 return "connected";
1839         case HEADSET_STATE_PLAY_IN_PROGRESS:
1840                 return "Play In Progress";
1841         case HEADSET_STATE_ON_CALL:
1842                 return "On Call";
1843         }
1844
1845         return NULL;
1846 }
1847
1848 void _bt_convert_addr_string_to_type_rev(unsigned char *addr,
1849                 const char *address)
1850 {
1851         int i;
1852         char *ptr = NULL;
1853
1854         ret_if(address == NULL);
1855         ret_if(addr == NULL);
1856
1857         for (i = 0; i < 6; i++) {
1858                 addr[5 - i] = strtol(address, &ptr, 16);
1859                 if (ptr[0] != '\0') {
1860                         if (ptr[0] != ':')
1861                                 return;
1862
1863                         address = ptr + 1;
1864                 }
1865         }
1866 }
1867
1868 static gboolean __bt_ag_check_nval(GIOChannel *chan)
1869 {
1870         struct pollfd file_desc;
1871
1872         memset(&file_desc, 0, sizeof(file_desc));
1873         file_desc.fd = g_io_channel_unix_get_fd(chan);
1874         file_desc.events = POLLNVAL;
1875
1876         if (poll(&file_desc, 1, 0) > 0 && (POLLNVAL & file_desc.revents))
1877                 return TRUE;
1878
1879         return FALSE;
1880 }
1881
1882 static int __bt_ag_sco_connect(bt_ag_info_t *hs)
1883 {
1884         struct sco_socket_addr sco_addr;
1885         int err;
1886         GIOChannel *io;
1887         int sco_skt;
1888         bt_voice bt_vo;
1889         bt_ag_slconn_t *slconn = hs->slc;
1890         /*guint watch_id;*/
1891
1892         if (hs->state == HEADSET_STATE_ON_CALL)
1893                 return BT_HFP_AGENT_ERROR_ALREADY_CONNECTED;
1894
1895         if (hs->state != HEADSET_STATE_CONNECTED)
1896                 return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
1897 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
1898         _bt_ag_agent_check_transport_state();
1899 #endif
1900
1901         /* Create Sco socket */
1902         sco_skt = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BT_SCO_PRTCL);
1903         if (sco_skt < 0) {
1904                 ERR("ERROR: Create socket failed.\n");
1905                 return BT_HFP_AGENT_ERROR_INTERNAL;
1906         }
1907
1908         /* Bind Sco Socket to Local BD addr */
1909         memset(&sco_addr, 0, sizeof(sco_addr));
1910         sco_addr.sco_family = AF_BLUETOOTH;
1911
1912         __bt_ag_str2ba(local_addr, &sco_addr.sco_bdaddr);
1913         DBG("Local BD address: %s", local_addr);
1914
1915         err = bind(sco_skt, (struct sockaddr *) &sco_addr, sizeof(sco_addr));
1916         if (err < 0) {
1917                 ERR("ERROR: sco socket binding failed");
1918                 ERR("Close SCO skt");
1919                 close(sco_skt);
1920                 return BT_HFP_AGENT_ERROR_INTERNAL;
1921         }
1922
1923         DBG("Socket FD : %d", sco_skt);
1924
1925         io = g_io_channel_unix_new(sco_skt);
1926         g_io_channel_set_close_on_unref(io, TRUE);
1927         /*g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
1928         g_io_channel_set_buffered(io, FALSE);
1929         g_io_channel_set_encoding(io, NULL, NULL);*/
1930
1931         if ((ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) &&
1932                 (slconn && (slconn->hs_features &
1933                         BT_HF_FEATURE_CODEC_NEGOTIATION)) &&
1934                         wbs_opts.wbs_enable == TRUE) {
1935                 bt_vo.setting = (hs->codec == BT_MSBC_CODEC_ID) ?
1936                                 BT_HFP_MSBC_VOICE : BT_HFP_CVSD_VOICE;
1937
1938                 DBG("set Bluetooth voice: %d", bt_vo.setting);
1939                 err = setsockopt(sco_skt, BT_SOCKET_LEVEL,
1940                                         BT_VOICE_NUM, &bt_vo, sizeof(bt_vo));
1941                 if (err < 0) {
1942                         ERR("ERROR: sco socket set socket option failed");
1943                         ERR("Close SCO skt");
1944                         g_io_channel_unref(io);
1945                         close(sco_skt);
1946                         return BT_HFP_AGENT_ERROR_INTERNAL;
1947                 }
1948         } else {
1949                 DBG("Set NB codec parameter");
1950                 __bt_ag_set_codec(hs, "SetNbParameters");
1951         }
1952
1953         memset(&sco_addr, 0, sizeof(sco_addr));
1954         sco_addr.sco_family = AF_BLUETOOTH;
1955         __bt_ag_str2ba(hs->remote_addr, &sco_addr.sco_bdaddr);
1956         DBG("remotel BD address: %s", hs->remote_addr);
1957
1958         err = connect(sco_skt, (struct sockaddr *) &sco_addr, sizeof(sco_addr));
1959         if (err < 0 && !(errno == EINPROGRESS || errno == EAGAIN)) {
1960                 ERR("ERROR: sco socket connect failed : %d", err);
1961                 ERR("Close SCO skt");
1962                 g_io_channel_unref(io);
1963                 close(sco_skt);
1964                 return BT_HFP_AGENT_ERROR_INTERNAL;
1965         }
1966
1967         /* Disabling the watch since SCO is connected */
1968         /*watch_id = __bt_ag_set_watch(io,
1969                         (GIOFunc) __bt_ag_sco_connect_cb, hs);
1970         if (watch_id)
1971                 DBG("SCO watch set Success");*/
1972
1973         hs->sco = io;
1974
1975         _bt_ag_set_headset_state(hs, HEADSET_STATE_ON_CALL);
1976         return BT_HFP_AGENT_ERROR_NONE;
1977 }
1978
1979 static void __bt_ag_close_sco(bt_ag_info_t *hs)
1980 {
1981         DBG("");
1982         if (hs->sco) {
1983                 int sock = g_io_channel_unix_get_fd(hs->sco);
1984                 shutdown(sock, SHUT_RDWR);
1985                 g_io_channel_unref(hs->sco);
1986                 hs->sco = NULL;
1987         }
1988
1989         if (hs->sco_id)
1990                 __bt_ag_agent_remove_watch(&hs->sco_id);
1991 }
1992
1993 static gboolean __bt_ag_sco_server_conn_cb(GIOChannel *chan,
1994                                 GIOCondition cond, gpointer user_data)
1995 {
1996         bt_ag_info_t *ag_info = user_data;
1997
1998         DBG("");
1999         if (cond & G_IO_NVAL)
2000                 return FALSE;
2001
2002         if (cond & (G_IO_HUP | G_IO_ERR)) {
2003                 ag_info->sco = NULL;
2004                 if (ag_info->sco_id)
2005                         __bt_ag_agent_remove_watch(&ag_info->sco_id);
2006
2007                 if (ag_info->watch_id)
2008                         _bt_ag_set_headset_state(ag_info, HEADSET_STATE_CONNECTED);
2009                 return FALSE;
2010         }
2011         return TRUE;
2012 }
2013
2014 static gboolean __bt_ag_sco_server_cb(GIOChannel *chan,
2015                                 GIOCondition cond, gpointer user_data)
2016 {
2017         bt_ag_info_t *ag_info = user_data;
2018         int sco_skt;
2019         int cli_sco_sock;
2020         GIOChannel *sco_io;
2021         bt_ag_slconn_t *slconn = ag_info->slc;
2022         bt_voice bt_vo;
2023         int err;
2024
2025         if ((cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) ||
2026                                 __bt_ag_check_nval(chan)) {
2027                 ERR("cond or chan is not valid");
2028                 return FALSE;
2029         }
2030
2031         INFO_C("Incoming SCO....");
2032
2033         if (ag_info->state < HEADSET_STATE_CONNECTED)
2034                 return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
2035
2036         sco_skt = g_io_channel_unix_get_fd(chan);
2037
2038         cli_sco_sock = accept(sco_skt, NULL, NULL);
2039         if (cli_sco_sock < 0) {
2040                 ERR("accept is failed");
2041                 return TRUE;
2042         }
2043
2044         sco_io = g_io_channel_unix_new(cli_sco_sock);
2045         g_io_channel_set_close_on_unref(sco_io, TRUE);
2046         g_io_channel_set_encoding(sco_io, NULL, NULL);
2047         g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
2048         g_io_channel_set_buffered(sco_io, FALSE);
2049
2050         if ((ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) &&
2051                 (slconn && (slconn->hs_features &
2052                         BT_HF_FEATURE_CODEC_NEGOTIATION)) &&
2053                         wbs_opts.wbs_enable == TRUE) {
2054                 bt_vo.setting = (ag_info->codec == BT_MSBC_CODEC_ID) ?
2055                                 BT_HFP_MSBC_VOICE : BT_HFP_CVSD_VOICE;
2056
2057                 DBG("set Bluetooth voice: %d", bt_vo.setting);
2058                 err = setsockopt(cli_sco_sock, BT_SOCKET_LEVEL,
2059                                         BT_VOICE_NUM, &bt_vo, sizeof(bt_vo));
2060                 if (err < 0) {
2061                         ERR("Sco socket set socket option failed");
2062                         close(cli_sco_sock);
2063                         return FALSE;
2064                 }
2065         }
2066
2067         ag_info->sco = sco_io;
2068         ag_info->sco_id = g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
2069                                         __bt_ag_sco_server_conn_cb, ag_info);
2070
2071         if (remote_dev_path)
2072                 g_free(remote_dev_path);
2073
2074         remote_dev_path = g_strdup(ag_info->path);
2075
2076         _bt_ag_set_headset_state(ag_info, HEADSET_STATE_ON_CALL);
2077
2078         return TRUE;
2079 }
2080
2081 static int __bt_ag_start_sco_server(bt_ag_info_t *hs)
2082 {
2083         DBG("Start SCO server");
2084         struct sco_socket_addr addr;
2085         GIOChannel *sco_io;
2086         int sco_skt;
2087         bdaddr_t bd_addr = {{0},};
2088
2089         if (hs->sco_server_started) {
2090                 DBG("Already exsist");
2091                 return BT_HFP_AGENT_ERROR_ALREADY_EXSIST;
2092         }
2093
2094         /* Create socket */
2095         sco_skt = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BT_SCO_PRTCL);
2096         if (sco_skt < 0) {
2097                 ERR("Can't create socket:\n");
2098                 return BT_HFP_AGENT_ERROR_INTERNAL;
2099         }
2100
2101         /* Bind to local address */
2102         memset(&addr, 0, sizeof(addr));
2103         addr.sco_family = AF_BLUETOOTH;
2104
2105         _bt_convert_addr_string_to_type_rev(bd_addr.b, hs->remote_addr);
2106         DBG("Bind to address %s", hs->remote_addr);
2107         memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
2108
2109         if (bind(sco_skt, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2110                 ERR("Can't bind socket:\n");
2111                 goto error;
2112         }
2113
2114         if (listen(sco_skt, 1)) {
2115                 ERR("Can not listen on the socket:\n");
2116                 goto error;
2117         }
2118
2119         sco_io = g_io_channel_unix_new(sco_skt);
2120         g_io_channel_set_close_on_unref(sco_io, TRUE);
2121         g_io_channel_set_encoding(sco_io, NULL, NULL);
2122         g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
2123         g_io_channel_set_buffered(sco_io, FALSE);
2124
2125         hs->sco_server = sco_io;
2126         hs->sco_watch_id = g_io_add_watch(sco_io,
2127                         G_IO_IN | G_IO_HUP | G_IO_ERR |
2128                         G_IO_NVAL, __bt_ag_sco_server_cb, hs);
2129
2130         hs->sco_server_started = TRUE;
2131         return BT_HFP_AGENT_ERROR_NONE;
2132
2133 error:
2134         close(sco_skt);
2135         return BT_HFP_AGENT_ERROR_INTERNAL;
2136 }
2137
2138 void __bt_ag_stop_sco_server(bt_ag_info_t *hs)
2139 {
2140         DBG("Stop SCO server");
2141         if (hs->sco_server) {
2142                 g_io_channel_shutdown(hs->sco_server, TRUE, NULL);
2143                 g_io_channel_unref(hs->sco_server);
2144                 hs->sco_server = NULL;
2145         }
2146         hs->sco_server_started = FALSE;
2147 }
2148
2149 static int __bt_ag_headset_close_rfcomm(bt_ag_info_t *hs)
2150 {
2151         GIOChannel *rfcomm = hs->rfcomm;
2152
2153         if (rfcomm) {
2154                 g_io_channel_shutdown(rfcomm, TRUE, NULL);
2155                 g_io_channel_unref(rfcomm);
2156                 hs->rfcomm = NULL;
2157         }
2158
2159         g_free(hs->slc);
2160         hs->slc = NULL;
2161
2162         return 0;
2163 }
2164
2165 static gboolean __bt_ag_sco_cb(GIOChannel *chan, GIOCondition cond,
2166                         bt_ag_info_t *hs)
2167 {
2168         if (cond & G_IO_NVAL)
2169                 return FALSE;
2170
2171         if (name_owner_sig_id != -1)
2172                 g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
2173                                         name_owner_sig_id);
2174         name_owner_sig_id = -1;
2175         g_free(sco_owner);
2176         sco_owner = NULL;
2177
2178         DBG("Audio connection disconnected");
2179         _bt_ag_set_headset_state(hs, HEADSET_STATE_CONNECTED);
2180
2181         return FALSE;
2182 }
2183
2184 void _bt_ag_set_headset_state(bt_ag_info_t *hs, hs_state_t state)
2185 {
2186         bt_ag_slconn_t *slconn = hs->slc;
2187         const char *hs_state;
2188         hs_state_t org_state = hs->state;
2189         gboolean val = FALSE;
2190
2191         if (org_state == state)
2192                 return;
2193
2194         hs_state = __bt_ag_state2str(state);
2195
2196         switch (state) {
2197         case HEADSET_STATE_CONNECTING:
2198                 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2199                                         hs->path,
2200                                         BT_HEADSET_INTERFACE, "State",
2201                                         g_variant_new("s", hs_state));
2202                 hs->state = state;
2203                 break;
2204
2205         case HEADSET_STATE_CONNECTED:
2206                 if (hs->state != HEADSET_STATE_PLAY_IN_PROGRESS)
2207                         _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2208                                         hs->path,
2209                                         BT_HEADSET_INTERFACE, "State",
2210                                         g_variant_new("s", hs_state));
2211
2212                 if (hs->state < state) {
2213                         val = TRUE;
2214                         active_devices = g_slist_append(active_devices, hs);
2215                         _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2216                                                 hs->path,
2217                                                 BT_HEADSET_INTERFACE,
2218                                                 "Connected",
2219                                                 g_variant_new("b", val));
2220
2221                         DBG("Device %s connected\n", hs->remote_addr);
2222 #if defined(TIZEN_SUPPORT_DUAL_HF)
2223                          if (!hs->is_companion_device)
2224                                 __bt_ag_start_sco_server(hs);
2225 #else
2226                         __bt_ag_start_sco_server(hs);
2227 #endif
2228
2229                         /* Set default code as Gateway NB */
2230                         __bt_ag_set_codec(hs, "SetNbParameters");
2231                 } else if (hs->state == HEADSET_STATE_ON_CALL) {
2232                         val = FALSE;
2233                         _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2234                                                 hs->path,
2235                                                 BT_HEADSET_INTERFACE,
2236                                                 "Playing",
2237                                                 g_variant_new("b", val));
2238                 }
2239                 hs->state = state;
2240                 break;
2241
2242         case HEADSET_STATE_DISCONNECTED:
2243                 __bt_ag_close_sco(hs);
2244                 __bt_ag_headset_close_rfcomm(hs);
2245
2246                 if (hs->state == HEADSET_STATE_ON_CALL) {
2247                         val = FALSE;
2248                         _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2249                                                 hs->path,
2250                                                 BT_HEADSET_INTERFACE,
2251                                                 "Playing",
2252                                                 g_variant_new("b", val));
2253                 }
2254
2255                 val = FALSE;
2256                 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2257                                 hs->path,
2258                                 BT_HEADSET_INTERFACE,
2259                                 "Connected",
2260                                 g_variant_new("b", val));
2261                 if (hs->state > HEADSET_STATE_CONNECTING)
2262                         _bt_hfp_device_disconnected(hs);
2263
2264                 active_devices = g_slist_remove(active_devices, hs);
2265
2266                 __bt_ag_codec_negotiation_info_reset(hs, TRUE);
2267 #if 0 /* SCO is crashed if below is called when SCO is opened by hf-agent */
2268                 __bt_ag_set_codec(hs, "SetNbParameters");
2269 #endif
2270                 hs->codec = 0;
2271
2272                 /* Since SCO server is binded on remote address */
2273                 /* Need to stop SCO server once heasdet disconencted*/
2274                 if (hs->sco_server_started)
2275                         __bt_ag_stop_sco_server(hs);
2276
2277                 g_free(hs->remote_addr);
2278                 g_free(hs);
2279                 break;
2280
2281         case HEADSET_STATE_PLAY_IN_PROGRESS:
2282         case HEADSET_STATE_ON_CALL:
2283                 val = TRUE;
2284                 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2285                                         hs->path,
2286                                         BT_HEADSET_INTERFACE, "State",
2287                                         g_variant_new("s", hs_state));
2288
2289                 /*add watch for sco data */
2290                 hs->sco_id = g_io_add_watch(hs->sco,
2291                                         G_IO_ERR | G_IO_NVAL,
2292                                         (GIOFunc) __bt_ag_sco_cb, hs);
2293
2294                 _bt_ag_agent_emit_property_changed(
2295                                 ag_dbus_conn, hs->path,
2296                                 BT_HEADSET_INTERFACE, "Playing",
2297                                 g_variant_new("b", val));
2298
2299                 if (slconn->microphone_gain >= 0)
2300                         _bt_ag_send_at(hs, "\r\n+VGM=%u\r\n",
2301                                 slconn->microphone_gain);
2302
2303                 if (slconn->speaker_gain >= 0)
2304                         _bt_ag_send_at(hs, "\r\n+VGS=%u\r\n",
2305                                 slconn->speaker_gain);
2306
2307                 hs->state = state;
2308                 break;
2309
2310         default:
2311                 hs->state = state;
2312                 break;
2313         }
2314
2315         INFO("STATE CHANGED from [%s(%d)] to [%s(%d)]",
2316                 __bt_ag_state2str(org_state), org_state, __bt_ag_state2str(state), state);
2317 }
2318
2319 static struct event at_event_callbacks[] = {
2320         { "AT+BRSF", _bt_hfp_supported_features },
2321         { "AT+CIND", _bt_hfp_report_indicators },
2322         { "AT+CMER", _bt_hfp_enable_indicators },
2323         { "AT+CHLD", _bt_hfp_call_hold },
2324         { "ATA", _bt_hfp_answer_call },
2325         { "ATD", _bt_hfp_dial_number },
2326         { "AT+VG", _bt_hfp_signal_gain_setting },
2327         { "AT+CHUP", _bt_hfp_terminate_call },
2328         { "AT+CKPD", _bt_hfp_key_press },
2329         { "AT+CLIP", _bt_hfp_cli_notification },
2330         { "AT+BTRH", _bt_hfp_response_and_hold },
2331         { "AT+BLDN", _bt_hfp_last_dialed_number },
2332         { "AT+VTS", _bt_hfp_dtmf_tone },
2333         { "AT+CNUM", _bt_hfp_subscriber_number },
2334         { "AT+CLCC", _bt_hfp_list_current_calls },
2335         { "AT+CMEE", _bt_hfp_extended_errors },
2336         { "AT+CCWA", _bt_hfp_call_waiting_notify },
2337         { "AT+COPS", _bt_hfp_operator_selection },
2338         { "AT+NREC", _bt_hfp_nr_and_ec },
2339         { "AT+BVRA", _bt_hfp_voice_dial },
2340         { "AT+XAPL", _bt_hfp_apl_command },
2341         { "AT+IPHONEACCEV", _bt_hfp_apl_command },
2342         { "AT+BIA", _bt_hfp_indicators_activation },
2343         { "AT+CPBS", _bt_hfp_select_pb_memory },
2344         { "AT+CPBR", _bt_hfp_read_pb_entries},
2345         { "AT+CPBF", _bt_hfp_find_pb_entires },
2346         { "AT+CSCS", _bt_hfp_select_character_set },
2347         { "AT+CSQ", _bt_hfp_get_signal_quality },
2348         { "AT+CBC", _bt_hfp_get_battery_charge_status },
2349         { "AT+CPAS", _bt_hfp_get_activity_status },
2350         { "AT+CGSN", _bt_hfp_get_equipment_identity },
2351         { "AT+CGMM", _bt_hfp_get_model_information },
2352         { "AT+CGMI", _bt_hfp_get_device_manufacturer },
2353         { "AT+CGMR", _bt_hfp_get_revision_information },
2354         { "AT+BAC", __bt_hfp_available_codecs },
2355         { "AT+BCC", __bt_hfp_codec_connection },
2356         { "AT+BCS", __bt_hfp_codec_selection },
2357         { "AT+XSAT", _bt_hfp_vendor_cmd },
2358         { "AT+CIMI", _bt_hfp_get_imsi },
2359         { "AT+CREG", _bt_hfp_get_creg_status },
2360         { 0 }
2361 };
2362
2363 int num_of_secure_command = 4;
2364 static const char* secure_command[] = {"CLCC", "CLIP", "CPBR", "CCWA"};
2365
2366 void __bt_ag_agent_print_at_buffer(char *message, const char *buf)
2367 {
2368
2369         int i = 0;
2370         char s[MAX_BUFFER_SIZE] = {0, };
2371         gboolean hide = FALSE;
2372
2373         gboolean is_security_command = FALSE;
2374         char *xsat_ptr;
2375
2376         strncpy(s, buf, MAX_BUFFER_SIZE - 1);
2377
2378         for (i = 0; i < num_of_secure_command; i++) {
2379                 if (strstr(buf, secure_command[i])) {
2380                         is_security_command = TRUE;
2381                         break;
2382                 }
2383         }
2384
2385         /* +XSAT: 11,DISC */
2386         xsat_ptr =  strstr(s, "11,DISC,");
2387         if (xsat_ptr) {
2388                 xsat_ptr = xsat_ptr + 8;
2389                 int x = 0;
2390                 while (xsat_ptr[x] != '\0' && xsat_ptr[x] != '\r' && xsat_ptr[x] != '\n') {
2391                         xsat_ptr[x] = 'X';
2392                         x++;
2393                 }
2394         }
2395
2396         /* AT+XSAT=11,Q_CT,X,XXXX */
2397         xsat_ptr =  strstr(s, "11,Q_CT,");
2398         if (xsat_ptr) {
2399                 xsat_ptr = xsat_ptr + 8;
2400                 int x = 0;
2401                 while (xsat_ptr[x] != '\0' && xsat_ptr[x] != '\r' && xsat_ptr[x] != '\n') {
2402                         if (x > 1) /* ignore 0 and 1 position */
2403                                 xsat_ptr[x] = 'X';
2404                         x++;
2405                 }
2406         }
2407
2408         i = 0;
2409         while (s[i] != '\0') {
2410                 if (s[i] == '\r' || s[i] == '\n') {
2411                         s[i] = '.';
2412                 } else {
2413                         if (s[i] == '\"')
2414                                 hide = hide ? FALSE : TRUE;
2415                         else if (is_security_command && hide) {
2416                                 if (i % 2)
2417                                         s[i] = 'X';
2418                         }
2419                 }
2420                 i++;
2421         }
2422         if (message)
2423                 INFO("%s Buffer = [%s], Len(%d)", message, s, strlen(s));
2424         else
2425                 INFO("[%s]", s);
2426 }
2427
2428 static int __bt_ag_at_handler(bt_ag_info_t *hs, const char *buf)
2429 {
2430         struct event *ev;
2431
2432         __bt_ag_agent_print_at_buffer("[AG AT CMD][RCVD] :", buf);
2433
2434         for (ev = at_event_callbacks; ev->cmd; ev++) {
2435                 if (!strncmp(buf, ev->cmd, strlen(ev->cmd)))
2436                         return ev->callback(hs, buf);
2437         }
2438
2439         return -EINVAL;
2440 }
2441
2442 static int __bt_ag_send_at_valist(bt_ag_info_t *hdset, va_list list,
2443                         char *list_format)
2444 {
2445         ssize_t final_written, count;
2446         char rsp_buffer[MAX_BUFFER_SIZE];
2447         int fd;
2448         int err;
2449
2450         count = vsnprintf(rsp_buffer, sizeof(rsp_buffer), list_format, list);
2451         if (count < 0) {
2452                 ERR("count is %d", count);
2453                 return -EINVAL;
2454         }
2455
2456         if (!hdset->io_chan) {
2457                 ERR("__bt_ag_send_at_valist: headset not connected");
2458                 return -EIO;
2459         }
2460
2461         final_written = 0;
2462
2463         fd = g_io_channel_unix_get_fd(hdset->io_chan);
2464
2465         if (fd != 0) {
2466                 while (final_written < count) {
2467                         ssize_t written;
2468
2469                         do {
2470                                 written = write(fd, rsp_buffer + final_written,
2471                                                 count - final_written);
2472                         } while (written < 0 && errno == EINTR);
2473
2474                         if (written < 0) {
2475                                 err = -errno;
2476                                 ERR("write failed : %s (%d)", strerror(-err), -err);
2477                                 return -errno;
2478                         }
2479
2480                         final_written += written;
2481                 }
2482
2483                 /* Synchronize the sending buffer */
2484                 sync();
2485                 fsync(fd);
2486         } else {
2487                 ERR("FD is 0. remote_addr : %s", hdset->remote_addr);
2488                 return -1;
2489         }
2490
2491         __bt_ag_agent_print_at_buffer("[AG AT CMD][SENT]", rsp_buffer);
2492
2493         return 0;
2494 }
2495
2496 int __attribute__((format(printf, 2, 3)))
2497                         _bt_ag_send_at(bt_ag_info_t *hs, char *format, ...)
2498 {
2499         va_list ap;
2500         int ret;
2501
2502         va_start(ap, format);
2503         ret = __bt_ag_send_at_valist(hs, ap, format);
2504         va_end(ap);
2505
2506         return ret;
2507 }
2508
2509 void __attribute__((format(printf, 3, 4)))
2510                 _bt_ag_send_foreach_headset(GSList *devices,
2511                                 int (*cmp) (bt_ag_info_t *hs),
2512                                 char *format, ...)
2513 {
2514         GSList *l;
2515         va_list ap;
2516
2517         for (l = devices; l != NULL; l = l->next) {
2518                 bt_ag_info_t *hs = l->data;
2519                 int ret;
2520
2521                 if (cmp && cmp(hs) != 0)
2522                         continue;
2523
2524                 va_start(ap, format);
2525                 ret = __bt_ag_send_at_valist(hs, ap, format);
2526                 if (ret < 0)
2527                         ERR("Failed to send to headset: %s (%d)",
2528                                         strerror(-ret), -ret);
2529                 va_end(ap);
2530         }
2531 }
2532
2533 int _bt_ag_send_response(bt_ag_info_t *hs, hfp_state_manager_err_t err)
2534 {
2535         if ((err != HFP_STATE_MNGR_ERR_NONE) && hs->slc->is_cme_enabled)
2536                 return _bt_ag_send_at(hs, "\r\n+CME ERROR: %d\r\n", err);
2537
2538         switch (err) {
2539         case HFP_STATE_MNGR_ERR_NONE:
2540                 return _bt_ag_send_at(hs, "\r\nOK\r\n");
2541         case HFP_STATE_MNGR_ERR_NO_NETWORK_SERVICE:
2542                 return _bt_ag_send_at(hs, "\r\nNO CARRIER\r\n");
2543         default:
2544                 return _bt_ag_send_at(hs, "\r\nERROR\r\n");
2545         }
2546 }
2547
2548 static gboolean __bt_ag_event_handler(GIOChannel *channel,
2549                                 GIOCondition cond, void *user_data)
2550 {
2551         bt_ag_slconn_t *slconn;
2552         unsigned char event_buf[MAX_BUFFER_SIZE];
2553         ssize_t len;
2554         size_t available_buffer;
2555         int fd;
2556         bt_ag_info_t *bt_ag_info = (bt_ag_info_t *)user_data;
2557
2558
2559         if (cond & G_IO_NVAL)
2560                 return FALSE;
2561
2562         slconn = bt_ag_info->slc;
2563         if (cond & (G_IO_ERR | G_IO_HUP)) {
2564                 if (bt_ag_info->watch_id)
2565                         __bt_ag_agent_remove_watch(&bt_ag_info->watch_id);
2566
2567                 ERR("ERR or HUP on RFCOMM socket");
2568                 INFO_C("Disconnected [AG role] [Terminated by remote dev]");
2569                 goto failed;
2570         }
2571
2572         fd = g_io_channel_unix_get_fd(channel);
2573         len = read(fd, event_buf, sizeof(event_buf) - 1);
2574
2575         if (len < 0)
2576                 return FALSE;
2577         available_buffer = sizeof(slconn->buffer) - (slconn->start) -
2578                                 (slconn->length) - 1;
2579         if (available_buffer < (size_t) len) {
2580                 ERR("Buffer over flow");
2581                 goto failed;
2582         }
2583
2584         memcpy(&slconn->buffer[slconn->start], event_buf, len);
2585         slconn->length += len;
2586
2587         slconn->buffer[slconn->start + slconn->length] = '\0';
2588
2589         while (slconn->length > 0) {
2590                 char *get_cr;
2591                 int err;
2592                 off_t cmd_len;
2593
2594                 get_cr = strchr(&slconn->buffer[slconn->start], '\r');
2595                 if (!get_cr)
2596                         break;
2597
2598                 cmd_len = 1 + (off_t) get_cr -
2599                         (off_t) &slconn->buffer[slconn->start];
2600                 *get_cr = '\0';
2601
2602                 if (cmd_len > 1) {
2603                         DBG("Call AT handler");
2604                         err = __bt_ag_at_handler(bt_ag_info,
2605                                         &slconn->buffer[slconn->start]);
2606                 } else {
2607                         ERR("Failed to call AT handler");
2608                         err = 0;
2609                 }
2610
2611                 if (err == -EINVAL) {
2612                         ERR("Unrecognized command: %s",
2613                                 &slconn->buffer[slconn->start]);
2614                         err = _bt_ag_send_response(bt_ag_info,
2615                                         HFP_STATE_MNGR_ERR_NOT_SUPPORTED);
2616                         if (err < 0)
2617                                 goto failed;
2618                 } else if (err < 0)
2619                         ERR("Error handling command %s: %s (%d)",
2620                                                 &slconn->buffer[slconn->start],
2621                                                 strerror(-err), -err);
2622
2623                 slconn->start += cmd_len;
2624                 slconn->length -= cmd_len;
2625
2626                 if (!slconn->length)
2627                         slconn->start = 0;
2628         }
2629         return TRUE;
2630 failed:
2631         ERR("Failed in event handler - SLC Disconnect");
2632         _bt_ag_set_headset_state(bt_ag_info,
2633                                         HEADSET_STATE_DISCONNECTED);
2634         return FALSE;
2635 }
2636
2637 static gboolean __bt_ag_agent_connection(gint32 fd, const gchar *device_path,
2638                                                 const gchar *object_path)
2639 {
2640         GIOFlags flags;
2641
2642         bt_ag_info_t *bt_ag_info = g_new0(bt_ag_info_t, 1);
2643         struct sockaddr_remote address;
2644         socklen_t address_len;
2645
2646         INFO_C("Connected [AG role]");
2647         bt_ag_info->rfcomm = NULL;
2648         bt_ag_info->slc = NULL;
2649         bt_ag_info->hfp_active = TRUE;
2650         bt_ag_info->vr_blacklisted = FALSE;
2651         bt_ag_info->state = HEADSET_STATE_DISCONNECTED;
2652         bt_ag_info->sco_server_started = FALSE;
2653         __bt_ag_codec_negotiation_info_reset(bt_ag_info, TRUE);
2654
2655         bt_ag_info->path = device_path;
2656         DBG("device_path = [%s]", device_path);
2657
2658         address_len = sizeof(address);
2659         if (getpeername(fd, (struct sockaddr *) &address, &address_len) != 0)
2660                 ERR("BD_ADDR is NULL");
2661
2662         DBG("RFCOMM connection for HFP/HSP is completed. Fd = [%d]", fd);
2663         bt_ag_info->fd = fd;
2664         bt_ag_info->io_chan = g_io_channel_unix_new(bt_ag_info->fd);
2665         flags = g_io_channel_get_flags(bt_ag_info->io_chan);
2666
2667         flags &= ~G_IO_FLAG_NONBLOCK;
2668         flags &= G_IO_FLAG_MASK;
2669         g_io_channel_set_flags(bt_ag_info->io_chan, flags, NULL);
2670         g_io_channel_set_encoding(bt_ag_info->io_chan, NULL, NULL);
2671         g_io_channel_set_buffered(bt_ag_info->io_chan, FALSE);
2672
2673         bt_ag_info->rfcomm = g_io_channel_ref(bt_ag_info->io_chan);
2674
2675         bt_ag_info->remote_addr = g_malloc0(BT_ADDRESS_STRING_SIZE);
2676         __bt_convert_addr_type_to_rev_string(bt_ag_info->remote_addr,
2677                                                 address.remote_bdaddr.b);
2678
2679 #if defined(TIZEN_SUPPORT_DUAL_HF)
2680         bt_ag_info->is_companion_device =
2681                         __bt_ag_agent_is_companion_device(bt_ag_info->remote_addr);
2682 #endif
2683
2684         DBG("remote Device Address = [%s]", bt_ag_info->remote_addr);
2685
2686         if (g_strcmp0(object_path, BT_HS_AG_AGENT_OBJECT_PATH) == 0) {
2687                 DBG("HSP connection completed");
2688                 _bt_ag_set_headset_state(bt_ag_info,
2689                                                 HEADSET_STATE_CONNECTED);
2690         } else {
2691                 DBG("HFP connection connecting");
2692                 _bt_ag_set_headset_state(bt_ag_info,
2693                                                 HEADSET_STATE_CONNECTING);
2694         }
2695
2696         __bt_ag_agent_start_watch(bt_ag_info);
2697
2698         bt_ag_info->slc = g_new0(bt_ag_slconn_t, 1);
2699         bt_ag_info->slc->speaker_gain = 15;
2700         bt_ag_info->slc->microphone_gain = 15;
2701         bt_ag_info->slc->is_nrec = TRUE;
2702
2703         return TRUE;
2704 }
2705
2706 static gboolean __bt_ag_agent_is_device_vr_blacklisted(const char *lap_addr)
2707 {
2708         char *buffer;
2709         FILE *fp;
2710         long size;
2711         size_t result;
2712         char *token;
2713         char *saveptr;
2714
2715         fp = fopen(AGENT_VR_BLACKLIST_FILE, "r");
2716
2717         if (fp == NULL) {
2718                 ERR("Unable to open VR blacklist file");
2719                 return FALSE;
2720         }
2721
2722         fseek(fp, 0, SEEK_END);
2723         size = ftell(fp);
2724         if (size <= 0) {
2725                 ERR("size is not a positive number");
2726                 fclose(fp);
2727                 return FALSE;
2728         }
2729
2730         rewind(fp);
2731
2732         buffer = g_malloc0(sizeof(char) * size);
2733         if (buffer == NULL) {
2734                 ERR("g_malloc0 is failed");
2735                 fclose(fp);
2736                 return FALSE;
2737         }
2738         result = fread((char *)buffer, 1, size, fp);
2739         fclose(fp);
2740         if (result != size) {
2741                 ERR("Read Error");
2742                 g_free(buffer);
2743                 return FALSE;
2744         }
2745
2746         token = strtok_r(buffer, "=", &saveptr);
2747         if (token == NULL) {
2748                 g_free(buffer);
2749                 return FALSE;
2750         }
2751
2752         while ((token = strtok_r(NULL, ",", &saveptr))) {
2753                 if (strlen(token) > 8)
2754                         token[8] = '\0';
2755                 if (0 == g_strcmp0(token, lap_addr)) {
2756                         INFO("Voice Recognition blacklisted");
2757                         g_free(buffer);
2758                         return TRUE;
2759                 }
2760         }
2761         g_free(buffer);
2762         return FALSE;
2763 }
2764
2765 static gboolean __bt_sco_open_delay_timeout_cb(gpointer user_data)
2766 {
2767         bt_ag_info_t *bt_ag_info = (bt_ag_info_t *)user_data;
2768         sco_open_timer_id = 0;
2769         DBG("sco_open_request (%d)", sco_open_request);
2770
2771         if (sco_open_request && bt_ag_info->state == HEADSET_STATE_CONNECTED) {
2772                 bt_ag_slconn_t *slconn = bt_ag_info->slc;
2773
2774                 INFO("try to open SCO");
2775                 sco_open_request = FALSE;
2776
2777                 if ((ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) &&
2778                                 (slconn && (slconn->hs_features &
2779                                         BT_HF_FEATURE_CODEC_NEGOTIATION))) {
2780                         switch (bt_ag_info->codec_info.final_codec) {
2781                         case BT_CVSD_CODEC_ID:
2782                                 __bt_ag_set_codec(bt_ag_info, "SetNbParameters");
2783                                 __bt_ag_sco_connect(bt_ag_info);
2784                                 break;
2785                         case BT_MSBC_CODEC_ID:
2786                                 __bt_ag_set_codec(bt_ag_info, "SetWbsParameters");
2787                                 __bt_ag_sco_connect(bt_ag_info);
2788                                 break;
2789                         default:
2790                                 __bt_hfp_codec_connection_setup(bt_ag_info, FALSE);
2791                                 break;
2792                         }
2793                 } else
2794                         __bt_ag_sco_connect(bt_ag_info);
2795         }
2796
2797         return FALSE;
2798 }
2799
2800 /*
2801 * Service level connection complete
2802 * indication and state management
2803 */
2804 void _bt_ag_slconn_complete(bt_ag_info_t *hs)
2805 {
2806         char lap_address[BT_LOWER_ADDRESS_LENGTH];
2807
2808         DBG("HFP Service Level Connection established\n");
2809
2810         /* Check device Voice Recognition blacklist status */
2811         g_strlcpy(lap_address, hs->remote_addr, sizeof(lap_address));
2812         hs->vr_blacklisted =
2813                 __bt_ag_agent_is_device_vr_blacklisted(lap_address);
2814
2815         if (sco_open_timer_id > 0) {
2816                 g_source_remove(sco_open_timer_id);
2817                 sco_open_timer_id = 0;
2818         }
2819
2820         sco_open_request = FALSE;
2821         sco_open_timer_id = g_timeout_add(BT_SCO_OPEN_DELAY_TIMER,
2822                                                 __bt_sco_open_delay_timeout_cb, hs);
2823
2824         _bt_ag_set_headset_state(hs, HEADSET_STATE_CONNECTED);
2825 }
2826
2827 static gboolean __bt_ag_agent_connection_release(bt_ag_info_t *hs)
2828 {
2829
2830         g_io_channel_shutdown(hs->io_chan, TRUE, NULL);
2831         g_io_channel_unref(hs->io_chan);
2832         hs->io_chan = NULL;
2833
2834         if (hs->sco) {
2835                 __bt_ag_close_sco(hs);
2836                 _bt_ag_set_headset_state(hs, HEADSET_STATE_CONNECTED);
2837                 hs->sco = NULL;
2838         }
2839         __bt_ag_agent_remove_watch(&hs->watch_id);
2840
2841         _bt_ag_set_headset_state(hs, HEADSET_STATE_DISCONNECTED);
2842         return TRUE;
2843 }
2844
2845 static GQuark __bt_ag_agent_error_quark(void)
2846 {
2847         FN_START;
2848
2849         static GQuark quark = 0;
2850         if (!quark)
2851                 quark = g_quark_from_static_string("ag-agent");
2852
2853         FN_END;
2854         return quark;
2855 }
2856
2857 static GError *__bt_ag_agent_set_error(bt_hfp_agent_error_t error)
2858 {
2859         FN_START;
2860         ERR("error[%d]\n", error);
2861
2862         switch (error) {
2863         case BT_HFP_AGENT_ERROR_NOT_AVAILABLE:
2864                 return g_error_new(BT_AG_AGENT_ERROR, error,
2865                                         BT_ERROR_NOT_AVAILABLE);
2866         case BT_HFP_AGENT_ERROR_NOT_CONNECTED:
2867         return g_error_new(BT_AG_AGENT_ERROR, error,
2868                                         BT_ERROR_NOT_CONNECTED);
2869         case BT_HFP_AGENT_ERROR_BUSY:
2870                 return g_error_new(BT_AG_AGENT_ERROR, error,
2871                                                 BT_ERROR_BUSY);
2872         case BT_HFP_AGENT_ERROR_INVALID_PARAM:
2873                 return g_error_new(BT_AG_AGENT_ERROR, error,
2874                                                 BT_ERROR_INVALID_PARAM);
2875         case BT_HFP_AGENT_ERROR_ALREADY_EXSIST:
2876                 return g_error_new(BT_AG_AGENT_ERROR, error,
2877                                                 BT_ERROR_ALREADY_EXSIST);
2878         case BT_HFP_AGENT_ERROR_ALREADY_CONNECTED:
2879                 return g_error_new(BT_AG_AGENT_ERROR, error,
2880                                                 BT_ERROR_ALREADY_CONNECTED);
2881         case BT_HFP_AGENT_ERROR_NO_MEMORY:
2882                 return g_error_new(BT_AG_AGENT_ERROR, error,
2883                                                 BT_ERROR_NO_MEMORY);
2884         case BT_HFP_AGENT_ERROR_I_O_ERROR:
2885                 return g_error_new(BT_AG_AGENT_ERROR, error,
2886                                                 BT_ERROR_I_O_ERROR);
2887         case BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE:
2888                 return g_error_new(BT_AG_AGENT_ERROR, error,
2889                                         BT_ERROR_OPERATION_NOT_AVAILABLE);
2890         case BT_HFP_AGENT_ERROR_BATTERY_STATUS:
2891                 return g_error_new(BT_AG_AGENT_ERROR, error,
2892                                         BT_ERROR_BATTERY);
2893         case BT_HFP_AGENT_ERROR_SIGNAL_STATUS:
2894                 return g_error_new(BT_AG_AGENT_ERROR, error,
2895                                         BT_ERROR_SIGNAL);
2896         case BT_HFP_AGENT_ERROR_NO_CALL_LOGS:
2897                 return g_error_new(BT_AG_AGENT_ERROR, error,
2898                                         BT_ERROR_NO_CALL_LOG);
2899         case BT_HFP_AGENT_ERROR_INTERNAL:
2900         default:
2901                 return g_error_new(BT_AG_AGENT_ERROR, error,
2902                                                 BT_ERROR_INTERNAL);
2903         }
2904         FN_END;
2905 }
2906
2907 static bt_ag_info_t *__bt_get_active_headset(const gchar *device_path)
2908 {
2909         GSList *l;
2910
2911         for (l = active_devices ; l; l = l->next) {
2912                 bt_ag_info_t *data = l->data;
2913                 if (device_path == NULL) /*just to avoid crash incase of "play" when dailed from device[NEEDS TO BE CHANGED]*/
2914                         return data;
2915                 if (g_strcmp0(data->path, device_path) == 0) {
2916                         INFO("Active device found");
2917                         return data;
2918                 }
2919         }
2920
2921         INFO("Active device not found");
2922         return NULL;
2923 }
2924
2925 static void __bt_ag_agent_method(GDBusConnection *connection,
2926                         const gchar *sender,
2927                         const gchar *object_path,
2928                         const gchar *interface_name,
2929                         const gchar *method_name,
2930                         GVariant *parameters,
2931                         GDBusMethodInvocation *invocation,
2932                         gpointer user_data)
2933 {
2934         FN_START;
2935
2936         INFO("method %s", method_name);
2937         INFO("object_path %s", object_path);
2938         int ret = BT_HFP_AGENT_ERROR_NONE;
2939         GError *err = NULL;
2940         const gchar *device_path = NULL;
2941
2942         if (g_strcmp0(method_name, "NewConnection") == 0) {
2943                 gint32 fd;
2944                 int index = 0;
2945                 GDBusMessage *msg;
2946                 GUnixFDList *fd_list;
2947                 GVariant *options = NULL;
2948                 int device_count = 0;
2949
2950                 device_count = g_slist_length(active_devices);
2951
2952                 INFO("device_count %d", device_count);
2953
2954                 if (device_count >= MAX_CONNECTED_DEVICES) {
2955                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
2956                         goto fail;
2957                 }
2958
2959                 g_variant_get(parameters, "(oha{sv})",
2960                                                 &device_path, &index, &options);
2961
2962 #if defined(TIZEN_SUPPORT_DUAL_HF) && defined(TIZEN_PROFILE_WEARABLE)
2963                 /*
2964                  * Below code is not required for dual HF support for
2965                  * mobile devices
2966                  */
2967                 if (device_count &&
2968                         __bt_ag_agent_check_dual_hf_condition(device_path) == FALSE) {
2969                         INFO("not allow to connect 2nd HF connection");
2970                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
2971                         goto fail;
2972                 }
2973 #endif
2974                 msg = g_dbus_method_invocation_get_message(invocation);
2975                 fd_list = g_dbus_message_get_unix_fd_list(msg);
2976                 if (fd_list == NULL) {
2977                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
2978                         goto fail;
2979                 }
2980
2981                 fd = g_unix_fd_list_get(fd_list, index, NULL);
2982                 if (fd == -1) {
2983                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
2984                         goto fail;
2985                 }
2986
2987                 DBG("FD is = [%d], device_path = [%s]\n", fd, device_path);
2988
2989                 if (!__bt_ag_agent_connection(fd, device_path, object_path)) {
2990                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
2991                         goto fail;
2992                 }
2993
2994                 g_dbus_method_invocation_return_value(invocation, NULL);
2995         } else if (g_strcmp0(method_name, "RequestDisconnection") == 0) {
2996                 GSList *l;
2997
2998                 g_variant_get(parameters, "(o)", &device_path);
2999                 INFO("device_path %s", device_path);
3000
3001                 for (l = active_devices; l; l = l->next) {
3002                         bt_ag_info_t *data = l->data;
3003
3004                         INFO("data->path %s", data->path);
3005                         if (g_strcmp0(data->path, device_path) == 0) {
3006                                 if (!__bt_ag_agent_connection_release(data)) {
3007                                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3008                                         goto fail;
3009                                 }
3010                                 INFO_C("Disconnected [AG role] [Terminated by local host]");
3011                                 g_dbus_method_invocation_return_value(invocation, NULL);
3012                         }
3013                 }
3014         } else if (g_strcmp0(method_name, "RegisterApplication") == 0) {
3015                 gchar *path = NULL;
3016                 gchar *address = NULL;
3017                 g_variant_get(parameters, "(&s&s)", &path, &address);
3018                 /*local_addr = malloc(strlen(address));
3019                 memcpy(local_addr, address, strlen(address));*/
3020
3021                 DBG("Sender = %s, Application path = %s\n", sender, path);
3022                 ret = _bt_hfp_register_telephony_agent(TRUE, path, sender);
3023                 if (ret)
3024                         goto fail;
3025
3026                 g_free(local_addr);
3027                 local_addr = g_strdup(address);
3028                 DBG("Address = %s\n", local_addr);
3029                 g_dbus_method_invocation_return_value(invocation, NULL);
3030         } else if (g_strcmp0(method_name, "UnregisterApplication") == 0) {
3031                 gchar *path = NULL;
3032                 g_variant_get(parameters, "(&s)", &path);
3033
3034                 DBG("Application path = %s\n", path);
3035                 DBG("Sender = %s\n", sender);
3036
3037                 ret = _bt_hfp_register_telephony_agent(FALSE, path, sender);
3038                 if (ret)
3039                         goto fail;
3040
3041                 g_dbus_method_invocation_return_value(invocation, NULL);
3042         } else if (g_strcmp0(method_name, "IncomingCall") == 0) {
3043                 gchar *path = NULL;
3044                 gchar *number = NULL;
3045                 gint call_id = 0;
3046
3047                 g_variant_get(parameters, "(&s&si)", &path, &number, &call_id);
3048
3049                 DBG("Application path = %s", path);
3050                 DBG_SECURE("Phone number = %s", number);
3051                 DBG("Call id = %d", call_id);
3052
3053                 DBG("Sender = %s", sender);
3054
3055                 ret = _bt_hfp_incoming_call(path, number, call_id, sender);
3056                 if (ret)
3057                         goto fail;
3058                 g_dbus_method_invocation_return_value(invocation, NULL);
3059         } else if (g_strcmp0(method_name, "OutgoingCall") == 0) {
3060                 gchar *path = NULL;
3061                 gchar *number = NULL;
3062                 gint call_id = 0;
3063
3064                 g_variant_get(parameters, "(&s&si)", &path, &number, &call_id);
3065
3066                 DBG("Application path = %s", path);
3067                 DBG_SECURE("Phone number = %s", number);
3068                 DBG("Call id = %d", call_id);
3069
3070                 DBG("Sender = %s", sender);
3071
3072                 ret = _bt_hfp_outgoing_call(path, number, call_id, sender);
3073                 if (ret)
3074                         goto fail;
3075                 g_dbus_method_invocation_return_value(invocation, NULL);
3076         } else if (g_strcmp0(method_name, "ChangeCallStatus") == 0) {
3077                 gchar *path = NULL;
3078                 gchar *number = NULL;
3079                 gint status = 0;
3080                 gint call_id = 0;
3081                 GSList *l;
3082
3083                 g_variant_get(parameters, "(&s&sii)",
3084                                         &path, &number, &status, &call_id);
3085                 DBG("Application path = %s\n", path);
3086                 DBG_SECURE("Number = %s\n", number);
3087                 DBG("Status = %d\n", status);
3088                 DBG("Call id = %d\n", call_id);
3089                 DBG("Sender = %s\n", sender);
3090
3091                 ret = _bt_hfp_change_call_status(path,
3092                                         number, status, call_id, sender);
3093
3094                 if (_bt_hfp_is_call_exist() == FALSE) {
3095                         for (l = active_devices; l; l = l->next) {
3096                                 bt_ag_info_t *data = l->data;
3097
3098                                 if (data->state == HEADSET_STATE_ON_CALL) {
3099                                         __bt_ag_close_sco(data);
3100                                         _bt_ag_set_headset_state(data,
3101                                                 HEADSET_STATE_CONNECTED);
3102                                 }
3103                         }
3104                 }
3105
3106                 if (ret)
3107                         goto fail;
3108                 g_dbus_method_invocation_return_value(invocation, NULL);
3109         } else if (g_strcmp0(method_name, "GetProperties") == 0) {
3110                 GVariantBuilder *builder;
3111                 GVariant *var_data;
3112                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3113
3114                 if (bt_ag_info) {
3115                         gchar *codec = g_strdup("codec");
3116                         gchar *nrec = g_strdup("nrec");
3117
3118                         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3119
3120                         g_variant_builder_add(builder, "{sv}",
3121                                         codec, g_variant_new("u", bt_ag_info->codec_info.final_codec));
3122                         g_variant_builder_add(builder, "{sv}",
3123                                         nrec, g_variant_new("b", bt_ag_info->nrec_status));
3124
3125                         var_data = g_variant_new("(a{sv})", builder);
3126                         g_variant_builder_unref(builder);
3127                         g_dbus_method_invocation_return_value(invocation, var_data);
3128
3129                         g_free(codec);
3130                         g_free(nrec);
3131                 }
3132         } else if (g_strcmp0(method_name, "Disconnect") == 0) {
3133                 char hdset_address[18] = { 0, };
3134                 GSList *l;
3135
3136                 for (l = active_devices; l; l = l->next) {
3137                         bt_ag_info_t *data = l->data;
3138
3139                         __bt_convert_addr_type_to_rev_string(hdset_address,
3140                                         (unsigned char *)data->remote_addr);
3141
3142                         DBG("Disconnect Headset %s, %s\n",
3143                                                 hdset_address, data->path);
3144                         _bt_ag_set_headset_state(data,
3145                                                 HEADSET_STATE_DISCONNECTED);
3146                 }
3147                 g_dbus_method_invocation_return_value(invocation, NULL);
3148         } else if (g_strcmp0(method_name, "IsConnected") == 0) {
3149                 gboolean is_connected = FALSE;
3150                 GSList *l;
3151
3152                 for (l = active_devices; l; l = l->next) {
3153                         bt_ag_info_t *data = l->data;
3154
3155                         if (data->state == HEADSET_STATE_CONNECTED)
3156                                 is_connected = TRUE;
3157                 }
3158                 DBG("is_connected : %s",
3159                                 is_connected ? "Connected" : "Disconnected");
3160
3161                 g_dbus_method_invocation_return_value(invocation,
3162                                 g_variant_new("(b)", is_connected));
3163         } else if (g_strcmp0(method_name, "IndicateCall") == 0) {
3164                 GSList *l;
3165
3166                 if (0 == g_slist_length(active_devices)) {
3167                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3168                         goto fail;
3169                 }
3170
3171                 if (ag.ring_timer) {
3172                         DBG("IndicateCall received when already indicating");
3173                         g_dbus_method_invocation_return_value(invocation, NULL);
3174                 }
3175
3176                 for (l = active_devices; l; l = l->next) {
3177                         bt_ag_info_t *data = l->data;
3178
3179                         if (data->state >= HEADSET_STATE_CONNECTED)
3180                                 _bt_ag_send_at(data, "\r\nRING\r\n");
3181                 }
3182
3183                 __bt_ring_timer_cb(NULL);
3184                 ag.ring_timer = g_timeout_add(AG_RING_INTERVAL,
3185                                 __bt_ring_timer_cb, NULL);
3186                 g_dbus_method_invocation_return_value(invocation, NULL);
3187         } else if (g_strcmp0(method_name, "CancelCall") == 0) {
3188                 if (0 == g_slist_length(active_devices)) {
3189                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3190                         goto fail;
3191                 }
3192
3193                 if (ag.ring_timer) {
3194                         g_source_remove(ag.ring_timer);
3195                         ag.ring_timer = 0;
3196                 } else
3197                         DBG("Got CancelCall method call but no call is active");
3198
3199                 g_dbus_method_invocation_return_value(invocation, NULL);
3200         } else if (g_strcmp0(method_name, "Play") == 0) {
3201                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3202                 bt_ag_slconn_t *slconn = NULL;
3203
3204                 if (bt_ag_info) {
3205                         slconn = bt_ag_info->slc;
3206                 } else {
3207                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3208                         goto fail;
3209                 }
3210
3211 #ifndef __TIZEN_OPEN__
3212 #ifdef MDM_PHASE_2
3213                 int mode;
3214                 if (slconn && FALSE == slconn->is_voice_recognition_running &&
3215                                 mdm_get_service() == MDM_RESULT_SUCCESS) {
3216                         mode = mdm_get_allow_bluetooth_outgoing_call();
3217                         mdm_release_service();
3218
3219                         if (mode == MDM_RESTRICTED) {
3220                                 ERR("[MDM] Not allow the outgoing call");
3221                                 ret = BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE;
3222                                 goto fail;
3223                         }
3224                 }
3225 #endif
3226 #endif
3227
3228                 switch (bt_ag_info->state) {
3229                 case HEADSET_STATE_CONNECTING:
3230                 case HEADSET_STATE_DISCONNECTED:
3231                         ERR("HEADSET_STATE  ERROR");
3232                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3233                         break;
3234                 case HEADSET_STATE_CONNECTED:
3235                         break;
3236                 case HEADSET_STATE_PLAY_IN_PROGRESS:
3237                         ERR("Play In Progress");
3238                         ret = BT_HFP_AGENT_ERROR_BUSY;
3239                         break;
3240                 default:
3241                         break;
3242                 }
3243                 if (ret)
3244                         goto fail;
3245
3246                 if (sco_open_timer_id > 0) {
3247                         INFO("SCO open delay");
3248                         sco_open_request = TRUE;
3249                         g_dbus_method_invocation_return_value(invocation, NULL);
3250                         return;
3251                 }
3252
3253                 if ((ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) &&
3254                                 (slconn && (slconn->hs_features &
3255                                         BT_HF_FEATURE_CODEC_NEGOTIATION))) {
3256                         switch (bt_ag_info->codec_info.final_codec) {
3257                         case BT_CVSD_CODEC_ID:
3258                                 __bt_ag_set_codec(bt_ag_info, "SetNbParameters");
3259                                 ret = __bt_ag_sco_connect(bt_ag_info);
3260                                 break;
3261                         case BT_MSBC_CODEC_ID:
3262                                 __bt_ag_set_codec(bt_ag_info, "SetWbsParameters");
3263                                 ret = __bt_ag_sco_connect(bt_ag_info);
3264                                 break;
3265                         default:
3266                                 ret = __bt_hfp_codec_connection_setup(bt_ag_info, FALSE);
3267                                 break;
3268                         }
3269                 } else
3270                         ret = __bt_ag_sco_connect(bt_ag_info);
3271
3272                 if (ret)
3273                         goto fail;
3274
3275                 g_free(sco_owner);
3276                 sco_owner = g_strdup(sender);
3277
3278                 g_dbus_method_invocation_return_value(invocation, NULL);
3279
3280                 name_owner_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
3281                                         NULL, NULL, "NameOwnerChanged", NULL, NULL, 0,
3282                                         __bt_ag_name_owner_changed_cb, NULL, NULL);
3283         } else if (g_strcmp0(method_name, "Stop") == 0) {
3284                 GSList *l;
3285
3286                 for (l = active_devices; l; l = l->next) {
3287                         bt_ag_info_t *data = l->data;
3288
3289                         if (data->state > HEADSET_STATE_CONNECTED) {
3290                                 __bt_ag_close_sco(data);
3291                                 _bt_ag_set_headset_state(data,
3292                                         HEADSET_STATE_CONNECTED);
3293                         }
3294                 }
3295
3296                 g_dbus_method_invocation_return_value(invocation, NULL);
3297         } else if (g_strcmp0(method_name, "IsPlaying") == 0) {
3298                 gboolean is_playing = FALSE;
3299                 GSList *l;
3300
3301                 for (l = active_devices; l; l = l->next) {
3302                         bt_ag_info_t *data = l->data;
3303
3304                         if (data->state == HEADSET_STATE_ON_CALL)
3305                                 is_playing = TRUE;
3306                 }
3307                 DBG("is_playing : %s", is_playing ? "Playing" : "Not Playing");
3308
3309                 g_dbus_method_invocation_return_value(invocation,
3310                                 g_variant_new("(b)", is_playing));
3311         } else if (g_strcmp0(method_name, "GetSpeakerGain") == 0) {
3312                 bt_ag_slconn_t *slconn = NULL;
3313                 guint16 gain_value = 0;
3314                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3315
3316                 if (bt_ag_info == NULL) {
3317                         ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
3318                         goto fail;
3319                 }
3320
3321                 if (bt_ag_info->state < HEADSET_STATE_CONNECTED) {
3322                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3323                         goto fail;
3324                 }
3325
3326                 slconn = bt_ag_info->slc;
3327                 if (slconn)
3328                         gain_value = (guint16) slconn->speaker_gain;
3329
3330                 g_dbus_method_invocation_return_value(invocation,
3331                                 g_variant_new("(q)", gain_value));
3332         } else if (g_strcmp0(method_name, "SetSpeakerGain") == 0) {
3333                 guint16 gain = 0;
3334                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3335
3336                 g_variant_get(parameters, "(q)", &gain);
3337                 DBG("Speaker gain = %d\n", gain);
3338
3339                 if (bt_ag_info == NULL) {
3340                         ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
3341                         goto fail;
3342                 }
3343
3344                 ret = _bt_hfp_set_speaker_gain(bt_ag_info, gain);
3345                 if (ret)
3346                         goto fail;
3347                 g_dbus_method_invocation_return_value(invocation, NULL);
3348         } else if (g_strcmp0(method_name, "GetMicrophoneGain") == 0) {
3349                 bt_ag_slconn_t *slconn = NULL;
3350                 guint16 gain_value = 0;
3351                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3352
3353                 if (bt_ag_info == NULL) {
3354                         ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
3355                         goto fail;
3356                 }
3357
3358                 if (bt_ag_info->state < HEADSET_STATE_CONNECTED) {
3359                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3360                         goto fail;
3361                 }
3362
3363                 slconn = bt_ag_info->slc;
3364                 if (slconn)
3365                         gain_value = (guint16) slconn->microphone_gain;
3366
3367                 g_dbus_method_invocation_return_value(invocation,
3368                                 g_variant_new("(q)", gain_value));
3369         } else if (g_strcmp0(method_name, "SetMicrophoneGain") == 0) {
3370                 guint16 gain = 0;
3371                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3372
3373                 g_variant_get(parameters, "(q)", &gain);
3374                 DBG("Microphone gain = %d\n", gain);
3375
3376                 if (bt_ag_info == NULL) {
3377                         ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
3378                         goto fail;
3379                 }
3380
3381                 ret = _bt_hfp_set_microphone_gain(bt_ag_info, gain);
3382                 if (ret)
3383                         goto fail;
3384                 g_dbus_method_invocation_return_value(invocation, NULL);
3385         } else if (g_strcmp0(method_name, "SetVoiceDial") == 0) {
3386                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3387                 if (bt_ag_info == NULL) {
3388                         ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
3389                         goto fail;
3390                 }
3391
3392                 bt_ag_slconn_t *slconn = bt_ag_info->slc;
3393                 gboolean enable;
3394
3395                 g_variant_get(parameters, "(b)", &enable);
3396                 DBG("VoiceDail enable = %d\n", enable);
3397
3398                 if ((slconn && !(slconn->hs_features &
3399                                         BT_HF_FEATURE_VOICE_RECOGNITION)))
3400                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3401                 else if (bt_ag_info->vr_blacklisted)
3402                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3403                 else
3404                         ret = _bt_hfp_set_voice_dial(bt_ag_info, enable);
3405
3406                 if (slconn)
3407                         slconn->is_voice_recognition_running = enable;
3408
3409                 if (ret)
3410                         goto fail;
3411                 g_dbus_method_invocation_return_value(invocation, NULL);
3412         } else if (g_strcmp0(method_name, "SendVendorAtCmd") == 0) {
3413                 gchar *cmd;
3414                 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3415                 if (bt_ag_info == NULL) {
3416                         ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
3417                         goto fail;
3418                 }
3419
3420                 g_variant_get(parameters, "(&s)", &cmd);
3421                 if (cmd == NULL) {
3422                         ret = BT_HFP_AGENT_ERROR_INVALID_PARAM;
3423                         goto fail;
3424                 }
3425
3426                 DBG("vendor cmd = %s", cmd);
3427
3428                 ret = _bt_hfp_send_vendor_cmd(bt_ag_info, cmd);
3429                 if (ret)
3430                         goto fail;
3431                 g_dbus_method_invocation_return_value(invocation, NULL);
3432         } else if (g_strcmp0(method_name, "CheckPrivilege") == 0) {
3433                 DBG("Already pass dbus SMACK for bt-service::platform");
3434                 /* Return success */
3435                 g_dbus_method_invocation_return_value(invocation, NULL);
3436         }  else if (g_strcmp0(method_name, "SwapHeadset") == 0) {
3437                 GSList *l;
3438                 gchar *addr = NULL;
3439                 char address[BT_ADDRESS_STRING_SIZE];
3440                 char remote_addr[BT_ADDRESS_STRING_SIZE];
3441                 gboolean device_found = FALSE;
3442
3443                 g_variant_get(parameters, "(s)", &addr);
3444                 g_strlcpy(address, addr, sizeof(address));
3445                 DBG("Sender = %s", sender);
3446
3447                 /* Loop through connected headset list
3448                  * If found, update the remote_dev_path.
3449                  */
3450                 for (l = active_devices ; l; l = l->next) {
3451                         bt_ag_info_t *data = l->data;
3452                         g_strlcpy(remote_addr, data->remote_addr, sizeof(remote_addr));
3453                         if (g_strcmp0(remote_addr, address) == 0) {
3454                                 DBG("Active device found");
3455                                 if (data->path == NULL) {
3456                                         DBG("device path is null");
3457                                         ret = BT_HFP_AGENT_ERROR_INTERNAL;
3458                                         goto fail;
3459                                 }
3460                                 remote_dev_path = g_strdup(data->path);
3461                                 DBG("Setting device path %s as active device path", remote_dev_path);
3462                                 device_found = TRUE;
3463                                 break;
3464                         }
3465                 }
3466
3467                 if (!device_found) {
3468                         ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3469                         goto fail;
3470                 }
3471
3472                 g_dbus_method_invocation_return_value(invocation, NULL);
3473         }
3474
3475         INFO("-");
3476         return;
3477
3478 fail:
3479         err = __bt_ag_agent_set_error(ret);
3480         g_dbus_method_invocation_return_gerror(invocation, err);
3481         g_error_free(err);
3482         INFO("-");
3483 }
3484
3485 static const GDBusInterfaceVTable method_table = {
3486         __bt_ag_agent_method,
3487         NULL,
3488         NULL,
3489 };
3490
3491 static GDBusNodeInfo *__bt_ag_create_method_node_info
3492                                         (const gchar *introspection_data)
3493 {
3494         GError *err = NULL;
3495         GDBusNodeInfo *node_info = NULL;
3496
3497         if (introspection_data == NULL)
3498                 return NULL;
3499
3500         node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
3501
3502         if (err) {
3503                 ERR("Unable to create node: %s", err->message);
3504                 g_clear_error(&err);
3505         }
3506         return node_info;
3507 }
3508
3509 static GDBusConnection *__bt_ag_get_gdbus_connection(void)
3510 {
3511         FN_START;
3512
3513         GError *err = NULL;
3514
3515         if (ag_dbus_conn == NULL)
3516                 ag_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
3517
3518         if (!ag_dbus_conn) {
3519                 if (err) {
3520                         ERR("Unable to connect to dbus: %s", err->message);
3521                         g_clear_error(&err);
3522                 }
3523                 return NULL;
3524         }
3525         FN_END;
3526
3527         return ag_dbus_conn;
3528 }
3529
3530 static gboolean __bt_ag_register_profile_methods(void)
3531 {
3532         FN_START;
3533         GError *error = NULL;
3534         guint owner_id;
3535         GDBusNodeInfo *node_info = NULL;
3536         gchar *path;
3537
3538         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
3539                                 BT_AG_SERVICE_NAME,
3540                                 G_BUS_NAME_OWNER_FLAGS_NONE,
3541                                 NULL, NULL, NULL,
3542                                 NULL, NULL);
3543
3544         DBG("owner_id is [%d]", owner_id);
3545
3546         node_info = __bt_ag_create_method_node_info(
3547                                 ag_agent_bluez_introspection_xml);
3548         if (node_info == NULL)
3549                 return FALSE;
3550
3551         path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
3552         DBG("path is [%s]", path);
3553
3554         hf_bluez_id = g_dbus_connection_register_object(ag_dbus_conn, path,
3555                                         node_info->interfaces[0],
3556                                         &method_table,
3557                                         NULL, NULL, &error);
3558         if (hf_bluez_id == 0) {
3559                 ERR("Failed to register: %s", error->message);
3560                 g_error_free(error);
3561                 g_free(path);
3562                 g_dbus_node_info_unref(node_info);
3563                 return FALSE;
3564         }
3565         g_free(path);
3566
3567         /* Ag register profile methods for HSP*/
3568
3569         path = g_strdup(BT_HS_AG_AGENT_OBJECT_PATH);
3570         DBG("path is [%s]", path);
3571
3572         hs_bluez_id = g_dbus_connection_register_object(ag_dbus_conn, path,
3573                                         node_info->interfaces[0],
3574                                         &method_table,
3575                                         NULL, NULL, &error);
3576         if (hs_bluez_id == 0) {
3577                 ERR("Failed to register: %s", error->message);
3578                 g_error_free(error);
3579                 g_free(path);
3580                 g_dbus_node_info_unref(node_info);
3581                 return FALSE;
3582         }
3583         g_free(path);
3584         g_dbus_node_info_unref(node_info);
3585
3586         node_info = __bt_ag_create_method_node_info
3587                                 (ag_agent_app_introspection_xml);
3588         if (node_info == NULL)
3589                 return FALSE;
3590
3591         path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
3592         DBG("path is [%s]", path);
3593
3594         app_id = g_dbus_connection_register_object(ag_dbus_conn, path,
3595                                                 node_info->interfaces[0],
3596                                                 &method_table,
3597                                                 NULL, NULL, &error);
3598         if (app_id == 0) {
3599                 ERR("Failed to register: %s", error->message);
3600                 g_error_free(error);
3601                 g_free(path);
3602                 g_dbus_node_info_unref(node_info);
3603                 return FALSE;
3604         }
3605         g_free(path);
3606         g_dbus_node_info_unref(node_info);
3607
3608         FN_END;
3609         return TRUE;
3610 }
3611
3612 static void __bt_ag_unregister_profile_methods(void)
3613 {
3614         DBG("");
3615
3616         if (hf_bluez_id > 0) {
3617                 g_dbus_connection_unregister_object(ag_dbus_conn,
3618                                                         hf_bluez_id);
3619                 hf_bluez_id = 0;
3620         }
3621
3622         if (hs_bluez_id > 0) {
3623                 g_dbus_connection_unregister_object(ag_dbus_conn,
3624                                                         hs_bluez_id);
3625                 hs_bluez_id = 0;
3626         }
3627
3628         if (app_id > 0) {
3629                 g_dbus_connection_unregister_object(ag_dbus_conn,
3630                                                         app_id);
3631                 app_id = 0;
3632         }
3633 }
3634
3635 static GDBusProxy *__bt_ag_gdbus_get_service_proxy(const gchar *service,
3636                                 const gchar *path, const gchar *interface)
3637 {
3638         return (service_gproxy) ? service_gproxy :
3639                         __bt_ag_gdbus_init_service_proxy(service,
3640                                         path, interface);
3641 }
3642
3643 static void __bt_ag_agent_register(gchar *path, uint16_t profile_version,
3644                                 char *profile_uuid, const char* profile_name)
3645 {
3646         FN_START;
3647         GDBusProxy *proxy;
3648         GVariant *ret;
3649         GError *error = NULL;
3650         GVariantBuilder *builder;
3651
3652         proxy = __bt_ag_gdbus_get_service_proxy(BLUEZ_SERVICE_NAME,
3653                 "/org/bluez", BLUEZ_PROFILE_MGMT_INTERFACE);
3654         if (proxy == NULL)
3655                 return;
3656
3657
3658         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3659
3660         g_variant_builder_add(builder, "{sv}",
3661                         "Name", g_variant_new("s",
3662                         profile_name));
3663         g_variant_builder_add(builder, "{sv}",
3664                         "Version", g_variant_new("q", profile_version));
3665         /*g_variant_builder_add(builder, "{sv}",
3666                         "Role", g_variant_new("s","client"));*/
3667         if (g_strcmp0(path, BT_AG_AGENT_OBJECT_PATH) == 0) {
3668                 g_variant_builder_add(builder, "{sv}",
3669                                 "features", g_variant_new("q", ag.sdp_features));
3670         }
3671
3672         ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile",
3673                                         g_variant_new("(osa{sv})", path,
3674                                                         profile_uuid, builder),
3675                                         G_DBUS_CALL_FLAGS_NONE, -1,
3676                                         NULL, &error);
3677         g_variant_builder_unref(builder);
3678         /* set the name and role for the profile*/
3679         if (ret == NULL) {
3680                 /* dBUS-RPC is failed */
3681                 ERR("dBUS-RPC is failed");
3682
3683                 if (error != NULL) {
3684                         /* dBUS gives error cause */
3685                         ERR("D-Bus API failure: errCode[%x], message[%s]",
3686                                         error->code, error->message);
3687
3688                         g_clear_error(&error);
3689                 }
3690                 g_free(path);
3691                 return;
3692         }
3693         g_variant_unref(ret);
3694         g_free(path);
3695
3696         FN_END;
3697         return;
3698 }
3699
3700 static void __bt_ag_agent_unregister(gchar *path)
3701 {
3702         FN_START;
3703         GDBusProxy *proxy;
3704         GVariant *ret;
3705         GError *error = NULL;
3706
3707         proxy = __bt_ag_gdbus_get_service_proxy(BLUEZ_SERVICE_NAME,
3708                 "/org/bluez", BLUEZ_PROFILE_MGMT_INTERFACE);
3709         if (proxy == NULL)
3710                 return;
3711
3712
3713         ret = g_dbus_proxy_call_sync(proxy, "UnregisterProfile",
3714                                         g_variant_new("(o)", path),
3715                                         G_DBUS_CALL_FLAGS_NONE, -1,
3716                                         NULL, &error);
3717         g_free(path);
3718         /* set the name and role for the profile*/
3719         if (ret == NULL) {
3720                 /* dBUS-RPC is failed */
3721                 ERR("dBUS-RPC is failed");
3722
3723                 if (error != NULL) {
3724                         /* dBUS gives error cause */
3725                         ERR("D-Bus API failure: errCode[%x], message[%s]",
3726                                         error->code, error->message);
3727
3728                         g_clear_error(&error);
3729                 }
3730                 return;
3731         }
3732         g_variant_unref(ret);
3733
3734         if (local_addr) {
3735                 g_free(local_addr);
3736                 local_addr = NULL;
3737         }
3738         FN_END;
3739         return;
3740 }
3741
3742 static void __bt_ag_agent_battery_status_cb(keynode_t *node)
3743 {
3744         int batt = vconf_keynode_get_int(node);
3745
3746         _bt_hfp_set_property_value("BatteryBarsChanged", batt);
3747 }
3748
3749 static void __bt_ag_agent_network_signal_status_cb(keynode_t *node)
3750 {
3751         int signal_bar = vconf_keynode_get_int(node);
3752
3753         BT_CHECK_SIGNAL_STRENGTH(signal_bar);
3754         _bt_hfp_set_property_value("SignalBarsChanged", signal_bar);
3755 }
3756
3757 #ifdef TIZEN_FEATURE_BT_LUNAR_DEVICE
3758 static void __bt_ag_agent_lunar_connection_status_cb(keynode_t *node)
3759 {
3760         gboolean status = vconf_keynode_get_bool(node);
3761         GSList *l;
3762         DBG("status = %d", status);
3763
3764         if (status == TRUE) {
3765                 for (l = active_devices; l; l = l->next) {
3766                         bt_ag_info_t *data = l->data;
3767                         _bt_ag_send_at(data, "\r\n+BSIR:1\r\n");
3768                 }
3769         }
3770 }
3771 #endif
3772
3773 static void __bt_ag_agent_network_register_status_cb(keynode_t *node)
3774 {
3775         int service = vconf_keynode_get_int(node);
3776         bt_hfp_agent_network_registration_status_t network_service;
3777         int roam_status;
3778         int ret;
3779
3780         DBG("Current Signal Level = [%d] \n", service);
3781
3782         switch (service) {
3783         case VCONFKEY_TELEPHONY_SVCTYPE_NONE:
3784         case VCONFKEY_TELEPHONY_SVCTYPE_NOSVC:
3785         case VCONFKEY_TELEPHONY_SVCTYPE_SEARCH:
3786                 service = 0;
3787                 break;
3788         default:
3789                 service = 1;
3790                 break;
3791         }
3792
3793         ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
3794         if (ret != 0) {
3795                 ERR("Get roaming status failed err = %d\n", ret);
3796                 return;
3797         }
3798
3799         if (roam_status == 0 && service == 1)
3800                 network_service = BT_AGENT_NETWORK_REG_STATUS_HOME;
3801         else if (roam_status == 1 && service == 1)
3802                 network_service = BT_AGENT_NETWORK_REG_STATUS_ROAMING;
3803         else
3804                 network_service = BT_AGENT_NETWORK_REG_STATUS_UNKOWN;
3805
3806         _bt_hfp_set_property_value("RegistrationChanged", network_service);
3807 }
3808
3809 static void __bt_ag_agent_subscribe_vconf_updates(void)
3810 {
3811         int ret;
3812
3813         DBG("\n");
3814
3815         ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
3816                                 (void *)__bt_ag_agent_battery_status_cb, NULL);
3817         if (0 != ret)
3818                 ERR("Subsrciption to battery status failed err =  [%d]\n", ret);
3819
3820         ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_RSSI,
3821                         (void *)__bt_ag_agent_network_signal_status_cb, NULL);
3822         if (0 != ret)
3823                 ERR("Subsrciption to netowrk signal failed err =  [%d]\n", ret);
3824
3825         ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
3826                         (void *)__bt_ag_agent_network_register_status_cb, NULL);
3827         if (0 != ret)
3828                 ERR("Subsrciption to network failed err =  [%d]\n", ret);
3829
3830 #ifdef TIZEN_FEATURE_BT_LUNAR_DEVICE
3831         ret = vconf_notify_key_changed(VCONF_KEY_BT_LUNAR_ENABLED,
3832                         (void *)__bt_ag_agent_lunar_connection_status_cb, NULL);
3833         if (0 != ret)
3834                 ERR("Subsrciption to lunar connection failed err =  [%d]\n", ret);
3835
3836 #endif
3837 }
3838
3839 static void __bt_ag_agent_release_vconf_updates(void)
3840 {
3841         int ret;
3842
3843         DBG("\n");
3844
3845         ret = vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
3846                         (vconf_callback_fn)__bt_ag_agent_battery_status_cb);
3847         if (0 != ret)
3848                 ERR("vconf_ignore_key_changed failed\n");
3849
3850         ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_RSSI,
3851                 (vconf_callback_fn)__bt_ag_agent_network_signal_status_cb);
3852         if (0 != ret)
3853                 ERR("vconf_ignore_key_changed failed\n");
3854
3855         ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
3856                 (vconf_callback_fn)__bt_ag_agent_network_register_status_cb);
3857         if (0 != ret)
3858                 ERR("vconf_ignore_key_changed failed\n");
3859 }
3860
3861 static gboolean __bt_ag_agent_send_subscriber_number_changed(
3862                                                         const char *number)
3863 {
3864         const char *property = g_strdup("SubscriberNumberChanged");
3865
3866         FN_START;
3867
3868         DBG("Number is %s", number);
3869
3870         if (!_bt_hfp_set_property_name(property, number)) {
3871                 DBG("Error- set property for subscriber no change  - ERROR\n");
3872                 g_free((void *)property);
3873                 return FALSE;
3874         }
3875         g_free((void *)property);
3876         FN_END;
3877         return TRUE;
3878 }
3879 static void __bt_ag_agent_sigterm_handler(int signo)
3880 {
3881         int i;
3882         GSList *l;
3883
3884         ERR_C("***** Signal handler came with signal %d *****", signo);
3885
3886         for (l = active_devices ; l; l = l->next) {
3887                 bt_ag_info_t *data = l->data;
3888                 if (!__bt_ag_agent_connection_release(data))
3889                         ERR("__bt_ag_agent_connection_release failed");
3890         }
3891         if (ag_dbus_conn)
3892                 g_dbus_connection_flush(ag_dbus_conn, NULL, NULL, NULL);
3893
3894         if (gmain_loop) {
3895                 g_main_loop_quit(gmain_loop);
3896                 DBG("Exiting");
3897                 gmain_loop = NULL;
3898         } else {
3899                 INFO("Terminating AG agent");
3900                 exit(0);
3901         }
3902
3903         if (signo == SIGTERM)
3904                 return;
3905
3906         for (i = 0; i < BT_AG_SIG_NUM; i++)
3907                 sigaction(bt_ag_sig_to_handle[i], &(bt_ag_sigoldact[i]), NULL);
3908
3909         raise(signo);
3910 }
3911
3912 static void  __bt_ag_agent_tel_cb(TapiHandle *handle,
3913                                 int result,
3914                                 void *data,
3915                                 void *user_data)
3916 {
3917         TelSimMsisdnList_t *number;
3918         gchar *subscriber_number;
3919
3920         ERR("*********** result = %d", result);
3921
3922         if (result == TAPI_API_SIM_LOCKED ||
3923                 result == TAPI_API_SIM_NOT_INITIALIZED ||
3924                 result == TAPI_API_SERVICE_NOT_READY) {
3925                 DBG("initializing the tapi event for SIM status");
3926                 __bt_ag_agent_reg_sim_event(handle, user_data);
3927                 return;
3928         }
3929
3930         if (data == NULL)
3931                 return;
3932
3933         number = (TelSimMsisdnList_t *)data;
3934         subscriber_number = g_strdup(number->list[0].num);
3935         __bt_ag_agent_send_subscriber_number_changed(subscriber_number);
3936         g_free(subscriber_number);
3937 }
3938
3939 static void __bt_ag_agent_on_noti_sim_status(TapiHandle *handle,
3940                 const char *noti_id, void *data, void *user_data)
3941 {
3942         TelSimCardStatus_t *status = data;
3943         int tapi_result;
3944
3945         DBG("event TAPI_NOTI_SIM_STATUS received!! status[%d]", *status);
3946
3947         if (*status == TAPI_SIM_STATUS_SIM_INIT_COMPLETED) {
3948                 __bt_ag_agent_dereg_sim_event(handle);
3949                 tapi_result = tel_get_sim_msisdn(handle, __bt_ag_agent_tel_cb,
3950                                         user_data);
3951                 if (tapi_result != TAPI_API_SUCCESS)
3952                         ERR("Fail to get sim info: %d", tapi_result);
3953         }
3954 }
3955
3956 static void __bt_ag_agent_reg_sim_event(TapiHandle *handle, void *user_data)
3957 {
3958         int ret;
3959         ret = tel_register_noti_event(handle, TAPI_NOTI_SIM_STATUS,
3960                 __bt_ag_agent_on_noti_sim_status, user_data);
3961
3962         if (ret != TAPI_API_SUCCESS)
3963                 ERR("event register failed(%d)", ret);
3964 }
3965
3966 static void __bt_ag_agent_dereg_sim_event(TapiHandle *handle)
3967 {
3968         int ret;
3969         ret = tel_deregister_noti_event(handle, TAPI_NOTI_SIM_STATUS);
3970
3971         if (ret != TAPI_API_SUCCESS)
3972                 ERR("event deregister failed(%d)", ret);
3973 }
3974
3975 static void __bt_ag_name_owner_changed_cb(GDBusConnection *connection,
3976                                         const gchar *sender_name,
3977                                         const gchar *object_path,
3978                                         const gchar *interface_name,
3979                                         const gchar *signal_name,
3980                                         GVariant *parameters,
3981                                         gpointer user_data)
3982 {
3983         FN_START;
3984         char *name_owner = NULL;
3985         char *old_owner = NULL;
3986         char *new_owner = NULL;
3987
3988         if (strcasecmp(signal_name, "NameOwnerChanged") == 0) {
3989                 GSList *l;
3990
3991                 g_variant_get(parameters, "(sss)", &name_owner, &old_owner, &new_owner);
3992
3993                 _bt_hfp_release_all_calls_by_sender(name_owner);
3994
3995                 if (sco_owner == NULL)
3996                         return;
3997
3998                 if (strcasecmp(name_owner, sco_owner) == 0) {
3999                         if (name_owner_sig_id != -1)
4000                                 g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4001                                                         name_owner_sig_id);
4002                         name_owner_sig_id = -1;
4003                         g_free(sco_owner);
4004                         sco_owner = NULL;
4005
4006                         for (l = active_devices ; l; l = l->next) {
4007                                 bt_ag_info_t *data = l->data;
4008
4009                                 if (data->sco) {
4010                                         __bt_ag_close_sco(data);
4011                                         _bt_ag_set_headset_state(data,
4012                                                 HEADSET_STATE_CONNECTED);
4013                                 }
4014                         }
4015                 }
4016         }
4017 }
4018
4019 static void __bt_ag_agent_filter_cb(GDBusConnection *connection,
4020                                         const gchar *sender_name,
4021                                         const gchar *object_path,
4022                                         const gchar *interface_name,
4023                                         const gchar *signal_name,
4024                                         GVariant *parameters,
4025                                         gpointer user_data)
4026 {
4027         FN_START;
4028         char *path = NULL;
4029         GVariant *optional_param = NULL;
4030
4031         if (strcasecmp(signal_name, "InterfacesAdded") == 0) {
4032
4033                 g_variant_get(parameters, "(&o@a{sa{sv}})",
4034                                                         &path, &optional_param);
4035                 if (!path) {
4036                         if (optional_param)
4037                                 g_variant_unref(optional_param);
4038                         ERR("Invalid adapter path");
4039                         return;
4040                 }
4041
4042                 INFO("Adapter Path = [%s]", path);
4043                 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
4044                         gchar *path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
4045                         __bt_ag_agent_register(path, hfp_ver,
4046                                  HFP_AG_UUID, "Hands-Free Audio Gateway");
4047
4048                         path =  g_strdup(BT_HS_AG_AGENT_OBJECT_PATH);
4049                         __bt_ag_agent_register(path, hsp_ver,
4050                                 HSP_AG_UUID, "Headset Audio Gateway");
4051                 }
4052         } else if (strcasecmp(signal_name, "InterfacesRemoved") == 0) {
4053                 g_variant_get(parameters, "(&o@as)", &path, &optional_param);
4054                 if (!path) {
4055                         if (optional_param)
4056                                 g_variant_unref(optional_param);
4057                         ERR("Invalid adapter path");
4058                         return;
4059                 }
4060
4061                 INFO("Adapter Path = [%s]", path);
4062                 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
4063                         gchar *path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
4064                         __bt_ag_agent_unregister(path);
4065
4066                         path =  g_strdup(BT_HS_AG_AGENT_OBJECT_PATH);
4067                         __bt_ag_agent_unregister(path);
4068                 }
4069         }
4070
4071         if (optional_param)
4072                 g_variant_unref(optional_param);
4073
4074         FN_END;
4075 }
4076
4077 static void __bt_ag_agent_dbus_deinit(void)
4078 {
4079
4080         if (service_gproxy) {
4081                 g_object_unref(service_gproxy);
4082                 service_gproxy = NULL;
4083         }
4084
4085         if (app_gproxy) {
4086                 g_object_unref(app_gproxy);
4087                 app_gproxy = NULL;
4088         }
4089
4090         if (ag_dbus_conn) {
4091                 __bt_ag_unregister_profile_methods();
4092
4093                 if (owner_sig_id != -1)
4094                         g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4095                                                 owner_sig_id);
4096
4097                 if (name_owner_sig_id != -1)
4098                         g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4099                                                 name_owner_sig_id);
4100 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
4101                 if (media_sig_id != -1)
4102                         g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4103                                                 media_sig_id);
4104
4105                 if (media_state_sig_id != -1)
4106                         g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4107                                                 media_state_sig_id);
4108 #endif
4109                 name_owner_sig_id = -1;
4110                 g_free(sco_owner);
4111                 sco_owner = NULL;
4112
4113                 g_object_unref(ag_dbus_conn);
4114                 ag_dbus_conn = NULL;
4115         }
4116         return;
4117 }
4118
4119 static int __bt_ag_agent_get_adapter_path(GDBusConnection *conn, char *path)
4120 {
4121         GError *err = NULL;
4122         GDBusProxy *manager_proxy = NULL;
4123         GVariant *result = NULL;
4124         char *adapter_path = NULL;
4125
4126         if (conn == NULL)
4127                 return BT_HFP_AGENT_ERROR_INTERNAL;
4128
4129         manager_proxy =  g_dbus_proxy_new_sync(conn,
4130                         G_DBUS_PROXY_FLAGS_NONE, NULL,
4131                         BLUEZ_SERVICE_NAME,
4132                         "/",
4133                         BT_MANAGER_INTERFACE,
4134                         NULL, &err);
4135
4136         if (!manager_proxy) {
4137                 ERR("Unable to create proxy: %s", err->message);
4138                 goto fail;
4139         }
4140
4141         result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
4142                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
4143         if (!result) {
4144                 if (err != NULL)
4145                         ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
4146                 else
4147                         ERR("Fail to get DefaultAdapter");
4148
4149                 goto fail;
4150         }
4151
4152         if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
4153                 ERR("Incorrect result\n");
4154                 goto fail;
4155         }
4156
4157         g_variant_get(result, "(&o)", &adapter_path);
4158
4159         if (adapter_path == NULL ||
4160                 strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) {
4161                 ERR("Adapter path is inproper\n");
4162                 goto fail;
4163         }
4164
4165         if (path)
4166                 g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX);
4167
4168         g_variant_unref(result);
4169         g_object_unref(manager_proxy);
4170
4171         return 0;
4172
4173 fail:
4174         g_clear_error(&err);
4175
4176         if (result)
4177                 g_variant_unref(result);
4178
4179         if (manager_proxy)
4180                 g_object_unref(manager_proxy);
4181
4182         return BT_HFP_AGENT_ERROR_INTERNAL;
4183
4184 }
4185
4186 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
4187 void _bt_ag_agent_check_transport_state(void)
4188 {
4189         FN_START;
4190
4191         if (transport_state == MEDIA_TRANSPORT_STATE_PLAYING) {
4192                 GDBusProxy *proxy;
4193                 GError *err = NULL;
4194
4195                 proxy =  g_dbus_proxy_new_sync(ag_dbus_conn,
4196                                 G_DBUS_PROXY_FLAGS_NONE, NULL,
4197                                 "org.PulseAudio2", A2DP_SOURCE_ENDPOINT,
4198                                 BLUEZ_MEDIA_ENDPOINT_INTERFACE, NULL, &err);
4199
4200                 if (!proxy) {
4201                         if (err) {
4202                                 ERR("Unable to create proxy: %s", err->message);
4203                                 g_clear_error(&err);
4204                         }
4205                         return;
4206                 }
4207                 INFO_C("SuspendMedia initiated");
4208
4209                 g_dbus_proxy_call(proxy,
4210                                         "SuspendMedia", NULL,
4211                                         G_DBUS_CALL_FLAGS_NONE, 2000,
4212                                         NULL, NULL, NULL);
4213                 transport_state = MEDIA_TRANSPORT_STATE_IDLE;
4214         }
4215
4216         FN_END;
4217 }
4218
4219 static void __bt_ag_agent_transport_state_update(const char *value)
4220 {
4221
4222         if (!g_strcmp0(value, "idle"))
4223                 transport_state = MEDIA_TRANSPORT_STATE_IDLE;
4224         else if (!g_strcmp0(value, "pending") || !g_strcmp0(value, "active"))
4225                 transport_state = MEDIA_TRANSPORT_STATE_PLAYING;
4226         else
4227                 transport_state =  MEDIA_TRANSPORT_STATE_DISCONNECTED;
4228
4229         INFO_C("transport_state %d", transport_state);
4230 }
4231
4232 static void __bt_ag_agent_media_filter_cb(GDBusConnection *connection,
4233                                         const gchar *sender_name,
4234                                         const gchar *object_path,
4235                                         const gchar *interface_name,
4236                                         const gchar *signal_name,
4237                                         GVariant *parameters,
4238                                         gpointer user_data)
4239 {
4240         FN_START;
4241         char *inter = NULL;
4242         GVariant *dict_param = NULL;
4243         GVariant *optional_param = NULL;
4244
4245         if (strcasecmp(signal_name, "PropertiesChanged") == 0) {
4246                 if (g_strcmp0(g_variant_get_type_string(parameters),
4247                                                         "(sa{sv}as)")) {
4248                         ERR("Incorrect parameters\n");
4249                         return;
4250                 }
4251
4252                 g_variant_get(parameters, "(&s@a{sv}@as)",
4253                                         &inter, &dict_param, &optional_param);
4254                 if (dict_param && (!g_strcmp0(inter,
4255                                 BLUEZ_MEDIA_TRANSPORT_INTERFACE))){
4256                         GVariantIter *iter = NULL;
4257                         const gchar *key = NULL;
4258                         GVariant *value_var = NULL;
4259                         gchar *value = NULL;
4260                         g_variant_get(dict_param, "a{sv}", &iter);
4261                         while (g_variant_iter_loop(
4262                                         iter, "{sv}", &key, &value_var)) {
4263                                 DBG("key %s", key);
4264                                 if (g_strcmp0(key, "State") == 0) {
4265                                         value = (gchar *)g_variant_get_string(
4266                                                                 value_var,
4267                                                                 NULL);
4268                                         DBG("value %s", value);
4269                                         __bt_ag_agent_transport_state_update(value);
4270                                         break;
4271                                 }
4272                         }
4273                         g_variant_iter_free(iter);
4274                         g_variant_unref(dict_param);
4275                 }
4276         } else if (strcasecmp(signal_name, "ProfileStateChanged") == 0) {
4277                 char *profile_uuid = NULL;
4278                 int state = 0;
4279
4280                 g_variant_get(parameters, "(&si)", &profile_uuid, &state);
4281                 if ((g_strcmp0(profile_uuid, A2DP_SINK_UUID) == 0)  &&
4282                         (state == BT_PROFILE_STATE_DISCONNECTED)) {
4283                         DBG("Updating the transport state");
4284                         __bt_ag_agent_transport_state_update("Disconnect");
4285                 }
4286         }
4287
4288         if (dict_param)
4289                 g_variant_unref(dict_param);
4290
4291         if (optional_param)
4292                 g_variant_unref(optional_param);
4293
4294         FN_END;
4295 }
4296 #endif
4297 static void __bt_ag_agent_dbus_init(void)
4298 {
4299         FN_START;
4300
4301         if (__bt_ag_get_gdbus_connection() == NULL) {
4302                 ERR("Error in creating the gdbus connection\n");
4303                 return;
4304         }
4305         if (!__bt_ag_register_profile_methods()) {
4306                 ERR("Error in HFP / HSP register_profile_methods\n");
4307                 return;
4308         }
4309
4310         if (!__bt_ag_agent_get_adapter_path(ag_dbus_conn , NULL)) {
4311
4312                 gchar *path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
4313                 __bt_ag_agent_register(path, hfp_ver,
4314                          HFP_AG_UUID, "Hands-Free Audio Gateway");
4315
4316                 path = g_strdup(BT_HS_AG_AGENT_OBJECT_PATH);
4317                 __bt_ag_agent_register(path, hsp_ver,
4318                         HSP_AG_UUID, "Headset Audio Gateway");
4319         }
4320
4321         owner_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4322                                 NULL, BT_MANAGER_INTERFACE, NULL, NULL, NULL, 0,
4323                                 __bt_ag_agent_filter_cb, NULL, NULL);
4324 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
4325         media_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4326                                 NULL, BT_PROPERTIES_INTERFACE, NULL, NULL,
4327                                 NULL, 0, __bt_ag_agent_media_filter_cb,
4328                                 NULL, NULL);
4329
4330         media_state_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4331                                 NULL, BLUEZ_DEVICE_INTERFACE, NULL, NULL,
4332                                 NULL, 0, __bt_ag_agent_media_filter_cb,
4333                                 NULL, NULL);
4334
4335         transport_state = MEDIA_TRANSPORT_STATE_DISCONNECTED;
4336 #endif
4337         FN_END;
4338         return;
4339 }
4340
4341 static uint32_t __bt_ag_agent_get_ag_features(void)
4342 {
4343
4344         uint32_t ag_features = BT_AG_FEATURE_EC_AND_NR |
4345                                 BT_AG_FEATURE_REJECT_CALL |
4346                                 BT_AG_FEATURE_ENHANCED_CALL_STATUS |
4347                                 BT_AG_FEATURE_THREE_WAY_CALL |
4348 #ifndef TIZEN_FEATURE_BT_KIRAN_DEVICE
4349                                 BT_AG_FEATURE_VOICE_RECOGNITION |
4350 #endif
4351                                 BT_AG_FEATURE_EXTENDED_ERROR_RESULT_CODES;
4352
4353         wbs_en = TRUE;
4354 #if defined(TIZEN_FEATURE_BT_HFP_AG)
4355         hfp_ver = HFP_VERSION_1_6;
4356 #else
4357         hfp_ver = HFP_VERSION_1_5;
4358 #endif
4359         hsp_ver = HSP_VERSION_1_2;
4360
4361         if (hfp_ver == HFP_VERSION_1_6)
4362                 ag_features |= BT_AG_FEATURE_CODEC_NEGOTIATION;
4363         return ag_features;
4364 }
4365
4366 void *__bt_ag_agent_telephony_init(void *arg)
4367 {
4368
4369         int tapi_result;
4370         uint32_t ag_features = *((uint32_t *)arg);
4371
4372         INFO_C("Initializing the telephony info");
4373
4374         _bt_hfp_initialize_telephony_manager(ag_features);
4375         __bt_ag_agent_subscribe_vconf_updates();
4376
4377         tapi_handle = tel_init(NULL);
4378         tapi_result = tel_get_sim_msisdn(tapi_handle, __bt_ag_agent_tel_cb,
4379                                         NULL);
4380         if (tapi_result != TAPI_API_SUCCESS)
4381                 ERR("Fail to get sim info: %d", tapi_result);
4382         return NULL;
4383 }
4384
4385 int main(void)
4386 {
4387         int i;
4388         uint32_t ag_features;
4389         struct sigaction sa;
4390         pthread_t thread_id;
4391
4392         INFO_C("### Starting Bluetooth AG agent");
4393
4394         ag_features = __bt_ag_agent_get_ag_features();
4395
4396         ag.sdp_features = (uint16_t) ag_features & 0x1F;
4397
4398         if (hfp_ver == HFP_VERSION_1_6 && wbs_en == TRUE)
4399                 ag.sdp_features |= BT_AG_FEATURE_SDP_WIDEBAND_SPEECH;
4400
4401         memset(&sa, 0, sizeof(sa));
4402         sa.sa_flags = SA_NOCLDSTOP;
4403         sa.sa_handler = __bt_ag_agent_sigterm_handler;
4404
4405         for (i = 0; i < BT_AG_SIG_NUM; i++)
4406                 sigaction(bt_ag_sig_to_handle[i], &sa, &(bt_ag_sigoldact[i]));
4407
4408         gmain_loop = g_main_loop_new(NULL, FALSE);
4409
4410         if (gmain_loop == NULL) {
4411                 ERR("GMainLoop create failed");
4412                 return EXIT_FAILURE;
4413         }
4414
4415         __bt_ag_agent_dbus_init();
4416         if (pthread_create(&thread_id, NULL,
4417                         (void *)&__bt_ag_agent_telephony_init,
4418                                         &ag_features) < 0) {
4419                 ERR("pthread_create() is failed");
4420                 return EXIT_FAILURE;
4421         }
4422
4423         if (pthread_detach(thread_id) < 0)
4424                 ERR("pthread_detach() is failed");
4425
4426         g_main_loop_run(gmain_loop);
4427
4428         DBG("Cleaning up");
4429
4430         tel_deinit(tapi_handle);
4431
4432         __bt_ag_agent_dbus_deinit();
4433         _bt_hfp_deinitialize_telephony_manager();
4434         __bt_ag_agent_release_vconf_updates();
4435
4436         if (remote_dev_path)
4437                 g_free(remote_dev_path);
4438
4439         if (gmain_loop)
4440                 g_main_loop_unref(gmain_loop);
4441
4442         INFO_C("### Terminating Bluetooth AG agent");
4443         return 0;
4444 }