mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-18 14:42:33 +00:00
Merge branch 'master' into ble-api-cleanup
This commit is contained in:
commit
ad902e3d26
@ -993,6 +993,7 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte, int isHandsFree){
|
|||||||
context->command = HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS;
|
context->command = HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS;
|
||||||
break;
|
break;
|
||||||
case HFP_W4_RETRIEVE_INDICATORS:
|
case HFP_W4_RETRIEVE_INDICATORS:
|
||||||
|
context->send_ag_indicators_segment = 0;
|
||||||
context->command = HFP_CMD_RETRIEVE_AG_INDICATORS;
|
context->command = HFP_CMD_RETRIEVE_AG_INDICATORS;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -540,6 +540,7 @@ typedef struct hfp_connection {
|
|||||||
|
|
||||||
uint8_t send_phone_number_for_voice_tag;
|
uint8_t send_phone_number_for_voice_tag;
|
||||||
uint8_t send_ag_status_indicators;
|
uint8_t send_ag_status_indicators;
|
||||||
|
uint8_t send_ag_indicators_segment;
|
||||||
uint8_t send_response_and_hold_status; // 0 - don't send. BRTH:0 == 1, ..
|
uint8_t send_response_and_hold_status; // 0 - don't send. BRTH:0 == 1, ..
|
||||||
|
|
||||||
// AG only
|
// AG only
|
||||||
|
@ -256,23 +256,82 @@ static int hfp_ag_report_extended_audio_gateway_error(uint16_t cid, uint8_t erro
|
|||||||
return send_str_over_rfcomm(cid, buffer);
|
return send_str_over_rfcomm(cid, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hfp_ag_indicators_join(char * buffer, int buffer_size, hfp_connection_t * context){
|
// fast & small implementation for fixed int size
|
||||||
if (buffer_size < get_hfp_ag_indicators_nr(context) * (1 + sizeof(hfp_ag_indicator_t))) return 0;
|
static int string_len_for_uint32(uint32_t i){
|
||||||
int i;
|
if (i < 10) return 1;
|
||||||
int offset = 0;
|
if (i < 100) return 2;
|
||||||
for (i = 0; i < get_hfp_ag_indicators_nr(context)-1; i++) {
|
if (i < 1000) return 3;
|
||||||
offset += snprintf(buffer+offset, buffer_size-offset, "(\"%s\",(%d,%d)),",
|
if (i < 10000) return 4;
|
||||||
|
if (i < 10000) return 5;
|
||||||
|
if (i < 1000000) return 6;
|
||||||
|
if (i < 10000000) return 7;
|
||||||
|
if (i < 100000000) return 8;
|
||||||
|
if (i < 1000000000) return 9;
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get size for indicator string
|
||||||
|
static int hfp_ag_indicators_string_size(hfp_connection_t * context, int i){
|
||||||
|
// template: ("$NAME",($MIN,$MAX))
|
||||||
|
return 8 + strlen(get_hfp_ag_indicators(context)[i].name)
|
||||||
|
+ string_len_for_uint32(get_hfp_ag_indicators(context)[i].min_range)
|
||||||
|
+ string_len_for_uint32(get_hfp_ag_indicators(context)[i].min_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
// store indicator
|
||||||
|
static void hfp_ag_indicators_string_store(hfp_connection * context, int i, uint8_t * buffer){
|
||||||
|
sprintf((char *) buffer, "(\"%s\",(%d,%d)),",
|
||||||
get_hfp_ag_indicators(context)[i].name,
|
get_hfp_ag_indicators(context)[i].name,
|
||||||
get_hfp_ag_indicators(context)[i].min_range,
|
get_hfp_ag_indicators(context)[i].min_range,
|
||||||
get_hfp_ag_indicators(context)[i].max_range);
|
get_hfp_ag_indicators(context)[i].max_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
// structure: header [indicator [comma indicator]] footer
|
||||||
|
static int hfp_ag_indicators_cmd_generator_num_segments(hfp_connection_t * context){
|
||||||
|
int num_indicators = get_hfp_ag_indicators_nr(context);
|
||||||
|
if (!num_indicators) return 2;
|
||||||
|
return 3 + (num_indicators-1) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get size of individual segment for hfp_ag_retrieve_indicators_cmd
|
||||||
|
static int hfp_ag_indicators_cmd_generator_get_segment_len(hfp_connection_t * context, int index){
|
||||||
|
if (index == 0) {
|
||||||
|
return strlen(HFP_INDICATOR) + 3; // "\n\r%s:""
|
||||||
}
|
}
|
||||||
if ( i < get_hfp_ag_indicators_nr(context)){
|
index--;
|
||||||
offset += snprintf(buffer+offset, buffer_size-offset, "(\"%s\",(%d,%d))",
|
int num_indicators = get_hfp_ag_indicators_nr(context);
|
||||||
get_hfp_ag_indicators(context)[i].name,
|
int indicator_index = index >> 1;
|
||||||
get_hfp_ag_indicators(context)[i].min_range,
|
if ((index & 1) == 0){
|
||||||
get_hfp_ag_indicators(context)[i].max_range);
|
return hfp_ag_indicators_string_size(context, indicator_index);
|
||||||
}
|
}
|
||||||
return offset;
|
if (indicator_index == num_indicators - 1){
|
||||||
|
return 8; // "\r\n\r\nOK\r\n"
|
||||||
|
}
|
||||||
|
return 1; // comma
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hgp_ag_indicators_cmd_generator_store_segment(hfp_connection_t * context, int index, uint8_t * buffer){
|
||||||
|
if (index == 0){
|
||||||
|
*buffer++ = '\n';
|
||||||
|
*buffer++ = '\r';
|
||||||
|
int len = strlen(HFP_INDICATOR);
|
||||||
|
memcpy(buffer, HFP_INDICATOR, len);
|
||||||
|
buffer += len;
|
||||||
|
*buffer++ = ':';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index--;
|
||||||
|
int num_indicators = get_hfp_ag_indicators_nr(context);
|
||||||
|
int indicator_index = index >> 1;
|
||||||
|
if ((index & 1) == 0){
|
||||||
|
hfp_ag_indicators_string_store(context, indicator_index, buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (indicator_index == num_indicators-1){
|
||||||
|
memcpy(buffer, "\r\n\r\nOK\r\n", 8);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*buffer = ',';
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hfp_hf_indicators_join(char * buffer, int buffer_size){
|
static int hfp_hf_indicators_join(char * buffer, int buffer_size){
|
||||||
@ -324,16 +383,35 @@ static int hfp_ag_call_services_join(char * buffer, int buffer_size){
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hfp_ag_retrieve_indicators_cmd(uint16_t cid, hfp_connection_t * context){
|
static int hfp_ag_cmd_via_generator(uint16_t cid, hfp_connection_t * context,
|
||||||
char buffer[250];
|
int start_segment, int num_segments,
|
||||||
int offset = snprintf(buffer, sizeof(buffer), "\r\n%s:", HFP_INDICATOR);
|
int (*get_segment_len)(hfp_connection_t * context, int segment),
|
||||||
offset += hfp_ag_indicators_join(buffer+offset, sizeof(buffer)-offset, context);
|
void (*store_segment) (hfp_connection_t * context, int segment, uint8_t * buffer)){
|
||||||
|
|
||||||
buffer[offset] = 0;
|
// assumes: can send now == true
|
||||||
|
// assumes: num segments > 0
|
||||||
|
rfcomm_reserve_packet_buffer();
|
||||||
|
int mtu = rfcomm_get_max_frame_size(cid);
|
||||||
|
uint8_t * data = rfcomm_get_outgoing_buffer();
|
||||||
|
int offset = 0;
|
||||||
|
int segment = start_segment;
|
||||||
|
while (segment < num_segments){
|
||||||
|
int segment_len = get_segment_len(context, segment);
|
||||||
|
if (offset + segment_len <= mtu){
|
||||||
|
store_segment(context, segment, data+offset);
|
||||||
|
offset += segment_len;
|
||||||
|
segment++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rfcomm_send_prepared(cid, offset);
|
||||||
|
return segment;
|
||||||
|
}
|
||||||
|
|
||||||
offset += snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n\r\nOK\r\n");
|
// returns next segment to store
|
||||||
buffer[offset] = 0;
|
static int hfp_ag_retrieve_indicators_cmd_via_generator(uint16_t cid, hfp_connection_t * context, int start_segment){
|
||||||
return send_str_over_rfcomm(cid, buffer);
|
int num_segments = hfp_ag_indicators_cmd_generator_num_segments(context);
|
||||||
|
return hfp_ag_cmd_via_generator(cid, context, start_segment, num_segments,
|
||||||
|
hfp_ag_indicators_cmd_generator_get_segment_len, hgp_ag_indicators_cmd_generator_store_segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hfp_ag_retrieve_indicators_status_cmd(uint16_t cid){
|
static int hfp_ag_retrieve_indicators_status_cmd(uint16_t cid){
|
||||||
@ -355,7 +433,7 @@ static int hfp_ag_set_indicator_status_update_cmd(uint16_t cid, uint8_t activate
|
|||||||
|
|
||||||
|
|
||||||
static int hfp_ag_retrieve_can_hold_call_cmd(uint16_t cid){
|
static int hfp_ag_retrieve_can_hold_call_cmd(uint16_t cid){
|
||||||
char buffer[100];
|
char buffer[40];
|
||||||
int offset = snprintf(buffer, sizeof(buffer), "\r\n%s:", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES);
|
int offset = snprintf(buffer, sizeof(buffer), "\r\n%s:", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES);
|
||||||
offset += hfp_ag_call_services_join(buffer+offset, sizeof(buffer)-offset);
|
offset += hfp_ag_call_services_join(buffer+offset, sizeof(buffer)-offset);
|
||||||
|
|
||||||
@ -586,10 +664,21 @@ static int hfp_ag_run_for_context_service_level_connection(hfp_connection_t * co
|
|||||||
return done;
|
return done;
|
||||||
|
|
||||||
case HFP_CMD_RETRIEVE_AG_INDICATORS:
|
case HFP_CMD_RETRIEVE_AG_INDICATORS:
|
||||||
if (context->state != HFP_W4_RETRIEVE_INDICATORS) break;
|
if (context->state == HFP_W4_RETRIEVE_INDICATORS) {
|
||||||
context->state = HFP_W4_RETRIEVE_INDICATORS_STATUS;
|
context->command = HFP_CMD_NONE; // prevent reentrance
|
||||||
hfp_ag_retrieve_indicators_cmd(context->rfcomm_cid, context);
|
int next_segment = hfp_ag_retrieve_indicators_cmd_via_generator(context->rfcomm_cid, context, context->send_ag_indicators_segment);
|
||||||
return 1;
|
if (next_segment < hfp_ag_indicators_cmd_generator_num_segments(context)){
|
||||||
|
// prepare sending of next segment
|
||||||
|
context->send_ag_indicators_segment = next_segment;
|
||||||
|
context->command = HFP_CMD_RETRIEVE_AG_INDICATORS;
|
||||||
|
} else {
|
||||||
|
// done, go to next state
|
||||||
|
context->send_ag_indicators_segment = 0;
|
||||||
|
context->state = HFP_W4_RETRIEVE_INDICATORS_STATUS;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS:
|
case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS:
|
||||||
if (context->state != HFP_W4_RETRIEVE_INDICATORS_STATUS) break;
|
if (context->state != HFP_W4_RETRIEVE_INDICATORS_STATUS) break;
|
||||||
@ -1477,7 +1566,7 @@ static void hfp_run_for_context(hfp_connection_t *context){
|
|||||||
|
|
||||||
if (context->send_ag_status_indicators){
|
if (context->send_ag_status_indicators){
|
||||||
context->send_ag_status_indicators = 0;
|
context->send_ag_status_indicators = 0;
|
||||||
hfp_ag_retrieve_indicators_cmd(context->rfcomm_cid, context);
|
hfp_ag_retrieve_indicators_status_cmd(context->rfcomm_cid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1593,6 +1682,7 @@ static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_
|
|||||||
case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS:
|
case HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS:
|
||||||
// expected by SLC state machine
|
// expected by SLC state machine
|
||||||
if (context->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) break;
|
if (context->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) break;
|
||||||
|
context->send_ag_indicators_segment = 0;
|
||||||
context->send_ag_status_indicators = 1;
|
context->send_ag_status_indicators = 1;
|
||||||
break;
|
break;
|
||||||
case HFP_CMD_LIST_CURRENT_CALLS:
|
case HFP_CMD_LIST_CURRENT_CALLS:
|
||||||
|
@ -66,6 +66,8 @@ static uint16_t rfcomm_payload_len = 0;
|
|||||||
static uint8_t outgoing_rfcomm_payload[200];
|
static uint8_t outgoing_rfcomm_payload[200];
|
||||||
static uint16_t outgoing_rfcomm_payload_len = 0;
|
static uint16_t outgoing_rfcomm_payload_len = 0;
|
||||||
|
|
||||||
|
static uint8_t rfcomm_reserved_buffer[1000];
|
||||||
|
|
||||||
void * active_connection;
|
void * active_connection;
|
||||||
hfp_connection_t * hfp_context;
|
hfp_connection_t * hfp_context;
|
||||||
|
|
||||||
@ -109,7 +111,8 @@ char * get_next_hfp_command(int start_command_offset, int end_command_offset){
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_without_newlines(uint8_t *data, uint16_t len){
|
void print_without_newlines(uint8_t *data, uint16_t len);
|
||||||
|
void print_without_newlines(uint8_t *data, uint16_t len){
|
||||||
int found_newline = 0;
|
int found_newline = 0;
|
||||||
int found_item = 0;
|
int found_item = 0;
|
||||||
|
|
||||||
@ -131,7 +134,6 @@ extern "C" void l2cap_init(void){}
|
|||||||
extern "C" void l2cap_register_packet_handler(void (*handler)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)){
|
extern "C" void l2cap_register_packet_handler(void (*handler)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int rfcomm_send_internal(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){
|
int rfcomm_send_internal(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){
|
||||||
int start_command_offset = 2;
|
int start_command_offset = 2;
|
||||||
int end_command_offset = 2;
|
int end_command_offset = 2;
|
||||||
@ -155,6 +157,21 @@ int rfcomm_send_internal(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rfcomm_reserve_packet_buffer(void){
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
void rfcomm_release_packet_buffer(void){};
|
||||||
|
uint8_t * rfcomm_get_outgoing_buffer(void) {
|
||||||
|
return rfcomm_reserved_buffer;
|
||||||
|
}
|
||||||
|
uint16_t rfcomm_get_max_frame_size(uint16_t rfcomm_cid){
|
||||||
|
return sizeof(rfcomm_reserved_buffer);
|
||||||
|
}
|
||||||
|
int rfcomm_send_prepared(uint16_t rfcomm_cid, uint16_t len){
|
||||||
|
printf("--- rfcomm_send_prepared with len %u ---\n", len);
|
||||||
|
return rfcomm_send_internal(rfcomm_cid, rfcomm_reserved_buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
static void hci_event_sco_complete(){
|
static void hci_event_sco_complete(){
|
||||||
uint8_t event[19];
|
uint8_t event[19];
|
||||||
uint8_t pos = 0;
|
uint8_t pos = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user