Ejemplo n.º 1
0
// Must be called with |lock| held.
static sco_socket_t *sco_socket_establish_locked(bool is_listening, const bt_bdaddr_t *bd_addr, int *sock_fd) {
  int pair[2] = { INVALID_FD, INVALID_FD };
  sco_socket_t *sco_socket = NULL;

  if (socketpair(AF_LOCAL, SOCK_STREAM, 0, pair) == -1) {
    LOG_ERROR(LOG_TAG, "%s unable to allocate socket pair: %s", __func__, strerror(errno));
    goto error;
  }

  sco_socket = sco_socket_new();
  if (!sco_socket) {
    LOG_ERROR(LOG_TAG, "%s unable to allocate new SCO socket.", __func__);
    goto error;
  }

  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);
  if (status != BTM_CMD_STARTED) {
    LOG_ERROR(LOG_TAG, "%s unable to create SCO socket: %d", __func__, status);
    goto error;
  }

  socket_t *socket = socket_new_from_fd(pair[1]);
  if (!socket) {
    LOG_ERROR(LOG_TAG, "%s unable to allocate socket from file descriptor %d.", __func__, pair[1]);
    goto error;
  }

  *sock_fd = pair[0];           // Transfer ownership of one end to caller.
  sco_socket->socket = socket;  // Hang on to the other end.
  list_append(sco_sockets, sco_socket);

  socket_register(socket, thread_get_reactor(thread), sco_socket, socket_read_ready_cb, NULL);
  return sco_socket;

error:;
  if (pair[0] != INVALID_FD)
    close(pair[0]);
  if (pair[1] != INVALID_FD)
    close(pair[1]);

  sco_socket_free_locked(sco_socket);
  return NULL;
}
Ejemplo n.º 2
0
/*******************************************************************************
**
** Function         bta_hf_client_create_sco
**
** Description
**
**
** Returns          void
**
*******************************************************************************/
static void bta_hf_client_sco_create(BOOLEAN is_orig)
{
    tBTM_STATUS       status;
    UINT8            *p_bd_addr = NULL;
    tBTM_ESCO_PARAMS params;

    APPL_TRACE_DEBUG2("%s %d", __FUNCTION__, is_orig);

    /* Make sure this sco handle is not already in use */
    if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX)
    {
        APPL_TRACE_WARNING2("%s: Index 0x%04x already in use", __FUNCTION__,
                            bta_hf_client_cb.scb.sco_idx);
        return;
    }

    params = bta_hf_client_esco_params[1];

    /* if initiating set current scb and peer bd addr */
    if (is_orig)
    {
        /* Attempt to use eSCO if remote host supports HFP >= 1.5 */
        if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only)
        {
            BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, &params);
            /* If ESCO or EDR ESCO, retry with SCO only in case of failure */
            if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
               ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO))
            {
                bta_hf_client_cb.scb.retry_with_sco_only = TRUE;
                APPL_TRACE_API0("Setting retry_with_sco_only to TRUE");
            }
        }
        else
        {
            if(bta_hf_client_cb.scb.retry_with_sco_only)
                APPL_TRACE_API0("retrying with SCO only");
            bta_hf_client_cb.scb.retry_with_sco_only = FALSE;

            BTM_SetEScoMode(BTM_LINK_TYPE_SCO, &params);
        }

        /* tell sys to stop av if any */
        bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
    }
    else
    {
        bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
    }

    p_bd_addr = bta_hf_client_cb.scb.peer_addr;

    status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
                           &bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback,
                           bta_hf_client_sco_disc_cback);
    if (status == BTM_CMD_STARTED && !is_orig)
    {
        if(!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback))
            APPL_TRACE_DEBUG1("%s SCO registration success", __FUNCTION__);
    }

    APPL_TRACE_API5("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
                      __FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx,
                      status, params.packet_types);
}