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