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