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-manager.h"
30 #include "oal-audio-src.h"
32 #include "oal-device-mgr.h"
34 #include <bt-service-a2dp-src.h>
35 #include <bt-service-hf.h>
36 #include <bt-service-event.h>
38 static void __bt_hf_handle_audio_disconnection_state(bt_address_t *address)
42 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
43 int result = BLUETOOTH_ERROR_NONE;
44 bt_headset_wait_t *wait_list;
45 bluetooth_device_address_t device_address;
46 ret_if(NULL == address);
48 _bt_convert_addr_type_to_string(addr, address->addr);
50 /* Send HF(AG Role) disconnected event to Application */
51 param = g_variant_new("(is)", result, addr);
52 _bt_send_event(BT_HEADSET_EVENT, BLUETOOTH_EVENT_AG_DISCONNECTED, param);
54 /*Handle Platform logics */
55 /* Remove data from the connected list */
56 _bt_remove_headset_from_list(BT_AUDIO_HSP, addr);
58 wait_list = _bt_get_audio_wait_data();
59 if (wait_list == NULL)
61 _bt_set_audio_wait_data_flag(TRUE);
62 _bt_convert_addr_string_to_type(device_address.addr,
64 BT_INFO("Trigger connect for the waiting device [%s], audio type [%d]",
65 wait_list->address, wait_list->type);
66 _bt_audio_connect(wait_list->type, &device_address);
69 /*Handle Product logics */
73 static void __bt_reply_hf_disconnection_pending_request(bt_address_t *address)
75 char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
76 bluetooth_device_address_t device_address;
78 invocation_info_t *req_info;
79 bt_headset_wait_t *wait_list = NULL;
80 bt_pending_audio_conn_t* data = NULL;
81 int result = BLUETOOTH_ERROR_NONE;
83 ret_if(NULL == address);
85 memcpy(device_address.addr, address->addr, BLUETOOTH_ADDRESS_LENGTH);
86 _bt_convert_addr_type_to_string(addr, address->addr);
88 /* Remove data from the connected list */
89 _bt_remove_headset_from_list(BT_AUDIO_HSP, addr);
91 /* Find Async request information*/
92 req_info = _bt_get_request_info_data(BT_AG_DISCONNECT, addr);
93 if (NULL == req_info) {
94 BT_DBG("AG DisConnect request not found or possibly already replied..");
96 req_info = _bt_get_request_info_data(BT_AG_CONNECT, addr);
97 if (req_info == NULL) {
98 BT_DBG("AG Connect request also not found..");
100 req_info = _bt_get_request_info_data(BT_AUDIO_DISCONNECT, addr);
101 if (req_info == NULL) {
102 BT_DBG("AUDIO Disconnect request also not found..");
104 req_info = _bt_get_request_info_data(BT_AUDIO_CONNECT, addr);
105 if (req_info == NULL) {
106 BT_DBG("AUDIO Connect request also not found..");
109 BT_DBG("AG Audio All Connect request found..");
110 result = BLUETOOTH_ERROR_INTERNAL;
113 BT_DBG("Audio All DisConnect request found..");
116 BT_DBG("AG Connect request found..");
117 result = BLUETOOTH_ERROR_INTERNAL;
120 BT_DBG("AG DisConnect request found..");
123 /* Cleanup device service search info if Aysnc request was Audio Connect All */
124 if (req_info->service_function == BT_AUDIO_CONNECT) {
125 /* Check if pending connect was present */
126 data = _bt_get_pending_audio_conn_info(addr);
128 BT_DBG("HF Connection failed during Audio All connect, & pending connect present");
129 _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, BLUETOOTH_ERROR_INTERNAL);
130 goto try_waiting_device;
132 BT_DBG("Abnormal:HF Connection failed during Audio All connect, but pending connect not present");
136 /* In any of the above cases, reply DBUS context */
137 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
138 g_array_append_vals(out_param, addr, BT_ADDRESS_STRING_SIZE);
139 _bt_service_method_return(req_info->context,
141 g_array_free(out_param, TRUE);
142 g_free(req_info->user_data);
143 _bt_free_info_from_invocation_list(req_info);
146 wait_list = _bt_get_audio_wait_data();
147 if (wait_list == NULL)
149 _bt_convert_addr_string_to_type(device_address.addr,
151 BT_INFO("Trigger connect for the waiting device [%s], audio type [%d]",
152 wait_list->address + 12, wait_list->type);
153 _bt_audio_connect(wait_list->type, &device_address);
157 static void __bt_hf_handle_audio_connection_state(bt_address_t *bd_addr)
159 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
160 bt_headset_wait_t *wait_list = NULL;
162 unsigned int result = BLUETOOTH_ERROR_NONE;
163 invocation_info_t *req_info;
166 _bt_convert_addr_type_to_string(address, bd_addr->addr);
167 BT_INFO("HF(AG Role) Connected for address [%s]", address);
169 /* Send HF(AG Role) connected event to Application. Even though it is AG Audio
170 Connected, still send AG Connected event as per logic implemented in Tizen */
171 param = g_variant_new("(is)", result, address);
172 _bt_send_event(BT_HEADSET_EVENT, BLUETOOTH_EVENT_AG_CONNECTED, param);
174 /* Add data to the connected list */
175 _bt_add_headset_to_list(BT_AUDIO_HSP,
176 BT_STATE_CONNECTED, address);
178 wait_list = _bt_get_audio_wait_data();
179 if (wait_list != NULL &&
180 (g_strcmp0(wait_list->address, address) == 0)) {
181 BT_DBG("Same Device [%s] is under wait, connection type [%d], going to delete it",
182 wait_list->address, wait_list->type);
185 if (wait_list != NULL)
186 BT_DBG("Some Device [%s] is under wait, connection type [%d], ", wait_list->address, wait_list->type);
189 /* DBUS Context return */
190 req_info = _bt_get_request_info_data(BT_AUDIO_CONNECT, address);
192 if (NULL != req_info) {
193 BT_DBG("Audio All Connect request found");
194 goto check_pending_a2dp_connect;
196 BT_DBG("Audio All Connect Request not found..");
197 req_info = _bt_get_request_info_data(BT_AG_CONNECT, address);
200 BT_DBG("AG Connect Request found..");
203 BT_ERR("AG Connect Request also not found..Abnormal Case!!!");
208 check_pending_a2dp_connect:
209 /* Check pending A2DP connection */
210 BT_DBG("Check A2DP pending connect");
211 if (_bt_audio_check_pending_connection(address) == TRUE) {
212 BT_DBG("Pending A2DP connect is present..dont return DBUS for AUDIO_CONNECT_ALL");
215 BT_DBG("Pending A2DP connect is Not present..return DBUS for AUDIO_CONNECT_ALL");
217 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
218 g_array_append_vals(out_param, address, BT_ADDRESS_STRING_SIZE);
219 _bt_service_method_return(req_info->context,
220 out_param, BLUETOOTH_ERROR_NONE);
221 g_array_free(out_param, TRUE);
222 g_free(req_info->user_data);
223 _bt_free_info_from_invocation_list(req_info);
226 static void __bt_reply_hf_connection_pending_request(bt_address_t *address)
231 /* This event handler process events for HF (AG role) */
232 void _bt_hf_event_handler(int oal_event, gpointer event_data)
234 bt_address_t * bt_addr = event_data;
237 case OAL_EVENT_HFP_DISCONNECTED:
238 /* Reply to async request for HF connect or disconnect request, if any */
239 BT_INFO("HF Profile disconnected, reply pending DBUS request and check waiting device");
240 __bt_reply_hf_disconnection_pending_request(bt_addr);
241 BT_PERMANENT_LOG("Disconnected AG");
243 case OAL_EVENT_HFP_AUDIO_DISCONNECTED:
244 /* Reply to async request for HF connect or disconnect request, if any */
245 BT_INFO("HF SCO disconnected, reply pending request if any and send event");
246 __bt_hf_handle_audio_disconnection_state(bt_addr);
247 BT_PERMANENT_LOG("Disconnected SCO");
249 case OAL_EVENT_HFP_CONNECTED:
250 BT_INFO("HFP Profile connected, Event & DBUS context will be handled at finalizing SCO connect..");
251 __bt_reply_hf_connection_pending_request(bt_addr);
252 BT_PERMANENT_LOG("Connected AG");
254 case OAL_EVENT_HFP_AUDIO_CONNECTED:
255 BT_INFO("HFP SCO conencted, handle the event..");
256 __bt_hf_handle_audio_connection_state(bt_addr);
257 BT_PERMANENT_LOG("Connected SCO");
259 case OAL_EVENT_HFP_CONNECTING:
260 BT_INFO("HFP Profile connection successful, wait for Audio connect..");
262 case OAL_EVENT_HFP_DISCONNECTING:
263 BT_INFO("HFP Connecting or Disconnecting..No need to send event to app");
265 case OAL_EVENT_HFP_AUDIO_CONNECTING:
266 case OAL_EVENT_HFP_AUDIO_DISCONNECTING:
267 BT_INFO("HFP SCO conencting or disconnecting, Not handled..");
274 int _bt_connect_remote_hfp(bluetooth_device_address_t *device_address)
276 oal_status_t status = OAL_STATUS_SUCCESS;
277 int result = BLUETOOTH_ERROR_NONE;
280 status = hfp_connect((bt_address_t *)device_address);
281 if (status != OAL_STATUS_SUCCESS) {
282 BT_ERR("Connection could not be established, err: [%d]", status);
283 result = _bt_convert_oal_status_to_bt_error(status);
288 int _bt_disconnect_remote_hfp(bluetooth_device_address_t *device_address)
290 oal_status_t status = OAL_STATUS_SUCCESS;
291 int result = BLUETOOTH_ERROR_NONE;
294 status = hfp_disconnect((bt_address_t *)device_address);
295 if (status != OAL_STATUS_SUCCESS) {
296 BT_ERR("DisConnection err: [%d]", status);
297 result = _bt_convert_oal_status_to_bt_error(status);