mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-19 16:21:06 +00:00
avrcp browsing controller: fragmentation for get folder items
This commit is contained in:
parent
eb3e114b6f
commit
be65baf476
@ -1937,13 +1937,14 @@ typedef uint8_t sm_key_t[16];
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @format 1211
|
* @format 12211
|
||||||
* @param subevent_code
|
* @param subevent_code
|
||||||
* @param browsing_cid
|
* @param browsing_cid
|
||||||
|
* @param uid_counter
|
||||||
* @param browsing_status
|
* @param browsing_status
|
||||||
* @param bluetooth_status
|
* @param bluetooth_status
|
||||||
*/
|
*/
|
||||||
#define AVRCP_SUBEVENT_BROWSING_MEDIA_ITEM_DONE 0x1E
|
#define AVRCP_SUBEVENT_BROWSING_DONE 0x1E
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6216,31 +6216,40 @@ static inline uint16_t avrcp_subevent_browsing_connection_released_get_browsing_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get field browsing_cid from event AVRCP_SUBEVENT_BROWSING_MEDIA_ITEM_DONE
|
* @brief Get field browsing_cid from event AVRCP_SUBEVENT_BROWSING_DONE
|
||||||
* @param event packet
|
* @param event packet
|
||||||
* @return browsing_cid
|
* @return browsing_cid
|
||||||
* @note: btstack_type 2
|
* @note: btstack_type 2
|
||||||
*/
|
*/
|
||||||
static inline uint16_t avrcp_subevent_browsing_media_item_done_get_browsing_cid(const uint8_t * event){
|
static inline uint16_t avrcp_subevent_browsing_done_get_browsing_cid(const uint8_t * event){
|
||||||
return little_endian_read_16(event, 3);
|
return little_endian_read_16(event, 3);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Get field browsing_status from event AVRCP_SUBEVENT_BROWSING_MEDIA_ITEM_DONE
|
* @brief Get field uid_counter from event AVRCP_SUBEVENT_BROWSING_DONE
|
||||||
|
* @param event packet
|
||||||
|
* @return uid_counter
|
||||||
|
* @note: btstack_type 2
|
||||||
|
*/
|
||||||
|
static inline uint16_t avrcp_subevent_browsing_done_get_uid_counter(const uint8_t * event){
|
||||||
|
return little_endian_read_16(event, 5);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Get field browsing_status from event AVRCP_SUBEVENT_BROWSING_DONE
|
||||||
* @param event packet
|
* @param event packet
|
||||||
* @return browsing_status
|
* @return browsing_status
|
||||||
* @note: btstack_type 1
|
* @note: btstack_type 1
|
||||||
*/
|
*/
|
||||||
static inline uint8_t avrcp_subevent_browsing_media_item_done_get_browsing_status(const uint8_t * event){
|
static inline uint8_t avrcp_subevent_browsing_done_get_browsing_status(const uint8_t * event){
|
||||||
return event[5];
|
return event[7];
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Get field bluetooth_status from event AVRCP_SUBEVENT_BROWSING_MEDIA_ITEM_DONE
|
* @brief Get field bluetooth_status from event AVRCP_SUBEVENT_BROWSING_DONE
|
||||||
* @param event packet
|
* @param event packet
|
||||||
* @return bluetooth_status
|
* @return bluetooth_status
|
||||||
* @note: btstack_type 1
|
* @note: btstack_type 1
|
||||||
*/
|
*/
|
||||||
static inline uint8_t avrcp_subevent_browsing_media_item_done_get_bluetooth_status(const uint8_t * event){
|
static inline uint8_t avrcp_subevent_browsing_done_get_bluetooth_status(const uint8_t * event){
|
||||||
return event[6];
|
return event[8];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,6 +57,7 @@ extern "C" {
|
|||||||
#define AVRCP_MEDIA_ATTR_COUNT 7
|
#define AVRCP_MEDIA_ATTR_COUNT 7
|
||||||
#define AVRCP_MAX_ATTRIBUTTE_SIZE 100
|
#define AVRCP_MAX_ATTRIBUTTE_SIZE 100
|
||||||
#define AVRCP_ATTRIBUTE_HEADER_LEN 8
|
#define AVRCP_ATTRIBUTE_HEADER_LEN 8
|
||||||
|
#define AVRCP_MAX_FOLDER_NAME_SIZE 20
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
AVRCP_STATUS_INVALID_COMMAND = 0, // sent if TG received a PDU that it did not understand.
|
AVRCP_STATUS_INVALID_COMMAND = 0, // sent if TG received a PDU that it did not understand.
|
||||||
@ -129,6 +130,7 @@ typedef enum {
|
|||||||
AVRCP_PDU_ID_SET_BROWSED_PLAYER = 0x70,
|
AVRCP_PDU_ID_SET_BROWSED_PLAYER = 0x70,
|
||||||
AVRCP_PDU_ID_GET_FOLDER_ITEMS = 0x71,
|
AVRCP_PDU_ID_GET_FOLDER_ITEMS = 0x71,
|
||||||
AVRCP_PDU_ID_CHANGE_PATH = 0x72,
|
AVRCP_PDU_ID_CHANGE_PATH = 0x72,
|
||||||
|
AVRCP_PDU_ID_PLAY_ITEM = 0x74,
|
||||||
AVRCP_PDU_ID_UNDEFINED = 0xFF
|
AVRCP_PDU_ID_UNDEFINED = 0xFF
|
||||||
} avrcp_pdu_id_t;
|
} avrcp_pdu_id_t;
|
||||||
|
|
||||||
@ -256,6 +258,13 @@ typedef enum {
|
|||||||
AVCTP_W2_RECEIVE_RESPONSE
|
AVCTP_W2_RECEIVE_RESPONSE
|
||||||
} avctp_connection_state_t;
|
} avctp_connection_state_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AVRCP_BROWSING_MEDIA_PLAYER_LIST = 0x00,
|
||||||
|
AVRCP_BROWSING_MEDIA_PLAYER_VIRTUAL_FILESYSTEM,
|
||||||
|
AVRCP_BROWSING_SEARCH,
|
||||||
|
AVRCP_BROWSING_NOW_PLAYING
|
||||||
|
} avrcp_browsing_scope_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint8_t * value;
|
uint8_t * value;
|
||||||
@ -304,7 +313,7 @@ typedef struct {
|
|||||||
|
|
||||||
// get folder item
|
// get folder item
|
||||||
uint8_t get_folder_item;
|
uint8_t get_folder_item;
|
||||||
uint8_t scope;
|
avrcp_browsing_scope_t scope;
|
||||||
uint32_t start_item;
|
uint32_t start_item;
|
||||||
uint32_t end_item;
|
uint32_t end_item;
|
||||||
uint32_t attr_bitmap;
|
uint32_t attr_bitmap;
|
||||||
@ -314,6 +323,17 @@ typedef struct {
|
|||||||
uint8_t direction;
|
uint8_t direction;
|
||||||
uint16_t uid_counter;
|
uint16_t uid_counter;
|
||||||
uint8_t folder_uid[8];
|
uint8_t folder_uid[8];
|
||||||
|
|
||||||
|
// fragmentation
|
||||||
|
uint8_t fragmented;
|
||||||
|
avrcp_pdu_id_t fragmented_pdu_id;
|
||||||
|
uint8_t fragmented_browsing_status;
|
||||||
|
uint16_t fragmented_uid_counter;
|
||||||
|
uint16_t num_items;
|
||||||
|
uint8_t item_type;
|
||||||
|
uint16_t item_length;
|
||||||
|
uint16_t fragment_size;
|
||||||
|
uint8_t fragment[100];
|
||||||
} avrcp_browsing_connection_t;
|
} avrcp_browsing_connection_t;
|
||||||
// BROWSING END
|
// BROWSING END
|
||||||
|
|
||||||
|
@ -383,26 +383,33 @@ static void avrcp_browsing_controller_handle_can_send_now(avrcp_browsing_connect
|
|||||||
avrcp_browsing_controller_send_change_path_cmd(connection->l2cap_browsing_cid, connection);
|
avrcp_browsing_controller_send_change_path_cmd(connection->l2cap_browsing_cid, connection);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void avrcp_browsing_controller_emit_done(btstack_packet_handler_t callback, uint16_t browsing_cid, uint8_t browsing_status, uint8_t bluetooth_status){
|
|
||||||
|
static void avrcp_browsing_controller_emit_done_with_uid_counter(btstack_packet_handler_t callback, uint16_t browsing_cid, uint16_t uid_counter, uint8_t browsing_status, uint8_t bluetooth_status){
|
||||||
if (!callback) return;
|
if (!callback) return;
|
||||||
uint8_t event[7];
|
uint8_t event[9];
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
event[pos++] = HCI_EVENT_AVRCP_META;
|
event[pos++] = HCI_EVENT_AVRCP_META;
|
||||||
event[pos++] = sizeof(event) - 2;
|
event[pos++] = sizeof(event) - 2;
|
||||||
event[pos++] = AVRCP_SUBEVENT_BROWSING_MEDIA_ITEM_DONE;
|
event[pos++] = AVRCP_SUBEVENT_BROWSING_DONE;
|
||||||
little_endian_store_16(event, pos, browsing_cid);
|
little_endian_store_16(event, pos, browsing_cid);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
little_endian_store_16(event, pos, uid_counter);
|
||||||
|
pos += 2;
|
||||||
event[pos++] = browsing_status;
|
event[pos++] = browsing_status;
|
||||||
event[pos++] = bluetooth_status;
|
event[pos++] = bluetooth_status;
|
||||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void avrcp_browsing_controller_emit_done(btstack_packet_handler_t callback, uint16_t browsing_cid, uint8_t browsing_status, uint8_t bluetooth_status){
|
||||||
|
avrcp_browsing_controller_emit_done_with_uid_counter(callback, browsing_cid, 0, browsing_status, bluetooth_status);
|
||||||
|
}
|
||||||
|
|
||||||
static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||||
avrcp_browsing_connection_t * browsing_connection;
|
avrcp_browsing_connection_t * browsing_connection;
|
||||||
|
|
||||||
@ -410,52 +417,45 @@ static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16
|
|||||||
case L2CAP_DATA_PACKET:{
|
case L2CAP_DATA_PACKET:{
|
||||||
browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid(channel, &avrcp_controller_context);
|
browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid(channel, &avrcp_controller_context);
|
||||||
if (!browsing_connection) break;
|
if (!browsing_connection) break;
|
||||||
browsing_connection->state = AVCTP_CONNECTION_OPENED;
|
|
||||||
|
|
||||||
// printf_hexdump(packet, size);
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
uint8_t transport_header = packet[pos++];
|
uint8_t transport_header = packet[pos++];
|
||||||
// Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
|
// Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
|
||||||
// uint8_t transaction_label = transport_header >> 4;
|
// uint8_t transaction_label = transport_header >> 4;
|
||||||
avrcp_packet_type_t avctp_packet_type = (transport_header & 0x0F) >> 2;
|
avrcp_packet_type_t avctp_packet_type = (transport_header & 0x0F) >> 2;
|
||||||
|
|
||||||
|
avrcp_pdu_id_t pdu_id;
|
||||||
|
uint8_t browsing_status;
|
||||||
|
uint16_t uid_counter;
|
||||||
|
if (!browsing_connection->fragmented){
|
||||||
|
browsing_connection->state = AVCTP_CONNECTION_OPENED;
|
||||||
|
// printf_hexdump(packet, size);
|
||||||
// uint8_t frame_type = (transport_header & 0x03) >> 1;
|
// uint8_t frame_type = (transport_header & 0x03) >> 1;
|
||||||
// uint8_t ipid = transport_header & 0x01;
|
// uint8_t ipid = transport_header & 0x01;
|
||||||
pos += 2;
|
pos += 2;
|
||||||
browsing_connection->num_packets = 1;
|
browsing_connection->num_packets = 1;
|
||||||
switch (avctp_packet_type){
|
if (avctp_packet_type == AVRCP_START_PACKET){
|
||||||
case AVRCP_SINGLE_PACKET:
|
|
||||||
break;
|
|
||||||
case AVRCP_START_PACKET:
|
|
||||||
browsing_connection->num_packets = packet[pos++];
|
browsing_connection->num_packets = packet[pos++];
|
||||||
break;
|
|
||||||
case AVRCP_CONTINUE_PACKET:
|
|
||||||
case AVRCP_END_PACKET:
|
|
||||||
// browsing_connection->num_packets = packet[pos++];
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos + 4 > size){
|
if (pos + 4 > size){
|
||||||
avrcp_browsing_controller_emit_done(avrcp_controller_context.browsing_avrcp_callback, channel, AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND, ERROR_CODE_SUCCESS);
|
avrcp_browsing_controller_emit_done(avrcp_controller_context.browsing_avrcp_callback, channel, AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND, ERROR_CODE_SUCCESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
pdu_id = packet[pos++];
|
||||||
avrcp_pdu_id_t pdu_id = packet[pos++];
|
// uint16_t length = big_endian_read_16(packet, pos);
|
||||||
uint16_t length = big_endian_read_16(packet, pos);
|
|
||||||
pos += 2;
|
pos += 2;
|
||||||
UNUSED(length);
|
browsing_status = packet[pos++];
|
||||||
// if (browsing_connection->num_packets > 1)
|
|
||||||
// if (browsing_connection->num_packets == 1 && (pos + length > size)){
|
|
||||||
// printf("pos + length > size, %d, %d, %d \n", pos, length, size);
|
|
||||||
// avrcp_browsing_controller_emit_done(avrcp_controller_context.browsing_avrcp_callback, channel, AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND, ERROR_CODE_SUCCESS);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
uint8_t browsing_status = packet[pos++];
|
|
||||||
if (browsing_status != AVRCP_BROWSING_ERROR_CODE_SUCCESS){
|
if (browsing_status != AVRCP_BROWSING_ERROR_CODE_SUCCESS){
|
||||||
printf("browsing_status %d\n", browsing_status);
|
|
||||||
avrcp_browsing_controller_emit_done(avrcp_controller_context.browsing_avrcp_callback, channel, browsing_status, ERROR_CODE_SUCCESS);
|
avrcp_browsing_controller_emit_done(avrcp_controller_context.browsing_avrcp_callback, channel, browsing_status, ERROR_CODE_SUCCESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
uid_counter = big_endian_read_16(packet, pos);
|
||||||
|
pos += 2;
|
||||||
|
} else {
|
||||||
|
pdu_id = browsing_connection->fragmented_pdu_id;
|
||||||
|
browsing_status = browsing_connection->fragmented_browsing_status;
|
||||||
|
uid_counter = browsing_connection->fragmented_uid_counter;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
switch(pdu_id){
|
switch(pdu_id){
|
||||||
@ -463,46 +463,90 @@ static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16
|
|||||||
printf("AVRCP_PDU_ID_CHANGE_PATH \n");
|
printf("AVRCP_PDU_ID_CHANGE_PATH \n");
|
||||||
break;
|
break;
|
||||||
case AVRCP_PDU_ID_SET_ADDRESSED_PLAYER:
|
case AVRCP_PDU_ID_SET_ADDRESSED_PLAYER:
|
||||||
printf("AVRCP_PDU_ID_CHANGE_PATH \n");
|
printf("AVRCP_PDU_ID_SET_ADDRESSED_PLAYER \n");
|
||||||
break;
|
break;
|
||||||
case AVRCP_PDU_ID_SET_BROWSED_PLAYER:{
|
case AVRCP_PDU_ID_SET_BROWSED_PLAYER:{
|
||||||
browsing_connection->browsed_player_uid_counter = big_endian_read_16(packet, pos);
|
browsing_connection->browsed_player_uid_counter = uid_counter;
|
||||||
pos += 2;
|
// uint32_t num_items = big_endian_read_32(packet, pos);
|
||||||
uint32_t num_items = big_endian_read_32(packet, pos);
|
|
||||||
pos += 4;
|
pos += 4;
|
||||||
printf("AVRCP_PDU_ID_SET_BROWSED_PLAYER uuid counter 0x0%2x, num items %d\n", browsing_connection->browsed_player_uid_counter, num_items);
|
// uint16_t charset = big_endian_read_16(packet, pos);
|
||||||
|
pos += 2;
|
||||||
|
uint8_t folder_depth = packet[pos++];
|
||||||
|
|
||||||
for (i = 0; i < num_items; i++){
|
for (i = 0; i < folder_depth; i++){
|
||||||
uint16_t browsable_item_length = 5 + big_endian_read_16(packet, pos+3);
|
uint16_t folder_name_length = big_endian_read_16(packet, pos);
|
||||||
printf(" pos %d, len %d\n", pos, browsable_item_length);
|
pos += 2;
|
||||||
// reuse byte to put the new type AVRCP_BROWSING_MEDIA_ROOT_FOLDER
|
// reuse packet and add data type as a header
|
||||||
packet[pos-1] = AVRCP_BROWSING_MEDIA_ROOT_FOLDER;
|
packet[pos-1] = AVRCP_BROWSING_MEDIA_ROOT_FOLDER;
|
||||||
(*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos, browsable_item_length+1);
|
(*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos-1, folder_name_length+1);
|
||||||
pos += browsable_item_length;
|
pos += folder_name_length;
|
||||||
|
}
|
||||||
|
if (avctp_packet_type == AVRCP_SINGLE_PACKET || avctp_packet_type == AVRCP_END_PACKET){
|
||||||
|
avrcp_browsing_controller_emit_done_with_uid_counter(avrcp_controller_context.browsing_avrcp_callback, channel, browsing_connection->browsed_player_uid_counter, browsing_status, ERROR_CODE_SUCCESS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AVRCP_PDU_ID_GET_FOLDER_ITEMS:{
|
case AVRCP_PDU_ID_GET_FOLDER_ITEMS:{
|
||||||
// uint16_t uid_counter = big_endian_read_16(packet, pos);
|
printf("AVRCP_PDU_ID_GET_FOLDER_ITEMS \n");
|
||||||
|
// send UID counter with done
|
||||||
|
if (!browsing_connection->fragmented){
|
||||||
|
browsing_connection->num_items = big_endian_read_16(packet, pos);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
uint16_t num_items = big_endian_read_16(packet, pos);
|
}
|
||||||
|
while (pos < size){
|
||||||
|
uint8_t header_size = 1;
|
||||||
|
if (browsing_connection->fragment_size == 0){
|
||||||
|
browsing_connection->item_type = packet[pos++];
|
||||||
|
browsing_connection->item_length = big_endian_read_16(packet, pos);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
for (i = 0; i < num_items; i++){
|
// reuse packet and add data type as a header
|
||||||
uint16_t browsable_item_length = 3 + big_endian_read_16(packet, pos+1);
|
packet[pos-1] = browsing_connection->item_type;
|
||||||
(*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos, browsable_item_length);
|
|
||||||
pos += browsable_item_length;
|
if (browsing_connection->item_length + pos > size) {
|
||||||
|
browsing_connection->fragment_size = size - pos;
|
||||||
|
browsing_connection->fragment[0] = browsing_connection->item_type;
|
||||||
|
memcpy(&browsing_connection->fragment[header_size], &packet[pos], browsing_connection->fragment_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, &packet[pos-header_size], browsing_connection->item_length+header_size);
|
||||||
|
browsing_connection->num_items--;
|
||||||
|
pos += browsing_connection->item_length;
|
||||||
|
} else {
|
||||||
|
uint16_t remaining_bytes_to_copy = browsing_connection->item_length - browsing_connection->fragment_size;
|
||||||
|
if (remaining_bytes_to_copy + pos > size) {
|
||||||
|
memcpy(&browsing_connection->fragment[browsing_connection->fragment_size+1], &packet[pos], size - pos);
|
||||||
|
browsing_connection->fragment_size += size - pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memcpy(&browsing_connection->fragment[browsing_connection->fragment_size+1], &packet[pos], remaining_bytes_to_copy);
|
||||||
|
(*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, browsing_connection->fragment, browsing_connection->item_length+1);
|
||||||
|
browsing_connection->num_items--;
|
||||||
|
browsing_connection->fragment_size = 0;
|
||||||
|
pos += remaining_bytes_to_copy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (avctp_packet_type){
|
switch (avctp_packet_type){
|
||||||
case AVRCP_SINGLE_PACKET:
|
case AVRCP_SINGLE_PACKET:
|
||||||
case AVRCP_END_PACKET:
|
case AVRCP_END_PACKET:
|
||||||
avrcp_browsing_controller_emit_done(avrcp_controller_context.browsing_avrcp_callback, channel, browsing_status, ERROR_CODE_SUCCESS);
|
browsing_connection->state = AVCTP_CONNECTION_OPENED;
|
||||||
|
browsing_connection->fragmented = 0;
|
||||||
|
browsing_connection->num_items = 0;
|
||||||
|
browsing_connection->fragment_size = 0;
|
||||||
|
avrcp_browsing_controller_emit_done_with_uid_counter(avrcp_controller_context.browsing_avrcp_callback, channel, uid_counter, browsing_status, ERROR_CODE_SUCCESS);
|
||||||
break;
|
break;
|
||||||
default:
|
case AVRCP_START_PACKET:
|
||||||
|
browsing_connection->fragmented = 1;
|
||||||
|
browsing_connection->fragmented_pdu_id = pdu_id;
|
||||||
|
browsing_connection->fragmented_browsing_status = browsing_status;
|
||||||
|
break;
|
||||||
|
case AVRCP_CONTINUE_PACKET:
|
||||||
|
browsing_connection->fragmented = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -600,7 +644,7 @@ uint8_t avrcp_avrcp_browsing_decline_incoming_connection(uint16_t avrcp_browsing
|
|||||||
* @param attribute_count
|
* @param attribute_count
|
||||||
* @param attribute_list
|
* @param attribute_list
|
||||||
**/
|
**/
|
||||||
static uint8_t avrcp_browsing_controller_get_folder_items(uint16_t avrcp_browsing_cid, uint8_t scope, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
|
static uint8_t avrcp_browsing_controller_get_folder_items(uint16_t avrcp_browsing_cid, avrcp_browsing_scope_t scope, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
|
||||||
avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
|
avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
|
||||||
if (!avrcp_connection){
|
if (!avrcp_connection){
|
||||||
log_error("avrcp_browsing_controller_disconnect: could not find a connection.");
|
log_error("avrcp_browsing_controller_disconnect: could not find a connection.");
|
||||||
@ -620,21 +664,21 @@ static uint8_t avrcp_browsing_controller_get_folder_items(uint16_t avrcp_browsin
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t avrcp_browsing_controller_get_media_players(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
|
uint8_t avrcp_browsing_controller_get_media_players(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
|
||||||
return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 0, start_item, end_item, attr_bitmap);
|
return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_MEDIA_PLAYER_LIST, start_item, end_item, attr_bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t avrcp_browsing_controller_browse_file_system(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
|
uint8_t avrcp_browsing_controller_browse_file_system(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
|
||||||
// return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 1, 0, 0xFFFFFFFF, attr_bitmap);
|
// return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 1, 0, 0xFFFFFFFF, attr_bitmap);
|
||||||
return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 1, start_item, end_item, attr_bitmap);
|
return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_MEDIA_PLAYER_VIRTUAL_FILESYSTEM, start_item, end_item, attr_bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t avrcp_browsing_controller_browse_media(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
|
uint8_t avrcp_browsing_controller_browse_media(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
|
||||||
// return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 2, 0, 0xFFFFFFFF, 0, NULL);
|
// return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 2, 0, 0xFFFFFFFF, 0, NULL);
|
||||||
return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 2, start_item, end_item, attr_bitmap);
|
return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_SEARCH, start_item, end_item, attr_bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t avrcp_browsing_controller_browse_now_playing_list(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
|
uint8_t avrcp_browsing_controller_browse_now_playing_list(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
|
||||||
return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 3, start_item, end_item, attr_bitmap);
|
return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_NOW_PLAYING, start_item, end_item, attr_bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -690,7 +734,7 @@ uint8_t avrcp_browsing_controller_change_path(uint16_t avrcp_browsing_cid, uint8
|
|||||||
|
|
||||||
avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
|
avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
|
||||||
|
|
||||||
if (!connection || connection->state != AVCTP_CONNECTION_OPENED || !folder_uid){
|
if (!connection || connection->state != AVCTP_CONNECTION_OPENED){
|
||||||
log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
|
log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
|
||||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
}
|
}
|
||||||
@ -699,17 +743,20 @@ uint8_t avrcp_browsing_controller_change_path(uint16_t avrcp_browsing_cid, uint8
|
|||||||
log_error("avrcp_browsing_controller_change_path: no browsed player set.");
|
log_error("avrcp_browsing_controller_change_path: no browsed player set.");
|
||||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
}
|
}
|
||||||
|
printf(" send change path\n");
|
||||||
connection->change_path = 1;
|
connection->change_path = 1;
|
||||||
connection->direction = direction;
|
connection->direction = direction;
|
||||||
|
memset(connection->folder_uid, 0, 8);
|
||||||
|
if (folder_uid){
|
||||||
memcpy(connection->folder_uid, folder_uid, 8);
|
memcpy(connection->folder_uid, folder_uid, 8);
|
||||||
|
}
|
||||||
|
|
||||||
avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
|
avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
|
||||||
return ERROR_CODE_SUCCESS;
|
return ERROR_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t avrcp_browsing_controller_go_up_one_level(uint16_t avrcp_browsing_cid){
|
uint8_t avrcp_browsing_controller_go_up_one_level(uint16_t avrcp_browsing_cid){
|
||||||
return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 0, 0);
|
return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t avrcp_browsing_controller_go_down_one_level(uint16_t avrcp_browsing_cid, uint8_t * folder_uid){
|
uint8_t avrcp_browsing_controller_go_down_one_level(uint16_t avrcp_browsing_cid, uint8_t * folder_uid){
|
||||||
|
@ -202,7 +202,6 @@ uint8_t avrcp_browsing_controller_set_addressed_player(uint16_t avrcp_browsing_c
|
|||||||
uint8_t avrcp_browsing_controller_change_path(uint16_t avrcp_browsing_cid, uint8_t direction, uint8_t * folder_uid);
|
uint8_t avrcp_browsing_controller_change_path(uint16_t avrcp_browsing_cid, uint8_t direction, uint8_t * folder_uid);
|
||||||
uint8_t avrcp_browsing_controller_go_up_one_level(uint16_t avrcp_browsing_cid);
|
uint8_t avrcp_browsing_controller_go_up_one_level(uint16_t avrcp_browsing_cid);
|
||||||
uint8_t avrcp_browsing_controller_go_down_one_level(uint16_t avrcp_browsing_cid, uint8_t * folder_uid);
|
uint8_t avrcp_browsing_controller_go_down_one_level(uint16_t avrcp_browsing_cid, uint8_t * folder_uid);
|
||||||
|
|
||||||
/* API_END */
|
/* API_END */
|
||||||
|
|
||||||
#if defined __cplusplus
|
#if defined __cplusplus
|
||||||
|
@ -1185,3 +1185,40 @@ uint8_t avrcp_controller_disconnect(uint16_t avrcp_cid){
|
|||||||
l2cap_disconnect(connection->l2cap_signaling_cid, 0);
|
l2cap_disconnect(connection->l2cap_signaling_cid, 0);
|
||||||
return ERROR_CODE_SUCCESS;
|
return ERROR_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t avrcp_controller_play_item(uint16_t avrcp_cid, avrcp_browsing_scope_t scope, uint8_t * uid, uint16_t uid_counter){
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
|
||||||
|
connection->state = AVCTP_W2_SEND_COMMAND;
|
||||||
|
|
||||||
|
connection->transaction_label++;
|
||||||
|
connection->command_type = AVRCP_CTYPE_CONTROL;
|
||||||
|
connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
|
||||||
|
connection->subunit_id = AVRCP_SUBUNIT_ID;
|
||||||
|
connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
|
||||||
|
int pos = 0;
|
||||||
|
big_endian_store_24(connection->cmd_operands, pos, BT_SIG_COMPANY_ID);
|
||||||
|
pos += 3;
|
||||||
|
connection->cmd_operands[pos++] = AVRCP_PDU_ID_PLAY_ITEM; // PDU ID
|
||||||
|
// reserved
|
||||||
|
connection->cmd_operands[pos++] = 0;
|
||||||
|
// Parameter Length
|
||||||
|
big_endian_store_16(connection->cmd_operands, pos, 11);
|
||||||
|
pos += 2;
|
||||||
|
connection->cmd_operands[pos++] = scope;
|
||||||
|
memset(&connection->cmd_operands[pos], 0, 8);
|
||||||
|
if (uid){
|
||||||
|
memcpy(&connection->cmd_operands[pos], uid, 8);
|
||||||
|
}
|
||||||
|
pos += 8;
|
||||||
|
big_endian_store_16(connection->cmd_operands, pos, uid_counter);
|
||||||
|
pos += 2;
|
||||||
|
connection->cmd_operands_length = pos;
|
||||||
|
|
||||||
|
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
|
||||||
|
return ERROR_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
@ -284,6 +284,17 @@ uint8_t avrcp_controller_set_shuffle_mode(uint16_t avrcp_cid, avrcp_shuffle_mode
|
|||||||
* @returns status
|
* @returns status
|
||||||
*/
|
*/
|
||||||
uint8_t avrcp_controller_set_repeat_mode(uint16_t avrcp_cid, avrcp_repeat_mode_t mode);
|
uint8_t avrcp_controller_set_repeat_mode(uint16_t avrcp_cid, avrcp_repeat_mode_t mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The PlayItem command starts playing an item indicated by the UID. It is routed to the Addressed Player.
|
||||||
|
* @param avrcp_cid
|
||||||
|
* @param scope
|
||||||
|
* @param uid
|
||||||
|
* @param uid_counter
|
||||||
|
* @return status
|
||||||
|
**/
|
||||||
|
uint8_t avrcp_controller_play_item(uint16_t avrcp_cid, avrcp_browsing_scope_t scope, uint8_t * uid, uint16_t uid_counter);
|
||||||
|
|
||||||
/* API_END */
|
/* API_END */
|
||||||
|
|
||||||
// Used by AVRCP controller and AVRCP browsing controller
|
// Used by AVRCP controller and AVRCP browsing controller
|
||||||
|
Loading…
x
Reference in New Issue
Block a user