From f842c19ff9c536c33b53a6f52dab9bcbab04e414 Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Mon, 2 Sep 2024 14:38:00 +0800 Subject: [PATCH] Bluetooth: HFP_AG: Support Voice recognition activation Add configuration `CONFIG_BT_HFP_AG_VOICE_RECG` to enable Voice recognition activation feature. Add configuration `CONFIG_BT_HFP_AG_ENH_VOICE_RECG` to enable Enhanced Voice Recognition Status feature. Add configuration `CONFIG_BT_HFP_AG_VOICE_RECG_TEXT` to enable Voice Recognition Text feature. Add function `bt_hfp_ag_voice_recognition` activate/deactivate the Voice recognition activation feature. Add function `bt_hfp_ag_vre_state` to notify the state of the voice recognition engine. Add function `bt_hfp_ag_vre_textual_representation` to notify the state and textual representation of voice recognition engine. Add callback `voice_recognition` to notify the upper layer the status of voice recognition activation. Add callback `ready_to_accept_audio` to notify the upper layer that the HF is ready to accept audio. Signed-off-by: Lyle Zhu --- include/zephyr/bluetooth/classic/hfp_ag.h | 111 +++++++ subsys/bluetooth/host/classic/Kconfig | 18 ++ subsys/bluetooth/host/classic/hfp_ag.c | 276 ++++++++++++++++++ .../bluetooth/host/classic/hfp_ag_internal.h | 36 ++- subsys/bluetooth/host/classic/hfp_internal.h | 8 + 5 files changed, 447 insertions(+), 2 deletions(-) diff --git a/include/zephyr/bluetooth/classic/hfp_ag.h b/include/zephyr/bluetooth/classic/hfp_ag.h index 5e4f8829195..bc486e2bfc5 100644 --- a/include/zephyr/bluetooth/classic/hfp_ag.h +++ b/include/zephyr/bluetooth/classic/hfp_ag.h @@ -282,6 +282,42 @@ struct bt_hfp_ag_cb { * @param ag HFP AG object. */ void (*explicit_call_transfer)(struct bt_hfp_ag *ag); + + /** Voice recognition activation/deactivation callback + * + * If this callback is provided it will be called whenever the + * voice recognition activation is changed. + * If voice recognition is activated, the upper layer should + * call `bt_hfp_ag_audio_connect` with appropriate codec ID to + * setup audio connection. + * If the callback is not provided by upper layer, the function + * `bt_hfp_ag_audio_connect` will be called with default codec + * ID `BT_HFP_AG_CODEC_CVSD`. + * If @kconfig{CONFIG_BT_HFP_AG_VOICE_RECG} is not enabled, + * the callback will not be notified. + * + * @param ag HFP AG object. + * @param activate Voice recognition activation/deactivation. + */ + void (*voice_recognition)(struct bt_hfp_ag *ag, bool activate); + + /** Ready to accept audio callback + * + * If this callback is provided it will be called whenever the + * HF is ready to accept audio. + * If the feature `Enhanced Voice Recognition Status` is supported + * by HF, the callback will be notified if the AT command `AT+BVRA=2` + * is received. The HF may send this value during an ongoing VR + * (Voice Recognition) session to terminate audio output from the + * AG (if there is any) and prepare the AG for new audio input. + * Or, the callback will be notified after the voice recognition + * is activated. + * If @kconfig{CONFIG_BT_HFP_AG_ENH_VOICE_RECG} is not enabled, + * the callback will not be notified. + * + * @param ag HFP AG object. + */ + void (*ready_to_accept_audio)(struct bt_hfp_ag *ag); }; /** @brief Register HFP AG profile @@ -522,6 +558,81 @@ int bt_hfp_ag_audio_connect(struct bt_hfp_ag *ag, uint8_t id); */ int bt_hfp_ag_inband_ringtone(struct bt_hfp_ag *ag, bool inband); +/** @brief Enable/disable the voice recognition function + * + * Enables/disables the voice recognition function. + * If @kconfig{CONFIG_BT_HFP_AG_VOICE_RECG} is not enabled, the error + * `-ENOTSUP` will be returned if the function called. + * + * @param ag HFP AG object. + * @param activate Activate/deactivate the voice recognition function. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_voice_recognition(struct bt_hfp_ag *ag, bool activate); + +/** @brief set voice recognition engine state + * + * It is used to set the voice recognition engine state. + * The unsolicited result code `+BVRA: 1,` will be sent. + * ``: Bitmask that reflects the current state of the voice + * recognition engine on the AG. + * Bit 0 - If it is 1, the AG is ready to accept audio input + * Bit 1 - If it is 1, the AG is sending audio to the HF + * Bit 2 - If it is 1, the AG is processing the audio input + * If @kconfig{CONFIG_BT_HFP_AG_ENH_VOICE_RECG} is not enabled, the error + * `-ENOTSUP` will be returned if the function called. + * + * @param ag HFP AG object. + * @param state The value of ``. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_vre_state(struct bt_hfp_ag *ag, uint8_t state); + +/** @brief set voice recognition engine state and textual representation + * + * It is used to set the voice recognition engine state with + * textual representation. + * unsolicited result code `+BVRA: 1,, + * ` will be sent. + * `` is same as parameter `state` of function + * `bt_hfp_ag_vre_state`. + * `: ,,, + * `. + * ``: Unique ID of the current text as a hexadecimal string + * (a maximum of 4 characters in length, but less than 4 characters + * in length is valid). + * ``: ID of the textType from the following list: + * 0 - Text recognized by the AG from the audio input provided by the HF + * 1 - Text of the audio output from the AG + * 2 - Text of the audio output from the AG that contains a question + * 3 - Text of the audio output from the AG that contains an error + * description + * ``: ID of the operation of the text + * 1 - NewText: Indicates that a new text started. Shall be used when the + * `` changes + * 2 - Replace: Replace any existing text with the same `` and + * same `` + * 3 - Append: Attach new text to existing text and keep the same + * `` and same `` + * ``: The `` parameter shall be a UTF-8 text string and + * shall always be contained within double quotes. + * If @kconfig{CONFIG_BT_HFP_AG_VOICE_RECG_TEXT} is not enabled, the error + * `-ENOTSUP` will be returned if the function called. + * + * @param ag HFP AG object. + * @param state The value of ``. + * @param id Value of ``. + * @param type Value of ``. + * @param operation Value of ``. + * @param text Value of ``. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_vre_textual_representation(struct bt_hfp_ag *ag, uint8_t state, const char *id, + uint8_t type, uint8_t operation, const char *text); + #ifdef __cplusplus } #endif diff --git a/subsys/bluetooth/host/classic/Kconfig b/subsys/bluetooth/host/classic/Kconfig index 40b5c2daf1f..526d11823b3 100644 --- a/subsys/bluetooth/host/classic/Kconfig +++ b/subsys/bluetooth/host/classic/Kconfig @@ -355,6 +355,24 @@ config BT_HFP_AG_RING_NOTIFY_INTERVAL help Ring notification interval if the call is in alert state. The unit is seconds. + +config BT_HFP_AG_VOICE_RECG + bool "Voice recognition activation for HFP AG [EXPERIMENTAL]" + help + This option enables Voice recognition activation for HFP AG + +config BT_HFP_AG_ENH_VOICE_RECG + bool "Enhanced Voice Recognition Status for HFP AG [EXPERIMENTAL]" + select BT_HFP_AG_VOICE_RECG + help + This option enables Enhanced Voice Recognition Status for HFP AG + +config BT_HFP_AG_VOICE_RECG_TEXT + bool "Voice Recognition Text for HFP AG [EXPERIMENTAL]" + select BT_HFP_AG_ENH_VOICE_RECG + help + This option enables Voice Recognition Text for HFP AG + endif # BT_HFP_AG config BT_AVDTP diff --git a/subsys/bluetooth/host/classic/hfp_ag.c b/subsys/bluetooth/host/classic/hfp_ag.c index 29a767e49dc..e09eeaa0e25 100644 --- a/subsys/bluetooth/host/classic/hfp_ag.c +++ b/subsys/bluetooth/host/classic/hfp_ag.c @@ -2831,6 +2831,118 @@ static int bt_hfp_ag_ccwa_handler(struct bt_hfp_ag *ag, struct net_buf *buf) return 0; } +static void bt_hfp_ag_vr_activate(struct bt_hfp_ag *ag, void *user_data) +{ + bool feature; + + hfp_ag_lock(ag); + feature = (ag->ag_features & BT_HFP_AG_FEATURE_ENH_VOICE_RECG) && + (ag->hf_features & BT_HFP_HF_FEATURE_ENH_VOICE_RECG); + hfp_ag_unlock(ag); + +#if defined(CONFIG_BT_HFP_AG_VOICE_RECG) + if (bt_ag && bt_ag->voice_recognition) { + bt_ag->voice_recognition(ag, true); + } else { + (void)bt_hfp_ag_audio_connect(ag, BT_HFP_AG_CODEC_CVSD); + } +#endif /* CONFIG_BT_HFP_AG_VOICE_RECG */ + + atomic_set_bit_to(ag->flags, BT_HFP_AG_VRE_R2A, !feature); + +#if defined(CONFIG_BT_HFP_AG_ENH_VOICE_RECG) + if (atomic_test_bit(ag->flags, BT_HFP_AG_VRE_R2A)) { + if (bt_ag && bt_ag->ready_to_accept_audio) { + bt_ag->ready_to_accept_audio(ag); + } + } +#endif /* CONFIG_BT_HFP_AG_ENH_VOICE_RECG */ +} + +static void bt_hfp_ag_vr_deactivate(struct bt_hfp_ag *ag, void *user_data) +{ +#if defined(CONFIG_BT_HFP_AG_ENH_VOICE_RECG) + if (bt_ag && bt_ag->voice_recognition) { + bt_ag->voice_recognition(ag, false); + } +#endif /* CONFIG_BT_HFP_AG_ENH_VOICE_RECG */ +} + +static void bt_hfp_ag_vr_ready2accept(struct bt_hfp_ag *ag, void *user_data) +{ + atomic_set_bit(ag->flags, BT_HFP_AG_VRE_R2A); + +#if defined(CONFIG_BT_HFP_AG_ENH_VOICE_RECG) + if (bt_ag && bt_ag->ready_to_accept_audio) { + bt_ag->ready_to_accept_audio(ag); + } +#endif /* CONFIG_BT_HFP_AG_ENH_VOICE_RECG */ +} + +static int bt_hfp_ag_bvra_handler(struct bt_hfp_ag *ag, struct net_buf *buf) +{ + int err; + uint32_t value; + + hfp_ag_lock(ag); + if (!((ag->ag_features & BT_HFP_AG_FEATURE_VOICE_RECG) && + (ag->hf_features & BT_HFP_HF_FEATURE_VOICE_RECG))) { + hfp_ag_unlock(ag); + return -EOPNOTSUPP; + } + hfp_ag_unlock(ag); + + if (!is_char(buf, '=')) { + return -ENOTSUP; + } + + err = get_number(buf, &value); + if (err != 0) { + return -ENOTSUP; + } + + if (!is_char(buf, '\r')) { + return -ENOTSUP; + } + + switch (value) { + case BT_HFP_BVRA_DEACTIVATION: + if (!atomic_test_and_clear_bit(ag->flags, BT_HFP_AG_VRE_ACTIVATE)) { + LOG_WRN("VR is not activated"); + return -ENOTSUP; + } + err = hfp_ag_next_step(ag, bt_hfp_ag_vr_deactivate, NULL); + break; + case BT_HFP_BVRA_ACTIVATION: + if (atomic_test_and_set_bit(ag->flags, BT_HFP_AG_VRE_ACTIVATE)) { + LOG_WRN("VR has been activated"); + return -ENOTSUP; + } + atomic_clear_bit(ag->flags, BT_HFP_AG_VRE_R2A); + err = hfp_ag_next_step(ag, bt_hfp_ag_vr_activate, NULL); + break; + case BT_HFP_BVRA_READY_TO_ACCEPT: + hfp_ag_lock(ag); + if (!((ag->ag_features & BT_HFP_AG_FEATURE_ENH_VOICE_RECG) && + (ag->hf_features & BT_HFP_HF_FEATURE_ENH_VOICE_RECG))) { + hfp_ag_unlock(ag); + LOG_WRN("Enhance voice recognition is not supported"); + return -EOPNOTSUPP; + } + hfp_ag_unlock(ag); + if (!atomic_test_bit(ag->flags, BT_HFP_AG_VRE_ACTIVATE)) { + LOG_WRN("Voice recognition is not activated"); + return -ENOTSUP; + } + err = hfp_ag_next_step(ag, bt_hfp_ag_vr_ready2accept, NULL); + break; + default: + return -ENOTSUP; + } + + return err; +} + static struct bt_hfp_ag_at_cmd_handler cmd_handlers[] = { {"AT+BRSF", bt_hfp_ag_brsf_handler}, {"AT+BAC", bt_hfp_ag_bac_handler}, {"AT+CIND", bt_hfp_ag_cind_handler}, {"AT+CMER", bt_hfp_ag_cmer_handler}, @@ -2843,6 +2955,7 @@ static struct bt_hfp_ag_at_cmd_handler cmd_handlers[] = { {"AT+CLIP", bt_hfp_ag_clip_handler}, {"AT+VGM", bt_hfp_ag_vgm_handler}, {"AT+VGS", bt_hfp_ag_vgs_handler}, {"AT+NREC", bt_hfp_ag_nrec_handler}, {"AT+BTRH", bt_hfp_ag_btrh_handler}, {"AT+CCWA", bt_hfp_ag_ccwa_handler}, + {"AT+BVRA", bt_hfp_ag_bvra_handler}, }; static void hfp_ag_connected(struct bt_rfcomm_dlc *dlc) @@ -4203,3 +4316,166 @@ int bt_hfp_ag_inband_ringtone(struct bt_hfp_ag *ag, bool inband) atomic_set_bit_to(ag->flags, BT_HFP_AG_INBAND_RING, inband); return 0; } + +int bt_hfp_ag_voice_recognition(struct bt_hfp_ag *ag, bool activate) +{ +#if defined(CONFIG_BT_HFP_AG_VOICE_RECG) + int err; + bool feature; + char *bvra; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + hfp_ag_lock(ag); + if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); + return -ENOTCONN; + } + hfp_ag_unlock(ag); + + if (activate && atomic_test_bit(ag->flags, BT_HFP_AG_VRE_ACTIVATE)) { + LOG_WRN("VR has been activated"); + return -ENOTSUP; + } else if (!activate && !atomic_test_bit(ag->flags, BT_HFP_AG_VRE_ACTIVATE)) { + LOG_WRN("VR is not activated"); + return -ENOTSUP; + } + + hfp_ag_lock(ag); + feature = (ag->ag_features & BT_HFP_AG_FEATURE_ENH_VOICE_RECG) && + (ag->hf_features & BT_HFP_HF_FEATURE_ENH_VOICE_RECG); + hfp_ag_unlock(ag); + + if (!feature) { + bvra = ""; + } else { + bvra = ",0"; + } + + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BVRA:%d%s\r\n", activate, bvra); + if (err) { + LOG_ERR("Fail to notify VR activation :(%d)", err); + return err; + } + + atomic_set_bit_to(ag->flags, BT_HFP_AG_VRE_ACTIVATE, activate); + atomic_clear_bit(ag->flags, BT_HFP_AG_VRE_R2A); + return 0; +#else + return -ENOTSUP; +#endif /* CONFIG_BT_HFP_AG_VOICE_RECG */ +} + +int bt_hfp_ag_vre_state(struct bt_hfp_ag *ag, uint8_t state) +{ +#if defined(CONFIG_BT_HFP_AG_ENH_VOICE_RECG) + int err; + bool feature; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + hfp_ag_lock(ag); + if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); + return -ENOTCONN; + } + hfp_ag_unlock(ag); + + if (!atomic_test_bit(ag->flags, BT_HFP_AG_VRE_ACTIVATE)) { + LOG_WRN("Voice Recognition is not activated"); + return -EINVAL; + } + + hfp_ag_lock(ag); + feature = (ag->ag_features & BT_HFP_AG_FEATURE_ENH_VOICE_RECG) && + (ag->hf_features & BT_HFP_HF_FEATURE_ENH_VOICE_RECG); + hfp_ag_unlock(ag); + if (!feature) { + return -ENOTSUP; + } + + if ((state & BT_HFP_BVRA_STATE_SEND_AUDIO) && + !atomic_test_bit(ag->flags, BT_HFP_AG_VRE_R2A)) { + LOG_ERR("HFP HF is not ready to accept audio input"); + return -EINVAL; + } + + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BVRA:1,%d\r\n", state); + if (err) { + LOG_ERR("Fail to send state of VRE :(%d)", err); + return err; + } + + return 0; +#else + return -ENOTSUP; +#endif /* CONFIG_BT_HFP_AG_ENH_VOICE_RECG */ +} + +int bt_hfp_ag_vre_textual_representation(struct bt_hfp_ag *ag, uint8_t state, const char *id, + uint8_t type, uint8_t operation, const char *text) +{ +#if defined(CONFIG_BT_HFP_AG_VOICE_RECG_TEXT) + int err; + bool feature; + + LOG_DBG(""); + + if (ag == NULL) { + return -EINVAL; + } + + hfp_ag_lock(ag); + if (ag->state != BT_HFP_CONNECTED) { + hfp_ag_unlock(ag); + return -ENOTCONN; + } + hfp_ag_unlock(ag); + + if (!atomic_test_bit(ag->flags, BT_HFP_AG_VRE_ACTIVATE)) { + LOG_WRN("Voice Recognition is not activated"); + return -EINVAL; + } + + hfp_ag_lock(ag); + feature = (ag->ag_features & BT_HFP_AG_FEATURE_ENH_VOICE_RECG) && + (ag->hf_features & BT_HFP_HF_FEATURE_ENH_VOICE_RECG); + hfp_ag_unlock(ag); + if (!feature) { + return -ENOTSUP; + } + + hfp_ag_lock(ag); + feature = (ag->ag_features & BT_HFP_AG_FEATURE_VOICE_RECG_TEXT) && + (ag->hf_features & BT_HFP_HF_FEATURE_VOICE_RECG_TEXT); + hfp_ag_unlock(ag); + if (!feature) { + return -ENOTSUP; + } + + if ((state & BT_HFP_BVRA_STATE_SEND_AUDIO) && + !atomic_test_bit(ag->flags, BT_HFP_AG_VRE_R2A)) { + LOG_ERR("HFP HF is not ready to accept audio input"); + return -EINVAL; + } + + err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BVRA:1,%d,%s,%d,%d,\"%s\"\r\n", + state, id, type, operation, text); + if (err) { + LOG_ERR("Fail to send state of VRE :(%d)", err); + return err; + } + + return 0; +#else + return -ENOTSUP; +#endif /* CONFIG_BT_HFP_AG_VOICE_RECG_TEXT */ +} diff --git a/subsys/bluetooth/host/classic/hfp_ag_internal.h b/subsys/bluetooth/host/classic/hfp_ag_internal.h index 9d23ef4e437..82c77489142 100644 --- a/subsys/bluetooth/host/classic/hfp_ag_internal.h +++ b/subsys/bluetooth/host/classic/hfp_ag_internal.h @@ -60,6 +60,30 @@ #define BT_HFP_AG_FEATURE_ECC_ENABLE 0 #endif /* CONFIG_BT_HFP_AG_ECC */ +#if defined(CONFIG_BT_HFP_AG_VOICE_RECG) +#define BT_HFP_AG_FEATURE_VOICE_RECG_ENABLE BT_HFP_AG_FEATURE_VOICE_RECG +#define BT_HFP_AG_SDP_FEATURE_VOICE_RECG_ENABLE BT_HFP_AG_SDP_FEATURE_VOICE_RECG +#else +#define BT_HFP_AG_FEATURE_VOICE_RECG_ENABLE 0 +#define BT_HFP_AG_SDP_FEATURE_VOICE_RECG_ENABLE 0 +#endif /* CONFIG_BT_HFP_AG_VOICE_RECG */ + +#if defined(CONFIG_BT_HFP_AG_ENH_VOICE_RECG) +#define BT_HFP_AG_FEATURE_ENH_VOICE_RECG_ENABLE BT_HFP_AG_FEATURE_ENH_VOICE_RECG +#define BT_HFP_AG_SDP_FEATURE_ENH_VOICE_RECG_ENABLE BT_HFP_AG_SDP_FEATURE_ENH_VOICE_RECG +#else +#define BT_HFP_AG_FEATURE_ENH_VOICE_RECG_ENABLE 0 +#define BT_HFP_AG_SDP_FEATURE_ENH_VOICE_RECG_ENABLE 0 +#endif /* CONFIG_BT_HFP_AG_ENH_VOICE_RECG */ + +#if defined(CONFIG_BT_HFP_AG_VOICE_RECG_TEXT) +#define BT_HFP_AG_FEATURE_VOICE_RECG_TEXT_ENABLE BT_HFP_AG_FEATURE_VOICE_RECG_TEXT +#define BT_HFP_AG_SDP_FEATURE_VOICE_RECG_TEXT_ENABLE BT_HFP_AG_SDP_FEATURE_VOICE_RECG_TEXT +#else +#define BT_HFP_AG_FEATURE_VOICE_RECG_TEXT_ENABLE 0 +#define BT_HFP_AG_SDP_FEATURE_VOICE_RECG_TEXT_ENABLE 0 +#endif /* CONFIG_BT_HFP_AG_VOICE_RECG_TEXT */ + /* HFP AG Supported features */ #define BT_HFP_AG_SUPPORTED_FEATURES (\ BT_HFP_AG_FEATURE_3WAY_CALL_ENABLE | \ @@ -68,13 +92,19 @@ BT_HFP_AG_FEATURE_CODEC_NEG_ENABLE | \ BT_HFP_AG_FEATURE_ECNR_ENABLE | \ BT_HFP_AG_FEATURE_ECS_ENABLE | \ - BT_HFP_AG_FEATURE_ECC_ENABLE) + BT_HFP_AG_FEATURE_ECC_ENABLE | \ + BT_HFP_AG_FEATURE_VOICE_RECG_ENABLE | \ + BT_HFP_AG_FEATURE_ENH_VOICE_RECG_ENABLE | \ + BT_HFP_AG_FEATURE_VOICE_RECG_TEXT_ENABLE) /* HFP AG Supported features in SDP */ #define BT_HFP_AG_SDP_SUPPORTED_FEATURES (\ BT_HFP_AG_SDP_FEATURE_3WAY_CALL_ENABLE | \ BT_HFP_AG_SDP_FEATURE_INBAND_RINGTONE | \ - BT_HFP_AG_SDP_FEATURE_ECNR_ENABLE) + BT_HFP_AG_SDP_FEATURE_ECNR_ENABLE | \ + BT_HFP_AG_SDP_FEATURE_VOICE_RECG_ENABLE | \ + BT_HFP_AG_SDP_FEATURE_ENH_VOICE_RECG_ENABLE | \ + BT_HFP_AG_SDP_FEATURE_VOICE_RECG_TEXT_ENABLE) /* bt_hfp_ag flags: the flags defined here represent HFP AG parameters */ enum { @@ -89,6 +119,8 @@ enum { BT_HFP_AG_CODEC_CHANGED, /* Codec Id Changed */ BT_HFP_AG_TX_ONGOING, /* TX is ongoing */ BT_HFP_AG_CREATING_SCO, /* SCO is creating */ + BT_HFP_AG_VRE_ACTIVATE, /* VRE is activated */ + BT_HFP_AG_VRE_R2A, /* HF is ready to accept audio */ /* Total number of flags - must be at the end of the enum */ BT_HFP_AG_NUM_FLAGS, diff --git a/subsys/bluetooth/host/classic/hfp_internal.h b/subsys/bluetooth/host/classic/hfp_internal.h index 31865931a24..c11652d565b 100644 --- a/subsys/bluetooth/host/classic/hfp_internal.h +++ b/subsys/bluetooth/host/classic/hfp_internal.h @@ -348,3 +348,11 @@ enum hfp_hf_ag_indicators { * less than 4 characters in length is valid. */ #define BT_HFP_BVRA_TEXT_ID_MAX_LEN 4 + +/* BVRA VRE state */ +/* BVRA VRE state: the AG is ready to accept audio input */ +#define BT_HFP_BVRA_STATE_ACCEPT_INPUT BIT(0) +/* BVRA VRE state: the AG is sending audio to the HF */ +#define BT_HFP_BVRA_STATE_SEND_AUDIO BIT(1) +/* BVRA VRE state: the AG is processing the audio input */ +#define BT_HFP_BVRA_STATE_PROCESS_AUDIO BIT(2)