avrcp_browsing_target: test set browsed player

This commit is contained in:
Milanka Ringwald 2021-05-06 18:25:52 +02:00
parent bbee15159a
commit fd9293d815
3 changed files with 145 additions and 2 deletions

View File

@ -119,6 +119,21 @@ static void avrcp_browsing_target_emit_get_total_num_items(btstack_packet_handle
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void avrcp_browsing_target_emit_set_browsed_player(btstack_packet_handler_t callback, uint16_t browsing_cid, uint16_t browsed_player_id){
btstack_assert(callback != NULL);
uint8_t event[10];
int pos = 0;
event[pos++] = HCI_EVENT_AVRCP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVRCP_SUBEVENT_BROWSING_SET_BROWSED_PLAYER;
little_endian_store_16(event, pos, browsing_cid);
pos += 2;
little_endian_store_16(event, pos, browsed_player_id);
pos += 2;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void avrcp_browsing_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(size);
@ -174,6 +189,14 @@ static void avrcp_browsing_target_packet_handler(uint8_t packet_type, uint16_t c
avrcp_browsing_target_emit_get_total_num_items(avrcp_target_context.browsing_avrcp_callback, channel, browsing_connection);
break;
}
case AVRCP_PDU_ID_SET_BROWSED_PLAYER:
// param length (2), player_id (2)
if (big_endian_read_16(packet, pos) != 2){
avrcp_browsing_target_response_general_reject(browsing_connection, AVRCP_STATUS_INVALID_COMMAND);
break;
}
avrcp_browsing_target_emit_set_browsed_player(avrcp_target_context.browsing_avrcp_callback, channel, big_endian_read_16(packet, pos+2));
break;
default:
avrcp_browsing_target_response_general_reject(browsing_connection, AVRCP_STATUS_INVALID_COMMAND);
log_info("not parsed pdu ID 0x%02x", browsing_connection->pdu_id);
@ -260,6 +283,80 @@ uint8_t avrcp_browsing_target_send_get_folder_items_response(uint16_t avrcp_brow
return ERROR_CODE_SUCCESS;
}
uint8_t avrcp_browsing_target_send_accept_set_browsed_player(uint16_t avrcp_browsing_cid, uint16_t uid_counter, uint16_t browsed_player_id, uint8_t * response, uint16_t response_size){
avrcp_connection_t * avrcp_connection = avrcp_get_connection_for_browsing_cid_for_role(AVRCP_TARGET, avrcp_browsing_cid);
if (!avrcp_connection){
log_error("Could not find an AVRCP Target connection for browsing_cid 0x%02x.", avrcp_browsing_cid);
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
}
avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
if (!connection){
log_info("Could not find a browsing connection.");
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
}
if (connection->state != AVCTP_CONNECTION_OPENED) {
log_info("Browsing connection wrong state.");
return ERROR_CODE_COMMAND_DISALLOWED;
}
connection->browsed_player_id = browsed_player_id;
uint16_t pos = 0;
connection->cmd_operands[pos++] = AVRCP_PDU_ID_SET_BROWSED_PLAYER;
big_endian_store_16(connection->cmd_operands, pos, response_size + 2 + 1); // uuid counter + status
pos += 2;
connection->cmd_operands[pos++] = AVRCP_STATUS_SUCCESS;
big_endian_store_16(connection->cmd_operands, pos, uid_counter);
pos += 2;
// TODO: fragmentation
if (response_size > sizeof(connection->cmd_operands)){
connection->attr_list = response;
connection->attr_list_size = response_size;
log_info(" todo: list too big, invoke fragmentation");
return 1;
}
(void)memcpy(&connection->cmd_operands[pos], response, response_size);
pos += response_size;
connection->cmd_operands_length = pos;
connection->state = AVCTP_W2_SEND_RESPONSE;
avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
return ERROR_CODE_SUCCESS;
}
uint8_t avrcp_browsing_target_send_reject_set_browsed_player(uint16_t avrcp_browsing_cid, avrcp_status_code_t status){
avrcp_connection_t * avrcp_connection = avrcp_get_connection_for_browsing_cid_for_role(AVRCP_TARGET, avrcp_browsing_cid);
if (!avrcp_connection){
log_error("Could not find an AVRCP Target connection for browsing_cid 0x%02x.", avrcp_browsing_cid);
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
}
avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
if (!connection){
log_info("Could not find a browsing connection.");
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
}
if (connection->state != AVCTP_CONNECTION_OPENED) {
log_info("Browsing connection wrong state.");
return ERROR_CODE_COMMAND_DISALLOWED;
}
int pos = 0;
connection->cmd_operands[pos++] = AVRCP_PDU_ID_SET_BROWSED_PLAYER;
big_endian_store_16(connection->cmd_operands, pos, 1);
connection->cmd_operands[pos++] = status;
connection->cmd_operands_length = pos;
connection->state = AVCTP_W2_SEND_RESPONSE;
avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
return ERROR_CODE_SUCCESS;
}
uint8_t avrcp_browsing_target_send_get_total_num_items_response(uint16_t avrcp_browsing_cid, uint16_t uid_counter, uint32_t total_num_items){
avrcp_connection_t * avrcp_connection = avrcp_get_connection_for_browsing_cid_for_role(AVRCP_TARGET, avrcp_browsing_cid);
@ -273,7 +370,6 @@ uint8_t avrcp_browsing_target_send_get_total_num_items_response(uint16_t avrcp_b
log_info("Could not find a browsing connection.");
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
}
if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
if (connection->state != AVCTP_CONNECTION_OPENED) {
log_info("Browsing connection wrong state.");

View File

@ -66,6 +66,23 @@ void avrcp_browsing_target_init(void);
*/
void avrcp_browsing_target_register_packet_handler(btstack_packet_handler_t callback);
/**
* @brief Accept set browsed player
* @param browsing_cid
* @param uid_counter
* @param browsed_player_id
* @param response
* @param response_size
*/
uint8_t avrcp_browsing_target_send_accept_set_browsed_player(uint16_t browsing_cid, uint16_t uid_counter, uint16_t browsed_player_id, uint8_t * response, uint16_t response_len);
/**
* @brief Reject set browsed player
* @param browsing_cid
* @param status
*/
uint8_t avrcp_browsing_target_send_reject_set_browsed_player(uint16_t browsing_cid, avrcp_status_code_t status);
/**
* @brief Send answer to get folder items query on event AVRCP_SUBEVENT_BROWSING_GET_FOLDER_ITEMS. The first byte of this event defines the scope of the query, see avrcp_browsing_scope_t.
* @param browsing_cid

View File

@ -284,7 +284,28 @@ static uint8_t media_player_list[] = {
0x00, 0x10,
// Displayable Name
0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72};
static uint8_t browsed_player_data[]= {
// number of items (3)
0x00, 0x00, 0x04,
// Character Set Id (2B): 0x006A (UTF-8)
0x00, 0x6A,
// Folder depth
0x03,
// Folder Name Length (2)
0x00, 0x01,
// FOlder Name
0x41,
// Folder Name Length (2)
0x00, 0x01,
// FOlder Name
0x42,
// Folder Name Length (2)
0x00, 0x01,
// FOlder Name
0x43
};
static uint8_t virtual_filesystem_list[] ={ 0x00, 0x07, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x6A, 0x00, 0x06, 0x41, 0x6C, 0x62, 0x75, 0x6D, 0x73, 0x02, 0x00, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x6A, 0x00, 0x07, 0x41, 0x72, 0x74, 0x69, 0x73, 0x74, 0x73, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x6A, 0x00, 0x06, 0x47, 0x65, 0x6E, 0x72, 0x65, 0x73, 0x02, 0x00, 0x17, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x6A, 0x00, 0x09, 0x50, 0x6C, 0x61, 0x79, 0x6C, 0x69, 0x73, 0x74, 0x73, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x01, 0x01, 0x00, 0x6A, 0x00, 0x05, 0x53, 0x6F, 0x6E, 0x67, 0x73, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00}; // 0x71, 0x00, 0xA7, 0x04, 0x5A, 0x73,
static uint8_t search_list[] = {};
@ -914,6 +935,15 @@ static void avrcp_browsing_target_packet_handler(uint8_t packet_type, uint16_t c
if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
switch (packet[2]){
case AVRCP_SUBEVENT_BROWSING_SET_BROWSED_PLAYER:{
uint16_t browsed_player_id = avrcp_subevent_browsing_set_browsed_player_get_player_id(packet);
if (browsed_player_id == 1){
avrcp_status = avrcp_browsing_target_send_accept_set_browsed_player(browsing_cid, uid_counter, browsed_player_id, browsed_player_data, sizeof(browsed_player_data));
} else {
avrcp_status = avrcp_browsing_target_send_reject_set_browsed_player(browsing_cid, AVRCP_STATUS_PLAYER_NOT_BROWSABLE);
}
break;
}
case AVRCP_SUBEVENT_BROWSING_GET_FOLDER_ITEMS:{
avrcp_browsing_scope_t scope = avrcp_subevent_browsing_get_folder_items_get_scope(packet);
switch (scope){