Home | History | Annotate | Download | only in src
      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 <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 RawAddress* 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(&params);
     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 RawAddress* 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 RawAddress* 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(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   connect_signal.bd_addr = conn_data->bd_addr;
    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