1 /****************************************************************************** 2 * 3 * Copyright (C) 2014 Google, Inc. 4 * 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 19 #define LOG_TAG "bt_btif_sock_sco" 20 21 #include <base/logging.h> 22 #include <errno.h> 23 #include <pthread.h> 24 #include <string.h> 25 #include <sys/socket.h> 26 #include <sys/types.h> 27 #include <unistd.h> 28 29 #include <mutex> 30 31 #include <hardware/bluetooth.h> 32 #include <hardware/bt_sock.h> 33 34 #include "btif_common.h" 35 #include "device/include/esco_parameters.h" 36 #include "osi/include/allocator.h" 37 #include "osi/include/list.h" 38 #include "osi/include/log.h" 39 #include "osi/include/osi.h" 40 #include "osi/include/socket.h" 41 #include "osi/include/thread.h" 42 43 // 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 58 // socket_read_ready_cb() - local host closed SCO socket 59 // disconnect_completed_cb() - connection terminated 60 61 typedef struct { 62 uint16_t sco_handle; 63 socket_t* socket; 64 bool connect_completed; 65 } sco_socket_t; 66 67 static sco_socket_t* sco_socket_establish_locked(bool is_listening, 68 const bt_bdaddr_t* bd_addr, 69 int* sock_fd); 70 static sco_socket_t* sco_socket_new(void); 71 static void sco_socket_free_locked(sco_socket_t* socket); 72 static sco_socket_t* sco_socket_find_locked(uint16_t sco_handle); 73 static void connection_request_cb(tBTM_ESCO_EVT event, 74 tBTM_ESCO_EVT_DATA* data); 75 static void connect_completed_cb(uint16_t sco_handle); 76 static void disconnect_completed_cb(uint16_t sco_handle); 77 static void socket_read_ready_cb(socket_t* socket, void* context); 78 79 // |sco_lock| protects all of the static variables below and 80 // calls into the BTM layer. 81 static std::mutex sco_lock; 82 static list_t* sco_sockets; // Owns a collection of sco_socket_t objects. 83 static sco_socket_t* listen_sco_socket; // Not owned, do not free. 84 static thread_t* thread; // Not owned, do not free. 85 86 bt_status_t btsock_sco_init(thread_t* thread_) { 87 CHECK(thread_ != NULL); 88 89 sco_sockets = list_new((list_free_cb)sco_socket_free_locked); 90 if (!sco_sockets) return BT_STATUS_FAIL; 91 92 thread = thread_; 93 enh_esco_params_t params = esco_parameters_for_codec(ESCO_CODEC_CVSD); 94 BTM_SetEScoMode(¶ms); 95 96 return BT_STATUS_SUCCESS; 97 } 98 99 bt_status_t btsock_sco_cleanup(void) { 100 list_free(sco_sockets); 101 sco_sockets = NULL; 102 return BT_STATUS_SUCCESS; 103 } 104 105 bt_status_t btsock_sco_listen(int* sock_fd, UNUSED_ATTR int flags) { 106 CHECK(sock_fd != NULL); 107 108 std::unique_lock<std::mutex> lock(sco_lock); 109 110 sco_socket_t* sco_socket = sco_socket_establish_locked(true, NULL, sock_fd); 111 if (!sco_socket) return BT_STATUS_FAIL; 112 113 BTM_RegForEScoEvts(sco_socket->sco_handle, connection_request_cb); 114 listen_sco_socket = sco_socket; 115 116 return BT_STATUS_SUCCESS; 117 } 118 119 bt_status_t btsock_sco_connect(const bt_bdaddr_t* bd_addr, int* sock_fd, 120 UNUSED_ATTR int flags) { 121 CHECK(bd_addr != NULL); 122 CHECK(sock_fd != NULL); 123 124 std::unique_lock<std::mutex> lock(sco_lock); 125 sco_socket_t* sco_socket = 126 sco_socket_establish_locked(false, bd_addr, sock_fd); 127 128 return (sco_socket != NULL) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; 129 } 130 131 // Must be called with |lock| held. 132 static sco_socket_t* sco_socket_establish_locked(bool is_listening, 133 const bt_bdaddr_t* bd_addr, 134 int* sock_fd) { 135 int pair[2] = {INVALID_FD, INVALID_FD}; 136 sco_socket_t* sco_socket = NULL; 137 socket_t* socket = NULL; 138 tBTM_STATUS status; 139 enh_esco_params_t params; 140 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, pair) == -1) { 141 LOG_ERROR(LOG_TAG, "%s unable to allocate socket pair: %s", __func__, 142 strerror(errno)); 143 goto error; 144 } 145 146 sco_socket = sco_socket_new(); 147 if (!sco_socket) { 148 LOG_ERROR(LOG_TAG, "%s unable to allocate new SCO socket.", __func__); 149 goto error; 150 } 151 152 params = esco_parameters_for_codec(ESCO_CODEC_CVSD); 153 status = BTM_CreateSco((uint8_t*)bd_addr, !is_listening, params.packet_types, 154 &sco_socket->sco_handle, connect_completed_cb, 155 disconnect_completed_cb); 156 if (status != BTM_CMD_STARTED) { 157 LOG_ERROR(LOG_TAG, "%s unable to create SCO socket: %d", __func__, status); 158 goto error; 159 } 160 161 socket = socket_new_from_fd(pair[1]); 162 if (!socket) { 163 LOG_ERROR(LOG_TAG, "%s unable to allocate socket from file descriptor %d.", 164 __func__, pair[1]); 165 goto error; 166 } 167 168 *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 172 socket_register(socket, thread_get_reactor(thread), sco_socket, 173 socket_read_ready_cb, NULL); 174 return sco_socket; 175 176 error:; 177 if (pair[0] != INVALID_FD) close(pair[0]); 178 if (pair[1] != INVALID_FD) close(pair[1]); 179 180 sco_socket_free_locked(sco_socket); 181 return NULL; 182 } 183 184 static sco_socket_t* sco_socket_new(void) { 185 sco_socket_t* sco_socket = (sco_socket_t*)osi_calloc(sizeof(sco_socket_t)); 186 sco_socket->sco_handle = BTM_INVALID_SCO_INDEX; 187 return sco_socket; 188 } 189 190 // Must be called with |lock| held except during teardown when we know the 191 // socket thread 192 // is no longer alive. 193 static void sco_socket_free_locked(sco_socket_t* sco_socket) { 194 if (!sco_socket) return; 195 196 if (sco_socket->sco_handle != BTM_INVALID_SCO_INDEX) 197 BTM_RemoveSco(sco_socket->sco_handle); 198 socket_free(sco_socket->socket); 199 osi_free(sco_socket); 200 } 201 202 // Must be called with |lock| held. 203 static 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; 208 } 209 return NULL; 210 } 211 212 static void connection_request_cb(tBTM_ESCO_EVT event, 213 tBTM_ESCO_EVT_DATA* data) { 214 CHECK(data != NULL); 215 216 // Don't care about change of link parameters, only connection requests. 217 if (event != BTM_ESCO_CONN_REQ_EVT) return; 218 219 std::unique_lock<std::mutex> lock(sco_lock); 220 221 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); 223 int client_fd = INVALID_FD; 224 225 uint16_t temp; 226 sco_socket_t* new_sco_socket; 227 228 if (!sco_socket) { 229 LOG_ERROR(LOG_TAG, "%s unable to find sco_socket for handle: %hu", __func__, 230 conn_data->sco_inx); 231 goto error; 232 } 233 234 if (sco_socket != listen_sco_socket) { 235 LOG_ERROR( 236 LOG_TAG, 237 "%s received connection request on non-listening socket handle: %hu", 238 __func__, conn_data->sco_inx); 239 goto error; 240 } 241 242 new_sco_socket = sco_socket_establish_locked(true, NULL, &client_fd); 243 if (!new_sco_socket) { 244 LOG_ERROR(LOG_TAG, "%s unable to allocate new sco_socket.", __func__); 245 goto error; 246 } 247 248 // Swap socket->sco_handle and new_socket->sco_handle 249 temp = sco_socket->sco_handle; 250 sco_socket->sco_handle = new_sco_socket->sco_handle; 251 new_sco_socket->sco_handle = temp; 252 253 sock_connect_signal_t connect_signal; 254 connect_signal.size = sizeof(connect_signal); 255 memcpy(&connect_signal.bd_addr, conn_data->bd_addr, sizeof(bt_bdaddr_t)); 256 connect_signal.channel = 0; 257 connect_signal.status = 0; 258 259 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__); 265 goto error; 266 } 267 268 BTM_RegForEScoEvts(listen_sco_socket->sco_handle, connection_request_cb); 269 BTM_EScoConnRsp(conn_data->sco_inx, HCI_SUCCESS, NULL); 270 271 return; 272 273 error:; 274 if (client_fd != INVALID_FD) close(client_fd); 275 BTM_EScoConnRsp(conn_data->sco_inx, HCI_ERR_HOST_REJECT_RESOURCES, NULL); 276 } 277 278 static void connect_completed_cb(uint16_t sco_handle) { 279 std::unique_lock<std::mutex> lock(sco_lock); 280 281 sco_socket_t* sco_socket = sco_socket_find_locked(sco_handle); 282 if (!sco_socket) { 283 LOG_ERROR(LOG_TAG, "%s SCO socket not found on connect for handle: %hu", 284 __func__, sco_handle); 285 return; 286 } 287 288 // If sco_socket->socket was closed, we should tear down because there is no 289 // app-level 290 // interest in the SCO socket. 291 if (!sco_socket->socket) { 292 BTM_RemoveSco(sco_socket->sco_handle); 293 list_remove(sco_sockets, sco_socket); 294 return; 295 } 296 297 sco_socket->connect_completed = true; 298 } 299 300 static void disconnect_completed_cb(uint16_t sco_handle) { 301 std::unique_lock<std::mutex> lock(sco_lock); 302 303 sco_socket_t* sco_socket = sco_socket_find_locked(sco_handle); 304 if (!sco_socket) { 305 LOG_ERROR(LOG_TAG, "%s SCO socket not found on disconnect for handle: %hu", 306 __func__, sco_handle); 307 return; 308 } 309 310 list_remove(sco_sockets, sco_socket); 311 } 312 313 static void socket_read_ready_cb(UNUSED_ATTR socket_t* socket, void* context) { 314 std::unique_lock<std::mutex> lock(sco_lock); 315 316 sco_socket_t* sco_socket = (sco_socket_t*)context; 317 socket_free(sco_socket->socket); 318 sco_socket->socket = NULL; 319 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 323 // sco_socket->socket == NULL indicates to the connect callback 324 // routine that the socket is no longer desired and should be torn 325 // down. 326 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); 329 if (sco_socket == listen_sco_socket) listen_sco_socket = NULL; 330 } 331 } 332