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