hfp: send HFP_SUBEVENT_HF_INDICATOR event

This commit is contained in:
Milanka Ringwald 2021-07-13 17:56:19 +02:00
parent 3c439ac451
commit 347d46c839
6 changed files with 104 additions and 54 deletions

View File

@ -627,6 +627,19 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
report_status(status, "Echo Canceling and Noise Reduction Deactivate");
break;
case HFP_SUBEVENT_HF_INDICATOR:
switch (hfp_subevent_hf_indicator_get_uuid(event)){
case HFP_HF_INDICATOR_UUID_ENHANCED_SAFETY:
printf("Received ENHANCED SAFETY indicator, value %d\n", hfp_subevent_hf_indicator_get_value(event));
break;
case HFP_HF_INDICATOR_UUID_BATTERY_LEVEL:
printf("Received BATTERY LEVEL indicator, value %d\n", hfp_subevent_hf_indicator_get_value(event));
break;
default:
printf("Received HF INDICATOR indicator, UUID 0x%4X, value %d\n", hfp_subevent_hf_indicator_get_uuid(event), hfp_subevent_hf_indicator_get_value(event));
break;
}
break;
default:
break;
}

View File

@ -589,17 +589,12 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * even
printf("Voice Recognition command failed\n");
break;
}
switch(hfp_subevent_voice_recognition_status_get_state(event)){
case 0:
printf("\nVoice recognition status DEACTIVATED\n\n");
break;
case 1:
printf("\nVoice recognition status ACTIVATED\n\n");
break;
default:
btstack_assert(false);
break;
}
if (hfp_subevent_voice_recognition_status_get_state(event) > 0){
printf("\nVoice recognition status ACTIVATED\n\n");
} else {
printf("\nVoice recognition status DEACTIVATED\n\n");
}
break;
case HFP_SUBEVENT_ENHANCED_VOICE_RECOGNITION_HF_READY_FOR_AUDIO:

View File

@ -1842,6 +1842,15 @@ typedef uint8_t sm_key_t[16];
*/
#define HFP_SUBEVENT_ECHO_CANCELING_AND_NOISE_REDUCTION_DEACTIVATE 0x25
/**
* @format 1H21
* @param subevent_code
* @param acl_handle
* @param uuid
* @param value
*/
#define HFP_SUBEVENT_HF_INDICATOR 0x26
// ANCS Client

View File

@ -4914,6 +4914,34 @@ static inline uint8_t hfp_subevent_echo_canceling_and_noise_reduction_deactivate
return event[5];
}
/**
* @brief Get field acl_handle from event HFP_SUBEVENT_HF_INDICATOR
* @param event packet
* @return acl_handle
* @note: btstack_type H
*/
static inline hci_con_handle_t hfp_subevent_hf_indicator_get_acl_handle(const uint8_t * event){
return little_endian_read_16(event, 3);
}
/**
* @brief Get field uuid from event HFP_SUBEVENT_HF_INDICATOR
* @param event packet
* @return uuid
* @note: btstack_type 2
*/
static inline uint16_t hfp_subevent_hf_indicator_get_uuid(const uint8_t * event){
return little_endian_read_16(event, 5);
}
/**
* @brief Get field value from event HFP_SUBEVENT_HF_INDICATOR
* @param event packet
* @return value
* @note: btstack_type 1
*/
static inline uint8_t hfp_subevent_hf_indicator_get_value(const uint8_t * event){
return event[7];
}
#ifdef ENABLE_BLE
/**
* @brief Get field handle from event ANCS_SUBEVENT_CLIENT_CONNECTED

View File

@ -119,6 +119,8 @@ extern "C" {
#define HFP_MAX_VR_TEXT_SIZE 100
#define HFP_MAX_NETWORK_OPERATOR_NAME_SIZE 17
#define HFP_HF_INDICATOR_UUID_ENHANCED_SAFETY 0x0001 // 0 - disabled, 1 - enabled
#define HFP_HF_INDICATOR_UUID_BATTERY_LEVEL 0X0002 // 0-100 remaining level of battery
#define HFP_SUPPORTED_FEATURES "+BRSF"
#define HFP_AVAILABLE_CODECS "+BAC"
@ -589,11 +591,6 @@ typedef struct hfp_connection {
uint8_t ok_pending;
uint8_t send_error;
// track command
// in AG: track command for which ok/error response need to be sent
// in HF: track command for which ok/error response need to be received
hfp_command_t response_pending_for_command;
bool found_equal_sign;
uint8_t ignore_value;
@ -652,6 +649,9 @@ typedef struct hfp_connection {
int next_call_index;
// HF only
// HF: track command for which ok/error response need to be received
hfp_command_t response_pending_for_command;
hfp_hf_query_operator_state_t hf_query_operator_state;
uint8_t hf_answer_incoming_call;
uint8_t hf_initiate_outgoing_call;

View File

@ -828,6 +828,20 @@ static void hfp_ag_emit_enhanced_voice_recognition_msg_sent_event(hfp_connection
(*hfp_ag_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void hfp_ag_emit_hf_indicator_value_changed(hfp_connection_t * hfp_connection, uint16_t uuid, uint8_t value){
hci_con_handle_t acl_handle = (hfp_connection != NULL) ? hfp_connection->acl_handle : HCI_CON_HANDLE_INVALID;
uint8_t event[8];
event[0] = HCI_EVENT_HFP_META;
event[1] = sizeof(event) - 2;
event[2] = HFP_SUBEVENT_HF_INDICATOR;
little_endian_store_16(event, 3, acl_handle);
little_endian_store_16(event, 5, uuid);
event[7] = value;
(*hfp_ag_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static int hfp_ag_voice_recognition_state_machine(hfp_connection_t * hfp_connection){
if (hfp_connection->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) {
return 0;
@ -1893,20 +1907,8 @@ static void hfp_ag_send_call_status(hfp_connection_t * hfp_connection, int call_
send_str_over_rfcomm(hfp_connection->rfcomm_cid, buffer);
}
static void hfp_emit_event_for_command(hfp_connection_t * hfp_connection, uint8_t status){
switch(hfp_connection->response_pending_for_command){
case HFP_CMD_TURN_OFF_EC_AND_NR:
hfp_emit_event(hfp_connection, HFP_SUBEVENT_ECHO_CANCELING_AND_NOISE_REDUCTION_DEACTIVATE, status);
break;
default:
break;
}
}
// sends pending command, returns if command was sent
static int hfp_ag_send_commands(hfp_connection_t *hfp_connection){
hfp_connection->response_pending_for_command = HFP_CMD_NONE;
if (hfp_connection->send_status_of_current_calls){
hfp_connection->ok_pending = 0;
if (hfp_connection->next_call_index < hfp_gsm_get_number_of_calls()){
@ -1938,7 +1940,6 @@ static int hfp_ag_send_commands(hfp_connection_t *hfp_connection){
if (hfp_connection->send_error){
hfp_connection->send_error = 0;
hfp_connection->command = HFP_CMD_NONE;
hfp_emit_event_for_command(hfp_connection, ERROR_CODE_COMMAND_DISALLOWED);
hfp_ag_send_error(hfp_connection->rfcomm_cid);
return 1;
}
@ -1954,7 +1955,6 @@ static int hfp_ag_send_commands(hfp_connection_t *hfp_connection){
if (hfp_connection->ok_pending){
hfp_connection->ok_pending = 0;
hfp_connection->command = HFP_CMD_NONE;
hfp_emit_event_for_command(hfp_connection, ERROR_CODE_SUCCESS);
hfp_ag_send_ok(hfp_connection->rfcomm_cid);
return 1;
}
@ -2166,7 +2166,8 @@ static int hfp_parser_is_end_of_line(uint8_t byte){
static void hfp_ag_handle_rfcomm_data(hfp_connection_t * hfp_connection, uint8_t *packet, uint16_t size){
// assertion: size >= 1 as rfcomm.c does not deliver empty packets
if (size < 1) return;
uint8_t status = ERROR_CODE_SUCCESS;
hfp_log_rfcomm_message("HFP_AG_RX", packet, size);
#ifdef ENABLE_HFP_AT_MESSAGES
hfp_emit_string_event(hfp_connection, HFP_SUBEVENT_AT_MESSAGE_RECEIVED, (char *) packet);
@ -2209,32 +2210,34 @@ static void hfp_ag_handle_rfcomm_data(hfp_connection_t * hfp_connection, uint8_t
break;
case HFP_CMD_HF_INDICATOR_STATUS:
hfp_connection->command = HFP_CMD_NONE;
if (hfp_connection->parser_indicator_index < hfp_generic_status_indicators_nr){
indicator = &hfp_generic_status_indicators[hfp_connection->parser_indicator_index];
switch (indicator->uuid){
case HFP_HF_INDICATOR_UUID_ENHANCED_SAFETY:
if (hfp_connection->parser_indicator_value > 1) {
hfp_connection->send_error = 1;
break;
}
hfp_connection->ok_pending = 1;
hfp_ag_emit_hf_indicator_value_changed(hfp_connection, indicator->uuid, hfp_connection->parser_indicator_value);
break;
case HFP_HF_INDICATOR_UUID_BATTERY_LEVEL:
if (hfp_connection->parser_indicator_value > 100){
hfp_connection->send_error = 1;
break;
}
hfp_connection->ok_pending = 1;
hfp_ag_emit_hf_indicator_value_changed(hfp_connection, indicator->uuid, hfp_connection->parser_indicator_value);
break;
default:
hfp_connection->ok_pending = 1;
hfp_ag_emit_hf_indicator_value_changed(hfp_connection, indicator->uuid, hfp_connection->parser_indicator_value);
break;
}
} else {
hfp_connection->send_error = 1;
break;
}
switch (indicator->uuid){
case 1: // enhanced security
if (hfp_connection->parser_indicator_value > 1) {
hfp_connection->send_error = 1;
return;
}
log_info("HF Indicator 'enhanced security' set to %u", (unsigned int) hfp_connection->parser_indicator_value);
break;
case 2: // battery level
if (hfp_connection->parser_indicator_value > 100){
hfp_connection->send_error = 1;
return;
}
log_info("HF Indicator 'battery' set to %u", (unsigned int) hfp_connection->parser_indicator_value);
break;
default:
log_info("HF Indicator unknown set to %u", (unsigned int) hfp_connection->parser_indicator_value);
break;
}
hfp_connection->ok_pending = 1;
break;
case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS:
// expected by SLC state machine
@ -2270,14 +2273,16 @@ static void hfp_ag_handle_rfcomm_data(hfp_connection_t * hfp_connection, uint8_t
break;
case HFP_CMD_TURN_OFF_EC_AND_NR:
hfp_connection->command = HFP_CMD_NONE;
if (get_bit(hfp_supported_features, HFP_AGSF_EC_NR_FUNCTION)){
hfp_connection->ok_pending = 1;
hfp_supported_features = store_bit(hfp_supported_features, HFP_AGSF_EC_NR_FUNCTION, hfp_connection->ag_echo_and_noise_reduction);
log_info("AG: EC/NR = %u", hfp_connection->ag_echo_and_noise_reduction);
status = ERROR_CODE_SUCCESS;
} else {
hfp_connection->send_error = 1;
status = ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
}
hfp_connection->response_pending_for_command = HFP_CMD_TURN_OFF_EC_AND_NR;
hfp_emit_event(hfp_connection, HFP_SUBEVENT_ECHO_CANCELING_AND_NOISE_REDUCTION_DEACTIVATE, status);
break;
case HFP_CMD_CALL_ANSWERED:
hfp_connection->command = HFP_CMD_NONE;