#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
+#include <stdbool.h>
#include <sys/poll.h>
#include <gio/gunixfdlist.h>
#include <bundle_internal.h>
#include "bluetooth-ag-agent.h"
#include "bluetooth-ag-handler.h"
+#include "bluetooth-agent-profile.h"
+
+#include <bluetooth.h>
+#include <bluetooth_internal.h>
#include <TapiUtility.h>
#include <ITapiSim.h>
#include <ITapiModem.h>
+#include <ITapiCall.h>
#include <TelNetwork.h>
+#include <TelCall.h>
#include <app.h>
#include <aul.h>
#include <system_info.h>
#include "contacts.h"
#include "appsvc.h"
-
-static GMainLoop *gmain_loop = NULL;
-static GDBusProxy *service_gproxy;
-static int owner_sig_id = -1;
-static int name_owner_sig_id = -1;
+#include <device-error.h>
+#include <device/battery.h>
+#include <device/callback.h>
+
+static GMainLoop *gmain_loop;
+static GDBusProxy *profile_gproxy;
+static guint interface_added_sig_id;
+static guint interface_removed_sig_id;
+static guint proterty_changed_sig_id;
+static guint name_owner_sig_id;
GDBusConnection *ag_dbus_conn = NULL;
gchar *remote_dev_path = NULL;
gboolean wbs_en;
uint16_t hfp_ver;
uint16_t hsp_ver;
-static TapiHandle *tapi_handle;
+static TapiHandle *tapi_handle[3];
+int sim1;
+int sim2;
+static TapiHandle *tapi_handle_preferred_sim;
extern wbs_options wbs_opts;
GSList *active_devices = NULL;
-static gchar *local_addr = NULL;
-static GDBusProxy *app_gproxy;
+static gchar *local_addr;
static gboolean call_launch_requested = FALSE;
-static gchar* sco_owner = NULL;
-static guint sco_open_timer_id = 0;
-static gboolean sco_open_request = FALSE;
+static gchar* sco_owner;
+static guint sco_open_timer_id;
+static gboolean sco_open_request;
static guint hf_bluez_id;
static guint hs_bluez_id;
static guint app_id;
-#ifdef TIZEN_MEDIA_ENHANCE
-static int media_sig_id = -1;
-static int media_state_sig_id = -1;
+static guint device_property_id;
+#ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
+static guint media_sig_id;
+static guint media_state_sig_id;
static bt_ag_media_transport_state_t transport_state;
#endif
+static int last_speaker_gain = 9;
+
+#define GET_TAPI_HANDLE \
+ (tapi_handle_preferred_sim != NULL) ? tapi_handle_preferred_sim : \
+ ((sim1 == 1) ? tapi_handle[0] : tapi_handle[1])
#define HSP_AG_UUID "00001112-0000-1000-8000-00805f9b34fb"
#define HFP_AG_UUID "0000111f-0000-1000-8000-00805f9b34fb"
-#ifdef TIZEN_MEDIA_ENHANCE
+#ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
#define A2DP_SINK_UUID "0000110b-0000-1000-8000-00805f9b34fb"
#endif
#define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
-
-#ifdef TIZEN_SUPPORT_LUNAR_DEVICE
#define VCONF_KEY_BT_LUNAR_ENABLED "db/wms/bt_loop_device_hfp_connected"
-#endif
-#if defined(TIZEN_WEARABLE) && defined(TIZEN_BT_HFP_AG_ENABLE)
-#define CALL_APP_ID "org.tizen.call-ui"
-#endif
+#define CALL_ALIAS_APP_ID "tizen.call"
#if defined(TIZEN_SUPPORT_DUAL_HF)
#define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
" <method name='RequestDisconnection'>"
" <arg type='o' name='device' direction='in'/>"
" </method>"
+" <method name='ReplyAuthorize'>"
+" <arg type='u' name='accept' direction='in'/>"
+" </method>"
" </interface>"
"</node>";
" </method>"
" <method name='CheckPrivilege'>"
" </method>"
+" <method name='SwapHeadset'>"
+" <arg type='s' name='remote_addr' direction='in'/>"
+" </method>"
" </interface>"
"</node>";
uint16_t setting;
} bt_voice;
-struct ag_codec {
- bt_ag_info_t *bt_ag_info;
- char *codec_status;
-};
-
bt_ag_status_t ag = {
.telephony_ready = FALSE,
.features = 0,
void _bt_ag_set_headset_state(bt_ag_info_t *hs, hs_state_t state);
static void __bt_ag_agent_reg_sim_event(TapiHandle *handle, void *user_data);
static void __bt_ag_agent_dereg_sim_event(TapiHandle *handle);
+static uint32_t __bt_ag_agent_get_ag_features(void);
+static void __bt_ag_agent_tel_cb(TapiHandle *handle, int result, void *data, void *user_data);
+static void __bt_ag_agent_subscribe_tapi_updates(TapiHandle *handle);
+static void __bt_ag_agent_unsubscribe_tapi_updates(TapiHandle *handle);
static void __bt_ag_name_owner_changed_cb(GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data);
+static GError *__bt_ag_agent_set_error(bt_hfp_agent_error_t error);
static void __bt_convert_addr_type_to_rev_string(char *address,
unsigned char *addr)
addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
}
-static GDBusProxy *__bt_ag_gdbus_init_service_proxy(const gchar *service,
- const gchar *path, const gchar *interface)
+static GDBusProxy *__bt_ag_gdbus_init_profile_proxy(void)
{
FN_START;
proxy = g_dbus_proxy_new_sync(ag_dbus_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) {
ERR("Unable to create proxy: %s", err->message);
return NULL;
}
+ profile_gproxy = proxy;
+
FN_END;
return proxy;
}
static GDBusProxy *__bt_ag_gdbus_get_app_proxy(const gchar *service,
const gchar *path, const gchar *interface)
{
- return (app_gproxy) ? app_gproxy :
- __bt_ag_gdbus_init_service_proxy(service,
- path, interface);
+ FN_START;
+
+ GDBusProxy *proxy;
+ GError *err = NULL;
+
+ if (ag_dbus_conn == NULL)
+ ag_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+
+ if (!ag_dbus_conn) {
+ if (err) {
+ ERR("Unable to connect to gdbus: %s", err->message);
+ g_clear_error(&err);
+ }
+ return NULL;
+ }
+
+ DBG("%s %s %s", service, path, interface);
+
+ proxy = g_dbus_proxy_new_sync(ag_dbus_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;
+ }
+
+ FN_END;
+ return proxy;
}
static int __bt_ag_agent_gdbus_method_send(const char *service,
g_clear_error(&error);
}
+ g_object_unref(proxy);
return BT_HFP_AGENT_ERROR_INTERNAL;
}
G_DBUS_CALL_FLAGS_NONE, 2000,
NULL, NULL, NULL);
}
+ g_object_unref(proxy);
+
return BT_HFP_AGENT_ERROR_NONE;
}
#if defined(TIZEN_SUPPORT_DUAL_HF)
gboolean __bt_ag_agent_is_companion_device(const char *addr)
{
-#if defined(TIZEN_WEARABLE)
- char *host_device_address = NULL;
- host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
+ if (TIZEN_PROFILE_WEARABLE) {
+ char *host_device_address = NULL;
+ host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
- if (!host_device_address) {
- INFO("Failed to get a companion device address");
- return FALSE;
- }
+ if (!host_device_address) {
+ INFO("Failed to get a companion device address");
+ return FALSE;
+ }
- if (g_strcmp0(host_device_address, addr) == 0) {
- INFO("addr[%s] is companion device", addr);
- return TRUE;
+ if (g_strcmp0(host_device_address, addr) == 0) {
+ INFO("addr[%s] is companion device", addr);
+ free(host_device_address);
+ return TRUE;
+ }
+ free(host_device_address);
+ return FALSE;
}
-
return FALSE;
-#else
- /* TODO : Need to add companion device check condition for Phone models */
- return FALSE;
-#endif
}
void __bt_convert_device_path_to_address(const gchar *device_path,
dev_addr += 4;
g_strlcpy(address, dev_addr, sizeof(address));
- while ((pos = strchr(address, '_')) != NULL) {
+ while ((pos = strchr(address, '_')) != NULL)
*pos = ':';
- }
g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE);
}
__bt_convert_device_path_to_address(device_path, device_address);
is_companion_device = __bt_ag_agent_is_companion_device(device_address);
- DBG(" device_address[%s]", device_address);
+ DBG_SECURE(" device_address[%s]", device_address);
DBG(" is_companion_device[%d]", is_companion_device);
if (__bt_ag_agent_is_companion_device_connected()) {
if (!is_companion_device)
return FALSE;
}
-
return TRUE;
}
#endif /* TIZEN_SUPPORT_DUAL_HF */
if (NULL == callapp_type)
return FALSE;
-#if defined(TIZEN_WEARABLE) && defined(TIZEN_BT_HFP_AG_ENABLE)
*callapp_type = BT_VOICE_CALL;
FN_END;
return TRUE;
-#else
-#if 0
- int ret;
- ret = vconf_get_int(
- VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT,
- callapp_type);
- if (ret != 0) {
- ERR("Failed to read [%s]\n",
- VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT);
- return FALSE;
- }
-
- INFO(" [%s] = [%d]\n",
- VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT, *callapp_type);
-#endif
- /* The vconf value does not include in platform. */
- *callapp_type = BT_VOICE_CALL;
- FN_END;
- return TRUE;
-#endif
}
static gboolean __bt_get_outgoing_call_condition(int *condition)
if (NULL == condition)
return FALSE;
-#if defined(TIZEN_WEARABLE) && defined(TIZEN_BT_HFP_AG_ENABLE)
*condition = BT_MO_ONLY_UNLOCKED;
FN_END;
return TRUE;
-#else
-#if 0
- int ret;
- ret = vconf_get_int(
- VCONFKEY_CISSAPPL_OUTGOING_CALL_CONDITIONS_INT,
- condition);
- if (ret != 0) {
- ERR("Failed to read [%s]\n",
- VCONFKEY_CISSAPPL_OUTGOING_CALL_CONDITIONS_INT);
- return FALSE;
- }
-#endif
- /* The vconf value does not include in platform. */
- *condition = BT_MO_ONLY_UNLOCKED;
- FN_END;
- return TRUE;
-#endif
}
-#if defined(TIZEN_WEARABLE) && defined(TIZEN_TELEPHONY_ENABLED)
static gboolean __bt_ag_agent_launch_call_app(const char *number)
{
FN_START;
if (strlen(number) != 0)
bundle_add(b, "number", number);
- aul_launch_app_async(CALL_APP_ID, b);
+ aul_launch_app_async(CALL_ALIAS_APP_ID, b);
bundle_free(b);
FN_END;
return TRUE;
}
-#endif
-static void *__bt_ag_agent_launch_call_req(void *arg)
+static gboolean __bt_ag_agent_launch_call_req(void *arg)
{
FN_START;
bundle *b = (bundle *)arg;
+
if (appsvc_run_service(b, 0, NULL, NULL) < 0)
ERR("Unable to run app svc");
bundle_free(b);
call_launch_requested = FALSE;
FN_END;
- return NULL;
+ return FALSE;
}
static gboolean __bt_ag_agent_make_call(const char *number)
{
FN_START;
-#if defined(TIZEN_WEARABLE) && defined(TIZEN_BT_HFP_AG_ENABLE)
- 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");
appsvc_add_data(b, "ctindex", "-1");
call_launch_requested = TRUE;
- if (pthread_create(&thread_id, NULL,
- (void *)&__bt_ag_agent_launch_call_req,
- (void *)b) < 0) {
- ERR("pthread_create() is failed");
- call_launch_requested = FALSE;
- return FALSE;
- }
- if (pthread_detach(thread_id) < 0)
- ERR("pthread_detach() is failed");
+ g_idle_add(__bt_ag_agent_launch_call_req, b);
FN_END;
return TRUE;
-#endif
}
static gboolean __bt_ag_agent_make_video_call(const char *mo_number)
goto fail;
}
- DBG("Number = %s", number);
+ DBG_SECURE("Number = %s", number);
DBG("flags = %d", flags);
if (!__bt_is_phone_locked(&phone_lock_state)) {
goto done;
}
- DBG("number %s", number);
+ DBG_SECURE("number %s", number);
/*Make Voice call*/
if (!__bt_ag_agent_make_call(number)) {
if (dtmf == NULL || path == NULL || sender == NULL) {
ERR("Invalid Argument");
- return FALSE;
+ return BT_HFP_AGENT_ERROR_INVALID_PARAM;
}
DBG("Dtmf = %s", dtmf);
DBG("Value = %d", chld_value);
DBG("Sender = %s", sender);
-#if defined(TIZEN_WEARABLE) && defined(TIZEN_BT_HFP_AG_ENABLE)
- /* Check if AG supports (i.e. ag_chld_str = "0,1,2") the requested CHLD;
- if not return FALSE */
- if (chld_value != 0 && chld_value != 1 && chld_value != 2)
- return FALSE;
-#else
+ if (TIZEN_PROFILE_WEARABLE) {
+ /* Check if AG supports (i.e. ag_chld_str = "0,1,2") the requested CHLD;
+ if not return FALSE */
+ if (chld_value != 0 && chld_value != 1 && chld_value != 2)
+ return FALSE;
+ } else {
if (chld_value != 0 && chld_value != 1 && chld_value != 2 &&
chld_value != 3)
return FALSE;
-#endif
+ }
+
_bt_ag_agent_emit_signal(ag_dbus_conn, path,
BT_AG_SERVICE_NAME, "Threeway",
g_variant_new("(u)", chld_value));
gboolean _bt_ag_agent_get_signal_quality(void *device)
{
- gint rssi;
+ int rssi;
+ int ret;
FN_START;
-
- if (vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &rssi)) {
- DBG("VCONFKEY_TELEPHONY_RSSI failed\n");
+ ret = tel_get_property_int(GET_TAPI_HANDLE,
+ TAPI_PROP_NETWORK_SIGNALSTRENGTH_LEVEL, &rssi);
+ if (ret != TAPI_API_SUCCESS) {
+ ERR("Get signal status failed err = %d\n", ret);
goto fail;
}
gboolean _bt_ag_agent_get_battery_status(void *device)
{
- gint battery_chrg_status;
- gint battery_capacity;
+ bool battery_chrg_status;
+ int battery_capacity;
+ int ret;
FN_START;
- if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
- &battery_chrg_status)) {
- DBG("VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW failed\n");
+ ret = device_battery_is_charging(&battery_chrg_status);
+ if (ret != DEVICE_ERROR_NONE) {
+ ERR("Get battery charge status failed. Err = %d\n", ret);
goto fail;
}
DBG("Status : %d\n", battery_chrg_status);
- if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
- &battery_capacity)) {
- DBG("VCONFKEY_SYSMAN_BATTERY_CAPACITY failed\n");
+ ret = device_battery_get_percent(&battery_capacity);
+ if (ret != DEVICE_ERROR_NONE) {
+ ERR("Get battery capacity status failed. Err = %d\n", ret);
goto fail;
}
gboolean _bt_ag_agent_get_operator_name(void *device)
{
- char *operator_name;
+ char *operator_name = NULL;
+ int ret;
FN_START;
- operator_name = vconf_get_str(VCONFKEY_TELEPHONY_NWNAME);
+ ret = tel_get_property_string(GET_TAPI_HANDLE,
+ TAPI_PROP_NETWORK_NETWORK_NAME, &operator_name);
if (NULL == operator_name) {
- DBG("vconf_get_str failed");
+ DBG("TAPI_PROP_NETWORK_NETWORK_NAME failed (%d)", ret);
_bt_hfp_operator_reply(NULL, device);
return FALSE;
}
_bt_ag_agent_emit_signal(ag_dbus_conn, hs->path,
BT_AG_SERVICE_NAME, "NrecStatusChanged",
- g_variant_new("(b)", status));
+ g_variant_new("(b)", hs->nrec_status));
FN_END;
return TRUE;
}
FN_START;
char *imei_number;
- imei_number = tel_get_misc_me_imei_sync(tapi_handle);
+ imei_number = tel_get_misc_me_imei_sync(GET_TAPI_HANDLE);
if (NULL == imei_number) {
ERR("tel_get_misc_me_imei_sync for imei_number failed");
goto fail;
FN_START;
TelSimImsiInfo_t imsi;
memset(&imsi, 0, sizeof(TelSimImsiInfo_t));
- if (tel_get_sim_imsi(tapi_handle, &imsi) != TAPI_API_SUCCESS) {
+ if (tel_get_sim_imsi(GET_TAPI_HANDLE, &imsi) != TAPI_API_SUCCESS) {
ERR("tel_get_sim_imsi failed");
goto fail;
}
int registration_status = 0;
int roam_status = 0;
- ret = tel_get_property_int(tapi_handle, TAPI_PROP_NETWORK_CIRCUIT_STATUS,
- &result);
+ ret = tel_get_property_int(GET_TAPI_HANDLE,
+ TAPI_PROP_NETWORK_CIRCUIT_STATUS, &result);
if (ret != TAPI_API_SUCCESS) {
ERR("tel_get_property_int failed");
return;
DBG_SECURE("Mapped Status %d", registration_status);
if (registration_status ==
BT_AGENT_NETWORK_REG_STATUS_REGISTER_HOME_NETWORK) {
- ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
- if (ret != 0) {
+ ret = tel_get_property_int(GET_TAPI_HANDLE,
+ TAPI_PROP_NETWORK_ROAMING_STATUS, &roam_status);
+ if (ret != TAPI_API_SUCCESS) {
ERR("Get roaming status failed err = %d\n", ret);
return;
}
FN_END;
}
-#if defined(TIZEN_WEARABLE) && defined(TIZEN_BT_HFP_AG_ENABLE)
-static gboolean __bt_ag_agent_launch_voice_dial(gboolean activate)
+void _bt_ag_agent_set_last_speaker_gain(int gain)
{
- FN_START;
- bundle *b;
-
- b = bundle_create();
- if (NULL == b) {
- ERR("bundle_create() Failed");
- return FALSE;
- }
-
- bundle_add(b, "domain", "bt_headset");
- if (!activate)
- bundle_add(b, "action_type", "deactivate");
-
- aul_launch_app_async("org.tizen.svoice", b);
- bundle_free(b);
- FN_END;
- return TRUE;
+ last_speaker_gain = gain;
}
-#else
+
static gboolean __bt_ag_agent_launch_voice_dial(gboolean activate)
{
FN_START;
- app_control_h service = NULL;
+ if (TIZEN_PROFILE_WEARABLE) {
+ bundle *b;
- app_control_create(&service);
+ b = bundle_create();
+ if (NULL == b) {
+ ERR("bundle_create() Failed");
+ return FALSE;
+ }
- if (service == NULL) {
- ERR("Service create failed");
- return FALSE;
- }
+ bundle_add(b, "domain", "bt_headset");
+ if (!activate)
+ bundle_add(b, "action_type", "deactivate");
- app_control_set_app_id(service, "org.tizen.svoice");
- app_control_set_operation(service, APP_CONTROL_OPERATION_DEFAULT);
- if (app_control_add_extra_data(service, "domain", "bt_headset")
- != APP_CONTROL_ERROR_NONE) {
- ERR("app_control_add_extra_data failed");
- app_control_destroy(service);
- return FALSE;
- }
+ aul_launch_app_async("org.tizen.svoice", b);
+ bundle_free(b);
+ FN_END;
+ return TRUE;
+ } else {
+ app_control_h service = NULL;
+
+ app_control_create(&service);
- if (!activate)
- if (app_control_add_extra_data(service, "action_type", "deactivate")
+ if (service == NULL) {
+ ERR("Service create failed");
+ return FALSE;
+ }
+
+ app_control_set_app_id(service, "org.tizen.svoice");
+ app_control_set_operation(service, APP_CONTROL_OPERATION_DEFAULT);
+ if (app_control_add_extra_data(service, "domain", "bt_headset")
!= APP_CONTROL_ERROR_NONE) {
ERR("app_control_add_extra_data failed");
app_control_destroy(service);
return FALSE;
}
- if (app_control_send_launch_request(service, NULL, NULL) !=
+ if (!activate)
+ if (app_control_add_extra_data(service, "action_type", "deactivate")
+ != APP_CONTROL_ERROR_NONE) {
+ ERR("app_control_add_extra_data failed");
+ app_control_destroy(service);
+ return FALSE;
+ }
+
+ if (app_control_send_launch_request(service, NULL, NULL) !=
APP_CONTROL_ERROR_NONE) {
- ERR("launch failed");
+ ERR("launch failed");
+ app_control_destroy(service);
+ return FALSE;
+ }
+
app_control_destroy(service);
- return FALSE;
+ FN_END;
+ return TRUE;
}
-
- app_control_destroy(service);
- FN_END;
- return TRUE;
}
-#endif
gboolean _bt_ag_agent_voice_dial(gboolean activate)
{
hs->codec_info.is_negotiating = FALSE;
hs->codec_info.requested_by_hf = FALSE;
hs->codec_info.sending_codec = 0;
+ g_free(hs->codec_info.status);
+ hs->codec_info.status = NULL;
+
if (reset) {
hs->codec_info.remote_codecs = 0;
hs->codec_info.final_codec = 0;
static gboolean __bt_ag_codec_negotiation_finished(gpointer user_data)
{
- struct ag_codec *data = (struct ag_codec *)user_data;
+ bt_ag_info_t *hs = (bt_ag_info_t *)user_data;
- if (g_strcmp0(data->codec_status, "finish") == 0) {
+ if (g_strcmp0(hs->codec_info.status, "finish") == 0) {
DBG("Codec negotiation finished");
- __bt_ag_sco_connect(data->bt_ag_info);
- __bt_ag_codec_negotiation_info_reset(data->bt_ag_info, FALSE);
- g_free(data->codec_status);
- g_free(data);
+ __bt_ag_sco_connect(hs);
+ __bt_ag_codec_negotiation_info_reset(hs, FALSE);
return TRUE;
- } else if (g_strcmp0(data->codec_status, "timeout") == 0) {
- DBG("Timeout is occured in codec negotiation");
+ } else if (g_strcmp0(hs->codec_info.status, "timeout") == 0) {
+ ERR("Timeout is occured in codec negotiation");
+ /* Codec negotiation is timedout fall back to default NB */
+ hs->codec = BT_CVSD_CODEC_ID;
+ hs->codec_info.final_codec = BT_CVSD_CODEC_ID;
}
- if (data->bt_ag_info->codec_info.requested_by_hf) {
- __bt_ag_codec_negotiation_info_reset(data->bt_ag_info, FALSE);
+ if (hs->codec_info.requested_by_hf) {
+ __bt_ag_codec_negotiation_info_reset(hs, FALSE);
} else {
- __bt_ag_sco_connect(data->bt_ag_info);
- __bt_ag_codec_negotiation_info_reset(data->bt_ag_info, FALSE);
+ __bt_ag_sco_connect(hs);
+ __bt_ag_codec_negotiation_info_reset(hs, FALSE);
}
- g_free(data->codec_status);
- g_free(data);
return FALSE;
}
g_clear_error(&err);
}
+ g_object_unref(proxy);
return BT_HFP_AGENT_ERROR_INTERNAL;
}
g_variant_unref(ret);
+ g_object_unref(proxy);
return BT_HFP_AGENT_ERROR_NONE;
}
gboolean init_by_hf)
{
uint32_t codec;
- struct ag_codec *data = g_new0(struct ag_codec, 1);
-#ifdef TIZEN_KIRAN
- codec = BT_CVSD_CODEC_ID;
-#else
+#ifdef TIZEN_FEATURE_BT_SCO_WIDEBAND
if (hs->codec_info.remote_codecs & BT_MSBC_CODEC_MASK)
codec = BT_MSBC_CODEC_ID;
else
codec = BT_CVSD_CODEC_ID;
+#else
+ codec = BT_CVSD_CODEC_ID;
#endif
if (wbs_opts.wbs_enable == FALSE)
hs->codec_info.sending_codec = codec;
hs->codec_info.requested_by_hf = init_by_hf;
hs->codec_info.final_codec = codec;
-
- data->bt_ag_info = hs;
- data->codec_status = g_strdup("timeout");
+ hs->codec_info.status = g_strdup("timeout");
hs->codec_info.nego_timer = g_timeout_add_seconds(
HFP_CODEC_NEGOTIATION_TIMEOUT,
(GSourceFunc)__bt_ag_codec_negotiation_finished,
- data);
+ hs);
return BT_HFP_AGENT_ERROR_NONE;
}
hs->codec_info.is_negotiating = FALSE;
hs->codec_info.requested_by_hf = FALSE;
hs->codec_info.sending_codec = 0;
+ g_free(hs->codec_info.status);
+ hs->codec_info.status = NULL;
g_source_remove(hs->codec_info.nego_timer);
__bt_hfp_codec_connection_setup(hs, FALSE);
}
{
uint32_t codec = 0x00000000;
hfp_state_manager_err_t err = HFP_STATE_MNGR_ERR_NONE;
- struct ag_codec *data = g_new0(struct ag_codec, 1);
/* Timer reset */
if (hs->codec_info.nego_timer) {
g_source_remove(hs->codec_info.nego_timer);
hs->codec_info.nego_timer = 0;
+ g_free(hs->codec_info.status);
+ hs->codec_info.status = NULL;
}
if (!(ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION))
BT_HFP_AGENT_ERROR_NONE)
err = HFP_STATE_MNGR_ERR_AG_FAILURE;
- data->bt_ag_info = hs;
- data->codec_status = g_strdup("finish");
+ hs->codec_info.status = g_strdup("finish");
_bt_ag_send_response(hs, err);
- __bt_ag_codec_negotiation_finished(data);
+ __bt_ag_codec_negotiation_finished(hs);
return 0;
}
return NULL;
}
-void _bt_convert_addr_string_to_type_rev(unsigned char *addr,
- const char *address)
+static void __bt_convert_addr_string_to_type_rev(unsigned char *addr,
+ const char *address)
{
- int i;
- char *ptr = NULL;
+ int i;
+ char *ptr = NULL;
ret_if(address == NULL);
ret_if(addr == NULL);
- for (i = 0; i < 6; i++) {
- addr[5 - i] = strtol(address, &ptr, 16);
- if (ptr[0] != '\0') {
- if (ptr[0] != ':')
- return;
+ for (i = 0; i < 6; i++) {
+ addr[5 - i] = strtol(address, &ptr, 16);
+ if (ptr[0] != '\0') {
+ if (ptr[0] != ':')
+ return;
- address = ptr + 1;
- }
- }
+ address = ptr + 1;
+ }
+ }
}
static gboolean __bt_ag_check_nval(GIOChannel *chan)
bt_ag_slconn_t *slconn = hs->slc;
/*guint watch_id;*/
+ if (hs->state == HEADSET_STATE_ON_CALL)
+ return BT_HFP_AGENT_ERROR_ALREADY_CONNECTED;
+
if (hs->state != HEADSET_STATE_CONNECTED)
return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
-#ifdef TIZEN_MEDIA_ENHANCE
+#ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
_bt_ag_agent_check_transport_state();
#endif
memset(&sco_addr, 0, sizeof(sco_addr));
sco_addr.sco_family = AF_BLUETOOTH;
- __bt_ag_str2ba(local_addr, &sco_addr.sco_bdaddr);
- DBG("Local BD address: %s", local_addr);
+ if (local_addr) {
+ __bt_ag_str2ba(local_addr, &sco_addr.sco_bdaddr);
+ DBG_SECURE("Local BD address: %s", local_addr);
+ } else {
+ ERR("Local address is NULL");
+ ERR("Close SCO skt");
+ close(sco_skt);
+ return BT_HFP_AGENT_ERROR_INTERNAL;
+ }
+
err = bind(sco_skt, (struct sockaddr *) &sco_addr, sizeof(sco_addr));
if (err < 0) {
return BT_HFP_AGENT_ERROR_INTERNAL;
}
- DBG("Socket FD : %d", sco_skt);
+ DBG_SECURE("Socket FD : %d", sco_skt);
io = g_io_channel_unix_new(sco_skt);
g_io_channel_set_close_on_unref(io, TRUE);
if (err < 0) {
ERR("ERROR: sco socket set socket option failed");
ERR("Close SCO skt");
+ g_io_channel_unref(io);
close(sco_skt);
return BT_HFP_AGENT_ERROR_INTERNAL;
}
memset(&sco_addr, 0, sizeof(sco_addr));
sco_addr.sco_family = AF_BLUETOOTH;
__bt_ag_str2ba(hs->remote_addr, &sco_addr.sco_bdaddr);
- DBG("remotel BD address: %s", hs->remote_addr);
+ DBG_SECURE("remotel BD address: %s", hs->remote_addr);
err = connect(sco_skt, (struct sockaddr *) &sco_addr, sizeof(sco_addr));
if (err < 0 && !(errno == EINPROGRESS || errno == EAGAIN)) {
- ERR("ERROR: sco socket connect failed : %d", err);
+ err = -errno;
+ ERR("sco socket connect failed : %s (%d)", strerror(-err), -err);
ERR("Close SCO skt");
+ g_io_channel_unref(io);
close(sco_skt);
return BT_HFP_AGENT_ERROR_INTERNAL;
}
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;
BT_VOICE_NUM, &bt_vo, sizeof(bt_vo));
if (err < 0) {
ERR("Sco socket set socket option failed");
+ g_io_channel_unref(sco_io);
close(cli_sco_sock);
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)
memset(&addr, 0, sizeof(addr));
addr.sco_family = AF_BLUETOOTH;
- _bt_convert_addr_string_to_type_rev(bd_addr.b, hs->remote_addr);
- DBG("Bind to address %s", hs->remote_addr);
+ __bt_convert_addr_string_to_type_rev(bd_addr.b, hs->remote_addr);
+ DBG_SECURE("Bind to address %s", hs->remote_addr);
memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
if (bind(sco_skt, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
g_io_channel_unref(hs->sco_server);
hs->sco_server = NULL;
}
+ __bt_ag_agent_remove_watch(&hs->sco_watch_id);
hs->sco_server_started = FALSE;
}
if (cond & G_IO_NVAL)
return FALSE;
- if (name_owner_sig_id != -1)
+ if (name_owner_sig_id)
g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
name_owner_sig_id);
- name_owner_sig_id = -1;
+ name_owner_sig_id = 0;
g_free(sco_owner);
sco_owner = NULL;
BT_HEADSET_INTERFACE, "State",
g_variant_new("s", hs_state));
hs->state = state;
+ active_devices = g_slist_append(active_devices, hs);
break;
case HEADSET_STATE_CONNECTED:
if (hs->state < state) {
val = TRUE;
+ if (!g_slist_find(active_devices, hs))
active_devices = g_slist_append(active_devices, hs);
_bt_ag_agent_emit_property_changed(ag_dbus_conn,
hs->path,
"Connected",
g_variant_new("b", val));
- DBG("Device %s connected\n", hs->remote_addr);
+ DBG_SECURE("Device %s connected", hs->remote_addr);
+
+ /* update remote dev path to last connected device. */
+ if (remote_dev_path)
+ g_free(remote_dev_path);
+ remote_dev_path = g_strdup(hs->path);
+
#if defined(TIZEN_SUPPORT_DUAL_HF)
if (!hs->is_companion_device)
__bt_ag_start_sco_server(hs);
break;
case HEADSET_STATE_DISCONNECTED:
+ if (sco_open_timer_id > 0) {
+ g_source_remove(sco_open_timer_id);
+ sco_open_timer_id = 0;
+ if (hs->invocation) {
+ INFO("Disconnected before SCO Connection");
+ /* Reply with error */
+ GError *err = NULL;
+ err = __bt_ag_agent_set_error(BT_HFP_AGENT_ERROR_NOT_CONNECTED);
+ g_dbus_method_invocation_return_gerror(hs->invocation, err);
+ hs->invocation = NULL;
+ g_error_free(err);
+ }
+ }
+
__bt_ag_close_sco(hs);
__bt_ag_headset_close_rfcomm(hs);
__bt_ag_stop_sco_server(hs);
g_free(hs->remote_addr);
+ g_free(hs->slc);
g_free(hs);
break;
BT_HEADSET_INTERFACE, "Playing",
g_variant_new("b", val));
- if (slconn->microphone_gain >= 0)
+ if (slconn->microphone_gain >= 0 &&
+ !slconn->is_voice_recognition_running)
_bt_ag_send_at(hs, "\r\n+VGM=%u\r\n",
slconn->microphone_gain);
- if (slconn->speaker_gain >= 0)
+ if (slconn->speaker_gain >= 0 &&
+ !slconn->is_voice_recognition_running)
_bt_ag_send_at(hs, "\r\n+VGS=%u\r\n",
slconn->speaker_gain);
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;
}
/* Synchronize the sending buffer */
+#if 0
+ /* Don't do sync call as it may block process untill all buffers are cleared
+ * On Z300F device this issue is reproduciable just connect with meacap
+ * select phonebook and call CPBR when we call CPBR multiple times it is
+ * blocking for 5 seconds.*/
sync();
+#endif
fsync(fd);
} else {
- ERR("FD is 0. remote_addr : %s", hdset->remote_addr);
+ ERR_SECURE("FD is 0. remote_addr : %s", hdset->remote_addr);
return -1;
}
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;
__bt_ag_codec_negotiation_info_reset(bt_ag_info, TRUE);
bt_ag_info->path = device_path;
- DBG("device_path = [%s]", device_path);
+ DBG_SECURE("device_path = [%s]", device_path);
address_len = sizeof(address);
if (getpeername(fd, (struct sockaddr *) &address, &address_len) != 0)
__bt_ag_agent_is_companion_device(bt_ag_info->remote_addr);
#endif
- DBG("remote Device Address = [%s]", bt_ag_info->remote_addr);
+ DBG_SECURE("remote Device Address = [%s]", bt_ag_info->remote_addr);
if (g_strcmp0(object_path, BT_HS_AG_AGENT_OBJECT_PATH) == 0) {
DBG("HSP connection completed");
__bt_ag_agent_start_watch(bt_ag_info);
bt_ag_info->slc = g_new0(bt_ag_slconn_t, 1);
- bt_ag_info->slc->speaker_gain = 15;
- bt_ag_info->slc->microphone_gain = 15;
+ bt_ag_info->slc->speaker_gain = last_speaker_gain;
+ bt_ag_info->slc->microphone_gain = 9;
bt_ag_info->slc->is_nrec = TRUE;
return TRUE;
}
} else
__bt_ag_sco_connect(bt_ag_info);
+
+ DBG("Dbus Reply for SCO Connection request");
+ g_dbus_method_invocation_return_value(bt_ag_info->invocation, NULL);
}
return FALSE;
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);
int ret = BT_HFP_AGENT_ERROR_NONE;
GError *err = NULL;
const gchar *device_path = NULL;
+ GSList *l;
if (g_strcmp0(method_name, "NewConnection") == 0) {
gint32 fd;
g_variant_get(parameters, "(oha{sv})",
&device_path, &index, &options);
#if defined(TIZEN_SUPPORT_DUAL_HF)
- if (device_count &&
- __bt_ag_agent_check_dual_hf_condition(device_path) == FALSE) {
- INFO("not allow to connect 2nd HF connection");
- ret = BT_HFP_AGENT_ERROR_INTERNAL;
- goto fail;
+ if (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");
+ ret = BT_HFP_AGENT_ERROR_INTERNAL;
+ goto fail;
+ }
}
#endif
msg = g_dbus_method_invocation_get_message(invocation);
goto fail;
}
- DBG("FD is = [%d], device_path = [%s]\n", fd, device_path);
+ DBG_SECURE("FD is = [%d], device_path = [%s]\n", fd, device_path);
if (!__bt_ag_agent_connection(fd, device_path, object_path)) {
ret = BT_HFP_AGENT_ERROR_INTERNAL;
g_dbus_method_invocation_return_value(invocation, NULL);
} else if (g_strcmp0(method_name, "RequestDisconnection") == 0) {
- GSList *l;
g_variant_get(parameters, "(o)", &device_path);
- INFO("device_path %s", device_path);
+ INFO_SECURE("device_path %s", device_path);
for (l = active_devices; l; l = l->next) {
bt_ag_info_t *data = l->data;
- INFO("data->path %s", data->path);
+ INFO_SECURE("data->path %s", data->path);
if (g_strcmp0(data->path, device_path) == 0) {
if (!__bt_ag_agent_connection_release(data)) {
ret = BT_HFP_AGENT_ERROR_INTERNAL;
g_dbus_method_invocation_return_value(invocation, NULL);
}
}
+ } else if (g_strcmp0(method_name, "ReplyAuthorize") == 0) {
+ const guint accept;
+ bt_ag_info_t *data;
+ g_variant_get(parameters, "(u)", &accept);
+ INFO("Accept: %d", accept);
+
+ l = active_devices;
+ data = l->data;
+ INFO_SECURE("data->path %s", data->path);
+ data->pbap_trusted = accept;
+
+ _bt_hfp_select_phonebook_memory_status_reply(data);
+
+ INFO("pbap_trusted %d", data->pbap_trusted);
+
+ if (data->pbap_trusted == BT_AG_FEATURE_PBAP_ALLOWED) {
+ /* Allow Access update this to bluez */
+ bt_device_set_profile_trusted(data->remote_addr,
+ 1, TRUE);
+ } else if (data->pbap_trusted == BT_AG_FEATURE_PBAP_BLOCKED) {
+ /* Blocked Access update this to bluez */
+ bt_device_set_profile_trusted(data->remote_addr,
+ 1, FALSE);
+ }
} else if (g_strcmp0(method_name, "RegisterApplication") == 0) {
gchar *path = NULL;
gchar *address = NULL;
g_free(local_addr);
local_addr = g_strdup(address);
- DBG("Address = %s\n", local_addr);
+ DBG_SECURE("Address = %s\n", local_addr);
g_dbus_method_invocation_return_value(invocation, NULL);
} else if (g_strcmp0(method_name, "UnregisterApplication") == 0) {
gchar *path = NULL;
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, };
- GSList *l;
for (l = active_devices; l; l = l->next) {
bt_ag_info_t *data = l->data;
__bt_convert_addr_type_to_rev_string(hdset_address,
(unsigned char *)data->remote_addr);
- DBG("Disconnect Headset %s, %s\n",
+ DBG_SECURE("Disconnect Headset %s, %s\n",
hdset_address, data->path);
_bt_ag_set_headset_state(data,
HEADSET_STATE_DISCONNECTED);
g_dbus_method_invocation_return_value(invocation, NULL);
} else if (g_strcmp0(method_name, "IsConnected") == 0) {
gboolean is_connected = FALSE;
- GSList *l;
for (l = active_devices; l; l = l->next) {
bt_ag_info_t *data = l->data;
- if (data->state == HEADSET_STATE_CONNECTED)
+ if (data->state >= HEADSET_STATE_CONNECTED)
is_connected = TRUE;
}
DBG("is_connected : %s",
g_dbus_method_invocation_return_value(invocation,
g_variant_new("(b)", is_connected));
} else if (g_strcmp0(method_name, "IndicateCall") == 0) {
- GSList *l;
if (0 == g_slist_length(active_devices)) {
ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
ERR("Play In Progress");
ret = BT_HFP_AGENT_ERROR_BUSY;
break;
+ case HEADSET_STATE_ON_CALL:
+ ERR("SCO is already established");
+ ret = BT_HFP_AGENT_ERROR_ALREADY_CONNECTED;
+ break;
default:
break;
}
if (sco_open_timer_id > 0) {
INFO("SCO open delay");
sco_open_request = TRUE;
- g_dbus_method_invocation_return_value(invocation, NULL);
+ bt_ag_info->invocation = invocation;
return;
}
g_dbus_method_invocation_return_value(invocation, NULL);
- name_owner_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
+ if (name_owner_sig_id == 0)
+ name_owner_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
NULL, NULL, "NameOwnerChanged", NULL, NULL, 0,
__bt_ag_name_owner_changed_cb, NULL, NULL);
} else if (g_strcmp0(method_name, "Stop") == 0) {
- GSList *l;
for (l = active_devices; l; l = l->next) {
bt_ag_info_t *data = l->data;
g_dbus_method_invocation_return_value(invocation, NULL);
} else if (g_strcmp0(method_name, "IsPlaying") == 0) {
gboolean is_playing = FALSE;
- GSList *l;
for (l = active_devices; l; l = l->next) {
bt_ag_info_t *data = l->data;
guint16 gain_value = 0;
bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
- if (bt_ag_info == NULL) {
- ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
- goto fail;
- }
-
- if (bt_ag_info->state < HEADSET_STATE_CONNECTED) {
+ if (bt_ag_info == NULL ||
+ bt_ag_info->state < HEADSET_STATE_CONNECTED) {
ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
goto fail;
}
} else if (g_strcmp0(method_name, "SetSpeakerGain") == 0) {
guint16 gain = 0;
bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
+ if (bt_ag_info == NULL ||
+ bt_ag_info->state < HEADSET_STATE_CONNECTED) {
+ ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
+ goto fail;
+ }
g_variant_get(parameters, "(q)", &gain);
DBG("Speaker gain = %d\n", gain);
- if (bt_ag_info == NULL) {
- ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
- goto fail;
- }
-
ret = _bt_hfp_set_speaker_gain(bt_ag_info, gain);
if (ret)
goto fail;
guint16 gain_value = 0;
bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
- if (bt_ag_info == NULL) {
- ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
+ if (bt_ag_info == NULL ||
+ bt_ag_info->state < HEADSET_STATE_CONNECTED) {
+ ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
goto fail;
}
} else if (g_strcmp0(method_name, "SetMicrophoneGain") == 0) {
guint16 gain = 0;
bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
+ if (bt_ag_info == NULL ||
+ bt_ag_info->state < HEADSET_STATE_CONNECTED) {
+ ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
+ goto fail;
+ }
g_variant_get(parameters, "(q)", &gain);
DBG("Microphone gain = %d\n", gain);
- if (bt_ag_info == NULL) {
- ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
- goto fail;
- }
-
ret = _bt_hfp_set_microphone_gain(bt_ag_info, gain);
if (ret)
goto fail;
g_dbus_method_invocation_return_value(invocation, NULL);
} else if (g_strcmp0(method_name, "SetVoiceDial") == 0) {
bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
- if (bt_ag_info == NULL) {
- ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
+ if (bt_ag_info == NULL ||
+ bt_ag_info->state < HEADSET_STATE_CONNECTED) {
+ ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
goto fail;
}
} else if (g_strcmp0(method_name, "SendVendorAtCmd") == 0) {
gchar *cmd;
bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
- if (bt_ag_info == NULL) {
- ret = BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
+ if (bt_ag_info == NULL ||
+ bt_ag_info->state < HEADSET_STATE_CONNECTED) {
+ ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
goto fail;
}
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("-");
}
}
-static GDBusProxy *__bt_ag_gdbus_get_service_proxy(const gchar *service,
- const gchar *path, const gchar *interface)
+static GDBusProxy *__bt_ag_gdbus_get_profile_proxy(void)
{
- return (service_gproxy) ? service_gproxy :
- __bt_ag_gdbus_init_service_proxy(service,
- path, interface);
+ return (profile_gproxy) ? profile_gproxy :
+ __bt_ag_gdbus_init_profile_proxy();
}
static void __bt_ag_agent_register(gchar *path, uint16_t profile_version,
GError *error = NULL;
GVariantBuilder *builder;
- proxy = __bt_ag_gdbus_get_service_proxy(BLUEZ_SERVICE_NAME,
- "/org/bluez", BLUEZ_PROFILE_MGMT_INTERFACE);
+ proxy = __bt_ag_gdbus_get_profile_proxy();
if (proxy == NULL)
return;
-
builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
g_variant_builder_add(builder, "{sv}",
GVariant *ret;
GError *error = NULL;
- proxy = __bt_ag_gdbus_get_service_proxy(BLUEZ_SERVICE_NAME,
- "/org/bluez", BLUEZ_PROFILE_MGMT_INTERFACE);
+ proxy = __bt_ag_gdbus_get_profile_proxy();
if (proxy == NULL)
return;
-
ret = g_dbus_proxy_call_sync(proxy, "UnregisterProfile",
g_variant_new("(o)", path),
- G_DBUS_CALL_FLAGS_NONE, -1,
+ G_DBUS_CALL_FLAGS_NONE, 100,
NULL, &error);
g_free(path);
/* set the name and role for the profile*/
return;
}
-static void __bt_ag_agent_battery_status_cb(keynode_t *node)
+static void __bt_ag_agent_battery_status_cb(device_callback_e type,
+ void *value, void *user_data)
{
- int batt = vconf_keynode_get_int(node);
-
- _bt_hfp_set_property_value("BatteryBarsChanged", batt);
+ int batt_cap;
+ if (type == DEVICE_CALLBACK_BATTERY_CAPACITY) {
+ device_battery_get_percent(&batt_cap);
+ _bt_hfp_set_property_value("BatteryBarsChanged", batt_cap);
+ }
}
-static void __bt_ag_agent_network_signal_status_cb(keynode_t *node)
+static void __bt_ag_agent_network_signal_status_cb(TapiHandle *handle,
+ const char *noti_id, void *data, void *user_data)
{
- int signal_bar = vconf_keynode_get_int(node);
+ int *signal_bar = data;
- BT_CHECK_SIGNAL_STRENGTH(signal_bar);
- _bt_hfp_set_property_value("SignalBarsChanged", signal_bar);
+ BT_CHECK_SIGNAL_STRENGTH(*signal_bar);
+ _bt_hfp_set_property_value("SignalBarsChanged", *signal_bar);
}
-#ifdef TIZEN_SUPPORT_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)
+static void __bt_ag_agent_call_preferred_voice_subscription_cb(TapiHandle *handle,
+ const char *noti_id, void *data, void *user_data)
{
- int service = vconf_keynode_get_int(node);
+ TelCallPreferredVoiceSubsNoti_t *noti_data = (TelCallPreferredVoiceSubsNoti_t *)data;
+ uint32_t ag_features;
+ int tapi_result;
+ if (!noti_data) {
+ ERR("Error happen during voice subscription data noti");
+ return;
+ }
+
+ INFO("TAPI_NOTI_CALL_PREFERRED_VOICE_SUBSCRIPTION = Value %d",
+ noti_data->preferred_subs);
+ ag_features = __bt_ag_agent_get_ag_features();
+ switch (noti_data->preferred_subs) {
+ case TAPI_CALL_PREFERRED_VOICE_SUBS_SIM1:
+ case TAPI_CALL_PREFERRED_VOICE_SUBS_ASK_ALWAYS:
+ if (tapi_handle_preferred_sim == tapi_handle[0]) {
+ INFO("No handler change. Preferred sim is same as SIM1");
+ break;
+ }
+ __bt_ag_agent_unsubscribe_tapi_updates(tapi_handle_preferred_sim);
+ tapi_handle_preferred_sim = tapi_handle[0];
+ _bt_hfp_initialize_telephony_manager(ag_features, tapi_handle_preferred_sim);
+ __bt_ag_agent_subscribe_tapi_updates(tapi_handle_preferred_sim);
+ tapi_result = tel_get_sim_msisdn(GET_TAPI_HANDLE, __bt_ag_agent_tel_cb, NULL);
+ if (tapi_result != TAPI_API_SUCCESS)
+ ERR("Fail to get sim info: %d", tapi_result);
+ break;
+ case TAPI_CALL_PREFERRED_VOICE_SUBS_SIM2:
+ if (tapi_handle_preferred_sim == tapi_handle[1]) {
+ INFO("No handler change. Preferred sim is same as SIM2");
+ break;
+ }
+ __bt_ag_agent_unsubscribe_tapi_updates(tapi_handle_preferred_sim);
+ tapi_handle_preferred_sim = tapi_handle[1];
+ _bt_hfp_initialize_telephony_manager(ag_features, tapi_handle_preferred_sim);
+ __bt_ag_agent_subscribe_tapi_updates(tapi_handle_preferred_sim);
+ tapi_result = tel_get_sim_msisdn(GET_TAPI_HANDLE, __bt_ag_agent_tel_cb, NULL);
+ if (tapi_result != TAPI_API_SUCCESS)
+ ERR("Fail to get sim info: %d", tapi_result);
+
+ break;
+
+ case TAPI_CALL_PREFERRED_VOICE_SUBS_CURRENT_NETWORK:
+ case TAPI_CALL_PREFERRED_VOICE_SUBS_UNKNOWN:
+ default:
+ break;
+ }
+}
+
+static void __bt_ag_agent_network_register_status_cb(TapiHandle *handle,
+ const char *noti_id, void *data, void *user_data)
+{
+ int service;
bt_hfp_agent_network_registration_status_t network_service;
int roam_status;
int ret;
- DBG("Current Signal Level = [%d] \n", service);
+ int *service_type = data;
+
+ DBG("Network service type changed = [%d]", *service_type);
- switch (service) {
- case VCONFKEY_TELEPHONY_SVCTYPE_NONE:
- case VCONFKEY_TELEPHONY_SVCTYPE_NOSVC:
- case VCONFKEY_TELEPHONY_SVCTYPE_SEARCH:
+ switch (*service_type) {
+ case TAPI_NETWORK_SERVICE_TYPE_UNKNOWN:
+ case TAPI_NETWORK_SERVICE_TYPE_NO_SERVICE:
+ case TAPI_NETWORK_SERVICE_TYPE_SEARCH:
service = 0;
break;
default:
break;
}
- ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
- if (ret != 0) {
+ ret = tel_get_property_int(GET_TAPI_HANDLE,
+ TAPI_PROP_NETWORK_ROAMING_STATUS, &roam_status);
+ if (ret != TAPI_API_SUCCESS) {
ERR("Get roaming status failed err = %d\n", ret);
return;
}
int ret;
DBG("\n");
-
- ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
- (void *)__bt_ag_agent_battery_status_cb, NULL);
- if (0 != ret) {
- ERR("Subsrciption to battery status failed err = [%d]\n", ret);
- }
-
- ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_RSSI,
- (void *)__bt_ag_agent_network_signal_status_cb, NULL);
- if (0 != ret) {
- ERR("Subsrciption to netowrk signal failed err = [%d]\n", ret);
+ ret = device_add_callback(DEVICE_CALLBACK_BATTERY_CAPACITY,
+ __bt_ag_agent_battery_status_cb, NULL);
+ if (ret != DEVICE_ERROR_NONE) {
+ ERR("Subscription to battery status failed err = [%d]\n", ret);
}
- ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
- (void *)__bt_ag_agent_network_register_status_cb, NULL);
- if (0 != ret) {
- ERR("Subsrciption to network failed err = [%d]\n", ret);
+ 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);
}
-#ifdef TIZEN_SUPPORT_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
}
static void __bt_ag_agent_release_vconf_updates(void)
int ret;
DBG("\n");
-
- ret = vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
- (vconf_callback_fn)__bt_ag_agent_battery_status_cb);
- if (0 != ret) {
- ERR("vconf_ignore_key_changed failed\n");
+ ret = device_remove_callback(DEVICE_CALLBACK_BATTERY_CAPACITY,
+ __bt_ag_agent_battery_status_cb);
+ if (ret != DEVICE_ERROR_NONE) {
+ ERR("Unsubscription to battery status failed err = [%d]\n", ret);
}
- ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_RSSI,
- (vconf_callback_fn)__bt_ag_agent_network_signal_status_cb);
- if (0 != ret) {
- ERR("vconf_ignore_key_changed failed\n");
- }
-
- ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
- (vconf_callback_fn)__bt_ag_agent_network_register_status_cb);
- if (0 != ret) {
- ERR("vconf_ignore_key_changed failed\n");
+ if (TIZEN_PROFILE_WEARABLE) {
+ ret = vconf_ignore_key_changed(VCONF_KEY_BT_LUNAR_ENABLED,
+ (void *)__bt_ag_agent_lunar_connection_status_cb);
+ if (0 != ret)
+ ERR("Subsrciption to lunar connection failed err = [%d]\n", ret);
}
}
FN_START;
- DBG("Number is %s", number);
+ DBG_SECURE("Number is %s", number);
if (!_bt_hfp_set_property_name(property, number)) {
DBG("Error- set property for subscriber no change - ERROR\n");
TelSimMsisdnList_t *number;
gchar *subscriber_number;
- ERR("*********** result = %d", result);
+ ERR("*********** Result =%d **********", result);
+
+ if (result == TAPI_ERROR_OPERATION_FAILED ||
+ result == TAPI_ERROR_ACCESS_DENIED ||
+ result == TAPI_ERROR_OPERATION_NOT_SUPPORTED) {
+ ERR("SIM has limited capabilities");
+ __bt_ag_agent_send_subscriber_number_changed("");
+ return;
+ }
if (result == TAPI_API_SIM_LOCKED ||
result == TAPI_API_SIM_NOT_INITIALIZED ||
return;
if (strcasecmp(name_owner, sco_owner) == 0) {
- if (name_owner_sig_id != -1)
+ if (name_owner_sig_id)
g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
name_owner_sig_id);
- name_owner_sig_id = -1;
+ name_owner_sig_id = 0;
g_free(sco_owner);
sco_owner = NULL;
}
}
-static void __bt_ag_agent_filter_cb(GDBusConnection *connection,
+static void __bt_ag_agent_bluez_interface_signal_cb(GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
return;
}
- INFO("Adapter Path = [%s]", path);
+ INFO_SECURE("Adapter Path = [%s]", path);
if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
gchar *path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
__bt_ag_agent_register(path, hfp_ver,
return;
}
- INFO("Adapter Path = [%s]", path);
+ INFO_SECURE("Adapter Path = [%s]", path);
if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
gchar *path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
__bt_ag_agent_unregister(path);
FN_END;
}
-static void __bt_ag_agent_dbus_deinit(void)
+static void __bt_ag_agent_bluez_property_changed_cb(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
{
+ GVariant *optional_param = NULL;
+ char *inter = NULL;
+ GVariant *dict_param = NULL;
- if (service_gproxy) {
- g_object_unref(service_gproxy);
- service_gproxy = NULL;
+ if (strcasecmp(signal_name, BT_PROPERTY_CHANGED) == 0) {
+ if (g_strcmp0(g_variant_get_type_string(parameters),
+ "(sa{sv}as)")) {
+ ERR("Incorrect parameters\n");
+ return;
+ }
+ g_variant_get(parameters, "(&s@a{sv}@as)",
+ &inter, &dict_param, &optional_param);
+ if (strcasecmp(inter, BLUEZ_DEVICE_INTERFACE) == 0) {
+ GVariantDict dict;
+ int trusted = 0;
+ g_variant_dict_init(&dict, dict_param);
+ if (g_variant_dict_lookup(
+ &dict, "TrustedProfiles", "u", &trusted)) {
+ GSList *l;
+ for (l = active_devices ; l; l = l->next) {
+ bt_ag_info_t *data = l->data;
+ if (g_strcmp0(data->path, object_path) != 0)
+ continue;
+ if (trusted == BT_PROFILE_SUPPORTED_TRUSTED) {
+ data->pbap_trusted =
+ BT_AG_FEATURE_PBAP_ALLOWED;
+ DBG("[%s] PBAP is TRUSTED", object_path);
+ } else if (trusted == BT_PROFILE_SUPPORTED_BLOCKED) {
+ data->pbap_trusted =
+ BT_AG_FEATURE_PBAP_BLOCKED;
+ DBG("[%s] PBAP is BLOCKED", object_path);
+ }
+ }
+ }
+ g_variant_dict_end(&dict);
+ }
+ if (dict_param)
+ g_variant_unref(dict_param);
}
- if (app_gproxy) {
- g_object_unref(app_gproxy);
- app_gproxy = NULL;
+ if (optional_param)
+ g_variant_unref(optional_param);
+}
+
+static void __bt_ag_agent_dbus_deinit(void)
+{
+ if (profile_gproxy) {
+ g_object_unref(profile_gproxy);
+ profile_gproxy = NULL;
}
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,
- owner_sig_id);
+ interface_added_sig_id);
- if (name_owner_sig_id != -1)
+ if (interface_removed_sig_id)
+ g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
+ interface_removed_sig_id);
+
+ if (proterty_changed_sig_id)
+ g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
+ proterty_changed_sig_id);
+
+ if (name_owner_sig_id)
g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
name_owner_sig_id);
-#ifdef TIZEN_MEDIA_ENHANCE
- if (media_sig_id != -1)
+#ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
+ if (media_sig_id)
g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
media_sig_id);
- if (media_state_sig_id != -1)
- g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
- media_state_sig_id);
+ media_sig_id = 0;
#endif
- name_owner_sig_id = -1;
+ if (device_property_id)
+ g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
+ device_property_id);
+
+ device_property_id = 0;
+ interface_added_sig_id = 0;
+ interface_removed_sig_id = 0;
+ proterty_changed_sig_id = 0;
+ name_owner_sig_id = 0;
g_free(sco_owner);
sco_owner = NULL;
g_object_unref(ag_dbus_conn);
ag_dbus_conn = NULL;
}
- return;
}
static int __bt_ag_agent_get_adapter_path(GDBusConnection *conn, char *path)
}
-#ifdef TIZEN_MEDIA_ENHANCE
+#ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
void _bt_ag_agent_check_transport_state(void)
{
FN_START;
G_DBUS_CALL_FLAGS_NONE, 2000,
NULL, NULL, NULL);
transport_state = MEDIA_TRANSPORT_STATE_IDLE;
+ g_object_unref(proxy);
}
FN_END;
char *inter = NULL;
GVariant *dict_param = NULL;
GVariant *optional_param = NULL;
-
+ GSList *l;
if (strcasecmp(signal_name, "PropertiesChanged") == 0) {
if (g_strcmp0(g_variant_get_type_string(parameters),
"(sa{sv}as)")) {
GVariantIter *iter = NULL;
const gchar *key = NULL;
GVariant *value_var = NULL;
- gchar *value = NULL;
+ const gchar *value = NULL;
g_variant_get(dict_param, "a{sv}", &iter);
while (g_variant_iter_loop(
iter, "{sv}", &key, &value_var)) {
}
}
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,
- __bt_ag_agent_filter_cb, NULL, NULL);
-#ifdef TIZEN_MEDIA_ENHANCE
+ 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_bluez_interface_signal_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_bluez_interface_signal_cb, NULL, NULL);
+
+ proterty_changed_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
+ NULL, BT_MANAGER_INTERFACE,
+ BT_PROPERTY_CHANGED, NULL, NULL, 0,
+ __bt_ag_agent_bluez_property_changed_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,
NULL, 0, __bt_ag_agent_media_filter_cb,
transport_state = MEDIA_TRANSPORT_STATE_DISCONNECTED;
#endif
+ device_property_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
+ NULL, BT_PROPERTIES_INTERFACE, BT_PROPERTY_CHANGED, NULL,
+ NULL, 0, __bt_ag_agent_bluez_property_changed_cb,
+ NULL, NULL);
FN_END;
return;
}
+static void __bt_ag_agent_subscribe_tapi_updates(TapiHandle *handle)
+{
+ int ret;
+
+ DBG("\nSubscribe tapi update for handler %p", handle);
+
+ ret = tel_register_noti_event(handle, TAPI_PROP_NETWORK_SIGNALSTRENGTH_LEVEL,
+ __bt_ag_agent_network_signal_status_cb, NULL);
+ if (ret != TAPI_API_SUCCESS) {
+ ERR("Subsrciption to netowrk signal failed err = [%d]\n", ret);
+ }
+
+ ret = tel_register_noti_event(handle, TAPI_PROP_NETWORK_SERVICE_TYPE,
+ __bt_ag_agent_network_register_status_cb, NULL);
+ if (ret != TAPI_API_SUCCESS) {
+ ERR("Subsrciption to network failed err = [%d]\n", ret);
+ }
+
+ ret = tel_register_noti_event(handle, TAPI_NOTI_CALL_PREFERRED_VOICE_SUBSCRIPTION,
+ __bt_ag_agent_call_preferred_voice_subscription_cb, NULL);
+ if (ret != TAPI_API_SUCCESS) {
+ ERR("Subsrciption to preferred voice err = [%d]\n", ret);
+ }
+
+}
+
+static void __bt_ag_agent_unsubscribe_tapi_updates(TapiHandle *handle)
+{
+ int ret;
+
+ DBG("\nUnsubscribe tapi update for handler %p", handle);
+
+ ret = tel_deregister_noti_event(handle, TAPI_PROP_NETWORK_SIGNALSTRENGTH_LEVEL);
+ if (ret != TAPI_API_SUCCESS) {
+ ERR("Subsrciption to netowrk signal failed err = [%d]\n", ret);
+ }
+
+ ret = tel_deregister_noti_event(handle, TAPI_PROP_NETWORK_SERVICE_TYPE);
+ if (ret != TAPI_API_SUCCESS) {
+ ERR("Subsrciption to network failed err = [%d]\n", ret);
+ }
+
+ ret = tel_deregister_noti_event(handle, TAPI_NOTI_CALL_PREFERRED_VOICE_SUBSCRIPTION);
+ if (ret != TAPI_API_SUCCESS) {
+ ERR("Subsrciption to preferred voice err = [%d]\n", ret);
+ }
+}
+
static uint32_t __bt_ag_agent_get_ag_features(void)
{
BT_AG_FEATURE_REJECT_CALL |
BT_AG_FEATURE_ENHANCED_CALL_STATUS |
BT_AG_FEATURE_THREE_WAY_CALL |
-#ifndef TIZEN_KIRAN
+#if !defined(TIZEN_FEATURE_BT_VENDOR_SPRD)
BT_AG_FEATURE_VOICE_RECOGNITION |
#endif
BT_AG_FEATURE_EXTENDED_ERROR_RESULT_CODES;
+#ifdef TIZEN_FEATURE_BT_SCO_WIDEBAND
wbs_en = TRUE;
-#if defined(TIZEN_BT_HFP_AG_ENABLE)
- hfp_ver = HFP_VERSION_1_6;
#else
- hfp_ver = HFP_VERSION_1_5;
+ wbs_en = FALSE;
#endif
+
+ hfp_ver = HFP_VERSION_1_7;
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;
}
-void *__bt_ag_agent_telephony_init(void *arg)
+static void __bt_ag_agent_tel_get_preferred_sim(TapiHandle *handler)
+{
+ TelCallPreferredVoiceSubs_t preferredSubscription;
+ int err_code = tel_get_call_preferred_voice_subscription(handler, &preferredSubscription);
+ if (err_code == TAPI_API_SUCCESS) {
+ if (preferredSubscription == TAPI_CALL_PREFERRED_VOICE_SUBS_SIM1) {
+ tapi_handle_preferred_sim = tapi_handle[0];
+ INFO("Preferred SIM 1");
+ } else if (preferredSubscription == TAPI_CALL_PREFERRED_VOICE_SUBS_SIM2) {
+ tapi_handle_preferred_sim = tapi_handle[1];
+ INFO("Preferred SIM 2");
+ } else if (preferredSubscription == TAPI_CALL_PREFERRED_VOICE_SUBS_CURRENT_NETWORK) {
+ INFO("Preferred SIM Current Network");
+ } else if (preferredSubscription == TAPI_CALL_PREFERRED_VOICE_SUBS_ASK_ALWAYS) {
+ tapi_handle_preferred_sim = tapi_handle[0];
+ INFO("Preferred SIM Always Ask");
+ } else {
+ ERR("Unknown Preferred voice subscription");
+ }
+ }
+}
+
+static void __bt_ag_agent_tel_init_multisim(void)
+{
+ INFO_C("Initializing the telephony multi sim info");
+
+ char **cp_list = NULL;
+ unsigned int modem_num = 0;
+ int err_code;
+ TelSimCardStatus_t simStatus = 0;
+ int card_changed = 0;
+
+
+
+ /* Get CP name list ? cp_list */
+ cp_list = tel_get_cp_name_list();
+ if (cp_list == NULL) {
+ ERR("tel_get_cp_name_list() Failed");
+ return;
+ }
+
+ while (cp_list[modem_num]) {
+ /* Initialize TAPI handle */
+ tapi_handle[modem_num] = tel_init(cp_list[modem_num]);
+
+ if (tapi_handle[modem_num] == NULL) {
+ /* TAPI initialization ? Failure */
+ ERR_SECURE("tel_init failed for Modem SIM number = %d", modem_num);
+ } else {
+ /* TAPI initialization ? Success */
+ DBG_SECURE("Success for Modem SIM number = %d, handler = %p",
+ modem_num, tapi_handle[modem_num]);
+ err_code = tel_get_sim_init_info(tapi_handle[modem_num],
+ &simStatus, &card_changed);
+ INFO_SECURE("Sim number = %d SIM status = %d", modem_num, simStatus);
+ if ((TAPI_API_SUCCESS == err_code) &&
+ (TAPI_SIM_STATUS_SIM_INIT_COMPLETED == simStatus)) {
+ if (modem_num == 0)
+ sim1 = 1;
+ else
+ sim2 = 1;
+ }
+ }
+
+ /* Move to next CP Name in cp_list */
+ modem_num++;
+ }
+
+ tapi_handle[modem_num] = NULL;
+
+ g_strfreev(cp_list);
+}
+
+static void __bt_ag_agent_tel_deinit_multisim(void)
{
+ INFO_C("DeInitializing the telephony multi sim info");
+
+ char **cp_list = NULL;
+ unsigned int modem_num = 0;
+ int result;
+
+ cp_list = tel_get_cp_name_list();
+ if (cp_list == NULL) {
+ ERR("tel_get_cp_name_list() Failed");
+ return;
+ }
+
+ while (cp_list[modem_num]) {
+ result = tel_deinit(tapi_handle[modem_num]);
+ if (result != TAPI_API_SUCCESS)
+ ERR("Fail to tel_deinit");
+ /* Move to next CP Name in cp_list */
+ modem_num++;
+ }
+ g_strfreev(cp_list);
+}
+
+gboolean __bt_ag_agent_telephony_init(void *arg)
+{
int tapi_result;
uint32_t ag_features = *((uint32_t *)arg);
INFO_C("Initializing the telephony info");
-
- _bt_hfp_initialize_telephony_manager(ag_features);
+ __bt_ag_agent_tel_init_multisim();
+ __bt_ag_agent_tel_get_preferred_sim(GET_TAPI_HANDLE);
+ _bt_hfp_initialize_telephony_manager(ag_features, GET_TAPI_HANDLE);
+ __bt_ag_agent_subscribe_tapi_updates(GET_TAPI_HANDLE);
__bt_ag_agent_subscribe_vconf_updates();
-
- tapi_handle = tel_init(NULL);
- tapi_result = tel_get_sim_msisdn(tapi_handle, __bt_ag_agent_tel_cb,
+ tapi_result = tel_get_sim_msisdn(GET_TAPI_HANDLE, __bt_ag_agent_tel_cb,
NULL);
if (tapi_result != TAPI_API_SUCCESS)
ERR("Fail to get sim info: %d", tapi_result);
- return NULL;
+ return FALSE;
}
int main(void)
int i;
uint32_t ag_features;
struct sigaction sa;
- pthread_t thread_id;
- INFO_C("Starting Bluetooth AG agent");
+ INFO_C("### Starting Bluetooth AG agent");
+#if GLIB_VERSION_MIN_REQUIRED < GLIB_VERSION_2_36
+ g_type_init();
+#endif
ag_features = __bt_ag_agent_get_ag_features();
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;
+ __bt_ag_agent_dbus_init();
+
+ g_idle_add(__bt_ag_agent_telephony_init, &ag_features);
+
memset(&sa, 0, sizeof(sa));
sa.sa_flags = SA_NOCLDSTOP;
sa.sa_handler = __bt_ag_agent_sigterm_handler;
return EXIT_FAILURE;
}
- __bt_ag_agent_dbus_init();
- if (pthread_create(&thread_id, NULL,
- (void *)&__bt_ag_agent_telephony_init,
- &ag_features) < 0) {
- ERR("pthread_create() is failed");
- return EXIT_FAILURE;
- }
-
- if (pthread_detach(thread_id) < 0) {
- ERR("pthread_detach() is failed");
- }
-
g_main_loop_run(gmain_loop);
DBG("Cleaning up");
- tel_deinit(tapi_handle);
-
__bt_ag_agent_dbus_deinit();
_bt_hfp_deinitialize_telephony_manager();
__bt_ag_agent_release_vconf_updates();
-
+ __bt_ag_agent_unsubscribe_tapi_updates(GET_TAPI_HANDLE);
+ __bt_ag_agent_tel_deinit_multisim();
if (remote_dev_path)
g_free(remote_dev_path);
if (gmain_loop)
g_main_loop_unref(gmain_loop);
- INFO_C("Terminating Bluetooth AG agent");
+ INFO_C("### Terminating Bluetooth AG agent");
return 0;
}