#include "bluetooth-agent-profile.h"
#define BT_AGENT_SYSPOPUP_MAX_ATTEMPT 3
-#define CALL_APP_ID "org.tizen.call-ui"
+#define CALL_ALIAS_APP_ID "org.tizen.call-ui"
#define MAX_WAITING_DELAY 8
#define READ_TX_POWER_MIN -30
static GMainLoop *gmain_loop = NULL;
static char *g_obj_path;
-static GDBusConnection *gdbus_conn;
-static GDBusProxy *service_gproxy;
+static GDBusConnection *gdbus_conn = NULL;
+static GDBusProxy *profile_gproxy = NULL;
static guint interface_added_sig_id;
static guint interface_removed_sig_id;
int g_id = 0;
uint16_t hf_ver;
+guint clcc_timer = 0;
+int clcc_retry_count = 0;
+guint clcc_async_timer = 0;
+int clcc_async_retry_count = 0;
+#define CLCC_RETRY_COUNT 10
+#define CLCC_RETRY_TIMER 100 /* 100 msec */
+
#define HFP_HF_UUID "0000111e-0000-1000-8000-00805f9b34fb"
#define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
" <method name='VoiceRecognition'>"
" <arg type='i' name='status' direction='in'/>"
" </method>"
+" <method name='ScoConnect'>"
+" </method>"
" <method name='ScoDisconnect'>"
" </method>"
" <method name='SpeakerGain'>"
" <arg type='i' name='count' direction='out'/>"
" <arg type='a(siiii)' name='callList' direction='out'/>"
" </method>"
+" <method name='RequestCallListAsync'>"
+" </method>"
" <method name='GetAudioConnected'>"
" <arg type='i' name='status' direction='out'/>"
" </method>"
" <method name='IsHfConnected'>"
" <arg type='b' name='status' direction='out'/>"
" </method>"
+" <method name='IsInbandRingtoneSupported'>"
+" <arg type='b' name='status' direction='out'/>"
+" </method>"
" </interface>"
"</node>";
-static bt_hf_agent_info_t bt_hf_info;
+static bt_hf_agent_info_t bt_hf_info = {0,};
static gboolean is_hf_connected = FALSE;
static int32_t current_codec_id = BT_HF_CODEC_ID_CVSD;
static int32_t sco_audio_connected = BT_HF_AUDIO_DISCONNECTED;
char *number;
} hf_call_list_info_t;
+#define BT_HF_SIG_NUM 3
+static struct sigaction bt_hf_sigoldact[BT_HF_SIG_NUM];
+static int bt_hf_sig_to_handle[] = { SIGABRT, SIGSEGV, SIGTERM };
+
static GError *__bt_hf_agent_set_error(bt_hf_agent_error_t error);
static gboolean __bt_hf_agent_emit_property_changed(
static gboolean __bt_get_supported_indicators(bt_hf_agent_info_t *bt_hf_info);
static gboolean __bt_hf_agent_connection(gint32 fd, const gchar * object_path);
static gboolean __bt_hf_agent_connection_release(void);
+static void __bt_hf_agent_handle_call_list(bt_hf_agent_info_t *bt_hf_info);
struct indicator {
gchar descr[BT_HF_INDICATOR_DESCR_SIZE];
static int _hf_agent_voice_recognition(GDBusMethodInvocation *context,
unsigned int status);
+static gboolean bt_hf_agent_sco_connect(void);
+
static gboolean bt_hf_agent_sco_disconnect(void);
static int _hf_agent_send_dtmf(GDBusMethodInvocation *context, char *dtmf);
static int hf_handle_rx_at_cmd(bt_hf_agent_info_t *bt_hf_info, const char *buf);
-void __bt_hf_agent_print_at_buffer(char *message, const char *buf)
+static void __on_log_glib(const gchar *log_domain, GLogLevelFlags log_level,
+ const gchar *msg, gpointer user_data)
+{
+ ERR_C("%s", msg);
+}
+
+static void __bt_hf_agent_print_at_buffer(char *message, const char *buf)
{
int i = 0;
case BT_HF_AGENT_ERROR_NO_MEMORY:
return g_error_new(BT_HF_AGENT_ERROR, error,
BT_ERROR_NO_MEMORY);
+ case BT_HF_AGENT_ERROR_NO_DATA:
+ return g_error_new(BT_HF_AGENT_ERROR, error,
+ BT_ERROR_NO_DATA);
case BT_HF_AGENT_ERROR_I_O_ERROR:
return g_error_new(BT_HF_AGENT_ERROR, error,
BT_ERROR_I_O_ERROR);
ERR("deviced error!");
}
+static gboolean __clcc_timer_func(gpointer data)
+{
+ GVariant *call_var;
+ GError *err;
+
+ DBG("+");
+
+ if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
+ DBG("NOT CONNECTED");
+ err = __bt_hf_agent_set_error(BT_HF_AGENT_ERROR_NOT_CONNECTED);
+ g_dbus_method_invocation_return_gerror((GDBusMethodInvocation *) data, err);
+ g_error_free(err);
+ clcc_timer = 0;
+ return FALSE;
+ }
+
+ if (send_flag && clcc_retry_count > 0) {
+ clcc_retry_count--;
+ DBG("Still pending. try later (remained [%d] times)", clcc_retry_count);
+ return TRUE;
+ }
+
+ clcc_timer = 0;
+
+ call_var = bt_hf_agent_request_call_list();
+ if (!call_var) {
+ INFO("NOT AVAILABLE");
+ err = __bt_hf_agent_set_error(BT_HF_AGENT_ERROR_NOT_AVAILABLE);
+ g_dbus_method_invocation_return_gerror((GDBusMethodInvocation *) data, err);
+ g_error_free(err);
+ return FALSE;
+ }
+
+ INFO("return call list info");
+ g_dbus_method_invocation_return_value((GDBusMethodInvocation *) data, call_var);
+ return FALSE;
+}
+
+static gboolean __clcc_async_timer_func(gpointer data)
+{
+ DBG("+");
+
+ if (send_flag && clcc_async_retry_count > 0) {
+ clcc_async_retry_count--;
+ ERR("Still pending. try later (remained [%d] times)", clcc_async_retry_count);
+ return TRUE;
+ }
+
+ clcc_async_timer = 0;
+
+ __bt_hf_agent_handle_call_list(&bt_hf_info);
+ g_dbus_method_invocation_return_value((GDBusMethodInvocation*)data, NULL);
+
+ INFO("update_call_list succeeded");
+
+ return FALSE;
+}
+
static void __hf_agent_method(GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
if (ret)
goto fail;
+ } else if (g_strcmp0(method_name, "ScoConnect") == 0) {
+ DBG("Going to call ScoConnect");
+ if (!bt_hf_agent_sco_connect()) {
+ ret = BT_HF_AGENT_ERROR_INTERNAL;
+ goto fail;
+ }
+
+ g_dbus_method_invocation_return_value(context, NULL);
} else if (g_strcmp0(method_name, "ScoDisconnect") == 0) {
DBG("Going to call ScoDisconnect");
if (!bt_hf_agent_sco_disconnect()) {
g_variant_get(parameters, "(&s)", &cmd);
DBG("Going to call SendAtCmd\n");
- ret = bt_hf_agent_send_at_cmd(context, cmd);
+ ret = bt_hf_agent_send_at_cmd(NULL, cmd);
if (ret)
goto fail;
+ g_dbus_method_invocation_return_value(context, NULL);
} else if (g_strcmp0(method_name, "ReleaseAndAccept") == 0) {
DBG("Going to call ReleaseAndAccept");
} else if (g_strcmp0(method_name, "RequestCallList") == 0) {
GVariant *call_var;
- DBG("Going to call RequestCallList");
- call_var = bt_hf_agent_request_call_list();
- if (!call_var) {
+ INFO("Going to call RequestCallList (send_flag[%d])", send_flag);
+
+ if (send_flag) {
+ INFO("Send_flag is true. Try to send CLCC later");
+ clcc_retry_count = CLCC_RETRY_COUNT;
+ clcc_timer = g_timeout_add(CLCC_RETRY_TIMER, __clcc_timer_func, context);
+ } else {
+ call_var = bt_hf_agent_request_call_list();
+ if (!call_var) {
+ ret = BT_HF_AGENT_ERROR_NOT_AVAILABLE;
+ goto fail;
+ }
+ g_dbus_method_invocation_return_value(context, call_var);
+ }
+ } else if (g_strcmp0(method_name, "RequestCallListAsync") == 0) {
+ INFO("Going to call RequestCallListAsync (send_flag[%d])", send_flag);
+
+ if (clcc_async_timer > 0) {
ret = BT_HF_AGENT_ERROR_NOT_AVAILABLE;
goto fail;
}
- g_dbus_method_invocation_return_value(context, call_var);
+ if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
+ ret = BT_HF_AGENT_ERROR_NOT_CONNECTED;
+ goto fail;
+ }
+ if (bt_hf_info.ciev_call_status == 0 &&
+ bt_hf_info.ciev_call_setup_status == 0) {
+ ret = BT_HF_AGENT_ERROR_NO_DATA;
+ goto fail;
+ }
+
+ if (send_flag) {
+ INFO("Send_flag is true. Try to send CLCC later");
+ clcc_async_retry_count = CLCC_RETRY_COUNT;
+ clcc_async_timer = g_timeout_add(CLCC_RETRY_TIMER, __clcc_async_timer_func, context);
+ } else {
+ __bt_hf_agent_handle_call_list(&bt_hf_info);
+ g_dbus_method_invocation_return_value(context, NULL);
+ }
} else if (g_strcmp0(method_name, "GetAudioConnected") == 0) {
DBG("Going to call GetAudioConnected");
g_dbus_method_invocation_return_value(context,
g_dbus_method_invocation_return_value(context,
g_variant_new("(b)", is_hf_connected));
+ } else if (g_strcmp0(method_name, "IsInbandRingtoneSupported") == 0) {
+ gboolean is_supported = FALSE;
+
+ if (is_hf_connected == FALSE) {
+ ret = BT_HF_AGENT_ERROR_NOT_CONNECTED;
+ goto fail;
+ }
+
+ if (bt_hf_info.inband_ringtone_support)
+ is_supported = TRUE;
+ else
+ is_supported = FALSE;
+
+ INFO("IsInbandRingtoneSupported : %s", is_supported ?
+ "Supported" : "NotSupported");
+ g_dbus_method_invocation_return_value(context,
+ g_variant_new("(b)", is_supported));
}
+
INFO("-");
return;
return TRUE;
}
-static GDBusProxy *__bt_hf_gdbus_init_service_proxy(const gchar *service,
- const gchar *path, const gchar *interface)
+static GDBusProxy *__bt_hf_gdbus_init_profile_proxy(void)
{
DBG("+");
proxy = g_dbus_proxy_new_sync(conn,
G_DBUS_PROXY_FLAGS_NONE, NULL,
- service, path,
- interface, NULL, &err);
+ BLUEZ_SERVICE_NAME, "/org/bluez",
+ BLUEZ_PROFILE_MGMT_INTERFACE, NULL, &err);
if (!proxy) {
if (err) {
return NULL;
}
+ profile_gproxy = proxy;
+
DBG("-");
return proxy;
}
+static GDBusProxy *__bt_hf_gdbus_get_profile_proxy(void)
+{
+ return (profile_gproxy) ? profile_gproxy :
+ __bt_hf_gdbus_init_profile_proxy();
+}
+
static GDBusProxy *__bt_hf_gdbus_get_service_proxy(const gchar *service,
const gchar *path, const gchar *interface)
{
- return (service_gproxy) ? service_gproxy :
- __bt_hf_gdbus_init_service_proxy(service,
- path, interface);
+ DBG("+");
+
+ GDBusProxy *proxy;
+ GError *err = NULL;
+ GDBusConnection *conn;
+
+ conn = __bt_hf_get_gdbus_connection();
+ if (!conn) {
+ ERR("Unable to get connection");
+ return NULL;
+ }
+
+ proxy = g_dbus_proxy_new_sync(conn,
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ service, path,
+ interface, NULL, &err);
+
+ if (!proxy) {
+ if (err) {
+ ERR("Unable to create proxy: %s", err->message);
+ g_clear_error(&err);
+ }
+ return NULL;
+ }
+
+ DBG("-");
+ return proxy;
}
static char __bt_hf_agent_get_tx_power(char *address)
error->code, error->message);
g_clear_error(&error);
}
+ g_object_unref(proxy);
return result;
}
g_variant_get(ret, "(y)", &result);
DBG("TX power level = %d", result);
g_variant_unref(ret);
+ g_object_unref(proxy);
+
return result;
}
g_clear_error(&error);
}
+ g_object_unref(proxy);
return BT_HF_AGENT_ERROR_INTERNAL;
}
g_variant_unref(ret);
+ g_object_unref(proxy);
return BT_HF_AGENT_ERROR_NONE;
}
gboolean __bt_hf_agent_add_queue(GDBusMethodInvocation *context, char *at,
int count, gboolean pending_flag)
{
- int i, len;
+ int i, len, timer_id;
if (bt_hf_info.slc == FALSE)
return FALSE;
len = g_slist_length(bt_hf_info.cmd_send_queue);
for (i = 0; i < len; ++i) {
cmd = g_slist_nth_data(bt_hf_info.cmd_send_queue, i);
- DBG("Q> %.6s[%d]", cmd->at_cmd, cmd->id);
+ if (cmd)
+ DBG("Q> %.6s[%d]", cmd->at_cmd, cmd->id);
}
/* We need to have base timeout + tolerance value to process other request */
if (strstr(at, "ATD") || strstr(at, "BLDN")) {
/* Android 15 seconds timeout in case of ATD timeout in flight mode */
- cmd->timer_id = g_timeout_add_seconds(BT_HF_COMMAND_TIMEOUT * 5 + len,
+ timer_id = g_timeout_add_seconds(BT_HF_COMMAND_TIMEOUT * 5 + len,
__bt_hf_monitor_timer_cb, cmd);
+ if (cmd)
+ cmd->timer_id = timer_id;
} else {
- cmd->timer_id = g_timeout_add_seconds(BT_HF_COMMAND_TIMEOUT + len,
+ timer_id = g_timeout_add_seconds(BT_HF_COMMAND_TIMEOUT + len,
__bt_hf_monitor_timer_cb, cmd);
+ if (cmd)
+ cmd->timer_id = timer_id;
}
return TRUE;
}
ret = g_dbus_connection_emit_signal(connection,
NULL, path, interface,
"PropertyChanged",
- g_variant_new("s(v)", name, property),
+ g_variant_new("(sv)", name, property),
&error);
if (!ret) {
if (error != NULL) {
Below methods exposed to Bluez
*/
+static gboolean __bt_hf_agent_launch_call_app(void)
+{
+ bundle *b;
+ bool is_running;
+
+ DBG("+");
+ app_manager_is_running(CALL_ALIAS_APP_ID, &is_running);
+ if (is_running) {
+ DBG("Call app is already started");
+ return TRUE;
+ }
+
+ b = bundle_create();
+ if (NULL == b) {
+ ERR("bundle_create() Failed");
+ return FALSE;
+ }
+
+ bundle_add(b, "launch-type", "BT_LAUNCH");
+
+ bundle_add(b, "carrier-type", "BT");
+ DBG("For 3G, carrier-type: BT has been added");
+ aul_launch_app_async(CALL_ALIAS_APP_ID, b);
+ bundle_free(b);
+
+ INFO("-aul_launch_app_async -");
+
+ return TRUE;
+}
+
static void __bt_hf_agent_handle_ind_change(bt_hf_agent_info_t *bt_hf_info,
guint index, gint value)
{
BT_HF_SERVICE_INTERFACE,
"CallEnded", NULL);
bt_hf_info->call_active = FALSE;
+
+ if (bt_hf_info->ciev_call_setup_status == 0) {
+ __bt_hf_agent_emit_signal(gdbus_conn,
+ BT_HF_AGENT_OBJECT_PATH,
+ BT_HF_SERVICE_INTERFACE,
+ "CallIdle", NULL);
+ }
}
} else if (!strcmp(name, "\"callsetup\"")) {
bt_hf_info->ciev_call_setup_status = value;
if (value == 0 && bt_hf_info->is_dialing) {
+ bt_hf_info->is_dialing = FALSE;
__bt_hf_agent_emit_signal(conn,
BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE,
"CallTerminated",
NULL);
- bt_hf_info->is_dialing = FALSE;
- } else if (!bt_hf_info->is_dialing && value > 0)
+ } else if (!bt_hf_info->is_dialing && value > 0) {
bt_hf_info->is_dialing = TRUE;
+ }
- if (bt_hf_info->ciev_call_status == 0 &&
- bt_hf_info->ciev_call_setup_status == 0)
+ if (bt_hf_info->ciev_call_setup_status == 1) {
__bt_hf_agent_emit_signal(gdbus_conn,
BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE,
- "CallEnded", NULL);
-
+ "CallSetupIncoming", NULL);
+ if (__bt_hf_agent_launch_call_app() == FALSE)
+ DBG("call app launching failed");
+ } else if (bt_hf_info->ciev_call_setup_status == 2) {
+ __bt_hf_agent_emit_signal(gdbus_conn,
+ BT_HF_AGENT_OBJECT_PATH,
+ BT_HF_SERVICE_INTERFACE,
+ "CallSetupDialing", NULL);
+ } else if (bt_hf_info->ciev_call_setup_status == 3) {
+ __bt_hf_agent_emit_signal(gdbus_conn,
+ BT_HF_AGENT_OBJECT_PATH,
+ BT_HF_SERVICE_INTERFACE,
+ "CallSetupAlerting", NULL);
+ } else if (bt_hf_info->ciev_call_status == 0 &&
+ bt_hf_info->ciev_call_setup_status == 0) {
+ __bt_hf_agent_emit_signal(gdbus_conn,
+ BT_HF_AGENT_OBJECT_PATH,
+ BT_HF_SERVICE_INTERFACE,
+ "CallIdle", NULL);
+ }
} else if (!strcmp(name, "\"callheld\"")) {
if (value == 0) { /* No calls held*/
__bt_hf_agent_emit_signal(conn,
BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE,
"CallsSwapped", NULL);
- bt_hf_info->is_dialing = FALSE;
} else {
/*Call on hold, no active call*/
__bt_hf_agent_emit_signal(conn,
BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE,
"CallOnHold", NULL);
- bt_hf_info->is_dialing = FALSE;
}
- } else if (!strcmp(name, "\"service\""))
+ } else if (!strcmp(name, "\"service\"")) {
+ if (value < 0 || value > 1)
+ ERR("Out of range");
+ else
__bt_hf_agent_emit_property_changed(conn,
BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE,
"RegistrationStatus",
- g_variant_new("(q)", value));
- else if (!strcmp(name, "\"signal\""))
+ g_variant_new("q", value));
+ } else if (!strcmp(name, "\"signal\"")) {
+ if (value < 0 || value > 5)
+ ERR("Out of range");
+ else
__bt_hf_agent_emit_property_changed(conn,
BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE, "SignalStrength",
- g_variant_new("(q)", value));
- else if (!strcmp(name, "\"roam\""))
+ g_variant_new("q", value));
+ } else if (!strcmp(name, "\"roam\"")) {
+ if (value < 0 || value > 1)
+ ERR("Out of range");
+ else
__bt_hf_agent_emit_property_changed(conn,
BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE, "RoamingStatus",
- g_variant_new("(q)", value));
- else if (!strcmp(name, "\"battchg\""))
+ g_variant_new("q", value));
+ } else if (!strcmp(name, "\"battchg\"")) {
+ if (value < 0 || value > 5)
+ ERR("Out of range");
+ else
__bt_hf_agent_emit_property_changed(conn,
BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE, "BatteryCharge",
- g_variant_new("(q)", value));
-}
-
-
-static gboolean __bt_hf_agent_launch_call_app(const char *launch_type,
- const char *number)
-{
- bundle *b;
- bool is_running;
-
- DBG("+");
- app_manager_is_running(CALL_APP_ID, &is_running);
- if (is_running)
- return FALSE;
-
- DBG_SECURE("Launch type = %s, number(%s)", launch_type, number);
-
- b = bundle_create();
- if (NULL == b) {
- ERR("bundle_create() Failed");
- return FALSE;
+ g_variant_new("q", value));
}
-
- bundle_add(b, "launch-type", launch_type);
-
- if (strlen(number) != 0)
- bundle_add(b, "number", number);
-
- bundle_add(b, "carrier-type", "BT");
- DBG("For 3G, carrier-type: BT has been added");
-
- aul_launch_app(CALL_APP_ID, b);
- bundle_free(b);
-
- DBG("-");
-
- return TRUE;
}
static void __bt_hf_agent_handle_voice_activation(gint value)
return;
}
+static int __bt_hf_agent_handle_clip(bt_hf_agent_info_t *bt_hf_info,
+ const gchar *buf)
+{
+ GDBusConnection *conn;
+ gchar *clip;
+ gchar number[BT_HF_CALLER_NUM_SIZE];
+ gchar *sep;
+ char fmt_str[BT_HF_FMT_STR_SIZE];
+ int len = strlen(buf);
+
+ DBG("__bt_hf_agent_handle_clip +");
+ if (len > BT_HF_CALLER_NUM_SIZE + 10) {
+ ERR("buf len %d is too long", len);
+ return 1;
+ }
+
+ if ((clip = strstr(buf, "\r\n+CLIP"))) {
+ snprintf(fmt_str, sizeof(fmt_str), "\r\n+CLIP: \"%%%ds", (int)(sizeof(number) - 1));
+ if (sscanf(clip, fmt_str, number) == 1) {
+ sep = strchr(number, '"');
+ sep[0] = '\0';
+
+ clip = number;
+
+ conn = __bt_hf_get_gdbus_connection();
+ if (!conn) {
+ ERR("Unable to get connection");
+ return 1;
+ }
+
+ __bt_hf_agent_emit_signal(conn,
+ BT_HF_AGENT_OBJECT_PATH,
+ BT_HF_SERVICE_INTERFACE, "Ring",
+ g_variant_new("(s)", clip));
+ } else {
+ ERR_SECURE("CLIP '%s' is Call Incoming", buf);
+ return 1;
+ }
+ }
+ DBG("__bt_hf_agent_handle_clip -");
+ return 0;
+}
+
static int __bt_hf_agent_handle_ccwa(bt_hf_agent_info_t *bt_hf_info,
const gchar *buf)
{
GDBusConnection *conn;
gchar *ccwa;
- gchar *number;
- gchar *ptr;
+ gchar number[BT_HF_CALLER_NUM_SIZE];
gchar *sep;
char fmt_str[BT_HF_FMT_STR_SIZE];
int len = strlen(buf);
if ((ccwa = strstr(buf, "\r\n+CCWA"))) {
snprintf(fmt_str, sizeof(fmt_str), "\r\n+CCWA: \"%%%ds",
- BT_HF_CALLER_NUM_SIZE - 1);
- if ((ptr = strstr(ccwa, "\"")) != NULL) {
- number = ptr + 1;
+ (int)(sizeof(number) - 1));
+ if (sscanf(ccwa, fmt_str, number) == 1) {
sep = strchr(number, '"');
sep[0] = '\0';
return 0;
}
+static void __bt_hf_agent_handle_bsir(bt_hf_agent_info_t *bt_hf_info,
+ gint value)
+{
+ INFO("new value : %d", value);
+
+ if (value == 1)
+ bt_hf_info->inband_ringtone_support = TRUE;
+ else
+ bt_hf_info->inband_ringtone_support = FALSE;
+
+ return;
+}
+
static GSList *__bt_hf_prepare_call_list(const char *buf)
{
GSList *call_list = NULL;
char *ptr = NULL;
char *temp = NULL;
char *sp;
- char *stop;
char delim_sep[] = "\r\n";
char temp_buf[BT_HF_DATA_BUF_SIZE] = {0,};
call_info = g_new0(hf_call_list_info_t, 1);
- /* str format : "+CLCC: %1d,%1d, %1d, %1d, %1d" */
- if ((ptr = strchr(str, ':')) != NULL) {
- call_info->idx = strtol(ptr + 1, &stop, 10);
- call_info->dir = strtol(stop + 1, &stop, 10);
- call_info->status = strtol(stop + 1, &stop, 10);
- call_info->mode = strtol(stop + 1, &stop, 10);
- call_info->multi_party = strtol(stop + 1, &stop, 10);
-
- DBG("Index = [%d], Direction = [%d], Status = [%d], Mode = [%d], Multi_party = [%d]\n",
- call_info->idx, call_info->dir, call_info->status,
- call_info->mode, call_info->multi_party);
- }
+ sscanf(str, "+CLCC: %1d,%1d, %1d, %1d, %1d",
+ &call_info->idx, &call_info->dir,
+ &call_info->status, &call_info->mode,
+ &call_info->multi_party);
+ DBG("Index = [%d], Direction = [%d], Status = [%d], Mode = [%d], Multi_party = [%d]\n",
+ call_info->idx, call_info->dir, call_info->status,
+ call_info->mode, call_info->multi_party);
ptr = strstr(str, "\"");
if (ptr) {
DBG("-");
}
-static void __bt_hf_launch_call_using_call_list(GSList *call_list,
- bt_hf_agent_info_t *bt_hf_info)
+static void __bt_hf_launch_call_using_call_list(GSList *call_list)
{
guint len;
- const char *launch_type_str;
- hf_call_list_info_t *call_info;
DBG("+");
if (call_list == NULL)
len = g_slist_length(call_list);
- while (len--) {
- call_info = g_slist_nth_data(call_list, len);
-
- /* Launch based on below conditions
- * DC - Active call which is initiated from H
- * MR - Alerting call which is initiated from H
- * MT - Incoming call */
- if (call_info->status == BT_HF_CALL_STAT_ACTIVE) {
- launch_type_str = "DC";
- } else {
- if (call_info->dir == BT_HF_CALL_DIR_INCOMING)
- launch_type_str = "MT";
- else
- launch_type_str = "MR";
- }
+ if (len > 0 && __bt_hf_agent_launch_call_app() == FALSE)
+ DBG("call app launching failed");
- if (__bt_hf_agent_launch_call_app(launch_type_str,
- call_info->number) == FALSE)
- DBG("call app launching failed");
- }
DBG("-");
}
while (call_count--) {
call_info = g_slist_nth_data(call_list, call_count);
- INFO("Idx=%d, Dir=%d, status=%d, mode=%d, mparty=%d",
- call_info->idx, call_info->dir, call_info->status,
- call_info->mode, call_info->multi_party);
- caller = call_info->number;
-
- g_variant_builder_add(builder, "(siiii)",
- caller, call_info->dir, call_info->status,
- call_info->multi_party, call_info->idx);
+ if (call_info) {
+ INFO("Idx=%d, Dir=%d, status=%d, mode=%d, mparty=%d",
+ call_info->idx, call_info->dir, call_info->status,
+ call_info->mode, call_info->multi_party);
+ caller = call_info->number;
+
+ g_variant_builder_add(builder, "(siiii)",
+ caller, call_info->dir, call_info->status,
+ call_info->multi_party, call_info->idx);
+ }
}
var_data = g_variant_new("(ia(siiii))",
g_slist_length(call_list), builder);
GDBusConnection *conn;
GVariant *var_data;
- var_data = __bt_hf_agent_get_call_status_info(call_list);
conn = __bt_hf_get_gdbus_connection();
if (!conn) {
ERR("Unable to get connection");
- return;
- }
-
- if (conn)
+ } else {
+ var_data = __bt_hf_agent_get_call_status_info(call_list);
__bt_hf_agent_emit_signal(conn,
BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE,
"CallStatusUpdate",
var_data);
+ }
}
static void __bt_hf_agent_handle_call_list(bt_hf_agent_info_t *bt_hf_info)
__bt_hf_unlock_display();
}
-static void __bt_hf_agent_request_call_list_info(bt_hf_agent_info_t *bt_hf_info,
- guint index)
-{
- char *name;
- struct indicator *ind = g_slist_nth_data(bt_hf_info->indies, index - 1);
- if (ind == NULL) {
- ERR("Indicator is NULL");
- return;
- }
- name = ind->descr;
- DBG("name : %s", name);
-
- if ((strcmp(name, "\"callsetup\"") != 0) &&
- (strcmp(name, "\"call\"") != 0) &&
- (strcmp(name, "\"callheld\"") != 0))
- return;
-
- __bt_hf_lock_display(0);
-
- __bt_hf_agent_handle_call_list(bt_hf_info);
-
- __bt_hf_unlock_display();
-
-}
-
static gboolean __bt_hf_send_available_codec(bt_hf_agent_info_t *bt_hf_info, int send_only)
{
gchar buf[BT_HF_DATA_BUF_SIZE];
{
gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
gboolean ret;
+ int retval;
if (codec_id != BT_HF_CODEC_ID_CVSD && codec_id != BT_HF_CODEC_ID_MSBC) {
INFO("Codec id doesn't match, so send available codec again");
ret = __bt_hf_send_available_codec(bt_hf_info, 1);
- if (!ret)
+ if (FALSE == ret)
ERR("Failed to send avalable codec");
return;
}
/* HF should be ready accpet SCO connection before sending theresponse for
"\r\n+BCS=>Codec ID\r\n", Keep the BT chip ready to recevie encoded SCO data */
- ret = _hf_agent_codec_setup(bt_hf_info->remote_addr, codec_id);
+ retval = _hf_agent_codec_setup(bt_hf_info->remote_addr, codec_id);
+ if (retval) {
+ ERR("_hf_agent_codec_setup : Failed [%d]", retval);
+ }
snprintf(cmd_buf, sizeof(cmd_buf), BT_HF_CODEC_SELECT, codec_id);
bt_hf_info->context = NULL;
-
ret = __bt_hf_send_only(bt_hf_info, cmd_buf, strlen(cmd_buf));
- if (!ret)
- ERR("Failed to select the Codec");
+ if (FALSE == ret) {
+ ERR("__bt_hf_send_only : FALSE");
+ }
}
static int __bt_hf_agent_handler_ciev(bt_hf_agent_info_t *bt_hf_info, const char *buf)
{
- gchar *indicator;
+ gchar indicator[BT_HF_INDICATOR_DESCR_SIZE + 4];
gchar *sep;
- gchar *ptr;
gint value;
guint index;
char fmt_str[BT_HF_FMT_STR_SIZE];
snprintf(fmt_str, sizeof(fmt_str), "\r\n+CIEV:%%%ds\r\n",
BT_HF_INDICATOR_DESCR_SIZE + 4 - 1);
- if ((ptr = strchr(buf, ':')) != NULL) {
- indicator = ptr + 1;
+ if (sscanf(buf, fmt_str, indicator) == 1) {
sep = strchr(indicator, ',');
sep[0] = '\0';
sep += 1;
index = atoi(indicator);
value = atoi(sep);
__bt_hf_agent_handle_ind_change(bt_hf_info, index, value);
-
- if (bt_hf_info->ciev_call_status == 0 &&
- bt_hf_info->ciev_call_setup_status == 0)
- INFO("No active call");
- else
- /* Request CLCC based on indicator change for call/callsetup/callHeld */
- __bt_hf_agent_request_call_list_info(bt_hf_info, index);
}
DBG("--------- __bt_hf_agent_handler_ciev ------------");
return 0;
static int __bt_hf_agent_handler_clip(bt_hf_agent_info_t *bt_hf_info, const char *buf)
{
DBG("+++++++++ __bt_hf_agent_handler_clip ++++++++");
+ __bt_hf_agent_handle_clip(bt_hf_info, buf);
DBG("---------__bt_hf_agent_handler_clip --------");
return 0;
{
DBG("+++++++++ __bt_hf_agent_handler_bvra +++++++++");
gint value;
- gchar *ptr;
- gchar *stop;
- if ((ptr = strstr(buf, "BVRA:")) != NULL) {
- value = strtol(ptr + 5, &stop, 10);
+ if (sscanf(buf, "\r\n+BVRA:%1d\r\n", &value) == 1)
__bt_hf_agent_handle_voice_activation(value);
- }
DBG("---------__bt_hf_agent_handler_bvra --------");
return 0;
static int __bt_hf_agent_handler_bcs(bt_hf_agent_info_t *bt_hf_info, const char *buf)
{
guint codec_id;
- gchar *ptr;
- gchar *stop;
DBG("+++++++++ __bt_hf_agent_handler_bcs +++++++++-");
- if ((ptr = strstr(buf, "BCS:")) != NULL) {
- codec_id = strtol(ptr + 4, &stop, 10);
+ if (sscanf(buf, "\r\n+BCS:%3d\r\n", &codec_id))
__bt_hf_agent_handle_codec_select(bt_hf_info, codec_id);
- }
DBG("---------__bt_hf_agent_handler_bcs --------");
return 0;
static int __bt_hf_agent_handler_vgs(bt_hf_agent_info_t *bt_hf_info, const char *buf)
{
gint value;
- gchar *ptr;
- gchar *stop;
+ int ret = 0;
DBG("+++++++++ __bt_hf_agent_handler_vgs +++++++++");
- if ((ptr = strstr(buf, "VGS:")) != NULL) {
- value = strtol(ptr + 4, &stop, 10);
+ if (buf[6] == ':')
+ ret = sscanf(buf, "\r\n+VGS:%2d\r\n", &value);
+ else if (buf[6] == '=')
+ ret = sscanf(buf, "\r\n+VGS=%2d\r\n", &value);
+ if (ret)
__bt_hf_agent_handle_speaker_gain(value);
- }
DBG("---------__bt_hf_agent_handler_vgs --------");
const char *buf)
{
gint app_id = 0;
- char *msg = NULL;
+ char msg[BT_HF_DATA_BUF_SIZE];
char fmt_str[BT_HF_CMD_BUF_SIZE];
- char *ptr = NULL;
- char *save_ptr = NULL;
- char *stop = NULL;
DBG("+++++++++ __bt_hf_agent_handler_xsat +++++++++");
snprintf(fmt_str, sizeof(fmt_str), "\r\n+XSAT:%%d,%%%ds\r\n",
(int)(sizeof(msg) - 1));
- ptr = strstr(buf, "XSAT:");
- if (ptr)
- app_id = strtol(ptr + 5, &stop, 10);
-
- if (stop)
- msg = strtok_r(stop + 1, "\\", &save_ptr);
-
- if (app_id > 0 && msg) {
+ if (sscanf(buf, fmt_str, &app_id, msg)) {
if (app_id == 2 && strstr(msg, "READTXPOWER")) {
char cmd_buf[BT_HF_CMD_BUF_SIZE * 2] = {0, };
char power = __bt_hf_agent_get_tx_power(bt_hf_info->remote_addr);
return 0;
}
+static int __bt_hf_agent_handler_bsir(bt_hf_agent_info_t *bt_hf_info, const char *buf)
+{
+ DBG("+++++++++ __bt_hf_agent_handler_bsir +++++++++");
+ gint value;
+ if (sscanf(buf, "\r\n+BSIR:%1d\r\n", &value) == 1)
+ __bt_hf_agent_handle_bsir(bt_hf_info, value);
+
+ DBG("---------__bt_hf_agent_handler_bsir --------");
+ return 0;
+}
+
static int __bt_hf_agent_handler_cme_error(bt_hf_agent_info_t *bt_hf_info,
const char *buf)
{
__bt_hf_agent_emit_signal(conn,
BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE,
- "CallTerminated",
+ "FailedToDial",
NULL);
}
__bt_hf_agent_emit_signal(conn, BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE,
- "CallTerminated",
+ "FailedToDial",
NULL);
}
__bt_hf_clear_prev_sent_cmd();
__bt_hf_agent_emit_signal(conn, BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE,
- "CallTerminated",
+ "FailedToDial",
NULL);
}
if (call_list == NULL)
goto done;
- __bt_hf_launch_call_using_call_list(call_list, bt_hf_info);
+ __bt_hf_launch_call_using_call_list(call_list);
__bt_hf_agent_send_call_status_info(call_list);
return 0;
}
-static struct hf_event hf_event_callbacks[] = {
+static bt_hf_event hf_event_callbacks[] = {
{ "\r\n+CIEV:", __bt_hf_agent_handler_ciev },
{ "\r\nRING", __bt_hf_agent_handler_ring },
{ "\r\n+CLIP:", __bt_hf_agent_handler_clip },
{ "\r\n+BVRA:", __bt_hf_agent_handler_bvra },
{ "\r\n+BCS:", __bt_hf_agent_handler_bcs },
- { "\r\n+VGS:", __bt_hf_agent_handler_vgs },
+ { "\r\n+VGS", __bt_hf_agent_handler_vgs },
{ "\r\n+CCWA:", __bt_hf_agent_handler_ccwa },
{ "\r\n+XSAT:", __bt_hf_agent_handler_xsat },
{"\r\n+CLCC:", __bt_hf_agent_handler_clcc },
+ {"\r\n+BSIR:", __bt_hf_agent_handler_bsir },
{ 0 }
};
-static struct hf_event hf_event_resp_callbacks[] = {
+static bt_hf_event hf_event_resp_callbacks[] = {
{ "\r\n+CME ERROR:", __bt_hf_agent_handler_cme_error },
{ "\r\nOK\r\n", __bt_hf_agent_handler_response_ok },
{ "ERROR", __bt_hf_agent_handler_response_err },
len = g_slist_length(bt_hf_info->cmd_send_queue);
for (i = 0; i < len; ++i) {
cmd = g_slist_nth_data(bt_hf_info->cmd_send_queue, i);
- DBG("F> %.6s[%d]", cmd->at_cmd, cmd->id);
+ if (cmd)
+ DBG("F> %.6s[%d]", cmd->at_cmd, cmd->id);
}
len = g_slist_length(bt_hf_info->cmd_send_queue);
DBG("Context queue length = %d", len);
static int hf_handle_rx_at_cmd(bt_hf_agent_info_t *bt_hf_info, const char *buf)
{
- struct hf_event *ev;
+ bt_hf_event *ev;
int ret = -EINVAL;
bt_hf_agent_send_at_info *cmd = NULL;
ERR("Invalid AT command signature..\n");
return 0;
}
- pos_end = strstr(pos_end, "\r\n");
- cmd_length = (pos_end - pos_start) + 2;
+ pos_end = strstr(pos_end, "\r\n");
+ cmd_length = (pos_end - pos_start) + 2;
INFO("CLCC balance Cmd Length = %d\n", cmd_length);
memcpy(cmd_buf + cmd_buf_len, pos_start, cmd_length);
cmd_buf[cmd_buf_len + cmd_length] = '\0';
if (strstr(cmd_buf, "\r\nOK\r\n")) {
pos_end = strstr(datap, "\r\nOK\r\n");
- cmd_length = (pos_end - pos_start);
+ cmd_length = (pos_end - pos_start);
memcpy(cmd_buf + cmd_buf_len, pos_start, cmd_length);
cmd_buf[cmd_buf_len + cmd_length] = '\0';
INFO("New CLCC balance Cmd Length = %d", cmd_length);
ERR("Invalid AT command end signature..\n");
break;
}
- cmd_length = (pos_end - pos_start) + 2;
+ cmd_length = (pos_end - pos_start) + 2;
DBG("Cmd Length = %d\n", cmd_length);
+ if (cmd_length > BT_HF_DATA_BUF_SIZE - 1)
+ return FALSE;
memcpy(cmd_buf, pos_start, cmd_length);
cmd_buf[cmd_length] = '\0';
data);
send_flag++;
- DBG("Ref %d(after) on Send only buffer size =[%d] - Send <<<<<| %s",
- send_flag, count, data);
+ DBG("Ref %d(after) on Send only buffer size =[%d] - Send <<<<<",
+ send_flag, count);
return TRUE;
}
GSList *runner = indices;
gchar *cur = values - 1;
- gchar *stop;
DBG("Indicator string = %s", values);
__bt_hf_agent_print_at_buffer("Indicator values :", values);
while (cur != NULL) {
cur += 1;
- val = strtol(cur, &stop, 10);
+ sscanf(cur, "%1d", &val);
cur = strchr(cur, ',');
ind = g_slist_nth_data(runner, 0);
- ind->value = val;
+ if (ind != NULL)
+ ind->value = val;
runner = g_slist_next(runner);
+ if (runner == NULL)
+ break;
}
return indices;
}
return result;
}
-static gboolean __bt_hf_agent_sco_conn_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
+static gboolean __bt_hf_agent_sco_disconnect_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
{
bt_hf_agent_info_t *bt_hf_info = user_data;
GDBusConnection *conn;
if (cond & (G_IO_HUP | G_IO_ERR)) {
g_io_channel_shutdown(chan, TRUE, NULL);
close(bt_hf_info->cli_sco_fd);
+ bt_hf_info->cli_sco_fd = -1;
g_io_channel_unref(chan);
DBG("Emit AudioDisconnected Signal");
return TRUE;
}
-static gboolean __bt_agent_query_and_update_call_list(gpointer data)
-{
- DBG("+");
- bt_hf_agent_info_t *bt_hf_info = data;
-
- if (bt_hf_info->cli_sco_fd >= 0)
- __bt_hf_agent_handle_call_list(bt_hf_info);
- else
- INFO("SCO Audio is already disconnected");
-
- DBG("-");
-
- return FALSE;
-}
-
static gboolean __bt_hf_agent_sco_accept_cb(GIOChannel *chan, GIOCondition cond, gpointer user_data)
{
bt_hf_agent_info_t *bt_hf_info = user_data;
g_io_channel_set_buffered(sco_io, FALSE);
g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- __bt_hf_agent_sco_conn_cb, bt_hf_info);
+ __bt_hf_agent_sco_disconnect_cb, bt_hf_info);
+
+ if (bt_hf_info->state != BT_HF_STATE_CONNECTED)
+ ERR("HFP is not yet connected");
/* S-Voice app requires the AudioConnected signal earlier */
DBG("Emit AudioConnected Signal");
* In the case of outgoing call we need to lauch the callapp.
*/
- g_idle_add(__bt_agent_query_and_update_call_list, bt_hf_info);
+ __bt_hf_agent_launch_call_app();
return TRUE;
}
-void _bt_convert_addr_string_to_type_rev(unsigned char *addr,
+static void __bt_convert_addr_string_to_type_rev(unsigned char *addr,
const char *address)
{
int i;
ret_if(address == NULL);
ret_if(addr == NULL);
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < BT_ADDRESS_LENGTH_MAX; i++) {
addr[5 - i] = strtol(address, &ptr, 16);
if (ptr[0] != '\0') {
if (ptr[0] != ':')
bdaddr_t bd_addr = {{0},};
int sco_skt;
- if (bt_hf_info->state != BT_HF_STATE_CONNECTED)
- return FALSE;
-
/* Create socket */
sco_skt = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
if (sco_skt < 0) {
DBG("Bind to address %s", bt_hf_info->remote_addr);
- _bt_convert_addr_string_to_type_rev(bd_addr.b, bt_hf_info->remote_addr);
+ __bt_convert_addr_string_to_type_rev(bd_addr.b, bt_hf_info->remote_addr);
memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
if (bind(sco_skt, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
gboolean ret;
char *buf_ptr;
- char *stop;
guint feature = BT_HF_FEATURE_EC_ANDOR_NR |
BT_HF_FEATURE_CALL_WAITING_AND_3WAY |
BT_HF_FEATURE_CLI_PRESENTATION |
- BT_HF_FEATURE_VOICE_RECOGNITION |
BT_HF_FEATURE_REMOTE_VOLUME_CONTROL |
BT_HF_FEATURE_ENHANCED_CALL_STATUS;
if (buf_ptr == NULL)
return FALSE;
- buf_ptr = strstr(buf_ptr, "BRSF:");
- bt_hf_info->ag_features = strtol(buf_ptr + 5, &stop, 10);
-
-
- if (!ret || !bt_hf_info->ag_features)
+ if (!ret || sscanf(buf_ptr, "\r\n+BRSF:%5d", &bt_hf_info->ag_features) != 1)
return FALSE;
INFO("Gateway supported features are 0x%X", bt_hf_info->ag_features);
} else
bt_hf_info->hold_multiparty_features = 0;
+ if (bt_hf_info->ag_features & BT_AG_FEATURE_INBAND_RINGTONE)
+ bt_hf_info->inband_ringtone_support = TRUE;
+ else
+ bt_hf_info->inband_ringtone_support = FALSE;
+
INFO("Service layer connection successfully established...!");
+ bt_hf_info->slc = TRUE;
+ send_flag = FALSE;
+ g_id = 0;
+ memset(global_buff, 0, sizeof(global_buff));
+ return TRUE;
+}
+
+static void __bt_establish_initialization(bt_hf_agent_info_t *bt_hf_info)
+{
+ gchar buf[BT_HF_DATA_BUF_SIZE];
+ gchar cmd_buf[BT_HF_CMD_BUF_SIZE] = {0};
+ gboolean ret;
+
__bt_hf_send_and_read(bt_hf_info, BT_HF_CALLER_IDENT_ENABLE, buf,
sizeof(BT_HF_CALLER_IDENT_ENABLE) - 1);
__bt_hf_send_and_read(bt_hf_info, BT_HF_CARRIER_FORMAT, buf,
else
ERR("BT_HF_XSAT sending failed");
- /* send Bluetooth Samsung Support Feature cmd */
- ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_BSSF, buf,
- sizeof(BT_HF_BSSF) - 1);
- if (ret)
- INFO("SLC completed with all commands");
- else
- ERR("BT_HF_BSSF sending failed");
+ if (TIZEN_PROFILE_WEARABLE) {
+ /* send Bluetooth Samsung Support Feature cmd */
+ ret = __bt_hf_send_and_read(bt_hf_info, BT_HF_BSSF, buf,
+ sizeof(BT_HF_BSSF) - 1);
+
+ /* If we got a 'OK' reply, peer AG is samsung device.
+ * Otherwise, non-samsung device */
+ if (ret && strstr(buf, "OK"))
+ bt_hf_info->is_companion_dev = TRUE;
+ else
+ bt_hf_info->is_companion_dev = FALSE;
- bt_hf_info->slc = TRUE;
- send_flag = FALSE;
- g_id = 0;
- memset(global_buff, 0, sizeof(global_buff));
- return TRUE;
+ if (ret)
+ INFO("SLC completed with [%s] device",
+ bt_hf_info->is_companion_dev ? "SS Companion" : "Other");
+ else
+ ERR("BT_HF_BSSF sending failed");
+ }
}
static void __bt_hf_agent_sigterm_handler(int signo)
{
- ERR_C("***** Signal handler came with signal %d *****", signo);
GDBusConnection *conn;
+ int i;
+
+ ERR_C("***** Signal handler came with signal %d *****", signo);
conn = __bt_hf_get_gdbus_connection();
if (!conn) {
- ERR("Unable to get connection");
- return;
+ ERR("Unable to get G-DBus connection");
+ goto done;
}
+ INFO("Getting gdbus connection done");
__bt_hf_agent_emit_signal(conn,
BT_HF_AGENT_OBJECT_PATH,
BT_HF_SERVICE_INTERFACE,
- "CallEnded", NULL);
- DBG("CallEnded Signal done");
+ "CallIdle", NULL);
+ INFO("CallEnded Signal done");
+
+ g_dbus_connection_flush(conn, NULL, NULL, NULL);
+ INFO("Flush g_dbus_connection");
+
+done:
if (gmain_loop) {
g_main_loop_quit(gmain_loop);
- DBG("Exiting");
+ INFO("Exiting");
gmain_loop = NULL;
} else {
INFO_C("Terminating HF agent");
exit(0);
}
+
+ if (signo == SIGTERM)
+ return;
+
+ for (i = 0; i < BT_HF_SIG_NUM; i++)
+ sigaction(bt_hf_sig_to_handle[i], &(bt_hf_sigoldact[i]), NULL);
+
+ raise(signo);
}
static void __bt_convert_addr_type_to_rev_string(char *address,
DBG("+");
memset(prev_cmd, 0, BT_HF_CMD_BUF_SIZE);
+ __bt_hf_agent_sco_accept(&bt_hf_info);
+
if (!__bt_establish_service_level_conn(&bt_hf_info)) {
ERR("Service Level Connection is fail");
bt_hf_info.state = BT_HF_STATE_CONNECTED;
- __bt_hf_agent_sco_accept(&bt_hf_info);
-
__bt_hf_agent_start_watch(&bt_hf_info);
remote_addr = bt_hf_info.remote_addr;
"Connected",
g_variant_new("(s)", remote_addr));
- /* Request the call list and launch call app if required */
- __bt_hf_agent_handle_call_list(&bt_hf_info);
+ /* Establish the initialization */
+ __bt_establish_initialization(&bt_hf_info);
done:
DBG("-");
int bt_device_state = VCONFKEY_BT_DEVICE_NONE;
GDBusConnection *conn;
+ if (clcc_timer) {
+ g_source_remove(clcc_timer);
+ clcc_timer = 0;
+ }
+
if (bt_hf_info.state == BT_HF_STATE_DISCONNECTED) {
ERR("hf is already disconnected");
return FALSE;
GVariantBuilder *builder;
gchar *path = NULL;
- proxy = __bt_hf_gdbus_get_service_proxy(BLUEZ_SERVICE_NAME,
- "/org/bluez", BLUEZ_PROFILE_MGMT_INTERFACE);
+ proxy = __bt_hf_gdbus_get_profile_proxy();
if (proxy == NULL)
return BT_HF_AGENT_ERROR_INTERNAL;
DBG("-");
}
+static int __bt_hf_agent_get_adapter_path(GDBusConnection *conn, char *path)
+{
+ GError *err = NULL;
+ GDBusProxy *manager_proxy = NULL;
+ GVariant *result = NULL;
+ char *adapter_path = NULL;
+
+ if (conn == NULL)
+ return BT_HF_AGENT_ERROR_INTERNAL;
+
+ manager_proxy = g_dbus_proxy_new_sync(conn,
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ BLUEZ_SERVICE_NAME,
+ "/",
+ BT_MANAGER_INTERFACE,
+ NULL, &err);
+
+ if (!manager_proxy) {
+ ERR("Unable to create proxy: %s", err->message);
+ goto fail;
+ }
+
+ result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
+ G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
+ if (!result) {
+ if (err != NULL)
+ ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
+ else
+ ERR("Fail to get DefaultAdapter");
+
+ goto fail;
+ }
+
+ if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
+ ERR("Incorrect result\n");
+ goto fail;
+ }
+
+ g_variant_get(result, "(&o)", &adapter_path);
+
+ if (adapter_path == NULL ||
+ strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) {
+ ERR("Adapter path is inproper\n");
+ goto fail;
+ }
+
+ if (path)
+ g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX);
+
+ if (g_obj_path == NULL) {
+ g_obj_path = g_strdup(adapter_path);
+ INFO("Update g_obj_path [%s]", adapter_path);
+ }
+
+ g_variant_unref(result);
+ g_object_unref(manager_proxy);
+
+ return 0;
+
+fail:
+ g_clear_error(&err);
+
+ if (result)
+ g_variant_unref(result);
+
+ if (manager_proxy)
+ g_object_unref(manager_proxy);
+
+ return BT_HF_AGENT_ERROR_INTERNAL;
+
+}
+
static void __bt_hf_agent_dbus_init(void)
{
GDBusConnection *conn;
return;
}
+ if (!__bt_hf_agent_get_adapter_path(gdbus_conn , NULL)) {
+ __bt_hf_agent_register();
+ }
+
interface_added_sig_id = g_dbus_connection_signal_subscribe(conn,
NULL, BT_MANAGER_INTERFACE, BT_INTERFACES_ADDED, NULL, NULL, 0,
__bt_hf_agent_filter_cb, NULL, NULL);
__bt_hf_agent_filter_cb, NULL, NULL);
DBG("-");
- return;
}
static void __bt_hf_agent_dbus_deinit(void)
{
-
- if (service_gproxy) {
- g_object_unref(service_gproxy);
- service_gproxy = NULL;
+ if (profile_gproxy) {
+ g_object_unref(profile_gproxy);
+ profile_gproxy = NULL;
}
if (gdbus_conn) {
g_object_unref(gdbus_conn);
gdbus_conn = NULL;
}
- return;
}
static int _hf_agent_answer_call(GDBusMethodInvocation *context)
return BT_HF_AGENT_ERROR_NONE;
}
+static gboolean bt_hf_agent_sco_connect(void)
+{
+ struct sockaddr_sco addr;
+ bdaddr_t bd_addr = {{0},};
+ int sk;
+ GIOChannel *sco_io;
+ GDBusConnection *conn;
+
+ DBG("+");
+
+ if (bt_hf_info.state != BT_HF_STATE_CONNECTED) {
+ ERR("HF RFCOMM not Connected");
+ return FALSE;
+ }
+
+ if (bt_hf_info.cli_sco_fd > 0) {
+ ERR("SCO Already connected..");
+ return FALSE;
+ }
+
+ /* Create socket */
+ sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
+ if (sk < 0) {
+ ERR("Can't create SCO socket");
+ return FALSE;
+ }
+
+ /* Bind to local address */
+ memset(&addr, 0, sizeof(addr));
+ addr.sco_family = AF_BLUETOOTH;
+ memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
+
+ if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ ERR("Can't bind socket");
+ goto error;
+ }
+
+ /* Connect to remote device */
+ memset(&addr, 0, sizeof(addr));
+ addr.sco_family = AF_BLUETOOTH;
+ __bt_convert_addr_string_to_type_rev(addr.sco_bdaddr.b, bt_hf_info.remote_addr);
+ if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ ERR("Can't connect");
+ goto error;
+ }
+
+ DBG("SCO Connected");
+
+ bt_hf_info.cli_sco_fd = sk;
+
+ sco_io = g_io_channel_unix_new(sk);
+ g_io_channel_set_close_on_unref(sco_io, TRUE);
+ g_io_channel_set_encoding(sco_io, NULL, NULL);
+ g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_channel_set_buffered(sco_io, FALSE);
+
+ g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ __bt_hf_agent_sco_disconnect_cb, &bt_hf_info);
+
+ DBG("Emit AudioConnected Signal - Outgoing SCo connection");
+ sco_audio_connected = BT_HF_AUDIO_CONNECTED;
+
+ conn = __bt_hf_get_gdbus_connection();
+ if (!conn) {
+ ERR("Unable to get connection");
+ return FALSE;
+ }
+
+ __bt_hf_agent_emit_signal(conn,
+ BT_HF_AGENT_OBJECT_PATH,
+ BT_HF_SERVICE_INTERFACE,
+ "AudioConnected", NULL);
+
+ DBG("-");
+ return TRUE;
+
+error:
+ close(sk);
+ DBG("-");
+ return FALSE;
+}
+
static gboolean bt_hf_agent_sco_disconnect(void)
{
DBG("+");
if (bt_hf_info.state != BT_HF_STATE_CONNECTED)
return BT_HF_AGENT_ERROR_NOT_CONNECTED;
- /* Should not send cmds if DUT has sent a command and waiting for response */
- if (prev_cmd[0] != 0) {
- INFO("DUT is waiting a respond for previous TX cmd. Skip sending.");
- return BT_HF_AGENT_ERROR_INTERNAL;
- }
-
strncpy(cmd_buf, atcmd, sizeof(cmd_buf) - 2);
strncat(cmd_buf, "\r", (sizeof(cmd_buf) - 1) - strlen(cmd_buf));
uint32_t hf_features = BT_HF_FEATURE_EC_ANDOR_NR |
BT_HF_FEATURE_CALL_WAITING_AND_3WAY |
BT_HF_FEATURE_CLI_PRESENTATION |
- BT_HF_FEATURE_VOICE_RECOGNITION |
BT_HF_FEATURE_REMOTE_VOLUME_CONTROL |
BT_HF_FEATURE_ENHANCED_CALL_STATUS |
BT_HF_FEATURE_CODEC_NEGOTIATION;
int main(void)
{
+ int i;
struct sigaction sa;
uint32_t hf_features;
INFO_C("### Starting Bluetooth HF agent");
+#if GLIB_VERSION_MIN_REQUIRED < GLIB_VERSION_2_36
+ g_type_init();
+#endif
hf_features = __bt_hf_agent_get_hf_features();
bt_hf_info.feature = (uint16_t) hf_features & 0x3F;
memset(&sa, 0, sizeof(sa));
sa.sa_flags = SA_NOCLDSTOP;
sa.sa_handler = __bt_hf_agent_sigterm_handler;
- sigaction(SIGTERM, &sa, NULL);
- /* Temporarily, block the below signal for debugging */
-// sigaction(SIGSEGV, &sa, NULL);
-// sigaction(SIGABRT, &sa, NULL);
+ for (i = 0; i < BT_HF_SIG_NUM; i++)
+ sigaction(bt_hf_sig_to_handle[i], &sa, &(bt_hf_sigoldact[i]));
+
+ g_log_set_default_handler(__on_log_glib, NULL);
+
gmain_loop = g_main_loop_new(NULL, FALSE);
if (gmain_loop == NULL) {
}
__bt_hf_agent_dbus_init();
+
g_main_loop_run(gmain_loop);
__bt_hf_agent_dbus_deinit();
#ifdef __cplusplus
extern "C" {
#endif
+#include <unistd.h>
+#include <dlog.h>
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/socket.h>
#undef LOG_TAG
#define LOG_TAG "BLUETOOTH_HF_AGENT"
#define ERR_C(fmt, arg...) \
SLOGI_IF(TRUE, LOG_COLOR_RED" "fmt" "LOG_COLOR_RESET, ##arg)
-
-#include <unistd.h>
-#include <dlog.h>
-#include <stdio.h>
-#include <signal.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <sys/socket.h>
+#define retv_if(expr, val) \
+ do { \
+ if (expr) { \
+ ERR("(%s) return", #expr); \
+ return (val); \
+ } \
+ } while (0)
#define BTPROTO_SCO 2
-
#define BT_HF_DATA_BUF_SIZE 1024
#define BT_HF_CMD_BUF_SIZE 32
#define BT_HF_INDICATOR_DESCR_SIZE 20
#define BT_HF_CALLER_NUM_SIZE 64 /* size of number + type */
#define BT_HF_FMT_STR_SIZE 32
+#define BT_ADDRESS_LENGTH_MAX 6
+#define BT_ADAPTER_OBJECT_PATH_MAX 50
+#define AT_CMD_BUFF_SIZE 500
+#define BT_MAX_TEL_NUM_STR 100
#define BT_HF_AGENT_ERROR (__bt_hf_agent_error_quark())
#define BT_ERROR_ALREADY_EXIST "AlreadyExists"
#define BT_ERROR_ALREADY_CONNECTED "Already Connected"
#define BT_ERROR_NO_MEMORY "No memory"
+#define BT_ERROR_NO_DATA "No data"
#define BT_ERROR_I_O_ERROR "I/O error"
#define BT_ERROR_OPERATION_NOT_AVAILABLE "Operation currently not available"
#define BT_ERROR_OPERATION_NOT_ALLOWED "Operation not allowed"
#define BT_ERROR_OPERATION_NOT_SUPPORTED "Operation not supported"
#define BT_ERROR_INVALID_FILE_DESCRIPTOR "Invalid File Descriptor"
+#define BT_HF_OK_RESPONSE "\r\nOK\r\n"
+#define BT_HF_ERROR_RESPONSE "ERROR"
+#define BT_HF_SEC_ERROR_RESPONSE "SERR"
+
+/* dbus interfaces */
+#define BT_HF_SERVICE_NAME "org.bluez.hf_agent"
+#define BT_HF_AGENT_OBJECT_PATH "/org/bluez/handsfree_agent"
+#define BT_HF_SERVICE_INTERFACE "org.tizen.HfApp"
+#define BT_HF_BLUEZ_OBJECT_PATH "/org/tizen/handsfree"
+#define BT_HF_BLUEZ_INTERFACE "org.bluez.HandsfreeAgent"
+#define BLUEZ_SERVICE_NAME "org.bluez"
+#define BLUEZ_HF_INTERFACE_NAME "org.bluez.HandsfreeGateway"
+#define BLUEZ_PROFILE_MGMT_INTERFACE "org.bluez.ProfileManager1"
+#define BT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager"
+#define BT_ADAPTER_INTERFACE "org.bluez.Adapter1"
+
+#define BT_INTERFACES_ADDED "InterfacesAdded"
+#define BT_INTERFACES_REMOVED "InterfacesRemoved"
+
+/* Handsfree features */
+#define BT_HF_FEATURE_EC_ANDOR_NR 0x0001
+#define BT_HF_FEATURE_CALL_WAITING_AND_3WAY 0x0002
+#define BT_HF_FEATURE_CLI_PRESENTATION 0x0004
+#define BT_HF_FEATURE_VOICE_RECOGNITION 0x0008
+#define BT_HF_FEATURE_REMOTE_VOLUME_CONTROL 0x0010
+#define BT_HF_FEATURE_ENHANCED_CALL_STATUS 0x0020
+#define BT_HF_FEATURE_ENHANCED_CALL_CONTROL 0x0040
+#define BT_HF_FEATURE_CODEC_NEGOTIATION 0x0080
+
+/* Audio Gateway features */
+#define BT_AG_FEATURE_3WAY 0x1
+#define BT_AG_FEATURE_NREC 0x0002
+#define BT_AG_FEATURE_VOICE_RECOGNITION 0x0004
+#define BT_AG_FEATURE_INBAND_RINGTONE 0x0008
+#define BT_AG_FEATURE_VOICE_TAG 0x0010
+#define BT_AG_FEATURE_REJECT_CALL 0x0020
+#define BT_AG_FEATURE_ENHANCED_CALL_STATUS 0x0040
+#define BT_AG_FEATURE_ENHANCED_CALL_CONTROL 0x0080
+#define BT_AG_FEATURE_EXTENDED_RES_CODE 0x100
+#define BT_AG_FEATURE_CODEC_NEGOTIATION 0x0200
+
+/* SCO Codec types */
+#define BT_HF_CODEC_ID_CVSD 1
+#define BT_HF_CODEC_ID_MSBC 2
+
+/* AT commands */
+#define BT_HF_FEATURES "AT+BRSF=%d\r" /* = 0x7F = All features supported */
+#define BT_HF_INDICATORS_SUPP "AT+CIND=?\r"
+#define BT_HF_INDICATORS_VAL "AT+CIND?\r"
+#define BT_HF_INDICATORS_ENABLE "AT+CMER=3,0,0,1\r"
+#define BT_HF_HOLD_MPTY_SUPP "AT+CHLD=?\r"
+#define BT_HF_CALLER_IDENT_ENABLE "AT+CLIP=1\r"
+#define BT_HF_CARRIER_FORMAT "AT+COPS=3,0\r"
+#define BT_HF_EXTENDED_RESULT_CODE "AT+CMEE=1\r"
+#define BT_HF_INDICATORS_ACTIVATION "AT+BIA="
+#define BT_HF_ANSWER_CALL "ATA\r"
+#define BT_HF_END_CALL "AT+CHUP\r"
+#define BT_HF_REDIAL "AT+BLDN\r"
+#define BT_HF_DIAL_NO "ATD%.100s;\r"
+#define BT_HF_VOICE_RECOGNITION "AT+BVRA=%d\r"
+#define BT_HF_XSAT "AT+XSAT=00,TY,WA\r"
+#define BT_HF_BSSF "AT+BSSF=8\r"
+#define BT_HF_CALLLIST "AT+CLCC\r"
+#define BT_HF_AVAILABLE_CODEC "AT+BAC=%d,%d\r"
+#define BT_HF_CODEC_SELECT "AT+BCS=%d\r"
+#define BT_HF_SPEAKER_GAIN "AT+VGS=%d\r"
+#define BT_HF_DTMF "AT+VTS=%s\r"
+#define BT_HF_NREC "AT+NREC=0\r"
+#define BT_HF_CALLWAIT_NOTI_ENABLE "AT+CCWA=1\r"
+#define BT_HF_RELEASE_ALL "AT+CHLD=0\r"
+#define BT_HF_RELEASE_AND_ACCEPT "AT+CHLD=1\r"
+#define BT_HF_ACCEPT_AND_HOLD "AT+CHLD=2\r"
+#define BT_HF_JOIN_CALL "AT+CHLD=3\r"
+
+#define BT_HF_MAX_SPEAKER_GAIN 15
+#define BT_HF_MIN_SPEAKER_GAIN 0
+
+/* Hold and multipary services on AG */
+#define BT_HF_CHLD_0 0x01 /* Releases all held calls or sets User Busy for a waiting call */
+#define BT_HF_CHLD_1 0x02 /* Releases all active calls and accept others */
+#define BT_HF_CHLD_1x 0x04 /* Releases specified active call only (<idx>) */
+#define BT_HF_CHLD_2 0x08 /* Places all active calls on hold and accepts others */
+#define BT_HF_CHLD_2x 0x10 /* Place all calls on hold EXCEPT the call indicated by <idx> */
+#define BT_HF_CHLD_3 0x20 /* Adds a held call to the conversation */
+#define BT_HF_CHLD_4 0x40 /* Explicit Call Transfer */
+
+enum hfp_version {
+ HFP_VERSION_1_5 = 0x0105,
+ HFP_VERSION_1_6 = 0x0106,
+ HFP_VERSION_LATEST = HFP_VERSION_1_6,
+};
+
typedef enum {
BT_HF_AGENT_ERROR_NONE,
BT_HF_AGENT_ERROR_INTERNAL,
BT_HF_AGENT_ERROR_ALREADY_EXIST,
BT_HF_AGENT_ERROR_ALREADY_CONNECTED,
BT_HF_AGENT_ERROR_NO_MEMORY,
+ BT_HF_AGENT_ERROR_NO_DATA,
BT_HF_AGENT_ERROR_I_O_ERROR,
BT_HF_AGENT_ERROR_APPLICATION,
BT_HF_AGENT_ERROR_NOT_ALLOWED,
} bt_ag_cme_error_t;
typedef enum {
+ BT_HF_STATE_DISCONNECTED,
+ BT_HF_STATE_CONNECTED
+} bt_hf_state_t;
+
+typedef enum {
+ BT_HF_AUDIO_DISCONNECTED,
+ BT_HF_AUDIO_CONNECTED
+} bt_hf_sco_state_t;
+
+typedef enum {
BT_HF_CALL_DIR_OUTGOING,
BT_HF_CALL_DIR_INCOMING,
} bt_hf_call_direction_t;
-/* Call status as per spec */
typedef enum {
BT_HF_CALL_STAT_ACTIVE,
BT_HF_CALL_STAT_HELD,
BT_HF_CALL_STAT_WAITING,
} bt_hf_call_status_t;
-enum hfp_version {
- HFP_VERSION_1_5 = 0x0105,
- HFP_VERSION_1_6 = 0x0106,
- HFP_VERSION_LATEST = HFP_VERSION_1_6,
-};
-
-/*Handsfree supported features*/
-#define BT_HF_FEATURE_EC_ANDOR_NR 0x0001
-#define BT_HF_FEATURE_CALL_WAITING_AND_3WAY 0x0002
-#define BT_HF_FEATURE_CLI_PRESENTATION 0x0004
-#define BT_HF_FEATURE_VOICE_RECOGNITION 0x0008
-#define BT_HF_FEATURE_REMOTE_VOLUME_CONTROL 0x0010
-#define BT_HF_FEATURE_ENHANCED_CALL_STATUS 0x0020
-#define BT_HF_FEATURE_ENHANCED_CALL_CONTROL 0x0040
-#define BT_HF_FEATURE_CODEC_NEGOTIATION 0x0080
-
-/*AG suported feature*/
-#define BT_AG_FEATURE_3WAY 0x1
-#define BT_AG_FEATURE_NREC 0x0002
-#define BT_AG_FEATURE_EXTENDED_RES_CODE 0x100
-#define BT_AG_FEATURE_CODEC_NEGOTIATION 0x0200
-
-#define BT_HF_CODEC_ID_CVSD 1
-#define BT_HF_CODEC_ID_MSBC 2
-
-#define BT_HF_AUDIO_DISCONNECTED 0
-#define BT_HF_AUDIO_CONNECTED 1
-
-#define BT_MAX_TEL_NUM_STR 100
-
-#define BT_HF_FEATURES "AT+BRSF=%d\r" /* = 0x7F = All features supported */
-#define BT_HF_INDICATORS_SUPP "AT+CIND=?\r"
-#define BT_HF_INDICATORS_VAL "AT+CIND?\r"
-#define BT_HF_INDICATORS_ENABLE "AT+CMER=3,0,0,1\r"
-#define BT_HF_HOLD_MPTY_SUPP "AT+CHLD=?\r"
-#define BT_HF_CALLER_IDENT_ENABLE "AT+CLIP=1\r"
-#define BT_HF_CARRIER_FORMAT "AT+COPS=3,0\r"
-#define BT_HF_EXTENDED_RESULT_CODE "AT+CMEE=1\r"
-#define BT_HF_INDICATORS_ACTIVATION "AT+BIA="
-#define BT_HF_ANSWER_CALL "ATA\r"
-#define BT_HF_END_CALL "AT+CHUP\r"
-#define BT_HF_REDIAL "AT+BLDN\r"
-#define BT_HF_DIAL_NO "ATD%.100s;\r"
-#define BT_HF_VOICE_RECOGNITION "AT+BVRA=%d\r"
-#define BT_HF_XSAT "AT+XSAT=00,TY,WA\r"
-#define BT_HF_BSSF "AT+BSSF=8\r"
-#define BT_HF_CALLLIST "AT+CLCC\r"
-#define BT_HF_AVAILABLE_CODEC "AT+BAC=%d,%d\r"
-#define BT_HF_CODEC_SELECT "AT+BCS=%d\r"
-#define BT_HF_SPEAKER_GAIN "AT+VGS=%d\r"
-#define BT_HF_DTMF "AT+VTS=%s\r"
-#define BT_HF_NREC "AT+NREC=0\r"
-#define BT_HF_CALLWAIT_NOTI_ENABLE "AT+CCWA=1\r"
-#define BT_HF_RELEASE_ALL "AT+CHLD=0\r"
-#define BT_HF_RELEASE_AND_ACCEPT "AT+CHLD=1\r"
-#define BT_HF_ACCEPT_AND_HOLD "AT+CHLD=2\r"
-#define BT_HF_JOIN_CALL "AT+CHLD=3\r"
-
-#define BT_MAX_EVENT_STR_LENGTH 50
-#define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
-
-#define BT_HF_MAX_SPEAKER_GAIN 15
-#define BT_HF_MIN_SPEAKER_GAIN 0
-
-
-typedef enum {
- BT_AGENT_EVENT_HANDSFREE_CONNECT = 0x1100,
- BT_AGENT_EVENT_HANDSFREE_DISCONNECT = 0x1200,
-} bt_hfp_agent_event_type_t;
-
-/* Hold and multipary AG features.
- * Comments below are copied from hands-free spec for reference */
-/* Releases all held calls or sets User Determined User Busy (UDUB)
- * for a waiting call */
-#define BT_HF_CHLD_0 0x01
-/* Releases all active calls (if any exist) and accepts the other
- * (held or waiting) call */
-#define BT_HF_CHLD_1 0x02
-/* Releases specified active call only <x> */
-#define BT_HF_CHLD_1x 0x04
-/* Places all active calls (if any exist) on hold and accepts the other
- * (held or waiting) call */
-#define BT_HF_CHLD_2 0x08
-/* Request private consultation mode with specified call <x> (Place all
- * calls on hold EXCEPT the call <x>) */
-#define BT_HF_CHLD_2x 0x10
-/* Adds a held call to the conversation */
-#define BT_HF_CHLD_3 0x20
-/* Connects the two calls and disconnects the subscriber from both calls
- * (Explicit Call Transfer). Support for this value and its associated
- * functionality is optional for the HF. */
-#define BT_HF_CHLD_4 0x40
-
-#define BT_HF_OK_RESPONSE "\r\nOK\r\n"
-#define BT_HF_ERROR_RESPONSE "ERROR"
-#define BT_HF_SEC_ERROR_RESPONSE "SERR"
-
-#define BT_HF_SERVICE_NAME "org.bluez.hf_agent"
-#define BT_HF_AGENT_OBJECT_PATH "/org/bluez/handsfree_agent"
-#define BT_HF_SERVICE_INTERFACE "org.tizen.HfApp"
-
-#define BT_HF_BLUEZ_OBJECT_PATH "/org/tizen/handsfree"
-#define BT_HF_BLUEZ_INTERFACE "org.bluez.HandsfreeAgent"
-
-#define BLUEZ_SERVICE_NAME "org.bluez"
-#define BLUEZ_HF_INTERFACE_NAME "org.bluez.HandsfreeGateway"
-
-#define PM_SERVICE_NAME "org.tizen.system.deviced"
-#define PM_OBJECT_PATH "/Org/Tizen/System/DeviceD/Display"
-#define PM_INTERFACE_NAME "org.tizen.system.deviced.display"
-#define AT_CMD_BUFF_SIZE 500
-#define BLUEZ_PROFILE_MGMT_INTERFACE "org.bluez.ProfileManager1"
-#define BT_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager"
-#define BT_ADAPTER_INTERFACE "org.bluez.Adapter1"
-
-#define BT_INTERFACES_ADDED "InterfacesAdded"
-#define BT_INTERFACES_REMOVED "InterfacesRemoved"
-
-#define retv_if(expr, val) \
- do { \
- if (expr) { \
- ERR("(%s) return", #expr); \
- return (val); \
- } \
- } while (0)
-
-typedef enum {
- BT_HF_STATE_DISCONNECTED,
- BT_HF_STATE_CONNECTED
-} bt_hf_state_t;
-
typedef struct {
guint32 fd;
gint sco_fd;
gboolean is_dialing;
gboolean call_active;
+ gboolean inband_ringtone_support;
+ gboolean is_companion_dev;
guint ciev_call_status;
guint ciev_call_setup_status;
int timer_id;
} bt_hf_agent_send_at_info;
-struct hf_event {
+typedef struct {
const char *cmd;
int (*callback) (bt_hf_agent_info_t *bt_hf_info, const char *buf);
-};
+} bt_hf_event;
typedef struct {
unsigned char b[6];