mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-19 16:21:06 +00:00
avrcp controller: use max num fragments to limit num fragments that the controller can accept
This commit is contained in:
parent
864d08b05a
commit
8b2b40348d
@ -373,6 +373,7 @@ static avrcp_connection_t * avrcp_create_connection(bd_addr_t remote_addr, avrcp
|
||||
memset(connection, 0, sizeof(avrcp_connection_t));
|
||||
connection->state = AVCTP_CONNECTION_IDLE;
|
||||
connection->transaction_label = 0xFF;
|
||||
connection->max_num_fragments = 0xFF;
|
||||
connection->avrcp_cid = avrcp_get_next_cid();
|
||||
memcpy(connection->remote_addr, remote_addr, 6);
|
||||
btstack_linked_list_add(&context->connections, (btstack_linked_item_t *) connection);
|
||||
|
@ -55,7 +55,7 @@ extern "C" {
|
||||
|
||||
#define BT_SIG_COMPANY_ID 0x001958
|
||||
#define AVRCP_MEDIA_ATTR_COUNT 7
|
||||
#define AVRCP_MAX_ATTRIBUTTE_SIZE 100
|
||||
#define AVRCP_MAX_ATTRIBUTTE_SIZE 5000
|
||||
#define AVRCP_ATTRIBUTE_HEADER_LEN 8
|
||||
#define AVRCP_MAX_FOLDER_NAME_SIZE 20
|
||||
|
||||
@ -285,10 +285,9 @@ typedef struct {
|
||||
} avrcp_track_t;
|
||||
|
||||
typedef enum {
|
||||
AVRCP_PARSER_IDLE = 0,
|
||||
AVRCP_PARSER_GET_ATTRIBUTE_HEADER, // 8 bytes
|
||||
AVRCP_PARSER_GET_ATTRIBUTE_HEADER = 0, // 8 bytes
|
||||
AVRCP_PARSER_GET_ATTRIBUTE_VALUE,
|
||||
AVRCP_PARSER_IGNORE_ATTRIBUTE_VALUE
|
||||
AVRCP_PARSER_CONTINUE_GET_ATTRIBUTE_VALUE
|
||||
} avrcp_parser_state_t;
|
||||
|
||||
// BROWSING
|
||||
@ -342,7 +341,7 @@ typedef struct {
|
||||
uint8_t item_type;
|
||||
uint16_t item_length;
|
||||
uint16_t fragment_size;
|
||||
uint8_t fragment[100];
|
||||
uint8_t fragment[AVRCP_MAX_ATTRIBUTTE_SIZE];
|
||||
} avrcp_browsing_connection_t;
|
||||
// BROWSING END
|
||||
|
||||
@ -422,6 +421,10 @@ typedef struct {
|
||||
|
||||
uint8_t num_attributes;
|
||||
uint8_t num_parsed_attributes;
|
||||
|
||||
// PTS requires definition of max num fragments
|
||||
uint8_t max_num_fragments;
|
||||
uint8_t num_received_fragments;
|
||||
} avrcp_connection_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -215,7 +215,8 @@ static void avrcp_parser_reset(avrcp_connection_t * connection){
|
||||
connection->num_attributes = 0;
|
||||
connection->num_parsed_attributes = 0;
|
||||
connection->parser_attribute_header_pos = 0;
|
||||
connection->parser_state = AVRCP_PARSER_IDLE;
|
||||
connection->num_received_fragments = 0;
|
||||
connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER;
|
||||
}
|
||||
|
||||
static void avrcp_controller_emit_now_playing_info_event_done(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t ctype, uint8_t status){
|
||||
@ -301,23 +302,24 @@ static void avrcp_controller_emit_now_playing_info_event(btstack_packet_handler_
|
||||
|
||||
static void avrcp_parser_process_byte(uint8_t byte, avrcp_connection_t * connection, avrcp_command_type_t ctype){
|
||||
switch(connection->parser_state){
|
||||
case AVRCP_PARSER_GET_ATTRIBUTE_HEADER:
|
||||
case AVRCP_PARSER_GET_ATTRIBUTE_HEADER:{
|
||||
if (connection->parser_attribute_header_pos < AVRCP_ATTRIBUTE_HEADER_LEN) {
|
||||
connection->parser_attribute_header[connection->parser_attribute_header_pos++] = byte;
|
||||
connection->list_offset++;
|
||||
break;
|
||||
}
|
||||
connection->attribute_value_len = btstack_min(big_endian_read_16(connection->parser_attribute_header, 6), AVRCP_MAX_ATTRIBUTTE_SIZE );
|
||||
// printf(" attr id %d, len to read %d, total len %d \n", big_endian_read_32(connection->parser_attribute_header, 0), connection->attribute_value_len, big_endian_read_16(connection->parser_attribute_header, 6));
|
||||
uint16_t attribute_total_value_len = big_endian_read_16(connection->parser_attribute_header, 6);
|
||||
connection->attribute_value_len = btstack_min(attribute_total_value_len, AVRCP_MAX_ATTRIBUTTE_SIZE);
|
||||
connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_VALUE;
|
||||
break;
|
||||
}
|
||||
case AVRCP_PARSER_GET_ATTRIBUTE_VALUE:{
|
||||
if (connection->attribute_value_offset < connection->attribute_value_len){
|
||||
connection->attribute_value[connection->attribute_value_offset++] = byte;
|
||||
connection->list_offset++;
|
||||
break;
|
||||
}
|
||||
// TODO emit event
|
||||
|
||||
uint32_t attribute_id = big_endian_read_32(connection->parser_attribute_header, 0);
|
||||
if (attribute_id > AVRCP_MEDIA_ATTR_NONE && attribute_id <= AVRCP_MEDIA_ATTR_SONG_LENGTH_MS){
|
||||
avrcp_controller_emit_now_playing_info_event(avrcp_controller_context.avrcp_callback, connection->avrcp_cid, ctype, attribute_id, connection->attribute_value, connection->attribute_value_len);
|
||||
@ -325,7 +327,7 @@ static void avrcp_parser_process_byte(uint8_t byte, avrcp_connection_t * connect
|
||||
|
||||
if (connection->attribute_value_offset < big_endian_read_16(connection->parser_attribute_header, 6)){
|
||||
// printf("parse until end of valuE, and ignore it\n");
|
||||
connection->parser_state = AVRCP_PARSER_IGNORE_ATTRIBUTE_VALUE;
|
||||
connection->parser_state = AVRCP_PARSER_CONTINUE_GET_ATTRIBUTE_VALUE;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -339,7 +341,7 @@ static void avrcp_parser_process_byte(uint8_t byte, avrcp_connection_t * connect
|
||||
connection->parser_attribute_header_pos = 0;
|
||||
break;
|
||||
}
|
||||
case AVRCP_PARSER_IGNORE_ATTRIBUTE_VALUE:
|
||||
case AVRCP_PARSER_CONTINUE_GET_ATTRIBUTE_VALUE:
|
||||
if (connection->attribute_value_offset < big_endian_read_16(connection->parser_attribute_header, 6)){
|
||||
connection->list_offset++;
|
||||
connection->attribute_value_offset++;
|
||||
@ -708,24 +710,27 @@ static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connec
|
||||
avrcp_parser_reset(connection);
|
||||
connection->list_size = param_length;
|
||||
connection->num_attributes = packet[pos++];
|
||||
|
||||
// printf("AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES num_attributes %d, total size %d, packet type 0x%02x \n", connection->num_attributes, connection->list_size, operands[4] & 0x03);
|
||||
connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER;
|
||||
avrcp_source_parse_and_emit_element_attrs(packet+pos, size-pos, connection, ctype);
|
||||
|
||||
if (packet_type == AVRCP_START_PACKET){
|
||||
if (connection->num_attributes == 1 && connection->parser_state == AVRCP_PARSER_IGNORE_ATTRIBUTE_VALUE){
|
||||
avrcp_controller_request_abort_continuation(connection);
|
||||
} else {
|
||||
avrcp_controller_request_continue_response(connection);
|
||||
}
|
||||
avrcp_controller_request_continue_response(connection);
|
||||
}
|
||||
break;
|
||||
case AVRCP_CONTINUE_PACKET:
|
||||
avrcp_source_parse_and_emit_element_attrs(packet+pos, size-pos, connection, ctype);
|
||||
avrcp_controller_request_continue_response(connection);
|
||||
break;
|
||||
case AVRCP_END_PACKET:
|
||||
avrcp_source_parse_and_emit_element_attrs(packet+pos, size-pos, connection, ctype);
|
||||
connection->num_received_fragments++;
|
||||
if (connection->num_received_fragments < connection->max_num_fragments){
|
||||
avrcp_source_parse_and_emit_element_attrs(packet+pos, size-pos, connection, ctype);
|
||||
if (packet_type == AVRCP_CONTINUE_PACKET){
|
||||
avrcp_controller_request_continue_response(connection);
|
||||
}
|
||||
} else {
|
||||
avrcp_controller_request_abort_continuation(connection);
|
||||
avrcp_controller_emit_now_playing_info_event_done(avrcp_controller_context.avrcp_callback, connection->avrcp_cid, ctype, 1);
|
||||
avrcp_parser_reset(connection);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1253,3 +1258,13 @@ uint8_t avrcp_controller_play_item(uint16_t avrcp_cid, avrcp_browsing_scope_t sc
|
||||
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t avrcp_controller_set_max_num_fragments(uint16_t avrcp_cid, uint8_t max_num_fragments){
|
||||
avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context);
|
||||
if (!connection){
|
||||
log_error("avrcp_controller_play_item: could not find a connection.");
|
||||
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
|
||||
}
|
||||
connection->max_num_fragments = max_num_fragments;
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
@ -92,6 +92,15 @@ uint8_t avrcp_controller_connect(bd_addr_t bd_addr, uint16_t * avrcp_cid);
|
||||
*/
|
||||
uint8_t avrcp_controller_disconnect(uint16_t avrcp_cid);
|
||||
|
||||
/**
|
||||
* @brief Set max num fragments in whuch message can be transmited.
|
||||
* @param avrcp_cid
|
||||
* @param max_num_fragments
|
||||
* @returns status
|
||||
*/
|
||||
uint8_t avrcp_controller_set_max_num_fragments(uint16_t avrcp_cid, uint8_t max_num_fragments);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Unit info.
|
||||
* @param avrcp_cid
|
||||
|
Loading…
x
Reference in New Issue
Block a user