./services/socket/bt-service-socket.c
./services/rfcomm/bt-service-rfcomm.c
./services/audio/bt-service-audio.c
+./services/audio/bt-service-headset-connection.c
./services/audio/hf/bt-service-hf.c
./services/audio/a2dp_src/bt-service-a2dp-src.c
./services/audio/a2dp_sink/bt-service-a2dp-sink.c
#include "oal-hardware.h"
#include "oal-device-mgr.h"
-#include <oal-manager.h>
-#include <oal-audio-src.h>
+#include "oal-manager.h"
+#include "oal-audio-src.h"
-#include <bt-service-a2dp-src.h>
-#include <bt-service-event.h>
+#include "bt-service-a2dp-src.h"
+#include "bt-service-core-device.h"
+#include "bt-service-event.h"
+#include "bt-service-headset-connection.h"
int _bt_a2dp_connect_remote_sink(bluetooth_device_address_t *device_address)
{
GArray *out_param;
invocation_info_t *req_info;
bt_pending_audio_conn_t *data = NULL;
+ guint trusted = TRUSTED_PROFILE_ALLOWED;
int result = BLUETOOTH_ERROR_NONE;
ret_if(NULL == address);
/* Send A2DP(SRC Role) connected event to Application */
param = g_variant_new("(is)", result, addr);
_bt_send_event(BT_HEADSET_EVENT, BLUETOOTH_EVENT_AV_CONNECTED, param);
+ _bt_connection_manager_set_state(addr, BLUETOOTH_EVENT_AV_CONNECTED);
connected = _bt_is_headset_type_connected(BT_AUDIO_A2DP, connected_address);
if (connected) {
out_param, result);
g_array_free(out_param, TRUE);
_bt_free_info_from_invocation_list(req_info);
+
+ _bt_get_trust_profile(address, TRUSTED_PROFILE_HFP_HF, &trusted);
+
+ if (_bt_headset_get_local_connection() == FALSE) {
+ if (trusted == TRUSTED_PROFILE_ALLOWED) /* Trusted */
+ _bt_start_timer_for_connection(addr, BT_AUDIO_HSP);
+ } else {
+ /* Connection Started from local device therefore no need to
+ * intiate connection for pending profile */
+ _bt_headset_set_local_connection(FALSE);
+ }
}
static void __bt_handle_av_disconnected_state(bluetooth_device_address_t *address)
_bt_audio_handle_a2dp_state_changed(addr, false);
#endif
+ _bt_connection_manager_set_state(addr, BLUETOOTH_EVENT_AV_DISCONNECTED);
+
req_info = _bt_get_request_info_data(BT_AV_DISCONNECT, addr);
BT_DBG("Address of disconnected device[%s]", addr);
#include <sys/errno.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <gio/gio.h>
#include <vconf.h>
-#include <oal-event.h>
-#include <oal-hardware.h>
-#include <oal-audio-src.h>
-#include <oal-a2dp-sink.h>
+#include "oal-a2dp-sink.h"
+#include "oal-audio-src.h"
+#include "oal-device-mgr.h"
+#include "oal-event.h"
+#include "oal-hardware.h"
+#include "oal-hf-client.h"
-#include "bt-service-common.h"
#include "bt-request-handler.h"
-#include "bt-service-audio-common.h"
-#include "bt-service-core-device.h"
-#include "bt-service-a2dp-src.h"
#include "bt-service-a2dp-sink.h"
-#include "bt-service-avrcp-tg.h"
+#include "bt-service-a2dp-src.h"
#include "bt-service-avrcp-ctrl.h"
+#include "bt-service-avrcp-tg.h"
+#include "bt-service-audio-common.h"
+#include "bt-service-common.h"
+#include "bt-service-core-device.h"
+#include "bt-service-headset-connection.h"
#include "bt-service-hf.h"
#include "bt-service-hf-client.h"
-#include "oal-hf-client.h"
#ifdef TIZEN_SUPPORT_DUAL_HF
#define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
/* List for saving device service search info */
static GSList *pending_audio_conn_list = NULL;
-/* Headset connection data structures */
-gboolean connection_local = FALSE;
-
static int curr_audio_role = BLUETOOTH_A2DP_SOURCE;
static int pending_audio_role = -1;
static void __bt_reply_pending_audio_connect_req(char *address, int result);
-#if 0
-void _bt_headset_set_local_connection(gboolean value)
-{
- BT_INFO("setting connection_local to %d", value);
- connection_local = value;
-}
-
-gboolean _bt_headset_get_local_connection()
-{
- return connection_local;
-}
-#endif
-
static const char *__convert_audio_type_to_string(bt_audio_type_t type)
{
switch (type) {
}
if (result == BLUETOOTH_ERROR_NONE) {
- //_bt_headset_set_local_connection(TRUE);
+ _bt_headset_set_local_connection(TRUE);
/* Add data to the connected list */
_bt_add_headset_to_list(type, BT_STATE_CONNECTING, addr);
BT_PERMANENT_LOG("Connect %s", __convert_audio_type_to_string(type));
g_array_free(out_param, TRUE);
_bt_free_info_from_invocation_list(req_info);
+ if (result != BLUETOOTH_ERROR_NONE)
+ _bt_headset_set_local_connection(FALSE);
+
BT_DBG("-");
}
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <glib.h>
+#include <string.h>
+#include <dlog.h>
+#include <vconf.h>
+#include <vconf-internal-bt-keys.h>
+
+#include "bluetooth-api.h"
+#include "bt-internal-types.h"
+
+#include "bt-service-audio-common.h"
+#include "bt-service-common.h"
+#include "bt-service-core-device.h"
+#include "bt-service-headset-connection.h"
+
+static GList *p_connection_list = NULL;
+typedef enum {
+ BLUETOOTH_NONE_CONNECTED = 0x00,
+ BLUETOOTH_HFP_CONNECTED ,
+ BLUETOOTH_A2DP_CONNECTED,
+ BLUETOOTH_ALL_CONNECTED,
+} bluetooth_state_type_t;
+
+typedef struct {
+ bluetooth_state_type_t state;
+ bluetooth_device_info_t dev_info;
+ int connection_type;
+} bt_connection_node_info_t;
+
+static gboolean connection_local = FALSE;
+static guint conn_timer;
+static bt_connection_node_info_t *conn_info;
+
+void _bt_headset_set_local_connection(gboolean value)
+{
+ BT_INFO("setting connection_local to %d", value);
+ connection_local = value;
+}
+
+gboolean _bt_headset_get_local_connection()
+{
+ return connection_local;
+}
+
+//gint compare_state(GList *data, bluetooth_state_type_t state)
+gint compare_state(gconstpointer list_data, gconstpointer conn_state)
+{
+ GList *data = (GList *) list_data;
+ bluetooth_state_type_t *state = (bluetooth_state_type_t *)conn_state;
+ bt_connection_node_info_t *p_data = (bt_connection_node_info_t *) data;
+ if (p_data->state == *state) {
+ BT_INFO("State Already Added");
+ return 0;
+ }
+ return 1;
+}
+
+gboolean connect_remote_media_audio(gpointer user_data)
+{
+ GList *list = NULL;
+ bluetooth_state_type_t state;
+
+ conn_timer = 0;
+ retv_if(conn_info == NULL, FALSE);
+
+ char remote_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+ _bt_convert_addr_type_to_string(remote_address, conn_info->dev_info.device_address.addr);
+ if (p_connection_list == NULL) {
+ BT_INFO("None of device connected and this hasbeen triggered");
+ g_free(conn_info);
+ conn_info = NULL;
+ return FALSE;
+ }
+ if (conn_info->connection_type == BT_AUDIO_A2DP) {
+ state = BLUETOOTH_A2DP_CONNECTED;
+ list = g_list_find_custom(p_connection_list,
+ &state, compare_state);
+ if (list == NULL) {
+ BT_INFO("Head Set didn't initiated a2dp connection");
+ BT_INFO("local device initiating A2DP connection");
+
+ _bt_audio_connect(BT_AUDIO_A2DP, &conn_info->dev_info.device_address);
+ } else {
+ BT_INFO("A2DP Connection Already exists");
+ }
+ } else {
+ state = BLUETOOTH_HFP_CONNECTED;
+ list = g_list_find_custom(p_connection_list,
+ &state, compare_state);
+ if (list == NULL) {
+ BT_INFO("Headset didn't initiated HFP connection");
+ BT_INFO("local device intiating HFP Connection");
+
+ _bt_audio_connect(BT_AUDIO_HSP, &conn_info->dev_info.device_address);
+ } else {
+ BT_INFO("HFP Connection Already exists");
+ }
+ }
+ g_free(conn_info);
+ conn_info = NULL;
+ return FALSE;
+}
+
+void _bt_get_bluetooth_device_info(char *remote_address, bluetooth_device_info_t *device)
+{
+ GArray *dev_list = NULL;
+ int size = 0;
+ int i = 0;
+ bluetooth_device_info_t *info;
+ char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+
+ if (device == NULL)
+ return;
+
+ dev_list = g_array_new(FALSE, FALSE, sizeof(gchar));
+
+ _bt_service_get_bonded_dev_list(&dev_list);
+ size = (dev_list->len) / sizeof(bluetooth_device_info_t);
+ for (i = 0; i < size; i++) {
+ info = &g_array_index(dev_list, bluetooth_device_info_t, i);
+ _bt_convert_addr_type_to_string(bond_address, info->device_address.addr);
+ if (strcmp(bond_address, remote_address) == 0) {
+ BT_INFO("Match found");
+ memcpy(device, info, sizeof(bluetooth_device_info_t));
+ g_array_free(dev_list, TRUE);
+ return;
+ }
+ }
+ g_array_free(dev_list, TRUE);
+ return;
+}
+
+static void _bt_headset_add_timer_function(int connection_type, bluetooth_device_info_t *info)
+{
+ if (info == NULL)
+ return;
+
+ _bt_stop_timer_for_connection();
+
+ conn_info = g_new0(bt_connection_node_info_t, 1);
+ conn_info->connection_type = connection_type;
+ memcpy(&conn_info->dev_info, info, sizeof(bluetooth_device_info_t));
+ /* This need to be freed in timer function */
+ conn_timer = g_timeout_add(CONNECT_TIMEOUT,
+ connect_remote_media_audio, NULL);
+ return;
+}
+
+void _bt_start_timer_for_connection(char *remote_address, int connection_type)
+{
+ GArray *dev_list = NULL;
+ int size;
+ int i;
+ int j;
+ bluetooth_device_info_t *info;
+ char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+ dev_list = g_array_new(FALSE, FALSE, sizeof(gchar));
+ _bt_service_get_bonded_dev_list(&dev_list);
+ size = (dev_list->len) / sizeof(bluetooth_device_info_t);
+
+ for (i = 0; i < size; i++) {
+ info = &g_array_index(dev_list, bluetooth_device_info_t, i);
+ j = 0;
+ _bt_convert_addr_type_to_string(bond_address,
+ info->device_address.addr);
+ if (strcmp(bond_address, remote_address) != 0)
+ continue;
+ BT_INFO("Device address Matched");
+
+ while (j != info->service_index) {
+ BT_INFO("UUID %s", info->uuids[j]);
+ if (connection_type == BT_AUDIO_A2DP) {
+ if (strcmp(info->uuids[j], A2DP_SINK_UUID) == 0) {
+ BT_INFO("Remote Device has A2DP Sink Support start timer");
+ _bt_headset_add_timer_function(BT_AUDIO_A2DP, info);
+ goto end;
+ }
+ } else {
+ if (strcmp(info->uuids[j], HFP_HS_UUID) == 0) {
+ BT_INFO("Remote Device has HFP Sink Support start timer");
+ _bt_headset_add_timer_function(BT_AUDIO_HSP, info);
+ goto end;
+ }
+ }
+ j++;
+ }
+ }
+end:
+ g_array_free(dev_list, TRUE);
+}
+
+void _bt_stop_timer_for_connection(void)
+{
+ if (conn_info != NULL) {
+ g_free(conn_info);
+ conn_info = NULL;
+ }
+
+ if (conn_timer > 0) {
+ g_source_remove(conn_timer);
+ conn_timer = 0;
+ }
+}
+
+void _bt_connection_manager_set_state(char *remote_address, int event)
+{
+ bt_connection_node_info_t *info;
+
+ char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+ if (event == BLUETOOTH_EVENT_AG_CONNECTED) {
+ info = g_new0(bt_connection_node_info_t, 1);
+ info->state = BLUETOOTH_HFP_CONNECTED;
+ _bt_get_bluetooth_device_info(remote_address, &info->dev_info);
+ _bt_convert_addr_type_to_string(bond_address,
+ info->dev_info.device_address.addr);
+ BT_INFO("Adding HFP Connected device to list");
+ p_connection_list = g_list_append(p_connection_list, info);
+ } else if (event == BLUETOOTH_EVENT_AG_DISCONNECTED) {
+ /* Delete coresponding node */
+ BT_INFO("Deleting HFP Connected device from list");
+ GList *list = NULL;
+ bluetooth_state_type_t state;
+ bt_connection_node_info_t *h_conn;
+ state = BLUETOOTH_HFP_CONNECTED;
+ list = g_list_find_custom(p_connection_list,
+ &state, compare_state);
+ if (list == NULL) {
+ BT_INFO("Didn't found any device with HFP State");
+ return;
+ }
+ h_conn = list->data;
+ p_connection_list = g_list_remove(p_connection_list, h_conn);
+ g_free(h_conn);
+ } else if (event == BLUETOOTH_EVENT_AV_CONNECTED) {
+ info = g_new0(bt_connection_node_info_t, 1);
+ info->state = BLUETOOTH_A2DP_CONNECTED;
+ _bt_get_bluetooth_device_info(remote_address, &info->dev_info);
+ _bt_convert_addr_type_to_string(bond_address,
+ info->dev_info.device_address.addr);
+ BT_INFO("Adding A2DP Connected device to list");
+ p_connection_list = g_list_append(p_connection_list, info);
+ } else if (event == BLUETOOTH_EVENT_AV_DISCONNECTED) {
+ BT_INFO("Deleting A2DP Connected device from list");
+ bt_connection_node_info_t *a_conn;
+ GList *list = NULL;
+ bluetooth_state_type_t state;
+ state = BLUETOOTH_A2DP_CONNECTED;
+ list = g_list_find_custom(p_connection_list,
+ &state, compare_state);
+ if (list == NULL) {
+ BT_INFO("Didn't found any device with A2DP State");
+ return;
+ }
+ a_conn = list->data;
+ p_connection_list = g_list_remove(p_connection_list, a_conn);
+ g_free(a_conn);
+ }
+}
+
#include "oal-hfp.h"
#include "oal-device-mgr.h"
-#include <bt-service-a2dp-src.h>
-#include <bt-service-hf.h>
-#include <bt-service-event.h>
+#include "bt-service-a2dp-src.h"
+#include "bt-service-core-device.h"
+#include "bt-service-event.h"
+#include "bt-service-headset-connection.h"
+#include "bt-service-hf.h"
static void __bt_hf_handle_audio_disconnection_state(bt_address_t *address)
{
void _bt_hf_event_handler(int oal_event, gpointer event_data)
{
bt_address_t * bt_addr = event_data;
+ char address[BT_ADDRESS_STRING_SIZE] = { 0 };
switch (oal_event) {
case OAL_EVENT_HFP_DISCONNECTED:
BT_INFO("HF Profile disconnected, reply pending DBUS request and check waiting device");
__bt_reply_hf_disconnection_pending_request(bt_addr);
BT_PERMANENT_LOG("Disconnected AG");
+
+ _bt_connection_manager_set_state(address, BLUETOOTH_EVENT_AG_DISCONNECTED);
break;
case OAL_EVENT_HFP_AUDIO_DISCONNECTED:
/* Reply to async request for HF connect or disconnect request, if any */
__bt_hf_handle_audio_disconnection_state(bt_addr);
BT_PERMANENT_LOG("Disconnected SCO");
break;
- case OAL_EVENT_HFP_CONNECTED:
+ case OAL_EVENT_HFP_CONNECTED: {
+ guint trusted = TRUSTED_PROFILE_ALLOWED;
+
BT_INFO("HFP Profile connected, Event & DBUS context will be handled at finalizing SCO connect..");
__bt_reply_hf_connection_pending_request(bt_addr);
BT_PERMANENT_LOG("Connected AG");
+
+ _bt_connection_manager_set_state(address, BLUETOOTH_EVENT_AG_CONNECTED);
+
+ _bt_get_trust_profile((bluetooth_device_address_t*)bt_addr,
+ TRUSTED_PROFILE_A2DP, &trusted);
+
+ if (_bt_headset_get_local_connection() == FALSE) {
+ _bt_convert_addr_type_to_string(address, bt_addr->addr);
+ if (trusted == TRUSTED_PROFILE_ALLOWED) /* Trusted */
+ _bt_start_timer_for_connection(address, BT_AUDIO_A2DP);
+ } else {
+ _bt_headset_set_local_connection(FALSE);
+ }
+
break;
+ }
case OAL_EVENT_HFP_AUDIO_CONNECTED:
BT_INFO("HFP SCO conencted, handle the event..");
__bt_hf_handle_audio_connection_state(bt_addr);
/*bt-service headers */
#include "bt-internal-types.h"
-#include "bt-service-common.h"
-#include "bt-service-util.h"
-#include "bt-service-main.h"
-#include "bt-service-core-device.h"
-#include "bt-service-core-adapter.h"
-#include "bt-service-event-receiver.h"
#include "bt-request-handler.h"
-#include "bt-service-event.h"
-#include "bt-service-agent-util.h"
#include "bt-service-a2dp-src.h"
#include "bt-service-a2dp-sink.h"
-#ifdef TIZEN_FEATURE_BT_OBEX
-#include "bt-service-obex-server.h"
-#endif
+#include "bt-service-agent-util.h"
+#include "bt-service-core-adapter.h"
+#include "bt-service-core-adapter-le.h"
+#include "bt-service-core-device.h"
+#include "bt-service-common.h"
#include "bt-service-device-internal.h"
-
+#include "bt-service-event.h"
+#include "bt-service-event-receiver.h"
#ifdef TIZEN_GATT_CLIENT
#include "bt-service-gatt.h"
#endif
+#include "bt-service-headset-connection.h"
+#include "bt-service-main.h"
+#ifdef TIZEN_MDM_ENABLE
+#include "bt-service-mdm.h"
+#endif
+#ifdef TIZEN_FEATURE_BT_OBEX
+#include "bt-service-obex-server.h"
+#endif
+#include "bt-service-util.h"
/* OAL headers */
#include <oal-event.h>
goto fail;
}
+ _bt_stop_timer_for_connection();
result = device_destroy_bond((bt_address_t *)device_address);
if (result != OAL_STATUS_SUCCESS)
goto fail;
#define BT_LE_ADV_NONCONN_IND 0x03
#define BT_LE_ADV_SCAN_RSP 0x04
+/* Trusted/Blocked Profile*/
+#define TRUSTED_PROFILE_BLOCKED 0x0
+#define TRUSTED_PROFILE_ALLOWED 0x1
+
/* Profile states matched to btd_service_state_t of bluez service.h */
typedef enum {
BT_PROFILE_STATE_UNAVAILABLE,
--- /dev/null
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __BT_SERVICE_HEADSET_CONNECTION__
+#define __BT_SERVICE_HEADSET_CONNECTION__
+
+#define CONNECT_TIMEOUT (3 * 1000)
+
+void _bt_headset_set_local_connection(gboolean value);
+gboolean _bt_headset_get_local_connection();
+void _bt_start_timer_for_connection(char *remote_address, int connection_type);
+void _bt_stop_timer_for_connection(void);
+void _bt_connection_manager_set_state(char *remote_address, int event);
+
+
+#endif