Merge branch 'master' into ble-api-cleanup

This commit is contained in:
Matthias Ringwald 2015-12-18 15:31:55 +01:00
commit ad902e3d26
4 changed files with 139 additions and 30 deletions

View File

@ -993,6 +993,7 @@ void hfp_parse(hfp_connection_t * context, uint8_t byte, int isHandsFree){
context->command = HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS;
break;
case HFP_W4_RETRIEVE_INDICATORS:
context->send_ag_indicators_segment = 0;
context->command = HFP_CMD_RETRIEVE_AG_INDICATORS;
break;
default:

View File

@ -540,6 +540,7 @@ typedef struct hfp_connection {
uint8_t send_phone_number_for_voice_tag;
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, ..
// AG only

View File

@ -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);
}
static int hfp_ag_indicators_join(char * buffer, int buffer_size, hfp_connection_t * context){
if (buffer_size < get_hfp_ag_indicators_nr(context) * (1 + sizeof(hfp_ag_indicator_t))) return 0;
int i;
int offset = 0;
for (i = 0; i < get_hfp_ag_indicators_nr(context)-1; i++) {
offset += snprintf(buffer+offset, buffer_size-offset, "(\"%s\",(%d,%d)),",
// fast & small implementation for fixed int size
static int string_len_for_uint32(uint32_t i){
if (i < 10) return 1;
if (i < 100) return 2;
if (i < 1000) return 3;
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].min_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)){
offset += snprintf(buffer+offset, buffer_size-offset, "(\"%s\",(%d,%d))",
get_hfp_ag_indicators(context)[i].name,
get_hfp_ag_indicators(context)[i].min_range,
get_hfp_ag_indicators(context)[i].max_range);
index--;
int num_indicators = get_hfp_ag_indicators_nr(context);
int indicator_index = index >> 1;
if ((index & 1) == 0){
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){
@ -324,16 +383,35 @@ static int hfp_ag_call_services_join(char * buffer, int buffer_size){
return offset;
}
static int hfp_ag_retrieve_indicators_cmd(uint16_t cid, hfp_connection_t * context){
char buffer[250];
int offset = snprintf(buffer, sizeof(buffer), "\r\n%s:", HFP_INDICATOR);
offset += hfp_ag_indicators_join(buffer+offset, sizeof(buffer)-offset, context);
buffer[offset] = 0;
offset += snprintf(buffer+offset, sizeof(buffer)-offset, "\r\n\r\nOK\r\n");
buffer[offset] = 0;
return send_str_over_rfcomm(cid, buffer);
static int hfp_ag_cmd_via_generator(uint16_t cid, hfp_connection_t * context,
int start_segment, int num_segments,
int (*get_segment_len)(hfp_connection_t * context, int segment),
void (*store_segment) (hfp_connection_t * context, int segment, uint8_t * buffer)){
// 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;
}
// returns next segment to store
static int hfp_ag_retrieve_indicators_cmd_via_generator(uint16_t cid, hfp_connection_t * context, int start_segment){
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){
@ -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){
char buffer[100];
char buffer[40];
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);
@ -586,10 +664,21 @@ static int hfp_ag_run_for_context_service_level_connection(hfp_connection_t * co
return done;
case HFP_CMD_RETRIEVE_AG_INDICATORS:
if (context->state != HFP_W4_RETRIEVE_INDICATORS) break;
context->state = HFP_W4_RETRIEVE_INDICATORS_STATUS;
hfp_ag_retrieve_indicators_cmd(context->rfcomm_cid, context);
return 1;
if (context->state == HFP_W4_RETRIEVE_INDICATORS) {
context->command = HFP_CMD_NONE; // prevent reentrance
int next_segment = hfp_ag_retrieve_indicators_cmd_via_generator(context->rfcomm_cid, context, context->send_ag_indicators_segment);
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:
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){
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;
}
@ -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:
// expected by SLC state machine
if (context->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) break;
context->send_ag_indicators_segment = 0;
context->send_ag_status_indicators = 1;
break;
case HFP_CMD_LIST_CURRENT_CALLS:

View File

@ -66,6 +66,8 @@ static uint16_t rfcomm_payload_len = 0;
static uint8_t outgoing_rfcomm_payload[200];
static uint16_t outgoing_rfcomm_payload_len = 0;
static uint8_t rfcomm_reserved_buffer[1000];
void * active_connection;
hfp_connection_t * hfp_context;
@ -109,7 +111,8 @@ char * get_next_hfp_command(int start_command_offset, int end_command_offset){
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_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)){
}
int rfcomm_send_internal(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){
int start_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;
}
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(){
uint8_t event[19];
uint8_t pos = 0;