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