diff --git a/src/classic/hfp.c b/src/classic/hfp.c index 071c9507a..3e7840dcc 100644 --- a/src/classic/hfp.c +++ b/src/classic/hfp.c @@ -893,8 +893,23 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet #ifdef ENABLE_BCM_PCM_WBS hfp_connection->bcm_send_disable_wbs = true; #endif - hfp_connection->sco_handle = HCI_CON_HANDLE_INVALID; - hfp_connection->release_audio_connection = 0; + if (hfp_connection->sco_handle == handle){ + hfp_connection->sco_handle = HCI_CON_HANDLE_INVALID; + hfp_connection->release_audio_connection = 0; + hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; + hfp_emit_audio_connection_released(hfp_connection, handle); + + hfp_connection->ag_audio_connection_opened_after_vra = false; + + if (hfp_connection->acl_handle == HCI_CON_HANDLE_INVALID){ + hfp_emit_event(hfp_connection, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0); + hfp_finalize_connection_context(hfp_connection); + } else if (hfp_connection->release_slc_connection == 1){ + hfp_connection->release_slc_connection = 0; + hfp_connection->state = HFP_W2_DISCONNECT_RFCOMM; + rfcomm_disconnect(hfp_connection->acl_handle); + } + } if (hfp_connection->state == HFP_W4_SCO_DISCONNECTED_TO_SHUTDOWN){ // RFCOMM already closed -> remote power off @@ -905,16 +920,6 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet #endif break; } - - hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; - hfp_connection->ag_audio_connection_opened_after_vra = false; - hfp_emit_audio_connection_released(hfp_connection, handle); - - if (hfp_connection->release_slc_connection){ - hfp_connection->release_slc_connection = 0; - log_info("SCO disconnected, w2 disconnect RFCOMM\n"); - hfp_connection->state = HFP_W2_DISCONNECT_RFCOMM; - } break; default: @@ -992,23 +997,26 @@ void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *pac rfcomm_cid = little_endian_read_16(packet,2); hfp_connection = get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid); if (!hfp_connection) break; - if (hfp_connection->state == HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART){ - hfp_connection->state = HFP_IDLE; - hfp_establish_service_level_connection(hfp_connection->remote_addr, hfp_connection->service_uuid, local_role); - break; - } - if ( hfp_connection->state == HFP_AUDIO_CONNECTION_ESTABLISHED){ - // service connection was released, this implicitly releases audio connection as well - hfp_connection->release_audio_connection = 0; - hci_con_handle_t sco_handle = hfp_connection->sco_handle; - gap_disconnect(hfp_connection->sco_handle); - hfp_connection->state = HFP_W4_SCO_DISCONNECTED_TO_SHUTDOWN; - hfp_emit_audio_connection_released(hfp_connection, sco_handle); - hfp_emit_event(hfp_connection, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0); - } else { - // regular case - hfp_emit_event(hfp_connection, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0); - hfp_finalize_connection_context(hfp_connection); + switch (hfp_connection->state){ + case HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART: + hfp_connection->acl_handle = HCI_CON_HANDLE_INVALID; + hfp_connection->state = HFP_IDLE; + hfp_establish_service_level_connection(hfp_connection->remote_addr, hfp_connection->service_uuid, local_role); + break; + + case HFP_AUDIO_CONNECTION_ESTABLISHED: + // service connection was released, this implicitly releases audio connection as well + hfp_connection->release_audio_connection = 0; + hfp_connection->acl_handle = HCI_CON_HANDLE_INVALID; + hfp_connection->state = HFP_W4_SCO_DISCONNECTED_TO_SHUTDOWN; + gap_disconnect(hfp_connection->sco_handle); + break; + + default: + // regular case + hfp_emit_event(hfp_connection, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0); + hfp_finalize_connection_context(hfp_connection); + break; } break; @@ -1711,7 +1719,6 @@ void hfp_trigger_release_service_level_connection(hfp_connection_t * hfp_connect btstack_assert(hfp_connection != NULL); hfp_trigger_release_audio_connection(hfp_connection); - if (hfp_connection->state < HFP_W4_RFCOMM_CONNECTED){ hfp_connection->state = HFP_IDLE; return; @@ -1721,19 +1728,17 @@ void hfp_trigger_release_service_level_connection(hfp_connection_t * hfp_connect hfp_connection->state = HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN; return; } - + hfp_connection->release_slc_connection = 1; if (hfp_connection->state < HFP_W4_SCO_CONNECTED){ hfp_connection->state = HFP_W2_DISCONNECT_RFCOMM; return; } - + if (hfp_connection->state < HFP_W4_SCO_DISCONNECTED){ hfp_connection->state = HFP_W2_DISCONNECT_SCO; + hfp_connection->release_audio_connection = 1; return; } - - // HFP_W4_SCO_DISCONNECTED or later - hfp_connection->release_slc_connection = 1; } uint8_t hfp_trigger_release_audio_connection(hfp_connection_t * hfp_connection){ diff --git a/src/classic/hfp_ag.c b/src/classic/hfp_ag.c index 1045d1325..5e3a515b9 100644 --- a/src/classic/hfp_ag.c +++ b/src/classic/hfp_ag.c @@ -933,6 +933,13 @@ static int hfp_ag_run_for_audio_connection(hfp_connection_t * hfp_connection){ (hfp_connection->state > HFP_W2_DISCONNECT_SCO)) return 0; if (hfp_connection->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return 0; + + if (hfp_connection->release_audio_connection){ + hfp_connection->state = HFP_W4_SCO_DISCONNECTED; + hfp_connection->release_audio_connection = 0; + gap_disconnect(hfp_connection->sco_handle); + return 1; + } // accept incoming audio connection (codec negotiation is not used) if (hfp_connection->accept_sco){