mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-01 01:13:23 +00:00
hfp_ag: release audio connection only if it was opened before audio VR activated, open audio only if connection does not already exist
This commit is contained in:
parent
734ef2bdf5
commit
0b4debbf1d
@ -542,17 +542,19 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
|
|||||||
printf("Voice Recognition command failed with status 0x%02x\n", status);
|
printf("Voice Recognition command failed with status 0x%02x\n", status);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
printf("\n");
|
||||||
switch(hfp_subevent_voice_recognition_status_get_state(event)){
|
switch(hfp_subevent_voice_recognition_status_get_state(event)){
|
||||||
case 0:
|
case HFP_VRA_VOICE_RECOGNITION_OFF:
|
||||||
printf("Voice recognition status deactivated\n");
|
printf("Voice recognition status DEACTIVATED\n");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case HFP_VRA_VOICE_RECOGNITION_ACTIVATED:
|
||||||
printf("Voice recognition status activated\n");
|
printf("Voice recognition status ACTIVATED\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
btstack_assert(false);
|
btstack_assert(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
printf("\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -507,7 +507,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
|
|||||||
printf("Audio connection released\n");
|
printf("Audio connection released\n");
|
||||||
sco_demo_close();
|
sco_demo_close();
|
||||||
break;
|
break;
|
||||||
case HFP_SUBEVENT_COMPLETE:
|
case HFP_SUBEVENT_COMPLETE:
|
||||||
status = hfp_subevent_complete_get_status(event);
|
status = hfp_subevent_complete_get_status(event);
|
||||||
if (status == ERROR_CODE_SUCCESS){
|
if (status == ERROR_CODE_SUCCESS){
|
||||||
printf("Cmd \'%c\' succeeded\n", cmd);
|
printf("Cmd \'%c\' succeeded\n", cmd);
|
||||||
@ -546,7 +546,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
|
|||||||
break;
|
break;
|
||||||
case HFP_SUBEVENT_MICROPHONE_VOLUME:
|
case HFP_SUBEVENT_MICROPHONE_VOLUME:
|
||||||
printf("Microphone volume: gain %u\n",
|
printf("Microphone volume: gain %u\n",
|
||||||
hfp_subevent_microphone_volume_get_gain(event));
|
hfp_subevent_microphone_volume_get_gain(event));
|
||||||
break;
|
break;
|
||||||
case HFP_SUBEVENT_CALLING_LINE_IDENTIFICATION_NOTIFICATION:
|
case HFP_SUBEVENT_CALLING_LINE_IDENTIFICATION_NOTIFICATION:
|
||||||
printf("Caller ID, number %s\n", hfp_subevent_calling_line_identification_notification_get_number(event));
|
printf("Caller ID, number %s\n", hfp_subevent_calling_line_identification_notification_get_number(event));
|
||||||
@ -567,17 +567,20 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
|
|||||||
printf("Voice Recognition command failed with status 0x%02x\n", status);
|
printf("Voice Recognition command failed with status 0x%02x\n", status);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
printf("\n");
|
||||||
switch(hfp_subevent_voice_recognition_status_get_state(event)){
|
switch(hfp_subevent_voice_recognition_status_get_state(event)){
|
||||||
case 0:
|
case HFP_VRA_VOICE_RECOGNITION_OFF:
|
||||||
printf("Voice recognition status deactivated\n");
|
printf("Voice recognition status DEACTIVATED\n");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case HFP_VRA_VOICE_RECOGNITION_ACTIVATED:
|
||||||
printf("Voice recognition status activated\n");
|
printf("Voice recognition status ACTIVATED\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
printf("Voice recognition status unexpected state %d\n", hfp_subevent_voice_recognition_status_get_state(event));
|
||||||
btstack_assert(false);
|
btstack_assert(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
printf("\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -869,6 +869,14 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
|||||||
hfp_connection->sco_handle = sco_handle;
|
hfp_connection->sco_handle = sco_handle;
|
||||||
hfp_connection->establish_audio_connection = 0;
|
hfp_connection->establish_audio_connection = 0;
|
||||||
hfp_connection->state = HFP_AUDIO_CONNECTION_ESTABLISHED;
|
hfp_connection->state = HFP_AUDIO_CONNECTION_ESTABLISHED;
|
||||||
|
switch (hfp_connection->vra_state){
|
||||||
|
case HFP_VRA_VOICE_RECOGNITION_ACTIVATED:
|
||||||
|
hfp_connection->ag_audio_connection_opened_after_vra = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
hfp_connection->ag_audio_connection_opened_after_vra = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
hfp_emit_sco_event(hfp_connection, status, sco_handle, event_addr, hfp_connection->negotiated_codec);
|
hfp_emit_sco_event(hfp_connection, status, sco_handle, event_addr, hfp_connection->negotiated_codec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -899,6 +907,7 @@ void hfp_handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
|||||||
}
|
}
|
||||||
|
|
||||||
hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
|
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);
|
hfp_emit_audio_connection_released(hfp_connection, handle);
|
||||||
|
|
||||||
if (hfp_connection->release_slc_connection){
|
if (hfp_connection->release_slc_connection){
|
||||||
@ -1480,11 +1489,6 @@ static void parse_sequence(hfp_connection_t * hfp_connection){
|
|||||||
hfp_connection->speaker_gain = value;
|
hfp_connection->speaker_gain = value;
|
||||||
log_info("hfp parse HFP_CMD_SET_SPEAKER_GAIN %d\n", value);
|
log_info("hfp parse HFP_CMD_SET_SPEAKER_GAIN %d\n", value);
|
||||||
break;
|
break;
|
||||||
case HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION:
|
|
||||||
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
|
|
||||||
hfp_connection->ag_activate_voice_recognition_value = value;
|
|
||||||
log_info("hfp parse HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION %d\n", value);
|
|
||||||
break;
|
|
||||||
case HFP_CMD_TURN_OFF_EC_AND_NR:
|
case HFP_CMD_TURN_OFF_EC_AND_NR:
|
||||||
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
|
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
|
||||||
hfp_connection->ag_echo_and_noise_reduction = value;
|
hfp_connection->ag_echo_and_noise_reduction = value;
|
||||||
@ -1624,10 +1628,15 @@ static void parse_sequence(hfp_connection_t * hfp_connection){
|
|||||||
case HFP_CMD_ENABLE_CALL_WAITING_NOTIFICATION:
|
case HFP_CMD_ENABLE_CALL_WAITING_NOTIFICATION:
|
||||||
hfp_connection->call_waiting_notification_enabled = hfp_connection->line_buffer[0] != '0';
|
hfp_connection->call_waiting_notification_enabled = hfp_connection->line_buffer[0] != '0';
|
||||||
break;
|
break;
|
||||||
|
case HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION:
|
||||||
|
value = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
|
||||||
|
hfp_connection->ag_activate_voice_recognition_value = value;
|
||||||
|
log_info("hfp parse HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION %d\n", value);
|
||||||
|
break;
|
||||||
case HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION:
|
case HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION:
|
||||||
switch(hfp_connection->parser_item_index){
|
switch(hfp_connection->parser_item_index){
|
||||||
case 0:
|
case 0:
|
||||||
hfp_connection->ag_vra_status = (hfp_voice_recognition_activation_status_t) btstack_atoi((char *)&hfp_connection->line_buffer[0]);
|
hfp_connection->ag_vra_status = btstack_atoi((char *)&hfp_connection->line_buffer[0]);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
hfp_connection->ag_vra_state = (hfp_voice_recognition_state_t) btstack_atoi((char *)&hfp_connection->line_buffer[0]);
|
hfp_connection->ag_vra_state = (hfp_voice_recognition_state_t) btstack_atoi((char *)&hfp_connection->line_buffer[0]);
|
||||||
@ -1727,13 +1736,24 @@ void hfp_trigger_release_service_level_connection(hfp_connection_t * hfp_connect
|
|||||||
hfp_connection->release_slc_connection = 1;
|
hfp_connection->release_slc_connection = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hfp_trigger_release_audio_connection(hfp_connection_t * hfp_connection){
|
uint8_t hfp_trigger_release_audio_connection(hfp_connection_t * hfp_connection){
|
||||||
// called internally, NULL check already performed
|
// called internally, NULL check already performed
|
||||||
btstack_assert(hfp_connection != NULL);
|
btstack_assert(hfp_connection != NULL);
|
||||||
|
if (hfp_connection->state <= HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED){
|
||||||
if (hfp_connection->state < HFP_W2_DISCONNECT_SCO){
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
hfp_connection->release_audio_connection = 1;
|
|
||||||
}
|
}
|
||||||
|
switch (hfp_connection->state) {
|
||||||
|
case HFP_W2_CONNECT_SCO:
|
||||||
|
hfp_connection->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED;
|
||||||
|
break;
|
||||||
|
case HFP_W4_SCO_CONNECTED:
|
||||||
|
case HFP_AUDIO_CONNECTION_ESTABLISHED:
|
||||||
|
hfp_connection->release_audio_connection = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
|
}
|
||||||
|
return ERROR_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct link_settings {
|
static const struct link_settings {
|
||||||
|
@ -640,6 +640,8 @@ typedef struct hfp_connection {
|
|||||||
uint8_t ag_echo_and_noise_reduction;
|
uint8_t ag_echo_and_noise_reduction;
|
||||||
// used by AG: HFP parser stores here the activation value issued by HF
|
// used by AG: HFP parser stores here the activation value issued by HF
|
||||||
uint8_t ag_activate_voice_recognition_value;
|
uint8_t ag_activate_voice_recognition_value;
|
||||||
|
bool ag_audio_connection_opened_after_vra;
|
||||||
|
|
||||||
uint8_t ag_notify_incoming_call_waiting;
|
uint8_t ag_notify_incoming_call_waiting;
|
||||||
uint8_t send_subscriber_number;
|
uint8_t send_subscriber_number;
|
||||||
uint8_t next_subscriber_number_to_send;
|
uint8_t next_subscriber_number_to_send;
|
||||||
@ -689,7 +691,7 @@ typedef struct hfp_connection {
|
|||||||
hfp_voice_recognition_activation_status_t vra_state;
|
hfp_voice_recognition_activation_status_t vra_state;
|
||||||
hfp_voice_recognition_activation_status_t vra_state_requested;
|
hfp_voice_recognition_activation_status_t vra_state_requested;
|
||||||
|
|
||||||
hfp_voice_recognition_activation_status_t ag_vra_status;
|
uint8_t ag_vra_status;
|
||||||
hfp_voice_recognition_state_t ag_vra_state;
|
hfp_voice_recognition_state_t ag_vra_state;
|
||||||
|
|
||||||
hfp_voice_recognition_message_t ag_msg;
|
hfp_voice_recognition_message_t ag_msg;
|
||||||
@ -782,7 +784,7 @@ void hfp_trigger_release_service_level_connection(hfp_connection_t * hfp_connect
|
|||||||
* @brief Prepare connection for audio connection release
|
* @brief Prepare connection for audio connection release
|
||||||
* @param hfp_connection
|
* @param hfp_connection
|
||||||
*/
|
*/
|
||||||
void hfp_trigger_release_audio_connection(hfp_connection_t * hfp_connection);
|
uint8_t hfp_trigger_release_audio_connection(hfp_connection_t * hfp_connection);
|
||||||
|
|
||||||
void hfp_reset_context_flags(hfp_connection_t * hfp_connection);
|
void hfp_reset_context_flags(hfp_connection_t * hfp_connection);
|
||||||
|
|
||||||
|
@ -778,19 +778,15 @@ static uint8_t hfp_ag_can_deactivate_voice_recognition_for_connection(hfp_connec
|
|||||||
return ERROR_CODE_SUCCESS;
|
return ERROR_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hfp_ag_voice_recognition_send(hfp_connection_t * hfp_connection, int value){
|
static bool hfp_ag_is_audio_connection_active(hfp_connection_t * hfp_connection){
|
||||||
int done = 0;
|
switch (hfp_connection->state){
|
||||||
switch(hfp_connection->command){
|
case HFP_W2_CONNECT_SCO:
|
||||||
case HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION:
|
case HFP_W4_SCO_CONNECTED:
|
||||||
done = hfp_ag_send_ok(hfp_connection->rfcomm_cid);
|
case HFP_AUDIO_CONNECTION_ESTABLISHED:
|
||||||
break;
|
return true;
|
||||||
case HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION:
|
|
||||||
done = hfp_ag_send_activate_voice_recognition_cmd(hfp_connection->rfcomm_cid, value);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
return done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hfp_ag_voice_recognition_state_machine(hfp_connection_t * hfp_connection){
|
static int hfp_ag_voice_recognition_state_machine(hfp_connection_t * hfp_connection){
|
||||||
@ -802,11 +798,10 @@ static int hfp_ag_voice_recognition_state_machine(hfp_connection_t * hfp_connect
|
|||||||
|
|
||||||
switch (hfp_connection->command){
|
switch (hfp_connection->command){
|
||||||
case HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION:
|
case HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION:
|
||||||
done = hfp_ag_voice_recognition_send(hfp_connection, hfp_connection->ag_activate_voice_recognition_value);
|
done = hfp_ag_send_activate_voice_recognition_cmd(hfp_connection->rfcomm_cid, hfp_connection->ag_activate_voice_recognition_value);
|
||||||
|
|
||||||
if (done == 0){
|
if (done == 0){
|
||||||
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
||||||
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_COMMAND_DISALLOWED, 1 - hfp_connection->ag_activate_voice_recognition_value);
|
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_COMMAND_DISALLOWED, hfp_connection->vra_state);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -840,21 +835,28 @@ static int hfp_ag_voice_recognition_state_machine(hfp_connection_t * hfp_connect
|
|||||||
hfp_connection->vra_state = HFP_VRA_VOICE_RECOGNITION_OFF;
|
hfp_connection->vra_state = HFP_VRA_VOICE_RECOGNITION_OFF;
|
||||||
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
||||||
|
|
||||||
hfp_trigger_release_audio_connection(hfp_connection);
|
// release audio connection only if it was opened before audio VR activated
|
||||||
|
if (hfp_ag_is_audio_connection_active(hfp_connection) && !hfp_connection->ag_audio_connection_opened_after_vra){
|
||||||
|
hfp_trigger_release_audio_connection(hfp_connection);
|
||||||
|
}
|
||||||
|
|
||||||
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_SUCCESS, 0);
|
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_SUCCESS, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HFP_VRA_W2_SEND_VOICE_RECOGNITION_ACTIVATED:
|
case HFP_VRA_W2_SEND_VOICE_RECOGNITION_ACTIVATED:
|
||||||
status = hfp_ag_setup_audio_connection(hfp_connection);
|
// open only if audio connection does not already exist
|
||||||
if (status != ERROR_CODE_SUCCESS){
|
if (!hfp_ag_is_audio_connection_active(hfp_connection)){
|
||||||
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
status = hfp_ag_setup_audio_connection(hfp_connection);
|
||||||
hfp_emit_voice_recognition_state_event(hfp_connection, status, 0);
|
if (status != ERROR_CODE_SUCCESS){
|
||||||
return 0;
|
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
||||||
|
hfp_emit_voice_recognition_state_event(hfp_connection, status, hfp_connection->vra_state);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hfp_connection->vra_state = HFP_VRA_VOICE_RECOGNITION_ACTIVATED;
|
hfp_connection->vra_state = HFP_VRA_VOICE_RECOGNITION_ACTIVATED;
|
||||||
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
||||||
hfp_emit_voice_recognition_state_event(hfp_connection, status, 1);
|
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_SUCCESS, hfp_connection->vra_state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -2456,7 +2458,6 @@ uint8_t hfp_ag_establish_audio_connection(hci_con_handle_t acl_handle){
|
|||||||
if (!hfp_connection){
|
if (!hfp_connection){
|
||||||
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t status = hfp_ag_setup_audio_connection(hfp_connection);
|
uint8_t status = hfp_ag_setup_audio_connection(hfp_connection);
|
||||||
if (status != ERROR_CODE_SUCCESS){
|
if (status != ERROR_CODE_SUCCESS){
|
||||||
return status;
|
return status;
|
||||||
@ -2471,9 +2472,16 @@ uint8_t hfp_ag_release_audio_connection(hci_con_handle_t acl_handle){
|
|||||||
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
hfp_trigger_release_audio_connection(hfp_connection);
|
if (hfp_connection->vra_state == HFP_VRA_VOICE_RECOGNITION_ACTIVATED){
|
||||||
hfp_ag_run_for_context(hfp_connection);
|
if (!hfp_connection->ag_audio_connection_opened_after_vra){
|
||||||
return ERROR_CODE_SUCCESS;
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t status = hfp_trigger_release_audio_connection(hfp_connection);
|
||||||
|
if (status == ERROR_CODE_SUCCESS){
|
||||||
|
hfp_ag_run_for_context(hfp_connection);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2641,6 +2649,7 @@ uint8_t hfp_ag_activate_voice_recognition(hci_con_handle_t acl_handle){
|
|||||||
hfp_connection->ag_activate_voice_recognition_value = 1;
|
hfp_connection->ag_activate_voice_recognition_value = 1;
|
||||||
hfp_connection->vra_state_requested = HFP_VRA_W2_SEND_VOICE_RECOGNITION_ACTIVATED;
|
hfp_connection->vra_state_requested = HFP_VRA_W2_SEND_VOICE_RECOGNITION_ACTIVATED;
|
||||||
hfp_connection->command = HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION;
|
hfp_connection->command = HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION;
|
||||||
|
hfp_connection->ag_audio_connection_opened_after_vra = hfp_ag_is_audio_connection_active(hfp_connection);
|
||||||
hfp_ag_run_for_context(hfp_connection);
|
hfp_ag_run_for_context(hfp_connection);
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
|
@ -433,10 +433,8 @@ static int hfp_hf_run_for_context_service_level_connection(hfp_connection_t * hf
|
|||||||
static int hfp_hf_run_for_context_service_level_connection_queries(hfp_connection_t * hfp_connection){
|
static int hfp_hf_run_for_context_service_level_connection_queries(hfp_connection_t * hfp_connection){
|
||||||
if (hfp_connection->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0;
|
if (hfp_connection->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) return 0;
|
||||||
if (hfp_connection->ok_pending){
|
if (hfp_connection->ok_pending){
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
log_info("ok not pending\n");
|
|
||||||
int done = 0;
|
int done = 0;
|
||||||
if (hfp_connection->enable_status_update_for_ag_indicators != 0xFF){
|
if (hfp_connection->enable_status_update_for_ag_indicators != 0xFF){
|
||||||
hfp_connection->ok_pending = 1;
|
hfp_connection->ok_pending = 1;
|
||||||
@ -484,6 +482,32 @@ static int hfp_hf_voice_recognition_state_machine(hfp_connection_t * hfp_connect
|
|||||||
}
|
}
|
||||||
int done = 0;
|
int done = 0;
|
||||||
|
|
||||||
|
if (hfp_connection->ok_pending == 1){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// voice recognition activated from AG
|
||||||
|
if (hfp_connection->command == HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION){
|
||||||
|
switch(hfp_connection->vra_state_requested){
|
||||||
|
case HFP_VRA_W4_VOICE_RECOGNITION_ACTIVATED:
|
||||||
|
// ignore AG command, continue to wait for OK
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case HFP_VRA_W4_VOICE_RECOGNITION_OFF:
|
||||||
|
// ignore AG command, continue to wait for OK
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (hfp_connection->ag_vra_status > 0){
|
||||||
|
hfp_connection->vra_state_requested = HFP_VRA_W4_VOICE_RECOGNITION_ACTIVATED;
|
||||||
|
} else {
|
||||||
|
hfp_connection->vra_state_requested = HFP_VRA_W4_VOICE_RECOGNITION_OFF;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hfp_connection->command = HFP_CMD_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
switch (hfp_connection->vra_state_requested){
|
switch (hfp_connection->vra_state_requested){
|
||||||
case HFP_VRA_W2_SEND_ENHANCED_VOICE_RECOGNITION_OFF:
|
case HFP_VRA_W2_SEND_ENHANCED_VOICE_RECOGNITION_OFF:
|
||||||
case HFP_VRA_W2_SEND_VOICE_RECOGNITION_OFF:
|
case HFP_VRA_W2_SEND_VOICE_RECOGNITION_OFF:
|
||||||
@ -497,7 +521,7 @@ static int hfp_hf_voice_recognition_state_machine(hfp_connection_t * hfp_connect
|
|||||||
case HFP_VRA_W4_VOICE_RECOGNITION_OFF:
|
case HFP_VRA_W4_VOICE_RECOGNITION_OFF:
|
||||||
hfp_connection->vra_state = HFP_VRA_VOICE_RECOGNITION_OFF;
|
hfp_connection->vra_state = HFP_VRA_VOICE_RECOGNITION_OFF;
|
||||||
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
||||||
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_SUCCESS, 0);
|
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_SUCCESS, hfp_connection->vra_state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HFP_VRA_W2_SEND_VOICE_RECOGNITION_ACTIVATED:
|
case HFP_VRA_W2_SEND_VOICE_RECOGNITION_ACTIVATED:
|
||||||
@ -505,13 +529,14 @@ static int hfp_hf_voice_recognition_state_machine(hfp_connection_t * hfp_connect
|
|||||||
if (done != 0){
|
if (done != 0){
|
||||||
hfp_connection->vra_state_requested = HFP_VRA_W4_VOICE_RECOGNITION_ACTIVATED;
|
hfp_connection->vra_state_requested = HFP_VRA_W4_VOICE_RECOGNITION_ACTIVATED;
|
||||||
hfp_connection->ok_pending = 1;
|
hfp_connection->ok_pending = 1;
|
||||||
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
return 1;
|
break;
|
||||||
|
|
||||||
case HFP_VRA_W4_VOICE_RECOGNITION_ACTIVATED:
|
case HFP_VRA_W4_VOICE_RECOGNITION_ACTIVATED:
|
||||||
hfp_connection->vra_state = HFP_VRA_VOICE_RECOGNITION_ACTIVATED;
|
hfp_connection->vra_state = HFP_VRA_VOICE_RECOGNITION_ACTIVATED;
|
||||||
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
||||||
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_SUCCESS, 1);
|
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_SUCCESS, hfp_connection->vra_state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HFP_VRA_W2_SEND_ENHANCED_VOICE_RECOGNITION_ACTIVATED:
|
case HFP_VRA_W2_SEND_ENHANCED_VOICE_RECOGNITION_ACTIVATED:
|
||||||
@ -525,10 +550,11 @@ static int hfp_hf_voice_recognition_state_machine(hfp_connection_t * hfp_connect
|
|||||||
case HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_ACTIVATED:
|
case HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_ACTIVATED:
|
||||||
hfp_connection->vra_state = HFP_VRA_ENHANCED_VOICE_RECOGNITION_ACTIVATED;
|
hfp_connection->vra_state = HFP_VRA_ENHANCED_VOICE_RECOGNITION_ACTIVATED;
|
||||||
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
||||||
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_SUCCESS, 2);
|
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_SUCCESS, hfp_connection->vra_state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return done;
|
return done;
|
||||||
@ -1128,7 +1154,8 @@ static void hfp_hf_handle_rfcomm_command(hfp_connection_t * hfp_connection){
|
|||||||
hfp_connection->extended_audio_gateway_error = 0;
|
hfp_connection->extended_audio_gateway_error = 0;
|
||||||
hfp_emit_event(hfp_connection, HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR, hfp_connection->extended_audio_gateway_error_value);
|
hfp_emit_event(hfp_connection, HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR, hfp_connection->extended_audio_gateway_error_value);
|
||||||
break;
|
break;
|
||||||
|
case HFP_CMD_AG_ACTIVATE_VOICE_RECOGNITION:
|
||||||
|
break;
|
||||||
case HFP_CMD_ERROR:
|
case HFP_CMD_ERROR:
|
||||||
switch (hfp_connection->state){
|
switch (hfp_connection->state){
|
||||||
case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
|
case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
|
||||||
@ -1144,18 +1171,18 @@ static void hfp_hf_handle_rfcomm_command(hfp_connection_t * hfp_connection){
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle error response for voice activation (HF initiated)
|
// handle error response for voice activation (HF initiated)
|
||||||
switch(hfp_connection->command){
|
switch(hfp_connection->vra_state_requested){
|
||||||
case HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION:
|
case HFP_VRA_VOICE_RECOGNITION_ACTIVATED:
|
||||||
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
case HFP_VRA_VOICE_RECOGNITION_OFF:
|
||||||
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_UNSPECIFIED_ERROR, hfp_connection->vra_state);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
hfp_emit_event(hfp_connection, HFP_SUBEVENT_COMPLETE, 1);
|
hfp_connection->vra_state_requested = hfp_connection->vra_state;
|
||||||
break;
|
hfp_emit_voice_recognition_state_event(hfp_connection, ERROR_CODE_UNSPECIFIED_ERROR, hfp_connection->vra_state);
|
||||||
|
hfp_reset_context_flags(hfp_connection);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
hfp_emit_event(hfp_connection, HFP_SUBEVENT_COMPLETE, 1);
|
||||||
hfp_reset_context_flags(hfp_connection);
|
hfp_reset_context_flags(hfp_connection);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1191,14 +1218,10 @@ static int hfp_parser_is_end_of_line(uint8_t byte){
|
|||||||
return (byte == '\n') || (byte == '\r');
|
return (byte == '\n') || (byte == '\r');
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hfp_hf_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
static void hfp_hf_handle_rfcomm_data(hfp_connection_t * hfp_connection, uint8_t *packet, uint16_t size){
|
||||||
UNUSED(packet_type); // ok: only called with RFCOMM_DATA_PACKET
|
|
||||||
// assertion: size >= 1 as rfcomm.c does not deliver empty packets
|
// assertion: size >= 1 as rfcomm.c does not deliver empty packets
|
||||||
if (size < 1) return;
|
if (size < 1) return;
|
||||||
|
|
||||||
hfp_connection_t * hfp_connection = get_hfp_connection_context_for_rfcomm_cid(channel);
|
|
||||||
if (!hfp_connection) return;
|
|
||||||
|
|
||||||
hfp_log_rfcomm_message("HFP_HF_RX", packet, size);
|
hfp_log_rfcomm_message("HFP_HF_RX", packet, size);
|
||||||
#ifdef ENABLE_HFP_AT_MESSAGES
|
#ifdef ENABLE_HFP_AT_MESSAGES
|
||||||
hfp_emit_string_event(hfp_connection, HFP_SUBEVENT_AT_MESSAGE_RECEIVED, (char *) packet);
|
hfp_emit_string_event(hfp_connection, HFP_SUBEVENT_AT_MESSAGE_RECEIVED, (char *) packet);
|
||||||
@ -1208,13 +1231,10 @@ static void hfp_hf_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uin
|
|||||||
int pos;
|
int pos;
|
||||||
for (pos = 0; pos < size; pos++){
|
for (pos = 0; pos < size; pos++){
|
||||||
hfp_parse(hfp_connection, packet[pos], 1);
|
hfp_parse(hfp_connection, packet[pos], 1);
|
||||||
|
|
||||||
// parse until end of line "\r" or "\n"
|
// parse until end of line "\r" or "\n"
|
||||||
if (!hfp_parser_is_end_of_line(packet[pos])) continue;
|
if (!hfp_parser_is_end_of_line(packet[pos])) continue;
|
||||||
|
|
||||||
hfp_hf_handle_rfcomm_command(hfp_connection);
|
|
||||||
}
|
}
|
||||||
hfp_hf_run_for_context(hfp_connection);
|
hfp_hf_handle_rfcomm_command(hfp_connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hfp_hf_run(void){
|
static void hfp_hf_run(void){
|
||||||
@ -1228,10 +1248,14 @@ static void hfp_hf_run(void){
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void hfp_hf_rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
static void hfp_hf_rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||||
|
hfp_connection_t * hfp_connection;
|
||||||
switch (packet_type){
|
switch (packet_type){
|
||||||
case RFCOMM_DATA_PACKET:
|
case RFCOMM_DATA_PACKET:
|
||||||
hfp_hf_handle_rfcomm_data(packet_type, channel, packet, size);
|
hfp_connection = get_hfp_connection_context_for_rfcomm_cid(channel);
|
||||||
break;
|
if (!hfp_connection) return;
|
||||||
|
hfp_hf_handle_rfcomm_data(hfp_connection, packet, size);
|
||||||
|
hfp_hf_run_for_context(hfp_connection);
|
||||||
|
return;
|
||||||
case HCI_EVENT_PACKET:
|
case HCI_EVENT_PACKET:
|
||||||
if (packet[0] == RFCOMM_EVENT_CAN_SEND_NOW){
|
if (packet[0] == RFCOMM_EVENT_CAN_SEND_NOW){
|
||||||
uint16_t rfcomm_cid = rfcomm_event_can_send_now_get_rfcomm_cid(packet);
|
uint16_t rfcomm_cid = rfcomm_event_can_send_now_get_rfcomm_cid(packet);
|
||||||
@ -1407,7 +1431,6 @@ uint8_t hfp_hf_establish_audio_connection(hci_con_handle_t acl_handle){
|
|||||||
if (hfp_connection->state >= HFP_W2_DISCONNECT_SCO){
|
if (hfp_connection->state >= HFP_W2_DISCONNECT_SCO){
|
||||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_codec_negotiation_feature(hfp_connection)) {
|
if (has_codec_negotiation_feature(hfp_connection)) {
|
||||||
switch (hfp_connection->codecs_state) {
|
switch (hfp_connection->codecs_state) {
|
||||||
case HFP_CODECS_W4_AG_COMMON_CODEC:
|
case HFP_CODECS_W4_AG_COMMON_CODEC:
|
||||||
@ -1443,8 +1466,15 @@ uint8_t hfp_hf_release_audio_connection(hci_con_handle_t acl_handle){
|
|||||||
if (!hfp_connection) {
|
if (!hfp_connection) {
|
||||||
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||||
}
|
}
|
||||||
hfp_trigger_release_audio_connection(hfp_connection);
|
if (hfp_connection->vra_state == HFP_VRA_VOICE_RECOGNITION_ACTIVATED){
|
||||||
hfp_hf_run_for_context(hfp_connection);
|
if (!hfp_connection->ag_audio_connection_opened_after_vra){
|
||||||
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t status = hfp_trigger_release_audio_connection(hfp_connection);
|
||||||
|
if (status == ERROR_CODE_SUCCESS){
|
||||||
|
hfp_hf_run_for_context(hfp_connection);
|
||||||
|
}
|
||||||
return ERROR_CODE_SUCCESS;
|
return ERROR_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1736,7 +1766,6 @@ uint8_t hfp_hf_deactivate_voice_recognition(hci_con_handle_t acl_handle){
|
|||||||
if (!hfp_hf_voice_recognition_supported(hfp_connection)){
|
if (!hfp_hf_voice_recognition_supported(hfp_connection)){
|
||||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (hfp_connection->vra_state){
|
switch (hfp_connection->vra_state){
|
||||||
case HFP_VRA_VOICE_RECOGNITION_ACTIVATED:
|
case HFP_VRA_VOICE_RECOGNITION_ACTIVATED:
|
||||||
hfp_connection->command = HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION;
|
hfp_connection->command = HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user