mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-25 06:40:10 +00:00
fix ATA during wait for SCO. support CLIP
This commit is contained in:
parent
930ca5654e
commit
40a7976ab3
@ -671,6 +671,10 @@ static hfp_command_t parse_command(const char * line_buffer, int isHandsFree){
|
||||
return HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE;
|
||||
}
|
||||
|
||||
if (strncmp(line_buffer+offset, HFP_ENABLE_CLIP, strlen(HFP_ENABLE_CLIP)) == 0){
|
||||
return HFP_CMD_ENABLE_CLIP;
|
||||
}
|
||||
|
||||
if (strncmp(line_buffer+offset, HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES, strlen(HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES)) == 0){
|
||||
return HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES;
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ extern "C" {
|
||||
#define HFP_AVAILABLE_CODECS "+BAC"
|
||||
#define HFP_INDICATOR "+CIND"
|
||||
#define HFP_ENABLE_STATUS_UPDATE_FOR_AG_INDICATORS "+CMER"
|
||||
#define HFP_ENABLE_CLIP "+CLIP"
|
||||
#define HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS "+BIA" // +BIA:<enabled>,,<enabled>,,,<enabled>
|
||||
#define HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES "+CHLD"
|
||||
#define HFP_GENERIC_STATUS_INDICATOR "+BIND"
|
||||
@ -142,6 +143,7 @@ typedef enum {
|
||||
HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE,
|
||||
HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE,
|
||||
HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES,
|
||||
HFP_CMD_ENABLE_CLIP,
|
||||
|
||||
HFP_CMD_LIST_GENERIC_STATUS_INDICATORS,
|
||||
HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS,
|
||||
@ -401,6 +403,9 @@ typedef struct hfp_connection {
|
||||
// Retrieved during service level connection establishment, not used yet
|
||||
uint8_t negotiated_codec;
|
||||
|
||||
// HF -> AG configuration
|
||||
uint8_t clip_enabled;
|
||||
|
||||
// TODO: put these bit flags in a bitmap
|
||||
uint8_t ok_pending;
|
||||
// uint8_t send_ok;
|
||||
@ -424,6 +429,7 @@ typedef struct hfp_connection {
|
||||
uint8_t run_call_state_machine;
|
||||
uint8_t change_in_band_ring_tone_setting;
|
||||
uint8_t ag_ring;
|
||||
uint8_t ag_send_clip;
|
||||
|
||||
timer_source_t hfp_timeout;
|
||||
} hfp_connection_t;
|
||||
|
56
src/hfp_ag.c
56
src/hfp_ag.c
@ -80,6 +80,9 @@ 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;
|
||||
|
||||
// CLIP feature
|
||||
static uint8_t clip_type; // 0 == not set
|
||||
static char clip_number[25]; //
|
||||
|
||||
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);
|
||||
@ -204,6 +207,12 @@ static int hfp_ag_ring(uint16_t cid){
|
||||
return send_str_over_rfcomm(cid, (char *) "\r\nRING\r\n");
|
||||
}
|
||||
|
||||
static int hfp_ag_send_clip(uint16_t cid){
|
||||
char buffer[50];
|
||||
sprintf(buffer, "\r\n+CLIP: \"%s\",%u\r\n", clip_number, clip_type);
|
||||
return send_str_over_rfcomm(cid, buffer);
|
||||
}
|
||||
|
||||
static int hfp_ag_error(uint16_t cid){
|
||||
char buffer[10];
|
||||
sprintf(buffer, "\r\nERROR\r\n");
|
||||
@ -647,6 +656,7 @@ static void hfp_timeout_handler(timer_source_t * timer){
|
||||
|
||||
log_info("HFP start ring timeout, con handle 0x%02x", context->con_handle);
|
||||
context->ag_ring = 1;
|
||||
context->ag_send_clip = clip_type && context->clip_enabled;
|
||||
|
||||
run_loop_set_timer(&context->hfp_timeout, 2000); // 5 seconds timeout
|
||||
run_loop_add_timer(&context->hfp_timeout);
|
||||
@ -694,6 +704,7 @@ static int incoming_call_state_machine(hfp_connection_t * context){
|
||||
static void hfp_ag_hf_start_ringing(hfp_connection_t * context){
|
||||
hfp_timeout_start(context);
|
||||
context->ag_ring = 1;
|
||||
context->ag_send_clip = clip_type && context->clip_enabled;
|
||||
if (use_in_band_tone()){
|
||||
context->call_state = HFP_CALL_W4_AUDIO_CONNECTION_FOR_IN_BAND_RING;
|
||||
hfp_ag_establish_audio_connection(context->remote_addr);
|
||||
@ -705,6 +716,7 @@ static void hfp_ag_hf_start_ringing(hfp_connection_t * context){
|
||||
|
||||
static void hfp_ag_hf_stop_ringing(hfp_connection_t * context){
|
||||
context->ag_ring = 0;
|
||||
context->ag_send_clip = 0;
|
||||
hfp_timeout_stop(context);
|
||||
hfp_emit_event(hfp_callback, HFP_SUBEVENT_STOP_RINGINIG, 0);
|
||||
}
|
||||
@ -764,7 +776,8 @@ static void hfp_ag_hf_accept_call(hfp_connection_t * source){
|
||||
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);
|
||||
if (connection->call_state != HFP_CALL_RINGING) continue;
|
||||
if (connection->call_state != HFP_CALL_RINGING &&
|
||||
connection->call_state != HFP_CALL_W4_AUDIO_CONNECTION_FOR_IN_BAND_RING) continue;
|
||||
|
||||
hfp_ag_hf_stop_ringing(connection);
|
||||
connection->run_call_state_machine = 1;
|
||||
@ -786,7 +799,6 @@ static void hfp_ag_hf_accept_call(hfp_connection_t * source){
|
||||
connection->call_state = HFP_CALL_IDLE;
|
||||
}
|
||||
hfp_run_for_context(connection);
|
||||
break; // only single
|
||||
}
|
||||
}
|
||||
|
||||
@ -819,7 +831,8 @@ static void hfp_ag_trigger_reject_call(void){
|
||||
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);
|
||||
if (connection->call_state != HFP_CALL_RINGING) continue;
|
||||
if (connection->call_state != HFP_CALL_RINGING &&
|
||||
connection->call_state != HFP_CALL_W4_AUDIO_CONNECTION_FOR_IN_BAND_RING) continue;
|
||||
hfp_ag_hf_stop_ringing(connection);
|
||||
connection->ag_indicators_status_update_bitmap = store_bit(connection->ag_indicators_status_update_bitmap, callsetup_indicator_index, 1);
|
||||
connection->run_call_state_machine = 0;
|
||||
@ -897,6 +910,8 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect
|
||||
|
||||
break;
|
||||
case HFP_AG_INCOMING_CALL_ACCEPTED_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){
|
||||
@ -915,6 +930,8 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect
|
||||
}
|
||||
break;
|
||||
case HFP_AG_INCOMING_CALL_ACCEPTED_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){
|
||||
@ -934,6 +951,8 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect
|
||||
break;
|
||||
|
||||
case HFP_AG_TERMINATE_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){
|
||||
@ -962,6 +981,8 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect
|
||||
break;
|
||||
|
||||
case HFP_AG_TERMINATE_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){
|
||||
@ -984,6 +1005,8 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect
|
||||
}
|
||||
break;
|
||||
case HFP_AG_CALL_DROPPED:
|
||||
// clear CLIP
|
||||
clip_type = 0;
|
||||
switch (hfp_ag_call_state){
|
||||
case HFP_CALL_STATUS_ACTIVE_OR_HELD_CALL_IS_PRESENT:
|
||||
hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_NO_CALL_SETUP_IN_PROGRESS);
|
||||
@ -1040,6 +1063,7 @@ static void hfp_ag_call_sm(hfp_ag_call_event_t event, hfp_connection_t * connect
|
||||
hfp_ag_set_callsetup_state(HFP_CALLSETUP_STATUS_OUTGOING_CALL_SETUP_IN_ALERTING_STATE);
|
||||
hfp_ag_transfer_callsetup_state();
|
||||
break;
|
||||
|
||||
case HFP_AG_OUTGOING_CALL_ESTABLISHED:
|
||||
switch (hfp_ag_call_state){
|
||||
case HFP_CALL_STATUS_NO_HELD_OR_ACTIVE_CALLS:
|
||||
@ -1111,6 +1135,13 @@ static void hfp_run_for_context(hfp_connection_t *context){
|
||||
return;
|
||||
}
|
||||
|
||||
if (context->ag_send_clip){
|
||||
context->ag_send_clip = 0;
|
||||
context->command = HFP_CMD_NONE;
|
||||
hfp_ag_send_clip(context->rfcomm_cid);
|
||||
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);
|
||||
@ -1125,7 +1156,7 @@ static void hfp_run_for_context(hfp_connection_t *context){
|
||||
}
|
||||
|
||||
if (context->command == HFP_CMD_NONE && !done){
|
||||
log_info("context->command == HFP_CMD_NONE");
|
||||
// log_info("context->command == HFP_CMD_NONE");
|
||||
switch(context->state){
|
||||
case HFP_W2_DISCONNECT_RFCOMM:
|
||||
context->state = HFP_W4_RFCOMM_DISCONNECTED;
|
||||
@ -1150,6 +1181,7 @@ static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_
|
||||
switch(context->command){
|
||||
case HFP_CMD_CALL_ANSWERED:
|
||||
context->command = HFP_CMD_NONE;
|
||||
printf("HFP: ATA\n");
|
||||
hfp_ag_call_sm(HFP_AG_INCOMING_CALL_ACCEPTED_BY_HF, context);
|
||||
break;
|
||||
case HFP_CMD_HANG_UP_CALL:
|
||||
@ -1164,6 +1196,12 @@ static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_
|
||||
case HFP_CMD_REDIAL_LAST_NUMBER:
|
||||
context->command = HFP_CMD_NONE;
|
||||
hfp_ag_call_sm(HFP_AG_OUTGOING_REDIAL_INITIATED, context);
|
||||
case HFP_CMD_ENABLE_CLIP:
|
||||
context->command = HFP_CMD_NONE;
|
||||
context->clip_enabled = context->line_buffer[8] != '0';
|
||||
log_info("hfp: clip set, now: %u", context->clip_enabled);
|
||||
context->ok_pending = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1315,6 +1353,16 @@ void hfp_ag_incoming_call(void){
|
||||
hfp_ag_call_sm(HFP_AG_INCOMING_CALL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief number is stored.
|
||||
*/
|
||||
void hfp_ag_set_clip(uint8_t type, const char * number){
|
||||
clip_type = type;
|
||||
// copy and terminate
|
||||
strncpy(clip_number, number, sizeof(clip_number));
|
||||
clip_number[sizeof(clip_number)-1] = '\0';
|
||||
}
|
||||
|
||||
void hfp_ag_call_dropped(void){
|
||||
hfp_ag_call_sm(HFP_AG_CALL_DROPPED, NULL);
|
||||
}
|
||||
|
@ -175,6 +175,11 @@ void hfp_ag_set_use_in_band_ring_tone(int use_in_band_ring_tone);
|
||||
*/
|
||||
void hfp_ag_incoming_call(void);
|
||||
|
||||
/**
|
||||
* @brief number is stored.
|
||||
*/
|
||||
void hfp_ag_set_clip(uint8_t type, const char * number);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
|
@ -187,6 +187,7 @@ static int stdin_process(struct data_source *ds){
|
||||
break;
|
||||
case 'c':
|
||||
printf("Simulate incoming call\n");
|
||||
hfp_ag_set_clip(129, "1234567");
|
||||
hfp_ag_incoming_call();
|
||||
break;
|
||||
case 'C':
|
||||
@ -237,6 +238,14 @@ static int stdin_process(struct data_source *ds){
|
||||
printf("Set battery level to 5\n");
|
||||
hfp_ag_set_battery_level(5);
|
||||
break;
|
||||
case 'j':
|
||||
printf("Answering call on remote side\n");
|
||||
hfp_ag_outgoing_call_established();
|
||||
break;
|
||||
case 'r':
|
||||
printf("Disable in-band ring tone\n");
|
||||
hfp_ag_set_use_in_band_ring_tone(0);
|
||||
break;
|
||||
case 'k':
|
||||
printf("Memory 1 cleared\n");
|
||||
memory_1_enabled = 0;
|
||||
@ -253,14 +262,6 @@ static int stdin_process(struct data_source *ds){
|
||||
printf("Last dialed number set\n");
|
||||
last_number_exists = 1;
|
||||
break;
|
||||
case 'j':
|
||||
printf("Answering call on remote side\n");
|
||||
hfp_ag_outgoing_call_established();
|
||||
break;
|
||||
case 'r':
|
||||
printf("Disable in-band ring tone\n");
|
||||
hfp_ag_set_use_in_band_ring_tone(0);
|
||||
break;
|
||||
case 'R':
|
||||
printf("Enable in-band ring tone\n");
|
||||
hfp_ag_set_use_in_band_ring_tone(1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user