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