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