blob: 62831960c164d570ecaf4d09bf97ba0ee5a09189 [file] [log] [blame]
Ian McKellare93ac122013-11-07 16:30:05 -08001/******************************************************************************
2 *
Jakub Pawlowski5b790fe2017-09-18 09:00:20 -07003 * Copyright 2014 Google, Inc.
Ian McKellare93ac122013-11-07 16:30:05 -08004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
Marie Janssen49120dc2015-07-07 16:47:20 -070019#define LOG_TAG "bt_btif_sock_sco"
20
Jack Hef2af1c42016-12-13 01:59:12 -080021#include <base/logging.h>
Etan Cohen3e59b5b2015-03-31 17:15:53 -070022#include <errno.h>
Arman Ugurayd30195c2015-05-29 15:27:58 -070023#include <pthread.h>
Etan Cohen3e59b5b2015-03-31 17:15:53 -070024#include <string.h>
Ian McKellare93ac122013-11-07 16:30:05 -080025#include <sys/socket.h>
June R. Tate-Gansf8662042015-02-19 14:29:35 -080026#include <sys/types.h>
Arman Ugurayd30195c2015-05-29 15:27:58 -070027#include <unistd.h>
Ian McKellare93ac122013-11-07 16:30:05 -080028
Marie Janssena5764682016-10-10 13:38:30 -070029#include <mutex>
30
Marie Janssendb554582015-06-26 14:53:46 -070031#include <hardware/bluetooth.h>
32#include <hardware/bt_sock.h>
33
Ian McKellare93ac122013-11-07 16:30:05 -080034#include "btif_common.h"
Mudumba Ananth57f65082017-02-09 09:05:48 -080035#include "device/include/esco_parameters.h"
Arman Uguray625ec342015-06-10 16:21:12 -070036#include "osi/include/allocator.h"
Sharvil Nanavati0f9b91e2015-03-12 15:42:50 -070037#include "osi/include/list.h"
Sharvil Nanavati44802762014-12-23 23:08:58 -080038#include "osi/include/log.h"
Arman Uguray625ec342015-06-10 16:21:12 -070039#include "osi/include/osi.h"
Sharvil Nanavati0f9b91e2015-03-12 15:42:50 -070040#include "osi/include/socket.h"
41#include "osi/include/thread.h"
Ian McKellare93ac122013-11-07 16:30:05 -080042
June R. Tate-Gansf8662042015-02-19 14:29:35 -080043// This module provides a socket abstraction for SCO connections to a higher
44// layer. It returns file descriptors representing two types of sockets:
45// listening (server) and connected (client) sockets. No SCO data is
46// transferred across these sockets; instead, they are used to manage SCO
47// connection lifecycles while the data routing takes place over the I2S bus.
48//
49// This code bridges the gap between the BTM layer, which implements SCO
50// connections, and the Android HAL. It adapts the BTM representation of SCO
51// connections (integer handles) to a file descriptor representation usable by
52// Android's LocalSocket implementation.
53//
54// Sample flow for an incoming connection:
55// btsock_sco_listen() - listen for incoming connections
56// connection_request_cb() - incoming connection request from remote host
57// connect_completed_cb() - connection successfully established
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -070058// socket_read_ready_cb() - local host closed SCO socket
June R. Tate-Gansf8662042015-02-19 14:29:35 -080059// disconnect_completed_cb() - connection terminated
Ian McKellare93ac122013-11-07 16:30:05 -080060
June R. Tate-Gansf8662042015-02-19 14:29:35 -080061typedef struct {
62 uint16_t sco_handle;
Myles Watson6bd442f2016-10-19 09:50:22 -070063 socket_t* socket;
June R. Tate-Gansf8662042015-02-19 14:29:35 -080064 bool connect_completed;
65} sco_socket_t;
66
Myles Watson6bd442f2016-10-19 09:50:22 -070067static sco_socket_t* sco_socket_establish_locked(bool is_listening,
Jakub Pawlowskia484a882017-06-24 17:30:18 -070068 const RawAddress* bd_addr,
Myles Watson6bd442f2016-10-19 09:50:22 -070069 int* sock_fd);
70static sco_socket_t* sco_socket_new(void);
71static void sco_socket_free_locked(sco_socket_t* socket);
72static sco_socket_t* sco_socket_find_locked(uint16_t sco_handle);
73static void connection_request_cb(tBTM_ESCO_EVT event,
74 tBTM_ESCO_EVT_DATA* data);
June R. Tate-Gansf8662042015-02-19 14:29:35 -080075static void connect_completed_cb(uint16_t sco_handle);
76static void disconnect_completed_cb(uint16_t sco_handle);
Myles Watson6bd442f2016-10-19 09:50:22 -070077static void socket_read_ready_cb(socket_t* socket, void* context);
Ian McKellare93ac122013-11-07 16:30:05 -080078
Marie Janssena5764682016-10-10 13:38:30 -070079// |sco_lock| protects all of the static variables below and
June R. Tate-Gansf8662042015-02-19 14:29:35 -080080// calls into the BTM layer.
Marie Janssena5764682016-10-10 13:38:30 -070081static std::mutex sco_lock;
Myles Watson6bd442f2016-10-19 09:50:22 -070082static list_t* sco_sockets; // Owns a collection of sco_socket_t objects.
83static sco_socket_t* listen_sco_socket; // Not owned, do not free.
84static thread_t* thread; // Not owned, do not free.
Ian McKellara1d7cf22013-12-16 12:26:19 -080085
Myles Watson6bd442f2016-10-19 09:50:22 -070086bt_status_t btsock_sco_init(thread_t* thread_) {
Jack Hef2af1c42016-12-13 01:59:12 -080087 CHECK(thread_ != NULL);
Ian McKellara1d7cf22013-12-16 12:26:19 -080088
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -070089 sco_sockets = list_new((list_free_cb)sco_socket_free_locked);
Myles Watson6bd442f2016-10-19 09:50:22 -070090 if (!sco_sockets) return BT_STATUS_FAIL;
Ian McKellara1d7cf22013-12-16 12:26:19 -080091
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -070092 thread = thread_;
Mudumba Ananth57f65082017-02-09 09:05:48 -080093 enh_esco_params_t params = esco_parameters_for_codec(ESCO_CODEC_CVSD);
94 BTM_SetEScoMode(&params);
Ian McKellara1d7cf22013-12-16 12:26:19 -080095
June R. Tate-Gansf8662042015-02-19 14:29:35 -080096 return BT_STATUS_SUCCESS;
Ian McKellara1d7cf22013-12-16 12:26:19 -080097}
98
June R. Tate-Gansf8662042015-02-19 14:29:35 -080099bt_status_t btsock_sco_cleanup(void) {
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700100 list_free(sco_sockets);
101 sco_sockets = NULL;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800102 return BT_STATUS_SUCCESS;
Ian McKellara1d7cf22013-12-16 12:26:19 -0800103}
104
Myles Watson6bd442f2016-10-19 09:50:22 -0700105bt_status_t btsock_sco_listen(int* sock_fd, UNUSED_ATTR int flags) {
Jack Hef2af1c42016-12-13 01:59:12 -0800106 CHECK(sock_fd != NULL);
Ian McKellare93ac122013-11-07 16:30:05 -0800107
Marie Janssena5764682016-10-10 13:38:30 -0700108 std::unique_lock<std::mutex> lock(sco_lock);
Ian McKellare93ac122013-11-07 16:30:05 -0800109
Myles Watson6bd442f2016-10-19 09:50:22 -0700110 sco_socket_t* sco_socket = sco_socket_establish_locked(true, NULL, sock_fd);
111 if (!sco_socket) return BT_STATUS_FAIL;
Ian McKellare93ac122013-11-07 16:30:05 -0800112
Marie Janssena5764682016-10-10 13:38:30 -0700113 BTM_RegForEScoEvts(sco_socket->sco_handle, connection_request_cb);
114 listen_sco_socket = sco_socket;
Ian McKellare93ac122013-11-07 16:30:05 -0800115
Marie Janssena5764682016-10-10 13:38:30 -0700116 return BT_STATUS_SUCCESS;
Ian McKellare93ac122013-11-07 16:30:05 -0800117}
118
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700119bt_status_t btsock_sco_connect(const RawAddress* bd_addr, int* sock_fd,
Myles Watson6bd442f2016-10-19 09:50:22 -0700120 UNUSED_ATTR int flags) {
Jack Hef2af1c42016-12-13 01:59:12 -0800121 CHECK(bd_addr != NULL);
122 CHECK(sock_fd != NULL);
Ian McKellare93ac122013-11-07 16:30:05 -0800123
Marie Janssena5764682016-10-10 13:38:30 -0700124 std::unique_lock<std::mutex> lock(sco_lock);
Myles Watson6bd442f2016-10-19 09:50:22 -0700125 sco_socket_t* sco_socket =
126 sco_socket_establish_locked(false, bd_addr, sock_fd);
Ian McKellare93ac122013-11-07 16:30:05 -0800127
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700128 return (sco_socket != NULL) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
Ian McKellare93ac122013-11-07 16:30:05 -0800129}
130
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800131// Must be called with |lock| held.
Myles Watson6bd442f2016-10-19 09:50:22 -0700132static sco_socket_t* sco_socket_establish_locked(bool is_listening,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700133 const RawAddress* bd_addr,
Myles Watson6bd442f2016-10-19 09:50:22 -0700134 int* sock_fd) {
135 int pair[2] = {INVALID_FD, INVALID_FD};
136 sco_socket_t* sco_socket = NULL;
137 socket_t* socket = NULL;
Jakub Pawlowski713993d2016-04-21 13:16:45 -0700138 tBTM_STATUS status;
Mudumba Ananth57f65082017-02-09 09:05:48 -0800139 enh_esco_params_t params;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800140 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, pair) == -1) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700141 LOG_ERROR(LOG_TAG, "%s unable to allocate socket pair: %s", __func__,
142 strerror(errno));
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800143 goto error;
144 }
Ian McKellare93ac122013-11-07 16:30:05 -0800145
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700146 sco_socket = sco_socket_new();
147 if (!sco_socket) {
Marie Janssendb554582015-06-26 14:53:46 -0700148 LOG_ERROR(LOG_TAG, "%s unable to allocate new SCO socket.", __func__);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800149 goto error;
150 }
Ian McKellare93ac122013-11-07 16:30:05 -0800151
Mudumba Ananth57f65082017-02-09 09:05:48 -0800152 params = esco_parameters_for_codec(ESCO_CODEC_CVSD);
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700153 status = BTM_CreateSco(bd_addr, !is_listening, params.packet_types,
Mudumba Ananth57f65082017-02-09 09:05:48 -0800154 &sco_socket->sco_handle, connect_completed_cb,
155 disconnect_completed_cb);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800156 if (status != BTM_CMD_STARTED) {
Marie Janssendb554582015-06-26 14:53:46 -0700157 LOG_ERROR(LOG_TAG, "%s unable to create SCO socket: %d", __func__, status);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800158 goto error;
159 }
Ian McKellare93ac122013-11-07 16:30:05 -0800160
Jakub Pawlowski713993d2016-04-21 13:16:45 -0700161 socket = socket_new_from_fd(pair[1]);
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700162 if (!socket) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700163 LOG_ERROR(LOG_TAG, "%s unable to allocate socket from file descriptor %d.",
164 __func__, pair[1]);
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700165 goto error;
166 }
Ian McKellare93ac122013-11-07 16:30:05 -0800167
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700168 *sock_fd = pair[0]; // Transfer ownership of one end to caller.
169 sco_socket->socket = socket; // Hang on to the other end.
170 list_append(sco_sockets, sco_socket);
171
Myles Watson6bd442f2016-10-19 09:50:22 -0700172 socket_register(socket, thread_get_reactor(thread), sco_socket,
173 socket_read_ready_cb, NULL);
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700174 return sco_socket;
Ian McKellare93ac122013-11-07 16:30:05 -0800175
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800176error:;
Myles Watson6bd442f2016-10-19 09:50:22 -0700177 if (pair[0] != INVALID_FD) close(pair[0]);
178 if (pair[1] != INVALID_FD) close(pair[1]);
Ian McKellare93ac122013-11-07 16:30:05 -0800179
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700180 sco_socket_free_locked(sco_socket);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800181 return NULL;
Ian McKellare93ac122013-11-07 16:30:05 -0800182}
183
Myles Watson6bd442f2016-10-19 09:50:22 -0700184static sco_socket_t* sco_socket_new(void) {
185 sco_socket_t* sco_socket = (sco_socket_t*)osi_calloc(sizeof(sco_socket_t));
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800186 sco_socket->sco_handle = BTM_INVALID_SCO_INDEX;
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700187 return sco_socket;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800188}
Ian McKellara1d7cf22013-12-16 12:26:19 -0800189
Myles Watson6bd442f2016-10-19 09:50:22 -0700190// Must be called with |lock| held except during teardown when we know the
191// socket thread
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700192// is no longer alive.
Myles Watson6bd442f2016-10-19 09:50:22 -0700193static void sco_socket_free_locked(sco_socket_t* sco_socket) {
194 if (!sco_socket) return;
Ian McKellara1d7cf22013-12-16 12:26:19 -0800195
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700196 if (sco_socket->sco_handle != BTM_INVALID_SCO_INDEX)
197 BTM_RemoveSco(sco_socket->sco_handle);
198 socket_free(sco_socket->socket);
Pavlin Radoslavoveae61662015-06-02 13:54:58 -0700199 osi_free(sco_socket);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800200}
Ian McKellare93ac122013-11-07 16:30:05 -0800201
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800202// Must be called with |lock| held.
Myles Watson6bd442f2016-10-19 09:50:22 -0700203static sco_socket_t* sco_socket_find_locked(uint16_t sco_handle) {
204 for (const list_node_t* node = list_begin(sco_sockets);
205 node != list_end(sco_sockets); node = list_next(node)) {
206 sco_socket_t* sco_socket = (sco_socket_t*)list_node(node);
207 if (sco_socket->sco_handle == sco_handle) return sco_socket;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800208 }
209 return NULL;
210}
Ian McKellare93ac122013-11-07 16:30:05 -0800211
Myles Watson6bd442f2016-10-19 09:50:22 -0700212static void connection_request_cb(tBTM_ESCO_EVT event,
213 tBTM_ESCO_EVT_DATA* data) {
Jack Hef2af1c42016-12-13 01:59:12 -0800214 CHECK(data != NULL);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800215
216 // Don't care about change of link parameters, only connection requests.
Myles Watson6bd442f2016-10-19 09:50:22 -0700217 if (event != BTM_ESCO_CONN_REQ_EVT) return;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800218
Marie Janssena5764682016-10-10 13:38:30 -0700219 std::unique_lock<std::mutex> lock(sco_lock);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800220
Myles Watson6bd442f2016-10-19 09:50:22 -0700221 const tBTM_ESCO_CONN_REQ_EVT_DATA* conn_data = &data->conn_evt;
222 sco_socket_t* sco_socket = sco_socket_find_locked(conn_data->sco_inx);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800223 int client_fd = INVALID_FD;
224
Jakub Pawlowski713993d2016-04-21 13:16:45 -0700225 uint16_t temp;
Myles Watson6bd442f2016-10-19 09:50:22 -0700226 sco_socket_t* new_sco_socket;
Jakub Pawlowski713993d2016-04-21 13:16:45 -0700227
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700228 if (!sco_socket) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700229 LOG_ERROR(LOG_TAG, "%s unable to find sco_socket for handle: %hu", __func__,
230 conn_data->sco_inx);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800231 goto error;
232 }
233
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700234 if (sco_socket != listen_sco_socket) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700235 LOG_ERROR(
236 LOG_TAG,
237 "%s received connection request on non-listening socket handle: %hu",
238 __func__, conn_data->sco_inx);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800239 goto error;
240 }
241
Jakub Pawlowski713993d2016-04-21 13:16:45 -0700242 new_sco_socket = sco_socket_establish_locked(true, NULL, &client_fd);
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700243 if (!new_sco_socket) {
Marie Janssendb554582015-06-26 14:53:46 -0700244 LOG_ERROR(LOG_TAG, "%s unable to allocate new sco_socket.", __func__);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800245 goto error;
246 }
247
248 // Swap socket->sco_handle and new_socket->sco_handle
Jakub Pawlowski713993d2016-04-21 13:16:45 -0700249 temp = sco_socket->sco_handle;
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700250 sco_socket->sco_handle = new_sco_socket->sco_handle;
251 new_sco_socket->sco_handle = temp;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800252
253 sock_connect_signal_t connect_signal;
254 connect_signal.size = sizeof(connect_signal);
Jakub Pawlowskic2276b02017-06-09 16:00:25 -0700255 connect_signal.bd_addr = conn_data->bd_addr;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800256 connect_signal.channel = 0;
257 connect_signal.status = 0;
258
Myles Watson6bd442f2016-10-19 09:50:22 -0700259 if (socket_write_and_transfer_fd(sco_socket->socket, &connect_signal,
260 sizeof(connect_signal),
261 client_fd) != sizeof(connect_signal)) {
262 LOG_ERROR(LOG_TAG,
263 "%s unable to send new file descriptor to listening socket.",
264 __func__);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800265 goto error;
266 }
267
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700268 BTM_RegForEScoEvts(listen_sco_socket->sco_handle, connection_request_cb);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800269 BTM_EScoConnRsp(conn_data->sco_inx, HCI_SUCCESS, NULL);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800270
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800271 return;
272
273error:;
Myles Watson6bd442f2016-10-19 09:50:22 -0700274 if (client_fd != INVALID_FD) close(client_fd);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800275 BTM_EScoConnRsp(conn_data->sco_inx, HCI_ERR_HOST_REJECT_RESOURCES, NULL);
276}
277
278static void connect_completed_cb(uint16_t sco_handle) {
Marie Janssena5764682016-10-10 13:38:30 -0700279 std::unique_lock<std::mutex> lock(sco_lock);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800280
Myles Watson6bd442f2016-10-19 09:50:22 -0700281 sco_socket_t* sco_socket = sco_socket_find_locked(sco_handle);
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700282 if (!sco_socket) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700283 LOG_ERROR(LOG_TAG, "%s SCO socket not found on connect for handle: %hu",
284 __func__, sco_handle);
Marie Janssena5764682016-10-10 13:38:30 -0700285 return;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800286 }
287
Myles Watson6bd442f2016-10-19 09:50:22 -0700288 // If sco_socket->socket was closed, we should tear down because there is no
289 // app-level
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800290 // interest in the SCO socket.
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700291 if (!sco_socket->socket) {
292 BTM_RemoveSco(sco_socket->sco_handle);
293 list_remove(sco_sockets, sco_socket);
Marie Janssena5764682016-10-10 13:38:30 -0700294 return;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800295 }
296
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700297 sco_socket->connect_completed = true;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800298}
299
300static void disconnect_completed_cb(uint16_t sco_handle) {
Marie Janssena5764682016-10-10 13:38:30 -0700301 std::unique_lock<std::mutex> lock(sco_lock);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800302
Myles Watson6bd442f2016-10-19 09:50:22 -0700303 sco_socket_t* sco_socket = sco_socket_find_locked(sco_handle);
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700304 if (!sco_socket) {
Myles Watson6bd442f2016-10-19 09:50:22 -0700305 LOG_ERROR(LOG_TAG, "%s SCO socket not found on disconnect for handle: %hu",
306 __func__, sco_handle);
Marie Janssena5764682016-10-10 13:38:30 -0700307 return;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800308 }
309
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700310 list_remove(sco_sockets, sco_socket);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800311}
312
Myles Watson6bd442f2016-10-19 09:50:22 -0700313static void socket_read_ready_cb(UNUSED_ATTR socket_t* socket, void* context) {
Marie Janssena5764682016-10-10 13:38:30 -0700314 std::unique_lock<std::mutex> lock(sco_lock);
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800315
Myles Watson6bd442f2016-10-19 09:50:22 -0700316 sco_socket_t* sco_socket = (sco_socket_t*)context;
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700317 socket_free(sco_socket->socket);
318 sco_socket->socket = NULL;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800319
320 // Defer the underlying disconnect until the connection completes
321 // since the BTM code doesn't behave correctly when a disconnect
322 // request is issued while a connect is in progress. The fact that
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700323 // sco_socket->socket == NULL indicates to the connect callback
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800324 // routine that the socket is no longer desired and should be torn
325 // down.
Sharvil Nanavatic8aaee22014-08-21 18:17:19 -0700326 if (sco_socket->connect_completed || sco_socket == listen_sco_socket) {
327 if (BTM_RemoveSco(sco_socket->sco_handle) == BTM_SUCCESS)
328 list_remove(sco_sockets, sco_socket);
Myles Watson6bd442f2016-10-19 09:50:22 -0700329 if (sco_socket == listen_sco_socket) listen_sco_socket = NULL;
June R. Tate-Gansf8662042015-02-19 14:29:35 -0800330 }
Ian McKellare93ac122013-11-07 16:30:05 -0800331}