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