avrcp: Add handler for GET_TOTAL_NUMBER_OF_ITEMS
authorArchie Pusaka <apusaka@chromium.org>
Wed, 2 Sep 2020 04:57:45 +0000 (12:57 +0800)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 11 Mar 2022 13:38:32 +0000 (19:08 +0530)
According to the AVRCP spec, section 4.5, GetTotalNumberOfItems PDU
is mandatory for TG supporting category 1 or 3.

Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
profiles/audio/avrcp.c

index 73c6f96..906e002 100644 (file)
@@ -78,6 +78,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
@@ -214,6 +215,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;
@@ -626,6 +633,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)
@@ -2225,10 +2235,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:
@@ -2242,6 +2298,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 },
                { },
 };