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 _bt_free_info_from_invocation_list(req_info);
145 wait_list = _bt_get_audio_wait_data();
146 if (wait_list == NULL)
148 _bt_convert_addr_string_to_type(device_address.addr,
150 BT_INFO("Trigger connect for the waiting device [%s], audio type [%d]",
151 wait_list->address + 12, wait_list->type);
152 _bt_audio_connect(wait_list->type, &device_address);
156 static void __bt_hf_handle_audio_connection_state(bt_address_t *bd_addr)
158 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
159 bt_headset_wait_t *wait_list = NULL;
161 unsigned int result = BLUETOOTH_ERROR_NONE;
162 invocation_info_t *req_info;
165 _bt_convert_addr_type_to_string(address, bd_addr->addr);
166 BT_INFO("HF(AG Role) Connected for address [%s]", address);
168 /* Send HF(AG Role) connected event to Application. Even though it is AG Audio
169 Connected, still send AG Connected event as per logic implemented in Tizen */
170 param = g_variant_new("(is)", result, address);
171 _bt_send_event(BT_HEADSET_EVENT, BLUETOOTH_EVENT_AG_CONNECTED, param);
173 /* Add data to the connected list */
174 _bt_add_headset_to_list(BT_AUDIO_HSP,
175 BT_STATE_CONNECTED, address);
177 wait_list = _bt_get_audio_wait_data();
178 if (wait_list != NULL &&
179 (g_strcmp0(wait_list->address, address) == 0)) {
180 BT_DBG("Same Device [%s] is under wait, connection type [%d], going to delete it",
181 wait_list->address, wait_list->type);
184 if (wait_list != NULL)
185 BT_DBG("Some Device [%s] is under wait, connection type [%d], ", wait_list->address, wait_list->type);
188 /* DBUS Context return */
189 req_info = _bt_get_request_info_data(BT_AUDIO_CONNECT, address);
191 if (NULL != req_info) {
192 BT_DBG("Audio All Connect request found");
193 goto check_pending_a2dp_connect;
195 BT_DBG("Audio All Connect Request not found..");
196 req_info = _bt_get_request_info_data(BT_AG_CONNECT, address);
199 BT_DBG("AG Connect Request found..");
202 BT_ERR("AG Connect Request also not found..Abnormal Case!!!");
207 check_pending_a2dp_connect:
208 /* Check pending A2DP connection */
209 BT_DBG("Check A2DP pending connect");
210 if (_bt_audio_check_pending_connection(address) == TRUE) {
211 BT_DBG("Pending A2DP connect is present..dont return DBUS for AUDIO_CONNECT_ALL");
214 BT_DBG("Pending A2DP connect is Not present..return DBUS for AUDIO_CONNECT_ALL");
216 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
217 g_array_append_vals(out_param, address, BT_ADDRESS_STRING_SIZE);
218 _bt_service_method_return(req_info->context,
219 out_param, BLUETOOTH_ERROR_NONE);
220 g_array_free(out_param, TRUE);
221 _bt_free_info_from_invocation_list(req_info);
224 static void __bt_reply_hf_connection_pending_request(bt_address_t *address)
229 /* This event handler process events for HF (AG role) */
230 void _bt_hf_event_handler(int oal_event, gpointer event_data)
232 bt_address_t * bt_addr = event_data;
235 case OAL_EVENT_HFP_DISCONNECTED:
236 /* Reply to async request for HF connect or disconnect request, if any */
237 BT_INFO("HF Profile disconnected, reply pending DBUS request and check waiting device");
238 __bt_reply_hf_disconnection_pending_request(bt_addr);
239 BT_PERMANENT_LOG("Disconnected AG");
241 case OAL_EVENT_HFP_AUDIO_DISCONNECTED:
242 /* Reply to async request for HF connect or disconnect request, if any */
243 BT_INFO("HF SCO disconnected, reply pending request if any and send event");
244 __bt_hf_handle_audio_disconnection_state(bt_addr);
245 BT_PERMANENT_LOG("Disconnected SCO");
247 case OAL_EVENT_HFP_CONNECTED:
248 BT_INFO("HFP Profile connected, Event & DBUS context will be handled at finalizing SCO connect..");
249 __bt_reply_hf_connection_pending_request(bt_addr);
250 BT_PERMANENT_LOG("Connected AG");
252 case OAL_EVENT_HFP_AUDIO_CONNECTED:
253 BT_INFO("HFP SCO conencted, handle the event..");
254 __bt_hf_handle_audio_connection_state(bt_addr);
255 BT_PERMANENT_LOG("Connected SCO");
257 case OAL_EVENT_HFP_CONNECTING:
258 BT_INFO("HFP Profile connection successful, wait for Audio connect..");
260 case OAL_EVENT_HFP_DISCONNECTING:
261 BT_INFO("HFP Connecting or Disconnecting..No need to send event to app");
263 case OAL_EVENT_HFP_AUDIO_CONNECTING:
264 case OAL_EVENT_HFP_AUDIO_DISCONNECTING:
265 BT_INFO("HFP SCO conencting or disconnecting, Not handled..");
272 int _bt_connect_remote_hfp(bluetooth_device_address_t *device_address)
274 oal_status_t status = OAL_STATUS_SUCCESS;
275 int result = BLUETOOTH_ERROR_NONE;
278 status = hfp_connect((bt_address_t *)device_address);
279 if (status != OAL_STATUS_SUCCESS) {
280 BT_ERR("Connection could not be established, err: [%d]", status);
281 result = _bt_convert_oal_status_to_bt_error(status);
286 int _bt_disconnect_remote_hfp(bluetooth_device_address_t *device_address)
288 oal_status_t status = OAL_STATUS_SUCCESS;
289 int result = BLUETOOTH_ERROR_NONE;
292 status = hfp_disconnect((bt_address_t *)device_address);
293 if (status != OAL_STATUS_SUCCESS) {
294 BT_ERR("DisConnection err: [%d]", status);
295 result = _bt_convert_oal_status_to_bt_error(status);