#include <bundle_internal.h>
#include "bluetooth-ag-agent.h"
#include "bluetooth-ag-handler.h"
+#include "bluetooth-agent-profile.h"
#include <TapiUtility.h>
#include <ITapiSim.h>
static GMainLoop *gmain_loop = NULL;
static GDBusProxy *service_gproxy;
-static int owner_sig_id = -1;
-static int name_owner_sig_id = -1;
+static guint interface_added_sig_id = 0;
+static guint interface_removed_sig_id = 0;
+static guint name_owner_sig_id = 0;
GDBusConnection *ag_dbus_conn = NULL;
gchar *remote_dev_path = NULL;
gboolean wbs_en;
static guint hs_bluez_id;
static guint app_id;
#ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
-static int media_sig_id = -1;
-static int media_state_sig_id = -1;
+static guint media_sig_id = 0;
+static guint media_state_sig_id = 0;
static bt_ag_media_transport_state_t transport_state;
#endif
#define A2DP_SINK_UUID "0000110b-0000-1000-8000-00805f9b34fb"
#endif
#define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
-
-#ifdef TIZEN_FEATURE_BT_LUNAR_DEVICE
#define VCONF_KEY_BT_LUNAR_ENABLED "db/wms/bt_loop_device_hfp_connected"
-#endif
#if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
#define CALL_APP_ID "org.tizen.call-ui"
" </method>"
" <method name='CheckPrivilege'>"
" </method>"
+" <method name='SwapHeadset'>"
+" <arg type='s' name='remote_addr' direction='in'/>"
+" </method>"
" </interface>"
"</node>";
if (!is_companion_device)
return FALSE;
}
-
return TRUE;
}
#endif /* TIZEN_SUPPORT_DUAL_HF */
#endif
}
-#if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_TELEPHONY_ENABLED)
static gboolean __bt_ag_agent_launch_call_app(const char *number)
{
FN_START;
FN_END;
return TRUE;
}
-#endif
static void *__bt_ag_agent_launch_call_req(void *arg)
{
{
FN_START;
-#if defined(TIZEN_PROFILE_WEARABLE) && defined(TIZEN_FEATURE_BT_HFP_AG)
- FN_END;
- return __bt_ag_agent_launch_call_app(number);
-#else
char telnum[BT_MAX_TEL_NUM_STRING];
bundle *b;
pthread_t thread_id;
+ if (TIZEN_PROFILE_WEARABLE)
+ return __bt_ag_agent_launch_call_app(number);
+
if (call_launch_requested == TRUE) {
DBG("Launch request is in progress");
return TRUE;
FN_END;
return TRUE;
-#endif
}
static gboolean __bt_ag_agent_make_video_call(const char *mo_number)
if (dtmf == NULL || path == NULL || sender == NULL) {
ERR("Invalid Argument");
- return FALSE;
+ return BT_HFP_AGENT_ERROR_INVALID_PARAM;
}
DBG("Dtmf = %s", dtmf);
gboolean init_by_hf)
{
uint32_t codec;
- struct ag_codec *data = g_new0(struct ag_codec, 1);
+ struct ag_codec *data = NULL;;
-#ifdef TIZEN_FEATURE_BT_KIRAN_DEVICE
- codec = BT_CVSD_CODEC_ID;
-#else
- if (hs->codec_info.remote_codecs & BT_MSBC_CODEC_MASK)
- codec = BT_MSBC_CODEC_ID;
- else
+ if (TIZEN_MODEL_NAME_TM1) {
codec = BT_CVSD_CODEC_ID;
-#endif
+ } else {
+ if (hs->codec_info.remote_codecs & BT_MSBC_CODEC_MASK)
+ codec = BT_MSBC_CODEC_ID;
+ else
+ codec = BT_CVSD_CODEC_ID;
+ }
if (wbs_opts.wbs_enable == FALSE)
codec = BT_CVSD_CODEC_ID;
hs->codec_info.requested_by_hf = init_by_hf;
hs->codec_info.final_codec = codec;
+ data = g_new0(struct ag_codec, 1);
+ if (data == NULL)
+ return BT_HFP_AGENT_ERROR_NO_MEMORY;
+
data->bt_ag_info = hs;
data->codec_status = g_strdup("timeout");
if (hs->sco_id)
__bt_ag_agent_remove_watch(&hs->sco_id);
+
+ if (hs->sco_incoming_id)
+ __bt_ag_agent_remove_watch(&hs->sco_incoming_id);
}
static gboolean __bt_ag_sco_server_conn_cb(GIOChannel *chan,
if (ag_info->sco_id)
__bt_ag_agent_remove_watch(&ag_info->sco_id);
+ if (ag_info->sco_incoming_id)
+ __bt_ag_agent_remove_watch(&ag_info->sco_incoming_id);
+
if (ag_info->watch_id)
_bt_ag_set_headset_state(ag_info, HEADSET_STATE_CONNECTED);
return FALSE;
}
ag_info->sco = sco_io;
- ag_info->sco_id = g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ ag_info->sco_incoming_id = g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
__bt_ag_sco_server_conn_cb, ag_info);
if (remote_dev_path)
int num_of_secure_command = 4;
static const char* secure_command[] = {"CLCC", "CLIP", "CPBR", "CCWA"};
-void __bt_ag_agent_print_at_buffer(char *message, const char *buf)
+static void __bt_ag_agent_print_at_buffer(char *message, const char *buf)
{
int i = 0;
size_t available_buffer;
int fd;
bt_ag_info_t *bt_ag_info = (bt_ag_info_t *)user_data;
+ int err_return = 0;
if (cond & G_IO_NVAL)
goto failed;
}
- memcpy(&slconn->buffer[slconn->start], event_buf, len);
+ memcpy(&slconn->buffer[slconn->start + slconn->length], event_buf, len);
slconn->length += len;
slconn->buffer[slconn->start + slconn->length] = '\0';
off_t cmd_len;
get_cr = strchr(&slconn->buffer[slconn->start], '\r');
- if (!get_cr)
+ if (!get_cr) {
+ ERR("Broken AT command received, break");
break;
+ }
cmd_len = 1 + (off_t) get_cr -
(off_t) &slconn->buffer[slconn->start];
err = 0;
}
- if (err == -EINVAL) {
- ERR("Unrecognized command: %s",
- &slconn->buffer[slconn->start]);
- err = _bt_ag_send_response(bt_ag_info,
- HFP_STATE_MNGR_ERR_NOT_SUPPORTED);
- if (err < 0)
- goto failed;
- } else if (err < 0)
+ if (err < 0) {
+ switch (err) {
+ case -EINVAL:
+ err_return = HFP_STATE_MNGR_ERR_NOT_SUPPORTED;
+ break;
+ case -EACCES:
+ err_return = HFP_STATE_MNGR_ERR_NOT_ALLOWED;
+ break;
+ default:
+ err_return = HFP_STATE_MNGR_ERR_NOT_SUPPORTED;
+ break;
+ }
ERR("Error handling command %s: %s (%d)",
&slconn->buffer[slconn->start],
strerror(-err), -err);
+ err = _bt_ag_send_response(bt_ag_info,
+ err_return);
+ if (err < 0)
+ goto failed;
+ }
slconn->start += cmd_len;
slconn->length -= cmd_len;
- if (!slconn->length)
+ if (slconn->length <= 0)
slconn->start = 0;
}
return TRUE;
if (hs->sco) {
__bt_ag_close_sco(hs);
_bt_ag_set_headset_state(hs, HEADSET_STATE_CONNECTED);
- hs->sco = NULL;
}
__bt_ag_agent_remove_watch(&hs->watch_id);
g_variant_get(parameters, "(oha{sv})",
&device_path, &index, &options);
-#if defined(TIZEN_SUPPORT_DUAL_HF)
+
+#if defined(TIZEN_SUPPORT_DUAL_HF) && defined(TIZEN_PROFILE_WEARABLE)
+ /*
+ * Below code is not required for dual HF support for
+ * mobile devices
+ */
if (device_count &&
__bt_ag_agent_check_dual_hf_condition(device_path) == FALSE) {
INFO("not allow to connect 2nd HF connection");
g_free(codec);
g_free(nrec);
+ } else {
+ ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
+ goto fail;
}
} else if (g_strcmp0(method_name, "Disconnect") == 0) {
char hdset_address[18] = { 0, };
DBG("Already pass dbus SMACK for bt-service::platform");
/* Return success */
g_dbus_method_invocation_return_value(invocation, NULL);
+ } else if (g_strcmp0(method_name, "SwapHeadset") == 0) {
+ GSList *l;
+ gchar *addr = NULL;
+ char address[BT_ADDRESS_STRING_SIZE];
+ char remote_addr[BT_ADDRESS_STRING_SIZE];
+ gboolean device_found = FALSE;
+
+ g_variant_get(parameters, "(s)", &addr);
+ g_strlcpy(address, addr, sizeof(address));
+ DBG("Sender = %s", sender);
+
+ /* Loop through connected headset list
+ * If found, update the remote_dev_path.
+ */
+ for (l = active_devices ; l; l = l->next) {
+ bt_ag_info_t *data = l->data;
+ g_strlcpy(remote_addr, data->remote_addr, sizeof(remote_addr));
+ if (g_strcmp0(remote_addr, address) == 0) {
+ DBG("Active device found");
+ if (data->path == NULL) {
+ DBG("device path is null");
+ ret = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto fail;
+ }
+ remote_dev_path = g_strdup(data->path);
+ DBG("Setting device path %s as active device path", remote_dev_path);
+ device_found = TRUE;
+ break;
+ }
+ }
+
+ if (!device_found) {
+ ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
+ goto fail;
+ }
+
+ g_dbus_method_invocation_return_value(invocation, NULL);
}
INFO("-");
_bt_hfp_set_property_value("SignalBarsChanged", signal_bar);
}
-#ifdef TIZEN_FEATURE_BT_LUNAR_DEVICE
static void __bt_ag_agent_lunar_connection_status_cb(keynode_t *node)
{
gboolean status = vconf_keynode_get_bool(node);
}
}
}
-#endif
static void __bt_ag_agent_network_register_status_cb(keynode_t *node)
{
if (0 != ret)
ERR("Subsrciption to network failed err = [%d]\n", ret);
-#ifdef TIZEN_FEATURE_BT_LUNAR_DEVICE
- ret = vconf_notify_key_changed(VCONF_KEY_BT_LUNAR_ENABLED,
- (void *)__bt_ag_agent_lunar_connection_status_cb, NULL);
- if (0 != ret)
- ERR("Subsrciption to lunar connection failed err = [%d]\n", ret);
-
-#endif
+ if (TIZEN_PROFILE_WEARABLE) {
+ ret = vconf_notify_key_changed(VCONF_KEY_BT_LUNAR_ENABLED,
+ (void *)__bt_ag_agent_lunar_connection_status_cb, NULL);
+ if (0 != ret)
+ ERR("Subsrciption to lunar connection failed err = [%d]\n", ret);
+ }
}
static void __bt_ag_agent_release_vconf_updates(void)
if (ag_dbus_conn) {
__bt_ag_unregister_profile_methods();
- if (owner_sig_id != -1)
+ if (interface_added_sig_id)
+ g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
+ interface_added_sig_id);
+
+ if (interface_removed_sig_id)
g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
- owner_sig_id);
+ interface_removed_sig_id);
- if (name_owner_sig_id != -1)
+ if (name_owner_sig_id)
g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
name_owner_sig_id);
#ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
- if (media_sig_id != -1)
+ if (media_sig_id)
g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
media_sig_id);
+ media_sig_id = 0;
- if (media_state_sig_id != -1)
+ if (media_state_sig_id)
g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
media_state_sig_id);
+ media_state_sig_id = 0;
#endif
- name_owner_sig_id = -1;
+
+ interface_added_sig_id = 0;
+ interface_removed_sig_id = 0;
+ name_owner_sig_id = 0;
g_free(sco_owner);
sco_owner = NULL;
}
}
g_variant_iter_free(iter);
- g_variant_unref(dict_param);
}
} else if (strcasecmp(signal_name, "ProfileStateChanged") == 0) {
char *profile_uuid = NULL;
HSP_AG_UUID, "Headset Audio Gateway");
}
- owner_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
- NULL, BT_MANAGER_INTERFACE, NULL, NULL, NULL, 0,
+ interface_added_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
+ NULL, BT_MANAGER_INTERFACE,
+ BT_INTERFACES_ADDED, NULL, NULL, 0,
+ __bt_ag_agent_filter_cb, NULL, NULL);
+
+ interface_removed_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
+ NULL, BT_MANAGER_INTERFACE,
+ BT_INTERFACES_REMOVED, NULL, NULL, 0,
__bt_ag_agent_filter_cb, NULL, NULL);
+
#ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
media_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
NULL, BT_PROPERTIES_INTERFACE, NULL, NULL,
static uint32_t __bt_ag_agent_get_ag_features(void)
{
- uint32_t ag_features = BT_AG_FEATURE_EC_AND_NR |
+ uint32_t ag_features;
+
+ if (TIZEN_MODEL_NAME_TM1) {
+ ag_features = BT_AG_FEATURE_EC_AND_NR |
+ BT_AG_FEATURE_REJECT_CALL |
+ BT_AG_FEATURE_ENHANCED_CALL_STATUS |
+ BT_AG_FEATURE_THREE_WAY_CALL |
+ BT_AG_FEATURE_EXTENDED_ERROR_RESULT_CODES;
+ } else {
+ ag_features = BT_AG_FEATURE_EC_AND_NR |
BT_AG_FEATURE_REJECT_CALL |
BT_AG_FEATURE_ENHANCED_CALL_STATUS |
BT_AG_FEATURE_THREE_WAY_CALL |
-#ifndef TIZEN_FEATURE_BT_KIRAN_DEVICE
BT_AG_FEATURE_VOICE_RECOGNITION |
-#endif
BT_AG_FEATURE_EXTENDED_ERROR_RESULT_CODES;
+ }
wbs_en = TRUE;
#if defined(TIZEN_FEATURE_BT_HFP_AG)
- hfp_ver = HFP_VERSION_1_6;
+ hfp_ver = HFP_VERSION_1_7;
#else
hfp_ver = HFP_VERSION_1_5;
#endif
hsp_ver = HSP_VERSION_1_2;
- if (hfp_ver == HFP_VERSION_1_6)
+ if (hfp_ver > HFP_VERSION_1_5)
ag_features |= BT_AG_FEATURE_CODEC_NEGOTIATION;
+ if (hfp_ver == HFP_VERSION_1_7)
+ ag_features |= BT_AG_FEATURE_ESCO_S4_T2_SUPPORT;
+
return ag_features;
}
int i;
uint32_t ag_features;
struct sigaction sa;
- pthread_t thread_id;
+ pthread_t thread_id = 0;
INFO_C("### Starting Bluetooth AG agent");
ag.sdp_features = (uint16_t) ag_features & 0x1F;
- if (hfp_ver == HFP_VERSION_1_6 && wbs_en == TRUE)
+ if (hfp_ver >= HFP_VERSION_1_6 && wbs_en == TRUE)
ag.sdp_features |= BT_AG_FEATURE_SDP_WIDEBAND_SPEECH;
memset(&sa, 0, sizeof(sa));