mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-14 01:27:41 +00:00
Merge branch 'master' of https://github.com/bluekitchen/btstack
Conflicts: src/hfp.c src/hfp.h
This commit is contained in:
commit
62ccb98ad5
27
src/hfp.c
27
src/hfp.c
@ -694,6 +694,20 @@ static hfp_command_t parse_command(const char * line_buffer, int isHandsFree){
|
||||
return HFP_CMD_SUPPORTED_FEATURES;
|
||||
}
|
||||
|
||||
if (strncmp(line_buffer+offset, HFP_TRANSFER_HF_INDICATOR_STATUS, strlen(HFP_TRANSFER_HF_INDICATOR_STATUS)) == 0){
|
||||
return HFP_CMD_HF_INDICATOR_STATUS;
|
||||
}
|
||||
|
||||
if (strncmp(line_buffer+offset, HFP_RESPONSE_AND_HOLD, strlen(HFP_RESPONSE_AND_HOLD)) == 0){
|
||||
if (strncmp(line_buffer+strlen(HFP_RESPONSE_AND_HOLD)+offset, "?", 1) == 0){
|
||||
return HFP_CMD_RESPONSE_AND_HOLD_QUERY;
|
||||
}
|
||||
|
||||
if (strncmp(line_buffer+strlen(HFP_RESPONSE_AND_HOLD)+offset, "=", 1) == 0){
|
||||
return HFP_CMD_RESPONSE_AND_HOLD_COMMAND;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(line_buffer+offset, HFP_INDICATOR, strlen(HFP_INDICATOR)) == 0){
|
||||
if (strncmp(line_buffer+strlen(HFP_INDICATOR)+offset, "?", 1) == 0){
|
||||
return HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS;
|
||||
@ -851,12 +865,9 @@ static void hfp_parser_next_state(hfp_connection_t * context, uint8_t byte){
|
||||
case HFP_CMD_TRANSFER_AG_INDICATOR_STATUS:
|
||||
case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME:
|
||||
case HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT:
|
||||
context->parser_state = HFP_PARSER_SECOND_ITEM;
|
||||
break;
|
||||
case HFP_CMD_RETRIEVE_AG_INDICATORS:
|
||||
context->parser_state = HFP_PARSER_SECOND_ITEM;
|
||||
break;
|
||||
case HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE:
|
||||
case HFP_CMD_HF_INDICATOR_STATUS:
|
||||
context->parser_state = HFP_PARSER_SECOND_ITEM;
|
||||
break;
|
||||
default:
|
||||
@ -877,8 +888,6 @@ static void hfp_parser_next_state(hfp_connection_t * context, uint8_t byte){
|
||||
}
|
||||
|
||||
void hfp_parse(hfp_connection_t * context, uint8_t byte, int isHandsFree){
|
||||
int value;
|
||||
|
||||
// handle ATD<dial_string>;
|
||||
if (strncmp((const char*)context->line_buffer, HFP_CALL_PHONE_NUMBER, strlen(HFP_CALL_PHONE_NUMBER)) == 0){
|
||||
// check for end-of-line or ';'
|
||||
@ -1106,6 +1115,10 @@ static void parse_sequence(hfp_connection_t * context){
|
||||
log_info("Parsed List generic status indicator %s state: ", context->line_buffer);
|
||||
context->parser_item_index = (uint8_t)atoi((char*)context->line_buffer);
|
||||
break;
|
||||
case HFP_CMD_HF_INDICATOR_STATUS:
|
||||
context->parser_indicator_index = (uint8_t)atoi((char*)context->line_buffer);
|
||||
log_info("Parsed HF indicator index %u", context->parser_indicator_index);
|
||||
break;
|
||||
case HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE:
|
||||
// AG parses new gen. ind. state
|
||||
if (context->ignore_value){
|
||||
@ -1153,7 +1166,7 @@ static void parse_sequence(hfp_connection_t * context){
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hfp_init(uint16_t rfcomm_channel_nr){
|
||||
|
26
src/hfp.h
26
src/hfp.h
@ -114,6 +114,7 @@ extern "C" {
|
||||
#define HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES "+CHLD"
|
||||
#define HFP_GENERIC_STATUS_INDICATOR "+BIND"
|
||||
#define HFP_TRANSFER_AG_INDICATOR_STATUS "+CIEV" // +CIEV: <index>,<value>
|
||||
#define HFP_TRANSFER_HF_INDICATOR_STATUS "+BIEV" // +BIEC: <index>,<value>
|
||||
#define HFP_QUERY_OPERATOR_SELECTION "+COPS" // +COPS: <mode>,0,<opearator>
|
||||
#define HFP_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR "+CMEE"
|
||||
#define HFP_EXTENDED_AUDIO_GATEWAY_ERROR "+CME ERROR"
|
||||
@ -132,7 +133,7 @@ extern "C" {
|
||||
#define HFP_TRANSMIT_DTMF_CODES "+VTS"
|
||||
#define HFP_SUBSCRIBER_NUMBER_INFORMATION "+CNUM"
|
||||
#define HFP_LIST_CURRENT_CALLS "+CLCC"
|
||||
|
||||
#define HFP_RESPONSE_AND_HOLD "+BTRH"
|
||||
|
||||
#define HFP_OK "OK"
|
||||
#define HFP_ERROR "ERROR"
|
||||
@ -189,8 +190,10 @@ typedef enum {
|
||||
HFP_CMD_SET_MICROPHONE_GAIN,
|
||||
HFP_CMD_SET_SPEAKER_GAIN,
|
||||
HFP_CMD_GET_SUBSCRIBER_NUMBER_INFORMATION,
|
||||
HFP_CMD_LIST_CURRENT_CALLS
|
||||
|
||||
HFP_CMD_LIST_CURRENT_CALLS,
|
||||
HFP_CMD_RESPONSE_AND_HOLD_QUERY,
|
||||
HFP_CMD_RESPONSE_AND_HOLD_COMMAND,
|
||||
HFP_CMD_HF_INDICATOR_STATUS
|
||||
} hfp_command_t;
|
||||
|
||||
|
||||
@ -263,6 +266,12 @@ typedef enum {
|
||||
HFP_AG_TERMINATE_CALL_BY_AG,
|
||||
HFP_AG_TERMINATE_CALL_BY_HF,
|
||||
HFP_AG_CALL_DROPPED,
|
||||
HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG,
|
||||
HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_AG,
|
||||
HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG,
|
||||
HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF,
|
||||
HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF,
|
||||
HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF,
|
||||
} hfp_ag_call_event_t;
|
||||
|
||||
|
||||
@ -375,6 +384,12 @@ typedef enum{
|
||||
HFP_ENHANCED_CALL_MPTY_CONFERENCE_CALL
|
||||
} hfp_enhanced_call_mpty_t;
|
||||
|
||||
typedef enum {
|
||||
HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD = 0,
|
||||
HFP_RESPONSE_AND_HOLD_HELD_INCOMING_ACCEPTED,
|
||||
HFP_RESPONSE_AND_HOLD_HELD_INCOMING_REJECTED
|
||||
} hfp_response_and_hold_state_t;
|
||||
|
||||
typedef enum{
|
||||
HFP_NONE_SM,
|
||||
HFP_SLC_SM,
|
||||
@ -435,6 +450,7 @@ typedef struct hfp_connection {
|
||||
hfp_command_t command;
|
||||
hfp_parser_state_t parser_state;
|
||||
int parser_item_index;
|
||||
int parser_indicator_index;
|
||||
uint8_t line_buffer[HFP_MAX_INDICATOR_DESC_SIZE];
|
||||
int line_size;
|
||||
|
||||
@ -506,6 +522,10 @@ typedef struct hfp_connection {
|
||||
|
||||
uint8_t hf_answer_incoming_call;
|
||||
|
||||
int send_ag_status_indicators;
|
||||
int send_response_and_hold_active;
|
||||
int send_response_and_hold_status;
|
||||
|
||||
timer_source_t hfp_timeout;
|
||||
} hfp_connection_t;
|
||||
|
||||
|
225
src/hfp_ag.c
225
src/hfp_ag.c
@ -79,6 +79,8 @@ static hfp_callback_t hfp_callback;
|
||||
static hfp_call_status_t hfp_ag_call_state;
|
||||
static hfp_callsetup_status_t hfp_ag_callsetup_state;
|
||||
static hfp_callheld_status_t hfp_ag_callheld_state;
|
||||
static hfp_response_and_hold_state_t hfp_ag_response_and_hold_state;
|
||||
static int hfp_ag_response_and_hold_active = 0;
|
||||
|
||||
// CLIP feature
|
||||
static uint8_t clip_type; // 0 == not set
|
||||
@ -91,6 +93,7 @@ static int subscriber_numbers_count = 0;
|
||||
static void packet_handler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
static void hfp_run_for_context(hfp_connection_t *context);
|
||||
static void hfp_ag_setup_audio_connection(hfp_connection_t * connection);
|
||||
static void hfp_ag_hf_start_ringing(hfp_connection_t * context);
|
||||
|
||||
hfp_generic_status_indicator_t * get_hfp_generic_status_indicators();
|
||||
int get_hfp_generic_status_indicators_nr();
|
||||
@ -431,6 +434,12 @@ static int hfp_ag_set_microphone_gain_cmd(uint16_t cid, uint8_t gain){
|
||||
return send_str_over_rfcomm(cid, buffer);
|
||||
}
|
||||
|
||||
static int hfp_ag_set_response_and_hold(uint16_t cid, int state){
|
||||
char buffer[30];
|
||||
sprintf(buffer, "\r\n%s: %d\r\n", HFP_RESPONSE_AND_HOLD, state);
|
||||
return send_str_over_rfcomm(cid, buffer);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t hfp_ag_suggest_codec(hfp_connection_t *context){
|
||||
int i,j;
|
||||
@ -527,6 +536,11 @@ static void hfp_ag_slc_established(hfp_connection_t * context){
|
||||
if (hfp_ag_call_state == HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT){
|
||||
context->call_state = HFP_CALL_W4_AUDIO_CONNECTION_FOR_ACTIVE;
|
||||
}
|
||||
// if AG is ringing, also start ringing on the HF
|
||||
if (hfp_ag_call_state == HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS &&
|
||||
hfp_ag_callsetup_state == HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS){
|
||||
hfp_ag_hf_start_ringing(context);
|
||||
}
|
||||
}
|
||||
|
||||
static int hfp_ag_run_for_context_service_level_connection(hfp_connection_t * context){
|
||||
@ -585,10 +599,11 @@ static int hfp_ag_run_for_context_service_level_connection(hfp_connection_t * co
|
||||
if (context->state != HFP_W4_RETRIEVE_CAN_HOLD_CALL) break;
|
||||
if (has_hf_indicators_feature(context)){
|
||||
context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS;
|
||||
} else {
|
||||
hfp_ag_slc_established(context);
|
||||
}
|
||||
hfp_ag_retrieve_can_hold_call_cmd(context->rfcomm_cid);
|
||||
if (!has_hf_indicators_feature(context)){
|
||||
hfp_ag_slc_established(context);
|
||||
}
|
||||
return 1;
|
||||
|
||||
case HFP_CMD_LIST_GENERIC_STATUS_INDICATORS:
|
||||
@ -903,6 +918,7 @@ static void hfp_ag_trigger_terminate_call(void){
|
||||
if (connection->call_state == HFP_CALL_IDLE) continue;
|
||||
connection->call_state = HFP_CALL_IDLE;
|
||||
connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, call_indicator_index, 1);
|
||||
connection->release_audio_connection = 1;
|
||||
hfp_run_for_context(connection);
|
||||
}
|
||||
hfp_emit_event(hfp_callback, HFP_SUBEVENT_CALL_TERMINATED, 0);
|
||||
@ -956,6 +972,15 @@ static hfp_connection_t * hfp_ag_connection_for_call_state(hfp_call_state_t call
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void hfp_ag_send_response_and_hold_state(void){
|
||||
linked_list_iterator_t it;
|
||||
linked_list_iterator_init(&it, hfp_get_connections());
|
||||
while (linked_list_iterator_has_next(&it)){
|
||||
hfp_connection_t * connection = (hfp_connection_t *)linked_list_iterator_next(&it);
|
||||
connection->send_response_and_hold_status = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int call_setup_state_machine(hfp_connection_t * connection){
|
||||
int indicator_index;
|
||||
switch (connection->call_state){
|
||||
@ -1083,6 +1108,76 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect
|
||||
}
|
||||
break;
|
||||
|
||||
case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG:
|
||||
// clear CLIP
|
||||
clip_type = 0;
|
||||
switch (hfp_ag_call_state){
|
||||
case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS:
|
||||
switch (hfp_ag_callsetup_state){
|
||||
case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS:
|
||||
hfp_ag_response_and_hold_active = 1;
|
||||
hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD;
|
||||
hfp_ag_send_response_and_hold_state();
|
||||
// as with regualr call
|
||||
hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT);
|
||||
hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
|
||||
hfp_ag_ag_accept_call();
|
||||
printf("AG response and hold - hold by AG\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF:
|
||||
// clear CLIP
|
||||
clip_type = 0;
|
||||
switch (hfp_ag_call_state){
|
||||
case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS:
|
||||
switch (hfp_ag_callsetup_state){
|
||||
case HFP_CALLSETUP_STATUS_INCOMING_CALL_SETUP_IN_PROGRESS:
|
||||
hfp_ag_response_and_hold_active = 1;
|
||||
hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD;
|
||||
hfp_ag_send_response_and_hold_state();
|
||||
// as with regualr call
|
||||
hfp_ag_set_call_state(HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT);
|
||||
hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
|
||||
hfp_ag_hf_accept_call(connection);
|
||||
printf("AG response and hold - hold by HF\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_AG:
|
||||
case HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF:
|
||||
if (!hfp_ag_response_and_hold_active) break;
|
||||
if (hfp_ag_response_and_hold_state != HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD) break;
|
||||
hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_HELD_INCOMING_ACCEPTED;
|
||||
hfp_ag_send_response_and_hold_state();
|
||||
printf("Held Call accepted and active\n");
|
||||
break;
|
||||
|
||||
case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG:
|
||||
case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF:
|
||||
if (!hfp_ag_response_and_hold_active) break;
|
||||
if (hfp_ag_response_and_hold_state != HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD) break;
|
||||
hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_HELD_INCOMING_REJECTED;
|
||||
hfp_ag_send_response_and_hold_state();
|
||||
// from terminate by ag
|
||||
hfp_ag_set_call_state(HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS);
|
||||
hfp_ag_trigger_terminate_call();
|
||||
break;
|
||||
|
||||
case HFP_AG_TERMINATE_CALL_BY_HF:
|
||||
// clear CLIP
|
||||
clip_type = 0;
|
||||
@ -1158,6 +1253,10 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect
|
||||
hfp_ag_transfer_callsetup_state();
|
||||
break;
|
||||
case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT:
|
||||
if (hfp_ag_response_and_hold_active) {
|
||||
hfp_ag_response_and_hold_state = HFP_RESPONSE_AND_HOLD_HELD_INCOMING_REJECTED;
|
||||
hfp_ag_send_response_and_hold_state();
|
||||
}
|
||||
hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
|
||||
hfp_ag_set_call_state(HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS);
|
||||
hfp_ag_trigger_terminate_call();
|
||||
@ -1247,6 +1346,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect
|
||||
hfp_ag_transfer_callheld_state();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1269,13 +1369,6 @@ static void hfp_run_for_context(hfp_connection_t *context){
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->ok_pending){
|
||||
context->ok_pending = 0;
|
||||
context->command = HFP_CMD_NONE;
|
||||
hfp_ag_ok(context->rfcomm_cid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->send_error){
|
||||
context->send_error = 0;
|
||||
context->command = HFP_CMD_NONE;
|
||||
@ -1283,16 +1376,36 @@ static void hfp_run_for_context(hfp_connection_t *context){
|
||||
return;
|
||||
}
|
||||
|
||||
// note: before update AG indicators and ok_pending
|
||||
if (context->send_response_and_hold_status){
|
||||
context->send_response_and_hold_status = 0;
|
||||
hfp_ag_set_response_and_hold(context->rfcomm_cid, hfp_ag_response_and_hold_state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->send_response_and_hold_active){
|
||||
context->send_response_and_hold_active = 0;
|
||||
hfp_ag_set_response_and_hold(context->rfcomm_cid, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->ok_pending){
|
||||
context->ok_pending = 0;
|
||||
context->command = HFP_CMD_NONE;
|
||||
hfp_ag_ok(context->rfcomm_cid);
|
||||
return;
|
||||
}
|
||||
|
||||
// update AG indicators
|
||||
if (context->ag_indicators_status_update_bitmap){
|
||||
int i;
|
||||
for (i=0;i<context->ag_indicators_nr;i++){
|
||||
if (get_bit(context->ag_indicators_status_update_bitmap, i)){
|
||||
context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, i, 0);
|
||||
if (!context->enable_status_update_for_ag_indicators) {
|
||||
printf("+CMER:3,0,0,0 - not sending update for %s\n", hfp_ag_indicators[i].name);
|
||||
log_info("+CMER:3,0,0,0 - not sending update for '%s'", hfp_ag_indicators[i].name);
|
||||
break;
|
||||
}
|
||||
context->ag_indicators_status_update_bitmap = store_bit(context->ag_indicators_status_update_bitmap, i, 0);
|
||||
hfp_ag_transfer_ag_indicators_status_cmd(context->rfcomm_cid, &hfp_ag_indicators[i]);
|
||||
return;
|
||||
}
|
||||
@ -1347,6 +1460,12 @@ static void hfp_run_for_context(hfp_connection_t *context){
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->send_ag_status_indicators){
|
||||
context->send_ag_status_indicators = 0;
|
||||
hfp_ag_retrieve_indicators_cmd(context->rfcomm_cid, context);
|
||||
return;
|
||||
}
|
||||
|
||||
int done = hfp_ag_run_for_context_service_level_connection(context);
|
||||
if (!done){
|
||||
done = hfp_ag_run_for_context_service_level_connection_queries(context);
|
||||
@ -1375,6 +1494,16 @@ static void hfp_run_for_context(hfp_connection_t *context){
|
||||
context->command = HFP_CMD_NONE;
|
||||
}
|
||||
}
|
||||
static hfp_generic_status_indicator_t *get_hf_indicator_by_number(int number){
|
||||
int i;
|
||||
for (i=0;i< get_hfp_generic_status_indicators_nr();i++){
|
||||
hfp_generic_status_indicator_t * indicator = &get_hfp_generic_status_indicators()[i];
|
||||
if (indicator->uuid == number){
|
||||
return indicator;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
hfp_connection_t * context = get_hfp_connection_context_for_rfcomm_cid(channel);
|
||||
@ -1383,7 +1512,68 @@ static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_
|
||||
for (pos = 0; pos < size ; pos++){
|
||||
hfp_parse(context, packet[pos], 0);
|
||||
}
|
||||
hfp_generic_status_indicator_t * indicator;
|
||||
int value;
|
||||
switch(context->command){
|
||||
case HFP_CMD_RESPONSE_AND_HOLD_QUERY:
|
||||
if (hfp_ag_response_and_hold_active){
|
||||
context->send_response_and_hold_active = 1;
|
||||
}
|
||||
context->ok_pending = 1;
|
||||
break;
|
||||
case HFP_CMD_RESPONSE_AND_HOLD_COMMAND:
|
||||
value = atoi((char *)&context->line_buffer[0]);
|
||||
printf("HF Response and Hold: %u\n", value);
|
||||
switch(value){
|
||||
case HFP_RESPONSE_AND_HOLD_INCOMING_ON_HOLD:
|
||||
hfp_ag_call_sm(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_HF, context);
|
||||
break;
|
||||
case HFP_RESPONSE_AND_HOLD_HELD_INCOMING_ACCEPTED:
|
||||
hfp_ag_call_sm(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_HF, context);
|
||||
break;
|
||||
case HFP_RESPONSE_AND_HOLD_HELD_INCOMING_REJECTED:
|
||||
hfp_ag_call_sm(HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_HF, context);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
context->ok_pending = 1;
|
||||
break;
|
||||
case HFP_CMD_HF_INDICATOR_STATUS:
|
||||
context->command = HFP_CMD_NONE;
|
||||
// find indicator by assigned number
|
||||
indicator = get_hf_indicator_by_number(context->parser_indicator_index);
|
||||
if (!indicator){
|
||||
context->send_error = 1;
|
||||
break;
|
||||
}
|
||||
value = atoi((char *)&context->line_buffer[0]);
|
||||
switch (indicator->uuid){
|
||||
case 1: // enhanced security
|
||||
if (value > 1) {
|
||||
context->send_error = 1;
|
||||
return;
|
||||
}
|
||||
printf("HF Indicator 'enhanced security' set to %u\n", value);
|
||||
break;
|
||||
case 2: // battery level
|
||||
if (value > 100){
|
||||
context->send_error = 1;
|
||||
return;
|
||||
}
|
||||
printf("HF Indicator 'battery' set to %u\n", value);
|
||||
break;
|
||||
default:
|
||||
printf("HF Indicator unknown set to %u\n", value);
|
||||
break;
|
||||
}
|
||||
context->ok_pending = 1;
|
||||
break;
|
||||
case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS:
|
||||
// expected by SLC state machine
|
||||
if (context->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) break;
|
||||
context->send_ag_status_indicators = 1;
|
||||
break;
|
||||
case HFP_CMD_LIST_CURRENT_CALLS:
|
||||
context->command = HFP_CMD_NONE;
|
||||
context->send_status_of_current_calls = 1;
|
||||
@ -1726,6 +1916,19 @@ void hfp_ag_outgoing_call_rejected(void){
|
||||
void hfp_ag_outgoing_call_accepted(void){
|
||||
hfp_ag_call_sm(HFP_AG_OUTGOING_CALL_ACCEPTED, NULL);
|
||||
}
|
||||
|
||||
void hfp_ag_hold_incoming_call(void){
|
||||
hfp_ag_call_sm(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_INCOMING_CALL_BY_AG, NULL);
|
||||
}
|
||||
|
||||
void hfp_ag_accept_held_incoming_call(void) {
|
||||
hfp_ag_call_sm(HFP_AG_RESPONSE_AND_HOLD_ACCEPT_HELD_CALL_BY_AG, NULL);
|
||||
}
|
||||
|
||||
void hfp_ag_reject_held_incoming_call(void){
|
||||
hfp_ag_call_sm(HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG, NULL);
|
||||
}
|
||||
|
||||
static void hfp_ag_set_ag_indicator(const char * name, int value){
|
||||
int indicator_index = get_ag_indicator_index_for_name(name);
|
||||
if (indicator_index < 0) return;
|
||||
|
18
src/hfp_ag.h
18
src/hfp_ag.h
@ -287,8 +287,26 @@ void hfp_ag_send_current_call_status(bd_addr_t bd_addr, int idx, hfp_enhanced_ca
|
||||
hfp_enhanced_call_status_t status, hfp_enhanced_call_mode_t mode,
|
||||
hfp_enhanced_call_mpty_t mpty, uint8_t type, const char * number);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
void hfp_ag_send_current_call_status_done(bd_addr_t bd_addr);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
void hfp_ag_hold_incoming_call(void);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
void hfp_ag_accept_held_incoming_call(void);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*/
|
||||
void hfp_ag_reject_held_incoming_call(void);
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
|
@ -339,6 +339,9 @@ static void show_usage(void){
|
||||
printf("t - terminate connection\n");
|
||||
printf("u - join held call\n");
|
||||
printf("v - discover nearby HF units\n");
|
||||
printf("w - put incoming call on hold (Response and Hold)\n");
|
||||
printf("x - accept held incoming call (Response and Hold)\n");
|
||||
printf("X - reject held incoming call (Response and Hold)\n");
|
||||
|
||||
printf("---\n");
|
||||
printf("Ctrl-c - exit\n");
|
||||
@ -524,6 +527,18 @@ static int stdin_process(struct data_source *ds){
|
||||
case 'v':
|
||||
start_scan();
|
||||
break;
|
||||
case 'w':
|
||||
printf("AG: Put incoming call on hold (Response and Hold)\n");
|
||||
hfp_ag_hold_incoming_call();
|
||||
break;
|
||||
case 'x':
|
||||
printf("AG: Accept held incoming call (Response and Hold)\n");
|
||||
hfp_ag_accept_held_incoming_call();
|
||||
break;
|
||||
case 'X':
|
||||
printf("AG: Reject held incoming call (Response and Hold)\n");
|
||||
hfp_ag_reject_held_incoming_call();
|
||||
break;
|
||||
default:
|
||||
show_usage();
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user