mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-29 04:20:20 +00:00
hfp: Response and Hold by AG
This commit is contained in:
parent
11a5c01e22
commit
3e2ef1ed5e
11
src/hfp.h
11
src/hfp.h
@ -266,6 +266,9 @@ typedef enum {
|
|||||||
HFP_AG_TERMINATE_CALL_BY_AG,
|
HFP_AG_TERMINATE_CALL_BY_AG,
|
||||||
HFP_AG_TERMINATE_CALL_BY_HF,
|
HFP_AG_TERMINATE_CALL_BY_HF,
|
||||||
HFP_AG_CALL_DROPPED,
|
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_call_event_t;
|
} hfp_ag_call_event_t;
|
||||||
|
|
||||||
|
|
||||||
@ -378,6 +381,12 @@ typedef enum{
|
|||||||
HFP_ENHANCED_CALL_MPTY_CONFERENCE_CALL
|
HFP_ENHANCED_CALL_MPTY_CONFERENCE_CALL
|
||||||
} hfp_enhanced_call_mpty_t;
|
} 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{
|
typedef enum{
|
||||||
HFP_NONE_SM,
|
HFP_NONE_SM,
|
||||||
HFP_SLC_SM,
|
HFP_SLC_SM,
|
||||||
@ -507,6 +516,8 @@ typedef struct hfp_connection {
|
|||||||
int send_status_of_current_calls;
|
int send_status_of_current_calls;
|
||||||
|
|
||||||
int send_ag_status_indicators;
|
int send_ag_status_indicators;
|
||||||
|
int send_response_and_hold_active;
|
||||||
|
int send_response_and_hold_status;
|
||||||
|
|
||||||
timer_source_t hfp_timeout;
|
timer_source_t hfp_timeout;
|
||||||
} hfp_connection_t;
|
} hfp_connection_t;
|
||||||
|
95
src/hfp_ag.c
95
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_call_status_t hfp_ag_call_state;
|
||||||
static hfp_callsetup_status_t hfp_ag_callsetup_state;
|
static hfp_callsetup_status_t hfp_ag_callsetup_state;
|
||||||
static hfp_callheld_status_t hfp_ag_callheld_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
|
// CLIP feature
|
||||||
static uint8_t clip_type; // 0 == not set
|
static uint8_t clip_type; // 0 == not set
|
||||||
@ -431,6 +433,12 @@ static int hfp_ag_set_microphone_gain_cmd(uint16_t cid, uint8_t gain){
|
|||||||
return send_str_over_rfcomm(cid, buffer);
|
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){
|
static uint8_t hfp_ag_suggest_codec(hfp_connection_t *context){
|
||||||
int i,j;
|
int i,j;
|
||||||
@ -956,6 +964,15 @@ static hfp_connection_t * hfp_ag_connection_for_call_state(hfp_call_state_t call
|
|||||||
return NULL;
|
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){
|
static int call_setup_state_machine(hfp_connection_t * connection){
|
||||||
int indicator_index;
|
int indicator_index;
|
||||||
switch (connection->call_state){
|
switch (connection->call_state){
|
||||||
@ -1083,6 +1100,48 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect
|
|||||||
}
|
}
|
||||||
break;
|
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_HELD_CALL_BY_AG:
|
||||||
|
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();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HFP_AG_RESPONSE_AND_HOLD_REJECT_HELD_CALL_BY_AG:
|
||||||
|
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:
|
case HFP_AG_TERMINATE_CALL_BY_HF:
|
||||||
// clear CLIP
|
// clear CLIP
|
||||||
clip_type = 0;
|
clip_type = 0;
|
||||||
@ -1247,6 +1306,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect
|
|||||||
hfp_ag_transfer_callheld_state();
|
hfp_ag_transfer_callheld_state();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1283,6 +1343,14 @@ static void hfp_run_for_context(hfp_connection_t *context){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// note: before update AG indicators in case of HFP_RESPONSE_AND_HOLD_HELD_INCOMING_REJECTED
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// update AG indicators
|
// update AG indicators
|
||||||
if (context->ag_indicators_status_update_bitmap){
|
if (context->ag_indicators_status_update_bitmap){
|
||||||
int i;
|
int i;
|
||||||
@ -1353,6 +1421,13 @@ static void hfp_run_for_context(hfp_connection_t *context){
|
|||||||
return;
|
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);
|
||||||
|
context->ok_pending = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int done = hfp_ag_run_for_context_service_level_connection(context);
|
int done = hfp_ag_run_for_context_service_level_connection(context);
|
||||||
if (!done){
|
if (!done){
|
||||||
done = hfp_ag_run_for_context_service_level_connection_queries(context);
|
done = hfp_ag_run_for_context_service_level_connection_queries(context);
|
||||||
@ -1402,6 +1477,13 @@ static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_
|
|||||||
hfp_generic_status_indicator_t * indicator;
|
hfp_generic_status_indicator_t * indicator;
|
||||||
int value;
|
int value;
|
||||||
switch(context->command){
|
switch(context->command){
|
||||||
|
case HFP_CMD_RESPONSE_AND_HOLD_QUERY:
|
||||||
|
if (hfp_ag_response_and_hold_active){
|
||||||
|
context->send_response_and_hold_active = 1;
|
||||||
|
} else {
|
||||||
|
context->ok_pending = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case HFP_CMD_HF_INDICATOR_STATUS:
|
case HFP_CMD_HF_INDICATOR_STATUS:
|
||||||
context->command = HFP_CMD_NONE;
|
context->command = HFP_CMD_NONE;
|
||||||
// find indicator by assigned number
|
// find indicator by assigned number
|
||||||
@ -1779,6 +1861,19 @@ void hfp_ag_outgoing_call_rejected(void){
|
|||||||
void hfp_ag_outgoing_call_accepted(void){
|
void hfp_ag_outgoing_call_accepted(void){
|
||||||
hfp_ag_call_sm(HFP_AG_OUTGOING_CALL_ACCEPTED, NULL);
|
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){
|
static void hfp_ag_set_ag_indicator(const char * name, int value){
|
||||||
int indicator_index = get_ag_indicator_index_for_name(name);
|
int indicator_index = get_ag_indicator_index_for_name(name);
|
||||||
if (indicator_index < 0) return;
|
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_status_t status, hfp_enhanced_call_mode_t mode,
|
||||||
hfp_enhanced_call_mpty_t mpty, uint8_t type, const char * number);
|
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);
|
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 */
|
/* API_END */
|
||||||
|
|
||||||
#if defined __cplusplus
|
#if defined __cplusplus
|
||||||
|
@ -339,6 +339,9 @@ static void show_usage(void){
|
|||||||
printf("t - terminate connection\n");
|
printf("t - terminate connection\n");
|
||||||
printf("u - join held call\n");
|
printf("u - join held call\n");
|
||||||
printf("v - discover nearby HF units\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("---\n");
|
||||||
printf("Ctrl-c - exit\n");
|
printf("Ctrl-c - exit\n");
|
||||||
@ -524,6 +527,18 @@ static int stdin_process(struct data_source *ds){
|
|||||||
case 'v':
|
case 'v':
|
||||||
start_scan();
|
start_scan();
|
||||||
break;
|
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:
|
default:
|
||||||
show_usage();
|
show_usage();
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user