summaryrefslogtreecommitdiff
path: root/monitor/avctp.c
diff options
context:
space:
mode:
authorBharat Panda <bharat.panda@samsung.com>2015-04-16 18:46:37 +0530
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2015-04-17 16:48:24 +0300
commitddb01ec67362b71b302cd57d85972895ed294826 (patch)
treef3afe36610ce0bb57aad04426f1876059e9506c3 /monitor/avctp.c
parent45e762c4774f841a5bcc57afdc3ce91227d39964 (diff)
downloadbluez-ddb01ec67362b71b302cd57d85972895ed294826.tar.gz
monitor: Add AVRCP GetFolderItems Support
Support for decoding AVRCP GetFolderItems added in btmon. Channel: 65 len 20 ctrl 0x0000 [PSM 27 mode 3] {chan 1} I-frame: Unsegmented TxSeq 0 ReqSeq 0 AVCTP Browsing: Command: type 0x00 label 0 PID 0x110e AVRCP: GetFolderItems: len 0x000a Scope: 0x01 (Media Player Virtual Filesystem) StartItem: 0x00000000 (0) EndItem: 0x0000000a (10) AttributeCount: 0xff (255) AttributeID: 0x0000326e (Reserved)
Diffstat (limited to 'monitor/avctp.c')
-rw-r--r--monitor/avctp.c112
1 files changed, 110 insertions, 2 deletions
diff --git a/monitor/avctp.c b/monitor/avctp.c
index c599aa46f..c14306116 100644
--- a/monitor/avctp.c
+++ b/monitor/avctp.c
@@ -182,6 +182,11 @@
#define AVRCP_MEDIA_SEARCH 0x02
#define AVRCP_MEDIA_NOW_PLAYING 0x03
+/* Media Item Type */
+#define AVRCP_MEDIA_PLAYER_ITEM_TYPE 0x01
+#define AVRCP_FOLDER_ITEM_TYPE 0x02
+#define AVRCP_MEDIA_ELEMENT_ITEM_TYPE 0x03
+
/* operands in passthrough commands */
#define AVC_PANEL_VOLUME_UP 0x41
#define AVC_PANEL_VOLUME_DOWN 0x42
@@ -677,6 +682,20 @@ static char *op2str(uint8_t op)
}
}
+static const char *type2str(uint8_t type)
+{
+ switch (type) {
+ case AVRCP_MEDIA_PLAYER_ITEM_TYPE:
+ return "Media Player";
+ case AVRCP_FOLDER_ITEM_TYPE:
+ return "Folder";
+ case AVRCP_MEDIA_ELEMENT_ITEM_TYPE:
+ return "Media Element";
+ default:
+ return "Unknown";
+ }
+}
+
static bool avrcp_passthrough_packet(struct avctp_frame *avctp_frame,
uint8_t indent)
{
@@ -1096,10 +1115,10 @@ static bool avrcp_get_element_attributes(struct avctp_frame *avctp_frame,
for (; num > 0; num--) {
uint32_t attr;
- if (!l2cap_frame_get_be32(frame, &attr))
+ if (!l2cap_frame_get_le32(frame, &attr))
return false;
- print_field("%*cAttribute: 0x%08x (%s)", (indent - 8),
+ print_field("%*cAttributeID: 0x%08x (%s)", (indent - 8),
' ', attr, mediattr2str(attr));
}
@@ -1637,6 +1656,92 @@ static bool avrcp_control_packet(struct avctp_frame *avctp_frame)
}
}
+static bool avrcp_get_folder_items(struct avctp_frame *avctp_frame)
+{
+ struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
+ uint8_t scope, count, status, indent = 2;
+ uint32_t start, end;
+ uint16_t uid, num;
+
+ if (avctp_frame->hdr & 0x02)
+ goto response;
+
+ if (!l2cap_frame_get_u8(frame, &scope))
+ return false;
+
+ print_field("%*cScope: 0x%02x (%s)", indent, ' ',
+ scope, scope2str(scope));
+
+ if (!l2cap_frame_get_be32(frame, &start))
+ return false;
+
+ print_field("%*cStartItem: 0x%08x (%u)", indent, ' ', start, start);
+
+ if (!l2cap_frame_get_be32(frame, &end))
+ return false;
+
+ print_field("%*cEndItem: 0x%08x (%u)", indent, ' ', end, end);
+
+ if (!l2cap_frame_get_u8(frame, &count))
+ return false;
+
+ print_field("%*cAttributeCount: 0x%02x (%u)", indent, ' ',
+ count, count);
+
+ for (; count > 0; count--) {
+ uint16_t attr;
+
+ if (!l2cap_frame_get_be16(frame, &attr))
+ return false;
+
+ print_field("%*cAttributeID: 0x%08x (%s)", indent, ' ',
+ attr, mediattr2str(attr));
+ }
+
+ return false;
+
+response:
+ if (!l2cap_frame_get_u8(frame, &status))
+ return false;
+
+ print_field("%*cStatus: 0x%02x (%s)", indent, ' ',
+ status, error2str(status));
+
+ if (!l2cap_frame_get_be16(frame, &uid))
+ return false;
+
+ print_field("%*cUIDCounter: 0x%04x (%u)", indent, ' ', uid, uid);
+
+ if (!l2cap_frame_get_be16(frame, &num))
+ return false;
+
+ print_field("%*cUIDCounter: 0x%04x (%u)", indent, ' ', num, num);
+
+ for (; num > 0; num--) {
+ uint8_t type;
+ uint16_t len;
+
+ if (!l2cap_frame_get_u8(frame, &type))
+ return false;
+
+ if (!l2cap_frame_get_be16(frame, &len))
+ return false;
+
+ print_field("%*cItem: 0x%02x (%s) ", indent, ' ',
+ type, type2str(type));
+ print_field("%*cLength: 0x%04x (%u)", indent, ' ', len, len);
+
+ switch (type) {
+ case AVRCP_MEDIA_PLAYER_ITEM_TYPE:
+ case AVRCP_FOLDER_ITEM_TYPE:
+ case AVRCP_MEDIA_ELEMENT_ITEM_TYPE:
+ packet_hexdump(frame->data, frame->size);
+ break;
+ }
+ }
+ return true;
+}
+
static bool avrcp_set_browsed_player(struct avctp_frame *avctp_frame)
{
struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
@@ -1722,6 +1827,9 @@ static bool avrcp_browsing_packet(struct avctp_frame *avctp_frame)
case AVRCP_SET_BROWSED_PLAYER:
avrcp_set_browsed_player(avctp_frame);
break;
+ case AVRCP_GET_FOLDER_ITEMS:
+ avrcp_get_folder_items(avctp_frame);
+ break;
default:
packet_hexdump(frame->data, frame->size);
}