From: Archie Pusaka <apusaka@xxxxxxxxxxxx> According to the AVRCP spec, section 4.5, GetTotalNumberOfItems PDU is mandatory for TG supporting category 1 or 3. Reviewed-by: Yun-Hao Chung <howardchung@xxxxxxxxxx> Reviewed-by: Michael Sun <michaelfsun@xxxxxxxxxx> --- profiles/audio/avrcp.c | 58 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c index 5d0256c52..6da73394f 100644 --- a/profiles/audio/avrcp.c +++ b/profiles/audio/avrcp.c @@ -79,6 +79,7 @@ #define AVRCP_STATUS_SUCCESS 0x04 #define AVRCP_STATUS_UID_CHANGED 0x05 #define AVRCP_STATUS_DOES_NOT_EXIST 0x09 +#define AVRCP_STATUS_INVALID_SCOPE 0x0a #define AVRCP_STATUS_OUT_OF_BOUNDS 0x0b #define AVRCP_STATUS_INVALID_PLAYER_ID 0x11 #define AVRCP_STATUS_PLAYER_NOT_BROWSABLE 0x12 @@ -211,6 +212,12 @@ struct player_item { char name[0]; } __attribute__ ((packed)); +struct get_total_number_of_items_rsp { + uint8_t status; + uint16_t uid_counter; + uint32_t num_items; +} __attribute__ ((packed)); + struct avrcp_server { struct btd_adapter *adapter; uint32_t tg_record_id; @@ -566,6 +573,9 @@ static void populate_default_features(void) /* supports at least AVRCP 1.4 */ default_features[7] |= (1 << 2); + + /* supports GetTotalNumberOfItems browsing command */ + default_features[8] |= (1 << 3); } static unsigned int attr_get_max_val(uint8_t attr) @@ -2048,10 +2058,56 @@ static void avrcp_handle_get_folder_items(struct avrcp *session, case AVRCP_SCOPE_SEARCH: case AVRCP_SCOPE_NOW_PLAYING: default: + status = AVRCP_STATUS_INVALID_SCOPE; + goto failed; + } + + return; + +failed: + pdu->params[0] = status; + pdu->param_len = htons(1); +} + +static void avrcp_handle_media_player_list_num_items(struct avrcp *session, + struct avrcp_browsing_header *pdu) +{ + struct avrcp_player *player = target_get_player(session); + struct get_total_number_of_items_rsp *rsp; + + rsp = (void *)pdu->params; + rsp->status = AVRCP_STATUS_SUCCESS; + rsp->uid_counter = htons(player_get_uid_counter(player)); + rsp->num_items = htonl(g_slist_length(session->server->players)); + pdu->param_len = htons(sizeof(*rsp)); +} + +static void avrcp_handle_get_total_number_of_items(struct avrcp *session, + struct avrcp_browsing_header *pdu, + uint8_t transaction) +{ + uint8_t scope; + uint8_t status = AVRCP_STATUS_SUCCESS; + + if (ntohs(pdu->param_len) != 1) { status = AVRCP_STATUS_INVALID_PARAM; goto failed; } + scope = pdu->params[0]; + + switch (scope) { + case AVRCP_SCOPE_MEDIA_PLAYER_LIST: + avrcp_handle_media_player_list_num_items(session, pdu); + break; + case AVRCP_SCOPE_MEDIA_PLAYER_VFS: + case AVRCP_SCOPE_SEARCH: + case AVRCP_SCOPE_NOW_PLAYING: + default: + status = AVRCP_STATUS_INVALID_SCOPE; + goto failed; + } + return; failed: @@ -2065,6 +2121,8 @@ static struct browsing_pdu_handler { uint8_t transaction); } browsing_handlers[] = { { AVRCP_GET_FOLDER_ITEMS, avrcp_handle_get_folder_items }, + { AVRCP_GET_TOTAL_NUMBER_OF_ITEMS, + avrcp_handle_get_total_number_of_items }, { }, }; -- 2.28.0.402.g5ffc5be6b7-goog