a4191b5fc4f28850da70c8e394a71708d452e90d
[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                 audio_out_drain((audio_out_h)bt_hf_info->audio_output);
2575                 audio_out_unprepare((audio_out_h)bt_hf_info->audio_output);
2576                 audio_out_destroy((audio_out_h)bt_hf_info->audio_output);
2577                 bt_hf_info->audio_output = NULL;
2578         }
2579
2580         INFO("-");
2581 }
2582
2583 static int __initialize_audio_in(bt_hf_agent_info_t *bt_hf_info)
2584 {
2585         int ret = 0;
2586
2587         INFO("+");
2588         if (bt_hf_info->audio_input != NULL) {
2589                 __release_audio_in(bt_hf_info);
2590         }
2591
2592         //init capturing
2593         ret = audio_in_create(HFP_FHUB_SAMPLE_RATE, AUDIO_CHANNEL_MONO,
2594                                         AUDIO_SAMPLE_TYPE_S16_LE, (audio_in_h *)&bt_hf_info->audio_input);
2595         if (ret == AUDIO_IO_ERROR_NONE) {
2596                 if (!(audio_in_prepare((audio_in_h)bt_hf_info->audio_input))) {
2597                         DBG("voice capturing is ready!\n");
2598                         bt_hf_info->is_audio_input_mute = FALSE;
2599                 } else {
2600                         ERR("audio_in_prepare failed, err(0x%x)\n", ret);
2601                         audio_in_destroy((audio_in_h)bt_hf_info->audio_input);
2602                         ret = -18;
2603                 }
2604         } else {
2605                 ERR("audio_in_create failed.\n");
2606                 ret = -17;
2607         }
2608
2609         INFO("-");
2610         return ret;
2611 }
2612
2613 static int __initialize_audio_out(bt_hf_agent_info_t *bt_hf_info)
2614 {
2615         int ret = 0;
2616         INFO("+");
2617
2618         if (bt_hf_info->audio_output != NULL) {
2619                 __release_audio_out(bt_hf_info);
2620         }
2621
2622         //init playback
2623         ret = audio_out_create_new(HFP_FHUB_SAMPLE_RATE, AUDIO_CHANNEL_MONO,
2624                                         AUDIO_SAMPLE_TYPE_S16_LE, (audio_out_h *)&bt_hf_info->audio_output);
2625         if (ret == AUDIO_IO_ERROR_NONE) {
2626                 INFO("after audio_out_create!!!");
2627
2628                 /* set sound stream info */
2629                 if (g_stream_info_write_h) {
2630                         if (!(ret = audio_out_set_sound_stream_info(bt_hf_info->audio_output, g_stream_info_write_h))) {
2631                                 INFO("after audio_out_set_sound_stream_info");
2632                         } else {
2633                                 ERR("fail to audio_out_set_sound_stream_info(), ret(0x%x)\n", ret);
2634                         }
2635                 } else {
2636                         ERR("no stream info!!!!");
2637                 }
2638
2639                 /* prepare */
2640                 if (!(ret = audio_out_prepare((audio_out_h)bt_hf_info->audio_output))) {
2641                         DBG("voice playback is ready!\n");
2642                 } else {
2643                         ERR("audio_out_prepare failed, err(0x%x)\n", ret);
2644                         audio_out_destroy((audio_out_h)bt_hf_info->audio_output);
2645                         bt_hf_info->audio_output = NULL;
2646                 }
2647         } else {
2648                 ERR("audio_out_create failed. \n");
2649         }
2650
2651         INFO("-");
2652         return ret;
2653 }
2654
2655 static gboolean __bt_hf_agent_sco_event_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
2656 {
2657         bt_hf_agent_info_t *bt_hf_info = user_data;
2658         GDBusConnection *conn;
2659         int sco_skt = g_io_channel_unix_get_fd(chan);
2660
2661         if (cond & G_IO_NVAL)
2662                 return FALSE;
2663
2664         if (cond & (G_IO_HUP | G_IO_ERR)) {
2665                 g_io_channel_shutdown(chan, TRUE, NULL);
2666                 close(bt_hf_info->cli_sco_fd);
2667                 bt_hf_info->cli_sco_fd = -1;
2668                 g_io_channel_unref(chan);
2669                 DBG("Emit AudioDisconnected Signal");
2670
2671                 sco_audio_connected = BT_HF_AUDIO_DISCONNECTED;
2672
2673                 bt_hf_info->call_state = BT_HF_DA_CALL_STAT_CALL_IDLE;
2674                 bt_hf_info->is_first_audio_out = TRUE;
2675
2676                 __release_audio_out(bt_hf_info);
2677                 __release_audio_in(bt_hf_info);
2678
2679                 conn = __bt_hf_get_gdbus_connection();
2680                 if (!conn) {
2681                         ERR("Unable to get connection");
2682                         return FALSE;
2683                 }
2684                 __bt_hf_agent_emit_signal(conn,
2685                                 BT_HF_AGENT_OBJECT_PATH,
2686                                 BT_HF_SERVICE_INTERFACE,
2687                                 "AudioDisconnected", NULL);
2688
2689                 return FALSE;
2690         }
2691
2692         if (cond & G_IO_IN) {
2693                 gchar buf_rx[HFP_SCO_DATA_BUFFER_SIZE] = { 0, };
2694                 int read;
2695
2696                 read = recv(sco_skt, buf_rx, HFP_SCO_DATA_BUFFER_SIZE, MSG_DONTWAIT);
2697                 if (read > 0) {
2698                         if (bt_hf_info->call_state == BT_HF_DA_CALL_STAT_CALL_SETUP_DIALING ||
2699                                 bt_hf_info->call_state == BT_HF_DA_CALL_STAT_CALL_SETUP_ALERTING ||
2700                                 bt_hf_info->call_active) {
2701
2702                                 if (bt_hf_info->is_first_audio_out) {
2703                                         __initialize_audio_out(bt_hf_info);
2704                                         bt_hf_info->is_first_audio_out = FALSE;
2705                                 }
2706                                 if (bt_hf_info->audio_output) {
2707                                         audio_out_write(bt_hf_info->audio_output, buf_rx, read);
2708                                 } else {
2709                                         ERR("can't write audio");
2710                                 }
2711                         }
2712                 }
2713         }
2714         if (cond & G_IO_OUT) {
2715                 gchar buf_tx[HFP_SCO_DATA_BUFFER_SIZE] = { 0, };
2716                 int size;
2717
2718                 if (bt_hf_info->is_first_audio_in) {
2719                         __initialize_audio_in(bt_hf_info);
2720                         bt_hf_info->is_first_audio_in = FALSE;
2721                         return  TRUE;
2722                 }
2723
2724                 size = audio_in_read(bt_hf_info->audio_input, (void *)buf_tx, HFP_SCO_DATA_BUFFER_SIZE);
2725                 if (size > 0) {
2726                         if (bt_hf_info->call_active) {
2727
2728                                 if (bt_hf_info->is_audio_input_mute) {
2729                                         memset(buf_tx, 0x0, size);
2730                                 }
2731
2732                                 if (send(sco_skt, buf_tx, size, MSG_DONTWAIT) < 0) {
2733                                         ERR("Write failed, error = %d[%s]", errno, strerror(errno));
2734                                 }
2735                         }
2736                 }
2737         }
2738         return TRUE;
2739 }
2740
2741
2742 static gboolean __bt_hf_agent_sco_disconnect_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
2743 {
2744         bt_hf_agent_info_t *bt_hf_info = user_data;
2745         GDBusConnection *conn;
2746
2747         DBG("");
2748         if (cond & G_IO_NVAL)
2749                 return FALSE;
2750
2751         if (cond & (G_IO_HUP | G_IO_ERR)) {
2752                 g_io_channel_shutdown(chan, TRUE, NULL);
2753                 close(bt_hf_info->cli_sco_fd);
2754                 bt_hf_info->cli_sco_fd = -1;
2755                 g_io_channel_unref(chan);
2756                 DBG("Emit AudioDisconnected Signal");
2757
2758                 sco_audio_connected = BT_HF_AUDIO_DISCONNECTED;
2759
2760                 conn = __bt_hf_get_gdbus_connection();
2761                 if (!conn) {
2762                         ERR("Unable to get connection");
2763                         return FALSE;
2764                 }
2765                 __bt_hf_agent_emit_signal(conn,
2766                                 BT_HF_AGENT_OBJECT_PATH,
2767                                 BT_HF_SERVICE_INTERFACE,
2768                                 "AudioDisconnected", NULL);
2769
2770                 return FALSE;
2771         }
2772
2773         return TRUE;
2774 }
2775
2776 static gboolean __bt_hf_agent_sco_accept_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
2777 {
2778         bt_hf_agent_info_t *bt_hf_info = user_data;
2779         int sco_skt;
2780         int cli_sco_sock;
2781         GIOChannel *sco_io;
2782         GDBusConnection *conn;
2783
2784         INFO("Incoming SCO....");
2785
2786         if (cond & G_IO_NVAL)
2787                 return FALSE;
2788
2789         sco_skt = g_io_channel_unix_get_fd(chan);
2790
2791         if (cond & (G_IO_HUP | G_IO_ERR)) {
2792                 close(sco_skt);
2793                 return FALSE;
2794         }
2795
2796         cli_sco_sock = accept(sco_skt, NULL, NULL);
2797         if (cli_sco_sock < 0)
2798                 return FALSE;
2799
2800         bt_hf_info->cli_sco_fd = cli_sco_sock;
2801
2802         sco_io = g_io_channel_unix_new(cli_sco_sock);
2803         g_io_channel_set_close_on_unref(sco_io, TRUE);
2804         g_io_channel_set_encoding(sco_io, NULL, NULL);
2805         g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
2806         g_io_channel_set_buffered(sco_io, FALSE);
2807
2808         if (TIZEN_MODEL_NAME_DA) {
2809                 bt_hf_info->call_state = BT_HF_DA_CALL_STAT_CALL_IDLE;
2810                 bt_hf_info->is_first_audio_out = TRUE;
2811                 bt_hf_info->is_first_audio_in = TRUE;
2812                 //__initialize_audio_in(bt_hf_info);
2813
2814                 g_io_add_watch(sco_io, G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
2815                                                 __bt_hf_agent_sco_event_cb, bt_hf_info);
2816         } else
2817                 g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
2818                                                 __bt_hf_agent_sco_disconnect_cb, bt_hf_info);
2819
2820         if (bt_hf_info->state != BT_HF_STATE_CONNECTED)
2821                 ERR("HFP is not yet connected");
2822
2823         /* S-Voice app requires the AudioConnected signal earlier */
2824         DBG("Emit AudioConnected Signal");
2825
2826         sco_audio_connected = BT_HF_AUDIO_CONNECTED;
2827
2828         conn = __bt_hf_get_gdbus_connection();
2829         if (!conn) {
2830                 ERR("Unable to get connection");
2831                 return FALSE;
2832         }
2833
2834         __bt_hf_agent_emit_signal(conn,
2835                         BT_HF_AGENT_OBJECT_PATH,
2836                         BT_HF_SERVICE_INTERFACE,
2837                         "AudioConnected", NULL);
2838
2839         /* In the case of incoming call, the call app is already launched,
2840          * hence AudioConnected signal is enough to update the call status.
2841          * In the case of outgoing call we need to lauch the callapp.
2842          */
2843
2844         __bt_hf_agent_launch_call_app();
2845
2846         return TRUE;
2847 }
2848
2849 static void __bt_convert_addr_string_to_type_rev(unsigned char *addr,
2850                                         const char *address)
2851 {
2852         int i;
2853         char *ptr = NULL;
2854
2855         ret_if(address == NULL);
2856         ret_if(addr == NULL);
2857
2858         for (i = 0; i < BT_ADDRESS_LENGTH_MAX; i++) {
2859                 addr[5 - i] = strtol(address, &ptr, 16);
2860                 if (ptr[0] != '\0') {
2861                         if (ptr[0] != ':')
2862                                 return;
2863
2864                         address = ptr + 1;
2865                 }
2866         }
2867 }
2868
2869 static gboolean __bt_hf_agent_sco_accept(bt_hf_agent_info_t *bt_hf_info)
2870 {
2871         struct sockaddr_sco addr;
2872         GIOChannel *sco_io;
2873         bdaddr_t bd_addr = {{0},};
2874         int sco_skt;
2875
2876         /* Create socket */
2877         sco_skt = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
2878         if (sco_skt < 0) {
2879                 ERR("Can't create socket:\n");
2880                 return FALSE;
2881         }
2882
2883         /* Bind to local address */
2884         memset(&addr, 0, sizeof(addr));
2885         addr.sco_family = AF_BLUETOOTH;
2886
2887         DBG("Bind to address %s", bt_hf_info->remote_addr);
2888
2889         __bt_convert_addr_string_to_type_rev(bd_addr.b, bt_hf_info->remote_addr);
2890         memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
2891
2892         if (bind(sco_skt, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2893                 ERR("Can't bind socket:\n");
2894                 goto error;
2895         }
2896
2897         if (listen(sco_skt, 1)) {
2898                 ERR("Can not listen on the socket:\n");
2899                 goto error;
2900         }
2901
2902         sco_io = g_io_channel_unix_new(sco_skt);
2903         g_io_channel_set_close_on_unref(sco_io, TRUE);
2904         g_io_channel_set_encoding(sco_io, NULL, NULL);
2905         g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
2906         g_io_channel_set_buffered(sco_io, FALSE);
2907
2908         bt_hf_info->sco_fd = sco_skt;
2909         bt_hf_info->sco_io_chan = sco_io;
2910
2911         bt_hf_info->sco_watch_id = g_io_add_watch(sco_io,
2912                         G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, __bt_hf_agent_sco_accept_cb, bt_hf_info);
2913
2914         g_io_channel_unref(sco_io);
2915
2916         return TRUE;
2917
2918 error:
2919         close(sco_skt);
2920         return FALSE;
2921 }
2922
2923 static gboolean __bt_get_supported_indicators(bt_hf_agent_info_t *bt_hf_info)
2924 {
2925         gchar buf[BT_HF_DATA_BUF_SIZE] = {0,};
2926         gboolean ret;
2927
2928         ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_INDICATORS_SUPP, buf,
2929                                 sizeof(BT_HF_INDICATORS_SUPP) - 1);
2930         if (!ret || !strstr(buf, "+CIND:"))
2931                 return FALSE;
2932
2933         bt_hf_info->indies = __bt_hf_parse_indicator_names(strchr(buf, '('), NULL);
2934
2935         return TRUE;
2936 }
2937
2938 static gboolean __bt_get_bia_cmd(bt_hf_agent_info_t *bt_hf_info, gchar *cmd, gsize cmd_size)
2939 {
2940         GSList *l;
2941         gsize ret;
2942
2943         if (bt_hf_info == NULL || cmd == NULL) {
2944                 ERR("Invalid parameter");
2945                 return FALSE;
2946         }
2947
2948         ret = g_strlcpy(cmd, BT_HF_INDICATORS_ACTIVATION, cmd_size);
2949
2950         for (l = bt_hf_info->indies; l != NULL; l = g_slist_next(l)) {
2951                 ret = g_strlcat(cmd, "0,", cmd_size);
2952                 if (ret >= cmd_size) {
2953                         ERR("Too many indices");
2954                         return FALSE;
2955                 }
2956
2957         }
2958
2959         cmd[ret - 1] = '\0';
2960         DBG("BIA Str : %s", cmd);
2961
2962         ret = g_strlcat(cmd, "\r", cmd_size);
2963         if (ret >= cmd_size) {
2964                 ERR("Too many indices");
2965                 return FALSE;
2966         }
2967
2968         return TRUE;
2969 }
2970
2971 static gboolean __bt_get_current_indicators(bt_hf_agent_info_t *bt_hf_info)
2972 {
2973         gchar buf[BT_HF_DATA_BUF_SIZE] = {0,};
2974         gboolean ret;
2975         gchar *str;
2976         GSList *l;
2977         int index =  1;
2978
2979         ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_INDICATORS_VAL, buf,
2980                 sizeof(BT_HF_INDICATORS_VAL) - 1);
2981         if (!ret || !strstr(buf, "+CIND:"))
2982                 return FALSE;
2983
2984         /* if buf has other command prefix, skip it */
2985         str = strstr(buf, "+CIND");
2986         if (str == NULL)
2987                 return FALSE;
2988
2989         bt_hf_info->indies = __bt_hf_parse_indicator_values(str + 6, bt_hf_info->indies);
2990
2991         /* Parse the updated value */
2992         for (l = bt_hf_info->indies; l != NULL; l = g_slist_next(l), ++index) {
2993                 struct indicator *ind = l->data;
2994                 if (!ind) {
2995                         DBG("Index is NULL");
2996                         break;
2997                 }
2998
2999                 if (0 == g_strcmp0(ind->descr, "\"call\"")) {
3000                         DBG("CIND Match found index = %d, %s, value = %d",
3001                                                 index, ind->descr, ind->value);
3002                         bt_hf_info->ciev_call_status = ind->value;
3003                         if (ind->value > 0) {
3004                                 bt_hf_info->is_dialing = FALSE;
3005                                 bt_hf_info->call_active = TRUE;
3006                         }
3007                 } else if (0 == g_strcmp0(ind->descr, "\"callsetup\"")) {
3008                         DBG("CIND Match found index = %d, %s, value = %d",
3009                                                 index, ind->descr, ind->value);
3010                         bt_hf_info->ciev_call_setup_status = ind->value;
3011                         if (!bt_hf_info->is_dialing && ind->value > 0)
3012                                 bt_hf_info->is_dialing = TRUE;
3013                 }
3014         }
3015
3016         return TRUE;
3017 }
3018
3019 static gboolean __bt_establish_service_level_conn(bt_hf_agent_info_t *bt_hf_info)
3020 {
3021         gchar buf[BT_HF_DATA_BUF_SIZE];
3022         gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
3023         gboolean ret;
3024         char *buf_ptr;
3025         guint feature;
3026
3027         if (TIZEN_MODEL_NAME_DA)
3028                 feature = BT_HF_FEATURE_CLI_PRESENTATION |
3029                                 BT_HF_FEATURE_REMOTE_VOLUME_CONTROL |
3030                                 BT_HF_FEATURE_ENHANCED_CALL_STATUS;
3031         else {
3032                 feature = BT_HF_FEATURE_EC_ANDOR_NR |
3033                                 BT_HF_FEATURE_CALL_WAITING_AND_3WAY |
3034                                 BT_HF_FEATURE_CLI_PRESENTATION |
3035                                 BT_HF_FEATURE_REMOTE_VOLUME_CONTROL |
3036                                 BT_HF_FEATURE_ENHANCED_CALL_STATUS;
3037
3038                 if (TIZEN_PROFILE_WEARABLE)
3039                         feature = feature | BT_HF_FEATURE_CODEC_NEGOTIATION;
3040         }
3041
3042         snprintf(cmd_buf, sizeof(cmd_buf), BT_HF_FEATURES, feature);
3043         ret = __bt_hf_send_and_read(bt_hf_info, cmd_buf, buf,
3044                                 strlen(cmd_buf));
3045         if (!ret)
3046                 return FALSE;
3047
3048         buf_ptr = strstr(buf, "\r\n+BRSF:");
3049         if (buf_ptr == NULL)
3050                 return FALSE;
3051
3052         if (!ret || sscanf(buf_ptr, "\r\n+BRSF:%5d", &bt_hf_info->ag_features) != 1)
3053                 return FALSE;
3054         INFO("Gateway supported features are 0x%X", bt_hf_info->ag_features);
3055
3056         if (TIZEN_PROFILE_WEARABLE) {
3057                 if (bt_hf_info->ag_features & BT_AG_FEATURE_CODEC_NEGOTIATION) {
3058                         ret = _hf_agent_codec_setup(bt_hf_info->remote_addr, BT_HF_CODEC_ID_MSBC);
3059                         if (ret != BT_HF_AGENT_ERROR_NONE)
3060                                 ERR("Unable to set the default WBC codec");
3061
3062                         ret = __bt_hf_send_available_codec(bt_hf_info, 0);
3063                         if (!ret)
3064                                 return FALSE;
3065                 }
3066         } else {
3067                 /* Default codec is NB */
3068                 ret = _hf_agent_codec_setup(bt_hf_info->remote_addr, BT_HF_CODEC_ID_CVSD);
3069                 if (ret != BT_HF_AGENT_ERROR_NONE)
3070                         ERR("Unable to set the default NBC codec");
3071         }
3072
3073         ret = __bt_get_supported_indicators(bt_hf_info);
3074         if (!ret)
3075                 return FALSE;
3076
3077
3078         ret = __bt_get_current_indicators(bt_hf_info);
3079         if (!ret)
3080                 return FALSE;
3081
3082         ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_INDICATORS_ENABLE, buf,
3083                                         sizeof(BT_HF_INDICATORS_ENABLE) - 1);
3084         if (!ret || !strstr(buf, "OK"))
3085                 return FALSE;
3086
3087         if ((bt_hf_info->ag_features & BT_AG_FEATURE_3WAY) != 0) {
3088                 ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_HOLD_MPTY_SUPP,
3089                                         buf, sizeof(BT_HF_HOLD_MPTY_SUPP) - 1);
3090                 if (!ret || !strstr(buf, "+CHLD:")) {
3091                         ERR("Unable to get the CHLD Supported info");
3092                         return FALSE;
3093                 }
3094                 bt_hf_info->hold_multiparty_features = __bt_hf_get_hold_mpty_features(
3095                                                         strchr(buf, '('));
3096         } else
3097                 bt_hf_info->hold_multiparty_features = 0;
3098
3099         if (bt_hf_info->ag_features & BT_AG_FEATURE_INBAND_RINGTONE)
3100                 bt_hf_info->inband_ringtone_support = TRUE;
3101         else
3102                 bt_hf_info->inband_ringtone_support = FALSE;
3103
3104         INFO("Service layer connection successfully established...!");
3105
3106         bt_hf_info->slc = TRUE;
3107         send_flag = FALSE;
3108         g_id = 0;
3109         memset(global_buff, 0, sizeof(global_buff));
3110         return TRUE;
3111 }
3112
3113 static void __bt_establish_initialization(bt_hf_agent_info_t *bt_hf_info)
3114 {
3115         gchar buf[BT_HF_DATA_BUF_SIZE];
3116         gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
3117         gboolean ret;
3118
3119         __bt_hf_send_and_read(bt_hf_info, BT_HF_CALLER_IDENT_ENABLE, buf,
3120                         sizeof(BT_HF_CALLER_IDENT_ENABLE) - 1);
3121         __bt_hf_send_and_read(bt_hf_info, BT_HF_CARRIER_FORMAT, buf,
3122                         sizeof(BT_HF_CARRIER_FORMAT) - 1);
3123         __bt_hf_send_and_read(bt_hf_info, BT_HF_CALLWAIT_NOTI_ENABLE, buf,
3124                         sizeof(BT_HF_CALLWAIT_NOTI_ENABLE) - 1);
3125
3126         if ((bt_hf_info->ag_features & BT_AG_FEATURE_NREC) != 0)
3127                 __bt_hf_send_and_read(bt_hf_info, BT_HF_NREC, buf,
3128                                                 sizeof(BT_HF_NREC) - 1);
3129
3130         if ((bt_hf_info->ag_features & BT_AG_FEATURE_EXTENDED_RES_CODE) != 0)
3131                 __bt_hf_send_and_read(bt_hf_info, BT_HF_EXTENDED_RESULT_CODE,
3132                         buf, sizeof(BT_HF_EXTENDED_RESULT_CODE) - 1);
3133
3134         if (__bt_get_bia_cmd(bt_hf_info, cmd_buf, sizeof(cmd_buf)) == TRUE)
3135                 __bt_hf_send_and_read(bt_hf_info, cmd_buf, buf, strlen(cmd_buf));
3136         else
3137                 ERR("__bt_get_bia_cmd is failed");
3138
3139         ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_XSAT, buf,
3140                                                 sizeof(BT_HF_XSAT) - 1);
3141         if (ret)
3142                 DBG("sent BT_HF_XSAT");
3143         else
3144                 ERR("BT_HF_XSAT sending failed");
3145
3146         if (TIZEN_PROFILE_WEARABLE) {
3147                 /* send Bluetooth Samsung Support Feature cmd */
3148                 ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_BSSF, buf,
3149                                                         sizeof(BT_HF_BSSF) - 1);
3150
3151                 /* If we got a 'OK' reply, peer AG is samsung device.
3152                  * Otherwise, non-samsung device */
3153                 if (ret && strstr(buf, "OK"))
3154                         bt_hf_info->is_companion_dev = TRUE;
3155                 else
3156                         bt_hf_info->is_companion_dev = FALSE;
3157
3158                 if (ret)
3159                         INFO("SLC completed with [%s] device",
3160                                 bt_hf_info->is_companion_dev ? "SS Companion" : "Other");
3161                 else
3162                         ERR("BT_HF_BSSF sending failed");
3163         }
3164 }
3165
3166 static void __bt_hf_agent_sigterm_handler(int signo)
3167 {
3168         GDBusConnection *conn;
3169         int i;
3170
3171         ERR_C("***** Signal handler came with signal %d *****", signo);
3172
3173         conn = __bt_hf_get_gdbus_connection();
3174         if (!conn) {
3175                 ERR("Unable to get G-DBus connection");
3176                 goto done;
3177         }
3178         INFO("Getting gdbus connection done");
3179
3180         __bt_hf_agent_emit_signal(conn,
3181                         BT_HF_AGENT_OBJECT_PATH,
3182                         BT_HF_SERVICE_INTERFACE,
3183                         "CallIdle", NULL);
3184         INFO("CallEnded Signal done");
3185
3186         g_dbus_connection_flush(conn, NULL, NULL, NULL);
3187         INFO("Flush g_dbus_connection");
3188
3189 done:
3190         if (gmain_loop) {
3191                 g_main_loop_quit(gmain_loop);
3192                 INFO("Exiting");
3193                 gmain_loop = NULL;
3194         } else {
3195                 INFO_C("Terminating HF agent");
3196                 exit(0);
3197         }
3198
3199         if (signo == SIGTERM)
3200                 return;
3201
3202         for (i = 0; i < BT_HF_SIG_NUM; i++)
3203                 sigaction(bt_hf_sig_to_handle[i], &(bt_hf_sigoldact[i]), NULL);
3204
3205         raise(signo);
3206 }
3207
3208 static void __bt_convert_addr_type_to_rev_string(char *address,
3209                                 unsigned char *addr)
3210 {
3211         ret_if(address == NULL);
3212         ret_if(addr == NULL);
3213
3214         g_snprintf(address, BT_ADDRESS_STRING_SIZE,
3215                         "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
3216                         addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
3217 }
3218
3219
3220 static gboolean __bt_hf_agent_release_after(gpointer user_data)
3221 {
3222         if (__bt_hf_agent_release() == FALSE)
3223                 ERR("Unable to release hf connection");
3224
3225         return FALSE;
3226 }
3227
3228 static gboolean __bt_agent_request_service_level_conn(gpointer data)
3229 {
3230         char *remote_addr;
3231         int bt_device_state = VCONFKEY_BT_DEVICE_NONE;
3232         GDBusConnection *conn;
3233
3234         DBG("+");
3235         memset(prev_cmd, 0, BT_HF_CMD_BUF_SIZE);
3236
3237         __bt_hf_agent_sco_accept(&bt_hf_info);
3238
3239         if (!__bt_establish_service_level_conn(&bt_hf_info)) {
3240                 ERR("Service Level Connection is fail");
3241
3242                 conn = __bt_hf_get_gdbus_connection();
3243                 if (conn) {
3244                         remote_addr = bt_hf_info.remote_addr;
3245                         __bt_hf_agent_emit_signal(conn,
3246                                         BT_HF_AGENT_OBJECT_PATH,
3247                                         BT_HF_SERVICE_INTERFACE,
3248                                         "Connected",
3249                                         g_variant_new("(s)", remote_addr));
3250                 }
3251                 bt_hf_info.state = BT_HF_STATE_CONNECTED;
3252
3253                 if (vconf_get_int(VCONFKEY_BT_DEVICE, &bt_device_state) == 0) {
3254                         DBG("BT device state is : 0x%X", bt_device_state);
3255                         bt_device_state |= VCONFKEY_BT_DEVICE_AG_CONNECTED;
3256                         if (vconf_set_int(VCONFKEY_BT_DEVICE, bt_device_state) != 0)
3257                                 ERR("vconf_set_int failed");
3258                 } else {
3259                         ERR("vconf_get_int failed");
3260                 }
3261
3262                 g_idle_add(__bt_hf_agent_release_after, NULL);
3263
3264                 goto done;
3265         }
3266
3267         bt_hf_info.state = BT_HF_STATE_CONNECTED;
3268
3269         __bt_hf_agent_start_watch(&bt_hf_info);
3270
3271         remote_addr = bt_hf_info.remote_addr;
3272
3273         INFO_SECURE("Address is : %s", remote_addr);
3274         INFO_C("### Connected [HF role]");
3275
3276         if (vconf_get_int(VCONFKEY_BT_DEVICE, &bt_device_state) == 0) {
3277                 DBG("BT device state is : 0x%X", bt_device_state);
3278                 bt_device_state |= VCONFKEY_BT_DEVICE_AG_CONNECTED;
3279
3280                 if (vconf_set_int(VCONFKEY_BT_DEVICE, bt_device_state) != 0)
3281                         ERR("vconf_set_int failed");
3282         } else {
3283                 ERR("vconf_get_int failed");
3284         }
3285
3286         conn = __bt_hf_get_gdbus_connection();
3287         if (!conn) {
3288                 ERR("Unable to get connection");
3289                 return FALSE;
3290         }
3291
3292         __bt_hf_agent_emit_signal(conn,
3293                         BT_HF_AGENT_OBJECT_PATH,
3294                         BT_HF_SERVICE_INTERFACE,
3295                         "Connected",
3296                         g_variant_new("(s)", remote_addr));
3297
3298         /* Establish the initialization */
3299         __bt_establish_initialization(&bt_hf_info);
3300
3301 done:
3302         DBG("-");
3303         return FALSE;
3304 }
3305
3306 static gboolean __bt_hf_agent_connection(gint32 fd, const gchar *obj_path)
3307 {
3308         GIOFlags flags;
3309
3310         struct sockaddr_remote address;
3311         socklen_t address_len;
3312         bt_hf_info.path = g_strdup(obj_path);
3313
3314         INFO_C("**** New HFP connection ****");
3315
3316         is_hf_connected = TRUE;
3317
3318         address_len = sizeof(address);
3319         if (getpeername(fd, (struct sockaddr *) &address, &address_len) != 0)
3320                 ERR("BD_ADDR is NULL");
3321
3322         DBG("RFCOMM connection for HFP is completed. Fd = [%d]\n", fd);
3323         bt_hf_info.fd = fd;
3324         bt_hf_info.io_chan = g_io_channel_unix_new(bt_hf_info.fd);
3325         flags = g_io_channel_get_flags(bt_hf_info.io_chan);
3326
3327         flags &= ~G_IO_FLAG_NONBLOCK;
3328         flags &= G_IO_FLAG_MASK;
3329         g_io_channel_set_flags(bt_hf_info.io_chan, flags, NULL);
3330         g_io_channel_set_encoding(bt_hf_info.io_chan, NULL, NULL);
3331         g_io_channel_set_buffered(bt_hf_info.io_chan, FALSE);
3332
3333         bt_hf_info.remote_addr = g_malloc0(BT_ADDRESS_STRING_SIZE);
3334         __bt_convert_addr_type_to_rev_string(bt_hf_info.remote_addr,
3335                                                 address.remote_bdaddr.b);
3336
3337         g_idle_add(__bt_agent_request_service_level_conn, NULL);
3338
3339         return TRUE;
3340 }
3341
3342 static void __bt_hf_agent_indicator_free(gpointer mem)
3343 {
3344         g_free(mem);
3345 }
3346
3347 static gboolean __bt_hf_agent_release(void)
3348 {
3349         int bt_device_state = VCONFKEY_BT_DEVICE_NONE;
3350         GDBusConnection *conn;
3351
3352         if (clcc_timer) {
3353                 g_source_remove(clcc_timer);
3354                 clcc_timer = 0;
3355         }
3356
3357         if (bt_hf_info.state == BT_HF_STATE_DISCONNECTED) {
3358                 ERR("hf is already disconnected");
3359                 return FALSE;
3360         }
3361
3362         if (bt_hf_info.indies) {
3363                 g_slist_free_full(bt_hf_info.indies, __bt_hf_agent_indicator_free);
3364                 bt_hf_info.indies = NULL;
3365         }
3366
3367         if (bt_hf_info.io_chan) {
3368                 g_io_channel_shutdown(bt_hf_info.io_chan, TRUE, NULL);
3369                 g_io_channel_unref(bt_hf_info.io_chan);
3370                 bt_hf_info.io_chan = NULL;
3371         }
3372
3373         if (bt_hf_info.sco_watch_id > 0) {
3374                 g_source_remove(bt_hf_info.sco_watch_id);
3375                 bt_hf_info.sco_watch_id = 0;
3376         }
3377
3378         bt_hf_info.state = BT_HF_STATE_DISCONNECTED;
3379
3380         __bt_hf_agent_release_queue();
3381
3382         if (vconf_get_int(VCONFKEY_BT_DEVICE, &bt_device_state) == 0) {
3383                 DBG("BT device state is : 0x%X", bt_device_state);
3384                 bt_device_state ^= VCONFKEY_BT_DEVICE_AG_CONNECTED;
3385
3386                 if (vconf_set_int(VCONFKEY_BT_DEVICE, bt_device_state) != 0)
3387                         ERR("vconf_set_int failed");
3388         } else {
3389                 ERR("vconf_get_int failed");
3390         }
3391
3392         __bt_hf_agent_stop_watch(&bt_hf_info);
3393         conn = __bt_hf_get_gdbus_connection();
3394         if (!conn) {
3395                 ERR("Unable to get connection");
3396                 return FALSE;
3397         }
3398
3399         __bt_hf_agent_emit_signal(conn,
3400                         BT_HF_AGENT_OBJECT_PATH,
3401                         BT_HF_SERVICE_INTERFACE,
3402                         "Disconnected",
3403                         g_variant_new("(s)", bt_hf_info.remote_addr));
3404
3405         g_free(bt_hf_info.path);
3406         bt_hf_info.path = NULL;
3407
3408         g_free(bt_hf_info.remote_addr);
3409         bt_hf_info.remote_addr = NULL;
3410
3411         is_hf_connected = FALSE;
3412
3413         return TRUE;
3414 }
3415
3416 static gboolean __bt_hf_agent_connection_release(void)
3417 {
3418         return __bt_hf_agent_release();
3419 }
3420
3421 static int __bt_hf_register_profile(const char *uuid, uint16_t version,
3422                  const char *name, const char *object, uint16_t features)
3423 {
3424         DBG("+");
3425         GDBusProxy *proxy;
3426         GVariant *ret;
3427         GError *error = NULL;
3428         GVariantBuilder *builder;
3429         gchar *path = NULL;
3430
3431         proxy = __bt_hf_gdbus_get_profile_proxy();
3432
3433         if (proxy == NULL)
3434                 return BT_HF_AGENT_ERROR_INTERNAL;
3435
3436         path = g_strdup(BT_HF_BLUEZ_OBJECT_PATH);
3437
3438         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3439
3440         g_variant_builder_add(builder, "{sv}",
3441                         "Name", g_variant_new("s",
3442                         name));
3443         g_variant_builder_add(builder, "{sv}",
3444                         "Version", g_variant_new("q", version));
3445
3446         g_variant_builder_add(builder, "{sv}",
3447                         "features", g_variant_new("q", features));
3448
3449         if (TIZEN_MODEL_NAME_DA)
3450                 ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile",
3451                                         g_variant_new("(osa{sv})", object,
3452                                                 uuid, builder),
3453                                         G_DBUS_CALL_FLAGS_NONE, -1,
3454                                         NULL, &error);
3455         else
3456                 ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile",
3457                                         g_variant_new("(osa{sv})", path,
3458                                                 HFP_HF_UUID, builder),
3459                                         G_DBUS_CALL_FLAGS_NONE, -1,
3460                                         NULL, &error);
3461
3462         g_variant_builder_unref(builder);
3463
3464         if (ret == NULL) {
3465                 /* dBUS-RPC is failed */
3466                 ERR("dBUS-RPC is failed");
3467                 if (error != NULL) {
3468                         /* dBUS gives error cause */
3469                         ERR("D-Bus API failure: errCode[%x], message[%s]",
3470                                 error->code, error->message);
3471                         g_clear_error(&error);
3472                 }
3473                 g_free(path);
3474                 return BT_HF_AGENT_ERROR_INTERNAL;
3475         }
3476         g_variant_unref(ret);
3477         g_free(path);
3478
3479         DBG("-");
3480         return BT_HF_AGENT_ERROR_NONE;
3481 }
3482
3483 static void __bt_hf_agent_register(void)
3484 {
3485         DBG("+");
3486         int ret;
3487         char *name;
3488         uint16_t version = hf_ver;
3489         uint16_t features = bt_hf_info.feature;
3490
3491         gchar *path = g_strdup(BT_HF_BLUEZ_OBJECT_PATH);
3492         name = g_strdup("Hands-Free");
3493
3494         ret = __bt_hf_register_profile(HFP_HF_UUID, version, name, path,
3495                                                                 features);
3496         if (ret)
3497                 ERR("Error in hf register");
3498
3499         if (TIZEN_MODEL_NAME_DA) {
3500                 ret = __bt_hf_register_profile(PBAP_PCE_UUID, 0x0101,
3501                                         "Phone Book Access Client",
3502                                         BT_PBAP_CLIENT_OBJECT_PATH, 0);
3503                 if (ret)
3504                         ERR("Error in pce register");
3505         }
3506
3507         g_free(path);
3508         g_free(name);
3509
3510         DBG("-");
3511         return;
3512 }
3513
3514 static void __bt_hf_agent_unregister(void)
3515 {
3516         DBG("+");
3517
3518         gchar *path = g_strdup(BT_HF_BLUEZ_OBJECT_PATH);
3519
3520         if (g_obj_path) {
3521                 __bt_hf_agent_gdbus_method_send(BLUEZ_SERVICE_NAME,
3522                                                 g_variant_new("(o)", path),
3523                                                 BLUEZ_HF_INTERFACE_NAME,
3524                                                 "UnregisterAgent");
3525                 g_free(g_obj_path);
3526                 g_obj_path = NULL;
3527         }
3528
3529         g_free(path);
3530
3531         DBG("-");
3532         return;
3533 }
3534
3535 static void __bt_hf_agent_filter_cb(GDBusConnection *connection,
3536                                                  const gchar *sender_name,
3537                                                  const gchar *object_path,
3538                                                  const gchar *interface_name,
3539                                                  const gchar *signal_name,
3540                                                  GVariant *parameters,
3541                                                  gpointer user_data)
3542 {
3543         DBG("+");
3544         char *path = NULL;
3545
3546         GVariant *optional_param;
3547
3548         if (strcasecmp(signal_name, "InterfacesAdded") == 0) {
3549
3550                 g_variant_get(parameters, "(&o@a{sa{sv}})",
3551                                 &path, &optional_param);
3552                 if (!path) {
3553                         ERR("Invalid adapter path");
3554                         return;
3555                 }
3556
3557                 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
3558                         g_obj_path = g_strdup(path);
3559                         INFO("Adapter Path = [%s]", path);
3560                         __bt_hf_agent_register();
3561                 }
3562         } else if (strcasecmp(signal_name, "InterfacesRemoved") == 0) {
3563                 g_variant_get(parameters, "(&o@as)", &path, &optional_param);
3564                 if (!path)
3565                         __bt_hf_agent_unregister();
3566         }
3567         DBG("-");
3568 }
3569
3570 static int __bt_hf_agent_get_adapter_path(GDBusConnection *conn, char *path)
3571 {
3572         GError *err = NULL;
3573         GDBusProxy *manager_proxy = NULL;
3574         GVariant *result = NULL;
3575         char *adapter_path = NULL;
3576
3577         if (conn == NULL)
3578                 return BT_HF_AGENT_ERROR_INTERNAL;
3579
3580         manager_proxy =  g_dbus_proxy_new_sync(conn,
3581                         G_DBUS_PROXY_FLAGS_NONE, NULL,
3582                         BLUEZ_SERVICE_NAME,
3583                         "/",
3584                         BT_MANAGER_INTERFACE,
3585                         NULL, &err);
3586
3587         if (!manager_proxy) {
3588                 ERR("Unable to create proxy: %s", err->message);
3589                 goto fail;
3590         }
3591
3592         result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
3593                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3594         if (!result) {
3595                 if (err != NULL)
3596                         ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
3597                 else
3598                         ERR("Fail to get DefaultAdapter");
3599
3600                 goto fail;
3601         }
3602
3603         if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
3604                 ERR("Incorrect result\n");
3605                 goto fail;
3606         }
3607
3608         g_variant_get(result, "(&o)", &adapter_path);
3609
3610         if (adapter_path == NULL ||
3611                 strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) {
3612                 ERR("Adapter path is inproper\n");
3613                 goto fail;
3614         }
3615
3616         if (path)
3617                 g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX);
3618
3619         if (g_obj_path == NULL) {
3620                 g_obj_path = g_strdup(adapter_path);
3621                 INFO("Update g_obj_path [%s]", adapter_path);
3622         }
3623
3624         g_variant_unref(result);
3625         g_object_unref(manager_proxy);
3626
3627         return 0;
3628
3629 fail:
3630         g_clear_error(&err);
3631
3632         if (result)
3633                 g_variant_unref(result);
3634
3635         if (manager_proxy)
3636                 g_object_unref(manager_proxy);
3637
3638         return BT_HF_AGENT_ERROR_INTERNAL;
3639
3640 }
3641
3642 static void __bt_hf_agent_dbus_init(void)
3643 {
3644         GDBusConnection *conn;
3645
3646         DBG("+");
3647
3648         conn = __bt_hf_get_gdbus_connection();
3649         if (conn == NULL) {
3650                 ERR("Error in creating the gdbus connection\n");
3651                 return;
3652         }
3653         if (!__bt_hf_register_profile_methods()) {
3654                 ERR("Error in register_profile_methods\n");
3655                 return;
3656         }
3657
3658         if (!__bt_hf_agent_get_adapter_path(gdbus_conn , NULL)) {
3659                 __bt_hf_agent_register();
3660         }
3661
3662         interface_added_sig_id = g_dbus_connection_signal_subscribe(conn,
3663                                 NULL, BT_MANAGER_INTERFACE, BT_INTERFACES_ADDED, NULL, NULL, 0,
3664                                 __bt_hf_agent_filter_cb, NULL, NULL);
3665
3666         interface_removed_sig_id = g_dbus_connection_signal_subscribe(conn,
3667                                 NULL, BT_MANAGER_INTERFACE, BT_INTERFACES_REMOVED, NULL, NULL, 0,
3668                                 __bt_hf_agent_filter_cb, NULL, NULL);
3669
3670         DBG("-");
3671 }
3672
3673 static void __bt_hf_agent_dbus_deinit(void)
3674 {
3675         if (profile_gproxy) {
3676                 g_object_unref(profile_gproxy);
3677                 profile_gproxy = NULL;
3678         }
3679
3680         if (gdbus_conn) {
3681                 if (interface_added_sig_id > 0)
3682                         g_dbus_connection_signal_unsubscribe(gdbus_conn,
3683                                                 interface_added_sig_id);
3684
3685                 if (interface_removed_sig_id > 0)
3686                         g_dbus_connection_signal_unsubscribe(gdbus_conn,
3687                                                 interface_removed_sig_id);
3688
3689                 interface_added_sig_id = 0;
3690                 interface_removed_sig_id = 0;
3691
3692                 g_object_unref(gdbus_conn);
3693                 gdbus_conn = NULL;
3694         }
3695 }
3696
3697 static int _hf_agent_answer_call(GDBusMethodInvocation *context)
3698 {
3699         int ret;
3700
3701         DBG("+\n");
3702         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3703                 ERR("HF not Connected");
3704                 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3705         }
3706         bt_hf_info.context = context;
3707
3708         ret = __bt_hf_send_only(&bt_hf_info, BT_HF_ANSWER_CALL,
3709                                 sizeof(BT_HF_ANSWER_CALL) - 1);
3710         if (!ret)
3711                 return BT_HF_AGENT_ERROR_INTERNAL;
3712
3713         DBG("-\n");
3714         return BT_HF_AGENT_ERROR_NONE;
3715
3716 }
3717
3718 static int _hf_agent_terminate_call(GDBusMethodInvocation *context)
3719 {
3720         int ret;
3721
3722         DBG("+\n");
3723         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3724                 ERR("HF not Connected");
3725                 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3726         }
3727
3728         bt_hf_info.context = context;
3729
3730         ret = __bt_hf_send_only(&bt_hf_info, BT_HF_END_CALL,
3731                                 sizeof(BT_HF_END_CALL) - 1);
3732         if (!ret)
3733                 return BT_HF_AGENT_ERROR_INTERNAL;
3734
3735         DBG("-\n");
3736         return BT_HF_AGENT_ERROR_NONE;
3737 }
3738
3739 static int _hf_agent_dial_no(GDBusMethodInvocation *context, char *no)
3740 {
3741         int ret;
3742         int prev_cmd_len = 0;
3743         char buf[BT_MAX_TEL_NUM_STR + 6] = {0};
3744
3745         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3746                 ERR("HF not Connected");
3747                 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3748         }
3749
3750         bt_hf_info.context = context;
3751
3752         if (strlen(no) > 0) {
3753                 snprintf(buf, sizeof(buf),  BT_HF_DIAL_NO, no);
3754
3755                 if (strstr(prev_cmd, "ATD") && bt_hf_info.ciev_call_status == 0
3756                                                 && bt_hf_info.ciev_call_setup_status == 0) {
3757                         INFO("RAD POPUP CANCEL CASE. send ATD w/o response - KOR REQUEST");
3758                         ret = __bt_hf_send_only_without_queue(&bt_hf_info, buf, strlen(buf));
3759                         if (send_flag)
3760                                 send_flag--;
3761                 } else {
3762                         ret = __bt_hf_send_only(&bt_hf_info, buf, strlen(buf));
3763                 }
3764
3765                 /* prev_cmd is meant for only meant for ATD & AT+BLDN Error handling */
3766                 prev_cmd_len = snprintf(prev_cmd, BT_HF_CMD_BUF_SIZE, "%s", buf);
3767
3768                 if (prev_cmd_len < 0) {
3769                         ERR("Encoding error occured in snprintf");
3770                         return BT_HF_AGENT_ERROR_INTERNAL;
3771                 }
3772
3773                 if (!ret)
3774                         return BT_HF_AGENT_ERROR_INTERNAL;
3775
3776                 return BT_HF_AGENT_ERROR_NONE;
3777         }
3778
3779         /* prev_cmd is meant for only meant for ATD & AT+BLDN Error handling */
3780         snprintf(prev_cmd, BT_HF_CMD_BUF_SIZE, "%s", BT_HF_REDIAL);
3781
3782         ret = __bt_hf_send_only(&bt_hf_info, BT_HF_REDIAL,
3783                                                 sizeof(BT_HF_REDIAL) - 1);
3784         if (!ret)
3785                 return BT_HF_AGENT_ERROR_INTERNAL;
3786
3787         return BT_HF_AGENT_ERROR_NONE;
3788 }
3789
3790 static int _hf_agent_voice_recognition(GDBusMethodInvocation *context, unsigned int status)
3791 {
3792         int ret;
3793         char buf[20] = {0};
3794
3795         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3796                 ERR("HF not Connected");
3797                 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3798         }
3799
3800         snprintf(buf, sizeof(buf),  BT_HF_VOICE_RECOGNITION, status);
3801
3802         bt_hf_info.context = context;
3803
3804         ret = __bt_hf_send_only(&bt_hf_info, buf, strlen(buf));
3805         if (!ret)
3806                 return BT_HF_AGENT_ERROR_INTERNAL;
3807
3808
3809         return BT_HF_AGENT_ERROR_NONE;
3810 }
3811
3812 static int _hf_agent_set_speaker_gain(GDBusMethodInvocation *context, unsigned int gain)
3813 {
3814         int ret;
3815         char buf[20] = {0};
3816
3817         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3818                 ERR("HF not Connected");
3819                 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3820         }
3821
3822         if (gain > BT_HF_MAX_SPEAKER_GAIN)
3823                 return BT_HF_AGENT_ERROR_INVALID_PARAM;
3824
3825         snprintf(buf, sizeof(buf),  BT_HF_SPEAKER_GAIN, gain);
3826
3827         bt_hf_info.context = context;
3828
3829         ret = __bt_hf_send_only(&bt_hf_info, buf,
3830                                 strlen(buf));
3831         if (!ret)
3832                 return BT_HF_AGENT_ERROR_INTERNAL;
3833
3834         return BT_HF_AGENT_ERROR_NONE;
3835
3836 }
3837
3838 static int _hf_agent_send_dtmf(GDBusMethodInvocation *context, char *dtmf)
3839 {
3840         int ret;
3841         char buf[20] = {0};
3842
3843         if (strlen(dtmf) <= 0)
3844                 return BT_HF_AGENT_ERROR_INVALID_PARAM;
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         snprintf(buf, sizeof(buf),  BT_HF_DTMF, dtmf);
3852
3853         bt_hf_info.context = context;
3854
3855         ret = __bt_hf_send_only(&bt_hf_info, buf, strlen(buf));
3856         if (!ret)
3857                 return BT_HF_AGENT_ERROR_INTERNAL;
3858
3859
3860         return BT_HF_AGENT_ERROR_NONE;
3861 }
3862
3863
3864 static int _hf_agent_send_3way_cmd(GDBusMethodInvocation *context, char *cmd)
3865 {
3866         int ret;
3867
3868         if (strlen(cmd) <= 0)
3869                 return BT_HF_AGENT_ERROR_INVALID_PARAM;
3870
3871         bt_hf_info.context = context;
3872
3873         ret = __bt_hf_send_only(&bt_hf_info, cmd,
3874                                 strlen(cmd));
3875         if (!ret)
3876                 return BT_HF_AGENT_ERROR_INTERNAL;
3877
3878         return BT_HF_AGENT_ERROR_NONE;
3879 }
3880
3881 static gboolean bt_hf_agent_sco_connect(void)
3882 {
3883         struct sockaddr_sco addr;
3884         bdaddr_t bd_addr = {{0},};
3885         int sk;
3886         GIOChannel *sco_io;
3887         GDBusConnection *conn;
3888
3889         DBG("+");
3890
3891         if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3892                 ERR("HF RFCOMM not Connected");
3893                 return FALSE;
3894         }
3895
3896         if (bt_hf_info.cli_sco_fd > 0) {
3897                 ERR("SCO Already connected..");
3898                 return FALSE;
3899         }
3900
3901         /* Create socket */
3902         sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
3903         if (sk < 0) {
3904                 ERR("Can't create SCO socket");
3905                 return FALSE;
3906         }
3907
3908         /* Bind to local address */
3909         memset(&addr, 0, sizeof(addr));
3910         addr.sco_family = AF_BLUETOOTH;
3911         memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
3912
3913         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3914                 ERR("Can't bind socket");
3915                 goto error;
3916         }
3917
3918         /* Connect to remote device */
3919         memset(&addr, 0, sizeof(addr));
3920         addr.sco_family = AF_BLUETOOTH;
3921         __bt_convert_addr_string_to_type_rev(addr.sco_bdaddr.b, bt_hf_info.remote_addr);
3922         if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3923                 ERR("Can't connect");
3924                 goto error;
3925         }
3926
3927         DBG("SCO Connected");
3928
3929          bt_hf_info.cli_sco_fd = sk;
3930
3931         sco_io = g_io_channel_unix_new(sk);
3932         g_io_channel_set_close_on_unref(sco_io, TRUE);
3933         g_io_channel_set_encoding(sco_io, NULL, NULL);
3934         g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
3935         g_io_channel_set_buffered(sco_io, FALSE);
3936
3937         g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
3938                                         __bt_hf_agent_sco_disconnect_cb, &bt_hf_info);
3939
3940         DBG("Emit AudioConnected Signal - Outgoing SCo connection");
3941         sco_audio_connected = BT_HF_AUDIO_CONNECTED;
3942
3943         conn = __bt_hf_get_gdbus_connection();
3944         if (!conn) {
3945                 ERR("Unable to get connection");
3946                 return FALSE;
3947         }
3948
3949         __bt_hf_agent_emit_signal(conn,
3950                         BT_HF_AGENT_OBJECT_PATH,
3951                         BT_HF_SERVICE_INTERFACE,
3952                         "AudioConnected", NULL);
3953
3954         DBG("-");
3955         return TRUE;
3956
3957 error:
3958         close(sk);
3959         DBG("-");
3960         return FALSE;
3961 }
3962
3963 static gboolean bt_hf_agent_sco_disconnect(void)
3964 {
3965         DBG("+");
3966         GDBusConnection *conn;
3967
3968         close(bt_hf_info.cli_sco_fd);
3969         bt_hf_info.cli_sco_fd = -1;
3970
3971         DBG("Emit AudioDisconnected Signal");
3972         conn = __bt_hf_get_gdbus_connection();
3973         if (!conn) {
3974                 ERR("Unable to get connection");
3975                 return FALSE;
3976         }
3977
3978         sco_audio_connected = BT_HF_AUDIO_DISCONNECTED;
3979
3980         __bt_hf_agent_emit_signal(conn,
3981                         BT_HF_AGENT_OBJECT_PATH,
3982                         BT_HF_SERVICE_INTERFACE,
3983                         "AudioDisconnected", NULL);
3984         DBG("-");
3985         return TRUE;
3986 }
3987
3988 static GVariant *bt_hf_agent_request_call_list(void)
3989 {
3990         GSList *call_list = NULL;
3991         GVariant *var_data;
3992         DBG("+");
3993
3994         call_list = __bt_hf_get_call_list(&bt_hf_info);
3995         if (!call_list) {
3996                 INFO("call list is NULL");
3997                 return NULL;
3998         }
3999
4000         var_data = __bt_hf_agent_get_call_status_info(call_list);
4001         __bt_hf_free_call_list(call_list);
4002
4003         DBG("-");
4004         return var_data;
4005 }
4006
4007 static int bt_hf_agent_send_at_cmd(GDBusMethodInvocation *context, char *atcmd)
4008
4009 {
4010         gboolean ret;
4011         char cmd_buf[BT_MAX_TEL_NUM_STR + 20] = {0, };
4012
4013         DBG("+");
4014
4015         if (atcmd == NULL)
4016                 return  BT_HF_AGENT_ERROR_INVALID_PARAM;
4017
4018         if (bt_hf_info.state != BT_HF_STATE_CONNECTED)
4019                 return  BT_HF_AGENT_ERROR_NOT_CONNECTED;
4020
4021         strncpy(cmd_buf, atcmd, sizeof(cmd_buf) - 2);
4022         strncat(cmd_buf, "\r", (sizeof(cmd_buf) - 1) - strlen(cmd_buf));
4023
4024         bt_hf_info.context = context;
4025
4026         ret = __bt_hf_send_only(&bt_hf_info, cmd_buf, strlen(cmd_buf));
4027         if (ret == FALSE)
4028                 return BT_HF_AGENT_ERROR_INTERNAL;
4029
4030         DBG("-");
4031         return BT_HF_AGENT_ERROR_NONE;
4032 }
4033
4034 static uint32_t __bt_hf_agent_get_hf_features(void)
4035 {
4036         uint32_t hf_features;
4037
4038         if (TIZEN_MODEL_NAME_DA)
4039                 hf_features = BT_HF_FEATURE_CLI_PRESENTATION |
4040                                 BT_HF_FEATURE_REMOTE_VOLUME_CONTROL;
4041         else {
4042                 hf_features = BT_HF_FEATURE_EC_ANDOR_NR |
4043                                 BT_HF_FEATURE_CALL_WAITING_AND_3WAY |
4044                                 BT_HF_FEATURE_CLI_PRESENTATION |
4045                                 BT_HF_FEATURE_REMOTE_VOLUME_CONTROL |
4046                                 BT_HF_FEATURE_ENHANCED_CALL_STATUS |
4047                                 BT_HF_FEATURE_CODEC_NEGOTIATION;
4048
4049                 if (TIZEN_PROFILE_WEARABLE)
4050                         hf_features = hf_features | BT_HF_FEATURE_CODEC_NEGOTIATION;
4051         }
4052
4053         hf_ver = HFP_VERSION_1_6;
4054
4055         return hf_features;
4056 }
4057
4058 int main(void)
4059 {
4060         int i;
4061         struct sigaction sa;
4062         uint32_t hf_features;
4063
4064         INFO_C("### Starting Bluetooth HF agent");
4065
4066 #if GLIB_VERSION_MIN_REQUIRED < GLIB_VERSION_2_36
4067         g_type_init();
4068 #endif
4069         hf_features = __bt_hf_agent_get_hf_features();
4070         bt_hf_info.feature = (uint16_t) hf_features & 0x3F;
4071
4072         bt_hf_info.audio_input = NULL;
4073         bt_hf_info.audio_output = NULL;
4074
4075         memset(&sa, 0, sizeof(sa));
4076         sa.sa_flags = SA_NOCLDSTOP;
4077         sa.sa_handler = __bt_hf_agent_sigterm_handler;
4078
4079         for (i = 0; i < BT_HF_SIG_NUM; i++)
4080                 sigaction(bt_hf_sig_to_handle[i], &sa, &(bt_hf_sigoldact[i]));
4081
4082         g_log_set_default_handler(__on_log_glib, NULL);
4083
4084         gmain_loop = g_main_loop_new(NULL, FALSE);
4085
4086         if (gmain_loop == NULL) {
4087                 ERR("GMainLoop create failed\n");
4088                 return EXIT_FAILURE;
4089         }
4090
4091         __bt_hf_agent_dbus_init();
4092
4093         g_main_loop_run(gmain_loop);
4094
4095         __bt_hf_agent_dbus_deinit();
4096
4097         if (gmain_loop)
4098                 g_main_loop_unref(gmain_loop);
4099
4100         INFO_C("### Terminating Bluetooth HF agent");
4101         return 0;
4102 }