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 <assert.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 <hardware/bluetooth.h> 30 #include <hardware/bt_sock.h> 31 32 #include "btif_common.h" 33 #include "osi/include/allocator.h" 34 #include "osi/include/list.h" 35 #include "osi/include/log.h" 36 #include "osi/include/osi.h" 37 #include "osi/include/socket.h" 38 #include "osi/include/thread.h" 39 40 // This module provides a socket abstraction for SCO connections to a higher 41 // layer. It returns file descriptors representing two types of sockets: 42 // listening (server) and connected (client) sockets. No SCO data is 43 // transferred across these sockets; instead, they are used to manage SCO 44 // connection lifecycles while the data routing takes place over the I2S bus. 45 // 46 // This code bridges the gap between the BTM layer, which implements SCO 47 // connections, and the Android HAL. It adapts the BTM representation of SCO 48 // connections (integer handles) to a file descriptor representation usable by 49 // Android's LocalSocket implementation. 50 // 51 // Sample flow for an incoming connection: 52 // btsock_sco_listen() - listen for incoming connections 53 // connection_request_cb() - incoming connection request from remote host 54 // connect_completed_cb() - connection successfully established 55 // socket_read_ready_cb() - local host closed SCO socket 56 // disconnect_completed_cb() - connection terminated 57 58 typedef struct { 59 uint16_t sco_handle; 60 socket_t *socket; 61 bool connect_completed; 62 } sco_socket_t; 63 64 // TODO: verify packet types that are being sent OTA. 65 static tBTM_ESCO_PARAMS sco_parameters = { 66 BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */ 67 BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */ 68 0x000a, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */ 69 0x0060, /* Inp Linear, Air CVSD, 2s Comp, 16bit */ 70 (BTM_SCO_LINK_ALL_PKT_MASK | 71 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | 72 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), 73 BTM_ESCO_RETRANS_POWER /* Retransmission effort */ 74 }; 75 76 static sco_socket_t *sco_socket_establish_locked(bool is_listening, const bt_bdaddr_t *bd_addr, int *sock_fd); 77 static sco_socket_t *sco_socket_new(void); 78 static void sco_socket_free_locked(sco_socket_t *socket); 79 static sco_socket_t *sco_socket_find_locked(uint16_t sco_handle); 80 static void connection_request_cb(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *data); 81 static void connect_completed_cb(uint16_t sco_handle); 82 static void disconnect_completed_cb(uint16_t sco_handle); 83 static void socket_read_ready_cb(socket_t *socket, void *context); 84 85 // |lock| protects all of the static variables below and 86 // calls into the BTM layer. 87 static pthread_mutex_t lock; 88 static list_t *sco_sockets; // Owns a collection of sco_socket_t objects. 89 static sco_socket_t *listen_sco_socket; // Not owned, do not free. 90 static thread_t *thread; // Not owned, do not free. 91 92 bt_status_t btsock_sco_init(thread_t *thread_) { 93 assert(thread_ != NULL); 94 95 sco_sockets = list_new((list_free_cb)sco_socket_free_locked); 96 if (!sco_sockets) 97 return BT_STATUS_FAIL; 98 99 pthread_mutex_init(&lock, NULL); 100 101 thread = thread_; 102 BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, &sco_parameters); 103 104 return BT_STATUS_SUCCESS; 105 } 106 107 bt_status_t btsock_sco_cleanup(void) { 108 list_free(sco_sockets); 109 sco_sockets = NULL; 110 pthread_mutex_destroy(&lock); 111 return BT_STATUS_SUCCESS; 112 } 113 114 bt_status_t btsock_sco_listen(int *sock_fd, UNUSED_ATTR int flags) { 115 assert(sock_fd != NULL); 116 117 pthread_mutex_lock(&lock); 118 119 sco_socket_t *sco_socket = sco_socket_establish_locked(true, NULL, sock_fd); 120 if (sco_socket) { 121 BTM_RegForEScoEvts(sco_socket->sco_handle, connection_request_cb); 122 listen_sco_socket = sco_socket; 123 } 124 125 pthread_mutex_unlock(&lock); 126 127 return sco_socket ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; 128 } 129 130 bt_status_t btsock_sco_connect(const bt_bdaddr_t *bd_addr, int *sock_fd, UNUSED_ATTR int flags) { 131 assert(bd_addr != NULL); 132 assert(sock_fd != NULL); 133 134 pthread_mutex_lock(&lock); 135 sco_socket_t *sco_socket = sco_socket_establish_locked(false, bd_addr, sock_fd); 136 pthread_mutex_unlock(&lock); 137 138 return (sco_socket != NULL) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; 139 } 140 141 // Must be called with |lock| held. 142 static sco_socket_t *sco_socket_establish_locked(bool is_listening, const bt_bdaddr_t *bd_addr, int *sock_fd) { 143 int pair[2] = { INVALID_FD, INVALID_FD }; 144 sco_socket_t *sco_socket = NULL; 145 146 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, pair) == -1) { 147 LOG_ERROR(LOG_TAG, "%s unable to allocate socket pair: %s", __func__, strerror(errno)); 148 goto error; 149 } 150 151 sco_socket = sco_socket_new(); 152 if (!sco_socket) { 153 LOG_ERROR(LOG_TAG, "%s unable to allocate new SCO socket.", __func__); 154 goto error; 155 } 156 157 tBTM_STATUS status = BTM_CreateSco((uint8_t *)bd_addr, !is_listening, sco_parameters.packet_types, &sco_socket->sco_handle, connect_completed_cb, disconnect_completed_cb); 158 if (status != BTM_CMD_STARTED) { 159 LOG_ERROR(LOG_TAG, "%s unable to create SCO socket: %d", __func__, status); 160 goto error; 161 } 162 163 socket_t *socket = socket_new_from_fd(pair[1]); 164 if (!socket) { 165 LOG_ERROR(LOG_TAG, "%s unable to allocate socket from file descriptor %d.", __func__, pair[1]); 166 goto error; 167 } 168 169 *sock_fd = pair[0]; // Transfer ownership of one end to caller. 170 sco_socket->socket = socket; // Hang on to the other end. 171 list_append(sco_sockets, sco_socket); 172 173 socket_register(socket, thread_get_reactor(thread), sco_socket, socket_read_ready_cb, NULL); 174 return sco_socket; 175 176 error:; 177 if (pair[0] != INVALID_FD) 178 close(pair[0]); 179 if (pair[1] != INVALID_FD) 180 close(pair[1]); 181 182 sco_socket_free_locked(sco_socket); 183 return NULL; 184 } 185 186 static sco_socket_t *sco_socket_new(void) { 187 sco_socket_t *sco_socket = (sco_socket_t *)osi_calloc(sizeof(sco_socket_t)); 188 sco_socket->sco_handle = BTM_INVALID_SCO_INDEX; 189 return sco_socket; 190 } 191 192 // Must be called with |lock| held except during teardown when we know the socket thread 193 // is no longer alive. 194 static void sco_socket_free_locked(sco_socket_t *sco_socket) { 195 if (!sco_socket) 196 return; 197 198 if (sco_socket->sco_handle != BTM_INVALID_SCO_INDEX) 199 BTM_RemoveSco(sco_socket->sco_handle); 200 socket_free(sco_socket->socket); 201 osi_free(sco_socket); 202 } 203 204 // Must be called with |lock| held. 205 static sco_socket_t *sco_socket_find_locked(uint16_t sco_handle) { 206 for (const list_node_t *node = list_begin(sco_sockets); node != list_end(sco_sockets); node = list_next(node)) { 207 sco_socket_t *sco_socket = (sco_socket_t *)list_node(node); 208 if (sco_socket->sco_handle == sco_handle) 209 return sco_socket; 210 } 211 return NULL; 212 } 213 214 static void connection_request_cb(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *data) { 215 assert(data != NULL); 216 217 // Don't care about change of link parameters, only connection requests. 218 if (event != BTM_ESCO_CONN_REQ_EVT) 219 return; 220 221 pthread_mutex_lock(&lock); 222 223 const tBTM_ESCO_CONN_REQ_EVT_DATA *conn_data = &data->conn_evt; 224 sco_socket_t *sco_socket = sco_socket_find_locked(conn_data->sco_inx); 225 int client_fd = INVALID_FD; 226 227 if (!sco_socket) { 228 LOG_ERROR(LOG_TAG, "%s unable to find sco_socket for handle: %hu", __func__, conn_data->sco_inx); 229 goto error; 230 } 231 232 if (sco_socket != listen_sco_socket) { 233 LOG_ERROR(LOG_TAG, "%s received connection request on non-listening socket handle: %hu", __func__, conn_data->sco_inx); 234 goto error; 235 } 236 237 sco_socket_t *new_sco_socket = sco_socket_establish_locked(true, NULL, &client_fd); 238 if (!new_sco_socket) { 239 LOG_ERROR(LOG_TAG, "%s unable to allocate new sco_socket.", __func__); 240 goto error; 241 } 242 243 // Swap socket->sco_handle and new_socket->sco_handle 244 uint16_t temp = sco_socket->sco_handle; 245 sco_socket->sco_handle = new_sco_socket->sco_handle; 246 new_sco_socket->sco_handle = temp; 247 248 sock_connect_signal_t connect_signal; 249 connect_signal.size = sizeof(connect_signal); 250 memcpy(&connect_signal.bd_addr, conn_data->bd_addr, sizeof(bt_bdaddr_t)); 251 connect_signal.channel = 0; 252 connect_signal.status = 0; 253 254 if (socket_write_and_transfer_fd(sco_socket->socket, &connect_signal, sizeof(connect_signal), client_fd) != sizeof(connect_signal)) { 255 LOG_ERROR(LOG_TAG, "%s unable to send new file descriptor to listening socket.", __func__); 256 goto error; 257 } 258 259 BTM_RegForEScoEvts(listen_sco_socket->sco_handle, connection_request_cb); 260 BTM_EScoConnRsp(conn_data->sco_inx, HCI_SUCCESS, NULL); 261 262 pthread_mutex_unlock(&lock); 263 return; 264 265 error:; 266 pthread_mutex_unlock(&lock); 267 268 if (client_fd != INVALID_FD) 269 close(client_fd); 270 BTM_EScoConnRsp(conn_data->sco_inx, HCI_ERR_HOST_REJECT_RESOURCES, NULL); 271 } 272 273 static void connect_completed_cb(uint16_t sco_handle) { 274 pthread_mutex_lock(&lock); 275 276 sco_socket_t *sco_socket = sco_socket_find_locked(sco_handle); 277 if (!sco_socket) { 278 LOG_ERROR(LOG_TAG, "%s SCO socket not found on connect for handle: %hu", __func__, sco_handle); 279 goto out; 280 } 281 282 // If sco_socket->socket was closed, we should tear down because there is no app-level 283 // interest in the SCO socket. 284 if (!sco_socket->socket) { 285 BTM_RemoveSco(sco_socket->sco_handle); 286 list_remove(sco_sockets, sco_socket); 287 goto out; 288 } 289 290 sco_socket->connect_completed = true; 291 292 out:; 293 pthread_mutex_unlock(&lock); 294 } 295 296 static void disconnect_completed_cb(uint16_t sco_handle) { 297 pthread_mutex_lock(&lock); 298 299 sco_socket_t *sco_socket = sco_socket_find_locked(sco_handle); 300 if (!sco_socket) { 301 LOG_ERROR(LOG_TAG, "%s SCO socket not found on disconnect for handle: %hu", __func__, sco_handle); 302 goto out; 303 } 304 305 list_remove(sco_sockets, sco_socket); 306 307 out:; 308 pthread_mutex_unlock(&lock); 309 } 310 311 static void socket_read_ready_cb(UNUSED_ATTR socket_t *socket, void *context) { 312 pthread_mutex_lock(&lock); 313 314 sco_socket_t *sco_socket = (sco_socket_t *)context; 315 socket_free(sco_socket->socket); 316 sco_socket->socket = NULL; 317 318 // Defer the underlying disconnect until the connection completes 319 // since the BTM code doesn't behave correctly when a disconnect 320 // request is issued while a connect is in progress. The fact that 321 // sco_socket->socket == NULL indicates to the connect callback 322 // routine that the socket is no longer desired and should be torn 323 // down. 324 if (sco_socket->connect_completed || sco_socket == listen_sco_socket) { 325 if (BTM_RemoveSco(sco_socket->sco_handle) == BTM_SUCCESS) 326 list_remove(sco_sockets, sco_socket); 327 if (sco_socket == listen_sco_socket) 328 listen_sco_socket = NULL; 329 } 330 331 pthread_mutex_unlock(&lock); 332 } 333