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));
|
memset(connection, 0, sizeof(avrcp_connection_t));
|
||||||
connection->state = AVCTP_CONNECTION_IDLE;
|
connection->state = AVCTP_CONNECTION_IDLE;
|
||||||
connection->transaction_label = 0xFF;
|
connection->transaction_label = 0xFF;
|
||||||
|
connection->max_num_fragments = 0xFF;
|
||||||
connection->avrcp_cid = avrcp_get_next_cid();
|
connection->avrcp_cid = avrcp_get_next_cid();
|
||||||
memcpy(connection->remote_addr, remote_addr, 6);
|
memcpy(connection->remote_addr, remote_addr, 6);
|
||||||
btstack_linked_list_add(&context->connections, (btstack_linked_item_t *) connection);
|
btstack_linked_list_add(&context->connections, (btstack_linked_item_t *) connection);
|
||||||
|
@ -55,7 +55,7 @@ extern "C" {
|
|||||||
|
|
||||||
#define BT_SIG_COMPANY_ID 0x001958
|
#define BT_SIG_COMPANY_ID 0x001958
|
||||||
#define AVRCP_MEDIA_ATTR_COUNT 7
|
#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_ATTRIBUTE_HEADER_LEN 8
|
||||||
#define AVRCP_MAX_FOLDER_NAME_SIZE 20
|
#define AVRCP_MAX_FOLDER_NAME_SIZE 20
|
||||||
|
|
||||||
@ -285,10 +285,9 @@ typedef struct {
|
|||||||
} avrcp_track_t;
|
} avrcp_track_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
AVRCP_PARSER_IDLE = 0,
|
AVRCP_PARSER_GET_ATTRIBUTE_HEADER = 0, // 8 bytes
|
||||||
AVRCP_PARSER_GET_ATTRIBUTE_HEADER, // 8 bytes
|
|
||||||
AVRCP_PARSER_GET_ATTRIBUTE_VALUE,
|
AVRCP_PARSER_GET_ATTRIBUTE_VALUE,
|
||||||
AVRCP_PARSER_IGNORE_ATTRIBUTE_VALUE
|
AVRCP_PARSER_CONTINUE_GET_ATTRIBUTE_VALUE
|
||||||
} avrcp_parser_state_t;
|
} avrcp_parser_state_t;
|
||||||
|
|
||||||
// BROWSING
|
// BROWSING
|
||||||
@ -342,7 +341,7 @@ typedef struct {
|
|||||||
uint8_t item_type;
|
uint8_t item_type;
|
||||||
uint16_t item_length;
|
uint16_t item_length;
|
||||||
uint16_t fragment_size;
|
uint16_t fragment_size;
|
||||||
uint8_t fragment[100];
|
uint8_t fragment[AVRCP_MAX_ATTRIBUTTE_SIZE];
|
||||||
} avrcp_browsing_connection_t;
|
} avrcp_browsing_connection_t;
|
||||||
// BROWSING END
|
// BROWSING END
|
||||||
|
|
||||||
@ -422,6 +421,10 @@ typedef struct {
|
|||||||
|
|
||||||
uint8_t num_attributes;
|
uint8_t num_attributes;
|
||||||
uint8_t num_parsed_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;
|
} avrcp_connection_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -215,7 +215,8 @@ static void avrcp_parser_reset(avrcp_connection_t * connection){
|
|||||||
connection->num_attributes = 0;
|
connection->num_attributes = 0;
|
||||||
connection->num_parsed_attributes = 0;
|
connection->num_parsed_attributes = 0;
|
||||||
connection->parser_attribute_header_pos = 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){
|
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){
|
static void avrcp_parser_process_byte(uint8_t byte, avrcp_connection_t * connection, avrcp_command_type_t ctype){
|
||||||
switch(connection->parser_state){
|
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) {
|
if (connection->parser_attribute_header_pos < AVRCP_ATTRIBUTE_HEADER_LEN) {
|
||||||
connection->parser_attribute_header[connection->parser_attribute_header_pos++] = byte;
|
connection->parser_attribute_header[connection->parser_attribute_header_pos++] = byte;
|
||||||
connection->list_offset++;
|
connection->list_offset++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
connection->attribute_value_len = btstack_min(big_endian_read_16(connection->parser_attribute_header, 6), AVRCP_MAX_ATTRIBUTTE_SIZE );
|
uint16_t attribute_total_value_len = big_endian_read_16(connection->parser_attribute_header, 6);
|
||||||
// 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));
|
connection->attribute_value_len = btstack_min(attribute_total_value_len, AVRCP_MAX_ATTRIBUTTE_SIZE);
|
||||||
connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_VALUE;
|
connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_VALUE;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case AVRCP_PARSER_GET_ATTRIBUTE_VALUE:{
|
case AVRCP_PARSER_GET_ATTRIBUTE_VALUE:{
|
||||||
if (connection->attribute_value_offset < connection->attribute_value_len){
|
if (connection->attribute_value_offset < connection->attribute_value_len){
|
||||||
connection->attribute_value[connection->attribute_value_offset++] = byte;
|
connection->attribute_value[connection->attribute_value_offset++] = byte;
|
||||||
connection->list_offset++;
|
connection->list_offset++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// TODO emit event
|
|
||||||
uint32_t attribute_id = big_endian_read_32(connection->parser_attribute_header, 0);
|
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){
|
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);
|
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)){
|
if (connection->attribute_value_offset < big_endian_read_16(connection->parser_attribute_header, 6)){
|
||||||
// printf("parse until end of valuE, and ignore it\n");
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,7 +341,7 @@ static void avrcp_parser_process_byte(uint8_t byte, avrcp_connection_t * connect
|
|||||||
connection->parser_attribute_header_pos = 0;
|
connection->parser_attribute_header_pos = 0;
|
||||||
break;
|
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)){
|
if (connection->attribute_value_offset < big_endian_read_16(connection->parser_attribute_header, 6)){
|
||||||
connection->list_offset++;
|
connection->list_offset++;
|
||||||
connection->attribute_value_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);
|
avrcp_parser_reset(connection);
|
||||||
connection->list_size = param_length;
|
connection->list_size = param_length;
|
||||||
connection->num_attributes = packet[pos++];
|
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);
|
// 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);
|
avrcp_source_parse_and_emit_element_attrs(packet+pos, size-pos, connection, ctype);
|
||||||
|
|
||||||
if (packet_type == AVRCP_START_PACKET){
|
if (packet_type == AVRCP_START_PACKET){
|
||||||
if (connection->num_attributes == 1 && connection->parser_state == AVRCP_PARSER_IGNORE_ATTRIBUTE_VALUE){
|
avrcp_controller_request_continue_response(connection);
|
||||||
avrcp_controller_request_abort_continuation(connection);
|
|
||||||
} else {
|
|
||||||
avrcp_controller_request_continue_response(connection);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVRCP_CONTINUE_PACKET:
|
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:
|
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;
|
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);
|
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
|
||||||
return ERROR_CODE_SUCCESS;
|
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);
|
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.
|
* @brief Unit info.
|
||||||
* @param avrcp_cid
|
* @param avrcp_cid
|
||||||
|
Loading…
x
Reference in New Issue
Block a user