@@ -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 },
{ },
};