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