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