Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 1 | /****************************************************************************** |
| 2 | * |
Jakub Pawlowski | 5b790fe | 2017-09-18 09:00:20 -0700 | [diff] [blame] | 3 | * Copyright 2014 Google, Inc. |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 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 | |
Marie Janssen | 49120dc | 2015-07-07 16:47:20 -0700 | [diff] [blame] | 19 | #define LOG_TAG "bt_btif_sock_sco" |
| 20 | |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 21 | #include <base/logging.h> |
Etan Cohen | 3e59b5b | 2015-03-31 17:15:53 -0700 | [diff] [blame] | 22 | #include <errno.h> |
Arman Uguray | d30195c | 2015-05-29 15:27:58 -0700 | [diff] [blame] | 23 | #include <pthread.h> |
Etan Cohen | 3e59b5b | 2015-03-31 17:15:53 -0700 | [diff] [blame] | 24 | #include <string.h> |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 25 | #include <sys/socket.h> |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 26 | #include <sys/types.h> |
Arman Uguray | d30195c | 2015-05-29 15:27:58 -0700 | [diff] [blame] | 27 | #include <unistd.h> |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 28 | |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 29 | #include <mutex> |
| 30 | |
Marie Janssen | db55458 | 2015-06-26 14:53:46 -0700 | [diff] [blame] | 31 | #include <hardware/bluetooth.h> |
| 32 | #include <hardware/bt_sock.h> |
| 33 | |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 34 | #include "btif_common.h" |
Mudumba Ananth | 57f6508 | 2017-02-09 09:05:48 -0800 | [diff] [blame] | 35 | #include "device/include/esco_parameters.h" |
Arman Uguray | 625ec34 | 2015-06-10 16:21:12 -0700 | [diff] [blame] | 36 | #include "osi/include/allocator.h" |
Sharvil Nanavati | 0f9b91e | 2015-03-12 15:42:50 -0700 | [diff] [blame] | 37 | #include "osi/include/list.h" |
Sharvil Nanavati | 4480276 | 2014-12-23 23:08:58 -0800 | [diff] [blame] | 38 | #include "osi/include/log.h" |
Arman Uguray | 625ec34 | 2015-06-10 16:21:12 -0700 | [diff] [blame] | 39 | #include "osi/include/osi.h" |
Sharvil Nanavati | 0f9b91e | 2015-03-12 15:42:50 -0700 | [diff] [blame] | 40 | #include "osi/include/socket.h" |
| 41 | #include "osi/include/thread.h" |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 42 | |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 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 |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 58 | // socket_read_ready_cb() - local host closed SCO socket |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 59 | // disconnect_completed_cb() - connection terminated |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 60 | |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 61 | typedef struct { |
| 62 | uint16_t sco_handle; |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 63 | socket_t* socket; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 64 | bool connect_completed; |
| 65 | } sco_socket_t; |
| 66 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 67 | static sco_socket_t* sco_socket_establish_locked(bool is_listening, |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 68 | const RawAddress* bd_addr, |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 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); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 75 | static void connect_completed_cb(uint16_t sco_handle); |
| 76 | static void disconnect_completed_cb(uint16_t sco_handle); |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 77 | static void socket_read_ready_cb(socket_t* socket, void* context); |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 78 | |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 79 | // |sco_lock| protects all of the static variables below and |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 80 | // calls into the BTM layer. |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 81 | static std::mutex sco_lock; |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 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. |
Ian McKellar | a1d7cf2 | 2013-12-16 12:26:19 -0800 | [diff] [blame] | 85 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 86 | bt_status_t btsock_sco_init(thread_t* thread_) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 87 | CHECK(thread_ != NULL); |
Ian McKellar | a1d7cf2 | 2013-12-16 12:26:19 -0800 | [diff] [blame] | 88 | |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 89 | sco_sockets = list_new((list_free_cb)sco_socket_free_locked); |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 90 | if (!sco_sockets) return BT_STATUS_FAIL; |
Ian McKellar | a1d7cf2 | 2013-12-16 12:26:19 -0800 | [diff] [blame] | 91 | |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 92 | thread = thread_; |
Mudumba Ananth | 57f6508 | 2017-02-09 09:05:48 -0800 | [diff] [blame] | 93 | enh_esco_params_t params = esco_parameters_for_codec(ESCO_CODEC_CVSD); |
| 94 | BTM_SetEScoMode(¶ms); |
Ian McKellar | a1d7cf2 | 2013-12-16 12:26:19 -0800 | [diff] [blame] | 95 | |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 96 | return BT_STATUS_SUCCESS; |
Ian McKellar | a1d7cf2 | 2013-12-16 12:26:19 -0800 | [diff] [blame] | 97 | } |
| 98 | |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 99 | bt_status_t btsock_sco_cleanup(void) { |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 100 | list_free(sco_sockets); |
| 101 | sco_sockets = NULL; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 102 | return BT_STATUS_SUCCESS; |
Ian McKellar | a1d7cf2 | 2013-12-16 12:26:19 -0800 | [diff] [blame] | 103 | } |
| 104 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 105 | bt_status_t btsock_sco_listen(int* sock_fd, UNUSED_ATTR int flags) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 106 | CHECK(sock_fd != NULL); |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 107 | |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 108 | std::unique_lock<std::mutex> lock(sco_lock); |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 109 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 110 | sco_socket_t* sco_socket = sco_socket_establish_locked(true, NULL, sock_fd); |
| 111 | if (!sco_socket) return BT_STATUS_FAIL; |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 112 | |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 113 | BTM_RegForEScoEvts(sco_socket->sco_handle, connection_request_cb); |
| 114 | listen_sco_socket = sco_socket; |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 115 | |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 116 | return BT_STATUS_SUCCESS; |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 117 | } |
| 118 | |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 119 | bt_status_t btsock_sco_connect(const RawAddress* bd_addr, int* sock_fd, |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 120 | UNUSED_ATTR int flags) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 121 | CHECK(bd_addr != NULL); |
| 122 | CHECK(sock_fd != NULL); |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 123 | |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 124 | std::unique_lock<std::mutex> lock(sco_lock); |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 125 | sco_socket_t* sco_socket = |
| 126 | sco_socket_establish_locked(false, bd_addr, sock_fd); |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 127 | |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 128 | return (sco_socket != NULL) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 129 | } |
| 130 | |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 131 | // Must be called with |lock| held. |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 132 | static sco_socket_t* sco_socket_establish_locked(bool is_listening, |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 133 | const RawAddress* bd_addr, |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 134 | int* sock_fd) { |
| 135 | int pair[2] = {INVALID_FD, INVALID_FD}; |
| 136 | sco_socket_t* sco_socket = NULL; |
| 137 | socket_t* socket = NULL; |
Jakub Pawlowski | 713993d | 2016-04-21 13:16:45 -0700 | [diff] [blame] | 138 | tBTM_STATUS status; |
Mudumba Ananth | 57f6508 | 2017-02-09 09:05:48 -0800 | [diff] [blame] | 139 | enh_esco_params_t params; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 140 | if (socketpair(AF_LOCAL, SOCK_STREAM, 0, pair) == -1) { |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 141 | LOG_ERROR(LOG_TAG, "%s unable to allocate socket pair: %s", __func__, |
| 142 | strerror(errno)); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 143 | goto error; |
| 144 | } |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 145 | |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 146 | sco_socket = sco_socket_new(); |
| 147 | if (!sco_socket) { |
Marie Janssen | db55458 | 2015-06-26 14:53:46 -0700 | [diff] [blame] | 148 | LOG_ERROR(LOG_TAG, "%s unable to allocate new SCO socket.", __func__); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 149 | goto error; |
| 150 | } |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 151 | |
Mudumba Ananth | 57f6508 | 2017-02-09 09:05:48 -0800 | [diff] [blame] | 152 | params = esco_parameters_for_codec(ESCO_CODEC_CVSD); |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 153 | status = BTM_CreateSco(bd_addr, !is_listening, params.packet_types, |
Mudumba Ananth | 57f6508 | 2017-02-09 09:05:48 -0800 | [diff] [blame] | 154 | &sco_socket->sco_handle, connect_completed_cb, |
| 155 | disconnect_completed_cb); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 156 | if (status != BTM_CMD_STARTED) { |
Marie Janssen | db55458 | 2015-06-26 14:53:46 -0700 | [diff] [blame] | 157 | LOG_ERROR(LOG_TAG, "%s unable to create SCO socket: %d", __func__, status); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 158 | goto error; |
| 159 | } |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 160 | |
Jakub Pawlowski | 713993d | 2016-04-21 13:16:45 -0700 | [diff] [blame] | 161 | socket = socket_new_from_fd(pair[1]); |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 162 | if (!socket) { |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 163 | LOG_ERROR(LOG_TAG, "%s unable to allocate socket from file descriptor %d.", |
| 164 | __func__, pair[1]); |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 165 | goto error; |
| 166 | } |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 167 | |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 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 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 172 | socket_register(socket, thread_get_reactor(thread), sco_socket, |
| 173 | socket_read_ready_cb, NULL); |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 174 | return sco_socket; |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 175 | |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 176 | error:; |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 177 | if (pair[0] != INVALID_FD) close(pair[0]); |
| 178 | if (pair[1] != INVALID_FD) close(pair[1]); |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 179 | |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 180 | sco_socket_free_locked(sco_socket); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 181 | return NULL; |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 182 | } |
| 183 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 184 | static sco_socket_t* sco_socket_new(void) { |
| 185 | sco_socket_t* sco_socket = (sco_socket_t*)osi_calloc(sizeof(sco_socket_t)); |
Pavlin Radoslavov | 717a4a9 | 2016-02-06 08:36:06 -0800 | [diff] [blame] | 186 | sco_socket->sco_handle = BTM_INVALID_SCO_INDEX; |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 187 | return sco_socket; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 188 | } |
Ian McKellar | a1d7cf2 | 2013-12-16 12:26:19 -0800 | [diff] [blame] | 189 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 190 | // Must be called with |lock| held except during teardown when we know the |
| 191 | // socket thread |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 192 | // is no longer alive. |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 193 | static void sco_socket_free_locked(sco_socket_t* sco_socket) { |
| 194 | if (!sco_socket) return; |
Ian McKellar | a1d7cf2 | 2013-12-16 12:26:19 -0800 | [diff] [blame] | 195 | |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 196 | if (sco_socket->sco_handle != BTM_INVALID_SCO_INDEX) |
| 197 | BTM_RemoveSco(sco_socket->sco_handle); |
| 198 | socket_free(sco_socket->socket); |
Pavlin Radoslavov | eae6166 | 2015-06-02 13:54:58 -0700 | [diff] [blame] | 199 | osi_free(sco_socket); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 200 | } |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 201 | |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 202 | // Must be called with |lock| held. |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 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; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 208 | } |
| 209 | return NULL; |
| 210 | } |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 211 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 212 | static void connection_request_cb(tBTM_ESCO_EVT event, |
| 213 | tBTM_ESCO_EVT_DATA* data) { |
Jack He | f2af1c4 | 2016-12-13 01:59:12 -0800 | [diff] [blame] | 214 | CHECK(data != NULL); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 215 | |
| 216 | // Don't care about change of link parameters, only connection requests. |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 217 | if (event != BTM_ESCO_CONN_REQ_EVT) return; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 218 | |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 219 | std::unique_lock<std::mutex> lock(sco_lock); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 220 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 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); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 223 | int client_fd = INVALID_FD; |
| 224 | |
Jakub Pawlowski | 713993d | 2016-04-21 13:16:45 -0700 | [diff] [blame] | 225 | uint16_t temp; |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 226 | sco_socket_t* new_sco_socket; |
Jakub Pawlowski | 713993d | 2016-04-21 13:16:45 -0700 | [diff] [blame] | 227 | |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 228 | if (!sco_socket) { |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 229 | LOG_ERROR(LOG_TAG, "%s unable to find sco_socket for handle: %hu", __func__, |
| 230 | conn_data->sco_inx); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 231 | goto error; |
| 232 | } |
| 233 | |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 234 | if (sco_socket != listen_sco_socket) { |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 235 | 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-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 239 | goto error; |
| 240 | } |
| 241 | |
Jakub Pawlowski | 713993d | 2016-04-21 13:16:45 -0700 | [diff] [blame] | 242 | new_sco_socket = sco_socket_establish_locked(true, NULL, &client_fd); |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 243 | if (!new_sco_socket) { |
Marie Janssen | db55458 | 2015-06-26 14:53:46 -0700 | [diff] [blame] | 244 | LOG_ERROR(LOG_TAG, "%s unable to allocate new sco_socket.", __func__); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 245 | goto error; |
| 246 | } |
| 247 | |
| 248 | // Swap socket->sco_handle and new_socket->sco_handle |
Jakub Pawlowski | 713993d | 2016-04-21 13:16:45 -0700 | [diff] [blame] | 249 | temp = sco_socket->sco_handle; |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 250 | sco_socket->sco_handle = new_sco_socket->sco_handle; |
| 251 | new_sco_socket->sco_handle = temp; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 252 | |
| 253 | sock_connect_signal_t connect_signal; |
| 254 | connect_signal.size = sizeof(connect_signal); |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 255 | connect_signal.bd_addr = conn_data->bd_addr; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 256 | connect_signal.channel = 0; |
| 257 | connect_signal.status = 0; |
| 258 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 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__); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 265 | goto error; |
| 266 | } |
| 267 | |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 268 | BTM_RegForEScoEvts(listen_sco_socket->sco_handle, connection_request_cb); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 269 | BTM_EScoConnRsp(conn_data->sco_inx, HCI_SUCCESS, NULL); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 270 | |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 271 | return; |
| 272 | |
| 273 | error:; |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 274 | if (client_fd != INVALID_FD) close(client_fd); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 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) { |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 279 | std::unique_lock<std::mutex> lock(sco_lock); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 280 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 281 | sco_socket_t* sco_socket = sco_socket_find_locked(sco_handle); |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 282 | if (!sco_socket) { |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 283 | LOG_ERROR(LOG_TAG, "%s SCO socket not found on connect for handle: %hu", |
| 284 | __func__, sco_handle); |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 285 | return; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 286 | } |
| 287 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 288 | // If sco_socket->socket was closed, we should tear down because there is no |
| 289 | // app-level |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 290 | // interest in the SCO socket. |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 291 | if (!sco_socket->socket) { |
| 292 | BTM_RemoveSco(sco_socket->sco_handle); |
| 293 | list_remove(sco_sockets, sco_socket); |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 294 | return; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 295 | } |
| 296 | |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 297 | sco_socket->connect_completed = true; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 298 | } |
| 299 | |
| 300 | static void disconnect_completed_cb(uint16_t sco_handle) { |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 301 | std::unique_lock<std::mutex> lock(sco_lock); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 302 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 303 | sco_socket_t* sco_socket = sco_socket_find_locked(sco_handle); |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 304 | if (!sco_socket) { |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 305 | LOG_ERROR(LOG_TAG, "%s SCO socket not found on disconnect for handle: %hu", |
| 306 | __func__, sco_handle); |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 307 | return; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 308 | } |
| 309 | |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 310 | list_remove(sco_sockets, sco_socket); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 311 | } |
| 312 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 313 | static void socket_read_ready_cb(UNUSED_ATTR socket_t* socket, void* context) { |
Marie Janssen | a576468 | 2016-10-10 13:38:30 -0700 | [diff] [blame] | 314 | std::unique_lock<std::mutex> lock(sco_lock); |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 315 | |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 316 | sco_socket_t* sco_socket = (sco_socket_t*)context; |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 317 | socket_free(sco_socket->socket); |
| 318 | sco_socket->socket = NULL; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 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 |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 323 | // sco_socket->socket == NULL indicates to the connect callback |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 324 | // routine that the socket is no longer desired and should be torn |
| 325 | // down. |
Sharvil Nanavati | c8aaee2 | 2014-08-21 18:17:19 -0700 | [diff] [blame] | 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); |
Myles Watson | 6bd442f | 2016-10-19 09:50:22 -0700 | [diff] [blame] | 329 | if (sco_socket == listen_sco_socket) listen_sco_socket = NULL; |
June R. Tate-Gans | f866204 | 2015-02-19 14:29:35 -0800 | [diff] [blame] | 330 | } |
Ian McKellar | e93ac12 | 2013-11-07 16:30:05 -0800 | [diff] [blame] | 331 | } |