4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Chethan T N <chethan.tn@samsung.com>
8 * Chanyeol Park <chanyeol.park@samsung.com>
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
14 * http://www.apache.org/licenses/LICENSE-2.0
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.
31 #include <sys/socket.h>
35 #include <gio/gunixfdlist.h>
36 #include <device/power.h>
37 #include <app_manager.h>
39 #include <vconf-keys.h>
40 #include <bundle_internal.h>
42 #include "bluetooth-hf-agent.h"
43 #include "bluetooth-agent-profile.h"
45 #define BT_AGENT_SYSPOPUP_MAX_ATTEMPT 3
46 #define CALL_ALIAS_APP_ID "org.tizen.call-ui"
48 #define MAX_WAITING_DELAY 8
49 #define READ_TX_POWER_MIN -30
51 #define BT_ADDRESS_STRING_SIZE 18
52 #define BT_AT_COMMAND_BUFFER_MAX 4000
53 #define BT_HF_ERROR_RESP "\r\nERROR\r\n"
54 #define BT_HF_COMMAND_TIMEOUT 3
56 #define ret_if(expr) \
59 ERR("(%s) return", #expr); \
64 static GMainLoop *gmain_loop = NULL;
65 static char *g_obj_path;
67 static GDBusConnection *gdbus_conn = NULL;
68 static GDBusProxy *profile_gproxy = NULL;
69 static guint interface_added_sig_id;
70 static guint interface_removed_sig_id;
75 int clcc_retry_count = 0;
76 guint clcc_async_timer = 0;
77 int clcc_async_retry_count = 0;
78 #define CLCC_RETRY_COUNT 10
79 #define CLCC_RETRY_TIMER 100 /* 100 msec */
81 #define HFP_HF_UUID "0000111e-0000-1000-8000-00805f9b34fb"
82 #define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
84 /*Below Inrospection data is exposed to bluez from agent*/
85 static const gchar hf_agent_bluez_introspection_xml[] =
87 " <interface name='org.bluez.Profile1'>"
88 " <method name='NewConnection'>"
89 " <arg type='o' name='device' direction='in'/>"
90 " <arg type='h' name='fd' direction='in'/>"
91 " <arg type='a{sv}' name='options' direction='in'/>"
93 " <method name='RequestDisconnection'>"
94 " <arg type='o' name='device' direction='in'/>"
99 /*Below Inrospection data is exposed to application from agent*/
100 static const gchar hf_agent_introspection_xml[] =
102 " <interface name='org.tizen.HfApp'>"
103 " <method name='AnswerCall'>"
105 " <method name='TerminateCall'>"
107 " <method name='InitiateCall'>"
108 " <arg type='s' name='phoneno' direction='in'/>"
110 " <method name='VoiceRecognition'>"
111 " <arg type='i' name='status' direction='in'/>"
113 " <method name='ScoConnect'>"
115 " <method name='ScoDisconnect'>"
117 " <method name='SpeakerGain'>"
118 " <arg type='u' name='gain' direction='in'/>"
120 " <method name='SendDtmf'>"
121 " <arg type='s' name='dtmf' direction='in'/>"
123 " <method name='SendAtCmd'>"
124 " <arg type='s' name='atcmd' direction='in'/>"
126 " <method name='ReleaseAndAccept'>"
128 " <method name='CallSwap'>"
130 " <method name='ReleaseAllCall'>"
132 " <method name='JoinCall'>"
134 " <method name='GetCurrentCodec'>"
135 " <arg type='i' name='codec' direction='out'/>"
137 " <method name='RequestCallList'>"
138 " <arg type='i' name='count' direction='out'/>"
139 " <arg type='a(siiii)' name='callList' direction='out'/>"
141 " <method name='RequestCallListAsync'>"
143 " <method name='GetAudioConnected'>"
144 " <arg type='i' name='status' direction='out'/>"
146 " <method name='IsHfConnected'>"
147 " <arg type='b' name='status' direction='out'/>"
149 " <method name='IsInbandRingtoneSupported'>"
150 " <arg type='b' name='status' direction='out'/>"
155 static bt_hf_agent_info_t bt_hf_info = {0,};
156 static gboolean is_hf_connected = FALSE;
157 static int32_t current_codec_id = BT_HF_CODEC_ID_CVSD;
158 static int32_t sco_audio_connected = BT_HF_AUDIO_DISCONNECTED;
160 static char global_buff[BT_AT_COMMAND_BUFFER_MAX] = {0,};
163 static char prev_cmd[BT_HF_CMD_BUF_SIZE];
173 } hf_call_list_info_t;
175 #define BT_HF_SIG_NUM 3
176 static struct sigaction bt_hf_sigoldact[BT_HF_SIG_NUM];
177 static int bt_hf_sig_to_handle[] = { SIGABRT, SIGSEGV, SIGTERM };
179 static GError *__bt_hf_agent_set_error(bt_hf_agent_error_t error);
181 static gboolean __bt_hf_agent_emit_property_changed(
182 GDBusConnection *connection,
184 const char *interface,
188 static gboolean __bt_hf_agent_data_cb(GIOChannel *chan, GIOCondition cond,
189 bt_hf_agent_info_t *bt_hf_info);
190 static void __bt_hf_agent_stop_watch(bt_hf_agent_info_t *bt_hf_info);
191 static void __bt_hf_agent_start_watch(bt_hf_agent_info_t *bt_hf_info);
192 static gboolean __bt_hf_channel_write(GIOChannel *io, gchar *data,
194 static gboolean __bt_hf_send_only_without_queue(bt_hf_agent_info_t *bt_hf_info,
195 gchar *data, gsize count);
197 static gboolean __bt_hf_send_only(bt_hf_agent_info_t *bt_hf_info, gchar *data,
199 static gboolean __bt_hf_send_and_read(bt_hf_agent_info_t *bt_hf_info,
200 gchar *data, gchar *response, gsize count);
201 static GSList *__bt_hf_parse_indicator_names(gchar *names, GSList *indies);
202 static GSList *__bt_hf_parse_indicator_values(gchar *values, GSList *indies);
203 static guint __bt_hf_get_hold_mpty_features(gchar *features);
204 static gboolean __bt_establish_service_level_conn(bt_hf_agent_info_t *bt_hf_info);
205 static void __bt_hf_agent_sigterm_handler(int signo);
206 static gboolean __bt_hf_agent_release(void);
208 static gboolean __bt_get_current_indicators(bt_hf_agent_info_t *bt_hf_info);
209 static gboolean __bt_get_supported_indicators(bt_hf_agent_info_t *bt_hf_info);
210 static gboolean __bt_hf_agent_connection(gint32 fd, const gchar * object_path);
211 static gboolean __bt_hf_agent_connection_release(void);
212 static void __bt_hf_agent_handle_call_list(bt_hf_agent_info_t *bt_hf_info);
215 gchar descr[BT_HF_INDICATOR_DESCR_SIZE];
219 static int _hf_agent_answer_call(GDBusMethodInvocation *context);
221 static int _hf_agent_terminate_call(GDBusMethodInvocation *context);
223 static int _hf_agent_dial_no(GDBusMethodInvocation *context, char *no);
225 static int _hf_agent_set_speaker_gain(GDBusMethodInvocation *context,
228 static int _hf_agent_send_3way_cmd(GDBusMethodInvocation *context, char *cmd);
230 static int _hf_agent_voice_recognition(GDBusMethodInvocation *context,
231 unsigned int status);
233 static gboolean bt_hf_agent_sco_connect(void);
235 static gboolean bt_hf_agent_sco_disconnect(void);
237 static int _hf_agent_send_dtmf(GDBusMethodInvocation *context, char *dtmf);
239 static GVariant *bt_hf_agent_request_call_list(void);
241 static int bt_hf_agent_send_at_cmd(GDBusMethodInvocation *context, char *atcmd);
243 static int hf_handle_rx_at_cmd(bt_hf_agent_info_t *bt_hf_info, const char *buf);
245 static void __on_log_glib(const gchar *log_domain, GLogLevelFlags log_level,
246 const gchar *msg, gpointer user_data)
251 static void __bt_hf_agent_print_at_buffer(char *message, const char *buf)
255 char s[BT_HF_DATA_BUF_SIZE] = {0, };
256 gboolean hide = FALSE;
258 gboolean has_clcc = FALSE;
259 gboolean has_clip = FALSE;
260 gboolean has_ccwa = FALSE;
263 strncpy(s, buf, BT_HF_DATA_BUF_SIZE - 1);
265 has_clcc = strstr(buf, "CLCC:") ? TRUE : FALSE;
266 if (has_clcc == TRUE)
268 has_clip = strstr(buf, "+CLIP:") ? TRUE : FALSE;
269 if (has_clip == TRUE)
271 has_ccwa = strstr(buf, "+CCWA:") ? TRUE : FALSE;
275 xsat_ptr = strstr(s, "11,DISC,");
277 xsat_ptr = xsat_ptr + 8;
279 while (xsat_ptr[x] != '\0' && xsat_ptr[x] != '\r' && xsat_ptr[x] != '\n') {
285 /* AT+XSAT=11,Q_CT,X,XXXX */
286 xsat_ptr = strstr(s, "11,Q_CT,");
288 xsat_ptr = xsat_ptr + 8;
290 while (xsat_ptr[x] != '\0' && xsat_ptr[x] != '\r' && xsat_ptr[x] != '\n') {
291 if (x > 1) /* ignore 0 and 1 position */
298 while (s[i] != '\0') {
299 if (s[i] == '\r' || s[i] == '\n') {
303 hide = hide ? FALSE : TRUE;
304 else if ((has_clcc || has_clip || has_ccwa) && hide) {
312 INFO("%s Buffer = %s, Length = %d ", message, s, strlen(s));
317 static GQuark __bt_hf_agent_error_quark(void)
321 static GQuark quark = 0;
323 quark = g_quark_from_static_string("hf-agent");
328 static GError *__bt_hf_agent_set_error(bt_hf_agent_error_t error)
330 ERR("error[%d]", error);
333 case BT_HF_AGENT_ERROR_NOT_AVAILABLE:
334 return g_error_new(BT_HF_AGENT_ERROR, error,
335 BT_ERROR_NOT_AVAILABLE);
336 case BT_HF_AGENT_ERROR_NOT_CONNECTED:
337 return g_error_new(BT_HF_AGENT_ERROR, error,
338 BT_ERROR_NOT_CONNECTED);
339 case BT_HF_AGENT_ERROR_CONNECTION_FAILED:
340 return g_error_new(BT_HF_AGENT_ERROR, error,
341 BT_ERROR_NOT_CONNECTION_FAILED);
342 case BT_HF_AGENT_ERROR_BUSY:
343 return g_error_new(BT_HF_AGENT_ERROR, error,
345 case BT_HF_AGENT_ERROR_INVALID_PARAM:
346 return g_error_new(BT_HF_AGENT_ERROR, error,
347 BT_ERROR_INVALID_PARAM);
348 case BT_HF_AGENT_ERROR_ALREADY_EXIST:
349 return g_error_new(BT_HF_AGENT_ERROR, error,
350 BT_ERROR_ALREADY_EXIST);
351 case BT_HF_AGENT_ERROR_ALREADY_CONNECTED:
352 return g_error_new(BT_HF_AGENT_ERROR, error,
353 BT_ERROR_ALREADY_CONNECTED);
354 case BT_HF_AGENT_ERROR_NO_MEMORY:
355 return g_error_new(BT_HF_AGENT_ERROR, error,
357 case BT_HF_AGENT_ERROR_NO_DATA:
358 return g_error_new(BT_HF_AGENT_ERROR, error,
360 case BT_HF_AGENT_ERROR_I_O_ERROR:
361 return g_error_new(BT_HF_AGENT_ERROR, error,
363 case BT_HF_AGENT_ERROR_APPLICATION:
364 return g_error_new(BT_HF_AGENT_ERROR, error,
365 BT_ERROR_OPERATION_NOT_AVAILABLE);
366 case BT_HF_AGENT_ERROR_NOT_ALLOWED:
367 return g_error_new(BT_HF_AGENT_ERROR, error,
368 BT_ERROR_OPERATION_NOT_ALLOWED);
369 case BT_HF_AGENT_ERROR_NOT_SUPPORTED:
370 return g_error_new(BT_HF_AGENT_ERROR, error,
371 BT_ERROR_OPERATION_NOT_SUPPORTED);
372 case BT_HF_AGENT_ERROR_INVALID_FILE_DESCRIPTOR:
373 return g_error_new(BT_HF_AGENT_ERROR, error,
374 BT_ERROR_INVALID_FILE_DESCRIPTOR);
375 case BT_HF_AGENT_ERROR_INTERNAL:
377 return g_error_new(BT_HF_AGENT_ERROR, error,
382 static void __bt_hf_lock_display(int timeout)
386 ret = device_power_request_lock(POWER_LOCK_DISPLAY, timeout);
388 DBG("Lock PM state as current state!");
390 ERR("deviced error!");
393 static void __bt_hf_unlock_display()
397 ret = device_power_release_lock(POWER_LOCK_DISPLAY);
399 DBG("UnLock PM state");
401 ERR("deviced error!");
404 static gboolean __clcc_timer_func(gpointer data)
411 if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
412 DBG("NOT CONNECTED");
413 err = __bt_hf_agent_set_error(BT_HF_AGENT_ERROR_NOT_CONNECTED);
414 g_dbus_method_invocation_return_gerror((GDBusMethodInvocation *) data, err);
420 if (send_flag && clcc_retry_count > 0) {
422 DBG("Still pending. try later (remained [%d] times)", clcc_retry_count);
428 call_var = bt_hf_agent_request_call_list();
430 INFO("NOT AVAILABLE");
431 err = __bt_hf_agent_set_error(BT_HF_AGENT_ERROR_NOT_AVAILABLE);
432 g_dbus_method_invocation_return_gerror((GDBusMethodInvocation *) data, err);
437 INFO("return call list info");
438 g_dbus_method_invocation_return_value((GDBusMethodInvocation *) data, call_var);
442 static gboolean __clcc_async_timer_func(gpointer data)
446 if (send_flag && clcc_async_retry_count > 0) {
447 clcc_async_retry_count--;
448 ERR("Still pending. try later (remained [%d] times)", clcc_async_retry_count);
452 clcc_async_timer = 0;
454 __bt_hf_agent_handle_call_list(&bt_hf_info);
455 g_dbus_method_invocation_return_value((GDBusMethodInvocation*)data, NULL);
457 INFO("update_call_list succeeded");
462 static void __hf_agent_method(GDBusConnection *connection,
464 const gchar *object_path,
465 const gchar *interface_name,
466 const gchar *method_name,
467 GVariant *parameters,
468 GDBusMethodInvocation *context,
473 INFO("method %s", method_name);
477 if (g_strcmp0(method_name, "NewConnection") == 0) {
481 GUnixFDList *fd_list;
482 const gchar *object_path;
485 g_variant_get(parameters, "(oha{sv})",
486 &object_path, &index, &options);
488 msg = g_dbus_method_invocation_get_message(context);
489 fd_list = g_dbus_message_get_unix_fd_list(msg);
490 if (fd_list == NULL) {
491 ret = BT_HF_AGENT_ERROR_INVALID_FILE_DESCRIPTOR;
495 fd = g_unix_fd_list_get(fd_list, index, NULL);
497 ret = BT_HF_AGENT_ERROR_INVALID_FILE_DESCRIPTOR;
501 DBG("FD is = [%d], Object path = [%s]", fd, object_path);
503 if (!__bt_hf_agent_connection(fd, object_path)) {
504 ret = BT_HF_AGENT_ERROR_INTERNAL;
508 g_dbus_method_invocation_return_value(context, NULL);
509 } else if (g_strcmp0(method_name, "RequestDisconnection") == 0) {
510 if (!__bt_hf_agent_connection_release()) {
511 ret = BT_HF_AGENT_ERROR_INTERNAL;
514 INFO_C("Disconnected [HF role] [Terminated by local host]");
515 g_dbus_method_invocation_return_value(context, NULL);
516 } else if (g_strcmp0(method_name, "Release") == 0) {
517 if (!__bt_hf_agent_connection_release()) {
518 ret = BT_HF_AGENT_ERROR_INTERNAL;
522 g_dbus_method_invocation_return_value(context, NULL);
523 } else if (g_strcmp0(method_name, "AnswerCall") == 0) {
524 DBG("Going to call AnswerCall");
525 ret = _hf_agent_answer_call(context);
529 } else if (g_strcmp0(method_name, "TerminateCall") == 0) {
530 DBG("Going to call TerminateCall");
531 ret = _hf_agent_terminate_call(context);
535 } else if (g_strcmp0(method_name, "InitiateCall") == 0) {
536 char *phoneno = NULL;
538 g_variant_get(parameters, "(&s)", &phoneno);
540 DBG_SECURE("Going to call InitiateCall, Number is = [%s]\n", phoneno);
541 ret = _hf_agent_dial_no(NULL, phoneno);
545 g_dbus_method_invocation_return_value(context, NULL);
547 } else if (g_strcmp0(method_name, "VoiceRecognition") == 0) {
550 g_variant_get(parameters, "(i)", &status);
552 DBG("Going to call VoiceRecognition, Status [%d]", status);
553 ret = _hf_agent_voice_recognition(context, status);
557 } else if (g_strcmp0(method_name, "ScoConnect") == 0) {
558 DBG("Going to call ScoConnect");
559 if (!bt_hf_agent_sco_connect()) {
560 ret = BT_HF_AGENT_ERROR_INTERNAL;
564 g_dbus_method_invocation_return_value(context, NULL);
565 } else if (g_strcmp0(method_name, "ScoDisconnect") == 0) {
566 DBG("Going to call ScoDisconnect");
567 if (!bt_hf_agent_sco_disconnect()) {
568 ret = BT_HF_AGENT_ERROR_INTERNAL;
572 g_dbus_method_invocation_return_value(context, NULL);
573 } else if (g_strcmp0(method_name, "SpeakerGain") == 0) {
574 unsigned int gain = 0;
576 g_variant_get(parameters, "(u)", &gain);
578 DBG("Going to call SpeakerGain, gain is = [%d]\n", gain);
579 ret = _hf_agent_set_speaker_gain(context, gain);
583 } else if (g_strcmp0(method_name, "SendDtmf") == 0) {
586 g_variant_get(parameters, "(&s)", &dtmf);
588 DBG("Going to call SendDtmf, dtmf is = [%s]\n", dtmf);
589 ret = _hf_agent_send_dtmf(NULL, dtmf);
592 g_dbus_method_invocation_return_value(context, NULL);
594 } else if (g_strcmp0(method_name, "SendAtCmd") == 0) {
597 g_variant_get(parameters, "(&s)", &cmd);
599 DBG("Going to call SendAtCmd\n");
600 ret = bt_hf_agent_send_at_cmd(NULL, cmd);
603 g_dbus_method_invocation_return_value(context, NULL);
605 } else if (g_strcmp0(method_name, "ReleaseAndAccept") == 0) {
606 DBG("Going to call ReleaseAndAccept");
607 ret = _hf_agent_send_3way_cmd(context,
608 BT_HF_RELEASE_AND_ACCEPT);
612 } else if (g_strcmp0(method_name, "CallSwap") == 0) {
613 DBG("Going to call CallSwap");
614 ret = _hf_agent_send_3way_cmd(context,
615 BT_HF_ACCEPT_AND_HOLD);
619 } else if (g_strcmp0(method_name, "ReleaseAllCall") == 0) {
620 DBG("Going to call ReleaseAllCall");
621 ret = _hf_agent_send_3way_cmd(context, BT_HF_RELEASE_ALL);
625 } else if (g_strcmp0(method_name, "JoinCall") == 0) {
626 DBG("Going to call JoinCall");
627 ret = _hf_agent_send_3way_cmd(context, BT_HF_JOIN_CALL);
631 } else if (g_strcmp0(method_name, "GetCurrentCodec") == 0) {
632 DBG("Going to call GetCurrentCodec");
633 INFO("Current codec : %d", current_codec_id);
634 g_dbus_method_invocation_return_value(context,
635 g_variant_new("(i)", current_codec_id));
636 } else if (g_strcmp0(method_name, "RequestCallList") == 0) {
639 INFO("Going to call RequestCallList (send_flag[%d])", send_flag);
642 INFO("Send_flag is true. Try to send CLCC later");
643 clcc_retry_count = CLCC_RETRY_COUNT;
644 clcc_timer = g_timeout_add(CLCC_RETRY_TIMER, __clcc_timer_func, context);
646 call_var = bt_hf_agent_request_call_list();
648 ret = BT_HF_AGENT_ERROR_NOT_AVAILABLE;
651 g_dbus_method_invocation_return_value(context, call_var);
653 } else if (g_strcmp0(method_name, "RequestCallListAsync") == 0) {
654 INFO("Going to call RequestCallListAsync (send_flag[%d])", send_flag);
656 if (clcc_async_timer > 0) {
657 ret = BT_HF_AGENT_ERROR_NOT_AVAILABLE;
660 if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
661 ret = BT_HF_AGENT_ERROR_NOT_CONNECTED;
664 if (bt_hf_info.ciev_call_status == 0 &&
665 bt_hf_info.ciev_call_setup_status == 0) {
666 ret = BT_HF_AGENT_ERROR_NO_DATA;
671 INFO("Send_flag is true. Try to send CLCC later");
672 clcc_async_retry_count = CLCC_RETRY_COUNT;
673 clcc_async_timer = g_timeout_add(CLCC_RETRY_TIMER, __clcc_async_timer_func, context);
675 __bt_hf_agent_handle_call_list(&bt_hf_info);
676 g_dbus_method_invocation_return_value(context, NULL);
678 } else if (g_strcmp0(method_name, "GetAudioConnected") == 0) {
679 DBG("Going to call GetAudioConnected");
680 g_dbus_method_invocation_return_value(context,
681 g_variant_new("(i)", sco_audio_connected));
682 } else if (g_strcmp0(method_name, "IsHfConnected") == 0) {
683 DBG("Going to call IsHfConnected");
684 INFO("is_hf_connected : %s", is_hf_connected ? "Connected" : "Disconnected");
686 g_dbus_method_invocation_return_value(context,
687 g_variant_new("(b)", is_hf_connected));
688 } else if (g_strcmp0(method_name, "IsInbandRingtoneSupported") == 0) {
689 gboolean is_supported = FALSE;
691 if (is_hf_connected == FALSE) {
692 ret = BT_HF_AGENT_ERROR_NOT_CONNECTED;
696 if (bt_hf_info.inband_ringtone_support)
699 is_supported = FALSE;
701 INFO("IsInbandRingtoneSupported : %s", is_supported ?
702 "Supported" : "NotSupported");
703 g_dbus_method_invocation_return_value(context,
704 g_variant_new("(b)", is_supported));
711 err = __bt_hf_agent_set_error(ret);
712 g_dbus_method_invocation_return_gerror(context, err);
717 static const GDBusInterfaceVTable method_table = {
723 static GDBusNodeInfo *__bt_hf_create_method_node_info
724 (const gchar *introspection_data)
726 if (introspection_data == NULL)
729 return g_dbus_node_info_new_for_xml(introspection_data, NULL);
732 static GDBusConnection *__bt_hf_get_gdbus_connection(void)
734 GDBusConnection *local_system_gconn = NULL;
737 if (gdbus_conn == NULL) {
738 gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
741 ERR("Unable to connect to dbus: %s", err->message);
746 } else if (g_dbus_connection_is_closed(gdbus_conn)) {
747 local_system_gconn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
749 if (!local_system_gconn) {
750 ERR("Unable to connect to dbus: %s", err->message);
754 gdbus_conn = local_system_gconn;
760 static gboolean __bt_hf_register_profile_methods(void)
763 GError *error = NULL;
766 GDBusNodeInfo *node_info;
768 GDBusConnection *conn;
770 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
772 G_BUS_NAME_OWNER_FLAGS_NONE,
776 DBG("owner_id is [%d]", owner_id);
778 node_info = __bt_hf_create_method_node_info(
779 hf_agent_bluez_introspection_xml);
780 if (node_info == NULL)
783 path = g_strdup(BT_HF_BLUEZ_OBJECT_PATH);
784 DBG("path is [%s]", path);
786 conn = __bt_hf_get_gdbus_connection();
788 ERR("Unable to get connection");
793 object_id = g_dbus_connection_register_object(conn, path,
794 node_info->interfaces[0],
797 if (object_id == 0) {
798 ERR("Failed to register: %s", error->message);
800 g_dbus_node_info_unref(node_info);
805 g_dbus_node_info_unref(node_info);
807 node_info = __bt_hf_create_method_node_info(hf_agent_introspection_xml);
808 if (node_info == NULL)
811 path = g_strdup(BT_HF_AGENT_OBJECT_PATH);
812 DBG("path is [%s]", path);
814 object_id = g_dbus_connection_register_object(conn, path,
815 node_info->interfaces[0],
818 if (object_id == 0) {
820 ERR("Failed to register: %s", error->message);
823 g_dbus_node_info_unref(node_info);
828 g_dbus_node_info_unref(node_info);
834 static GDBusProxy *__bt_hf_gdbus_init_profile_proxy(void)
840 GDBusConnection *conn;
842 conn = __bt_hf_get_gdbus_connection();
844 ERR("Unable to get connection");
848 proxy = g_dbus_proxy_new_sync(conn,
849 G_DBUS_PROXY_FLAGS_NONE, NULL,
850 BLUEZ_SERVICE_NAME, "/org/bluez",
851 BLUEZ_PROFILE_MGMT_INTERFACE, NULL, &err);
855 ERR("Unable to create proxy: %s", err->message);
861 profile_gproxy = proxy;
867 static GDBusProxy *__bt_hf_gdbus_get_profile_proxy(void)
869 return (profile_gproxy) ? profile_gproxy :
870 __bt_hf_gdbus_init_profile_proxy();
873 static GDBusProxy *__bt_hf_gdbus_get_service_proxy(const gchar *service,
874 const gchar *path, const gchar *interface)
880 GDBusConnection *conn;
882 conn = __bt_hf_get_gdbus_connection();
884 ERR("Unable to get connection");
888 proxy = g_dbus_proxy_new_sync(conn,
889 G_DBUS_PROXY_FLAGS_NONE, NULL,
891 interface, NULL, &err);
895 ERR("Unable to create proxy: %s", err->message);
905 static char __bt_hf_agent_get_tx_power(char *address)
909 GError *error = NULL;
910 char result = READ_TX_POWER_MIN; /* default minimum */
912 proxy = __bt_hf_gdbus_get_service_proxy(BLUEZ_SERVICE_NAME, g_obj_path,
913 BLUEZ_HF_INTERFACE_NAME);
915 ERR("Proxy is NULL");
919 ret = g_dbus_proxy_call_sync(proxy,
920 "GetTxPowerLevel", g_variant_new("(s)", address),
921 G_DBUS_CALL_FLAGS_NONE, -1,
924 ERR("DBus is failed");
926 /* Dbus gives error cause */
927 ERR("D-Bus API failure: errCode[%x], message[%s]",
928 error->code, error->message);
929 g_clear_error(&error);
931 g_object_unref(proxy);
934 g_variant_get(ret, "(y)", &result);
935 DBG("TX power level = %d", result);
936 g_variant_unref(ret);
937 g_object_unref(proxy);
942 static int __bt_hf_agent_gdbus_method_send(const char *service,
943 GVariant *path, const char *interface,
950 GError *error = NULL;
952 proxy = __bt_hf_gdbus_get_service_proxy(service, g_obj_path, interface);
954 return BT_HF_AGENT_ERROR_INTERNAL;
956 ret = g_dbus_proxy_call_sync(proxy,
958 G_DBUS_CALL_FLAGS_NONE, -1,
961 /* dBUS-RPC is failed */
962 ERR("dBUS-RPC is failed");
964 /* dBUS gives error cause */
965 ERR("D-Bus API failure: errCode[%x], message[%s]",
966 error->code, error->message);
968 g_clear_error(&error);
970 g_object_unref(proxy);
971 return BT_HF_AGENT_ERROR_INTERNAL;
974 g_variant_unref(ret);
975 g_object_unref(proxy);
977 return BT_HF_AGENT_ERROR_NONE;
980 static void __bt_hf_agent_release_queue(void)
983 bt_hf_agent_send_at_info *cmd;
986 len = g_slist_length(bt_hf_info.cmd_send_queue);
987 for (i = 0; i < len; ++i) {
988 cmd = g_slist_nth_data(bt_hf_info.cmd_send_queue, i);
989 if (cmd && cmd->context) {
990 DBG("Pending context found for %.6s[%d]",
991 cmd->at_cmd, cmd->id);
992 err = __bt_hf_agent_set_error(BT_HF_AGENT_ERROR_INTERNAL);
993 g_dbus_method_invocation_return_gerror(cmd->context, err);
996 if (cmd && cmd->timer_id)
997 g_source_remove(cmd->timer_id);
999 g_slist_free(bt_hf_info.cmd_send_queue);
1000 bt_hf_info.cmd_send_queue = NULL;
1004 static gboolean __bt_hf_monitor_timer_cb(gpointer data)
1007 bt_hf_agent_send_at_info *cmd = data;
1008 ERR_C("Monitor timer came becuase of timeout for sendflag %d, %s",
1009 send_flag, cmd->at_cmd);
1010 /* In the case of ATD, we have to inform the remote to end the call */
1011 if (strstr(cmd->at_cmd, "ATD") || strstr(cmd->at_cmd, "BLDN")) {
1012 INFO_C("Sending CHUP for remote call termination");
1013 __bt_hf_send_only_without_queue(&bt_hf_info, BT_HF_END_CALL,
1014 strlen(BT_HF_END_CALL));
1015 /* Here there is a high posisbility that we do not get response
1016 * for CHUP. Hence we need to decrement send_flag to process further
1017 * incomming packets because we already incremented it in the CHUP case. */
1021 /* In the case of ATD, prev_cmd will be always ATD, because we will not
1022 * allow further commands. For safer side again set prev_cmd as ATD */
1023 strncpy(prev_cmd, "ATD\0", BT_HF_CMD_BUF_SIZE - 1);
1025 hf_handle_rx_at_cmd(&bt_hf_info, BT_HF_ERROR_RESP);
1033 gboolean __bt_hf_agent_add_queue(GDBusMethodInvocation *context, char *at,
1034 int count, gboolean pending_flag)
1036 int i, len, timer_id;
1037 if (bt_hf_info.slc == FALSE)
1040 DBG("Add Pending queue. (pending_flag is %s)",
1041 pending_flag ? "TRUE" : "FALSE");
1043 bt_hf_agent_send_at_info *cmd = g_new0(bt_hf_agent_send_at_info, 1);
1045 memcpy(cmd->at_cmd, at, count);
1047 cmd->context = context;
1048 cmd->pending = pending_flag;
1049 bt_hf_info.cmd_send_queue = g_slist_append(bt_hf_info.cmd_send_queue,
1051 len = g_slist_length(bt_hf_info.cmd_send_queue);
1052 for (i = 0; i < len; ++i) {
1053 cmd = g_slist_nth_data(bt_hf_info.cmd_send_queue, i);
1055 DBG("Q> %.6s[%d]", cmd->at_cmd, cmd->id);
1058 /* We need to have base timeout + tolerance value to process other request */
1059 if (strstr(at, "ATD") || strstr(at, "BLDN")) {
1060 /* Android 15 seconds timeout in case of ATD timeout in flight mode */
1061 timer_id = g_timeout_add_seconds(BT_HF_COMMAND_TIMEOUT * 5 + len,
1062 __bt_hf_monitor_timer_cb, cmd);
1064 cmd->timer_id = timer_id;
1066 timer_id = g_timeout_add_seconds(BT_HF_COMMAND_TIMEOUT + len,
1067 __bt_hf_monitor_timer_cb, cmd);
1069 cmd->timer_id = timer_id;
1075 Below methods exposed to Applicatoins
1077 static gboolean __bt_hf_agent_emit_signal(GDBusConnection *connection,
1078 const char *path, const char *interface,
1079 const char *signal_name, GVariant *param)
1081 GError *error = NULL;
1083 ret = g_dbus_connection_emit_signal(connection,
1085 interface, signal_name,
1088 if (error != NULL) {
1089 /* dBUS gives error cause */
1090 ERR("D-Bus API failure: errCode[%x], message[%s]",
1091 error->code, error->message);
1092 g_clear_error(&error);
1095 INFO_C("Emit Signal [%s]", signal_name);
1100 static gboolean __bt_hf_agent_emit_property_changed(
1101 GDBusConnection *connection,
1103 const char *interface,
1109 GError *error = NULL;
1111 ret = g_dbus_connection_emit_signal(connection,
1112 NULL, path, interface,
1114 g_variant_new("(sv)", name, property),
1117 if (error != NULL) {
1118 /* dBUS gives error cause */
1119 ERR("D-Bus API failure: errCode[%x], message[%s]",
1120 error->code, error->message);
1121 g_clear_error(&error);
1129 Below methods exposed to Bluez
1132 static gboolean __bt_hf_agent_launch_call_app(void)
1138 app_manager_is_running(CALL_ALIAS_APP_ID, &is_running);
1140 DBG("Call app is already started");
1144 b = bundle_create();
1146 ERR("bundle_create() Failed");
1150 bundle_add(b, "launch-type", "BT_LAUNCH");
1152 bundle_add(b, "carrier-type", "BT");
1153 DBG("For 3G, carrier-type: BT has been added");
1154 aul_launch_app_async(CALL_ALIAS_APP_ID, b);
1157 INFO("-aul_launch_app_async -");
1162 static void __bt_hf_agent_handle_ind_change(bt_hf_agent_info_t *bt_hf_info,
1163 guint index, gint value)
1165 GDBusConnection *conn;
1167 struct indicator *ind = g_slist_nth_data(bt_hf_info->indies, index - 1);
1169 ERR("Indicator is NULL");
1176 conn = __bt_hf_get_gdbus_connection();
1178 ERR("Unable to get connection");
1182 INFO("Indicator name is %s, value = [%d]", name, value);
1183 if (!strcmp(name, "\"call\"")) {
1184 bt_hf_info->ciev_call_status = value;
1186 __bt_hf_agent_emit_signal(conn,
1187 BT_HF_AGENT_OBJECT_PATH,
1188 BT_HF_SERVICE_INTERFACE,
1189 "CallStarted", NULL);
1190 bt_hf_info->is_dialing = FALSE;
1191 bt_hf_info->call_active = TRUE;
1192 } else if (bt_hf_info->call_active) {
1193 __bt_hf_agent_emit_signal(conn,
1194 BT_HF_AGENT_OBJECT_PATH,
1195 BT_HF_SERVICE_INTERFACE,
1197 bt_hf_info->call_active = FALSE;
1199 if (bt_hf_info->ciev_call_setup_status == 0) {
1200 __bt_hf_agent_emit_signal(gdbus_conn,
1201 BT_HF_AGENT_OBJECT_PATH,
1202 BT_HF_SERVICE_INTERFACE,
1207 } else if (!strcmp(name, "\"callsetup\"")) {
1208 bt_hf_info->ciev_call_setup_status = value;
1209 if (value == 0 && bt_hf_info->is_dialing) {
1210 bt_hf_info->is_dialing = FALSE;
1211 __bt_hf_agent_emit_signal(conn,
1212 BT_HF_AGENT_OBJECT_PATH,
1213 BT_HF_SERVICE_INTERFACE,
1216 } else if (!bt_hf_info->is_dialing && value > 0) {
1217 bt_hf_info->is_dialing = TRUE;
1220 if (bt_hf_info->ciev_call_setup_status == 1) {
1221 __bt_hf_agent_emit_signal(gdbus_conn,
1222 BT_HF_AGENT_OBJECT_PATH,
1223 BT_HF_SERVICE_INTERFACE,
1224 "CallSetupIncoming", NULL);
1225 if (__bt_hf_agent_launch_call_app() == FALSE)
1226 DBG("call app launching failed");
1227 } else if (bt_hf_info->ciev_call_setup_status == 2) {
1228 __bt_hf_agent_emit_signal(gdbus_conn,
1229 BT_HF_AGENT_OBJECT_PATH,
1230 BT_HF_SERVICE_INTERFACE,
1231 "CallSetupDialing", NULL);
1232 } else if (bt_hf_info->ciev_call_setup_status == 3) {
1233 __bt_hf_agent_emit_signal(gdbus_conn,
1234 BT_HF_AGENT_OBJECT_PATH,
1235 BT_HF_SERVICE_INTERFACE,
1236 "CallSetupAlerting", NULL);
1237 } else if (bt_hf_info->ciev_call_status == 0 &&
1238 bt_hf_info->ciev_call_setup_status == 0) {
1239 __bt_hf_agent_emit_signal(gdbus_conn,
1240 BT_HF_AGENT_OBJECT_PATH,
1241 BT_HF_SERVICE_INTERFACE,
1244 } else if (!strcmp(name, "\"callheld\"")) {
1245 if (value == 0) { /* No calls held*/
1246 __bt_hf_agent_emit_signal(conn,
1247 BT_HF_AGENT_OBJECT_PATH,
1248 BT_HF_SERVICE_INTERFACE,
1251 } else if (value == 1) {
1252 /*Call is placed on hold or active/held calls swapped */
1253 __bt_hf_agent_emit_signal(conn,
1254 BT_HF_AGENT_OBJECT_PATH,
1255 BT_HF_SERVICE_INTERFACE,
1256 "CallsSwapped", NULL);
1258 /*Call on hold, no active call*/
1259 __bt_hf_agent_emit_signal(conn,
1260 BT_HF_AGENT_OBJECT_PATH,
1261 BT_HF_SERVICE_INTERFACE,
1262 "CallOnHold", NULL);
1264 } else if (!strcmp(name, "\"service\"")) {
1265 if (value < 0 || value > 1)
1266 ERR("Out of range");
1268 __bt_hf_agent_emit_property_changed(conn,
1269 BT_HF_AGENT_OBJECT_PATH,
1270 BT_HF_SERVICE_INTERFACE,
1271 "RegistrationStatus",
1272 g_variant_new("q", value));
1273 } else if (!strcmp(name, "\"signal\"")) {
1274 if (value < 0 || value > 5)
1275 ERR("Out of range");
1277 __bt_hf_agent_emit_property_changed(conn,
1278 BT_HF_AGENT_OBJECT_PATH,
1279 BT_HF_SERVICE_INTERFACE, "SignalStrength",
1280 g_variant_new("q", value));
1281 } else if (!strcmp(name, "\"roam\"")) {
1282 if (value < 0 || value > 1)
1283 ERR("Out of range");
1285 __bt_hf_agent_emit_property_changed(conn,
1286 BT_HF_AGENT_OBJECT_PATH,
1287 BT_HF_SERVICE_INTERFACE, "RoamingStatus",
1288 g_variant_new("q", value));
1289 } else if (!strcmp(name, "\"battchg\"")) {
1290 if (value < 0 || value > 5)
1291 ERR("Out of range");
1293 __bt_hf_agent_emit_property_changed(conn,
1294 BT_HF_AGENT_OBJECT_PATH,
1295 BT_HF_SERVICE_INTERFACE, "BatteryCharge",
1296 g_variant_new("q", value));
1300 static void __bt_hf_agent_handle_voice_activation(gint value)
1302 GDBusConnection *conn;
1304 conn = __bt_hf_get_gdbus_connection();
1306 ERR("Unable to get connection");
1310 __bt_hf_agent_emit_signal(conn, BT_HF_AGENT_OBJECT_PATH,
1311 BT_HF_SERVICE_INTERFACE,
1313 g_variant_new("(i)", value));
1318 static void __bt_hf_agent_handle_speaker_gain(gint value)
1320 GDBusConnection *conn;
1322 conn = __bt_hf_get_gdbus_connection();
1324 ERR("Unable to get connection");
1328 __bt_hf_agent_emit_signal(conn, BT_HF_AGENT_OBJECT_PATH,
1329 BT_HF_SERVICE_INTERFACE, "VolumeSpeaker",
1330 g_variant_new("(i)", value));
1335 static int __bt_hf_agent_handle_clip(bt_hf_agent_info_t *bt_hf_info,
1338 GDBusConnection *conn;
1340 gchar number[BT_HF_CALLER_NUM_SIZE];
1342 char fmt_str[BT_HF_FMT_STR_SIZE];
1343 int len = strlen(buf);
1345 DBG("__bt_hf_agent_handle_clip +");
1346 if (len > BT_HF_CALLER_NUM_SIZE + 10) {
1347 ERR("buf len %d is too long", len);
1351 if ((clip = strstr(buf, "\r\n+CLIP"))) {
1352 snprintf(fmt_str, sizeof(fmt_str), "\r\n+CLIP: \"%%%ds", (int)(sizeof(number) - 1));
1353 if (sscanf(clip, fmt_str, number) == 1) {
1354 sep = strchr(number, '"');
1359 conn = __bt_hf_get_gdbus_connection();
1361 ERR("Unable to get connection");
1365 __bt_hf_agent_emit_signal(conn,
1366 BT_HF_AGENT_OBJECT_PATH,
1367 BT_HF_SERVICE_INTERFACE, "Ring",
1368 g_variant_new("(s)", clip));
1370 ERR_SECURE("CLIP '%s' is Call Incoming", buf);
1374 DBG("__bt_hf_agent_handle_clip -");
1378 static int __bt_hf_agent_handle_ccwa(bt_hf_agent_info_t *bt_hf_info,
1381 GDBusConnection *conn;
1383 gchar number[BT_HF_CALLER_NUM_SIZE];
1385 char fmt_str[BT_HF_FMT_STR_SIZE];
1386 int len = strlen(buf);
1388 DBG("__bt_hf_agent_handle_ccwa +");
1389 if (len > BT_HF_CALLER_NUM_SIZE + 10) {
1390 ERR("buf len %d is too long", len);
1394 if ((ccwa = strstr(buf, "\r\n+CCWA"))) {
1395 snprintf(fmt_str, sizeof(fmt_str), "\r\n+CCWA: \"%%%ds",
1396 (int)(sizeof(number) - 1));
1397 if (sscanf(ccwa, fmt_str, number) == 1) {
1398 sep = strchr(number, '"');
1403 conn = __bt_hf_get_gdbus_connection();
1405 ERR("Unable to get connection");
1409 __bt_hf_agent_emit_signal(conn,
1410 BT_HF_AGENT_OBJECT_PATH,
1411 BT_HF_SERVICE_INTERFACE, "CallWaiting",
1412 g_variant_new("(s)", ccwa));
1414 ERR_SECURE("CCWA '%s' is Call Wating", buf);
1418 DBG("__bt_hf_agent_handle_ccwa -");
1422 static void __bt_hf_agent_handle_bsir(bt_hf_agent_info_t *bt_hf_info,
1425 INFO("new value : %d", value);
1428 bt_hf_info->inband_ringtone_support = TRUE;
1430 bt_hf_info->inband_ringtone_support = FALSE;
1435 static GSList *__bt_hf_prepare_call_list(const char *buf)
1437 GSList *call_list = NULL;
1442 char delim_sep[] = "\r\n";
1443 char temp_buf[BT_HF_DATA_BUF_SIZE] = {0,};
1445 hf_call_list_info_t *call_info;
1448 strncpy(temp_buf, buf, BT_HF_DATA_BUF_SIZE - 1);
1450 str = strtok_r(temp_buf, delim_sep, &sp);
1451 while (str != NULL) {
1452 if (!(strstr(str, "+CLCC:"))) {
1453 str = strtok_r(NULL, delim_sep, &sp);
1457 call_info = g_new0(hf_call_list_info_t, 1);
1459 sscanf(str, "+CLCC: %1d,%1d, %1d, %1d, %1d",
1460 &call_info->idx, &call_info->dir,
1461 &call_info->status, &call_info->mode,
1462 &call_info->multi_party);
1463 DBG("Index = [%d], Direction = [%d], Status = [%d], Mode = [%d], Multi_party = [%d]\n",
1464 call_info->idx, call_info->dir, call_info->status,
1465 call_info->mode, call_info->multi_party);
1467 ptr = strstr(str, "\"");
1469 temp = strstr(ptr + 1, "\"");
1472 DBG_SECURE("\tPhone Number = [%s]\n", ptr + 1);
1473 call_info->number = g_strdup(ptr + 1);
1475 if (strstr(temp + 1, ",")) {
1477 DBG("\tType = [%s]\n", temp);
1478 call_info->type = atoi(temp);
1482 /*In case of no phone no. in CLCC respnse, we should launch call application
1483 * with NULL string. By doing so "unknown" shall be displayed*/
1484 DBG("Phone number does not exist\n");
1485 call_info->number = g_strdup("");
1488 call_list = g_slist_append(call_list, call_info);
1489 str = strtok_r(NULL, delim_sep, &sp);
1495 static GSList *__bt_hf_get_call_list(bt_hf_agent_info_t *bt_hf_info)
1497 char buf[BT_HF_DATA_BUF_SIZE] = {0,};
1498 GSList *call_list = NULL;
1502 /* Send CLCC when the callsetup */
1503 __bt_hf_send_and_read(bt_hf_info, BT_HF_CALLLIST, buf,
1504 sizeof(BT_HF_CALLLIST) - 1);
1505 DBG_SECURE("Receive CLCC response buffer = '%s'", buf);
1507 call_list = __bt_hf_prepare_call_list(buf);
1512 static void __bt_hf_call_info_free(void *data)
1516 hf_call_list_info_t *call_info = data;
1517 g_free(call_info->number);
1523 static void __bt_hf_free_call_list(GSList *call_list)
1527 g_slist_free_full(call_list, __bt_hf_call_info_free);
1532 static void __bt_hf_launch_call_using_call_list(GSList *call_list)
1537 if (call_list == NULL)
1540 len = g_slist_length(call_list);
1542 if (len > 0 && __bt_hf_agent_launch_call_app() == FALSE)
1543 DBG("call app launching failed");
1548 static GVariant *__bt_hf_agent_get_call_status_info(GSList *call_list)
1554 hf_call_list_info_t *call_info;
1556 GVariantBuilder *builder;
1559 builder = g_variant_builder_new(G_VARIANT_TYPE("a(siiii)"));
1561 call_count = g_slist_length(call_list);
1562 DBG("Total call count = '%d'", call_count);
1564 while (call_count--) {
1565 call_info = g_slist_nth_data(call_list, call_count);
1567 INFO("Idx=%d, Dir=%d, status=%d, mode=%d, mparty=%d",
1568 call_info->idx, call_info->dir, call_info->status,
1569 call_info->mode, call_info->multi_party);
1570 caller = call_info->number;
1572 g_variant_builder_add(builder, "(siiii)",
1573 caller, call_info->dir, call_info->status,
1574 call_info->multi_party, call_info->idx);
1577 var_data = g_variant_new("(ia(siiii))",
1578 g_slist_length(call_list), builder);
1580 g_variant_builder_unref(builder);
1585 static void __bt_hf_clear_prev_sent_cmd(void)
1587 if (prev_cmd[0] != 0)
1588 ERR("No sent command");
1590 memset(prev_cmd, 0, BT_HF_CMD_BUF_SIZE);
1595 static void __bt_hf_agent_send_call_status_info(GSList *call_list)
1597 GDBusConnection *conn;
1600 conn = __bt_hf_get_gdbus_connection();
1602 ERR("Unable to get connection");
1604 var_data = __bt_hf_agent_get_call_status_info(call_list);
1605 __bt_hf_agent_emit_signal(conn,
1606 BT_HF_AGENT_OBJECT_PATH,
1607 BT_HF_SERVICE_INTERFACE,
1613 static void __bt_hf_agent_handle_call_list(bt_hf_agent_info_t *bt_hf_info)
1617 __bt_hf_lock_display(0);
1619 bt_hf_info->context = NULL;
1621 /* Send CLCC. The response will be handled in the handler */
1622 ret = __bt_hf_send_only(bt_hf_info, BT_HF_CALLLIST,
1623 sizeof(BT_HF_CALLLIST) - 1);
1625 ERR("Failed to send CLCC");
1627 __bt_hf_unlock_display();
1630 static gboolean __bt_hf_send_available_codec(bt_hf_agent_info_t *bt_hf_info, int send_only)
1632 gchar buf[BT_HF_DATA_BUF_SIZE];
1633 gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
1636 snprintf(cmd_buf, sizeof(cmd_buf), BT_HF_AVAILABLE_CODEC,
1637 BT_HF_CODEC_ID_CVSD, BT_HF_CODEC_ID_MSBC);
1639 bt_hf_info->context = NULL;
1641 ret = __bt_hf_send_only(bt_hf_info, cmd_buf, strlen(cmd_buf));
1644 ret = __bt_hf_send_and_read(bt_hf_info, cmd_buf, buf,
1647 if (!ret || !strstr(buf, "OK"))
1653 static int _hf_agent_codec_setup(const char *addr, guint codec_id)
1658 ERR("g_obj_path is NULL\n");
1659 return BT_HF_AGENT_ERROR_INTERNAL;
1663 case BT_HF_CODEC_ID_CVSD:
1664 INFO("Set NB parameters");
1665 ret = __bt_hf_agent_gdbus_method_send(BLUEZ_SERVICE_NAME,
1666 g_variant_new("(ss)", "Handsfree", addr),
1667 BT_ADAPTER_INTERFACE,
1670 case BT_HF_CODEC_ID_MSBC:
1671 INFO("Set WBS parameters");
1672 ret = __bt_hf_agent_gdbus_method_send(BLUEZ_SERVICE_NAME,
1673 g_variant_new("(ss)", "Handsfree", addr),
1674 BT_ADAPTER_INTERFACE,
1675 "SetWbsParameters");
1678 ret = BT_HF_AGENT_ERROR_INTERNAL;
1679 ERR("Invalid Codec\n");
1684 ERR("Failed to setup the Codec\n");
1686 current_codec_id = codec_id;
1691 static void __bt_hf_agent_handle_codec_select(bt_hf_agent_info_t *bt_hf_info,
1694 gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
1698 if (codec_id != BT_HF_CODEC_ID_CVSD && codec_id != BT_HF_CODEC_ID_MSBC) {
1699 INFO("Codec id doesn't match, so send available codec again");
1700 ret = __bt_hf_send_available_codec(bt_hf_info, 1);
1702 ERR("Failed to send avalable codec");
1706 /* HF should be ready accpet SCO connection before sending theresponse for
1707 "\r\n+BCS=>Codec ID\r\n", Keep the BT chip ready to recevie encoded SCO data */
1708 retval = _hf_agent_codec_setup(bt_hf_info->remote_addr, codec_id);
1710 ERR("_hf_agent_codec_setup : Failed [%d]", retval);
1713 snprintf(cmd_buf, sizeof(cmd_buf), BT_HF_CODEC_SELECT, codec_id);
1715 bt_hf_info->context = NULL;
1716 ret = __bt_hf_send_only(bt_hf_info, cmd_buf, strlen(cmd_buf));
1718 ERR("__bt_hf_send_only : FALSE");
1722 static int __bt_hf_agent_handler_ciev(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1724 gchar indicator[BT_HF_INDICATOR_DESCR_SIZE + 4];
1728 char fmt_str[BT_HF_FMT_STR_SIZE];
1730 DBG("++++++++ __bt_hf_agent_handler_ciev +++++++++");
1732 snprintf(fmt_str, sizeof(fmt_str), "\r\n+CIEV:%%%ds\r\n",
1733 BT_HF_INDICATOR_DESCR_SIZE + 4 - 1);
1734 if (sscanf(buf, fmt_str, indicator) == 1) {
1735 sep = strchr(indicator, ',');
1738 index = atoi(indicator);
1740 __bt_hf_agent_handle_ind_change(bt_hf_info, index, value);
1742 DBG("--------- __bt_hf_agent_handler_ciev ------------");
1746 static void __bt_hf_agent_handle_ven_samsung(bt_hf_agent_info_t *bt_hf_info,
1747 gint app_id, const char *msg)
1749 /* Whomesoever wants need to handle it */
1750 char *sig_name = "SamsungXSAT";
1751 GDBusConnection *conn;
1753 conn = __bt_hf_get_gdbus_connection();
1755 ERR("Unable to get connection");
1759 __bt_hf_agent_emit_signal(conn,
1760 BT_HF_AGENT_OBJECT_PATH,
1761 BT_HF_SERVICE_INTERFACE,
1763 g_variant_new("(is)", app_id, msg));
1766 static int __bt_hf_agent_handler_ring(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1768 DBG("++++++++ __bt_hf_agent_handler_ring ++++++++");
1769 DBG("---------__bt_hf_agent_handler_ring --------");
1774 static int __bt_hf_agent_handler_clip(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1776 DBG("+++++++++ __bt_hf_agent_handler_clip ++++++++");
1777 __bt_hf_agent_handle_clip(bt_hf_info, buf);
1778 DBG("---------__bt_hf_agent_handler_clip --------");
1783 static int __bt_hf_agent_handler_bvra(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1785 DBG("+++++++++ __bt_hf_agent_handler_bvra +++++++++");
1787 if (sscanf(buf, "\r\n+BVRA:%1d\r\n", &value) == 1)
1788 __bt_hf_agent_handle_voice_activation(value);
1790 DBG("---------__bt_hf_agent_handler_bvra --------");
1794 static int __bt_hf_agent_handler_bcs(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1797 DBG("+++++++++ __bt_hf_agent_handler_bcs +++++++++-");
1798 if (sscanf(buf, "\r\n+BCS:%3d\r\n", &codec_id))
1799 __bt_hf_agent_handle_codec_select(bt_hf_info, codec_id);
1801 DBG("---------__bt_hf_agent_handler_bcs --------");
1805 static int __bt_hf_agent_handler_vgs(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1809 DBG("+++++++++ __bt_hf_agent_handler_vgs +++++++++");
1811 ret = sscanf(buf, "\r\n+VGS:%2d\r\n", &value);
1812 else if (buf[6] == '=')
1813 ret = sscanf(buf, "\r\n+VGS=%2d\r\n", &value);
1815 __bt_hf_agent_handle_speaker_gain(value);
1817 DBG("---------__bt_hf_agent_handler_vgs --------");
1822 static int __bt_hf_agent_handler_ccwa(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1824 DBG("+++++++++ __bt_hf_agent_handler_ccwa ++++++++");
1825 __bt_hf_agent_handle_ccwa(bt_hf_info, buf);
1826 DBG("---------__bt_hf_agent_handler_ccwa --------");
1832 static int __bt_hf_agent_handler_xsat(bt_hf_agent_info_t *bt_hf_info,
1836 char msg[BT_HF_DATA_BUF_SIZE];
1837 char fmt_str[BT_HF_CMD_BUF_SIZE];
1839 DBG("+++++++++ __bt_hf_agent_handler_xsat +++++++++");
1840 snprintf(fmt_str, sizeof(fmt_str), "\r\n+XSAT:%%d,%%%ds\r\n",
1841 (int)(sizeof(msg) - 1));
1842 if (sscanf(buf, fmt_str, &app_id, msg)) {
1843 if (app_id == 2 && strstr(msg, "READTXPOWER")) {
1844 char cmd_buf[BT_HF_CMD_BUF_SIZE * 2] = {0, };
1845 char power = __bt_hf_agent_get_tx_power(bt_hf_info->remote_addr);
1846 snprintf(cmd_buf, sizeof(cmd_buf), "AT+XSAT: 2,%d", power);
1847 bt_hf_agent_send_at_cmd(NULL, cmd_buf);
1849 __bt_hf_agent_handle_ven_samsung(bt_hf_info, app_id, msg);
1853 DBG("---------__bt_hf_agent_handler_xsat --------");
1858 static int __bt_hf_agent_handler_bsir(bt_hf_agent_info_t *bt_hf_info, const char *buf)
1860 DBG("+++++++++ __bt_hf_agent_handler_bsir +++++++++");
1862 if (sscanf(buf, "\r\n+BSIR:%1d\r\n", &value) == 1)
1863 __bt_hf_agent_handle_bsir(bt_hf_info, value);
1865 DBG("---------__bt_hf_agent_handler_bsir --------");
1869 static int __bt_hf_agent_handler_cme_error(bt_hf_agent_info_t *bt_hf_info,
1872 DBG("+++++++++ __bt_hf_agent_handler_cme_error ++++++++");
1874 GDBusConnection *conn;
1876 if (strstr(prev_cmd, "ATD") || strstr(prev_cmd, BT_HF_REDIAL)) {
1877 conn = __bt_hf_get_gdbus_connection();
1879 ERR("Unable to get connection");
1883 __bt_hf_agent_emit_signal(conn,
1884 BT_HF_AGENT_OBJECT_PATH,
1885 BT_HF_SERVICE_INTERFACE,
1890 __bt_hf_clear_prev_sent_cmd();
1895 static int __bt_hf_agent_handler_response_ok(bt_hf_agent_info_t *bt_hf_info,
1898 DBG("+++++++++ __bt_hf_agent_handler_response_ok ++++++++");
1900 __bt_hf_clear_prev_sent_cmd();
1905 static int __bt_hf_agent_handler_response_err(bt_hf_agent_info_t *bt_hf_info,
1908 DBG("+++++++++ __bt_hf_agent_handler_response_err ++++++++");
1909 GDBusConnection *conn;
1911 if (strstr(prev_cmd, "ATD") || strstr(prev_cmd, BT_HF_REDIAL)) {
1912 conn = __bt_hf_get_gdbus_connection();
1914 ERR("Unable to get connection");
1918 __bt_hf_agent_emit_signal(conn, BT_HF_AGENT_OBJECT_PATH,
1919 BT_HF_SERVICE_INTERFACE,
1923 __bt_hf_clear_prev_sent_cmd();
1928 static int __bt_hf_agent_handler_response_serr(bt_hf_agent_info_t *bt_hf_info,
1932 GDBusConnection *conn;
1934 if (strstr(prev_cmd, "ATD") || strstr(prev_cmd, BT_HF_REDIAL)) {
1935 conn = __bt_hf_get_gdbus_connection();
1937 ERR("Unable to get connection");
1941 __bt_hf_agent_emit_signal(conn, BT_HF_AGENT_OBJECT_PATH,
1942 BT_HF_SERVICE_INTERFACE,
1947 __bt_hf_clear_prev_sent_cmd();
1953 static int __bt_hf_agent_handler_clcc(bt_hf_agent_info_t *bt_hf_info, const char *buffer)
1956 GSList *call_list = NULL;
1957 DBG("+++++++++ __bt_hf_agent_handler_clcc ++++++++");
1958 DBG_SECURE("Receive CLCC response buffer = '%s'", buffer);
1960 __bt_hf_lock_display(0);
1962 call_list = __bt_hf_prepare_call_list(buffer);
1964 if (call_list == NULL)
1967 __bt_hf_launch_call_using_call_list(call_list);
1969 __bt_hf_agent_send_call_status_info(call_list);
1971 __bt_hf_free_call_list(call_list);
1974 __bt_hf_unlock_display();
1975 DBG("---------__bt_hf_agent_handler_clcc --------");
1979 static bt_hf_event hf_event_callbacks[] = {
1980 { "\r\n+CIEV:", __bt_hf_agent_handler_ciev },
1981 { "\r\nRING", __bt_hf_agent_handler_ring },
1982 { "\r\n+CLIP:", __bt_hf_agent_handler_clip },
1983 { "\r\n+BVRA:", __bt_hf_agent_handler_bvra },
1984 { "\r\n+BCS:", __bt_hf_agent_handler_bcs },
1985 { "\r\n+VGS", __bt_hf_agent_handler_vgs },
1986 { "\r\n+CCWA:", __bt_hf_agent_handler_ccwa },
1987 { "\r\n+XSAT:", __bt_hf_agent_handler_xsat },
1988 {"\r\n+CLCC:", __bt_hf_agent_handler_clcc },
1989 {"\r\n+BSIR:", __bt_hf_agent_handler_bsir },
1993 static bt_hf_event hf_event_resp_callbacks[] = {
1994 { "\r\n+CME ERROR:", __bt_hf_agent_handler_cme_error },
1995 { "\r\nOK\r\n", __bt_hf_agent_handler_response_ok },
1996 { "ERROR", __bt_hf_agent_handler_response_err },
1997 { "SERR", __bt_hf_agent_handler_response_serr },
2001 bt_hf_agent_send_at_info *__bt_hf_agent_find_next(bt_hf_agent_info_t *bt_hf_info)
2005 bt_hf_agent_send_at_info *cmd;
2006 len = g_slist_length(bt_hf_info->cmd_send_queue);
2007 for (i = 0; i < len; ++i) {
2008 cmd = g_slist_nth_data(bt_hf_info->cmd_send_queue, i);
2010 DBG("F> %.6s[%d]", cmd->at_cmd, cmd->id);
2012 len = g_slist_length(bt_hf_info->cmd_send_queue);
2013 DBG("Context queue length = %d", len);
2017 cmd = g_slist_nth_data(bt_hf_info->cmd_send_queue, 0);
2019 bt_hf_info->cmd_send_queue = g_slist_remove(bt_hf_info->cmd_send_queue, cmd);
2020 DBG("NEXT[%d] Found %s, context = 0x%x, pending = %d", cmd->id,
2021 cmd->at_cmd, cmd->context, cmd->pending);
2025 DBG("**** Not found any pending command on list length %d ****", len);
2030 static int hf_handle_rx_at_cmd(bt_hf_agent_info_t *bt_hf_info, const char *buf)
2034 bt_hf_agent_send_at_info *cmd = NULL;
2036 __bt_hf_agent_print_at_buffer("Processing [Rx cmd]:", buf);
2038 for (ev = hf_event_resp_callbacks; ev->cmd; ev++) {
2039 if (strstr(buf, ev->cmd)) {
2042 DBG("Send flag value = %d(after)", send_flag);
2043 ret = ev->callback(bt_hf_info, buf);
2050 for (ev = hf_event_callbacks; ev->cmd; ev++) {
2051 if (!strncmp(buf, ev->cmd, strlen(ev->cmd))) {
2052 ret = ev->callback(bt_hf_info, buf);
2060 cmd = __bt_hf_agent_find_next(bt_hf_info);
2062 if (cmd && cmd->context) {
2063 DBG("Pending context found for %.6s[%d]", cmd->at_cmd, cmd->id);
2064 g_dbus_method_invocation_return_value(cmd->context, NULL);
2066 g_source_remove(cmd->timer_id);
2072 cmd = __bt_hf_agent_find_next(bt_hf_info);
2074 if (cmd && cmd->pending && send_flag == 0) {
2075 DBG("Pending only found of %.6s[%d]", cmd->at_cmd, cmd->id);
2076 __bt_hf_send_only_without_queue(bt_hf_info,
2077 cmd->at_cmd, cmd->count);
2078 cmd->pending = FALSE;
2079 bt_hf_info->cmd_send_queue = g_slist_prepend(bt_hf_info->cmd_send_queue,
2081 DBG("Prepend %.6s[%d]", cmd->at_cmd, cmd->id);
2084 DBG("Pending free for %.6s[%d] - send_flag = %d",
2085 cmd->at_cmd, cmd->id, send_flag);
2087 g_source_remove(cmd->timer_id);
2093 /* Need to process further pending */
2094 cmd = __bt_hf_agent_find_next(bt_hf_info);
2096 if (cmd->pending && send_flag == 0) {
2097 DBG("2nd Pending only found of %.6s[%d]",
2098 cmd->at_cmd, cmd->id);
2099 __bt_hf_send_only_without_queue(bt_hf_info,
2100 cmd->at_cmd, cmd->count);
2101 cmd->pending = FALSE;
2103 bt_hf_info->cmd_send_queue = g_slist_prepend(bt_hf_info->cmd_send_queue,
2105 DBG("2nd Prepend %.6s[%d]", cmd->at_cmd, cmd->id);
2111 static int hf_handle_append_clcc_buff(char *cmd_buf, const char *buf)
2115 int cmd_buf_len = 0;
2116 char *pos_start, *pos_end;
2117 const char *datap = buf;
2119 cmd_buf_len = strlen(cmd_buf);
2120 buf_length = strlen(buf);
2121 DBG("buf_length = %d, cmd_buf_len = %d", buf_length, cmd_buf_len);
2123 if (buf_length > 0 && strstr(datap, "+CLCC")) {
2124 pos_start = strstr(datap, "\r\n");
2125 if (pos_start == NULL) {
2126 ERR("Invalid AT command signature..\n");
2130 pos_end = g_strrstr(datap, "+CLCC");
2131 if (pos_end == NULL) {
2132 ERR("Invalid AT command signature..\n");
2135 pos_end = strstr(pos_end, "\r\n");
2136 cmd_length = (pos_end - pos_start) + 2;
2137 INFO("CLCC balance Cmd Length = %d\n", cmd_length);
2138 memcpy(cmd_buf + cmd_buf_len, pos_start, cmd_length);
2139 cmd_buf[cmd_buf_len + cmd_length] = '\0';
2141 if (strstr(cmd_buf, "\r\nOK\r\n")) {
2142 pos_end = strstr(datap, "\r\nOK\r\n");
2143 cmd_length = (pos_end - pos_start);
2144 memcpy(cmd_buf + cmd_buf_len, pos_start, cmd_length);
2145 cmd_buf[cmd_buf_len + cmd_length] = '\0';
2146 INFO("New CLCC balance Cmd Length = %d", cmd_length);
2153 static int hf_handle_rx_at_buff(bt_hf_agent_info_t *bt_hf_info, const char *buf)
2157 char *pos_start, *pos_end;
2159 gchar cmd_buf[BT_HF_DATA_BUF_SIZE] = {0,};
2160 const char *datap = buf;
2162 __bt_hf_agent_print_at_buffer("[HF AT CMD] Recv >>>>>:", buf);
2164 buf_length = strlen(buf);
2166 while (buf_length > 0) {
2167 pos_start = strstr(datap, "\r\n");
2168 if (pos_start == NULL) {
2169 ERR("Invalid AT command start signature..\n");
2174 pos_end = strstr(datap, "\r\n");
2175 if (pos_end == NULL) {
2176 ERR("Invalid AT command end signature..\n");
2179 cmd_length = (pos_end - pos_start) + 2;
2180 DBG("Cmd Length = %d\n", cmd_length);
2182 if (cmd_length > BT_HF_DATA_BUF_SIZE - 1)
2184 memcpy(cmd_buf, pos_start, cmd_length);
2185 cmd_buf[cmd_length] = '\0';
2187 buf_length = buf_length - cmd_length;
2188 datap = datap + cmd_length - 2;
2190 /* We need to pass all the CLCC's together to its handler */
2191 if (strstr(cmd_buf, "+CLCC")) {
2192 tmp = hf_handle_append_clcc_buff(cmd_buf, datap);
2194 buf_length = buf_length - tmp;
2196 hf_handle_rx_at_cmd(bt_hf_info, cmd_buf);
2197 DBG("Pending buf_length = %d\n", buf_length);
2202 static gboolean __bt_hf_agent_data_cb(GIOChannel *chan, GIOCondition cond,
2203 bt_hf_agent_info_t *bt_hf_info)
2205 gchar buf[BT_HF_DATA_BUF_SIZE] = {0,};
2207 GError *gerr = NULL;
2208 gboolean recvd_ok = FALSE;
2209 gboolean recvd_error = FALSE;
2210 gboolean recvd_sec_error = FALSE;
2212 if (cond & (G_IO_ERR | G_IO_HUP)) {
2213 ERR("ERR or HUP on RFCOMM socket");
2214 INFO_C("### Disconnected [HF role] [Terminated by remote dev]");
2215 is_hf_connected = FALSE;
2216 bt_hf_info->slc = FALSE;
2217 __bt_hf_agent_release();
2221 if (g_io_channel_read_chars(chan, buf, sizeof(buf) - 1, &read, &gerr)
2222 != G_IO_STATUS_NORMAL) {
2224 ERR("Read failed, cond = [%d], Err msg = [%s]",
2225 cond, gerr->message);
2231 recvd_ok = NULL != strstr(buf, BT_HF_OK_RESPONSE);
2232 recvd_error = NULL != strstr(buf, BT_HF_ERROR_RESPONSE);
2233 recvd_sec_error = NULL != strstr(buf, BT_HF_SEC_ERROR_RESPONSE);
2234 DBG("<-------Received data --send flag status = %d ----->", send_flag);
2236 /* Once service level connection is established we need to handle
2237 * all the intermediate AT commands */
2238 if (bt_hf_info->state != BT_HF_STATE_CONNECTED)
2242 strncat(global_buff, buf,
2243 (BT_AT_COMMAND_BUFFER_MAX - 1) - strlen(global_buff));
2244 if (!(recvd_ok || recvd_error || recvd_sec_error)) {
2245 __bt_hf_agent_print_at_buffer("Concat ()", global_buff);
2247 DBG("*** Received terminator.. process Rx buffer ***");
2248 hf_handle_rx_at_buff(bt_hf_info, global_buff);
2249 memset(global_buff, 0, sizeof(global_buff));
2252 INFO("*** Received Direct AT buffer packet handling ****");
2253 hf_handle_rx_at_buff(bt_hf_info, buf);
2258 static void __bt_hf_agent_start_watch(bt_hf_agent_info_t *bt_hf_info)
2260 bt_hf_info->watch_id = g_io_add_watch(bt_hf_info->io_chan,
2261 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
2262 (GIOFunc) __bt_hf_agent_data_cb, bt_hf_info);
2265 static void __bt_hf_agent_stop_watch(bt_hf_agent_info_t *bt_hf_info)
2267 if (bt_hf_info->watch_id > 0) {
2268 g_source_remove(bt_hf_info->watch_id);
2269 bt_hf_info->watch_id = 0;
2273 static gboolean __bt_hf_channel_write(GIOChannel *io, gchar *data,
2280 status = g_io_channel_write_chars(io, data, count, &written,
2282 if (status != G_IO_STATUS_NORMAL)
2291 static gboolean __bt_hf_send_only_without_queue(bt_hf_agent_info_t *bt_hf_info,
2292 gchar *data, gsize count)
2294 GIOChannel *io_chan = bt_hf_info->io_chan;
2295 if (!__bt_hf_channel_write(io_chan, data, count))
2298 g_io_channel_flush(io_chan, NULL);
2300 if (count > 2 && data[2] == 'D') { /* ATDXXXXX */
2301 INFO("[HF AT CMD] Send only without queue <<<<<: Buffer = %s, Length = %d ",
2302 "ATDXXXXXXX", count);
2303 snprintf(prev_cmd, BT_HF_CMD_BUF_SIZE, "%s", data);
2305 __bt_hf_agent_print_at_buffer("[HF AT CMD] Send only without queue <<<<<:",
2310 /* DBG("Ref %d(after) on Send only buffer size =[%d] - Send <<<<<| %s",
2311 * send_flag, count, data); */
2316 static gboolean __bt_hf_send_only(bt_hf_agent_info_t *bt_hf_info, gchar *data,
2319 gboolean pending = FALSE;
2320 GIOChannel *io_chan = bt_hf_info->io_chan;
2325 __bt_hf_agent_add_queue(bt_hf_info->context, data, count, pending);
2330 if (!__bt_hf_channel_write(io_chan, data, count))
2333 g_io_channel_flush(io_chan, NULL);
2335 if (count > 2 && data[2] == 'D') /* ATDXXXXX */
2336 INFO("[HF AT CMD] Send only <<<<<: Buffer = %s, Length = %d ",
2337 "ATDXXXXXXX", count);
2339 __bt_hf_agent_print_at_buffer("[HF AT CMD] Send only <<<<<:",
2343 DBG("Ref %d(after) on Send only buffer size =[%d] - Send <<<<<",
2348 static gboolean __bt_hf_send_and_read(bt_hf_agent_info_t *bt_hf_info,
2349 gchar *data, gchar *response, gsize count)
2351 GIOChannel *io_chan = bt_hf_info->io_chan;
2353 gboolean recvd_ok = FALSE;
2354 gboolean recvd_error = FALSE;
2355 gboolean recvd_sec_error = FALSE;
2356 gchar *resp_buf = response;
2357 gsize toread = BT_HF_DATA_BUF_SIZE - 1;
2362 GDBusConnection *conn;
2364 /* Should not send cmds if DUT send a command and wait the response */
2365 if (prev_cmd[0] != 0) {
2366 INFO("DUT is waiting a respond for previous TX cmd. Skip sending.");
2370 memset(resp_buf, 0, BT_HF_DATA_BUF_SIZE);
2372 if (!__bt_hf_channel_write(io_chan, data, count))
2375 g_io_channel_flush(io_chan, NULL);
2377 __bt_hf_agent_print_at_buffer("[HF AT CMD] Send <<<<<:", data);
2379 fd = g_io_channel_unix_get_fd(io_chan);
2381 p.events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
2383 /* Maximun 8 seconds of poll or 8 minus no of cmd received */
2384 for (i = 1; i <= MAX_WAITING_DELAY; i++) {
2385 DBG("Loop Counter = %d", i);
2387 err = poll(&p, 1, 1000);
2389 ERR("Loop Counter = %d, >>>> Poll error happen", i);
2391 } else if (err == 0) {
2392 INFO("Loop Counter = %d, >>>> Poll Timeout", i);
2395 if (p.revents & (POLLERR | POLLHUP | POLLNVAL)) {
2396 ERR("Loop Counter = %d, >> Poll ERR/HUP/INV (%d)",
2399 conn = __bt_hf_get_gdbus_connection();
2401 ERR("Unable to get connection");
2405 __bt_hf_agent_emit_signal(conn,
2406 BT_HF_AGENT_OBJECT_PATH,
2407 BT_HF_SERVICE_INTERFACE,
2409 g_variant_new("(s)",
2410 bt_hf_info->remote_addr));
2412 bt_hf_info->state = BT_HF_STATE_DISCONNECTED;
2416 if (p.revents & POLLIN) {
2417 rd_size = read(fd, resp_buf, toread);
2418 resp_buf[rd_size] = '\0';
2419 DBG_SECURE("size = %d, Buffer=[%s]", rd_size, resp_buf);
2420 recvd_ok = NULL != strstr(resp_buf, BT_HF_OK_RESPONSE);
2421 recvd_error = NULL != strstr(resp_buf, BT_HF_ERROR_RESPONSE);
2422 recvd_sec_error = NULL != strstr(resp_buf, BT_HF_SEC_ERROR_RESPONSE);
2424 resp_buf += rd_size;
2427 if (recvd_ok || recvd_error || recvd_sec_error) {
2428 DBG("Break Loop Counter = %d", i);
2434 /* Once service level connection is established we need to handle
2435 * all the intermediate AT commands */
2436 if (bt_hf_info->state == BT_HF_STATE_CONNECTED)
2437 hf_handle_rx_at_buff(bt_hf_info, response);
2441 static GSList *__bt_hf_parse_indicator_names(gchar *names, GSList *indices)
2443 struct indicator *ind;
2444 gchar *cur = names - 1;
2445 GSList *list = indices;
2448 DBG("Indicator buffer = %s", names);
2449 __bt_hf_agent_print_at_buffer("Indicator names :", names);
2450 while (cur != NULL) {
2452 next = strstr(cur, ",(");
2453 ind = g_new0(struct indicator, 1);
2454 g_strlcpy(ind->descr, cur, BT_HF_INDICATOR_DESCR_SIZE);
2455 ind->descr[(intptr_t) next - (intptr_t) cur] = '\0';
2456 list = g_slist_append(list, (gpointer) ind);
2457 cur = strstr(next + 1, ",(");
2462 static GSList *__bt_hf_parse_indicator_values(gchar *values, GSList *indices)
2465 struct indicator *ind;
2466 GSList *runner = indices;
2468 gchar *cur = values - 1;
2469 DBG("Indicator string = %s", values);
2470 __bt_hf_agent_print_at_buffer("Indicator values :", values);
2471 while (cur != NULL) {
2473 sscanf(cur, "%1d", &val);
2474 cur = strchr(cur, ',');
2475 ind = g_slist_nth_data(runner, 0);
2478 runner = g_slist_next(runner);
2485 static guint __bt_hf_get_hold_mpty_features(gchar *features)
2489 if (strstr(features, "0"))
2490 result |= BT_HF_CHLD_0;
2492 if (strstr(features, "1"))
2493 result |= BT_HF_CHLD_1;
2495 if (strstr(features, "1x"))
2496 result |= BT_HF_CHLD_1x;
2498 if (strstr(features, "2"))
2499 result |= BT_HF_CHLD_2;
2501 if (strstr(features, "2x"))
2502 result |= BT_HF_CHLD_2x;
2504 if (strstr(features, "3"))
2505 result |= BT_HF_CHLD_3;
2507 if (strstr(features, "4"))
2508 result |= BT_HF_CHLD_4;
2513 static gboolean __bt_hf_agent_sco_disconnect_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
2515 bt_hf_agent_info_t *bt_hf_info = user_data;
2516 GDBusConnection *conn;
2519 if (cond & G_IO_NVAL)
2522 if (cond & (G_IO_HUP | G_IO_ERR)) {
2523 g_io_channel_shutdown(chan, TRUE, NULL);
2524 close(bt_hf_info->cli_sco_fd);
2525 bt_hf_info->cli_sco_fd = -1;
2526 g_io_channel_unref(chan);
2527 DBG("Emit AudioDisconnected Signal");
2529 sco_audio_connected = BT_HF_AUDIO_DISCONNECTED;
2531 conn = __bt_hf_get_gdbus_connection();
2533 ERR("Unable to get connection");
2536 __bt_hf_agent_emit_signal(conn,
2537 BT_HF_AGENT_OBJECT_PATH,
2538 BT_HF_SERVICE_INTERFACE,
2539 "AudioDisconnected", NULL);
2547 static gboolean __bt_hf_agent_sco_accept_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
2549 bt_hf_agent_info_t *bt_hf_info = user_data;
2553 GDBusConnection *conn;
2555 INFO("Incoming SCO....");
2557 if (cond & G_IO_NVAL)
2560 sco_skt = g_io_channel_unix_get_fd(chan);
2562 if (cond & (G_IO_HUP | G_IO_ERR)) {
2567 cli_sco_sock = accept(sco_skt, NULL, NULL);
2568 if (cli_sco_sock < 0)
2571 bt_hf_info->cli_sco_fd = cli_sco_sock;
2573 sco_io = g_io_channel_unix_new(cli_sco_sock);
2574 g_io_channel_set_close_on_unref(sco_io, TRUE);
2575 g_io_channel_set_encoding(sco_io, NULL, NULL);
2576 g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
2577 g_io_channel_set_buffered(sco_io, FALSE);
2579 g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
2580 __bt_hf_agent_sco_disconnect_cb, bt_hf_info);
2582 if (bt_hf_info->state != BT_HF_STATE_CONNECTED)
2583 ERR("HFP is not yet connected");
2585 /* S-Voice app requires the AudioConnected signal earlier */
2586 DBG("Emit AudioConnected Signal");
2588 sco_audio_connected = BT_HF_AUDIO_CONNECTED;
2590 conn = __bt_hf_get_gdbus_connection();
2592 ERR("Unable to get connection");
2596 __bt_hf_agent_emit_signal(conn,
2597 BT_HF_AGENT_OBJECT_PATH,
2598 BT_HF_SERVICE_INTERFACE,
2599 "AudioConnected", NULL);
2601 /* In the case of incoming call, the call app is already launched,
2602 * hence AudioConnected signal is enough to update the call status.
2603 * In the case of outgoing call we need to lauch the callapp.
2606 __bt_hf_agent_launch_call_app();
2611 static void __bt_convert_addr_string_to_type_rev(unsigned char *addr,
2612 const char *address)
2617 ret_if(address == NULL);
2618 ret_if(addr == NULL);
2620 for (i = 0; i < BT_ADDRESS_LENGTH_MAX; i++) {
2621 addr[5 - i] = strtol(address, &ptr, 16);
2622 if (ptr[0] != '\0') {
2631 static gboolean __bt_hf_agent_sco_accept(bt_hf_agent_info_t *bt_hf_info)
2633 struct sockaddr_sco addr;
2635 bdaddr_t bd_addr = {{0},};
2639 sco_skt = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
2641 ERR("Can't create socket:\n");
2645 /* Bind to local address */
2646 memset(&addr, 0, sizeof(addr));
2647 addr.sco_family = AF_BLUETOOTH;
2649 DBG("Bind to address %s", bt_hf_info->remote_addr);
2651 __bt_convert_addr_string_to_type_rev(bd_addr.b, bt_hf_info->remote_addr);
2652 memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
2654 if (bind(sco_skt, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2655 ERR("Can't bind socket:\n");
2659 if (listen(sco_skt, 1)) {
2660 ERR("Can not listen on the socket:\n");
2664 sco_io = g_io_channel_unix_new(sco_skt);
2665 g_io_channel_set_close_on_unref(sco_io, TRUE);
2666 g_io_channel_set_encoding(sco_io, NULL, NULL);
2667 g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
2668 g_io_channel_set_buffered(sco_io, FALSE);
2670 bt_hf_info->sco_fd = sco_skt;
2671 bt_hf_info->sco_io_chan = sco_io;
2673 bt_hf_info->sco_watch_id = g_io_add_watch(sco_io,
2674 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, __bt_hf_agent_sco_accept_cb, bt_hf_info);
2676 g_io_channel_unref(sco_io);
2685 static gboolean __bt_get_supported_indicators(bt_hf_agent_info_t *bt_hf_info)
2687 gchar buf[BT_HF_DATA_BUF_SIZE] = {0,};
2690 ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_INDICATORS_SUPP, buf,
2691 sizeof(BT_HF_INDICATORS_SUPP) - 1);
2692 if (!ret || !strstr(buf, "+CIND:"))
2695 bt_hf_info->indies = __bt_hf_parse_indicator_names(strchr(buf, '('), NULL);
2700 static gboolean __bt_get_bia_cmd(bt_hf_agent_info_t *bt_hf_info, gchar *cmd, gsize cmd_size)
2705 if (bt_hf_info == NULL || cmd == NULL) {
2706 ERR("Invalid parameter");
2710 ret = g_strlcpy(cmd, BT_HF_INDICATORS_ACTIVATION, cmd_size);
2712 for (l = bt_hf_info->indies; l != NULL; l = g_slist_next(l)) {
2713 ret = g_strlcat(cmd, "0,", cmd_size);
2714 if (ret >= cmd_size) {
2715 ERR("Too many indices");
2721 cmd[ret - 1] = '\0';
2722 DBG("BIA Str : %s", cmd);
2724 ret = g_strlcat(cmd, "\r", cmd_size);
2725 if (ret >= cmd_size) {
2726 ERR("Too many indices");
2733 static gboolean __bt_get_current_indicators(bt_hf_agent_info_t *bt_hf_info)
2735 gchar buf[BT_HF_DATA_BUF_SIZE] = {0,};
2741 ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_INDICATORS_VAL, buf,
2742 sizeof(BT_HF_INDICATORS_VAL) - 1);
2743 if (!ret || !strstr(buf, "+CIND:"))
2746 /* if buf has other command prefix, skip it */
2747 str = strstr(buf, "+CIND");
2751 bt_hf_info->indies = __bt_hf_parse_indicator_values(str + 6, bt_hf_info->indies);
2753 /* Parse the updated value */
2754 for (l = bt_hf_info->indies; l != NULL; l = g_slist_next(l), ++index) {
2755 struct indicator *ind = l->data;
2757 DBG("Index is NULL");
2761 if (0 == g_strcmp0(ind->descr, "\"call\"")) {
2762 DBG("CIND Match found index = %d, %s, value = %d",
2763 index, ind->descr, ind->value);
2764 bt_hf_info->ciev_call_status = ind->value;
2765 if (ind->value > 0) {
2766 bt_hf_info->is_dialing = FALSE;
2767 bt_hf_info->call_active = TRUE;
2769 } else if (0 == g_strcmp0(ind->descr, "\"callsetup\"")) {
2770 DBG("CIND Match found index = %d, %s, value = %d",
2771 index, ind->descr, ind->value);
2772 bt_hf_info->ciev_call_setup_status = ind->value;
2773 if (!bt_hf_info->is_dialing && ind->value > 0)
2774 bt_hf_info->is_dialing = TRUE;
2781 static gboolean __bt_establish_service_level_conn(bt_hf_agent_info_t *bt_hf_info)
2783 gchar buf[BT_HF_DATA_BUF_SIZE];
2784 gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
2787 guint feature = BT_HF_FEATURE_EC_ANDOR_NR |
2788 BT_HF_FEATURE_CALL_WAITING_AND_3WAY |
2789 BT_HF_FEATURE_CLI_PRESENTATION |
2790 BT_HF_FEATURE_REMOTE_VOLUME_CONTROL |
2791 BT_HF_FEATURE_ENHANCED_CALL_STATUS;
2793 if (TIZEN_PROFILE_WEARABLE)
2794 feature = feature | BT_HF_FEATURE_CODEC_NEGOTIATION;
2796 snprintf(cmd_buf, sizeof(cmd_buf), BT_HF_FEATURES, feature);
2797 ret = __bt_hf_send_and_read(bt_hf_info, cmd_buf, buf,
2802 buf_ptr = strstr(buf, "\r\n+BRSF:");
2803 if (buf_ptr == NULL)
2806 if (!ret || sscanf(buf_ptr, "\r\n+BRSF:%5d", &bt_hf_info->ag_features) != 1)
2808 INFO("Gateway supported features are 0x%X", bt_hf_info->ag_features);
2810 if (TIZEN_PROFILE_WEARABLE) {
2811 if (bt_hf_info->ag_features & BT_AG_FEATURE_CODEC_NEGOTIATION) {
2812 ret = _hf_agent_codec_setup(bt_hf_info->remote_addr, BT_HF_CODEC_ID_MSBC);
2813 if (ret != BT_HF_AGENT_ERROR_NONE)
2814 ERR("Unable to set the default WBC codec");
2816 ret = __bt_hf_send_available_codec(bt_hf_info, 0);
2821 /* Default codec is NB */
2822 ret = _hf_agent_codec_setup(bt_hf_info->remote_addr, BT_HF_CODEC_ID_CVSD);
2823 if (ret != BT_HF_AGENT_ERROR_NONE)
2824 ERR("Unable to set the default NBC codec");
2827 ret = __bt_get_supported_indicators(bt_hf_info);
2832 ret = __bt_get_current_indicators(bt_hf_info);
2836 ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_INDICATORS_ENABLE, buf,
2837 sizeof(BT_HF_INDICATORS_ENABLE) - 1);
2838 if (!ret || !strstr(buf, "OK"))
2841 if ((bt_hf_info->ag_features & BT_AG_FEATURE_3WAY) != 0) {
2842 ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_HOLD_MPTY_SUPP,
2843 buf, sizeof(BT_HF_HOLD_MPTY_SUPP) - 1);
2844 if (!ret || !strstr(buf, "+CHLD:")) {
2845 ERR("Unable to get the CHLD Supported info");
2848 bt_hf_info->hold_multiparty_features = __bt_hf_get_hold_mpty_features(
2851 bt_hf_info->hold_multiparty_features = 0;
2853 if (bt_hf_info->ag_features & BT_AG_FEATURE_INBAND_RINGTONE)
2854 bt_hf_info->inband_ringtone_support = TRUE;
2856 bt_hf_info->inband_ringtone_support = FALSE;
2858 INFO("Service layer connection successfully established...!");
2860 bt_hf_info->slc = TRUE;
2863 memset(global_buff, 0, sizeof(global_buff));
2867 static void __bt_establish_initialization(bt_hf_agent_info_t *bt_hf_info)
2869 gchar buf[BT_HF_DATA_BUF_SIZE];
2870 gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
2873 __bt_hf_send_and_read(bt_hf_info, BT_HF_CALLER_IDENT_ENABLE, buf,
2874 sizeof(BT_HF_CALLER_IDENT_ENABLE) - 1);
2875 __bt_hf_send_and_read(bt_hf_info, BT_HF_CARRIER_FORMAT, buf,
2876 sizeof(BT_HF_CARRIER_FORMAT) - 1);
2877 __bt_hf_send_and_read(bt_hf_info, BT_HF_CALLWAIT_NOTI_ENABLE, buf,
2878 sizeof(BT_HF_CALLWAIT_NOTI_ENABLE) - 1);
2880 if ((bt_hf_info->ag_features & BT_AG_FEATURE_NREC) != 0)
2881 __bt_hf_send_and_read(bt_hf_info, BT_HF_NREC, buf,
2882 sizeof(BT_HF_NREC) - 1);
2884 if ((bt_hf_info->ag_features & BT_AG_FEATURE_EXTENDED_RES_CODE) != 0)
2885 __bt_hf_send_and_read(bt_hf_info, BT_HF_EXTENDED_RESULT_CODE,
2886 buf, sizeof(BT_HF_EXTENDED_RESULT_CODE) - 1);
2888 if (__bt_get_bia_cmd(bt_hf_info, cmd_buf, sizeof(cmd_buf)) == TRUE)
2889 __bt_hf_send_and_read(bt_hf_info, cmd_buf, buf, strlen(cmd_buf));
2891 ERR("__bt_get_bia_cmd is failed");
2893 ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_XSAT, buf,
2894 sizeof(BT_HF_XSAT) - 1);
2896 DBG("sent BT_HF_XSAT");
2898 ERR("BT_HF_XSAT sending failed");
2900 if (TIZEN_PROFILE_WEARABLE) {
2901 /* send Bluetooth Samsung Support Feature cmd */
2902 ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_BSSF, buf,
2903 sizeof(BT_HF_BSSF) - 1);
2905 /* If we got a 'OK' reply, peer AG is samsung device.
2906 * Otherwise, non-samsung device */
2907 if (ret && strstr(buf, "OK"))
2908 bt_hf_info->is_companion_dev = TRUE;
2910 bt_hf_info->is_companion_dev = FALSE;
2913 INFO("SLC completed with [%s] device",
2914 bt_hf_info->is_companion_dev ? "SS Companion" : "Other");
2916 ERR("BT_HF_BSSF sending failed");
2920 static void __bt_hf_agent_sigterm_handler(int signo)
2922 GDBusConnection *conn;
2925 ERR_C("***** Signal handler came with signal %d *****", signo);
2927 conn = __bt_hf_get_gdbus_connection();
2929 ERR("Unable to get G-DBus connection");
2932 INFO("Getting gdbus connection done");
2934 __bt_hf_agent_emit_signal(conn,
2935 BT_HF_AGENT_OBJECT_PATH,
2936 BT_HF_SERVICE_INTERFACE,
2938 INFO("CallEnded Signal done");
2940 g_dbus_connection_flush(conn, NULL, NULL, NULL);
2941 INFO("Flush g_dbus_connection");
2945 g_main_loop_quit(gmain_loop);
2949 INFO_C("Terminating HF agent");
2953 if (signo == SIGTERM)
2956 for (i = 0; i < BT_HF_SIG_NUM; i++)
2957 sigaction(bt_hf_sig_to_handle[i], &(bt_hf_sigoldact[i]), NULL);
2962 static void __bt_convert_addr_type_to_rev_string(char *address,
2963 unsigned char *addr)
2965 ret_if(address == NULL);
2966 ret_if(addr == NULL);
2968 g_snprintf(address, BT_ADDRESS_STRING_SIZE,
2969 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
2970 addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
2974 static gboolean __bt_hf_agent_release_after(gpointer user_data)
2976 if (__bt_hf_agent_release() == FALSE)
2977 ERR("Unable to release hf connection");
2982 static gboolean __bt_agent_request_service_level_conn(gpointer data)
2985 int bt_device_state = VCONFKEY_BT_DEVICE_NONE;
2986 GDBusConnection *conn;
2989 memset(prev_cmd, 0, BT_HF_CMD_BUF_SIZE);
2991 __bt_hf_agent_sco_accept(&bt_hf_info);
2993 if (!__bt_establish_service_level_conn(&bt_hf_info)) {
2994 ERR("Service Level Connection is fail");
2996 conn = __bt_hf_get_gdbus_connection();
2998 remote_addr = bt_hf_info.remote_addr;
2999 __bt_hf_agent_emit_signal(conn,
3000 BT_HF_AGENT_OBJECT_PATH,
3001 BT_HF_SERVICE_INTERFACE,
3003 g_variant_new("(s)", remote_addr));
3005 bt_hf_info.state = BT_HF_STATE_CONNECTED;
3007 if (vconf_get_int(VCONFKEY_BT_DEVICE, &bt_device_state) == 0) {
3008 DBG("BT device state is : 0x%X", bt_device_state);
3009 bt_device_state |= VCONFKEY_BT_DEVICE_AG_CONNECTED;
3010 if (vconf_set_int(VCONFKEY_BT_DEVICE, bt_device_state) != 0)
3011 ERR("vconf_set_int failed");
3013 ERR("vconf_get_int failed");
3016 g_idle_add(__bt_hf_agent_release_after, NULL);
3021 bt_hf_info.state = BT_HF_STATE_CONNECTED;
3023 __bt_hf_agent_start_watch(&bt_hf_info);
3025 remote_addr = bt_hf_info.remote_addr;
3027 INFO_SECURE("Address is : %s", remote_addr);
3028 INFO_C("### Connected [HF role]");
3030 if (vconf_get_int(VCONFKEY_BT_DEVICE, &bt_device_state) == 0) {
3031 DBG("BT device state is : 0x%X", bt_device_state);
3032 bt_device_state |= VCONFKEY_BT_DEVICE_AG_CONNECTED;
3034 if (vconf_set_int(VCONFKEY_BT_DEVICE, bt_device_state) != 0)
3035 ERR("vconf_set_int failed");
3037 ERR("vconf_get_int failed");
3040 conn = __bt_hf_get_gdbus_connection();
3042 ERR("Unable to get connection");
3046 __bt_hf_agent_emit_signal(conn,
3047 BT_HF_AGENT_OBJECT_PATH,
3048 BT_HF_SERVICE_INTERFACE,
3050 g_variant_new("(s)", remote_addr));
3052 /* Establish the initialization */
3053 __bt_establish_initialization(&bt_hf_info);
3060 static gboolean __bt_hf_agent_connection(gint32 fd, const gchar *obj_path)
3064 struct sockaddr_remote address;
3065 socklen_t address_len;
3066 bt_hf_info.path = g_strdup(obj_path);
3068 INFO_C("**** New HFP connection ****");
3070 is_hf_connected = TRUE;
3072 address_len = sizeof(address);
3073 if (getpeername(fd, (struct sockaddr *) &address, &address_len) != 0)
3074 ERR("BD_ADDR is NULL");
3076 DBG("RFCOMM connection for HFP is completed. Fd = [%d]\n", fd);
3078 bt_hf_info.io_chan = g_io_channel_unix_new(bt_hf_info.fd);
3079 flags = g_io_channel_get_flags(bt_hf_info.io_chan);
3081 flags &= ~G_IO_FLAG_NONBLOCK;
3082 flags &= G_IO_FLAG_MASK;
3083 g_io_channel_set_flags(bt_hf_info.io_chan, flags, NULL);
3084 g_io_channel_set_encoding(bt_hf_info.io_chan, NULL, NULL);
3085 g_io_channel_set_buffered(bt_hf_info.io_chan, FALSE);
3087 bt_hf_info.remote_addr = g_malloc0(BT_ADDRESS_STRING_SIZE);
3088 __bt_convert_addr_type_to_rev_string(bt_hf_info.remote_addr,
3089 address.remote_bdaddr.b);
3091 g_idle_add(__bt_agent_request_service_level_conn, NULL);
3096 static void __bt_hf_agent_indicator_free(gpointer mem)
3101 static gboolean __bt_hf_agent_release(void)
3103 int bt_device_state = VCONFKEY_BT_DEVICE_NONE;
3104 GDBusConnection *conn;
3107 g_source_remove(clcc_timer);
3111 if (bt_hf_info.state == BT_HF_STATE_DISCONNECTED) {
3112 ERR("hf is already disconnected");
3116 if (bt_hf_info.indies) {
3117 g_slist_free_full(bt_hf_info.indies, __bt_hf_agent_indicator_free);
3118 bt_hf_info.indies = NULL;
3121 if (bt_hf_info.io_chan) {
3122 g_io_channel_shutdown(bt_hf_info.io_chan, TRUE, NULL);
3123 g_io_channel_unref(bt_hf_info.io_chan);
3124 bt_hf_info.io_chan = NULL;
3127 if (bt_hf_info.sco_watch_id > 0) {
3128 g_source_remove(bt_hf_info.sco_watch_id);
3129 bt_hf_info.sco_watch_id = 0;
3132 bt_hf_info.state = BT_HF_STATE_DISCONNECTED;
3134 __bt_hf_agent_release_queue();
3136 if (vconf_get_int(VCONFKEY_BT_DEVICE, &bt_device_state) == 0) {
3137 DBG("BT device state is : 0x%X", bt_device_state);
3138 bt_device_state ^= VCONFKEY_BT_DEVICE_AG_CONNECTED;
3140 if (vconf_set_int(VCONFKEY_BT_DEVICE, bt_device_state) != 0)
3141 ERR("vconf_set_int failed");
3143 ERR("vconf_get_int failed");
3146 __bt_hf_agent_stop_watch(&bt_hf_info);
3147 conn = __bt_hf_get_gdbus_connection();
3149 ERR("Unable to get connection");
3153 __bt_hf_agent_emit_signal(conn,
3154 BT_HF_AGENT_OBJECT_PATH,
3155 BT_HF_SERVICE_INTERFACE,
3157 g_variant_new("(s)", bt_hf_info.remote_addr));
3159 g_free(bt_hf_info.path);
3160 bt_hf_info.path = NULL;
3162 g_free(bt_hf_info.remote_addr);
3163 bt_hf_info.remote_addr = NULL;
3165 is_hf_connected = FALSE;
3170 static gboolean __bt_hf_agent_connection_release(void)
3172 return __bt_hf_agent_release();
3175 static int __bt_hf_register_profile(const char *uuid, uint16_t version,
3176 const char *name, const char *object, uint16_t features)
3181 GError *error = NULL;
3182 GVariantBuilder *builder;
3185 proxy = __bt_hf_gdbus_get_profile_proxy();
3188 return BT_HF_AGENT_ERROR_INTERNAL;
3190 path = g_strdup(BT_HF_BLUEZ_OBJECT_PATH);
3192 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3194 g_variant_builder_add(builder, "{sv}",
3195 "Name", g_variant_new("s",
3197 g_variant_builder_add(builder, "{sv}",
3198 "Version", g_variant_new("q", version));
3200 g_variant_builder_add(builder, "{sv}",
3201 "features", g_variant_new("q", features));
3203 ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile",
3204 g_variant_new("(osa{sv})", path,
3205 HFP_HF_UUID, builder),
3206 G_DBUS_CALL_FLAGS_NONE, -1,
3209 g_variant_builder_unref(builder);
3212 /* dBUS-RPC is failed */
3213 ERR("dBUS-RPC is failed");
3214 if (error != NULL) {
3215 /* dBUS gives error cause */
3216 ERR("D-Bus API failure: errCode[%x], message[%s]",
3217 error->code, error->message);
3218 g_clear_error(&error);
3221 return BT_HF_AGENT_ERROR_INTERNAL;
3223 g_variant_unref(ret);
3227 return BT_HF_AGENT_ERROR_NONE;
3230 static void __bt_hf_agent_register(void)
3235 uint16_t version = hf_ver;
3236 uint16_t features = bt_hf_info.feature;
3238 gchar *path = g_strdup(BT_HF_BLUEZ_OBJECT_PATH);
3239 name = g_strdup("Hands-Free");
3241 ret = __bt_hf_register_profile(HFP_HF_UUID, version, name, path,
3244 ERR("Error in register");
3253 static void __bt_hf_agent_unregister(void)
3257 gchar *path = g_strdup(BT_HF_BLUEZ_OBJECT_PATH);
3260 __bt_hf_agent_gdbus_method_send(BLUEZ_SERVICE_NAME,
3261 g_variant_new("(o)", path),
3262 BLUEZ_HF_INTERFACE_NAME,
3274 static void __bt_hf_agent_filter_cb(GDBusConnection *connection,
3275 const gchar *sender_name,
3276 const gchar *object_path,
3277 const gchar *interface_name,
3278 const gchar *signal_name,
3279 GVariant *parameters,
3285 GVariant *optional_param;
3287 if (strcasecmp(signal_name, "InterfacesAdded") == 0) {
3289 g_variant_get(parameters, "(&o@a{sa{sv}})",
3290 &path, &optional_param);
3292 ERR("Invalid adapter path");
3296 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
3297 g_obj_path = g_strdup(path);
3298 INFO("Adapter Path = [%s]", path);
3299 __bt_hf_agent_register();
3301 } else if (strcasecmp(signal_name, "InterfacesRemoved") == 0) {
3302 g_variant_get(parameters, "(&o@as)", &path, &optional_param);
3304 __bt_hf_agent_unregister();
3309 static int __bt_hf_agent_get_adapter_path(GDBusConnection *conn, char *path)
3312 GDBusProxy *manager_proxy = NULL;
3313 GVariant *result = NULL;
3314 char *adapter_path = NULL;
3317 return BT_HF_AGENT_ERROR_INTERNAL;
3319 manager_proxy = g_dbus_proxy_new_sync(conn,
3320 G_DBUS_PROXY_FLAGS_NONE, NULL,
3323 BT_MANAGER_INTERFACE,
3326 if (!manager_proxy) {
3327 ERR("Unable to create proxy: %s", err->message);
3331 result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
3332 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
3335 ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
3337 ERR("Fail to get DefaultAdapter");
3342 if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
3343 ERR("Incorrect result\n");
3347 g_variant_get(result, "(&o)", &adapter_path);
3349 if (adapter_path == NULL ||
3350 strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) {
3351 ERR("Adapter path is inproper\n");
3356 g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX);
3358 if (g_obj_path == NULL) {
3359 g_obj_path = g_strdup(adapter_path);
3360 INFO("Update g_obj_path [%s]", adapter_path);
3363 g_variant_unref(result);
3364 g_object_unref(manager_proxy);
3369 g_clear_error(&err);
3372 g_variant_unref(result);
3375 g_object_unref(manager_proxy);
3377 return BT_HF_AGENT_ERROR_INTERNAL;
3381 static void __bt_hf_agent_dbus_init(void)
3383 GDBusConnection *conn;
3387 conn = __bt_hf_get_gdbus_connection();
3389 ERR("Error in creating the gdbus connection\n");
3392 if (!__bt_hf_register_profile_methods()) {
3393 ERR("Error in register_profile_methods\n");
3397 if (!__bt_hf_agent_get_adapter_path(gdbus_conn , NULL)) {
3398 __bt_hf_agent_register();
3401 interface_added_sig_id = g_dbus_connection_signal_subscribe(conn,
3402 NULL, BT_MANAGER_INTERFACE, BT_INTERFACES_ADDED, NULL, NULL, 0,
3403 __bt_hf_agent_filter_cb, NULL, NULL);
3405 interface_removed_sig_id = g_dbus_connection_signal_subscribe(conn,
3406 NULL, BT_MANAGER_INTERFACE, BT_INTERFACES_REMOVED, NULL, NULL, 0,
3407 __bt_hf_agent_filter_cb, NULL, NULL);
3412 static void __bt_hf_agent_dbus_deinit(void)
3414 if (profile_gproxy) {
3415 g_object_unref(profile_gproxy);
3416 profile_gproxy = NULL;
3420 if (interface_added_sig_id > 0)
3421 g_dbus_connection_signal_unsubscribe(gdbus_conn,
3422 interface_added_sig_id);
3424 if (interface_removed_sig_id > 0)
3425 g_dbus_connection_signal_unsubscribe(gdbus_conn,
3426 interface_removed_sig_id);
3428 interface_added_sig_id = 0;
3429 interface_removed_sig_id = 0;
3431 g_object_unref(gdbus_conn);
3436 static int _hf_agent_answer_call(GDBusMethodInvocation *context)
3441 if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3442 ERR("HF not Connected");
3443 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3445 bt_hf_info.context = context;
3447 ret = __bt_hf_send_only(&bt_hf_info, BT_HF_ANSWER_CALL,
3448 sizeof(BT_HF_ANSWER_CALL) - 1);
3450 return BT_HF_AGENT_ERROR_INTERNAL;
3453 return BT_HF_AGENT_ERROR_NONE;
3457 static int _hf_agent_terminate_call(GDBusMethodInvocation *context)
3462 if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3463 ERR("HF not Connected");
3464 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3467 bt_hf_info.context = context;
3469 ret = __bt_hf_send_only(&bt_hf_info, BT_HF_END_CALL,
3470 sizeof(BT_HF_END_CALL) - 1);
3472 return BT_HF_AGENT_ERROR_INTERNAL;
3475 return BT_HF_AGENT_ERROR_NONE;
3478 static int _hf_agent_dial_no(GDBusMethodInvocation *context, char *no)
3481 char buf[BT_MAX_TEL_NUM_STR + 6] = {0};
3483 if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3484 ERR("HF not Connected");
3485 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3488 bt_hf_info.context = context;
3490 if (strlen(no) > 0) {
3491 snprintf(buf, sizeof(buf), BT_HF_DIAL_NO, no);
3493 if (strstr(prev_cmd, "ATD") && bt_hf_info.ciev_call_status == 0
3494 && bt_hf_info.ciev_call_setup_status == 0) {
3495 INFO("RAD POPUP CANCEL CASE. send ATD w/o response - KOR REQUEST");
3496 ret = __bt_hf_send_only_without_queue(&bt_hf_info, buf, strlen(buf));
3500 ret = __bt_hf_send_only(&bt_hf_info, buf, strlen(buf));
3503 /* prev_cmd is meant for only meant for ATD & AT+BLDN Error handling */
3504 snprintf(prev_cmd, BT_HF_CMD_BUF_SIZE, "%s", buf);
3507 return BT_HF_AGENT_ERROR_INTERNAL;
3509 return BT_HF_AGENT_ERROR_NONE;
3512 /* prev_cmd is meant for only meant for ATD & AT+BLDN Error handling */
3513 snprintf(prev_cmd, BT_HF_CMD_BUF_SIZE, "%s", BT_HF_REDIAL);
3515 ret = __bt_hf_send_only(&bt_hf_info, BT_HF_REDIAL,
3516 sizeof(BT_HF_REDIAL) - 1);
3518 return BT_HF_AGENT_ERROR_INTERNAL;
3520 return BT_HF_AGENT_ERROR_NONE;
3523 static int _hf_agent_voice_recognition(GDBusMethodInvocation *context, unsigned int status)
3528 if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3529 ERR("HF not Connected");
3530 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3533 snprintf(buf, sizeof(buf), BT_HF_VOICE_RECOGNITION, status);
3535 bt_hf_info.context = context;
3537 ret = __bt_hf_send_only(&bt_hf_info, buf, strlen(buf));
3539 return BT_HF_AGENT_ERROR_INTERNAL;
3542 return BT_HF_AGENT_ERROR_NONE;
3545 static int _hf_agent_set_speaker_gain(GDBusMethodInvocation *context, unsigned int gain)
3550 if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3551 ERR("HF not Connected");
3552 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3555 if (gain > BT_HF_MAX_SPEAKER_GAIN)
3556 return BT_HF_AGENT_ERROR_INVALID_PARAM;
3558 snprintf(buf, sizeof(buf), BT_HF_SPEAKER_GAIN, gain);
3560 bt_hf_info.context = context;
3562 ret = __bt_hf_send_only(&bt_hf_info, buf,
3565 return BT_HF_AGENT_ERROR_INTERNAL;
3567 return BT_HF_AGENT_ERROR_NONE;
3571 static int _hf_agent_send_dtmf(GDBusMethodInvocation *context, char *dtmf)
3576 if (strlen(dtmf) <= 0)
3577 return BT_HF_AGENT_ERROR_INVALID_PARAM;
3579 if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3580 ERR("HF not Connected");
3581 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3584 snprintf(buf, sizeof(buf), BT_HF_DTMF, dtmf);
3586 bt_hf_info.context = context;
3588 ret = __bt_hf_send_only(&bt_hf_info, buf, strlen(buf));
3590 return BT_HF_AGENT_ERROR_INTERNAL;
3593 return BT_HF_AGENT_ERROR_NONE;
3597 static int _hf_agent_send_3way_cmd(GDBusMethodInvocation *context, char *cmd)
3601 if (strlen(cmd) <= 0)
3602 return BT_HF_AGENT_ERROR_INVALID_PARAM;
3604 bt_hf_info.context = context;
3606 ret = __bt_hf_send_only(&bt_hf_info, cmd,
3609 return BT_HF_AGENT_ERROR_INTERNAL;
3611 return BT_HF_AGENT_ERROR_NONE;
3614 static gboolean bt_hf_agent_sco_connect(void)
3616 struct sockaddr_sco addr;
3617 bdaddr_t bd_addr = {{0},};
3620 GDBusConnection *conn;
3624 if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
3625 ERR("HF RFCOMM not Connected");
3629 if (bt_hf_info.cli_sco_fd > 0) {
3630 ERR("SCO Already connected..");
3635 sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
3637 ERR("Can't create SCO socket");
3641 /* Bind to local address */
3642 memset(&addr, 0, sizeof(addr));
3643 addr.sco_family = AF_BLUETOOTH;
3644 memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
3646 if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3647 ERR("Can't bind socket");
3651 /* Connect to remote device */
3652 memset(&addr, 0, sizeof(addr));
3653 addr.sco_family = AF_BLUETOOTH;
3654 __bt_convert_addr_string_to_type_rev(addr.sco_bdaddr.b, bt_hf_info.remote_addr);
3655 if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3656 ERR("Can't connect");
3660 DBG("SCO Connected");
3662 bt_hf_info.cli_sco_fd = sk;
3664 sco_io = g_io_channel_unix_new(sk);
3665 g_io_channel_set_close_on_unref(sco_io, TRUE);
3666 g_io_channel_set_encoding(sco_io, NULL, NULL);
3667 g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
3668 g_io_channel_set_buffered(sco_io, FALSE);
3670 g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
3671 __bt_hf_agent_sco_disconnect_cb, &bt_hf_info);
3673 DBG("Emit AudioConnected Signal - Outgoing SCo connection");
3674 sco_audio_connected = BT_HF_AUDIO_CONNECTED;
3676 conn = __bt_hf_get_gdbus_connection();
3678 ERR("Unable to get connection");
3682 __bt_hf_agent_emit_signal(conn,
3683 BT_HF_AGENT_OBJECT_PATH,
3684 BT_HF_SERVICE_INTERFACE,
3685 "AudioConnected", NULL);
3696 static gboolean bt_hf_agent_sco_disconnect(void)
3699 GDBusConnection *conn;
3701 close(bt_hf_info.cli_sco_fd);
3702 bt_hf_info.cli_sco_fd = -1;
3704 DBG("Emit AudioDisconnected Signal");
3705 conn = __bt_hf_get_gdbus_connection();
3707 ERR("Unable to get connection");
3711 sco_audio_connected = BT_HF_AUDIO_DISCONNECTED;
3713 __bt_hf_agent_emit_signal(conn,
3714 BT_HF_AGENT_OBJECT_PATH,
3715 BT_HF_SERVICE_INTERFACE,
3716 "AudioDisconnected", NULL);
3721 static GVariant *bt_hf_agent_request_call_list(void)
3723 GSList *call_list = NULL;
3727 call_list = __bt_hf_get_call_list(&bt_hf_info);
3729 INFO("call list is NULL");
3733 var_data = __bt_hf_agent_get_call_status_info(call_list);
3734 __bt_hf_free_call_list(call_list);
3740 static int bt_hf_agent_send_at_cmd(GDBusMethodInvocation *context, char *atcmd)
3744 char cmd_buf[BT_MAX_TEL_NUM_STR + 20] = {0, };
3749 return BT_HF_AGENT_ERROR_INVALID_PARAM;
3751 if (bt_hf_info.state != BT_HF_STATE_CONNECTED)
3752 return BT_HF_AGENT_ERROR_NOT_CONNECTED;
3754 strncpy(cmd_buf, atcmd, sizeof(cmd_buf) - 2);
3755 strncat(cmd_buf, "\r", (sizeof(cmd_buf) - 1) - strlen(cmd_buf));
3757 bt_hf_info.context = context;
3759 ret = __bt_hf_send_only(&bt_hf_info, cmd_buf, strlen(cmd_buf));
3761 return BT_HF_AGENT_ERROR_INTERNAL;
3764 return BT_HF_AGENT_ERROR_NONE;
3767 static uint32_t __bt_hf_agent_get_hf_features(void)
3769 uint32_t hf_features = BT_HF_FEATURE_EC_ANDOR_NR |
3770 BT_HF_FEATURE_CALL_WAITING_AND_3WAY |
3771 BT_HF_FEATURE_CLI_PRESENTATION |
3772 BT_HF_FEATURE_REMOTE_VOLUME_CONTROL |
3773 BT_HF_FEATURE_ENHANCED_CALL_STATUS |
3774 BT_HF_FEATURE_CODEC_NEGOTIATION;
3776 if (TIZEN_PROFILE_WEARABLE)
3777 hf_features = hf_features | BT_HF_FEATURE_CODEC_NEGOTIATION;
3779 hf_ver = HFP_VERSION_1_6;
3787 struct sigaction sa;
3788 uint32_t hf_features;
3790 INFO_C("### Starting Bluetooth HF agent");
3792 #if GLIB_VERSION_MIN_REQUIRED < GLIB_VERSION_2_36
3795 hf_features = __bt_hf_agent_get_hf_features();
3796 bt_hf_info.feature = (uint16_t) hf_features & 0x3F;
3798 memset(&sa, 0, sizeof(sa));
3799 sa.sa_flags = SA_NOCLDSTOP;
3800 sa.sa_handler = __bt_hf_agent_sigterm_handler;
3802 for (i = 0; i < BT_HF_SIG_NUM; i++)
3803 sigaction(bt_hf_sig_to_handle[i], &sa, &(bt_hf_sigoldact[i]));
3805 g_log_set_default_handler(__on_log_glib, NULL);
3807 gmain_loop = g_main_loop_new(NULL, FALSE);
3809 if (gmain_loop == NULL) {
3810 ERR("GMainLoop create failed\n");
3811 return EXIT_FAILURE;
3814 __bt_hf_agent_dbus_init();
3816 g_main_loop_run(gmain_loop);
3818 __bt_hf_agent_dbus_deinit();
3821 g_main_loop_unref(gmain_loop);
3823 INFO_C("### Terminating Bluetooth HF agent");