/******************************************************************************* ** ** Function bta_hf_client_remove_sco ** ** Description Removes the specified SCO from the system. ** If only_active is TRUE, then SCO is only removed if connected ** ** Returns BOOLEAN - TRUE if Sco removal was started ** *******************************************************************************/ static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active) { BOOLEAN removed_started = FALSE; tBTM_STATUS status; APPL_TRACE_DEBUG2("%s %d", __FUNCTION__, only_active); if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) { status = BTM_RemoveSco(bta_hf_client_cb.scb.sco_idx); APPL_TRACE_DEBUG3("%s idx 0x%04x, status:0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx, status); if (status == BTM_CMD_STARTED) { removed_started = TRUE; } /* If no connection reset the sco handle */ else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) ) { bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX; } } return removed_started; }
/******************************************************************************* ** ** Function bta_hf_client_sco_conn_cback ** ** Description BTM SCO connection callback. ** ** ** Returns void ** *******************************************************************************/ static void bta_hf_client_sco_conn_cback(UINT16 sco_idx) { BT_HDR *p_buf; UINT8 *rem_bd; APPL_TRACE_DEBUG2("%s %d", __FUNCTION__, sco_idx); rem_bd = BTM_ReadScoBdAddr(sco_idx); if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 && bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx) { if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) { p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT; p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle; bta_sys_sendmsg(p_buf); } } /* no match found; disconnect sco, init sco variables */ else { bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; BTM_RemoveSco(sco_idx); } }
// Must be called with |lock| held except during teardown when we know the socket thread // is no longer alive. static void sco_socket_free_locked(sco_socket_t *sco_socket) { if (!sco_socket) return; if (sco_socket->sco_handle != BTM_INVALID_SCO_INDEX) BTM_RemoveSco(sco_socket->sco_handle); socket_free(sco_socket->socket); osi_free(sco_socket); }
static void socket_read_ready_cb(UNUSED_ATTR socket_t *socket, void *context) { pthread_mutex_lock(&lock); sco_socket_t *sco_socket = (sco_socket_t *)context; socket_free(sco_socket->socket); sco_socket->socket = NULL; // Defer the underlying disconnect until the connection completes // since the BTM code doesn't behave correctly when a disconnect // request is issued while a connect is in progress. The fact that // sco_socket->socket == NULL indicates to the connect callback // routine that the socket is no longer desired and should be torn // down. if (sco_socket->connect_completed || sco_socket == listen_sco_socket) { if (BTM_RemoveSco(sco_socket->sco_handle) == BTM_SUCCESS) list_remove(sco_sockets, sco_socket); if (sco_socket == listen_sco_socket) listen_sco_socket = NULL; } pthread_mutex_unlock(&lock); }
static void connect_completed_cb(uint16_t sco_handle) { pthread_mutex_lock(&lock); sco_socket_t *sco_socket = sco_socket_find_locked(sco_handle); if (!sco_socket) { LOG_ERROR(LOG_TAG, "%s SCO socket not found on connect for handle: %hu", __func__, sco_handle); goto out; } // If sco_socket->socket was closed, we should tear down because there is no app-level // interest in the SCO socket. if (!sco_socket->socket) { BTM_RemoveSco(sco_socket->sco_handle); list_remove(sco_sockets, sco_socket); goto out; } sco_socket->connect_completed = true; out:; pthread_mutex_unlock(&lock); }