Add checking memory allocation
[platform/core/connectivity/bluetooth-agent.git] / hf-agent / bluetooth-hf-agent.c
1 /*
2  * Bluetooth-hf-agent
3  *
4  * Copyright (c) 2000 - 2011 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  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *              http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <glib.h>
28 #include <signal.h>
29 #include <fcntl.h>
30 #include <inttypes.h>
31 #include <sys/socket.h>
32 #include <sys/poll.h>
33 #include <aul.h>
34 #include <gio/gio.h>
35 #include <gio/gunixfdlist.h>
36 #include <device/power.h>
37 #include <app_manager.h>
38 #include <vconf.h>
39 #include <vconf-keys.h>
40 #include <bundle_internal.h>
41
42 #include "bluetooth-hf-agent.h"
43 #include "bluetooth-agent-profile.h"
44
45 #define BT_AGENT_SYSPOPUP_MAX_ATTEMPT 3
46 #define CALL_ALIAS_APP_ID "org.tizen.call-ui"
47
48 #define MAX_WAITING_DELAY 8
49 #define READ_TX_POWER_MIN -30
50
51 #define BT_ADDRESS_STRING_SIZE 18
52 #define BT_AT_COMMAND_BUFFER_MAX 4000
53 #define BT_HF_ERROR_RESP "\r\nERROR\r\n"
54 #define BT_HF_COMMAND_TIMEOUT 3
55
56 #define ret_if(expr) \
57         do { \
58                 if (expr) { \
59                         ERR("(%s) return", #expr); \
60                         return; \
61                 } \
62         } while (0)
63
64 static GMainLoop *gmain_loop = NULL;
65 static char *g_obj_path;
66
67 static GDBusConnection *gdbus_conn = NULL;
68 static GDBusProxy *profile_gproxy = NULL;
69 static guint interface_added_sig_id;
70 static guint interface_removed_sig_id;
71 int g_id = 0;
72 uint16_t hf_ver;
73
74 guint clcc_timer = 0;
75 int clcc_retry_count = 0;
76 guint clcc_async_timer = 0;
77 int clcc_async_retry_count = 0;
78 #define CLCC_RETRY_COUNT 10
79 #define CLCC_RETRY_TIMER 100    /* 100 msec */
80
81 #define HFP_HF_UUID "0000111e-0000-1000-8000-00805f9b34fb"
82 #define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
83
84 /*Below Inrospection data is exposed to bluez from agent*/
85 static const gchar hf_agent_bluez_introspection_xml[] =
86 "<node name='/'>"
87 "       <interface name='org.bluez.Profile1'>"
88 "               <method name='NewConnection'>"
89 "                       <arg type='o' name='device' direction='in'/>"
90 "                       <arg type='h' name='fd' direction='in'/>"
91 "                       <arg type='a{sv}' name='options' direction='in'/>"
92 "               </method>"
93 "               <method name='RequestDisconnection'>"
94 "                       <arg type='o' name='device' direction='in'/>"
95 "               </method>"
96 "       </interface>"
97 "</node>";
98
99 /*Below Inrospection data is exposed to application from agent*/
100 static const gchar hf_agent_introspection_xml[] =
101 "<node name='/'>"
102 " <interface name='org.tizen.HfApp'>"
103 "               <method name='AnswerCall'>"
104 "                </method>"
105 "                <method name='TerminateCall'>"
106 "                </method>"
107 "                <method name='InitiateCall'>"
108 "                        <arg type='s' name='phoneno' direction='in'/>"
109 "                </method>"
110 "                <method name='VoiceRecognition'>"
111 "                        <arg type='i' name='status' direction='in'/>"
112 "                </method>"
113 "                <method name='ScoConnect'>"
114 "                </method>"
115 "                <method name='ScoDisconnect'>"
116 "                </method>"
117 "                <method name='SpeakerGain'>"
118 "                        <arg type='u' name='gain' direction='in'/>"
119 "                </method>"
120 "                <method name='SendDtmf'>"
121 "                        <arg type='s' name='dtmf' direction='in'/>"
122 "                </method>"
123 "                <method name='SendAtCmd'>"
124 "                        <arg type='s' name='atcmd' direction='in'/>"
125 "                </method>"
126 "                <method name='ReleaseAndAccept'>"
127 "                </method>"
128 "                <method name='CallSwap'>"
129 "                </method>"
130 "                <method name='ReleaseAllCall'>"
131 "                </method>"
132 "                <method name='JoinCall'>"
133 "                </method>"
134 "                <method name='GetCurrentCodec'>"
135 "                       <arg type='i' name='codec' direction='out'/>"
136 "                </method>"
137 "                <method name='RequestCallList'>"
138 "                       <arg type='i' name='count' direction='out'/>"
139 "                       <arg type='a(siiii)' name='callList' direction='out'/>"
140 "                </method>"
141 "                <method name='RequestCallListAsync'>"
142 "                </method>"
143 "                <method name='GetAudioConnected'>"
144 "                       <arg type='i' name='status' direction='out'/>"
145 "                </method>"
146 "                <method name='IsHfConnected'>"
147 "                       <arg type='b' name='status' direction='out'/>"
148 "                </method>"
149 "                <method name='IsInbandRingtoneSupported'>"
150 "                       <arg type='b' name='status' direction='out'/>"
151 "                </method>"
152 " </interface>"
153 "</node>";
154
155 static bt_hf_agent_info_t bt_hf_info = {0,};
156 static gboolean is_hf_connected = FALSE;
157 static int32_t current_codec_id = BT_HF_CODEC_ID_CVSD;
158 static int32_t sco_audio_connected = BT_HF_AUDIO_DISCONNECTED;
159
160 static char global_buff[BT_AT_COMMAND_BUFFER_MAX] = {0,};
161 int send_flag;
162
163 static char prev_cmd[BT_HF_CMD_BUF_SIZE];
164
165 typedef struct {
166         int idx;
167         int dir;
168         int status;
169         int mode;
170         int multi_party;
171         int type;
172         char *number;
173 } hf_call_list_info_t;
174
175 #define BT_HF_SIG_NUM 3
176 static struct sigaction bt_hf_sigoldact[BT_HF_SIG_NUM];
177 static int bt_hf_sig_to_handle[] = { SIGABRT, SIGSEGV, SIGTERM };
178
179 static GError *__bt_hf_agent_set_error(bt_hf_agent_error_t error);
180
181 static gboolean __bt_hf_agent_emit_property_changed(
182                                 GDBusConnection *connection,
183                                 const char *path,
184                                 const char *interface,
185                                 const char *name,
186                                 GVariant *property);
187
188 static gboolean __bt_hf_agent_data_cb(GIOChannel *chan, GIOCondition cond,
189                                         bt_hf_agent_info_t *bt_hf_info);
190 static void __bt_hf_agent_stop_watch(bt_hf_agent_info_t *bt_hf_info);
191 static void __bt_hf_agent_start_watch(bt_hf_agent_info_t *bt_hf_info);
192 static gboolean __bt_hf_channel_write(GIOChannel *io, gchar *data,
193                                         gsize count);
194 static gboolean __bt_hf_send_only_without_queue(bt_hf_agent_info_t *bt_hf_info,
195                                                 gchar *data, gsize count);
196
197 static gboolean __bt_hf_send_only(bt_hf_agent_info_t *bt_hf_info, gchar *data,
198                                         gsize count);
199 static gboolean __bt_hf_send_and_read(bt_hf_agent_info_t *bt_hf_info,
200                                 gchar *data, gchar *response, gsize count);
201 static GSList *__bt_hf_parse_indicator_names(gchar *names, GSList *indies);
202 static GSList *__bt_hf_parse_indicator_values(gchar *values, GSList *indies);
203 static guint __bt_hf_get_hold_mpty_features(gchar *features);
204 static gboolean __bt_establish_service_level_conn(bt_hf_agent_info_t *bt_hf_info);
205 static void __bt_hf_agent_sigterm_handler(int signo);
206 static gboolean __bt_hf_agent_release(void);
207
208 static gboolean __bt_get_current_indicators(bt_hf_agent_info_t *bt_hf_info);
209 static gboolean __bt_get_supported_indicators(bt_hf_agent_info_t *bt_hf_info);
210 static gboolean __bt_hf_agent_connection(gint32 fd, const gchar * object_path);
211 static gboolean __bt_hf_agent_connection_release(void);
212 static void __bt_hf_agent_handle_call_list(bt_hf_agent_info_t *bt_hf_info);
213
214 struct indicator {
215         gchar descr[BT_HF_INDICATOR_DESCR_SIZE];
216         gint value;
217 };
218
219 static int _hf_agent_answer_call(GDBusMethodInvocation *context);
220
221 static int _hf_agent_terminate_call(GDBusMethodInvocation *context);
222
223 static int _hf_agent_dial_no(GDBusMethodInvocation *context, char *no);
224
225 static int _hf_agent_set_speaker_gain(GDBusMethodInvocation *context,
226                                                         unsigned int gain);
227
228 static int _hf_agent_send_3way_cmd(GDBusMethodInvocation *context, char *cmd);
229
230 static int _hf_agent_voice_recognition(GDBusMethodInvocation *context,
231                                                         unsigned int status);
232
233 static gboolean bt_hf_agent_sco_connect(void);
234
235 static gboolean bt_hf_agent_sco_disconnect(void);
236
237 static int _hf_agent_send_dtmf(GDBusMethodInvocation *context, char *dtmf);
238
239 static GVariant *bt_hf_agent_request_call_list(void);
240
241 static int bt_hf_agent_send_at_cmd(GDBusMethodInvocation *context, char *atcmd);
242
243 static int hf_handle_rx_at_cmd(bt_hf_agent_info_t *bt_hf_info, const char *buf);
244
245 static void __on_log_glib(const gchar *log_domain, GLogLevelFlags log_level,
246                 const gchar *msg, gpointer user_data)
247 {
248         ERR_C("%s", msg);
249 }
250
251 static void __bt_hf_agent_print_at_buffer(char *message, const char *buf)
252 {
253
254         int i = 0;
255         char s[BT_HF_DATA_BUF_SIZE] = {0, };
256         gboolean hide = FALSE;
257
258         gboolean has_clcc = FALSE;
259         gboolean has_clip = FALSE;
260         gboolean has_ccwa = FALSE;
261         char *xsat_ptr;
262
263         strncpy(s, buf, BT_HF_DATA_BUF_SIZE - 1);
264
265         has_clcc = strstr(buf, "CLCC:") ? TRUE : FALSE;
266         if (has_clcc == TRUE)
267                 goto done;
268         has_clip = strstr(buf, "+CLIP:") ? TRUE : FALSE;
269         if (has_clip == TRUE)
270                 goto done;
271         has_ccwa = strstr(buf, "+CCWA:") ? TRUE : FALSE;
272
273 done:
274         /* +XSAT: 11,DISC */
275         xsat_ptr =  strstr(s, "11,DISC,");
276         if (xsat_ptr) {
277                 xsat_ptr = xsat_ptr + 8;
278                 int x = 0;
279                 while (xsat_ptr[x] != '\0' && xsat_ptr[x] != '\r' && xsat_ptr[x] != '\n') {
280                         xsat_ptr[x] = 'X';
281                         x++;
282                 }
283         }
284
285         /* AT+XSAT=11,Q_CT,X,XXXX */
286         xsat_ptr =  strstr(s, "11,Q_CT,");
287         if (xsat_ptr) {
288                 xsat_ptr = xsat_ptr + 8;
289                 int x = 0;
290                 while (xsat_ptr[x] != '\0' && xsat_ptr[x] != '\r' && xsat_ptr[x] != '\n') {
291                         if (x > 1) /* ignore 0 and 1 position */
292                                 xsat_ptr[x] = 'X';
293                         x++;
294                 }
295         }
296
297         i = 0;
298         while (s[i] != '\0') {
299                 if (s[i] == '\r' || s[i] == '\n') {
300                         s[i] = '.';
301                 } else {
302                         if (s[i] == '\"')
303                                 hide = hide ? FALSE : TRUE;
304                         else if ((has_clcc || has_clip || has_ccwa) && hide) {
305                                 if (i % 2)
306                                         s[i] = 'X';
307                         }
308                 }
309                 i++;
310         }
311         if (message)
312                 INFO("%s Buffer = %s, Length = %zd ", message, s, strlen(s));
313         else
314                 INFO("%s", s);
315 }
316
317 static GQuark __bt_hf_agent_error_quark(void)
318 {
319         DBG("");
320
321         static GQuark quark = 0;
322         if (!quark)
323                 quark = g_quark_from_static_string("hf-agent");
324
325         return quark;
326 }
327
328 static GError *__bt_hf_agent_set_error(bt_hf_agent_error_t error)
329 {
330         ERR("error[%d]", error);
331
332         switch (error) {
333         case BT_HF_AGENT_ERROR_NOT_AVAILABLE:
334                 return g_error_new(BT_HF_AGENT_ERROR, error,
335                                         BT_ERROR_NOT_AVAILABLE);
336         case BT_HF_AGENT_ERROR_NOT_CONNECTED:
337                 return g_error_new(BT_HF_AGENT_ERROR, error,
338                                         BT_ERROR_NOT_CONNECTED);
339         case BT_HF_AGENT_ERROR_CONNECTION_FAILED:
340                 return g_error_new(BT_HF_AGENT_ERROR, error,
341                                         BT_ERROR_NOT_CONNECTION_FAILED);
342         case BT_HF_AGENT_ERROR_BUSY:
343                 return g_error_new(BT_HF_AGENT_ERROR, error,
344                                         BT_ERROR_BUSY);
345         case BT_HF_AGENT_ERROR_INVALID_PARAM:
346                 return g_error_new(BT_HF_AGENT_ERROR, error,
347                                         BT_ERROR_INVALID_PARAM);
348         case BT_HF_AGENT_ERROR_ALREADY_EXIST:
349                 return g_error_new(BT_HF_AGENT_ERROR, error,
350                                         BT_ERROR_ALREADY_EXIST);
351         case BT_HF_AGENT_ERROR_ALREADY_CONNECTED:
352                 return g_error_new(BT_HF_AGENT_ERROR, error,
353                                         BT_ERROR_ALREADY_CONNECTED);
354         case BT_HF_AGENT_ERROR_NO_MEMORY:
355                 return g_error_new(BT_HF_AGENT_ERROR, error,
356                                         BT_ERROR_NO_MEMORY);
357         case BT_HF_AGENT_ERROR_NO_DATA:
358                 return g_error_new(BT_HF_AGENT_ERROR, error,
359                                         BT_ERROR_NO_DATA);
360         case BT_HF_AGENT_ERROR_I_O_ERROR:
361                 return g_error_new(BT_HF_AGENT_ERROR, error,
362                                         BT_ERROR_I_O_ERROR);
363         case BT_HF_AGENT_ERROR_APPLICATION:
364                 return g_error_new(BT_HF_AGENT_ERROR, error,
365                                         BT_ERROR_OPERATION_NOT_AVAILABLE);
366         case BT_HF_AGENT_ERROR_NOT_ALLOWED:
367                 return g_error_new(BT_HF_AGENT_ERROR, error,
368                                         BT_ERROR_OPERATION_NOT_ALLOWED);
369         case BT_HF_AGENT_ERROR_NOT_SUPPORTED:
370                 return g_error_new(BT_HF_AGENT_ERROR, error,
371                                         BT_ERROR_OPERATION_NOT_SUPPORTED);
372         case BT_HF_AGENT_ERROR_INVALID_FILE_DESCRIPTOR:
373                 return g_error_new(BT_HF_AGENT_ERROR, error,
374                                         BT_ERROR_INVALID_FILE_DESCRIPTOR);
375         case BT_HF_AGENT_ERROR_INTERNAL:
376         default:
377                 return g_error_new(BT_HF_AGENT_ERROR, error,
378                                                 BT_ERROR_INTERNAL);
379         }
380 }
381
382 static void __bt_hf_lock_display(int timeout)
383 {
384         int ret;
385
386         ret = device_power_request_lock(POWER_LOCK_DISPLAY, timeout);
387         if (ret >= 0)
388                 DBG("Lock PM state as current state!");
389         else
390                 ERR("deviced error!");
391 }
392
393 static void __bt_hf_unlock_display()
394 {
395         int ret;
396
397         ret = device_power_release_lock(POWER_LOCK_DISPLAY);
398         if (ret >= 0)
399                 DBG("UnLock PM state");
400         else
401                 ERR("deviced error!");
402 }
403
404 static gboolean __clcc_timer_func(gpointer data)
405 {
406         GVariant *call_var;
407         GError *err;
408
409         DBG("+");
410
411         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
412                 DBG("NOT CONNECTED");
413                 err = __bt_hf_agent_set_error(BT_HF_AGENT_ERROR_NOT_CONNECTED);
414                 g_dbus_method_invocation_return_gerror((GDBusMethodInvocation *) data, err);
415                 g_error_free(err);
416                 clcc_timer = 0;
417                 return FALSE;
418         }
419
420         if (send_flag && clcc_retry_count > 0) {
421                 clcc_retry_count--;
422                 DBG("Still pending. try later (remained [%d] times)", clcc_retry_count);
423                 return TRUE;
424         }
425
426         clcc_timer = 0;
427
428         call_var = bt_hf_agent_request_call_list();
429         if (!call_var) {
430                 INFO("NOT AVAILABLE");
431                 err = __bt_hf_agent_set_error(BT_HF_AGENT_ERROR_NOT_AVAILABLE);
432                 g_dbus_method_invocation_return_gerror((GDBusMethodInvocation *) data, err);
433                 g_error_free(err);
434                 return FALSE;
435         }
436
437         INFO("return call list info");
438         g_dbus_method_invocation_return_value((GDBusMethodInvocation *) data, call_var);
439         return FALSE;
440 }
441
442 static gboolean __clcc_async_timer_func(gpointer data)
443 {
444         DBG("+");
445
446         if (send_flag && clcc_async_retry_count > 0) {
447                 clcc_async_retry_count--;
448                 ERR("Still pending. try later (remained [%d] times)", clcc_async_retry_count);
449                 return TRUE;
450         }
451
452         clcc_async_timer = 0;
453
454         __bt_hf_agent_handle_call_list(&bt_hf_info);
455         g_dbus_method_invocation_return_value((GDBusMethodInvocation*)data, NULL);
456
457         INFO("update_call_list succeeded");
458
459         return FALSE;
460 }
461
462 static void __hf_agent_method(GDBusConnection *connection,
463                             const gchar *sender,
464                             const gchar *object_path,
465                             const gchar *interface_name,
466                             const gchar *method_name,
467                             GVariant *parameters,
468                             GDBusMethodInvocation *context,
469                             gpointer user_data)
470 {
471         DBG("+");
472
473         INFO("method %s", method_name);
474         int ret = 0;
475         GError *err;
476
477         if (g_strcmp0(method_name, "NewConnection") == 0) {
478                 gint32 fd;
479                 int index;
480                 GDBusMessage *msg;
481                 GUnixFDList *fd_list;
482                 const gchar *object_path;
483                 GVariant *options;
484
485                 g_variant_get(parameters, "(oha{sv})",
486                         &object_path, &index, &options);
487
488                 msg = g_dbus_method_invocation_get_message(context);
489                 fd_list = g_dbus_message_get_unix_fd_list(msg);
490                 if (fd_list == NULL) {
491                         ret = BT_HF_AGENT_ERROR_INVALID_FILE_DESCRIPTOR;
492                         goto fail;
493                 }
494
495                 fd = g_unix_fd_list_get(fd_list, index, NULL);
496                 if (fd == -1) {
497                         ret = BT_HF_AGENT_ERROR_INVALID_FILE_DESCRIPTOR;
498                         goto fail;
499                 }
500
501                 DBG("FD is = [%d], Object path = [%s]", fd, object_path);
502
503                 if (!__bt_hf_agent_connection(fd, object_path)) {
504                         ret = BT_HF_AGENT_ERROR_INTERNAL;
505                         goto fail;
506                 }
507
508                 g_dbus_method_invocation_return_value(context, NULL);
509         } else if (g_strcmp0(method_name, "RequestDisconnection") == 0) {
510                 if (!__bt_hf_agent_connection_release()) {
511                         ret = BT_HF_AGENT_ERROR_INTERNAL;
512                         goto fail;
513                 }
514                 INFO_C("Disconnected [HF role] [Terminated by local host]");
515                 g_dbus_method_invocation_return_value(context, NULL);
516         } else if (g_strcmp0(method_name, "Release") == 0) {
517                 if (!__bt_hf_agent_connection_release()) {
518                         ret = BT_HF_AGENT_ERROR_INTERNAL;
519                         goto fail;
520                 }
521
522                 g_dbus_method_invocation_return_value(context, NULL);
523         } else if (g_strcmp0(method_name, "AnswerCall") == 0) {
524                 DBG("Going to call AnswerCall");
525                 ret = _hf_agent_answer_call(context);
526                 if (ret)
527                         goto fail;
528
529         } else if (g_strcmp0(method_name, "TerminateCall") == 0) {
530                 DBG("Going to call TerminateCall");
531                 ret = _hf_agent_terminate_call(context);
532                 if (ret)
533                         goto fail;
534
535         } else if (g_strcmp0(method_name, "InitiateCall") == 0) {
536                 char *phoneno = NULL;
537
538                 g_variant_get(parameters, "(&s)", &phoneno);
539
540                 DBG_SECURE("Going to call InitiateCall, Number is = [%s]\n", phoneno);
541                 ret = _hf_agent_dial_no(NULL, phoneno);
542                 if (ret)
543                         goto fail;
544
545                 g_dbus_method_invocation_return_value(context, NULL);
546
547         } else if (g_strcmp0(method_name, "VoiceRecognition") == 0) {
548                 int status = 0;
549
550                 g_variant_get(parameters, "(i)", &status);
551
552                 DBG("Going to call VoiceRecognition, Status [%d]", status);
553                 ret = _hf_agent_voice_recognition(context, status);
554                 if (ret)
555                         goto fail;
556
557         } else if (g_strcmp0(method_name, "ScoConnect") == 0) {
558                 DBG("Going to call ScoConnect");
559                 if (!bt_hf_agent_sco_connect()) {
560                         ret = BT_HF_AGENT_ERROR_INTERNAL;
561                         goto fail;
562                 }
563
564                 g_dbus_method_invocation_return_value(context, NULL);
565         } else if (g_strcmp0(method_name, "ScoDisconnect") == 0) {
566                 DBG("Going to call ScoDisconnect");
567                 if (!bt_hf_agent_sco_disconnect()) {
568                         ret = BT_HF_AGENT_ERROR_INTERNAL;
569                         goto fail;
570                 }
571
572                 g_dbus_method_invocation_return_value(context, NULL);
573         } else if (g_strcmp0(method_name, "SpeakerGain") == 0) {
574                 unsigned int gain = 0;
575
576                 g_variant_get(parameters, "(u)", &gain);
577
578                 DBG("Going to call SpeakerGain, gain is = [%d]\n", gain);
579                 ret = _hf_agent_set_speaker_gain(context, gain);
580                 if (ret)
581                         goto fail;
582
583         } else if (g_strcmp0(method_name, "SendDtmf") == 0) {
584                 char *dtmf = NULL;
585
586                 g_variant_get(parameters, "(&s)", &dtmf);
587
588                 DBG("Going to call SendDtmf, dtmf is = [%s]\n", dtmf);
589                 ret = _hf_agent_send_dtmf(NULL, dtmf);
590                 if (ret)
591                         goto fail;
592                 g_dbus_method_invocation_return_value(context, NULL);
593
594         } else if (g_strcmp0(method_name, "SendAtCmd") == 0) {
595                 char *cmd = NULL;
596
597                 g_variant_get(parameters, "(&s)", &cmd);
598
599                 DBG("Going to call SendAtCmd\n");
600                 ret = bt_hf_agent_send_at_cmd(NULL, cmd);
601                 if (ret)
602                         goto fail;
603                 g_dbus_method_invocation_return_value(context, NULL);
604
605         } else if (g_strcmp0(method_name, "ReleaseAndAccept") == 0) {
606                 DBG("Going to call ReleaseAndAccept");
607                 ret = _hf_agent_send_3way_cmd(context,
608                                                 BT_HF_RELEASE_AND_ACCEPT);
609                 if (ret)
610                         goto fail;
611
612         } else if (g_strcmp0(method_name, "CallSwap") == 0) {
613                 DBG("Going to call CallSwap");
614                 ret = _hf_agent_send_3way_cmd(context,
615                                                         BT_HF_ACCEPT_AND_HOLD);
616                 if (ret)
617                         goto fail;
618
619         } else if (g_strcmp0(method_name, "ReleaseAllCall") == 0) {
620                 DBG("Going to call ReleaseAllCall");
621                 ret = _hf_agent_send_3way_cmd(context, BT_HF_RELEASE_ALL);
622                 if (ret)
623                         goto fail;
624
625         } else if (g_strcmp0(method_name, "JoinCall") == 0) {
626                 DBG("Going to call JoinCall");
627                 ret = _hf_agent_send_3way_cmd(context, BT_HF_JOIN_CALL);
628                 if (ret)
629                         goto fail;
630
631         } else if (g_strcmp0(method_name, "GetCurrentCodec") == 0) {
632                 DBG("Going to call GetCurrentCodec");
633                 INFO("Current codec : %d", current_codec_id);
634                 g_dbus_method_invocation_return_value(context,
635                                 g_variant_new("(i)", current_codec_id));
636         } else if (g_strcmp0(method_name, "RequestCallList") == 0) {
637                 GVariant *call_var;
638
639                 INFO("Going to call RequestCallList (send_flag[%d])", send_flag);
640
641                 if (send_flag) {
642                         INFO("Send_flag is true. Try to send CLCC later");
643                         clcc_retry_count = CLCC_RETRY_COUNT;
644                         clcc_timer = g_timeout_add(CLCC_RETRY_TIMER, __clcc_timer_func, context);
645                 } else {
646                         call_var = bt_hf_agent_request_call_list();
647                         if (!call_var) {
648                                 ret = BT_HF_AGENT_ERROR_NOT_AVAILABLE;
649                                 goto fail;
650                         }
651                         g_dbus_method_invocation_return_value(context, call_var);
652                 }
653         } else if (g_strcmp0(method_name, "RequestCallListAsync") == 0) {
654                 INFO("Going to call RequestCallListAsync (send_flag[%d])", send_flag);
655
656                 if (clcc_async_timer > 0) {
657                         ret = BT_HF_AGENT_ERROR_NOT_AVAILABLE;
658                         goto fail;
659                 }
660                 if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
661                         ret = BT_HF_AGENT_ERROR_NOT_CONNECTED;
662                         goto fail;
663                 }
664                 if (bt_hf_info.ciev_call_status == 0 &&
665                         bt_hf_info.ciev_call_setup_status == 0) {
666                         ret = BT_HF_AGENT_ERROR_NO_DATA;
667                         goto fail;
668                 }
669
670                 if (send_flag) {
671                         INFO("Send_flag is true. Try to send CLCC later");
672                         clcc_async_retry_count = CLCC_RETRY_COUNT;
673                         clcc_async_timer = g_timeout_add(CLCC_RETRY_TIMER, __clcc_async_timer_func, context);
674                 } else {
675                         __bt_hf_agent_handle_call_list(&bt_hf_info);
676                         g_dbus_method_invocation_return_value(context, NULL);
677                 }
678         } else if (g_strcmp0(method_name, "GetAudioConnected") == 0) {
679                 DBG("Going to call GetAudioConnected");
680                 g_dbus_method_invocation_return_value(context,
681                                 g_variant_new("(i)", sco_audio_connected));
682         } else if (g_strcmp0(method_name, "IsHfConnected") == 0) {
683                 DBG("Going to call IsHfConnected");
684                 INFO("is_hf_connected : %s", is_hf_connected ? "Connected" : "Disconnected");
685
686                 g_dbus_method_invocation_return_value(context,
687                                 g_variant_new("(b)", is_hf_connected));
688         } else if (g_strcmp0(method_name, "IsInbandRingtoneSupported") == 0) {
689                 gboolean is_supported = FALSE;
690
691                 if (is_hf_connected == FALSE) {
692                         ret = BT_HF_AGENT_ERROR_NOT_CONNECTED;
693                         goto fail;
694                 }
695
696                 if (bt_hf_info.inband_ringtone_support)
697                         is_supported = TRUE;
698                 else
699                         is_supported = FALSE;
700
701                 INFO("IsInbandRingtoneSupported : %s", is_supported ?
702                                 "Supported" : "NotSupported");
703                 g_dbus_method_invocation_return_value(context,
704                                 g_variant_new("(b)", is_supported));
705         }
706
707         INFO("-");
708         return;
709
710 fail:
711         err = __bt_hf_agent_set_error(ret);
712         g_dbus_method_invocation_return_gerror(context, err);
713         g_error_free(err);
714         INFO("-");
715 }
716
717 static const GDBusInterfaceVTable method_table = {
718         __hf_agent_method,
719         NULL,
720         NULL,
721 };
722
723 static GDBusNodeInfo *__bt_hf_create_method_node_info
724                                         (const gchar *introspection_data)
725 {
726         if (introspection_data == NULL)
727                 return NULL;
728
729         return g_dbus_node_info_new_for_xml(introspection_data, NULL);
730 }
731
732 static GDBusConnection *__bt_hf_get_gdbus_connection(void)
733 {
734         GDBusConnection *local_system_gconn = NULL;
735         GError *err = NULL;
736
737         if (gdbus_conn == NULL) {
738                 gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
739                 if (!gdbus_conn) {
740                         if (err) {
741                                 ERR("Unable to connect to dbus: %s", err->message);
742                                 g_clear_error(&err);
743                         }
744                         gdbus_conn = NULL;
745                 }
746         } else if (g_dbus_connection_is_closed(gdbus_conn)) {
747                 local_system_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
748
749                 if (!local_system_gconn) {
750                         ERR("Unable to connect to dbus: %s", err->message);
751                         g_clear_error(&err);
752                 }
753
754                 gdbus_conn = local_system_gconn;
755         }
756
757         return gdbus_conn;
758 }
759
760 static gboolean __bt_hf_register_profile_methods(void)
761 {
762         DBG("+");
763         GError *error = NULL;
764         guint object_id;
765         guint owner_id;
766         GDBusNodeInfo *node_info;
767         gchar *path;
768         GDBusConnection *conn;
769
770         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
771                                 BT_HF_SERVICE_NAME,
772                                 G_BUS_NAME_OWNER_FLAGS_NONE,
773                                 NULL, NULL, NULL,
774                                 NULL, NULL);
775
776         DBG("owner_id is [%d]", owner_id);
777
778         node_info = __bt_hf_create_method_node_info(
779                                 hf_agent_bluez_introspection_xml);
780         if (node_info == NULL)
781                 return FALSE;
782
783         path = g_strdup(BT_HF_BLUEZ_OBJECT_PATH);
784         DBG("path is [%s]", path);
785
786         conn = __bt_hf_get_gdbus_connection();
787         if (!conn) {
788                 ERR("Unable to get connection");
789                 g_free(path);
790                 return FALSE;
791         }
792
793         object_id = g_dbus_connection_register_object(conn, path,
794                                         node_info->interfaces[0],
795                                         &method_table,
796                                         NULL, NULL, &error);
797         if (object_id == 0) {
798                 ERR("Failed to register: %s", error->message);
799                 g_error_free(error);
800                 g_dbus_node_info_unref(node_info);
801                 g_free(path);
802                 return FALSE;
803         }
804         g_free(path);
805         g_dbus_node_info_unref(node_info);
806
807         node_info = __bt_hf_create_method_node_info(hf_agent_introspection_xml);
808         if (node_info == NULL)
809                 return FALSE;
810
811         path = g_strdup(BT_HF_AGENT_OBJECT_PATH);
812         DBG("path is [%s]", path);
813
814         object_id = g_dbus_connection_register_object(conn, path,
815                                                 node_info->interfaces[0],
816                                                 &method_table,
817                                                 NULL, NULL, &error);
818         if (object_id == 0) {
819                 if (error != NULL) {
820                         ERR("Failed to register: %s", error->message);
821                         g_error_free(error);
822                 }
823                 g_dbus_node_info_unref(node_info);
824                 g_free(path);
825                 return FALSE;
826         }
827         g_free(path);
828         g_dbus_node_info_unref(node_info);
829
830         DBG("-");
831         return TRUE;
832 }
833
834 static GDBusProxy *__bt_hf_gdbus_init_profile_proxy(void)
835 {
836         DBG("+");
837
838         GDBusProxy *proxy;
839         GError *err = NULL;
840         GDBusConnection *conn;
841
842         conn = __bt_hf_get_gdbus_connection();
843         if (!conn) {
844                 ERR("Unable to get connection");
845                 return NULL;
846         }
847
848         proxy =  g_dbus_proxy_new_sync(conn,
849                         G_DBUS_PROXY_FLAGS_NONE, NULL,
850                         BLUEZ_SERVICE_NAME, "/org/bluez",
851                         BLUEZ_PROFILE_MGMT_INTERFACE, NULL, &err);
852
853         if (!proxy) {
854                 if (err) {
855                         ERR("Unable to create proxy: %s", err->message);
856                          g_clear_error(&err);
857                 }
858                 return NULL;
859         }
860
861         profile_gproxy = proxy;
862
863         DBG("-");
864         return proxy;
865 }
866
867 static GDBusProxy *__bt_hf_gdbus_get_profile_proxy(void)
868 {
869         return (profile_gproxy) ? profile_gproxy :
870                                   __bt_hf_gdbus_init_profile_proxy();
871 }
872
873 static GDBusProxy *__bt_hf_gdbus_get_service_proxy(const gchar *service,
874                                 const gchar *path, const gchar *interface)
875 {
876         DBG("+");
877
878         GDBusProxy *proxy;
879         GError *err = NULL;
880         GDBusConnection *conn;
881
882         conn = __bt_hf_get_gdbus_connection();
883         if (!conn) {
884                 ERR("Unable to get connection");
885                 return NULL;
886         }
887
888         proxy =  g_dbus_proxy_new_sync(conn,
889                         G_DBUS_PROXY_FLAGS_NONE, NULL,
890                         service, path,
891                         interface, NULL, &err);
892
893         if (!proxy) {
894                 if (err) {
895                         ERR("Unable to create proxy: %s", err->message);
896                          g_clear_error(&err);
897                 }
898                 return NULL;
899         }
900
901         DBG("-");
902         return proxy;
903 }
904
905 static char __bt_hf_agent_get_tx_power(char *address)
906 {
907         GVariant *ret;
908         GDBusProxy *proxy;
909         GError *error = NULL;
910         char result = READ_TX_POWER_MIN; /* default minimum */
911
912         proxy = __bt_hf_gdbus_get_service_proxy(BLUEZ_SERVICE_NAME, g_obj_path,
913                                                 BLUEZ_HF_INTERFACE_NAME);
914         if (!proxy) {
915                 ERR("Proxy is NULL");
916                 return result;
917         }
918
919         ret = g_dbus_proxy_call_sync(proxy,
920                                 "GetTxPowerLevel", g_variant_new("(s)", address),
921                                 G_DBUS_CALL_FLAGS_NONE, -1,
922                                 NULL, &error);
923         if (ret == NULL) {
924                 ERR("DBus is failed");
925                 if (error != NULL) {
926                         /* Dbus gives error cause */
927                         ERR("D-Bus API failure: errCode[%x], message[%s]",
928                                                 error->code, error->message);
929                         g_clear_error(&error);
930                 }
931                 g_object_unref(proxy);
932                 return result;
933         }
934         g_variant_get(ret, "(y)", &result);
935         DBG("TX power level = %d", result);
936         g_variant_unref(ret);
937         g_object_unref(proxy);
938
939         return result;
940 }
941
942 static int __bt_hf_agent_gdbus_method_send(const char *service,
943                                 GVariant *path, const char *interface,
944                                 const char *method)
945 {
946         DBG("+");
947
948         GVariant *ret;
949         GDBusProxy *proxy;
950         GError *error = NULL;
951
952         proxy = __bt_hf_gdbus_get_service_proxy(service, g_obj_path, interface);
953         if (!proxy)
954                 return BT_HF_AGENT_ERROR_INTERNAL;
955
956         ret = g_dbus_proxy_call_sync(proxy,
957                                 method, path,
958                                 G_DBUS_CALL_FLAGS_NONE, -1,
959                                 NULL, &error);
960         if (ret == NULL) {
961                 /* dBUS-RPC is failed */
962                 ERR("dBUS-RPC is failed");
963                 if (error != NULL) {
964                         /* dBUS gives error cause */
965                         ERR("D-Bus API failure: errCode[%x], message[%s]",
966                                error->code, error->message);
967
968                         g_clear_error(&error);
969                 }
970                 g_object_unref(proxy);
971                 return BT_HF_AGENT_ERROR_INTERNAL;
972         }
973
974         g_variant_unref(ret);
975         g_object_unref(proxy);
976
977         return BT_HF_AGENT_ERROR_NONE;
978 }
979
980 static void  __bt_hf_agent_release_queue(void)
981 {
982         int i, len;
983         bt_hf_agent_send_at_info *cmd;
984         GError *err;
985
986         len = g_slist_length(bt_hf_info.cmd_send_queue);
987         for (i = 0; i < len; ++i) {
988                 cmd = g_slist_nth_data(bt_hf_info.cmd_send_queue, i);
989                 if (cmd && cmd->context) {
990                         DBG("Pending context found for %.6s[%d]",
991                                                         cmd->at_cmd, cmd->id);
992                         err = __bt_hf_agent_set_error(BT_HF_AGENT_ERROR_INTERNAL);
993                         g_dbus_method_invocation_return_gerror(cmd->context, err);
994                         g_error_free(err);
995                 }
996                 if (cmd && cmd->timer_id)
997                         g_source_remove(cmd->timer_id);
998         }
999         g_slist_free(bt_hf_info.cmd_send_queue);
1000         bt_hf_info.cmd_send_queue = NULL;
1001         send_flag = 0;
1002 }
1003
1004 static gboolean __bt_hf_monitor_timer_cb(gpointer data)
1005 {
1006         DBG("+");
1007         bt_hf_agent_send_at_info *cmd = data;
1008         ERR_C("Monitor timer came becuase of timeout for sendflag %d, %s",
1009                                                 send_flag, cmd->at_cmd);
1010         /* In the case of ATD, we have to inform the remote to end the call */
1011         if (strstr(cmd->at_cmd, "ATD") || strstr(cmd->at_cmd, "BLDN")) {
1012                 INFO_C("Sending CHUP for remote call termination");
1013                 __bt_hf_send_only_without_queue(&bt_hf_info, BT_HF_END_CALL,
1014                                                          strlen(BT_HF_END_CALL));
1015                 /* Here there is a high posisbility that we do not get response
1016                  * for CHUP. Hence we need to decrement send_flag to process further
1017                  * incomming packets because we already incremented it in the CHUP case. */
1018                  if (send_flag)
1019                         send_flag--;
1020
1021                 /* In the case of ATD, prev_cmd will be always ATD, because we will not
1022                  * allow further commands. For safer side again set prev_cmd as ATD */
1023                 strncpy(prev_cmd, "ATD\0", BT_HF_CMD_BUF_SIZE - 1);
1024         }
1025         hf_handle_rx_at_cmd(&bt_hf_info, BT_HF_ERROR_RESP);
1026
1027         DBG("-");
1028
1029         return FALSE;
1030 }
1031
1032
1033 gboolean __bt_hf_agent_add_queue(GDBusMethodInvocation *context, char *at,
1034                                         int count, gboolean pending_flag)
1035 {
1036         int i, len, timer_id;
1037         if (bt_hf_info.slc == FALSE)
1038                 return FALSE;
1039
1040         DBG("Add Pending queue. (pending_flag is %s)",
1041                                 pending_flag ? "TRUE" : "FALSE");
1042
1043         bt_hf_agent_send_at_info *cmd = g_new0(bt_hf_agent_send_at_info, 1);
1044         if (!cmd) {
1045                 ERR("failed to allocate cmd");
1046                 return FALSE;
1047         }
1048
1049         cmd->id = ++g_id;
1050         memcpy(cmd->at_cmd, at, count);
1051         cmd->count = count;
1052         cmd->context =  context;
1053         cmd->pending = pending_flag;
1054         bt_hf_info.cmd_send_queue = g_slist_append(bt_hf_info.cmd_send_queue,
1055                                                                         cmd);
1056         len = g_slist_length(bt_hf_info.cmd_send_queue);
1057         for (i = 0; i < len; ++i) {
1058                 cmd = g_slist_nth_data(bt_hf_info.cmd_send_queue, i);
1059                 if (cmd)
1060                         DBG("Q> %.6s[%d]", cmd->at_cmd, cmd->id);
1061         }
1062
1063         /* We need to have base timeout + tolerance value to process other request */
1064         if (strstr(at, "ATD") || strstr(at, "BLDN")) {
1065                 /* Android 15 seconds timeout in case of ATD timeout in flight mode */
1066                 timer_id = g_timeout_add_seconds(BT_HF_COMMAND_TIMEOUT * 5 + len,
1067                                          __bt_hf_monitor_timer_cb, cmd);
1068                 if (cmd)
1069                         cmd->timer_id = timer_id;
1070         } else {
1071                 timer_id = g_timeout_add_seconds(BT_HF_COMMAND_TIMEOUT + len,
1072                                          __bt_hf_monitor_timer_cb, cmd);
1073                 if (cmd)
1074                         cmd->timer_id = timer_id;
1075         }
1076         return TRUE;
1077 }
1078
1079 /*
1080 Below methods exposed to Applicatoins
1081 */
1082 static gboolean __bt_hf_agent_emit_signal(GDBusConnection *connection,
1083                                 const char *path, const char *interface,
1084                                 const char *signal_name, GVariant *param)
1085 {
1086         GError *error = NULL;
1087         gboolean ret;
1088         ret =  g_dbus_connection_emit_signal(connection,
1089                                  NULL, path,
1090                                  interface, signal_name,
1091                                  param, &error);
1092         if (!ret) {
1093                 if (error != NULL) {
1094                         /* dBUS gives error cause */
1095                         ERR("D-Bus API failure: errCode[%x], message[%s]",
1096                                error->code, error->message);
1097                         g_clear_error(&error);
1098                 }
1099         }
1100         INFO_C("Emit Signal [%s]", signal_name);
1101
1102         return ret;
1103 }
1104
1105 static gboolean __bt_hf_agent_emit_property_changed(
1106                                 GDBusConnection *connection,
1107                                 const char *path,
1108                                 const char *interface,
1109                                 const char *name,
1110                                 GVariant *property)
1111 {
1112         DBG("+");
1113
1114         GError *error = NULL;
1115         gboolean ret;
1116         ret =  g_dbus_connection_emit_signal(connection,
1117                                 NULL, path, interface,
1118                                 "PropertyChanged",
1119                                 g_variant_new("(sv)", name, property),
1120                                 &error);
1121         if (!ret) {
1122                 if (error != NULL) {
1123                         /* dBUS gives error cause */
1124                         ERR("D-Bus API failure: errCode[%x], message[%s]",
1125                                error->code, error->message);
1126                         g_clear_error(&error);
1127                 }
1128         }
1129         DBG("-");
1130         return ret;
1131 }
1132
1133 /*
1134 Below methods exposed to Bluez
1135 */
1136
1137 static gboolean  __bt_hf_agent_launch_call_app(void)
1138 {
1139         bundle *b;
1140         bool is_running;
1141
1142         DBG("+");
1143         app_manager_is_running(CALL_ALIAS_APP_ID, &is_running);
1144         if (is_running) {
1145                 DBG("Call app is already started");
1146                 return TRUE;
1147         }
1148
1149         b = bundle_create();
1150         if (NULL == b) {
1151                 ERR("bundle_create() Failed");
1152                 return FALSE;
1153         }
1154
1155         bundle_add(b, "launch-type", "BT_LAUNCH");
1156
1157         bundle_add(b, "carrier-type", "BT");
1158         DBG("For 3G, carrier-type: BT has been added");
1159         aul_launch_app_async(CALL_ALIAS_APP_ID, b);
1160         bundle_free(b);
1161
1162         INFO("-aul_launch_app_async -");
1163
1164         return TRUE;
1165 }
1166
1167 static void __bt_hf_agent_handle_ind_change(bt_hf_agent_info_t *bt_hf_info,
1168                                                         guint index, gint value)
1169 {
1170         GDBusConnection *conn;
1171         gchar *name;
1172         struct indicator *ind = g_slist_nth_data(bt_hf_info->indies, index - 1);
1173         if (ind == NULL) {
1174                 ERR("Indicator is NULL");
1175                 return;
1176         }
1177
1178         name = ind->descr;
1179         ind->value = value;
1180
1181         conn = __bt_hf_get_gdbus_connection();
1182         if (!conn) {
1183                 ERR("Unable to get connection");
1184                 return;
1185         }
1186
1187         INFO("Indicator name is %s, value = [%d]", name, value);
1188         if (!strcmp(name, "\"call\"")) {
1189                 bt_hf_info->ciev_call_status = value;
1190                 if (value > 0) {
1191                         __bt_hf_agent_emit_signal(conn,
1192                                         BT_HF_AGENT_OBJECT_PATH,
1193                                         BT_HF_SERVICE_INTERFACE,
1194                                         "CallStarted", NULL);
1195                         bt_hf_info->is_dialing = FALSE;
1196                         bt_hf_info->call_active = TRUE;
1197                 } else if (bt_hf_info->call_active) {
1198                         __bt_hf_agent_emit_signal(conn,
1199                                         BT_HF_AGENT_OBJECT_PATH,
1200                                         BT_HF_SERVICE_INTERFACE,
1201                                         "CallEnded", NULL);
1202                         bt_hf_info->call_active = FALSE;
1203
1204                         if (bt_hf_info->ciev_call_setup_status == 0) {
1205                                 __bt_hf_agent_emit_signal(gdbus_conn,
1206                                                 BT_HF_AGENT_OBJECT_PATH,
1207                                                 BT_HF_SERVICE_INTERFACE,
1208                                                 "CallIdle", NULL);
1209                         }
1210                 }
1211
1212         } else if (!strcmp(name, "\"callsetup\"")) {
1213                 bt_hf_info->ciev_call_setup_status = value;
1214                 if (value == 0 && bt_hf_info->is_dialing) {
1215                         bt_hf_info->is_dialing = FALSE;
1216                         __bt_hf_agent_emit_signal(conn,
1217                                         BT_HF_AGENT_OBJECT_PATH,
1218                                         BT_HF_SERVICE_INTERFACE,
1219                                         "CallTerminated",
1220                                         NULL);
1221                 } else if (!bt_hf_info->is_dialing && value > 0) {
1222                         bt_hf_info->is_dialing = TRUE;
1223                 }
1224
1225                 if (bt_hf_info->ciev_call_setup_status == 1) {
1226                         __bt_hf_agent_emit_signal(gdbus_conn,
1227                                         BT_HF_AGENT_OBJECT_PATH,
1228                                         BT_HF_SERVICE_INTERFACE,
1229                                         "CallSetupIncoming", NULL);
1230                         if (__bt_hf_agent_launch_call_app()  == FALSE)
1231                                 DBG("call app launching failed");
1232                 } else if (bt_hf_info->ciev_call_setup_status == 2) {
1233                         __bt_hf_agent_emit_signal(gdbus_conn,
1234                                         BT_HF_AGENT_OBJECT_PATH,
1235                                         BT_HF_SERVICE_INTERFACE,
1236                                         "CallSetupDialing", NULL);
1237                 } else if (bt_hf_info->ciev_call_setup_status == 3) {
1238                         __bt_hf_agent_emit_signal(gdbus_conn,
1239                                         BT_HF_AGENT_OBJECT_PATH,
1240                                         BT_HF_SERVICE_INTERFACE,
1241                                         "CallSetupAlerting", NULL);
1242                 } else  if (bt_hf_info->ciev_call_status == 0 &&
1243                                                 bt_hf_info->ciev_call_setup_status == 0) {
1244                         __bt_hf_agent_emit_signal(gdbus_conn,
1245                                         BT_HF_AGENT_OBJECT_PATH,
1246                                         BT_HF_SERVICE_INTERFACE,
1247                                                 "CallIdle", NULL);
1248                 }
1249         } else if (!strcmp(name, "\"callheld\"")) {
1250                 if (value == 0) { /* No calls held*/
1251                         __bt_hf_agent_emit_signal(conn,
1252                                         BT_HF_AGENT_OBJECT_PATH,
1253                                         BT_HF_SERVICE_INTERFACE,
1254                                         "NoCallsHeld",
1255                                         NULL);
1256                 } else if (value == 1) {
1257                         /*Call is placed on hold or active/held calls swapped */
1258                         __bt_hf_agent_emit_signal(conn,
1259                                         BT_HF_AGENT_OBJECT_PATH,
1260                                         BT_HF_SERVICE_INTERFACE,
1261                                         "CallsSwapped", NULL);
1262                 } else {
1263                         /*Call on hold, no active call*/
1264                         __bt_hf_agent_emit_signal(conn,
1265                                         BT_HF_AGENT_OBJECT_PATH,
1266                                         BT_HF_SERVICE_INTERFACE,
1267                                         "CallOnHold", NULL);
1268                 }
1269         } else if (!strcmp(name, "\"service\"")) {
1270                 if (value < 0 || value > 1)
1271                         ERR("Out of range");
1272                 else
1273                 __bt_hf_agent_emit_property_changed(conn,
1274                                 BT_HF_AGENT_OBJECT_PATH,
1275                                 BT_HF_SERVICE_INTERFACE,
1276                                 "RegistrationStatus",
1277                                 g_variant_new("q", value));
1278         } else if (!strcmp(name, "\"signal\"")) {
1279                 if (value < 0 || value > 5)
1280                         ERR("Out of range");
1281                 else
1282                 __bt_hf_agent_emit_property_changed(conn,
1283                                 BT_HF_AGENT_OBJECT_PATH,
1284                                 BT_HF_SERVICE_INTERFACE, "SignalStrength",
1285                                 g_variant_new("q", value));
1286         } else if (!strcmp(name, "\"roam\"")) {
1287                 if (value < 0 || value > 1)
1288                         ERR("Out of range");
1289                 else
1290                 __bt_hf_agent_emit_property_changed(conn,
1291                                 BT_HF_AGENT_OBJECT_PATH,
1292                                 BT_HF_SERVICE_INTERFACE, "RoamingStatus",
1293                                 g_variant_new("q", value));
1294         } else if (!strcmp(name, "\"battchg\"")) {
1295                 if (value < 0 || value > 5)
1296                         ERR("Out of range");
1297                 else
1298                 __bt_hf_agent_emit_property_changed(conn,
1299                                 BT_HF_AGENT_OBJECT_PATH,
1300                                 BT_HF_SERVICE_INTERFACE, "BatteryCharge",
1301                                 g_variant_new("q", value));
1302         }
1303 }
1304
1305 static void __bt_hf_agent_handle_voice_activation(gint value)
1306 {
1307         GDBusConnection *conn;
1308
1309         conn = __bt_hf_get_gdbus_connection();
1310                 if (!conn) {
1311                 ERR("Unable to get connection");
1312                 return;
1313         }
1314
1315         __bt_hf_agent_emit_signal(conn, BT_HF_AGENT_OBJECT_PATH,
1316                 BT_HF_SERVICE_INTERFACE,
1317                 "VoiceRecognition",
1318                 g_variant_new("(i)", value));
1319
1320         return;
1321 }
1322
1323 static void __bt_hf_agent_handle_speaker_gain(gint value)
1324 {
1325         GDBusConnection *conn;
1326
1327         conn = __bt_hf_get_gdbus_connection();
1328         if (!conn) {
1329                 ERR("Unable to get connection");
1330                 return;
1331         }
1332
1333         __bt_hf_agent_emit_signal(conn, BT_HF_AGENT_OBJECT_PATH,
1334                                 BT_HF_SERVICE_INTERFACE, "VolumeSpeaker",
1335                                 g_variant_new("(i)", value));
1336
1337         return;
1338 }
1339
1340 static int __bt_hf_agent_handle_clip(bt_hf_agent_info_t *bt_hf_info,
1341                                                         const gchar *buf)
1342 {
1343         GDBusConnection *conn;
1344         gchar *clip;
1345         gchar number[BT_HF_CALLER_NUM_SIZE];
1346         gchar *sep;
1347         char fmt_str[BT_HF_FMT_STR_SIZE];
1348         int len = strlen(buf);
1349
1350         DBG("__bt_hf_agent_handle_clip +");
1351         if (len > BT_HF_CALLER_NUM_SIZE + 10) {
1352                 ERR("buf len %d is too long", len);
1353                 return 1;
1354         }
1355
1356         if ((clip = strstr(buf, "\r\n+CLIP"))) {
1357                 snprintf(fmt_str, sizeof(fmt_str), "\r\n+CLIP: \"%%%ds", (int)(sizeof(number) - 1));
1358                 if (sscanf(clip, fmt_str, number) == 1) {
1359                         sep = strchr(number, '"');
1360                         sep[0] = '\0';
1361
1362                         clip = number;
1363
1364                         conn = __bt_hf_get_gdbus_connection();
1365                         if (!conn) {
1366                                 ERR("Unable to get connection");
1367                                 return 1;
1368                         }
1369
1370                         __bt_hf_agent_emit_signal(conn,
1371                                         BT_HF_AGENT_OBJECT_PATH,
1372                                         BT_HF_SERVICE_INTERFACE, "Ring",
1373                                         g_variant_new("(s)", clip));
1374                 } else {
1375                         ERR_SECURE("CLIP '%s' is Call Incoming", buf);
1376                         return 1;
1377                 }
1378         }
1379         DBG("__bt_hf_agent_handle_clip -");
1380         return 0;
1381 }
1382
1383 static int __bt_hf_agent_handle_ccwa(bt_hf_agent_info_t *bt_hf_info,
1384                                                         const gchar *buf)
1385 {
1386         GDBusConnection *conn;
1387         gchar *ccwa;
1388         gchar number[BT_HF_CALLER_NUM_SIZE];
1389         gchar *sep;
1390         char fmt_str[BT_HF_FMT_STR_SIZE];
1391         int len = strlen(buf);
1392
1393         DBG("__bt_hf_agent_handle_ccwa +");
1394         if (len > BT_HF_CALLER_NUM_SIZE + 10) {
1395                 ERR("buf len %d is too long", len);
1396                 return 1;
1397         }
1398
1399         if ((ccwa = strstr(buf, "\r\n+CCWA"))) {
1400                 snprintf(fmt_str, sizeof(fmt_str), "\r\n+CCWA: \"%%%ds",
1401                                                                         (int)(sizeof(number) - 1));
1402                 if (sscanf(ccwa, fmt_str, number) == 1) {
1403                         sep = strchr(number, '"');
1404                         sep[0] = '\0';
1405
1406                         ccwa = number;
1407
1408                         conn = __bt_hf_get_gdbus_connection();
1409                         if (!conn) {
1410                                 ERR("Unable to get connection");
1411                                 return 1;
1412                         }
1413
1414                         __bt_hf_agent_emit_signal(conn,
1415                                         BT_HF_AGENT_OBJECT_PATH,
1416                                         BT_HF_SERVICE_INTERFACE, "CallWaiting",
1417                                         g_variant_new("(s)", ccwa));
1418                 } else {
1419                         ERR_SECURE("CCWA '%s' is Call Wating", buf);
1420                         return 1;
1421                 }
1422         }
1423         DBG("__bt_hf_agent_handle_ccwa -");
1424         return 0;
1425 }
1426
1427 static void __bt_hf_agent_handle_bsir(bt_hf_agent_info_t *bt_hf_info,
1428                                                         gint value)
1429 {
1430         INFO("new value : %d", value);
1431
1432         if (value == 1)
1433                 bt_hf_info->inband_ringtone_support = TRUE;
1434         else
1435                 bt_hf_info->inband_ringtone_support = FALSE;
1436
1437         return;
1438 }
1439
1440 static GSList *__bt_hf_prepare_call_list(const char *buf)
1441 {
1442         GSList *call_list = NULL;
1443         char *str = NULL;
1444         char *ptr = NULL;
1445         char *temp = NULL;
1446         char *sp;
1447         char delim_sep[] = "\r\n";
1448         char temp_buf[BT_HF_DATA_BUF_SIZE] = {0,};
1449
1450         hf_call_list_info_t *call_info;
1451
1452         DBG("+");
1453         strncpy(temp_buf, buf, BT_HF_DATA_BUF_SIZE - 1);
1454
1455         str = strtok_r(temp_buf, delim_sep, &sp);
1456         while (str != NULL) {
1457                 if (!(strstr(str, "+CLCC:"))) {
1458                         str = strtok_r(NULL, delim_sep, &sp);
1459                         continue;
1460                 }
1461
1462                 call_info = g_new0(hf_call_list_info_t, 1);
1463
1464                 sscanf(str, "+CLCC: %1d,%1d, %1d, %1d, %1d",
1465                                 &call_info->idx, &call_info->dir,
1466                                 &call_info->status, &call_info->mode,
1467                                 &call_info->multi_party);
1468                 DBG("Index = [%d], Direction = [%d], Status = [%d], Mode = [%d], Multi_party = [%d]\n",
1469                                 call_info->idx, call_info->dir, call_info->status,
1470                                 call_info->mode, call_info->multi_party);
1471
1472                 ptr = strstr(str, "\"");
1473                 if (ptr) {
1474                         temp = strstr(ptr + 1, "\"");
1475                         if (temp) {
1476                                 *temp = '\0';
1477                                 DBG_SECURE("\tPhone Number = [%s]\n", ptr + 1);
1478                                 call_info->number = g_strdup(ptr + 1);
1479
1480                                 if (strstr(temp + 1, ",")) {
1481                                         temp += 2;
1482                                         DBG("\tType = [%s]\n", temp);
1483                                         call_info->type = atoi(temp);
1484                                 }
1485                         }
1486                 } else {
1487                         /*In case of no phone no. in CLCC respnse, we should launch call application
1488                          * with NULL string. By doing so "unknown" shall be displayed*/
1489                         DBG("Phone number does not exist\n");
1490                         call_info->number = g_strdup("");
1491                 }
1492
1493                 call_list = g_slist_append(call_list, call_info);
1494                 str = strtok_r(NULL, delim_sep, &sp);
1495         }
1496         DBG("-");
1497         return call_list;
1498 }
1499
1500 static GSList *__bt_hf_get_call_list(bt_hf_agent_info_t *bt_hf_info)
1501 {
1502         char buf[BT_HF_DATA_BUF_SIZE] = {0,};
1503         GSList *call_list = NULL;
1504
1505         DBG("+");
1506
1507         /* Send CLCC when the callsetup */
1508         __bt_hf_send_and_read(bt_hf_info, BT_HF_CALLLIST, buf,
1509                         sizeof(BT_HF_CALLLIST) - 1);
1510         DBG_SECURE("Receive CLCC response buffer = '%s'", buf);
1511
1512         call_list =  __bt_hf_prepare_call_list(buf);
1513         DBG("-");
1514         return call_list;
1515 }
1516
1517 static void __bt_hf_call_info_free(void *data)
1518 {
1519         DBG("+");
1520
1521         hf_call_list_info_t *call_info = data;
1522         g_free(call_info->number);
1523         g_free(call_info);
1524
1525         DBG("-");
1526 }
1527
1528 static void __bt_hf_free_call_list(GSList *call_list)
1529 {
1530         DBG("+");
1531
1532         g_slist_free_full(call_list, __bt_hf_call_info_free);
1533
1534         DBG("-");
1535 }
1536
1537 static void __bt_hf_launch_call_using_call_list(GSList *call_list)
1538 {
1539         guint len;
1540
1541         DBG("+");
1542         if (call_list == NULL)
1543                 return;
1544
1545         len = g_slist_length(call_list);
1546
1547         if (len > 0 && __bt_hf_agent_launch_call_app() == FALSE)
1548                 DBG("call app launching failed");
1549
1550         DBG("-");
1551 }
1552
1553 static GVariant *__bt_hf_agent_get_call_status_info(GSList *call_list)
1554 {
1555         DBG("+");
1556
1557         int32_t call_count;
1558         gchar *caller;
1559         hf_call_list_info_t *call_info;
1560
1561         GVariantBuilder *builder;
1562         GVariant *var_data;
1563
1564         builder = g_variant_builder_new(G_VARIANT_TYPE("a(siiii)"));
1565
1566         call_count = g_slist_length(call_list);
1567         DBG("Total call count = '%d'", call_count);
1568
1569         while (call_count--) {
1570                 call_info = g_slist_nth_data(call_list, call_count);
1571                 if (call_info) {
1572                         INFO("Idx=%d, Dir=%d, status=%d, mode=%d, mparty=%d",
1573                         call_info->idx, call_info->dir, call_info->status,
1574                         call_info->mode, call_info->multi_party);
1575                         caller = call_info->number;
1576
1577                         g_variant_builder_add(builder, "(siiii)",
1578                                         caller, call_info->dir, call_info->status,
1579                                         call_info->multi_party, call_info->idx);
1580                 }
1581         }
1582         var_data = g_variant_new("(ia(siiii))",
1583                                 g_slist_length(call_list), builder);
1584
1585         g_variant_builder_unref(builder);
1586         DBG("-");
1587         return  var_data;
1588 }
1589
1590 static void __bt_hf_clear_prev_sent_cmd(void)
1591 {
1592         if (prev_cmd[0] != 0)
1593                 ERR("No sent command");
1594
1595         memset(prev_cmd, 0, BT_HF_CMD_BUF_SIZE);
1596
1597         return;
1598 }
1599
1600 static void __bt_hf_agent_send_call_status_info(GSList *call_list)
1601 {
1602         GDBusConnection *conn;
1603         GVariant *var_data;
1604
1605         conn = __bt_hf_get_gdbus_connection();
1606         if (!conn) {
1607                 ERR("Unable to get connection");
1608         } else {
1609                 var_data = __bt_hf_agent_get_call_status_info(call_list);
1610                 __bt_hf_agent_emit_signal(conn,
1611                                 BT_HF_AGENT_OBJECT_PATH,
1612                                 BT_HF_SERVICE_INTERFACE,
1613                                 "CallStatusUpdate",
1614                                 var_data);
1615         }
1616 }
1617
1618 static void __bt_hf_agent_handle_call_list(bt_hf_agent_info_t *bt_hf_info)
1619 {
1620         int ret;
1621
1622         __bt_hf_lock_display(0);
1623
1624         bt_hf_info->context = NULL;
1625
1626         /* Send CLCC. The response will be handled in the handler */
1627         ret = __bt_hf_send_only(bt_hf_info, BT_HF_CALLLIST,
1628                                                 sizeof(BT_HF_CALLLIST) - 1);
1629         if (!ret)
1630                 ERR("Failed to send CLCC");
1631
1632         __bt_hf_unlock_display();
1633 }
1634
1635 static gboolean __bt_hf_send_available_codec(bt_hf_agent_info_t *bt_hf_info, int send_only)
1636 {
1637         gchar buf[BT_HF_DATA_BUF_SIZE];
1638         gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
1639         gboolean ret;
1640
1641         snprintf(cmd_buf, sizeof(cmd_buf), BT_HF_AVAILABLE_CODEC,
1642                         BT_HF_CODEC_ID_CVSD, BT_HF_CODEC_ID_MSBC);
1643         if (send_only) {
1644                 bt_hf_info->context = NULL;
1645
1646                 ret = __bt_hf_send_only(bt_hf_info, cmd_buf, strlen(cmd_buf));
1647                 return TRUE;
1648         } else {
1649                 ret = __bt_hf_send_and_read(bt_hf_info, cmd_buf, buf,
1650                                 strlen(cmd_buf));
1651         }
1652         if (!ret || !strstr(buf, "OK"))
1653                 return FALSE;
1654
1655         return TRUE;
1656 }
1657
1658 static  int _hf_agent_codec_setup(const char *addr, guint codec_id)
1659 {
1660         int ret;
1661
1662         if (!g_obj_path) {
1663                 ERR("g_obj_path is NULL\n");
1664                 return BT_HF_AGENT_ERROR_INTERNAL;
1665         }
1666
1667         switch (codec_id) {
1668         case BT_HF_CODEC_ID_CVSD:
1669                 INFO("Set NB parameters");
1670                 ret = __bt_hf_agent_gdbus_method_send(BLUEZ_SERVICE_NAME,
1671                                                 g_variant_new("(ss)", "Handsfree", addr),
1672                                                 BT_ADAPTER_INTERFACE,
1673                                                 "SetNbParameters");
1674                 break;
1675         case BT_HF_CODEC_ID_MSBC:
1676                 INFO("Set WBS parameters");
1677                 ret = __bt_hf_agent_gdbus_method_send(BLUEZ_SERVICE_NAME,
1678                                                 g_variant_new("(ss)", "Handsfree", addr),
1679                                                 BT_ADAPTER_INTERFACE,
1680                                                 "SetWbsParameters");
1681                 break;
1682         default:
1683                 ret = BT_HF_AGENT_ERROR_INTERNAL;
1684                 ERR("Invalid Codec\n");
1685                 break;
1686         }
1687
1688         if (ret)
1689                 ERR("Failed to setup the Codec\n");
1690         else
1691                 current_codec_id = codec_id;
1692
1693         return ret;
1694 }
1695
1696 static void __bt_hf_agent_handle_codec_select(bt_hf_agent_info_t *bt_hf_info,
1697                                                         guint codec_id)
1698 {
1699         gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
1700         gboolean ret;
1701         int retval;
1702
1703         if (codec_id != BT_HF_CODEC_ID_CVSD && codec_id != BT_HF_CODEC_ID_MSBC) {
1704                 INFO("Codec id doesn't match, so send available codec again");
1705                 ret = __bt_hf_send_available_codec(bt_hf_info, 1);
1706                 if (FALSE == ret)
1707                         ERR("Failed to send avalable codec");
1708                 return;
1709         }
1710
1711         /* HF should be ready accpet SCO connection before sending theresponse for
1712         "\r\n+BCS=>Codec ID\r\n", Keep the BT chip ready to recevie encoded SCO data */
1713         retval = _hf_agent_codec_setup(bt_hf_info->remote_addr, codec_id);
1714         if (retval) {
1715                 ERR("_hf_agent_codec_setup : Failed [%d]", retval);
1716         }
1717
1718         snprintf(cmd_buf, sizeof(cmd_buf), BT_HF_CODEC_SELECT, codec_id);
1719
1720         bt_hf_info->context = NULL;
1721         ret = __bt_hf_send_only(bt_hf_info, cmd_buf, strlen(cmd_buf));
1722         if (FALSE == ret) {
1723                 ERR("__bt_hf_send_only : FALSE");
1724         }
1725 }
1726
1727 static int __bt_hf_agent_handler_ciev(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1728 {
1729         gchar indicator[BT_HF_INDICATOR_DESCR_SIZE + 4];
1730         gchar *sep;
1731         gint value;
1732         guint index;
1733         char fmt_str[BT_HF_FMT_STR_SIZE];
1734
1735         DBG("++++++++ __bt_hf_agent_handler_ciev +++++++++");
1736
1737         snprintf(fmt_str, sizeof(fmt_str), "\r\n+CIEV:%%%ds\r\n",
1738                                                                 BT_HF_INDICATOR_DESCR_SIZE + 4 - 1);
1739         if (sscanf(buf, fmt_str, indicator) == 1) {
1740                 sep = strchr(indicator, ',');
1741                 sep[0] = '\0';
1742                 sep += 1;
1743                 index = atoi(indicator);
1744                 value = atoi(sep);
1745                 __bt_hf_agent_handle_ind_change(bt_hf_info, index, value);
1746         }
1747         DBG("--------- __bt_hf_agent_handler_ciev ------------");
1748         return 0;
1749 }
1750
1751 static void __bt_hf_agent_handle_ven_samsung(bt_hf_agent_info_t *bt_hf_info,
1752                                                 gint app_id, const char *msg)
1753 {
1754         /* Whomesoever wants need to handle it */
1755         char *sig_name = "SamsungXSAT";
1756         GDBusConnection *conn;
1757
1758         conn = __bt_hf_get_gdbus_connection();
1759         if (!conn) {
1760                 ERR("Unable to get connection");
1761                 return;
1762         }
1763
1764         __bt_hf_agent_emit_signal(conn,
1765                                 BT_HF_AGENT_OBJECT_PATH,
1766                                 BT_HF_SERVICE_INTERFACE,
1767                                 sig_name,
1768                                 g_variant_new("(is)", app_id, msg));
1769 }
1770
1771 static int __bt_hf_agent_handler_ring(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1772 {
1773         DBG("++++++++ __bt_hf_agent_handler_ring ++++++++");
1774         DBG("---------__bt_hf_agent_handler_ring --------");
1775
1776         return 0;
1777 }
1778
1779 static int __bt_hf_agent_handler_clip(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1780 {
1781         DBG("+++++++++ __bt_hf_agent_handler_clip ++++++++");
1782         __bt_hf_agent_handle_clip(bt_hf_info, buf);
1783         DBG("---------__bt_hf_agent_handler_clip --------");
1784
1785         return 0;
1786 }
1787
1788 static int __bt_hf_agent_handler_bvra(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1789 {
1790         DBG("+++++++++ __bt_hf_agent_handler_bvra +++++++++");
1791         gint value;
1792          if (sscanf(buf, "\r\n+BVRA:%1d\r\n", &value) == 1)
1793                 __bt_hf_agent_handle_voice_activation(value);
1794
1795          DBG("---------__bt_hf_agent_handler_bvra --------");
1796         return 0;
1797 }
1798
1799 static int __bt_hf_agent_handler_bcs(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1800 {
1801         guint codec_id;
1802         DBG("+++++++++ __bt_hf_agent_handler_bcs +++++++++-");
1803         if (sscanf(buf, "\r\n+BCS:%3d\r\n", &codec_id))
1804                 __bt_hf_agent_handle_codec_select(bt_hf_info, codec_id);
1805
1806         DBG("---------__bt_hf_agent_handler_bcs --------");
1807         return 0;
1808 }
1809
1810 static int __bt_hf_agent_handler_vgs(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1811 {
1812         gint value;
1813         int ret = 0;
1814         DBG("+++++++++ __bt_hf_agent_handler_vgs +++++++++");
1815         if (buf[6] == ':')
1816                 ret = sscanf(buf, "\r\n+VGS:%2d\r\n", &value);
1817         else if (buf[6] == '=')
1818                 ret = sscanf(buf, "\r\n+VGS=%2d\r\n", &value);
1819         if (ret)
1820                 __bt_hf_agent_handle_speaker_gain(value);
1821
1822         DBG("---------__bt_hf_agent_handler_vgs --------");
1823
1824         return 0;
1825 }
1826
1827 static int __bt_hf_agent_handler_ccwa(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1828 {
1829         DBG("+++++++++ __bt_hf_agent_handler_ccwa ++++++++");
1830                 __bt_hf_agent_handle_ccwa(bt_hf_info, buf);
1831         DBG("---------__bt_hf_agent_handler_ccwa --------");
1832
1833         return 0;
1834 }
1835
1836
1837 static int __bt_hf_agent_handler_xsat(bt_hf_agent_info_t *bt_hf_info,
1838                                                         const char *buf)
1839 {
1840         gint app_id = 0;
1841         char msg[BT_HF_DATA_BUF_SIZE];
1842         char fmt_str[BT_HF_CMD_BUF_SIZE];
1843
1844         DBG("+++++++++ __bt_hf_agent_handler_xsat +++++++++");
1845         snprintf(fmt_str, sizeof(fmt_str), "\r\n+XSAT:%%d,%%%ds\r\n",
1846                                                                                 (int)(sizeof(msg) - 1));
1847         if (sscanf(buf, fmt_str, &app_id, msg)) {
1848                 if (app_id == 2 && strstr(msg, "READTXPOWER")) {
1849                         char cmd_buf[BT_HF_CMD_BUF_SIZE * 2] = {0, };
1850                         char power = __bt_hf_agent_get_tx_power(bt_hf_info->remote_addr);
1851                         snprintf(cmd_buf, sizeof(cmd_buf), "AT+XSAT: 2,%d", power);
1852                         bt_hf_agent_send_at_cmd(NULL, cmd_buf);
1853                 } else {
1854                         __bt_hf_agent_handle_ven_samsung(bt_hf_info, app_id, msg);
1855                 }
1856         }
1857
1858         DBG("---------__bt_hf_agent_handler_xsat --------");
1859
1860         return 0;
1861 }
1862
1863 static int __bt_hf_agent_handler_bsir(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1864 {
1865         DBG("+++++++++ __bt_hf_agent_handler_bsir +++++++++");
1866         gint value;
1867          if (sscanf(buf, "\r\n+BSIR:%1d\r\n", &value) == 1)
1868                 __bt_hf_agent_handle_bsir(bt_hf_info, value);
1869
1870          DBG("---------__bt_hf_agent_handler_bsir --------");
1871         return 0;
1872 }
1873
1874 static int __bt_hf_agent_handler_cme_error(bt_hf_agent_info_t *bt_hf_info,
1875                                                         const char *buf)
1876 {
1877         DBG("+++++++++ __bt_hf_agent_handler_cme_error ++++++++");
1878
1879         GDBusConnection *conn;
1880
1881         if (strstr(prev_cmd, "ATD") || strstr(prev_cmd, BT_HF_REDIAL)) {
1882                 conn = __bt_hf_get_gdbus_connection();
1883                 if (!conn) {
1884                         ERR("Unable to get connection");
1885                         return 0;
1886                 }
1887
1888                 __bt_hf_agent_emit_signal(conn,
1889                                         BT_HF_AGENT_OBJECT_PATH,
1890                                         BT_HF_SERVICE_INTERFACE,
1891                                         "FailedToDial",
1892                                         NULL);
1893         }
1894
1895         __bt_hf_clear_prev_sent_cmd();
1896
1897         return 0;
1898 }
1899
1900 static int __bt_hf_agent_handler_response_ok(bt_hf_agent_info_t *bt_hf_info,
1901                                                         const char *buf)
1902 {
1903         DBG("+++++++++ __bt_hf_agent_handler_response_ok ++++++++");
1904
1905         __bt_hf_clear_prev_sent_cmd();
1906
1907         return 0;
1908 }
1909
1910 static int __bt_hf_agent_handler_response_err(bt_hf_agent_info_t *bt_hf_info,
1911                                                         const char *buf)
1912 {
1913         DBG("+++++++++ __bt_hf_agent_handler_response_err ++++++++");
1914         GDBusConnection *conn;
1915
1916         if (strstr(prev_cmd, "ATD") || strstr(prev_cmd, BT_HF_REDIAL)) {
1917                 conn = __bt_hf_get_gdbus_connection();
1918                 if (!conn) {
1919                         ERR("Unable to get connection");
1920                         return 0;
1921                 }
1922
1923                 __bt_hf_agent_emit_signal(conn, BT_HF_AGENT_OBJECT_PATH,
1924                                         BT_HF_SERVICE_INTERFACE,
1925                                         "FailedToDial",
1926                                         NULL);
1927         }
1928         __bt_hf_clear_prev_sent_cmd();
1929
1930         return 0;
1931 }
1932
1933 static int __bt_hf_agent_handler_response_serr(bt_hf_agent_info_t *bt_hf_info,
1934                                                         const char *buf)
1935 {
1936         DBG("+");
1937         GDBusConnection *conn;
1938
1939         if (strstr(prev_cmd, "ATD") || strstr(prev_cmd, BT_HF_REDIAL)) {
1940                 conn = __bt_hf_get_gdbus_connection();
1941                 if (!conn) {
1942                         ERR("Unable to get connection");
1943                         return 0;
1944                 }
1945
1946                 __bt_hf_agent_emit_signal(conn, BT_HF_AGENT_OBJECT_PATH,
1947                                         BT_HF_SERVICE_INTERFACE,
1948                                         "FailedToDial",
1949                                         NULL);
1950         }
1951
1952         __bt_hf_clear_prev_sent_cmd();
1953
1954         DBG("-");
1955         return 0;
1956 }
1957
1958 static int __bt_hf_agent_handler_clcc(bt_hf_agent_info_t *bt_hf_info, const char *buffer)
1959 {
1960
1961         GSList *call_list = NULL;
1962         DBG("+++++++++ __bt_hf_agent_handler_clcc ++++++++");
1963         DBG_SECURE("Receive CLCC response buffer = '%s'", buffer);
1964
1965         __bt_hf_lock_display(0);
1966
1967         call_list = __bt_hf_prepare_call_list(buffer);
1968
1969         if (call_list == NULL)
1970                 goto done;
1971
1972         __bt_hf_launch_call_using_call_list(call_list);
1973
1974         __bt_hf_agent_send_call_status_info(call_list);
1975
1976         __bt_hf_free_call_list(call_list);
1977
1978 done:
1979         __bt_hf_unlock_display();
1980         DBG("---------__bt_hf_agent_handler_clcc --------");
1981         return 0;
1982 }
1983
1984 static bt_hf_event hf_event_callbacks[] = {
1985         { "\r\n+CIEV:", __bt_hf_agent_handler_ciev },
1986         { "\r\nRING", __bt_hf_agent_handler_ring },
1987         { "\r\n+CLIP:", __bt_hf_agent_handler_clip },
1988         { "\r\n+BVRA:", __bt_hf_agent_handler_bvra },
1989         { "\r\n+BCS:", __bt_hf_agent_handler_bcs },
1990         { "\r\n+VGS", __bt_hf_agent_handler_vgs },
1991         { "\r\n+CCWA:", __bt_hf_agent_handler_ccwa },
1992         { "\r\n+XSAT:", __bt_hf_agent_handler_xsat },
1993         {"\r\n+CLCC:", __bt_hf_agent_handler_clcc },
1994         {"\r\n+BSIR:", __bt_hf_agent_handler_bsir },
1995         { 0 }
1996 };
1997
1998 static bt_hf_event hf_event_resp_callbacks[] = {
1999         { "\r\n+CME ERROR:", __bt_hf_agent_handler_cme_error },
2000         { "\r\nOK\r\n", __bt_hf_agent_handler_response_ok },
2001         { "ERROR", __bt_hf_agent_handler_response_err },
2002         { "SERR", __bt_hf_agent_handler_response_serr },
2003         { 0 }
2004 };
2005
2006 bt_hf_agent_send_at_info *__bt_hf_agent_find_next(bt_hf_agent_info_t *bt_hf_info)
2007 {
2008         int len;
2009         int i;
2010         bt_hf_agent_send_at_info *cmd;
2011         len = g_slist_length(bt_hf_info->cmd_send_queue);
2012         for (i = 0; i < len; ++i) {
2013                 cmd = g_slist_nth_data(bt_hf_info->cmd_send_queue, i);
2014                 if (cmd)
2015                         DBG("F> %.6s[%d]", cmd->at_cmd, cmd->id);
2016         }
2017         len = g_slist_length(bt_hf_info->cmd_send_queue);
2018         DBG("Context queue length = %d", len);
2019         if (len == 0)
2020                 return NULL;
2021
2022         cmd = g_slist_nth_data(bt_hf_info->cmd_send_queue, 0);
2023         if (cmd) {
2024                 bt_hf_info->cmd_send_queue = g_slist_remove(bt_hf_info->cmd_send_queue, cmd);
2025                 DBG("NEXT[%d] Found %s, context = 0x%p, pending = %d", cmd->id,
2026                                 cmd->at_cmd, cmd->context, cmd->pending);
2027                         return cmd;
2028         }
2029
2030         DBG("**** Not found any pending command on list length %d ****", len);
2031
2032         return NULL;
2033 }
2034
2035 static int hf_handle_rx_at_cmd(bt_hf_agent_info_t *bt_hf_info, const char *buf)
2036 {
2037         bt_hf_event *ev;
2038         int ret = -EINVAL;
2039         bt_hf_agent_send_at_info *cmd = NULL;
2040
2041         __bt_hf_agent_print_at_buffer("Processing [Rx cmd]:", buf);
2042
2043         for (ev = hf_event_resp_callbacks; ev->cmd; ev++) {
2044                 if (strstr(buf, ev->cmd)) {
2045                         if (send_flag)
2046                                 send_flag--;
2047                         DBG("Send flag value = %d(after)", send_flag);
2048                         ret = ev->callback(bt_hf_info, buf);
2049                 }
2050         }
2051
2052         if (ret != -EINVAL)
2053                 goto done;
2054
2055         for (ev = hf_event_callbacks; ev->cmd; ev++) {
2056                 if (!strncmp(buf, ev->cmd, strlen(ev->cmd))) {
2057                         ret = ev->callback(bt_hf_info, buf);
2058                         break;
2059                 }
2060         }
2061
2062                 return ret;
2063 done:
2064
2065         cmd = __bt_hf_agent_find_next(bt_hf_info);
2066
2067         if (cmd && cmd->context) {
2068                 DBG("Pending context found for %.6s[%d]", cmd->at_cmd, cmd->id);
2069                 g_dbus_method_invocation_return_value(cmd->context, NULL);
2070                 if (cmd->timer_id)
2071                         g_source_remove(cmd->timer_id);
2072                 g_free(cmd);
2073                 cmd = NULL;
2074         }
2075
2076         if (cmd == NULL)
2077                 cmd = __bt_hf_agent_find_next(bt_hf_info);
2078
2079         if (cmd && cmd->pending && send_flag == 0) {
2080                 DBG("Pending only found of %.6s[%d]", cmd->at_cmd, cmd->id);
2081                 __bt_hf_send_only_without_queue(bt_hf_info,
2082                                         cmd->at_cmd, cmd->count);
2083                  cmd->pending = FALSE;
2084                 bt_hf_info->cmd_send_queue = g_slist_prepend(bt_hf_info->cmd_send_queue,
2085                                                                         cmd);
2086                 DBG("Prepend %.6s[%d]", cmd->at_cmd, cmd->id);
2087         } else {
2088                 if (cmd) {
2089                         DBG("Pending free for %.6s[%d] - send_flag = %d",
2090                                         cmd->at_cmd, cmd->id, send_flag);
2091                         if (cmd->timer_id)
2092                                 g_source_remove(cmd->timer_id);
2093                         g_free(cmd);
2094                 }
2095
2096
2097
2098                 /* Need to process further pending */
2099                 cmd = __bt_hf_agent_find_next(bt_hf_info);
2100                 if (cmd) {
2101                         if (cmd->pending && send_flag == 0) {
2102                                 DBG("2nd Pending only found of %.6s[%d]",
2103                                                         cmd->at_cmd, cmd->id);
2104                                 __bt_hf_send_only_without_queue(bt_hf_info,
2105                                                 cmd->at_cmd, cmd->count);
2106                                  cmd->pending = FALSE;
2107                         }
2108                         bt_hf_info->cmd_send_queue = g_slist_prepend(bt_hf_info->cmd_send_queue,
2109                                                                         cmd);
2110                         DBG("2nd Prepend %.6s[%d]", cmd->at_cmd, cmd->id);
2111                 }
2112         }
2113         return ret;
2114 }
2115
2116 static int hf_handle_append_clcc_buff(char *cmd_buf, const char *buf)
2117 {
2118         int buf_length;
2119         int cmd_length =  0;
2120         int cmd_buf_len = 0;
2121         char *pos_start, *pos_end;
2122         const char *datap = buf;
2123
2124         cmd_buf_len = strlen(cmd_buf);
2125         buf_length = strlen(buf);
2126         DBG("buf_length = %d, cmd_buf_len = %d", buf_length, cmd_buf_len);
2127
2128         if (buf_length > 0 && strstr(datap, "+CLCC")) {
2129                 pos_start = strstr(datap, "\r\n");
2130                 if (pos_start == NULL) {
2131                         ERR("Invalid AT command signature..\n");
2132                         return 0;
2133                 }
2134
2135                 pos_end = g_strrstr(datap, "+CLCC");
2136                 if (pos_end == NULL) {
2137                         ERR("Invalid AT command signature..\n");
2138                         return 0;
2139                 }
2140                 pos_end = strstr(pos_end, "\r\n");
2141                 cmd_length = (pos_end - pos_start) + 2;
2142                 INFO("CLCC balance Cmd Length = %d\n", cmd_length);
2143                 memcpy(cmd_buf + cmd_buf_len, pos_start, cmd_length);
2144                 cmd_buf[cmd_buf_len + cmd_length] = '\0';
2145
2146                 if (strstr(cmd_buf, "\r\nOK\r\n")) {
2147                         pos_end = strstr(datap, "\r\nOK\r\n");
2148                         cmd_length = (pos_end - pos_start);
2149                         memcpy(cmd_buf + cmd_buf_len, pos_start, cmd_length);
2150                         cmd_buf[cmd_buf_len + cmd_length] = '\0';
2151                         INFO("New CLCC balance Cmd Length = %d", cmd_length);
2152                 }
2153         }
2154         return cmd_length;
2155 }
2156
2157
2158 static int hf_handle_rx_at_buff(bt_hf_agent_info_t *bt_hf_info, const char *buf)
2159 {
2160         int buf_length;
2161         int cmd_length;
2162         char *pos_start, *pos_end;
2163         int tmp;
2164         gchar cmd_buf[BT_HF_DATA_BUF_SIZE] = {0,};
2165         const char *datap = buf;
2166
2167         __bt_hf_agent_print_at_buffer("[HF AT CMD] Recv >>>>>:", buf);
2168
2169         buf_length = strlen(buf);
2170
2171         while (buf_length > 0) {
2172                 pos_start = strstr(datap, "\r\n");
2173                 if (pos_start == NULL) {
2174                         ERR("Invalid AT command start signature..\n");
2175                         break;
2176                 }
2177
2178                 datap += 2;
2179                 pos_end = strstr(datap, "\r\n");
2180                 if (pos_end == NULL) {
2181                         ERR("Invalid AT command end signature..\n");
2182                         break;
2183                 }
2184                 cmd_length = (pos_end - pos_start) + 2;
2185                 DBG("Cmd Length = %d\n", cmd_length);
2186
2187                 if (cmd_length > BT_HF_DATA_BUF_SIZE - 1)
2188                         return FALSE;
2189                 memcpy(cmd_buf, pos_start, cmd_length);
2190                 cmd_buf[cmd_length] = '\0';
2191
2192                 buf_length = buf_length - cmd_length;
2193                 datap = datap + cmd_length - 2;
2194
2195                 /* We need to pass all the CLCC's together to its handler */
2196                 if (strstr(cmd_buf, "+CLCC")) {
2197                         tmp = hf_handle_append_clcc_buff(cmd_buf, datap);
2198                         datap += tmp;
2199                         buf_length = buf_length - tmp;
2200                 }
2201                 hf_handle_rx_at_cmd(bt_hf_info, cmd_buf);
2202                 DBG("Pending buf_length = %d\n", buf_length);
2203         }
2204         return TRUE;
2205
2206 }
2207 static gboolean __bt_hf_agent_data_cb(GIOChannel *chan, GIOCondition cond,
2208                                         bt_hf_agent_info_t *bt_hf_info)
2209 {
2210         gchar buf[BT_HF_DATA_BUF_SIZE] = {0,};
2211         gsize read;
2212         GError *gerr = NULL;
2213         gboolean recvd_ok = FALSE;
2214         gboolean recvd_error = FALSE;
2215         gboolean recvd_sec_error = FALSE;
2216
2217         if (cond & (G_IO_ERR | G_IO_HUP)) {
2218                 ERR("ERR or HUP on RFCOMM socket");
2219                 INFO_C("### Disconnected [HF role] [Terminated by remote dev]");
2220                 is_hf_connected = FALSE;
2221                 bt_hf_info->slc = FALSE;
2222                 __bt_hf_agent_release();
2223                 return FALSE;
2224         }
2225
2226         if (g_io_channel_read_chars(chan, buf, sizeof(buf) - 1, &read, &gerr)
2227                         != G_IO_STATUS_NORMAL) {
2228                 if (gerr) {
2229                         ERR("Read failed, cond = [%d], Err msg = [%s]",
2230                                                         cond, gerr->message);
2231                         g_error_free(gerr);
2232                 }
2233                 return TRUE;
2234         }
2235         buf[read] = '\0';
2236         recvd_ok = NULL != strstr(buf, BT_HF_OK_RESPONSE);
2237         recvd_error = NULL != strstr(buf, BT_HF_ERROR_RESPONSE);
2238         recvd_sec_error = NULL != strstr(buf, BT_HF_SEC_ERROR_RESPONSE);
2239         DBG("<-------Received data --send flag status = %d ----->", send_flag);
2240
2241         /* Once service level connection is established we need to handle
2242          * all the intermediate AT commands */
2243         if (bt_hf_info->state != BT_HF_STATE_CONNECTED)
2244                 return TRUE;
2245
2246         if (send_flag) {
2247                 strncat(global_buff, buf,
2248                         (BT_AT_COMMAND_BUFFER_MAX - 1) - strlen(global_buff));
2249                 if (!(recvd_ok || recvd_error || recvd_sec_error)) {
2250                         __bt_hf_agent_print_at_buffer("Concat ()", global_buff);
2251                 } else {
2252                         DBG("*** Received terminator.. process Rx buffer ***");
2253                         hf_handle_rx_at_buff(bt_hf_info, global_buff);
2254                         memset(global_buff, 0, sizeof(global_buff));
2255                 }
2256         } else {
2257                 INFO("***  Received Direct AT buffer packet handling ****");
2258                 hf_handle_rx_at_buff(bt_hf_info, buf);
2259         }
2260         return TRUE;
2261 }
2262
2263 static void __bt_hf_agent_start_watch(bt_hf_agent_info_t *bt_hf_info)
2264 {
2265         bt_hf_info->watch_id = g_io_add_watch(bt_hf_info->io_chan,
2266                         G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
2267                         (GIOFunc) __bt_hf_agent_data_cb, bt_hf_info);
2268 }
2269
2270 static void __bt_hf_agent_stop_watch(bt_hf_agent_info_t *bt_hf_info)
2271 {
2272         if (bt_hf_info->watch_id > 0) {
2273                 g_source_remove(bt_hf_info->watch_id);
2274                 bt_hf_info->watch_id = 0;
2275         }
2276 }
2277
2278 static gboolean __bt_hf_channel_write(GIOChannel *io, gchar *data,
2279                                         gsize count)
2280 {
2281         gsize written = 0;
2282         GIOStatus status;
2283
2284         while (count > 0) {
2285                 status = g_io_channel_write_chars(io, data, count, &written,
2286                                                 NULL);
2287                 if (status != G_IO_STATUS_NORMAL)
2288                         return FALSE;
2289
2290                 data += written;
2291                 count -= written;
2292         }
2293         return TRUE;
2294 }
2295
2296 static gboolean __bt_hf_send_only_without_queue(bt_hf_agent_info_t *bt_hf_info,
2297                                                 gchar *data, gsize count)
2298 {
2299         GIOChannel *io_chan = bt_hf_info->io_chan;
2300         if (!__bt_hf_channel_write(io_chan, data, count))
2301                 return FALSE;
2302
2303         g_io_channel_flush(io_chan, NULL);
2304
2305         if (count > 2 && data[2] == 'D') { /* ATDXXXXX */
2306                 INFO("[HF AT CMD] Send only without queue <<<<<: Buffer = %s, Length = %zd ",
2307                                         "ATDXXXXXXX", count);
2308                 snprintf(prev_cmd, BT_HF_CMD_BUF_SIZE, "%s", data);
2309         } else {
2310                 __bt_hf_agent_print_at_buffer("[HF AT CMD] Send only without queue <<<<<:",
2311                                         data);
2312         }
2313
2314         send_flag++;
2315         /* DBG("Ref %d(after) on Send only buffer size =[%d] - Send <<<<<| %s",
2316          * send_flag, count, data); */
2317         return TRUE;
2318
2319 }
2320
2321 static gboolean __bt_hf_send_only(bt_hf_agent_info_t *bt_hf_info, gchar *data,
2322                                                                 gsize count)
2323 {
2324         gboolean pending = FALSE;
2325         GIOChannel *io_chan = bt_hf_info->io_chan;
2326
2327         if (send_flag)
2328                 pending = TRUE;
2329
2330         __bt_hf_agent_add_queue(bt_hf_info->context, data, count, pending);
2331
2332         if (pending)
2333                 return TRUE;
2334
2335         if (!__bt_hf_channel_write(io_chan, data, count))
2336                 return FALSE;
2337
2338         g_io_channel_flush(io_chan, NULL);
2339
2340         if (count > 2 && data[2] == 'D') /* ATDXXXXX */
2341                 INFO("[HF AT CMD] Send only <<<<<: Buffer = %s, Length = %zd ",
2342                                         "ATDXXXXXXX", count);
2343         else
2344                 __bt_hf_agent_print_at_buffer("[HF AT CMD] Send only <<<<<:",
2345                                         data);
2346
2347         send_flag++;
2348         DBG("Ref %d(after) on Send only buffer size =[%zd] - Send <<<<<",
2349                                                 send_flag, count);
2350         return TRUE;
2351 }
2352
2353 static gboolean __bt_hf_send_and_read(bt_hf_agent_info_t *bt_hf_info,
2354                 gchar *data, gchar *response, gsize count)
2355 {
2356         GIOChannel *io_chan = bt_hf_info->io_chan;
2357         gsize rd_size = 0;
2358         gboolean recvd_ok = FALSE;
2359         gboolean recvd_error = FALSE;
2360         gboolean recvd_sec_error = FALSE;
2361         gchar *resp_buf = response;
2362         gsize toread = BT_HF_DATA_BUF_SIZE - 1;
2363         int i = 0;
2364         int fd;
2365         int err;
2366         struct pollfd p;
2367         GDBusConnection *conn;
2368
2369         /* Should not send cmds if DUT send a command and wait the response */
2370         if (prev_cmd[0] != 0) {
2371                 INFO("DUT is waiting a respond for previous TX cmd. Skip sending.");
2372                 return FALSE;
2373         }
2374
2375         memset(resp_buf, 0, BT_HF_DATA_BUF_SIZE);
2376
2377         if (!__bt_hf_channel_write(io_chan, data, count))
2378                 return FALSE;
2379
2380         g_io_channel_flush(io_chan, NULL);
2381
2382         __bt_hf_agent_print_at_buffer("[HF AT CMD] Send <<<<<:", data);
2383
2384         fd = g_io_channel_unix_get_fd(io_chan);
2385         p.fd = fd;
2386         p.events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
2387
2388         /* Maximun 8 seconds of poll or 8 minus no of cmd received */
2389         for (i = 1; i <= MAX_WAITING_DELAY; i++) {
2390                 DBG("Loop Counter = %d", i);
2391                 p.revents = 0;
2392                 err = poll(&p, 1, 1000);
2393                 if (err < 0) {
2394                         ERR("Loop Counter = %d, >>>> Poll error happen", i);
2395                         return FALSE;
2396                 } else if (err == 0) {
2397                         INFO("Loop Counter = %d, >>>> Poll Timeout", i);
2398                 }
2399
2400                 if (p.revents & (POLLERR | POLLHUP | POLLNVAL)) {
2401                         ERR("Loop Counter = %d, >> Poll ERR/HUP/INV (%d)",
2402                                                                 i, p.revents);
2403
2404                         conn = __bt_hf_get_gdbus_connection();
2405                         if (!conn) {
2406                                 ERR("Unable to get connection");
2407                                 return FALSE;
2408                         }
2409
2410                         __bt_hf_agent_emit_signal(conn,
2411                                 BT_HF_AGENT_OBJECT_PATH,
2412                                 BT_HF_SERVICE_INTERFACE,
2413                                 "Disconnected",
2414                                 g_variant_new("(s)",
2415                                                 bt_hf_info->remote_addr));
2416
2417                         bt_hf_info->state = BT_HF_STATE_DISCONNECTED;
2418                         return FALSE;
2419                 }
2420
2421                 if (p.revents & POLLIN) {
2422                         rd_size = read(fd, resp_buf, toread);
2423                         resp_buf[rd_size] = '\0';
2424                         DBG_SECURE("size = %zd, Buffer=[%s]", rd_size, resp_buf);
2425                         recvd_ok = NULL != strstr(resp_buf, BT_HF_OK_RESPONSE);
2426                         recvd_error = NULL != strstr(resp_buf, BT_HF_ERROR_RESPONSE);
2427                         recvd_sec_error = NULL != strstr(resp_buf, BT_HF_SEC_ERROR_RESPONSE);
2428
2429                         resp_buf += rd_size;
2430                         toread -= rd_size;
2431
2432                         if (recvd_ok || recvd_error || recvd_sec_error) {
2433                                 DBG("Break Loop Counter = %d", i);
2434                                 break;
2435                         }
2436                 }
2437         }
2438
2439         /* Once service level connection is established we need to handle
2440          * all the intermediate AT commands */
2441         if (bt_hf_info->state == BT_HF_STATE_CONNECTED)
2442                 hf_handle_rx_at_buff(bt_hf_info, response);
2443         return TRUE;
2444 }
2445
2446 static GSList *__bt_hf_parse_indicator_names(gchar *names, GSList *indices)
2447 {
2448         struct indicator *ind;
2449         gchar *cur = names - 1;
2450         GSList *list = indices;
2451         gchar *next;
2452
2453         DBG("Indicator buffer = %s", names);
2454         __bt_hf_agent_print_at_buffer("Indicator names :", names);
2455         while (cur != NULL) {
2456                 cur += 2;
2457                 next = strstr(cur, ",(");
2458                 ind = g_new0(struct indicator, 1);
2459                 g_strlcpy(ind->descr, cur, BT_HF_INDICATOR_DESCR_SIZE);
2460                 ind->descr[(intptr_t) next - (intptr_t) cur] = '\0';
2461                 list = g_slist_append(list, (gpointer) ind);
2462                 cur = strstr(next + 1, ",(");
2463         }
2464         return list;
2465 }
2466
2467 static GSList *__bt_hf_parse_indicator_values(gchar *values, GSList *indices)
2468 {
2469         gint val;
2470         struct indicator *ind;
2471         GSList *runner = indices;
2472
2473         gchar *cur = values - 1;
2474         DBG("Indicator string = %s", values);
2475         __bt_hf_agent_print_at_buffer("Indicator values :", values);
2476         while (cur != NULL) {
2477                 cur += 1;
2478                 sscanf(cur, "%1d", &val);
2479                 cur = strchr(cur, ',');
2480                 ind = g_slist_nth_data(runner, 0);
2481                 if (ind != NULL)
2482                         ind->value = val;
2483                 runner = g_slist_next(runner);
2484                 if (runner == NULL)
2485                         break;
2486         }
2487         return indices;
2488 }
2489
2490 static guint __bt_hf_get_hold_mpty_features(gchar *features)
2491 {
2492         guint result = 0;
2493
2494         if (strstr(features, "0"))
2495                 result |= BT_HF_CHLD_0;
2496
2497         if (strstr(features, "1"))
2498                 result |= BT_HF_CHLD_1;
2499
2500         if (strstr(features, "1x"))
2501                 result |= BT_HF_CHLD_1x;
2502
2503         if (strstr(features, "2"))
2504                 result |= BT_HF_CHLD_2;
2505
2506         if (strstr(features, "2x"))
2507                 result |= BT_HF_CHLD_2x;
2508
2509         if (strstr(features, "3"))
2510                 result |= BT_HF_CHLD_3;
2511
2512         if (strstr(features, "4"))
2513                 result |= BT_HF_CHLD_4;
2514
2515         return result;
2516 }
2517
2518 static gboolean __bt_hf_agent_sco_disconnect_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
2519 {
2520         bt_hf_agent_info_t *bt_hf_info = user_data;
2521         GDBusConnection *conn;
2522
2523         DBG("");
2524         if (cond & G_IO_NVAL)
2525                 return FALSE;
2526
2527         if (cond & (G_IO_HUP | G_IO_ERR)) {
2528                 g_io_channel_shutdown(chan, TRUE, NULL);
2529                 close(bt_hf_info->cli_sco_fd);
2530                 bt_hf_info->cli_sco_fd = -1;
2531                 g_io_channel_unref(chan);
2532                 DBG("Emit AudioDisconnected Signal");
2533
2534                 sco_audio_connected = BT_HF_AUDIO_DISCONNECTED;
2535
2536                 conn = __bt_hf_get_gdbus_connection();
2537                 if (!conn) {
2538                         ERR("Unable to get connection");
2539                         return FALSE;
2540                 }
2541                 __bt_hf_agent_emit_signal(conn,
2542                                 BT_HF_AGENT_OBJECT_PATH,
2543                                 BT_HF_SERVICE_INTERFACE,
2544                                 "AudioDisconnected", NULL);
2545
2546                 return FALSE;
2547         }
2548
2549         return TRUE;
2550 }
2551
2552 static gboolean __bt_hf_agent_sco_accept_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
2553 {
2554         bt_hf_agent_info_t *bt_hf_info = user_data;
2555         int sco_skt;
2556         int cli_sco_sock;
2557         GIOChannel *sco_io;
2558         GDBusConnection *conn;
2559
2560         INFO("Incoming SCO....");
2561
2562         if (cond & G_IO_NVAL)
2563                 return FALSE;
2564
2565         sco_skt = g_io_channel_unix_get_fd(chan);
2566
2567         if (cond & (G_IO_HUP | G_IO_ERR)) {
2568                 close(sco_skt);
2569                 return FALSE;
2570         }
2571
2572         cli_sco_sock = accept(sco_skt, NULL, NULL);
2573         if (cli_sco_sock < 0)
2574                 return FALSE;
2575
2576         bt_hf_info->cli_sco_fd = cli_sco_sock;
2577
2578         sco_io = g_io_channel_unix_new(cli_sco_sock);
2579         g_io_channel_set_close_on_unref(sco_io, TRUE);
2580         g_io_channel_set_encoding(sco_io, NULL, NULL);
2581         g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
2582         g_io_channel_set_buffered(sco_io, FALSE);
2583
2584         g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
2585                                         __bt_hf_agent_sco_disconnect_cb, bt_hf_info);
2586
2587         if (bt_hf_info->state != BT_HF_STATE_CONNECTED)
2588                 ERR("HFP is not yet connected");
2589
2590         /* S-Voice app requires the AudioConnected signal earlier */
2591         DBG("Emit AudioConnected Signal");
2592
2593         sco_audio_connected = BT_HF_AUDIO_CONNECTED;
2594
2595         conn = __bt_hf_get_gdbus_connection();
2596         if (!conn) {
2597                 ERR("Unable to get connection");
2598                 return FALSE;
2599         }
2600
2601         __bt_hf_agent_emit_signal(conn,
2602                         BT_HF_AGENT_OBJECT_PATH,
2603                         BT_HF_SERVICE_INTERFACE,
2604                         "AudioConnected", NULL);
2605
2606         /* In the case of incoming call, the call app is already launched,
2607          * hence AudioConnected signal is enough to update the call status.
2608          * In the case of outgoing call we need to lauch the callapp.
2609          */
2610
2611         __bt_hf_agent_launch_call_app();
2612
2613         return TRUE;
2614 }
2615
2616 static void __bt_convert_addr_string_to_type_rev(unsigned char *addr,
2617                                         const char *address)
2618 {
2619         int i;
2620         char *ptr = NULL;
2621
2622         ret_if(address == NULL);
2623         ret_if(addr == NULL);
2624
2625         for (i = 0; i < BT_ADDRESS_LENGTH_MAX; i++) {
2626                 addr[5 - i] = strtol(address, &ptr, 16);
2627                 if (ptr[0] != '\0') {
2628                         if (ptr[0] != ':')
2629                                 return;
2630
2631                         address = ptr + 1;
2632                 }
2633         }
2634 }
2635
2636 static gboolean __bt_hf_agent_sco_accept(bt_hf_agent_info_t *bt_hf_info)
2637 {
2638         struct sockaddr_sco addr;
2639         GIOChannel *sco_io;
2640         bdaddr_t bd_addr = {{0},};
2641         int sco_skt;
2642
2643         /* Create socket */
2644         sco_skt = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
2645         if (sco_skt < 0) {
2646                 ERR("Can't create socket:\n");
2647                 return FALSE;
2648         }
2649
2650         /* Bind to local address */
2651         memset(&addr, 0, sizeof(addr));
2652         addr.sco_family = AF_BLUETOOTH;
2653
2654         DBG("Bind to address %s", bt_hf_info->remote_addr);
2655
2656         __bt_convert_addr_string_to_type_rev(bd_addr.b, bt_hf_info->remote_addr);
2657         memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
2658
2659         if (bind(sco_skt, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2660                 ERR("Can't bind socket:\n");
2661                 goto error;
2662         }
2663
2664         if (listen(sco_skt, 1)) {
2665                 ERR("Can not listen on the socket:\n");
2666                 goto error;
2667         }
2668
2669         sco_io = g_io_channel_unix_new(sco_skt);
2670         g_io_channel_set_close_on_unref(sco_io, TRUE);
2671         g_io_channel_set_encoding(sco_io, NULL, NULL);
2672         g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
2673         g_io_channel_set_buffered(sco_io, FALSE);
2674
2675         bt_hf_info->sco_fd = sco_skt;
2676         bt_hf_info->sco_io_chan = sco_io;
2677
2678         bt_hf_info->sco_watch_id = g_io_add_watch(sco_io,
2679                         G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, __bt_hf_agent_sco_accept_cb, bt_hf_info);
2680
2681         g_io_channel_unref(sco_io);
2682
2683         return TRUE;
2684
2685 error:
2686         close(sco_skt);
2687         return FALSE;
2688 }
2689
2690 static gboolean __bt_get_supported_indicators(bt_hf_agent_info_t *bt_hf_info)
2691 {
2692         gchar buf[BT_HF_DATA_BUF_SIZE] = {0,};
2693         gboolean ret;
2694
2695         ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_INDICATORS_SUPP, buf,
2696                                 sizeof(BT_HF_INDICATORS_SUPP) - 1);
2697         if (!ret || !strstr(buf, "+CIND:"))
2698                 return FALSE;
2699
2700         bt_hf_info->indies = __bt_hf_parse_indicator_names(strchr(buf, '('), NULL);
2701
2702         return TRUE;
2703 }
2704
2705 static gboolean __bt_get_bia_cmd(bt_hf_agent_info_t *bt_hf_info, gchar *cmd, gsize cmd_size)
2706 {
2707         GSList *l;
2708         gsize ret;
2709
2710         if (bt_hf_info == NULL || cmd == NULL) {
2711                 ERR("Invalid parameter");
2712                 return FALSE;
2713         }
2714
2715         ret = g_strlcpy(cmd, BT_HF_INDICATORS_ACTIVATION, cmd_size);
2716
2717         for (l = bt_hf_info->indies; l != NULL; l = g_slist_next(l)) {
2718                 ret = g_strlcat(cmd, "0,", cmd_size);
2719                 if (ret >= cmd_size) {
2720                         ERR("Too many indices");
2721                         return FALSE;
2722                 }
2723
2724         }
2725
2726         cmd[ret - 1] = '\0';
2727         DBG("BIA Str : %s", cmd);
2728
2729         ret = g_strlcat(cmd, "\r", cmd_size);
2730         if (ret >= cmd_size) {
2731                 ERR("Too many indices");
2732                 return FALSE;
2733         }
2734
2735         return TRUE;
2736 }
2737
2738 static gboolean __bt_get_current_indicators(bt_hf_agent_info_t *bt_hf_info)
2739 {
2740         gchar buf[BT_HF_DATA_BUF_SIZE] = {0,};
2741         gboolean ret;
2742         gchar *str;
2743         GSList *l;
2744         int index =  1;
2745
2746         ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_INDICATORS_VAL, buf,
2747                 sizeof(BT_HF_INDICATORS_VAL) - 1);
2748         if (!ret || !strstr(buf, "+CIND:"))
2749                 return FALSE;
2750
2751         /* if buf has other command prefix, skip it */
2752         str = strstr(buf, "+CIND");
2753         if (str == NULL)
2754                 return FALSE;
2755
2756         bt_hf_info->indies = __bt_hf_parse_indicator_values(str + 6, bt_hf_info->indies);
2757
2758         /* Parse the updated value */
2759         for (l = bt_hf_info->indies; l != NULL; l = g_slist_next(l), ++index) {
2760                 struct indicator *ind = l->data;
2761                 if (!ind) {
2762                         DBG("Index is NULL");
2763                         break;
2764                 }
2765
2766                 if (0 == g_strcmp0(ind->descr, "\"call\"")) {
2767                         DBG("CIND Match found index = %d, %s, value = %d",
2768                                                 index, ind->descr, ind->value);
2769                         bt_hf_info->ciev_call_status = ind->value;
2770                         if (ind->value > 0) {
2771                                 bt_hf_info->is_dialing = FALSE;
2772                                 bt_hf_info->call_active = TRUE;
2773                         }
2774                 } else if (0 == g_strcmp0(ind->descr, "\"callsetup\"")) {
2775                         DBG("CIND Match found index = %d, %s, value = %d",
2776                                                 index, ind->descr, ind->value);
2777                         bt_hf_info->ciev_call_setup_status = ind->value;
2778                         if (!bt_hf_info->is_dialing && ind->value > 0)
2779                                 bt_hf_info->is_dialing = TRUE;
2780                 }
2781         }
2782
2783         return TRUE;
2784 }
2785
2786 static gboolean __bt_establish_service_level_conn(bt_hf_agent_info_t *bt_hf_info)
2787 {
2788         gchar buf[BT_HF_DATA_BUF_SIZE];
2789         gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
2790         gboolean ret;
2791         char *buf_ptr;
2792         guint feature = BT_HF_FEATURE_EC_ANDOR_NR |
2793                         BT_HF_FEATURE_CALL_WAITING_AND_3WAY |
2794                         BT_HF_FEATURE_CLI_PRESENTATION |
2795                         BT_HF_FEATURE_REMOTE_VOLUME_CONTROL |
2796                         BT_HF_FEATURE_ENHANCED_CALL_STATUS;
2797
2798         if (TIZEN_PROFILE_WEARABLE)
2799                 feature = feature | BT_HF_FEATURE_CODEC_NEGOTIATION;
2800
2801         snprintf(cmd_buf, sizeof(cmd_buf), BT_HF_FEATURES, feature);
2802         ret = __bt_hf_send_and_read(bt_hf_info, cmd_buf, buf,
2803                                 strlen(cmd_buf));
2804         if (!ret)
2805                 return FALSE;
2806
2807         buf_ptr = strstr(buf, "\r\n+BRSF:");
2808         if (buf_ptr == NULL)
2809                 return FALSE;
2810
2811         if (!ret || sscanf(buf_ptr, "\r\n+BRSF:%5d", &bt_hf_info->ag_features) != 1)
2812                 return FALSE;
2813         INFO("Gateway supported features are 0x%X", bt_hf_info->ag_features);
2814
2815         if (TIZEN_PROFILE_WEARABLE) {
2816                 if (bt_hf_info->ag_features & BT_AG_FEATURE_CODEC_NEGOTIATION) {
2817                         ret = _hf_agent_codec_setup(bt_hf_info->remote_addr, BT_HF_CODEC_ID_MSBC);
2818                         if (ret != BT_HF_AGENT_ERROR_NONE)
2819                                 ERR("Unable to set the default WBC codec");
2820
2821                         ret = __bt_hf_send_available_codec(bt_hf_info, 0);
2822                         if (!ret)
2823                                 return FALSE;
2824                 }
2825         } else {
2826                 /* Default codec is NB */
2827                 ret = _hf_agent_codec_setup(bt_hf_info->remote_addr, BT_HF_CODEC_ID_CVSD);
2828                 if (ret != BT_HF_AGENT_ERROR_NONE)
2829                         ERR("Unable to set the default NBC codec");
2830         }
2831
2832         ret = __bt_get_supported_indicators(bt_hf_info);
2833         if (!ret)
2834                 return FALSE;
2835
2836
2837         ret = __bt_get_current_indicators(bt_hf_info);
2838         if (!ret)
2839                 return FALSE;
2840
2841         ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_INDICATORS_ENABLE, buf,
2842                                         sizeof(BT_HF_INDICATORS_ENABLE) - 1);
2843         if (!ret || !strstr(buf, "OK"))
2844                 return FALSE;
2845
2846         if ((bt_hf_info->ag_features & BT_AG_FEATURE_3WAY) != 0) {
2847                 ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_HOLD_MPTY_SUPP,
2848                                         buf, sizeof(BT_HF_HOLD_MPTY_SUPP) - 1);
2849                 if (!ret || !strstr(buf, "+CHLD:")) {
2850                         ERR("Unable to get the CHLD Supported info");
2851                         return FALSE;
2852                 }
2853                 bt_hf_info->hold_multiparty_features = __bt_hf_get_hold_mpty_features(
2854                                                         strchr(buf, '('));
2855         } else
2856                 bt_hf_info->hold_multiparty_features = 0;
2857
2858         if (bt_hf_info->ag_features & BT_AG_FEATURE_INBAND_RINGTONE)
2859                 bt_hf_info->inband_ringtone_support = TRUE;
2860         else
2861                 bt_hf_info->inband_ringtone_support = FALSE;
2862
2863         INFO("Service layer connection successfully established...!");
2864
2865         bt_hf_info->slc = TRUE;
2866         send_flag = FALSE;
2867         g_id = 0;
2868         memset(global_buff, 0, sizeof(global_buff));
2869         return TRUE;
2870 }
2871
2872 static void __bt_establish_initialization(bt_hf_agent_info_t *bt_hf_info)
2873 {
2874         gchar buf[BT_HF_DATA_BUF_SIZE];
2875         gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
2876         gboolean ret;
2877
2878         __bt_hf_send_and_read(bt_hf_info, BT_HF_CALLER_IDENT_ENABLE, buf,
2879                         sizeof(BT_HF_CALLER_IDENT_ENABLE) - 1);
2880         __bt_hf_send_and_read(bt_hf_info, BT_HF_CARRIER_FORMAT, buf,
2881                         sizeof(BT_HF_CARRIER_FORMAT) - 1);
2882         __bt_hf_send_and_read(bt_hf_info, BT_HF_CALLWAIT_NOTI_ENABLE, buf,
2883                         sizeof(BT_HF_CALLWAIT_NOTI_ENABLE) - 1);
2884
2885         if ((bt_hf_info->ag_features & BT_AG_FEATURE_NREC) != 0)
2886                 __bt_hf_send_and_read(bt_hf_info, BT_HF_NREC, buf,
2887                                                 sizeof(BT_HF_NREC) - 1);
2888
2889         if ((bt_hf_info->ag_features & BT_AG_FEATURE_EXTENDED_RES_CODE) != 0)
2890                 __bt_hf_send_and_read(bt_hf_info, BT_HF_EXTENDED_RESULT_CODE,
2891                         buf, sizeof(BT_HF_EXTENDED_RESULT_CODE) - 1);
2892
2893         if (__bt_get_bia_cmd(bt_hf_info, cmd_buf, sizeof(cmd_buf)) == TRUE)
2894                 __bt_hf_send_and_read(bt_hf_info, cmd_buf, buf, strlen(cmd_buf));
2895         else
2896                 ERR("__bt_get_bia_cmd is failed");
2897
2898         ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_XSAT, buf,
2899                                                 sizeof(BT_HF_XSAT) - 1);
2900         if (ret)
2901                 DBG("sent BT_HF_XSAT");
2902         else
2903                 ERR("BT_HF_XSAT sending failed");
2904
2905         if (TIZEN_PROFILE_WEARABLE) {
2906                 /* send Bluetooth Samsung Support Feature cmd */
2907                 ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_BSSF, buf,
2908                                                         sizeof(BT_HF_BSSF) - 1);
2909
2910                 /* If we got a 'OK' reply, peer AG is samsung device.
2911                  * Otherwise, non-samsung device */
2912                 if (ret && strstr(buf, "OK"))
2913                         bt_hf_info->is_companion_dev = TRUE;
2914                 else
2915                         bt_hf_info->is_companion_dev = FALSE;
2916
2917                 if (ret)
2918                         INFO("SLC completed with [%s] device",
2919                                 bt_hf_info->is_companion_dev ? "SS Companion" : "Other");
2920                 else
2921                         ERR("BT_HF_BSSF sending failed");
2922         }
2923 }
2924
2925 static void __bt_hf_agent_sigterm_handler(int signo)
2926 {
2927         GDBusConnection *conn;
2928         int i;
2929
2930         ERR_C("***** Signal handler came with signal %d *****", signo);
2931
2932         conn = __bt_hf_get_gdbus_connection();
2933         if (!conn) {
2934                 ERR("Unable to get G-DBus connection");
2935                 goto done;
2936         }
2937         INFO("Getting gdbus connection done");
2938
2939         __bt_hf_agent_emit_signal(conn,
2940                         BT_HF_AGENT_OBJECT_PATH,
2941                         BT_HF_SERVICE_INTERFACE,
2942                         "CallIdle", NULL);
2943         INFO("CallEnded Signal done");
2944
2945         g_dbus_connection_flush(conn, NULL, NULL, NULL);
2946         INFO("Flush g_dbus_connection");
2947
2948 done:
2949         if (gmain_loop) {
2950                 g_main_loop_quit(gmain_loop);
2951                 INFO("Exiting");
2952                 gmain_loop = NULL;
2953         } else {
2954                 INFO_C("Terminating HF agent");
2955                 exit(0);
2956         }
2957
2958         if (signo == SIGTERM)
2959                 return;
2960
2961         for (i = 0; i < BT_HF_SIG_NUM; i++)
2962                 sigaction(bt_hf_sig_to_handle[i], &(bt_hf_sigoldact[i]), NULL);
2963
2964         raise(signo);
2965 }
2966
2967 static void __bt_convert_addr_type_to_rev_string(char *address,
2968                                 unsigned char *addr)
2969 {
2970         ret_if(address == NULL);
2971         ret_if(addr == NULL);
2972
2973         g_snprintf(address, BT_ADDRESS_STRING_SIZE,
2974                         "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
2975                         addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
2976 }
2977
2978
2979 static gboolean __bt_hf_agent_release_after(gpointer user_data)
2980 {
2981         if (__bt_hf_agent_release() == FALSE)
2982                 ERR("Unable to release hf connection");
2983
2984         return FALSE;
2985 }
2986
2987 static gboolean __bt_agent_request_service_level_conn(gpointer data)
2988 {
2989         char *remote_addr;
2990         int bt_device_state = VCONFKEY_BT_DEVICE_NONE;
2991         GDBusConnection *conn;
2992
2993         DBG("+");
2994         memset(prev_cmd, 0, BT_HF_CMD_BUF_SIZE);
2995
2996         __bt_hf_agent_sco_accept(&bt_hf_info);
2997
2998         if (!__bt_establish_service_level_conn(&bt_hf_info)) {
2999                 ERR("Service Level Connection is fail");
3000
3001                 conn = __bt_hf_get_gdbus_connection();
3002                 if (conn) {
3003                         remote_addr = bt_hf_info.remote_addr;
3004                         __bt_hf_agent_emit_signal(conn,
3005                                         BT_HF_AGENT_OBJECT_PATH,
3006                                         BT_HF_SERVICE_INTERFACE,
3007                                         "Connected",
3008                                         g_variant_new("(s)", remote_addr));
3009                 }
3010                 bt_hf_info.state = BT_HF_STATE_CONNECTED;
3011
3012                 if (vconf_get_int(VCONFKEY_BT_DEVICE, &bt_device_state) == 0) {
3013                         DBG("BT device state is : 0x%X", bt_device_state);
3014                         bt_device_state |= VCONFKEY_BT_DEVICE_AG_CONNECTED;
3015                         if (vconf_set_int(VCONFKEY_BT_DEVICE, bt_device_state) != 0)
3016                                 ERR("vconf_set_int failed");
3017                 } else {
3018                         ERR("vconf_get_int failed");
3019                 }
3020
3021                 g_idle_add(__bt_hf_agent_release_after, NULL);
3022
3023                 goto done;
3024         }
3025
3026         bt_hf_info.state = BT_HF_STATE_CONNECTED;
3027
3028         __bt_hf_agent_start_watch(&bt_hf_info);
3029
3030         remote_addr = bt_hf_info.remote_addr;
3031
3032         INFO_SECURE("Address is : %s", remote_addr);
3033         INFO_C("### Connected [HF role]");
3034
3035         if (vconf_get_int(VCONFKEY_BT_DEVICE, &bt_device_state) == 0) {
3036                 DBG("BT device state is : 0x%X", bt_device_state);
3037                 bt_device_state |= VCONFKEY_BT_DEVICE_AG_CONNECTED;
3038
3039                 if (vconf_set_int(VCONFKEY_BT_DEVICE, bt_device_state) != 0)
3040                         ERR("vconf_set_int failed");
3041         } else {
3042                 ERR("vconf_get_int failed");
3043         }
3044
3045         conn = __bt_hf_get_gdbus_connection();
3046         if (!conn) {
3047                 ERR("Unable to get connection");
3048                 return FALSE;
3049         }
3050
3051         __bt_hf_agent_emit_signal(conn,
3052                         BT_HF_AGENT_OBJECT_PATH,
3053                         BT_HF_SERVICE_INTERFACE,
3054                         "Connected",
3055                         g_variant_new("(s)", remote_addr));
3056
3057         /* Establish the initialization */
3058         __bt_establish_initialization(&bt_hf_info);
3059
3060 done:
3061         DBG("-");
3062         return FALSE;
3063 }
3064
3065 static gboolean __bt_hf_agent_connection(gint32 fd, const gchar *obj_path)
3066 {
3067         GIOFlags flags;
3068
3069         struct sockaddr_remote address;
3070         socklen_t address_len;
3071         bt_hf_info.path = g_strdup(obj_path);
3072
3073         INFO_C("**** New HFP connection ****");
3074
3075         is_hf_connected = TRUE;
3076
3077         address_len = sizeof(address);
3078         if (getpeername(fd, (struct sockaddr *) &address, &address_len) != 0)
3079                 ERR("BD_ADDR is NULL");
3080
3081         DBG("RFCOMM connection for HFP is completed. Fd = [%d]\n", fd);
3082         bt_hf_info.fd = fd;
3083         bt_hf_info.io_chan = g_io_channel_unix_new(bt_hf_info.fd);
3084         flags = g_io_channel_get_flags(bt_hf_info.io_chan);
3085
3086         flags &= ~G_IO_FLAG_NONBLOCK;
3087         flags &= G_IO_FLAG_MASK;
3088         g_io_channel_set_flags(bt_hf_info.io_chan, flags, NULL);
3089         g_io_channel_set_encoding(bt_hf_info.io_chan, NULL, NULL);
3090         g_io_channel_set_buffered(bt_hf_info.io_chan, FALSE);
3091
3092         bt_hf_info.remote_addr = g_malloc0(BT_ADDRESS_STRING_SIZE);
3093         __bt_convert_addr_type_to_rev_string(bt_hf_info.remote_addr,
3094                                                 address.remote_bdaddr.b);
3095
3096         g_idle_add(__bt_agent_request_service_level_conn, NULL);
3097
3098         return TRUE;
3099 }
3100
3101 static void __bt_hf_agent_indicator_free(gpointer mem)
3102 {
3103         g_free(mem);
3104 }
3105
3106 static gboolean __bt_hf_agent_release(void)
3107 {
3108         int bt_device_state = VCONFKEY_BT_DEVICE_NONE;
3109         GDBusConnection *conn;
3110
3111         if (clcc_timer) {
3112                 g_source_remove(clcc_timer);
3113                 clcc_timer = 0;
3114         }
3115
3116         if (bt_hf_info.state == BT_HF_STATE_DISCONNECTED) {
3117                 ERR("hf is already disconnected");
3118                 return FALSE;
3119         }
3120
3121         if (bt_hf_info.indies) {
3122                 g_slist_free_full(bt_hf_info.indies, __bt_hf_agent_indicator_free);
3123                 bt_hf_info.indies = NULL;
3124         }
3125
3126         if (bt_hf_info.io_chan) {
3127                 g_io_channel_shutdown(bt_hf_info.io_chan, TRUE, NULL);
3128                 g_io_channel_unref(bt_hf_info.io_chan);
3129                 bt_hf_info.io_chan = NULL;
3130         }
3131
3132         if (bt_hf_info.sco_watch_id > 0) {
3133                 g_source_remove(bt_hf_info.sco_watch_id);
3134                 bt_hf_info.sco_watch_id = 0;
3135         }
3136
3137         bt_hf_info.state = BT_HF_STATE_DISCONNECTED;
3138
3139         __bt_hf_agent_release_queue();
3140
3141         if (vconf_get_int(VCONFKEY_BT_DEVICE, &bt_device_state) == 0) {
3142                 DBG("BT device state is : 0x%X", bt_device_state);
3143                 bt_device_state ^= VCONFKEY_BT_DEVICE_AG_CONNECTED;
3144
3145                 if (vconf_set_int(VCONFKEY_BT_DEVICE, bt_device_state) != 0)
3146                         ERR("vconf_set_int failed");
3147         } else {
3148                 ERR("vconf_get_int failed");
3149         }
3150
3151         __bt_hf_agent_stop_watch(&bt_hf_info);
3152         conn = __bt_hf_get_gdbus_connection();
3153         if (!conn) {
3154                 ERR("Unable to get connection");
3155                 return FALSE;
3156         }
3157
3158         __bt_hf_agent_emit_signal(conn,
3159                         BT_HF_AGENT_OBJECT_PATH,
3160                         BT_HF_SERVICE_INTERFACE,
3161                         "Disconnected",
3162                         g_variant_new("(s)", bt_hf_info.remote_addr));
3163
3164         g_free(bt_hf_info.path);
3165         bt_hf_info.path = NULL;
3166
3167         g_free(bt_hf_info.remote_addr);
3168         bt_hf_info.remote_addr = NULL;
3169
3170         is_hf_connected = FALSE;
3171
3172         return TRUE;
3173 }
3174
3175 static gboolean __bt_hf_agent_connection_release(void)
3176 {
3177         return __bt_hf_agent_release();
3178 }
3179
3180 static int __bt_hf_register_profile(const char *uuid, uint16_t version,
3181                  const char *name, const char *object, uint16_t features)
3182 {
3183         DBG("+");
3184         GDBusProxy *proxy;
3185         GVariant *ret;
3186         GError *error = NULL;
3187         GVariantBuilder *builder;
3188         gchar *path = NULL;
3189
3190         proxy = __bt_hf_gdbus_get_profile_proxy();
3191
3192         if (proxy == NULL)
3193                 return BT_HF_AGENT_ERROR_INTERNAL;
3194
3195         path = g_strdup(BT_HF_BLUEZ_OBJECT_PATH);
3196
3197         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3198
3199         g_variant_builder_add(builder, "{sv}",
3200                         "Name", g_variant_new("s",
3201                         name));
3202         g_variant_builder_add(builder, "{sv}",
3203                         "Version", g_variant_new("q", version));
3204
3205         g_variant_builder_add(builder, "{sv}",
3206                         "features", g_variant_new("q", features));
3207
3208         ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile",
3209                                 g_variant_new("(osa{sv})", path,
3210                                         HFP_HF_UUID, builder),
3211                                 G_DBUS_CALL_FLAGS_NONE, -1,
3212                                 NULL, &error);
3213
3214         g_variant_builder_unref(builder);
3215
3216         if (ret == NULL) {
3217                 /* dBUS-RPC is failed */
3218                 ERR("dBUS-RPC is failed");
3219                 if (error != NULL) {
3220                         /* dBUS gives error cause */
3221                         ERR("D-Bus API failure: errCode[%x], message[%s]",
3222                                 error->code, error->message);
3223                         g_clear_error(&error);
3224                 }
3225                 g_free(path);
3226                 return BT_HF_AGENT_ERROR_INTERNAL;
3227         }
3228         g_variant_unref(ret);
3229         g_free(path);
3230
3231         DBG("-");
3232         return BT_HF_AGENT_ERROR_NONE;
3233 }
3234
3235 static void __bt_hf_agent_register(void)
3236 {
3237         DBG("+");
3238         int ret;
3239         char *name;
3240         uint16_t version = hf_ver;
3241         uint16_t features = bt_hf_info.feature;
3242
3243         gchar *path = g_strdup(BT_HF_BLUEZ_OBJECT_PATH);
3244         name = g_strdup("Hands-Free");
3245
3246         ret = __bt_hf_register_profile(HFP_HF_UUID, version, name, path,
3247                                                                 features);
3248         if (ret)
3249                 ERR("Error in register");
3250
3251         g_free(path);
3252         g_free(name);
3253
3254         DBG("-");
3255         return;
3256 }
3257
3258 static void __bt_hf_agent_unregister(void)
3259 {
3260         DBG("+");
3261
3262         gchar *path = g_strdup(BT_HF_BLUEZ_OBJECT_PATH);
3263
3264         if (g_obj_path) {
3265                 __bt_hf_agent_gdbus_method_send(BLUEZ_SERVICE_NAME,
3266                                                 g_variant_new("(o)", path),
3267                                                 BLUEZ_HF_INTERFACE_NAME,
3268                                                 "UnregisterAgent");
3269                 g_free(g_obj_path);
3270                 g_obj_path = NULL;
3271         }
3272
3273         g_free(path);
3274
3275         DBG("-");
3276         return;
3277 }
3278
3279 static void __bt_hf_agent_filter_cb(GDBusConnection *connection,
3280                                                  const gchar *sender_name,
3281                                                  const gchar *object_path,
3282                                                  const gchar *interface_name,
3283                                                  const gchar *signal_name,
3284                                                  GVariant *parameters,
3285                                                  gpointer user_data)
3286 {
3287         DBG("+");
3288         char *path = NULL;
3289
3290         GVariant *optional_param;
3291
3292         if (strcasecmp(signal_name, "InterfacesAdded") == 0) {
3293
3294                 g_variant_get(parameters, "(&o@a{sa{sv}})",
3295                                 &path, &optional_param);
3296                 if (!path) {
3297                         ERR("Invalid adapter path");
3298                         return;
3299                 }
3300
3301                 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
3302                         g_obj_path = g_strdup(path);
3303                         INFO("Adapter Path = [%s]", path);
3304                         __bt_hf_agent_register();
3305                 }
3306         } else if (strcasecmp(signal_name, "InterfacesRemoved") == 0) {
3307                 g_variant_get(parameters, "(&o@as)", &path, &optional_param);
3308                 if (!path)
3309                         __bt_hf_agent_unregister();
3310         }
3311         DBG("-");
3312 }
3313
3314 static int __bt_hf_agent_get_adapter_path(GDBusConnection *conn, char *path)
3315 {
3316         GError *err = NULL;
3317         GDBusProxy *manager_proxy = NULL;
3318         GVariant *result = NULL;
3319         char *adapter_path = NULL;
3320
3321         if (conn == NULL)
3322                 return BT_HF_AGENT_ERROR_INTERNAL;
3323
3324         manager_proxy =  g_dbus_proxy_new_sync(conn,
3325                         G_DBUS_PROXY_FLAGS_NONE, NULL,
3326                         BLUEZ_SERVICE_NAME,
3327                         "/",
3328                         BT_MANAGER_INTERFACE,
3329                         NULL, &err);
3330
3331         if (!manager_proxy) {
3332                 ERR("Unable to create proxy: %s", err->message);
3333                 goto fail;
3334         }
3335
3336         result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
3337                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3338         if (!result) {
3339                 if (err != NULL)
3340                         ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
3341                 else
3342                         ERR("Fail to get DefaultAdapter");
3343
3344                 goto fail;
3345         }
3346
3347         if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
3348                 ERR("Incorrect result\n");
3349                 goto fail;
3350         }
3351
3352         g_variant_get(result, "(&o)", &adapter_path);
3353
3354         if (adapter_path == NULL ||
3355                 strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) {
3356                 ERR("Adapter path is inproper\n");
3357                 goto fail;
3358         }
3359
3360         if (path)
3361                 g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX);
3362
3363         if (g_obj_path == NULL) {
3364                 g_obj_path = g_strdup(adapter_path);
3365                 INFO("Update g_obj_path [%s]", adapter_path);
3366         }
3367
3368         g_variant_unref(result);
3369         g_object_unref(manager_proxy);
3370
3371         return 0;
3372
3373 fail:
3374         g_clear_error(&err);
3375
3376         if (result)
3377                 g_variant_unref(result);
3378
3379         if (manager_proxy)
3380                 g_object_unref(manager_proxy);
3381
3382         return BT_HF_AGENT_ERROR_INTERNAL;
3383
3384 }
3385
3386 static void __bt_hf_agent_dbus_init(void)
3387 {
3388         GDBusConnection *conn;
3389
3390         DBG("+");
3391
3392         conn = __bt_hf_get_gdbus_connection();
3393         if (conn == NULL) {
3394                 ERR("Error in creating the gdbus connection\n");
3395                 return;
3396         }
3397         if (!__bt_hf_register_profile_methods()) {
3398                 ERR("Error in register_profile_methods\n");
3399                 return;
3400         }
3401
3402         if (!__bt_hf_agent_get_adapter_path(gdbus_conn , NULL)) {
3403                 __bt_hf_agent_register();
3404         }
3405
3406         interface_added_sig_id = g_dbus_connection_signal_subscribe(conn,
3407                                 NULL, BT_MANAGER_INTERFACE, BT_INTERFACES_ADDED, NULL, NULL, 0,
3408                                 __bt_hf_agent_filter_cb, NULL, NULL);
3409
3410         interface_removed_sig_id = g_dbus_connection_signal_subscribe(conn,
3411                                 NULL, BT_MANAGER_INTERFACE, BT_INTERFACES_REMOVED, NULL, NULL, 0,
3412                                 __bt_hf_agent_filter_cb, NULL, NULL);
3413
3414         DBG("-");
3415 }
3416
3417 static void __bt_hf_agent_dbus_deinit(void)
3418 {
3419         if (profile_gproxy) {
3420                 g_object_unref(profile_gproxy);
3421                 profile_gproxy = NULL;
3422         }
3423
3424         if (gdbus_conn) {
3425                 if (interface_added_sig_id > 0)
3426                         g_dbus_connection_signal_unsubscribe(gdbus_conn,
3427                                                 interface_added_sig_id);
3428
3429                 if (interface_removed_sig_id > 0)
3430                         g_dbus_connection_signal_unsubscribe(gdbus_conn,
3431                                                 interface_removed_sig_id);
3432
3433                 interface_added_sig_id = 0;
3434                 interface_removed_sig_id = 0;
3435
3436                 g_object_unref(gdbus_conn);
3437                 gdbus_conn = NULL;
3438         }
3439 }
3440
3441 static int _hf_agent_answer_call(GDBusMethodInvocation *context)
3442 {
3443         int ret;
3444
3445         DBG("+\n");
3446         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3447                 ERR("HF not Connected");
3448                 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3449         }
3450         bt_hf_info.context = context;
3451
3452         ret = __bt_hf_send_only(&bt_hf_info, BT_HF_ANSWER_CALL,
3453                                 sizeof(BT_HF_ANSWER_CALL) - 1);
3454         if (!ret)
3455                 return BT_HF_AGENT_ERROR_INTERNAL;
3456
3457         DBG("-\n");
3458         return BT_HF_AGENT_ERROR_NONE;
3459
3460 }
3461
3462 static int _hf_agent_terminate_call(GDBusMethodInvocation *context)
3463 {
3464         int ret;
3465
3466         DBG("+\n");
3467         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3468                 ERR("HF not Connected");
3469                 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3470         }
3471
3472         bt_hf_info.context = context;
3473
3474         ret = __bt_hf_send_only(&bt_hf_info, BT_HF_END_CALL,
3475                                 sizeof(BT_HF_END_CALL) - 1);
3476         if (!ret)
3477                 return BT_HF_AGENT_ERROR_INTERNAL;
3478
3479         DBG("-\n");
3480         return BT_HF_AGENT_ERROR_NONE;
3481 }
3482
3483 static int _hf_agent_dial_no(GDBusMethodInvocation *context, char *no)
3484 {
3485         int ret;
3486         int prev_cmd_len = 0;
3487         char buf[BT_MAX_TEL_NUM_STR + 6] = {0};
3488
3489         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3490                 ERR("HF not Connected");
3491                 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3492         }
3493
3494         bt_hf_info.context = context;
3495
3496         if (strlen(no) > 0) {
3497                 snprintf(buf, sizeof(buf),  BT_HF_DIAL_NO, no);
3498
3499                 if (strstr(prev_cmd, "ATD") && bt_hf_info.ciev_call_status == 0
3500                                                 && bt_hf_info.ciev_call_setup_status == 0) {
3501                         INFO("RAD POPUP CANCEL CASE. send ATD w/o response - KOR REQUEST");
3502                         ret = __bt_hf_send_only_without_queue(&bt_hf_info, buf, strlen(buf));
3503                         if (send_flag)
3504                                 send_flag--;
3505                 } else {
3506                         ret = __bt_hf_send_only(&bt_hf_info, buf, strlen(buf));
3507                 }
3508
3509                 /* prev_cmd is meant for only meant for ATD & AT+BLDN Error handling */
3510                 prev_cmd_len = snprintf(prev_cmd, BT_HF_CMD_BUF_SIZE, "%s", buf);
3511
3512                 if (prev_cmd_len < 0) {
3513                         ERR("Encoding error occured in snprintf");
3514                         return BT_HF_AGENT_ERROR_INTERNAL;
3515                 }
3516
3517                 if (!ret)
3518                         return BT_HF_AGENT_ERROR_INTERNAL;
3519
3520                 return BT_HF_AGENT_ERROR_NONE;
3521         }
3522
3523         /* prev_cmd is meant for only meant for ATD & AT+BLDN Error handling */
3524         snprintf(prev_cmd, BT_HF_CMD_BUF_SIZE, "%s", BT_HF_REDIAL);
3525
3526         ret = __bt_hf_send_only(&bt_hf_info, BT_HF_REDIAL,
3527                                                 sizeof(BT_HF_REDIAL) - 1);
3528         if (!ret)
3529                 return BT_HF_AGENT_ERROR_INTERNAL;
3530
3531         return BT_HF_AGENT_ERROR_NONE;
3532 }
3533
3534 static int _hf_agent_voice_recognition(GDBusMethodInvocation *context, unsigned int status)
3535 {
3536         int ret;
3537         char buf[20] = {0};
3538
3539         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3540                 ERR("HF not Connected");
3541                 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3542         }
3543
3544         snprintf(buf, sizeof(buf),  BT_HF_VOICE_RECOGNITION, status);
3545
3546         bt_hf_info.context = context;
3547
3548         ret = __bt_hf_send_only(&bt_hf_info, buf, strlen(buf));
3549         if (!ret)
3550                 return BT_HF_AGENT_ERROR_INTERNAL;
3551
3552
3553         return BT_HF_AGENT_ERROR_NONE;
3554 }
3555
3556 static int _hf_agent_set_speaker_gain(GDBusMethodInvocation *context, unsigned int gain)
3557 {
3558         int ret;
3559         char buf[20] = {0};
3560
3561         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3562                 ERR("HF not Connected");
3563                 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3564         }
3565
3566         if (gain > BT_HF_MAX_SPEAKER_GAIN)
3567                 return BT_HF_AGENT_ERROR_INVALID_PARAM;
3568
3569         snprintf(buf, sizeof(buf),  BT_HF_SPEAKER_GAIN, gain);
3570
3571         bt_hf_info.context = context;
3572
3573         ret = __bt_hf_send_only(&bt_hf_info, buf,
3574                                 strlen(buf));
3575         if (!ret)
3576                 return BT_HF_AGENT_ERROR_INTERNAL;
3577
3578         return BT_HF_AGENT_ERROR_NONE;
3579
3580 }
3581
3582 static int _hf_agent_send_dtmf(GDBusMethodInvocation *context, char *dtmf)
3583 {
3584         int ret;
3585         char buf[20] = {0};
3586
3587         if (strlen(dtmf) <= 0)
3588                 return BT_HF_AGENT_ERROR_INVALID_PARAM;
3589
3590         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3591                 ERR("HF not Connected");
3592                 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3593         }
3594
3595         snprintf(buf, sizeof(buf),  BT_HF_DTMF, dtmf);
3596
3597         bt_hf_info.context = context;
3598
3599         ret = __bt_hf_send_only(&bt_hf_info, buf, strlen(buf));
3600         if (!ret)
3601                 return BT_HF_AGENT_ERROR_INTERNAL;
3602
3603
3604         return BT_HF_AGENT_ERROR_NONE;
3605 }
3606
3607
3608 static int _hf_agent_send_3way_cmd(GDBusMethodInvocation *context, char *cmd)
3609 {
3610         int ret;
3611
3612         if (strlen(cmd) <= 0)
3613                 return BT_HF_AGENT_ERROR_INVALID_PARAM;
3614
3615         bt_hf_info.context = context;
3616
3617         ret = __bt_hf_send_only(&bt_hf_info, cmd,
3618                                 strlen(cmd));
3619         if (!ret)
3620                 return BT_HF_AGENT_ERROR_INTERNAL;
3621
3622         return BT_HF_AGENT_ERROR_NONE;
3623 }
3624
3625 static gboolean bt_hf_agent_sco_connect(void)
3626 {
3627         struct sockaddr_sco addr;
3628         bdaddr_t bd_addr = {{0},};
3629         int sk;
3630         GIOChannel *sco_io;
3631         GDBusConnection *conn;
3632
3633         DBG("+");
3634
3635         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3636                 ERR("HF RFCOMM not Connected");
3637                 return FALSE;
3638         }
3639
3640         if (bt_hf_info.cli_sco_fd > 0) {
3641                 ERR("SCO Already connected..");
3642                 return FALSE;
3643         }
3644
3645         /* Create socket */
3646         sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
3647         if (sk < 0) {
3648                 ERR("Can't create SCO socket");
3649                 return FALSE;
3650         }
3651
3652         /* Bind to local address */
3653         memset(&addr, 0, sizeof(addr));
3654         addr.sco_family = AF_BLUETOOTH;
3655         memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
3656
3657         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3658                 ERR("Can't bind socket");
3659                 goto error;
3660         }
3661
3662         /* Connect to remote device */
3663         memset(&addr, 0, sizeof(addr));
3664         addr.sco_family = AF_BLUETOOTH;
3665         __bt_convert_addr_string_to_type_rev(addr.sco_bdaddr.b, bt_hf_info.remote_addr);
3666         if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3667                 ERR("Can't connect");
3668                 goto error;
3669         }
3670
3671         DBG("SCO Connected");
3672
3673          bt_hf_info.cli_sco_fd = sk;
3674
3675         sco_io = g_io_channel_unix_new(sk);
3676         g_io_channel_set_close_on_unref(sco_io, TRUE);
3677         g_io_channel_set_encoding(sco_io, NULL, NULL);
3678         g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
3679         g_io_channel_set_buffered(sco_io, FALSE);
3680
3681         g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
3682                                         __bt_hf_agent_sco_disconnect_cb, &bt_hf_info);
3683
3684         DBG("Emit AudioConnected Signal - Outgoing SCo connection");
3685         sco_audio_connected = BT_HF_AUDIO_CONNECTED;
3686
3687         conn = __bt_hf_get_gdbus_connection();
3688         if (!conn) {
3689                 ERR("Unable to get connection");
3690                 return FALSE;
3691         }
3692
3693         __bt_hf_agent_emit_signal(conn,
3694                         BT_HF_AGENT_OBJECT_PATH,
3695                         BT_HF_SERVICE_INTERFACE,
3696                         "AudioConnected", NULL);
3697
3698         DBG("-");
3699         return TRUE;
3700
3701 error:
3702         close(sk);
3703         DBG("-");
3704         return FALSE;
3705 }
3706
3707 static gboolean bt_hf_agent_sco_disconnect(void)
3708 {
3709         DBG("+");
3710         GDBusConnection *conn;
3711
3712         close(bt_hf_info.cli_sco_fd);
3713         bt_hf_info.cli_sco_fd = -1;
3714
3715         DBG("Emit AudioDisconnected Signal");
3716         conn = __bt_hf_get_gdbus_connection();
3717         if (!conn) {
3718                 ERR("Unable to get connection");
3719                 return FALSE;
3720         }
3721
3722         sco_audio_connected = BT_HF_AUDIO_DISCONNECTED;
3723
3724         __bt_hf_agent_emit_signal(conn,
3725                         BT_HF_AGENT_OBJECT_PATH,
3726                         BT_HF_SERVICE_INTERFACE,
3727                         "AudioDisconnected", NULL);
3728         DBG("-");
3729         return TRUE;
3730 }
3731
3732 static GVariant *bt_hf_agent_request_call_list(void)
3733 {
3734         GSList *call_list = NULL;
3735         GVariant *var_data;
3736         DBG("+");
3737
3738         call_list = __bt_hf_get_call_list(&bt_hf_info);
3739         if (!call_list) {
3740                 INFO("call list is NULL");
3741                 return NULL;
3742         }
3743
3744         var_data = __bt_hf_agent_get_call_status_info(call_list);
3745         __bt_hf_free_call_list(call_list);
3746
3747         DBG("-");
3748         return var_data;
3749 }
3750
3751 static int bt_hf_agent_send_at_cmd(GDBusMethodInvocation *context, char *atcmd)
3752
3753 {
3754         gboolean ret;
3755         char cmd_buf[BT_MAX_TEL_NUM_STR + 20] = {0, };
3756
3757         DBG("+");
3758
3759         if (atcmd == NULL)
3760                 return  BT_HF_AGENT_ERROR_INVALID_PARAM;
3761
3762         if (bt_hf_info.state != BT_HF_STATE_CONNECTED)
3763                 return  BT_HF_AGENT_ERROR_NOT_CONNECTED;
3764
3765         strncpy(cmd_buf, atcmd, sizeof(cmd_buf) - 2);
3766         strncat(cmd_buf, "\r", (sizeof(cmd_buf) - 1) - strlen(cmd_buf));
3767
3768         bt_hf_info.context = context;
3769
3770         ret = __bt_hf_send_only(&bt_hf_info, cmd_buf, strlen(cmd_buf));
3771         if (ret == FALSE)
3772                 return BT_HF_AGENT_ERROR_INTERNAL;
3773
3774         DBG("-");
3775         return BT_HF_AGENT_ERROR_NONE;
3776 }
3777
3778 static uint32_t __bt_hf_agent_get_hf_features(void)
3779 {
3780         uint32_t hf_features = BT_HF_FEATURE_EC_ANDOR_NR |
3781                         BT_HF_FEATURE_CALL_WAITING_AND_3WAY |
3782                         BT_HF_FEATURE_CLI_PRESENTATION |
3783                         BT_HF_FEATURE_REMOTE_VOLUME_CONTROL |
3784                         BT_HF_FEATURE_ENHANCED_CALL_STATUS |
3785                         BT_HF_FEATURE_CODEC_NEGOTIATION;
3786
3787         if (TIZEN_PROFILE_WEARABLE)
3788                 hf_features = hf_features | BT_HF_FEATURE_CODEC_NEGOTIATION;
3789
3790         hf_ver = HFP_VERSION_1_6;
3791
3792         return hf_features;
3793 }
3794
3795 int main(void)
3796 {
3797         int i;
3798         struct sigaction sa;
3799         uint32_t hf_features;
3800
3801         INFO_C("### Starting Bluetooth HF agent");
3802
3803 #if GLIB_VERSION_MIN_REQUIRED < GLIB_VERSION_2_36
3804         g_type_init();
3805 #endif
3806         hf_features = __bt_hf_agent_get_hf_features();
3807         bt_hf_info.feature = (uint16_t) hf_features & 0x3F;
3808
3809         memset(&sa, 0, sizeof(sa));
3810         sa.sa_flags = SA_NOCLDSTOP;
3811         sa.sa_handler = __bt_hf_agent_sigterm_handler;
3812
3813         for (i = 0; i < BT_HF_SIG_NUM; i++)
3814                 sigaction(bt_hf_sig_to_handle[i], &sa, &(bt_hf_sigoldact[i]));
3815
3816         g_log_set_default_handler(__on_log_glib, NULL);
3817
3818         gmain_loop = g_main_loop_new(NULL, FALSE);
3819
3820         if (gmain_loop == NULL) {
3821                 ERR("GMainLoop create failed\n");
3822                 return EXIT_FAILURE;
3823         }
3824
3825         __bt_hf_agent_dbus_init();
3826
3827         g_main_loop_run(gmain_loop);
3828
3829         __bt_hf_agent_dbus_deinit();
3830
3831         if (gmain_loop)
3832                 g_main_loop_unref(gmain_loop);
3833
3834         INFO_C("### Terminating Bluetooth HF agent");
3835         return 0;
3836 }