mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-14 10:21:49 +00:00
hfp_hf: implement activate/deactivate enhanced voice recognition
This commit is contained in:
parent
c5e8d2c20b
commit
be55a11d15
@ -373,6 +373,7 @@ typedef enum {
|
||||
|
||||
HFP_AUDIO_CONNECTION_ESTABLISHED,
|
||||
|
||||
|
||||
HFP_W2_DISCONNECT_SCO,
|
||||
HFP_W4_SCO_DISCONNECTED,
|
||||
HFP_W4_SCO_DISCONNECTED_TO_SHUTDOWN,
|
||||
@ -384,6 +385,20 @@ typedef enum {
|
||||
HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN
|
||||
} hfp_state_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
HFP_VRA_VOICE_RECOGNITION_OFF,
|
||||
|
||||
HFP_VRA_W4_VOICE_RECOGNITION_OFF,
|
||||
HFP_VRA_W4_VOICE_RECOGNITION_ACTIVATED,
|
||||
HFP_VRA_VOICE_RECOGNITION_ACTIVATED,
|
||||
|
||||
HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_OFF,
|
||||
HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_ACTIVATED,
|
||||
HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_NEW_SESSION,
|
||||
HFP_VRA_ENHANCED_VOICE_RECOGNITION_ACTIVATED
|
||||
} hfp_voice_recognition_activation_t;
|
||||
|
||||
typedef enum {
|
||||
HFP_CODECS_IDLE,
|
||||
HFP_CODECS_RECEIVED_LIST,
|
||||
@ -651,8 +666,11 @@ typedef struct hfp_connection {
|
||||
uint8_t hf_activate_echo_canceling_and_noise_reduction;
|
||||
uint8_t hf_deactivate_echo_canceling_and_noise_reduction;
|
||||
|
||||
uint8_t voice_recognition_state_required;
|
||||
uint8_t voice_recognition_state_current; // 1-enabled; 0-dissabled
|
||||
hfp_voice_recognition_activation_t vra_state;
|
||||
// uint8_t voice_recognition_status_required;
|
||||
// uint8_t voice_recognition_status_current; // 1-enabled; 0-dissabled
|
||||
|
||||
// hfp_voice_recognition_state_t voice_recognition_state;
|
||||
|
||||
uint8_t clcc_idx;
|
||||
uint8_t clcc_dir;
|
||||
|
@ -474,8 +474,60 @@ static int hfp_hf_run_for_context_service_level_connection_queries(hfp_connectio
|
||||
return done;
|
||||
}
|
||||
|
||||
static int codecs_exchange_state_machine(hfp_connection_t * hfp_connection){
|
||||
static int voice_recognition_state_machine(hfp_connection_t * hfp_connection){
|
||||
if (hfp_connection->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) {
|
||||
return 0;
|
||||
}
|
||||
int done = 0;
|
||||
if (hfp_connection->ok_pending == 0) {
|
||||
switch (hfp_connection->vra_state){
|
||||
case HFP_VRA_W4_VOICE_RECOGNITION_OFF:
|
||||
case HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_OFF:
|
||||
hfp_connection->ok_pending = 1;
|
||||
hfp_hf_set_voice_recognition_notification_cmd(hfp_connection->rfcomm_cid, 0);
|
||||
break;
|
||||
case HFP_VRA_W4_VOICE_RECOGNITION_ACTIVATED:
|
||||
hfp_connection->ok_pending = 1;
|
||||
hfp_hf_set_voice_recognition_notification_cmd(hfp_connection->rfcomm_cid, 1);
|
||||
break;
|
||||
|
||||
case HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_ACTIVATED:
|
||||
if (hfp_connection->state != HFP_AUDIO_CONNECTION_ESTABLISHED){
|
||||
return 0;
|
||||
}
|
||||
hfp_connection->ok_pending = 1;
|
||||
hfp_hf_set_voice_recognition_notification_cmd(hfp_connection->rfcomm_cid, 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (hfp_connection->vra_state){
|
||||
case HFP_VRA_W4_VOICE_RECOGNITION_ACTIVATED:
|
||||
hfp_connection->vra_state = HFP_VRA_VOICE_RECOGNITION_ACTIVATED;
|
||||
hfp_emit_event(hfp_connection, HFP_SUBEVENT_VOICE_RECOGNITION_STATUS, 1);
|
||||
break;
|
||||
|
||||
case HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_ACTIVATED:
|
||||
hfp_connection->vra_state = HFP_VRA_ENHANCED_VOICE_RECOGNITION_ACTIVATED;
|
||||
hfp_emit_event(hfp_connection, HFP_SUBEVENT_VOICE_RECOGNITION_STATUS, 2);
|
||||
break;
|
||||
|
||||
case HFP_VRA_W4_VOICE_RECOGNITION_OFF:
|
||||
case HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_OFF:
|
||||
hfp_connection->vra_state = HFP_VRA_VOICE_RECOGNITION_OFF;
|
||||
hfp_emit_event(hfp_connection, HFP_SUBEVENT_VOICE_RECOGNITION_STATUS, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
|
||||
static int codecs_exchange_state_machine(hfp_connection_t * hfp_connection){
|
||||
if (hfp_connection->ok_pending) return 0;
|
||||
|
||||
if (hfp_connection->trigger_codec_exchange){
|
||||
@ -529,7 +581,6 @@ static int hfp_hf_run_for_audio_connection(hfp_connection_t * hfp_connection){
|
||||
hfp_setup_synchronous_connection(hfp_connection);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -623,6 +674,9 @@ static void hfp_hf_run_for_context(hfp_connection_t * hfp_connection){
|
||||
if (!done){
|
||||
done = hfp_hf_run_for_context_service_level_connection_queries(hfp_connection);
|
||||
}
|
||||
if (!done){
|
||||
done = voice_recognition_state_machine(hfp_connection);
|
||||
}
|
||||
if (!done){
|
||||
done = hfp_hf_run_for_audio_connection(hfp_connection);
|
||||
}
|
||||
@ -675,12 +729,6 @@ static void hfp_hf_run_for_context(hfp_connection_t * hfp_connection){
|
||||
return;
|
||||
}
|
||||
|
||||
if (hfp_connection->voice_recognition_state_required != hfp_connection->voice_recognition_state_current){
|
||||
hfp_connection->ok_pending = 1;
|
||||
hfp_hf_set_voice_recognition_notification_cmd(hfp_connection->rfcomm_cid, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hfp_connection->hf_deactivate_call_waiting_notification){
|
||||
hfp_connection->hf_deactivate_call_waiting_notification = 0;
|
||||
hfp_connection->ok_pending = 1;
|
||||
@ -899,7 +947,6 @@ static void hfp_hf_handle_suggested_codec(hfp_connection_t * hfp_connection){
|
||||
}
|
||||
|
||||
static void hfp_hf_switch_on_ok(hfp_connection_t *hfp_connection){
|
||||
hfp_connection->ok_pending = 0;
|
||||
switch (hfp_connection->state){
|
||||
case HFP_W4_EXCHANGE_SUPPORTED_FEATURES:
|
||||
if (has_codec_negotiation_feature(hfp_connection)){
|
||||
@ -992,22 +1039,20 @@ static void hfp_hf_switch_on_ok(hfp_connection_t *hfp_connection){
|
||||
default:
|
||||
break;
|
||||
}
|
||||
voice_recognition_state_machine(hfp_connection);
|
||||
break;
|
||||
case HFP_AUDIO_CONNECTION_ESTABLISHED:
|
||||
voice_recognition_state_machine(hfp_connection);
|
||||
break;
|
||||
default:
|
||||
switch (hfp_connection->command){
|
||||
case HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION:
|
||||
hfp_connection->voice_recognition_state_current = hfp_connection->voice_recognition_state_required;
|
||||
hfp_emit_event(hfp_connection, HFP_SUBEVENT_VOICE_RECOGNITION_STATUS, hfp_connection->voice_recognition_state_current);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// done
|
||||
hfp_connection->ok_pending = 0;
|
||||
hfp_connection->command = HFP_CMD_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hfp_hf_handle_transfer_ag_indicator_status(hfp_connection_t * hfp_connection) {
|
||||
uint16_t i;
|
||||
@ -1078,36 +1123,43 @@ static void hfp_hf_handle_rfcomm_command(hfp_connection_t * hfp_connection){
|
||||
case HFP_CMD_ERROR:
|
||||
hfp_connection->ok_pending = 0;
|
||||
hfp_reset_context_flags(hfp_connection);
|
||||
|
||||
hfp_connection->command = HFP_CMD_NONE;
|
||||
|
||||
switch (hfp_connection->state){
|
||||
case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
|
||||
switch (hfp_connection->codecs_state){
|
||||
case HFP_CODECS_RECEIVED_TRIGGER_CODEC_EXCHANGE:
|
||||
hfp_connection->command = HFP_CMD_NONE;
|
||||
hfp_emit_sco_event(hfp_connection, HFP_REMOTE_REJECTS_AUDIO_CONNECTION, 0, hfp_connection->remote_addr, hfp_connection->negotiated_codec);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (hfp_connection->command){
|
||||
case HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION:
|
||||
// reset required voice recognition flag
|
||||
hfp_connection->voice_recognition_state_required = hfp_connection->voice_recognition_state_current;
|
||||
|
||||
switch (hfp_connection->vra_state){
|
||||
case HFP_VRA_W4_VOICE_RECOGNITION_OFF:
|
||||
hfp_connection->vra_state = HFP_VRA_VOICE_RECOGNITION_ACTIVATED;
|
||||
break;
|
||||
case HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_OFF:
|
||||
hfp_connection->vra_state = HFP_VRA_ENHANCED_VOICE_RECOGNITION_ACTIVATED;
|
||||
break;
|
||||
case HFP_VRA_W4_VOICE_RECOGNITION_ACTIVATED:
|
||||
case HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_ACTIVATED:
|
||||
hfp_connection->vra_state = HFP_VRA_VOICE_RECOGNITION_OFF;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
hfp_connection->command = HFP_CMD_NONE;
|
||||
hfp_emit_event(hfp_connection, HFP_SUBEVENT_COMPLETE, 1);
|
||||
break;
|
||||
case HFP_CMD_OK:
|
||||
hfp_hf_switch_on_ok(hfp_connection);
|
||||
break;
|
||||
break;
|
||||
case HFP_CMD_RING:
|
||||
hfp_connection->command = HFP_CMD_NONE;
|
||||
hfp_emit_simple_event(hfp_connection, HFP_SUBEVENT_RING);
|
||||
@ -1627,38 +1679,109 @@ void hfp_hf_deactivate_echo_canceling_and_noise_reduction(hci_con_handle_t acl_h
|
||||
hfp_hf_run_for_context(hfp_connection);
|
||||
}
|
||||
|
||||
void hfp_hf_activate_voice_recognition_notification(hci_con_handle_t acl_handle){
|
||||
hfp_connection_t * hfp_connection = get_hfp_hf_connection_context_for_acl_handle(acl_handle);
|
||||
if (!hfp_connection) {
|
||||
log_error("HFP HF: ACL handle 0x%2x is not found.", acl_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hfp_connection->voice_recognition_state_current == 1){
|
||||
hfp_emit_event(hfp_connection, HFP_SUBEVENT_VOICE_RECOGNITION_STATUS, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
hfp_connection->command = HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION;
|
||||
hfp_connection->voice_recognition_state_required = 1;
|
||||
hfp_hf_run_for_context(hfp_connection);
|
||||
static bool hfp_hf_enhanced_voice_recognition_supported(hfp_connection_t * hfp_connection){
|
||||
int ag = get_bit(hfp_connection->remote_supported_features, HFP_AGSF_ENHANCED_VOICE_RECOGNITION_STATUS);
|
||||
int hf = get_bit(hfp_supported_features, HFP_HFSF_ENHANCED_VOICE_RECOGNITION_STATUS);
|
||||
return hf && ag;
|
||||
}
|
||||
|
||||
void hfp_hf_deactivate_voice_recognition_notification(hci_con_handle_t acl_handle){
|
||||
static bool hfp_hf_voice_recognition_supported(hfp_connection_t * hfp_connection){
|
||||
int ag = get_bit(hfp_connection->remote_supported_features, HFP_AGSF_VOICE_RECOGNITION_FUNCTION);
|
||||
int hf = get_bit(hfp_supported_features, HFP_HFSF_VOICE_RECOGNITION_FUNCTION);
|
||||
return hf && ag;
|
||||
}
|
||||
|
||||
uint8_t hfp_hf_activate_voice_recognition_notification(hci_con_handle_t acl_handle){
|
||||
hfp_connection_t * hfp_connection = get_hfp_hf_connection_context_for_acl_handle(acl_handle);
|
||||
if (!hfp_connection) {
|
||||
log_error("HFP HF: ACL handle 0x%2x is not found.", acl_handle);
|
||||
return;
|
||||
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||
}
|
||||
|
||||
if (hfp_connection->voice_recognition_state_current == 0){
|
||||
hfp_emit_event(hfp_connection, HFP_SUBEVENT_VOICE_RECOGNITION_STATUS, 0);
|
||||
return;
|
||||
if (!hfp_hf_voice_recognition_supported(hfp_connection)){
|
||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||
}
|
||||
|
||||
hfp_connection->command = HFP_CMD_HF_ACTIVATE_VOICE_RECOGNITION;
|
||||
hfp_connection->voice_recognition_state_required = 0;
|
||||
hfp_hf_run_for_context(hfp_connection);
|
||||
|
||||
switch (hfp_connection->vra_state){
|
||||
case HFP_VRA_VOICE_RECOGNITION_ACTIVATED:
|
||||
hfp_emit_event(hfp_connection, HFP_SUBEVENT_VOICE_RECOGNITION_STATUS, 1);
|
||||
break;
|
||||
case HFP_VRA_VOICE_RECOGNITION_OFF:
|
||||
hfp_connection->vra_state = HFP_VRA_W4_VOICE_RECOGNITION_ACTIVATED;
|
||||
hfp_hf_run_for_context(hfp_connection);
|
||||
break;
|
||||
default:
|
||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||
}
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uint8_t hfp_hf_activate_start_enhanced_voice_recognition_session(hci_con_handle_t acl_handle){
|
||||
hfp_connection_t * hfp_connection = get_hfp_hf_connection_context_for_acl_handle(acl_handle);
|
||||
if (!hfp_connection) {
|
||||
log_error("HFP HF: ACL handle 0x%2x is not found.", acl_handle);
|
||||
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||
}
|
||||
|
||||
if (!hfp_hf_enhanced_voice_recognition_supported(hfp_connection)){
|
||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||
}
|
||||
|
||||
switch (hfp_connection->vra_state){
|
||||
case HFP_VRA_ENHANCED_VOICE_RECOGNITION_ACTIVATED:
|
||||
case HFP_VRA_VOICE_RECOGNITION_OFF:
|
||||
hfp_connection->vra_state = HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_ACTIVATED;
|
||||
hfp_hf_run_for_context(hfp_connection);
|
||||
break;
|
||||
default:
|
||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||
}
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static uint8_t hfp_hf_deactivate_voice_recognition(hfp_connection_t * hfp_connection){
|
||||
switch (hfp_connection->vra_state){
|
||||
case HFP_VRA_VOICE_RECOGNITION_OFF:
|
||||
hfp_emit_event(hfp_connection, HFP_SUBEVENT_VOICE_RECOGNITION_STATUS, 0);
|
||||
break;
|
||||
case HFP_VRA_VOICE_RECOGNITION_ACTIVATED:
|
||||
hfp_connection->vra_state = HFP_VRA_W4_VOICE_RECOGNITION_OFF;
|
||||
hfp_hf_run_for_context(hfp_connection);
|
||||
break;
|
||||
case HFP_VRA_ENHANCED_VOICE_RECOGNITION_ACTIVATED:
|
||||
hfp_connection->vra_state = HFP_VRA_W4_ENHANCED_VOICE_RECOGNITION_OFF;
|
||||
hfp_hf_run_for_context(hfp_connection);
|
||||
break;
|
||||
default:
|
||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||
}
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uint8_t hfp_hf_deactivate_voice_recognition_notification(hci_con_handle_t acl_handle){
|
||||
hfp_connection_t * hfp_connection = get_hfp_hf_connection_context_for_acl_handle(acl_handle);
|
||||
if (!hfp_connection) {
|
||||
log_error("HFP HF: ACL handle 0x%2x is not found.", acl_handle);
|
||||
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||
}
|
||||
if (!hfp_hf_voice_recognition_supported(hfp_connection)){
|
||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||
}
|
||||
return hfp_hf_deactivate_voice_recognition(hfp_connection);
|
||||
}
|
||||
|
||||
|
||||
uint8_t hfp_hf_deactivate_enhanced_voice_recognition_notification(hci_con_handle_t acl_handle){
|
||||
hfp_connection_t * hfp_connection = get_hfp_hf_connection_context_for_acl_handle(acl_handle);
|
||||
if (!hfp_connection) {
|
||||
log_error("HFP HF: ACL handle 0x%2x is not found.", acl_handle);
|
||||
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||
}
|
||||
if (!hfp_hf_enhanced_voice_recognition_supported(hfp_connection)){
|
||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||
}
|
||||
return hfp_hf_deactivate_voice_recognition(hfp_connection);
|
||||
}
|
||||
|
||||
void hfp_hf_set_microphone_gain(hci_con_handle_t acl_handle, int gain){
|
||||
|
@ -316,13 +316,17 @@ void hfp_hf_deactivate_echo_canceling_and_noise_reduction(hci_con_handle_t acl_h
|
||||
* @brief Activate voice recognition function.
|
||||
* @param acl_handle of the AG
|
||||
*/
|
||||
void hfp_hf_activate_voice_recognition_notification(hci_con_handle_t acl_handle);
|
||||
uint8_t hfp_hf_activate_voice_recognition_notification(hci_con_handle_t acl_handle);
|
||||
|
||||
/*
|
||||
* @brief Dectivate voice recognition function.
|
||||
* @param acl_handle of the AG
|
||||
*/
|
||||
void hfp_hf_deactivate_voice_recognition_notification(hci_con_handle_t acl_handle);
|
||||
uint8_t hfp_hf_deactivate_voice_recognition_notification(hci_con_handle_t acl_handle);
|
||||
|
||||
uint8_t hfp_hf_activate_start_enhanced_voice_recognition_session(hci_con_handle_t acl_handle);
|
||||
|
||||
uint8_t hfp_hf_deactivate_enhanced_voice_recognition_notification(hci_con_handle_t acl_handle);
|
||||
|
||||
/*
|
||||
* @brief Set microphone gain.
|
||||
|
@ -139,9 +139,9 @@ HFP/HF/IIA/BV-04-I: D
|
||||
|
||||
HFP/HF/HFI/BV-01-I: !, !, !
|
||||
|
||||
HFP/HF/VRR/BV-01-I: (test fail, not implemented / support Enhanced Voice Recognition Status per BRSF exchange info)
|
||||
HFP/HF/VRR/BV-01-I: R, B, r
|
||||
|
||||
HFP/HF/VTA/BV-01-I: (test fail, not implemented / support Enhanced Voice Recognition Status per BRSF exchange info)
|
||||
HFP/HF/VTA/BV-01-I: R, R
|
||||
|
||||
HFP/HF/ATAH/BV-01-I: f, b, B, A
|
||||
|
||||
|
@ -147,6 +147,7 @@ static void show_usage(void){
|
||||
printf("l/L - deactivate/activate calling line notification\n");
|
||||
printf("m/M - deactivate/activate echo canceling and noise reduction\n");
|
||||
printf("n/N - deactivate/activate voice recognition\n");
|
||||
printf("r/R - deactivate/activate enhanced voice recognition\n");
|
||||
printf("0123456789#*-+ - send DTMF dial tones\n");
|
||||
printf("x - request phone number for voice tag | X - current call status (ECS)\n");
|
||||
printf("y - release call with index 2 (ECC) | Y - private consulation with call 2(ECC)\n");
|
||||
@ -310,6 +311,18 @@ static void stdin_process(char c){
|
||||
printf("Activate voice recognition %s\n", bd_addr_to_str(device_addr));
|
||||
hfp_hf_activate_voice_recognition_notification(acl_handle);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Deactivate enhanced voice recognition\n");
|
||||
hfp_hf_deactivate_enhanced_voice_recognition_notification(acl_handle);
|
||||
break;
|
||||
case 'R':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Activate enhanced voice recognition %s\n", bd_addr_to_str(device_addr));
|
||||
hfp_hf_activate_start_enhanced_voice_recognition_session(acl_handle);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set speaker gain to 0 (minimum)\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user