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