4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include <sys/socket.h>
23 #include <sys/errno.h>
28 #include "oal-hardware.h"
29 #include "oal-device-mgr.h"
30 #include "oal-manager.h"
31 #include "oal-audio-src.h"
33 #include "bt-service-a2dp-src.h"
34 #include "bt-service-core-device.h"
35 #include "bt-service-event.h"
36 #include "bt-service-headset-connection.h"
38 int _bt_a2dp_connect_remote_sink(bluetooth_device_address_t *device_address)
40 oal_status_t status = OAL_STATUS_SUCCESS;
41 int result = BLUETOOTH_ERROR_NONE;
44 status = audio_connect((bt_address_t*)device_address);
45 if (status != OAL_STATUS_SUCCESS) {
46 BT_ERR("Connection could not be established, err: [%d]", status);
47 result = _bt_convert_oal_status_to_bt_error(status);
52 int _bt_a2dp_disconnect_remote_sink(bluetooth_device_address_t *device_address)
54 oal_status_t status = OAL_STATUS_SUCCESS;
55 int result = BLUETOOTH_ERROR_NONE;
58 status = audio_disconnect((bt_address_t*)device_address);
59 if (status != OAL_STATUS_SUCCESS) {
60 BT_ERR("DisConnection err: [%d]", status);
61 result = _bt_convert_oal_status_to_bt_error(status);
66 static void __bt_handle_av_connected_state(bluetooth_device_address_t *address)
68 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
69 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
71 bt_headset_wait_t *wait_device = NULL;
72 bluetooth_device_address_t device_address;
73 bluetooth_device_address_t wait_device_address;
77 invocation_info_t *req_info;
78 bt_pending_audio_conn_t *data = NULL;
79 guint trusted = TRUSTED_PROFILE_ALLOWED;
81 int result = BLUETOOTH_ERROR_NONE;
82 ret_if(NULL == address);
84 _bt_convert_addr_type_to_string(addr, address->addr);
85 BT_INFO("Address of connected device [%s]", addr + 12);
87 /* Set VCONF Key for A2DP Connected status */
88 _bt_set_device_values(TRUE, VCONFKEY_BT_DEVICE_A2DP_HEADSET_CONNECTED);
90 /* Set readout notification of tts */
91 #ifdef TIZEN_FEATURE_READOUT_NOTIFICATION
92 _bt_set_readout_notification_of_tts();
95 /* Send A2DP(SRC Role) connected event to Application */
96 param = g_variant_new("(is)", result, addr);
97 _bt_send_event(BT_HEADSET_EVENT, BLUETOOTH_EVENT_AV_CONNECTED, param);
98 _bt_connection_manager_set_state(addr, BLUETOOTH_EVENT_AV_CONNECTED);
100 connected = _bt_is_headset_type_connected(BT_AUDIO_A2DP, connected_address);
102 BT_INFO("connected_address: %s", connected_address + 12);
103 if (g_strcmp0(connected_address, addr) != 0) {
104 _bt_convert_addr_string_to_type(
107 _bt_audio_disconnect(BT_AUDIO_A2DP, &device_address);
111 /* Add data from the connected list */
112 _bt_add_headset_to_list(BT_AUDIO_A2DP, BT_STATE_CONNECTED, addr);
114 #ifdef TIZEN_FEATURE_BT_AVC_TARGET
115 /* Send the information to Absolute Volume Controller */
116 _bt_audio_handle_a2dp_state_changed(addr, true);
119 /* Delete waiting device data if present */
120 wait_device = _bt_get_audio_wait_data();
121 if (wait_device != NULL &&
122 (g_strcmp0(wait_device->address, addr) == 0))
125 if (wait_device != NULL) {
126 BT_INFO("A2DP Profile connected for device [%s] but another device [%s]is waiting to be connnected type [%d]",
127 addr, wait_device->address + 12, wait_device->type);
128 BT_INFO("Trigger connect for the waiting device [%s], audio type [%d]",
129 wait_device->address + 12, wait_device->type);
130 _bt_convert_addr_string_to_type(wait_device_address.addr,
131 wait_device->address);
132 _bt_audio_connect(wait_device->type, &wait_device_address);
133 /* Now free the wait list */
134 //_bt_rel_wait_data();
138 /* DBUS Context return */
139 req_info = _bt_get_request_info_data(BT_AV_CONNECT, addr);
140 if (NULL == req_info) {
141 BT_INFO("AV Connect request not found or possibly already replied");
142 req_info = _bt_get_request_info_data(BT_AUDIO_CONNECT, addr);
144 if (req_info == NULL) {
145 BT_INFO("AV Connect request & Audio All connect not found or possibly already replied");
148 BT_INFO("Audio All connect request found for address [%s]", addr + 12);
149 /* TODO Delete the search info if present */
150 data = _bt_get_pending_audio_conn_info(addr);
152 BT_INFO("Audio Connect All request present and pending connect is also present, delete info");
153 _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, BLUETOOTH_ERROR_NONE);
156 BT_ERR("Abnormal: Audio Connect All request present but pending connect absent");
160 BT_INFO("AV Connect request found for [%s]", addr);
163 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
164 g_array_append_vals(out_param, addr, BT_ADDRESS_STRING_SIZE);
165 _bt_service_method_return(req_info->context,
167 g_array_free(out_param, TRUE);
168 _bt_free_info_from_invocation_list(req_info);
170 _bt_get_trust_profile(address, TRUSTED_PROFILE_HFP_HF, &trusted);
172 if (_bt_headset_get_local_connection() == FALSE) {
173 if (trusted == TRUSTED_PROFILE_ALLOWED) /* Trusted */
174 _bt_start_timer_for_connection(addr, BT_AUDIO_HSP);
176 /* Connection Started from local device therefore no need to
177 * intiate connection for pending profile */
178 _bt_headset_set_local_connection(FALSE);
182 static void __bt_handle_av_disconnected_state(bluetooth_device_address_t *address)
184 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
185 int result = BLUETOOTH_ERROR_NONE;
187 bt_headset_wait_t *wait_device;
188 bluetooth_device_address_t device_address;
189 bt_pending_audio_conn_t *data = NULL;
191 invocation_info_t *req_info = NULL;
192 ret_if(NULL == address);
194 _bt_convert_addr_type_to_string(addr, address->addr);
196 /* Set VCONF status for A2DP Disconnection */
197 _bt_set_device_values(FALSE, VCONFKEY_BT_DEVICE_A2DP_HEADSET_CONNECTED);
199 /* Remove data from the connected list */
200 _bt_remove_headset_from_list(BT_AUDIO_A2DP, addr);
202 #ifdef TIZEN_FEATURE_BT_AVC_TARGET
203 /* Send the information to Absolute Volume Controller */
204 _bt_audio_handle_a2dp_state_changed(addr, false);
207 _bt_connection_manager_set_state(addr, BLUETOOTH_EVENT_AV_DISCONNECTED);
209 req_info = _bt_get_request_info_data(BT_AV_DISCONNECT, addr);
210 BT_DBG("Address of disconnected device[%s]", addr);
212 if (NULL == req_info) {
213 BT_DBG("AV DisConnect request not found or possibly already replied");
214 req_info = _bt_get_request_info_data(BT_AV_CONNECT, addr);
215 if (NULL == req_info) {
216 /* This means, AV Disconnect request has successfully passed, and real disconnect is completed */
217 BT_DBG("Neither AV Connect or AV Disconnect request is found..means, AV Profile is disconnected");
219 req_info = _bt_get_request_info_data(BT_AUDIO_CONNECT, addr);
220 if (req_info == NULL) {
221 BT_DBG("Audio Connect All request is also Not found..");
223 /* Send A2DP(SRC Role) disconnected event to Application */
224 param = g_variant_new("(is)", result, addr);
225 _bt_send_event(BT_HEADSET_EVENT, BLUETOOTH_EVENT_AV_DISCONNECTED, param);
227 req_info = _bt_get_request_info_data(BT_AUDIO_DISCONNECT, addr);
228 if (req_info == NULL) {
229 BT_DBG("Audio DisConnect All request is also Not found..");
231 BT_DBG("Audio DisConnect All request is found..");
232 /* Check if HFP profile is also connected, if yes, disconnect it too */
233 _bt_audio_check_pending_disconnection(addr, BT_AUDIO_HSP);
236 BT_DBG("Audio Connect All request is found..");
237 result = BLUETOOTH_ERROR_INTERNAL;
238 data = _bt_get_pending_audio_conn_info(addr);
240 BT_DBG("Pending connect is found, delete it..");
241 _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, result);
244 BT_DBG("Pending connect is Not found..");
247 /* Delete waiting device data if present for this device */
248 wait_device = _bt_get_audio_wait_data();
249 if (wait_device && strncasecmp(wait_device->address, addr, BT_ADDRESS_STRING_SIZE) == 0) {
254 goto check_wait_device;
256 BT_ERR("AV Connect request has failed.."); /* DBUS return needed */
257 result = BLUETOOTH_ERROR_INTERNAL;
258 /* Delete waiting device data if present for this device */
259 wait_device = _bt_get_audio_wait_data();
260 if (wait_device && strncasecmp(wait_device->address, addr, BT_ADDRESS_STRING_SIZE) == 0) {
265 goto check_wait_device;
268 BT_ERR("AV Disconnect request found for [%s], means disconnect request is successful", addr); /* DBUS return needed */
269 /* Send A2DP(SRC Role) disconnected event to Application */
270 param = g_variant_new("(is)", result, addr);
271 _bt_send_event(BT_HEADSET_EVENT, BLUETOOTH_EVENT_AV_DISCONNECTED, param);
272 goto check_wait_device;
275 wait_device = _bt_get_audio_wait_data();
277 if (wait_device == NULL)
280 BT_INFO("type: %d, ag_flag: %d, disconnection_type: %d", wait_device->type,
281 wait_device->ag_flag, wait_device->disconnection_type);
282 if (((wait_device->type == BT_AUDIO_ALL) &&
283 (wait_device->ag_flag == TRUE)) ||
284 (wait_device->type == BT_AUDIO_A2DP) ||
285 (wait_device->disconnection_type & BT_AUDIO_A2DP)) {
286 if (g_strcmp0(wait_device->address, addr) != 0) {
287 BT_INFO("Trigger connect for the waiting device [%s], audio type [%d]",
288 wait_device->address, wait_device->type);
289 _bt_convert_addr_string_to_type(device_address.addr,
290 wait_device->address);
291 _bt_audio_connect(wait_device->type, &device_address);
292 /* Now free the wait list */
293 //_bt_rel_wait_data();
299 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
300 g_array_append_vals(out_param, addr, BT_ADDRESS_STRING_SIZE);
301 _bt_service_method_return(req_info->context,
303 g_array_free(out_param, TRUE);
304 _bt_free_info_from_invocation_list(req_info);
308 static void __bt_handle_av_audio_stopped(bluetooth_device_address_t *address)
310 BT_DBG("Currently not handled..");
313 static void __bt_handle_av_audio_started(bluetooth_device_address_t *address)
315 BT_DBG("Currently not handled..");
318 void _bt_a2dp_source_event_handler(int oal_event, gpointer event_data)
320 bluetooth_device_address_t * bd_addr = (bluetooth_device_address_t*)event_data;
323 case OAL_EVENT_AUDIO_CONNECTING:
324 BT_INFO("A2DP Profile connecting..Ignore this event, wait for connected event");
326 case OAL_EVENT_AUDIO_DISCONNECTING:
327 BT_INFO("A2DP Profile Disconnecting..Ignore this event, wait for Disconnected event");
329 case OAL_EVENT_AUDIO_CONNECTED:
330 BT_INFO("A2DP Audio Profile connected..");
331 __bt_handle_av_connected_state(bd_addr);
332 BT_PERMANENT_LOG("Connected A2DP src");
334 case OAL_EVENT_AUDIO_DISCONNECTED:
335 BT_INFO("A2DP Audio Profile dissconnected..");
336 __bt_handle_av_disconnected_state(bd_addr);
337 BT_PERMANENT_LOG("Disconnected A2DP src");
339 case OAL_EVENT_AUDIO_STOPPED:
340 BT_INFO("A2DP Audio Stream stopped..");
341 __bt_handle_av_audio_stopped(bd_addr);
343 case OAL_EVENT_AUDIO_STARTED:
344 BT_INFO("A2DP Audio Stream started..");
345 __bt_handle_av_audio_started(bd_addr);
348 BT_INFO("Invalid Event = %d", oal_event);
353 void _bt_a2dp_src_handle_incoming_authorization(char *address, int service_id)
355 char connected_address[BT_ADDRESS_STRING_SIZE + 1];
357 bluetooth_device_address_t device_address;
358 oal_status_t res = OAL_STATUS_SUCCESS;
360 _bt_convert_addr_string_to_type(device_address.addr, address);
362 switch (service_id) {
363 case A2DP_SERVICE_ID:
364 connected = _bt_is_headset_type_connected(BT_AUDIO_A2DP, connected_address);
366 BT_INFO("A2DP is already connected..check which device..");
367 if (g_strcmp0(connected_address, address) != 0) {
368 BT_INFO("Different device is connected[%s] reject current [%s] device authorization request",
369 connected_address, address);
370 res = device_reply_auth_request((bt_address_t*)&device_address, service_id, FALSE, FALSE);
371 if (res != OAL_STATUS_SUCCESS)
372 BT_ERR("authorize_response: %d", res);
376 res = device_reply_auth_request((bt_address_t*)&device_address, service_id, TRUE, FALSE);
377 if (res != OAL_STATUS_SUCCESS)
378 BT_ERR("authorize_response: %d", res);
382 BT_ERR("Invalid Audio Service ID..");