diff --git a/tools/parser/avrcp.c b/tools/parser/avrcp.c
index 3a16315..c83b70f 100644
--- a/tools/parser/avrcp.c
+++ b/tools/parser/avrcp.c
#define AVC_PANEL_FORWARD 0x4b
#define AVC_PANEL_BACKWARD 0x4c
+/* Packet types */
+#define AVRCP_PACKET_TYPE_SINGLE 0x00
+#define AVRCP_PACKET_TYPE_START 0x01
+#define AVRCP_PACKET_TYPE_CONTINUING 0x02
+#define AVRCP_PACKET_TYPE_END 0x03
+
/* pdu ids */
#define AVRCP_GET_CAPABILITIES 0x10
#define AVRCP_LIST_PLAYER_ATTRIBUTES 0x11
#define AVRCP_PLAY_STATUS_REV_SEEK 0x04
#define AVRCP_PLAY_STATUS_ERROR 0xFF
+static struct avrcp_continuing {
+ uint16_t num;
+ uint16_t size;
+} avrcp_continuing;
+
static const char *ctype2str(uint8_t ctype)
{
switch (ctype & 0x0f) {
}
}
+static const char *pt2str(uint8_t pt)
+{
+ switch (pt) {
+ case AVRCP_PACKET_TYPE_SINGLE:
+ return "Single";
+ case AVRCP_PACKET_TYPE_START:
+ return "Start";
+ case AVRCP_PACKET_TYPE_CONTINUING:
+ return "Continuing";
+ case AVRCP_PACKET_TYPE_END:
+ return "End";
+ default:
+ return "Unknown";
+ }
+}
+
static const char *pdu2str(uint8_t pduid)
{
switch (pduid) {
}
static void avrcp_get_element_attributes_dump(int level, struct frame *frm,
- uint8_t ctype, uint16_t len)
+ uint8_t ctype, uint16_t len,
+ uint8_t pt)
{
uint64_t id;
uint8_t num;
return;
response:
- if (len < 1) {
- printf("PDU Malformed\n");
- raw_dump(level, frm);
- return;
- }
+ if (pt == AVRCP_PACKET_TYPE_SINGLE || pt == AVRCP_PACKET_TYPE_START) {
+ if (len < 1) {
+ printf("PDU Malformed\n");
+ raw_dump(level, frm);
+ return;
+ }
- num = get_u8(frm);
- printf("AttributeCount: 0x%02x\n", num);
+ num = get_u8(frm);
+ avrcp_continuing.num = num;
+ printf("AttributeCount: 0x%02x\n", num);
+ len--;
+ } else {
+ num = avrcp_continuing.num;
+
+ if (avrcp_continuing.size > 0) {
+ uint16_t size;
+
+ if (avrcp_continuing.size > len) {
+ size = len;
+ avrcp_continuing.size -= len;
+ } else {
+ size = avrcp_continuing.size;
+ avrcp_continuing.size = 0;
+ }
+
+ printf("ContinuingAttributeValue: ");
+ for (; size > 0; size--) {
+ uint8_t c = get_u8(frm);
+ printf("%1c", isprint(c) ? c : '.');
+ }
+ printf("\n");
- for (; num > 0; num--) {
+ len -= size;
+ }
+ }
+
+ while (num > 0 && len > 0) {
uint32_t attr;
- uint16_t charset, len;
+ uint16_t charset, attrlen;
p_indent(level, frm);
charset2str(charset));
p_indent(level, frm);
+ attrlen = get_u16(frm);
+ printf("AttributeValueLength: 0x%04x\n", attrlen);
- len = get_u16(frm);
- printf("AttributeValueLength: 0x%04x\n", len);
+ len -= sizeof(attr) + sizeof(charset) + sizeof(attrlen);
+ num--;
p_indent(level, frm);
printf("AttributeValue: ");
- for (; len > 0; len--) {
+ for (; attrlen > 0 && len > 0; attrlen--, len--) {
uint8_t c = get_u8(frm);
printf("%1c", isprint(c) ? c : '.');
}
printf("\n");
+
+ if (attrlen > 0)
+ avrcp_continuing.size = attrlen;
}
+
+ avrcp_continuing.num = num;
}
static const char *playstatus2str(uint8_t status)
pt = get_u8(frm);
len = get_u16(frm);
- printf("AVRCP: %s: pt 0x%02x len 0x%04x\n", pdu2str(pduid), pt, len);
+ printf("AVRCP: %s: pt %s len 0x%04x\n", pdu2str(pduid),
+ pt2str(pt), len);
if (len != frm->len) {
p_indent(level, frm);
avrcp_ct_battery_status_dump(level + 1, frm, ctype, len);
break;
case AVRCP_GET_ELEMENT_ATTRIBUTES:
- avrcp_get_element_attributes_dump(level + 1, frm, ctype, len);
+ avrcp_get_element_attributes_dump(level + 1, frm, ctype, len,
+ pt);
break;
case AVRCP_GET_PLAY_STATUS:
avrcp_get_play_status_dump(level + 1, frm, ctype, len);