[PATCH hcidump 00/13] AVRCP 1.3 pdus

STALE5529d

18 messages, 2 authors, 2011-08-01 · open the first message on its own page

[PATCH hcidump 00/13] AVRCP 1.3 pdus

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:05

From: Luiz Augusto von Dentz <redacted>

This adds parsing for remaining pdus defined by AVRCP 1.3 spec, here is
an example of what it would generate using current upstream agains Sony
MW600 headset (note that current upstream has a bug in which it sets an
invalid pdu length for not implemented response):
AVCTP: Command : pt 0x00 transaction 5 pid 0x110e 
    AV/C: Status: address 0x48 opcode 0x00
      Subunit: Panel
      Opcode: Vendor Dependent
      Company ID: 0x001958
      AVRCP: GetCapabilities: pt 0x00 len 0x0001
        CapabilityID: 0x02 (CompanyID)
< AVCTP: Response : pt 0x00 transaction 5 pid 0x110e 
    AV/C: Not Implemented: address 0x48 opcode 0x00
      Subunit: Panel
      Opcode: Vendor Dependent
      Company ID: 0x001958
      AVRCP: GetCapabilities: pt 0x00 len 0x0001
      PDU Malformed
AVCTP: Command : pt 0x00 transaction 6 pid 0x110e 
    AV/C: Notify: address 0x48 opcode 0x00
      Subunit: Panel
      Opcode: Vendor Dependent
      Company ID: 0x001958
      AVRCP: RegisterNotification: pt 0x00 len 0x0005
        EventID: 0x02 (EVENT_TRACK_CHANGED)
        Interval: 0x0000000a (10 seconds)
< AVCTP: Response : pt 0x00 transaction 6 pid 0x110e 
    AV/C: Not Implemented: address 0x48 opcode 0x00
      Subunit: Panel
      Opcode: Vendor Dependent
      Company ID: 0x001958
      AVRCP: RegisterNotification: pt 0x00 len 0x0005
      PDU Malformed

Same thing but now using Lucas's tree:

< AVCTP: Response : pt 0x00 transaction 5 pid 0x110e 
    AV/C: Stable: address 0x48 opcode 0x00
      Subunit: Panel
      Opcode: Vendor Dependent
      Company ID: 0x001958
      AVRCP: GetCapabilities: pt 0x00 len 0x0005
        CapabilityID: 0x02 (CompanyID)
        CapabilityCount: 0x01
        CompanyID: 0x001958
AVCTP: Command : pt 0x00 transaction 6 pid 0x110e 
    AV/C: Status: address 0x48 opcode 0x00
      Subunit: Panel
      Opcode: Vendor Dependent
      Company ID: 0x001958
      AVRCP: GetCapabilities: pt 0x00 len 0x0001
        CapabilityID: 0x03 (EventsID)
< AVCTP: Response : pt 0x00 transaction 6 pid 0x110e 
    AV/C: Stable: address 0x48 opcode 0x00
      Subunit: Panel
      Opcode: Vendor Dependent
      Company ID: 0x001958
      AVRCP: GetCapabilities: pt 0x00 len 0x0004
        CapabilityID: 0x03 (EventsID)
        CapabilityCount: 0x02
        EventsID: 0x01 (EVENT_PLAYBACK_STATUS_CHANGED)
        EventsID: 0x02 (EVENT_TRACK_CHANGED)
AVCTP: Command : pt 0x00 transaction 7 pid 0x110e 
    AV/C: Notify: address 0x48 opcode 0x00
      Subunit: Panel
      Opcode: Vendor Dependent
      Company ID: 0x001958
      AVRCP: RegisterNotification: pt 0x00 len 0x0005
        EventID: 0x02 (EVENT_TRACK_CHANGED)
        Interval: 0x0000000a (10 seconds)
< AVCTP: Response : pt 0x00 transaction 7 pid 0x110e 
    AV/C: Interim: address 0x48 opcode 0x00
      Subunit: Panel
      Opcode: Vendor Dependent
      Company ID: 0x001958
      AVRCP: RegisterNotification: pt 0x00 len 0x0009
        EventID: 0x02 (EVENT_TRACK_CHANGED)
        Identifier: 0xffffffffffffffff (Reserved)
AVCTP: Command : pt 0x00 transaction 8 pid 0x110e 
    AV/C: Status: address 0x48 opcode 0x00
      Subunit: Panel
      Opcode: Vendor Dependent
      Company ID: 0x001958
      AVRCP: GetElementAttributes: pt 0x00 len 0x000d
        Identifier: 0x0 (PLAYING)
        AttributeCount: 0x01
        Attribute: 0x00000001 (Title)
< AVCTP: Response : pt 0x00 transaction 8 pid 0x110e 
    AV/C: Stable: address 0x48 opcode 0x00
      Subunit: Panel
      Opcode: Vendor Dependent
      Company ID: 0x001958
      AVRCP: GetElementAttributes: pt 0x00 len 0x0009
        AttributeCount: 0x01
        Attribute: 0x00000001 (Title)
        CharsetID: 0x006a (UTF-8)
        AttributeValueLength: 0x0000
        AttributeValue: 

Luiz Augusto von Dentz (13):
  Don't parse response AVRCP pdu if ctype is NOT_IMPLETED
  Add parsing for command type rejected AVRCP responses
  Add parsing for AVRCP ListPlayerApplicationSettingAttributes pdu
  Add parsing for AVRCP ListPlayerApplicationSettingValues pdu
  Add parsing for AVRCP GetCurrentPlayerApplicationSettingValue pdu
  Add parsing for AVRCP SetPlayerApplicationSettingValue pdu
  Add parsing for AVRCP GetPlayerApplicationSettingAttributeText pdu
  Add parsing for AVRCP GetPlayerApplicationSettingValueText pdu
  Add parsing for AVRCP InformDisplayableCharacterSet pdu
  Add parsing for AVRCP InformBatteryStatusOfCT pdu
  Add parsing for AVRCP GetElementAttributes pdu
  Add parsing for AVRCP GetPlayStatus pdu
  Add parsing for AVRCP RegisterNotification pdu

 parser/avrcp.c |  863 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 863 insertions(+), 0 deletions(-)

-- 
1.7.6

[PATCH hcidump 01/13] Don't parse response AVRCP pdu if ctype is NOT_IMPLETED

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:06

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index ff6862d..a1768e3 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -347,6 +347,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 		return;
 	}
 
+	if (ctype == AVC_CTYPE_NOT_IMPLEMENTED)
+		return;
+
 	switch (pduid) {
 	case AVRCP_GET_CAPABILITIES:
 		avrcp_get_capabilities_dump(level + 1, frm, len);
-- 
1.7.6

[PATCH hcidump 02/13] Add parsing for command type rejected AVRCP responses

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:07

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |   97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 97 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index a1768e3..025805e 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -126,6 +126,30 @@
 #define AVRCP_EVENT_UIDS_CHANGED			0x0c
 #define AVRCP_EVENT_VOLUME_CHANGED			0x0d
 
+/* error statuses */
+#define AVRCP_STATUS_INVALID_COMMAND			0x00
+#define AVRCP_STATUS_INVALID_PARAMETER			0x01
+#define AVRCP_STATUS_NOT_FOUND				0x02
+#define AVRCP_STATUS_INTERNAL_ERROR			0x03
+#define AVRCP_STATUS_SUCCESS				0x04
+#define AVRCP_STATUS_UID_CHANGED			0x05
+#define AVRCP_STATUS_INVALID_DIRECTION			0x07
+#define AVRCP_STATUS_NOT_DIRECTORY			0x08
+#define AVRCP_STATUS_DOES_NOT_EXIST			0x09
+#define AVRCP_STATUS_INVALID_SCOPE			0x0a
+#define AVRCP_STATUS_OUT_OF_BOUNDS			0x0b
+#define AVRCP_STATUS_IS_DIRECTORY			0x0c
+#define AVRCP_STATUS_MEDIA_IN_USE			0x0d
+#define AVRCP_STATUS_NOW_PLAYING_LIST_FULL		0x0e
+#define AVRCP_STATUS_SEARCH_NOT_SUPPORTED		0x0f
+#define AVRCP_STATUS_SEARCH_IN_PROGRESS			0x10
+#define AVRCP_STATUS_INVALID_PLAYER_ID			0x11
+#define AVRCP_STATUS_PLAYER_NOT_BROWSABLE		0x12
+#define AVRCP_STATUS_PLAYER_NOT_ADDRESSED		0x13
+#define AVRCP_STATUS_NO_VALID_SEARCH_RESULTS		0x14
+#define AVRCP_STATUS_NO_AVAILABLE_PLAYERS		0x15
+#define AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED		0x16
+
 static const char *ctype2str(uint8_t ctype)
 {
 	switch (ctype & 0x0f) {
@@ -274,6 +298,74 @@ static char *event2str(uint8_t event)
 	}
 }
 
+static const char *error2str(uint8_t status)
+{
+	switch (status) {
+	case AVRCP_STATUS_INVALID_COMMAND:
+		return "Invalid Command";
+	case AVRCP_STATUS_INVALID_PARAMETER:
+		return "Invalid Parameter";
+	case AVRCP_STATUS_NOT_FOUND:
+		return "Not Found";
+	case AVRCP_STATUS_INTERNAL_ERROR:
+		return "Internal Error";
+	case AVRCP_STATUS_SUCCESS:
+		return "Success";
+	case AVRCP_STATUS_UID_CHANGED:
+		return "UID Changed";
+	case AVRCP_STATUS_INVALID_DIRECTION:
+		return "Invalid Direction";
+	case AVRCP_STATUS_NOT_DIRECTORY:
+		return "Not a Directory";
+	case AVRCP_STATUS_DOES_NOT_EXIST:
+		return "Does Not Exist";
+	case AVRCP_STATUS_INVALID_SCOPE:
+		return "Invalid Scope";
+	case AVRCP_STATUS_OUT_OF_BOUNDS:
+		return "Range Out of Bonds";
+	case AVRCP_STATUS_MEDIA_IN_USE:
+		return "Media in Use";
+	case AVRCP_STATUS_IS_DIRECTORY:
+		return "UID is a Directory";
+	case AVRCP_STATUS_NOW_PLAYING_LIST_FULL:
+		return "Now Playing List Full";
+	case AVRCP_STATUS_SEARCH_NOT_SUPPORTED:
+		return "Seach Not Supported";
+	case AVRCP_STATUS_SEARCH_IN_PROGRESS:
+		return "Search in Progress";
+	case AVRCP_STATUS_INVALID_PLAYER_ID:
+		return "Invalid Player ID";
+	case AVRCP_STATUS_PLAYER_NOT_BROWSABLE:
+		return "Player Not Browsable";
+	case AVRCP_STATUS_PLAYER_NOT_ADDRESSED:
+		return "Player Not Addressed";
+	case AVRCP_STATUS_NO_VALID_SEARCH_RESULTS:
+		return "No Valid Search Result";
+	case AVRCP_STATUS_NO_AVAILABLE_PLAYERS:
+		return "No Available Players";
+	case AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED:
+		return "Addressed Player Changed";
+	default:
+		return "Unknown";
+	}
+}
+
+static void avrcp_rejected_dump(int level, struct frame *frm, uint16_t len)
+{
+	uint8_t status;
+
+	p_indent(level, frm);
+
+	if (len < 1) {
+		printf("PDU Malformed\n");
+		raw_dump(level, frm);
+		return;
+	}
+
+	status = get_u8(frm);
+	printf("Error: 0x%02x (%s)\n", status, error2str(status));
+}
+
 static void avrcp_get_capabilities_dump(int level, struct frame *frm, uint16_t len)
 {
 	uint8_t cap;
@@ -350,6 +442,11 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 	if (ctype == AVC_CTYPE_NOT_IMPLEMENTED)
 		return;
 
+	if (ctype == AVC_CTYPE_REJECTED) {
+		avrcp_rejected_dump(level + 1, frm, len);
+		return;
+	}
+
 	switch (pduid) {
 	case AVRCP_GET_CAPABILITIES:
 		avrcp_get_capabilities_dump(level + 1, frm, len);
-- 
1.7.6

[PATCH hcidump 03/13] Add parsing for AVRCP ListPlayerApplicationSettingAttributes pdu

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:08

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |   51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 025805e..7daba13 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -150,6 +150,13 @@
 #define AVRCP_STATUS_NO_AVAILABLE_PLAYERS		0x15
 #define AVRCP_STATUS_ADDRESSED_PLAYER_CHANGED		0x16
 
+/* player attributes */
+#define AVRCP_ATTRIBUTE_ILEGAL		0x00
+#define AVRCP_ATTRIBUTE_EQUALIZER	0x01
+#define AVRCP_ATTRIBUTE_REPEAT_MODE	0x02
+#define AVRCP_ATTRIBUTE_SHUFFLE		0x03
+#define AVRCP_ATTRIBUTE_SCAN		0x04
+
 static const char *ctype2str(uint8_t ctype)
 {
 	switch (ctype & 0x0f) {
@@ -419,6 +426,47 @@ static void avrcp_get_capabilities_dump(int level, struct frame *frm, uint16_t l
 	}
 }
 
+static const char *attr2str(uint8_t attr)
+{
+	switch (attr) {
+	case AVRCP_ATTRIBUTE_ILEGAL:
+		return "Illegal";
+	case AVRCP_ATTRIBUTE_EQUALIZER:
+		return "Equalizer ON/OFF Status";
+	case AVRCP_ATTRIBUTE_REPEAT_MODE:
+		return "Repeat Mode Status";
+	case AVRCP_ATTRIBUTE_SHUFFLE:
+		return "Shuffle ON/OFF Status";
+	case AVRCP_ATTRIBUTE_SCAN:
+		return "Scan ON/OFF Status";
+	default:
+		return "Unknown";
+	}
+}
+
+static void avrcp_list_player_attributes_dump(int level, struct frame *frm,
+								uint16_t len)
+{
+	uint8_t num;
+
+	if (len == 0)
+		return;
+
+	p_indent(level, frm);
+
+	num = get_u8(frm);
+	printf("AttributeCount: 0x%02x\n", num);
+
+	for (; num > 0; num--) {
+		uint8_t attr;
+
+		p_indent(level, frm);
+
+		attr = get_u8(frm);
+		printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
+	}
+}
+
 static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 {
 	uint8_t pduid, pt;
@@ -451,6 +499,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 	case AVRCP_GET_CAPABILITIES:
 		avrcp_get_capabilities_dump(level + 1, frm, len);
 		break;
+	case AVRCP_LIST_PLAYER_ATTRIBUTES:
+		avrcp_list_player_attributes_dump(level + 1, frm, len);
+		break;
 	default:
 		raw_dump(level, frm);
 	}
-- 
1.7.6

[PATCH hcidump 04/13] Add parsing for AVRCP ListPlayerApplicationSettingValues pdu

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:09

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |   94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 94 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 7daba13..e6f8755 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -467,6 +467,97 @@ static void avrcp_list_player_attributes_dump(int level, struct frame *frm,
 	}
 }
 
+static const char *value2str(uint8_t attr, uint8_t value)
+{
+	switch (attr) {
+	case AVRCP_ATTRIBUTE_ILEGAL:
+		return "Illegal";
+	case AVRCP_ATTRIBUTE_EQUALIZER:
+		switch (value) {
+		case 0x01:
+			return "OFF";
+		case 0x02:
+			return "ON";
+		default:
+			return "Reserved";
+		}
+	case AVRCP_ATTRIBUTE_REPEAT_MODE:
+		switch (value) {
+		case 0x01:
+			return "OFF";
+		case 0x02:
+			return "Single Track Repeat";
+		case 0x03:
+			return "All Track Repeat";
+		case 0x04:
+			return "Group Repeat";
+		default:
+			return "Reserved";
+		}
+	case AVRCP_ATTRIBUTE_SHUFFLE:
+		switch (value) {
+		case 0x01:
+			return "OFF";
+		case 0x02:
+			return "All Track Suffle";
+		case 0x03:
+			return "Group Suffle";
+		default:
+			return "Reserved";
+		}
+	case AVRCP_ATTRIBUTE_SCAN:
+		switch (value) {
+		case 0x01:
+			return "OFF";
+		case 0x02:
+			return "All Track Scan";
+		case 0x03:
+			return "Group Scan";
+		default:
+			return "Reserved";
+		}
+	default:
+		return "Unknown";
+	}
+}
+
+static void avrcp_list_player_values_dump(int level, struct frame *frm,
+						uint8_t ctype, uint16_t len)
+{
+	static uint8_t attr = 0; /* Remember attribute */
+	uint8_t num;
+
+	p_indent(level, frm);
+
+	if (len < 1) {
+		printf("PDU Malformed\n");
+		raw_dump(level, frm);
+		return;
+	}
+
+	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
+		goto response;
+
+	attr = get_u8(frm);
+	printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
+
+	return;
+
+response:
+	num = get_u8(frm);
+	printf("ValueCount: 0x%02x\n", num);
+
+	for (; num > 0; num--) {
+		uint8_t value;
+
+		p_indent(level, frm);
+
+		value = get_u8(frm);
+		printf("ValueID: 0x%02x (%s)\n", value,
+						value2str(attr, value));
+	}
+}
+
 static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 {
 	uint8_t pduid, pt;
@@ -502,6 +593,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 	case AVRCP_LIST_PLAYER_ATTRIBUTES:
 		avrcp_list_player_attributes_dump(level + 1, frm, len);
 		break;
+	case AVRCP_LIST_PLAYER_VALUES:
+		avrcp_list_player_values_dump(level + 1, frm, ctype, len);
+		break;
 	default:
 		raw_dump(level, frm);
 	}
-- 
1.7.6

[PATCH hcidump 05/13] Add parsing for AVRCP GetCurrentPlayerApplicationSettingValue pdu

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:10

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |   59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index e6f8755..bb0dd1d 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -558,6 +558,61 @@ response:
 	}
 }
 
+static void avrcp_get_current_player_value_dump(int level, struct frame *frm,
+						uint8_t ctype, uint16_t len)
+{
+	uint8_t num;
+
+	p_indent(level, frm);
+
+	if (len < 2) {
+		printf("PDU Malformed\n");
+		raw_dump(level, frm);
+		return;
+	}
+
+	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
+		goto response;
+
+	num = get_u8(frm);
+	printf("AttributeCount: 0x%02x\n", num);
+
+	for (; num > 0; num--) {
+		uint8_t attr;
+
+		p_indent(level, frm);
+
+		attr = get_u8(frm);
+		printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
+	}
+
+	return;
+
+response:
+	num = get_u8(frm);
+	printf("ValueCount: 0x%02x\n", num);
+
+	for (; num > 0; num--) {
+		uint8_t attr, player, value;
+
+		p_indent(level, frm);
+
+		attr = get_u8(frm);
+		printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
+
+		p_indent(level, frm);
+
+		player = get_u8(frm);
+		printf("Player: 0x%02x\n", player);
+
+		p_indent(level, frm);
+
+		value = get_u8(frm);
+		printf("ValueID: 0x%02x (%s)\n", value,
+						value2str(attr, value));
+	}
+}
+
 static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 {
 	uint8_t pduid, pt;
@@ -596,6 +651,10 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 	case AVRCP_LIST_PLAYER_VALUES:
 		avrcp_list_player_values_dump(level + 1, frm, ctype, len);
 		break;
+	case AVRCP_GET_CURRENT_PLAYER_VALUE:
+		avrcp_get_current_player_value_dump(level + 1, frm, ctype,
+									len);
+		break;
 	default:
 		raw_dump(level, frm);
 	}
-- 
1.7.6

[PATCH hcidump 06/13] Add parsing for AVRCP SetPlayerApplicationSettingValue pdu

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:11

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |   38 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index bb0dd1d..e07e77b 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -613,6 +613,41 @@ response:
 	}
 }
 
+static void avrcp_set_player_value_dump(int level, struct frame *frm,
+						uint8_t ctype, uint16_t len)
+{
+	uint8_t num;
+
+	p_indent(level, frm);
+
+	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
+		return;
+
+	if (len < 1) {
+		printf("PDU Malformed\n");
+		raw_dump(level, frm);
+		return;
+	}
+
+	num = get_u8(frm);
+	printf("AttributeCount: 0x%02x\n", num);
+
+	for (; num > 0; num--) {
+		uint8_t attr, value;
+
+		p_indent(level, frm);
+
+		attr = get_u8(frm);
+		printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
+
+		p_indent(level, frm);
+
+		value = get_u8(frm);
+		printf("ValueID: 0x%02x (%s)\n", value,
+						value2str(attr, value));
+	}
+}
+
 static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 {
 	uint8_t pduid, pt;
@@ -655,6 +690,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 		avrcp_get_current_player_value_dump(level + 1, frm, ctype,
 									len);
 		break;
+	case AVRCP_SET_PLAYER_VALUE:
+		avrcp_set_player_value_dump(level + 1, frm, ctype, len);
+		break;
 	default:
 		raw_dump(level, frm);
 	}
-- 
1.7.6

[PATCH hcidump 07/13] Add parsing for AVRCP GetPlayerApplicationSettingAttributeText pdu

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:12

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |  100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 100 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index e07e77b..5915cc4 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -30,6 +30,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #include <sys/types.h>
 #include <netinet/in.h>
@@ -648,6 +649,101 @@ static void avrcp_set_player_value_dump(int level, struct frame *frm,
 	}
 }
 
+static const char *charset2str(uint16_t charset)
+{
+	switch (charset) {
+	case 1:
+	case 2:
+		return "Reserved";
+	case 3:
+		return "ASCII";
+	case 4:
+		return "ISO_8859-1";
+	case 5:
+		return "ISO_8859-2";
+	case 6:
+		return "ISO_8859-3";
+	case 7:
+		return "ISO_8859-4";
+	case 8:
+		return "ISO_8859-5";
+	case 9:
+		return "ISO_8859-6";
+	case 10:
+		return "ISO_8859-7";
+	case 11:
+		return "ISO_8859-8";
+	case 12:
+		return "ISO_8859-9";
+	case 106:
+		return "UTF-8";
+	default:
+		return "Unknown";
+	}
+}
+
+static void avrcp_get_player_attribute_text_dump(int level, struct frame *frm,
+						uint8_t ctype, uint16_t len)
+{
+	uint8_t num;
+
+	p_indent(level, frm);
+
+	if (len < 1) {
+		printf("PDU Malformed\n");
+		raw_dump(level, frm);
+		return;
+	}
+
+	num = get_u8(frm);
+	printf("AttributeCount: 0x%02x\n", num);
+
+	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
+		goto response;
+
+	for (; num > 0; num--) {
+		uint8_t attr;
+
+		p_indent(level, frm);
+
+		attr = get_u8(frm);
+		printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
+	}
+
+	return;
+
+response:
+	for (; num > 0; num--) {
+		uint8_t attr, len;
+		uint16_t charset;
+
+		p_indent(level, frm);
+
+		attr = get_u8(frm);
+		printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
+
+		p_indent(level, frm);
+
+		charset = get_u16(frm);
+		printf("CharsetID: 0x%04x (%s)\n", charset,
+							charset2str(charset));
+
+		p_indent(level, frm);
+
+		len = get_u8(frm);
+		printf("StringLength: 0x%02x\n", len);
+
+		p_indent(level, frm);
+
+		printf("String: ");
+		for (; len > 0; len--) {
+			uint8_t c = get_u8(frm);
+			printf("%1c", isprint(c) ? c : '.');
+		}
+		printf("\n");
+	}
+}
+
 static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 {
 	uint8_t pduid, pt;
@@ -693,6 +789,10 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 	case AVRCP_SET_PLAYER_VALUE:
 		avrcp_set_player_value_dump(level + 1, frm, ctype, len);
 		break;
+	case AVRCP_GET_PLAYER_ATTRIBUTE_TEXT:
+		avrcp_get_player_attribute_text_dump(level + 1, frm, ctype,
+									len);
+		break;
 	default:
 		raw_dump(level, frm);
 	}
-- 
1.7.6

[PATCH hcidump 08/13] Add parsing for AVRCP GetPlayerApplicationSettingValueText pdu

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:13

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |   76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 76 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 5915cc4..5fb5cbe 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -744,6 +744,79 @@ response:
 	}
 }
 
+static void avrcp_get_player_value_text_dump(int level, struct frame *frm,
+						uint8_t ctype, uint16_t len)
+{
+	static uint8_t attr = 0; /* Remember attribute */
+	uint8_t num;
+
+	p_indent(level, frm);
+
+	if (len < 1) {
+		printf("PDU Malformed\n");
+		raw_dump(level, frm);
+		return;
+	}
+
+	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
+		goto response;
+
+	attr = get_u8(frm);
+	printf("AttributeID: 0x%02x (%s)\n", attr, attr2str(attr));
+
+	p_indent(level, frm);
+
+	num = get_u8(frm);
+	printf("ValueCount: 0x%02x\n", num);
+
+	for (; num > 0; num--) {
+		uint8_t value;
+
+		p_indent(level, frm);
+
+		value = get_u8(frm);
+		printf("ValueID: 0x%02x (%s)\n", value,
+						value2str(attr, value));
+	}
+
+	return;
+
+response:
+	num = get_u8(frm);
+	printf("ValueCount: 0x%02x\n", num);
+
+	for (; num > 0; num--) {
+		uint8_t value, len;
+		uint16_t charset;
+
+		p_indent(level, frm);
+
+		value = get_u8(frm);
+		printf("ValueID: 0x%02x (%s)\n", value,
+						value2str(attr, value));
+
+		p_indent(level, frm);
+
+		charset = get_u16(frm);
+		printf("CharsetID: 0x%04x (%s)\n", charset,
+							charset2str(charset));
+
+		p_indent(level, frm);
+
+		len = get_u8(frm);
+		printf("StringLength: 0x%02x\n", len);
+
+		p_indent(level, frm);
+
+		printf("String: ");
+		for (; len > 0; len--) {
+			uint8_t c = get_u8(frm);
+			printf("%1c", isprint(c) ? c : '.');
+		}
+		printf("\n");
+	}
+}
+
 static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 {
 	uint8_t pduid, pt;
@@ -793,6 +866,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 		avrcp_get_player_attribute_text_dump(level + 1, frm, ctype,
 									len);
 		break;
+	case AVRCP_GET_PLAYER_VALUE_TEXT:
+		avrcp_get_player_value_text_dump(level + 1, frm, ctype, len);
+		break;
 	default:
 		raw_dump(level, frm);
 	}
-- 
1.7.6

[PATCH hcidump 09/13] Add parsing for AVRCP InformDisplayableCharacterSet pdu

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:14

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 5fb5cbe..ababe03 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -817,6 +817,36 @@ response:
 	}
 }
 
+static void avrcp_displayable_charset(int level, struct frame *frm,
+						uint8_t ctype, uint16_t len)
+{
+	uint8_t num;
+
+	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
+		return;
+
+	p_indent(level, frm);
+
+	if (len < 2) {
+		printf("PDU Malformed\n");
+		raw_dump(level, frm);
+		return;
+	}
+
+	num = get_u8(frm);
+	printf("CharsetCount: 0x%02x\n", num);
+
+	for (; num > 0; num--) {
+		uint16_t charset;
+
+		p_indent(level, frm);
+
+		charset = get_u16(frm);
+		printf("CharsetID: 0x%04x (%s)\n", charset,
+							charset2str(charset));
+	}
+}
+
 static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 {
 	uint8_t pduid, pt;
@@ -869,6 +899,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 	case AVRCP_GET_PLAYER_VALUE_TEXT:
 		avrcp_get_player_value_text_dump(level + 1, frm, ctype, len);
 		break;
+	case AVRCP_DISPLAYABLE_CHARSET:
+		avrcp_displayable_charset(level + 1, frm, ctype, len);
+		break;
 	default:
 		raw_dump(level, frm);
 	}
-- 
1.7.6

[PATCH hcidump 10/13] Add parsing for AVRCP InformBatteryStatusOfCT pdu

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:15

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |   35 +++++++++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index ababe03..bb7bcbb 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -847,6 +847,38 @@ static void avrcp_displayable_charset(int level, struct frame *frm,
 	}
 }
 
+static const char *status2str(uint8_t status)
+{
+	switch (status) {
+	case 0x0:
+		return "NORMAL";
+	case 0x1:
+		return "WARNING";
+	case 0x2:
+		return "CRITICAL";
+	case 0x3:
+		return "EXTERNAL";
+	case 0x4:
+		return "FULL_CHARGE";
+	default:
+		return "Reserved";
+	}
+}
+
+static void avrcp_ct_battery_status_dump(int level, struct frame *frm,
+						uint8_t ctype, uint16_t len)
+{
+	uint8_t status;
+
+	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
+		return;
+
+	p_indent(level, frm);
+
+	status = get_u8(frm);
+	printf("BatteryStatus: 0x%02x (%s)\n", status, status2str(status));
+}
+
 static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 {
 	uint8_t pduid, pt;
@@ -902,6 +934,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 	case AVRCP_DISPLAYABLE_CHARSET:
 		avrcp_displayable_charset(level + 1, frm, ctype, len);
 		break;
+	case AVRCP_CT_BATTERY_STATUS:
+		avrcp_ct_battery_status_dump(level + 1, frm, ctype, len);
+		break;
 	default:
 		raw_dump(level, frm);
 	}
-- 
1.7.6

[PATCH hcidump 11/13] Add parsing for AVRCP GetElementAttributes pdu

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:16

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |  114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 114 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index bb7bcbb..49a7145 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -158,6 +158,16 @@
 #define AVRCP_ATTRIBUTE_SHUFFLE		0x03
 #define AVRCP_ATTRIBUTE_SCAN		0x04
 
+/* media attributes */
+#define AVRCP_MEDIA_ATTRIBUTE_ILLEGAL	0x0
+#define AVRCP_MEDIA_ATTRIBUTE_TITLE	0x1
+#define AVRCP_MEDIA_ATTRIBUTE_ARTIST	0x2
+#define AVRCP_MEDIA_ATTRIBUTE_ALBUM	0x3
+#define AVRCP_MEDIA_ATTRIBUTE_TRACK	0x4
+#define AVRCP_MEDIA_ATTRIBUTE_TOTAL	0x5
+#define AVRCP_MEDIA_ATTRIBUTE_GENRE	0x6
+#define AVRCP_MEDIA_ATTRIBUTE_PROGRESS	0x7
+
 static const char *ctype2str(uint8_t ctype)
 {
 	switch (ctype & 0x0f) {
@@ -879,6 +889,107 @@ static void avrcp_ct_battery_status_dump(int level, struct frame *frm,
 	printf("BatteryStatus: 0x%02x (%s)\n", status, status2str(status));
 }
 
+static const char *mediattr2str(uint32_t attr)
+{
+	switch (attr) {
+	case AVRCP_MEDIA_ATTRIBUTE_ILLEGAL:
+		return "Illegal";
+	case AVRCP_MEDIA_ATTRIBUTE_TITLE:
+		return "Title";
+	case AVRCP_MEDIA_ATTRIBUTE_ARTIST:
+		return "Artist";
+	case AVRCP_MEDIA_ATTRIBUTE_ALBUM:
+		return "Album";
+	case AVRCP_MEDIA_ATTRIBUTE_TRACK:
+		return "Track";
+	case AVRCP_MEDIA_ATTRIBUTE_TOTAL:
+		return "Track Total";
+	case AVRCP_MEDIA_ATTRIBUTE_GENRE:
+		return "Genre";
+	case AVRCP_MEDIA_ATTRIBUTE_PROGRESS:
+		return "Progress";
+	default:
+		return "Reserved";
+	}
+}
+
+static void avrcp_get_element_attributes_dump(int level, struct frame *frm,
+						uint8_t ctype, uint16_t len)
+{
+	uint64_t id;
+	uint8_t num;
+
+	p_indent(level, frm);
+
+	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
+		goto response;
+
+	if (len < 9) {
+		printf("PDU Malformed\n");
+		raw_dump(level, frm);
+		return;
+	}
+
+	id = get_u64(frm);
+	printf("Identifier: 0x%jx (%s)\n", id, id ? "Reserved" : "PLAYING");
+
+	p_indent(level, frm);
+
+	num = get_u8(frm);
+	printf("AttributeCount: 0x%02x\n", num);
+
+	for (; num > 0; num--) {
+		uint32_t attr;
+
+		p_indent(level, frm);
+
+		attr = get_u32(frm);
+		printf("Attribute: 0x%08x (%s)\n", attr, mediattr2str(attr));
+	}
+
+	return;
+
+response:
+	if (len < 1) {
+		printf("PDU Malformed\n");
+		raw_dump(level, frm);
+		return;
+	}
+
+	num = get_u8(frm);
+	printf("AttributeCount: 0x%02x\n", num);
+
+	for (; num > 0; num--) {
+		uint32_t attr;
+		uint16_t charset, len;
+
+		p_indent(level, frm);
+
+		attr = get_u32(frm);
+		printf("Attribute: 0x%08x (%s)\n", attr, mediattr2str(attr));
+
+		p_indent(level, frm);
+
+		charset = get_u16(frm);
+		printf("CharsetID: 0x%04x (%s)\n", charset,
+							charset2str(charset));
+
+		p_indent(level, frm);
+
+		len = get_u16(frm);
+		printf("AttributeValueLength: 0x%04x\n", len);
+
+		p_indent(level, frm);
+
+		printf("AttributeValue: ");
+		for (; len > 0; len--) {
+			uint8_t c = get_u8(frm);
+			printf("%1c", isprint(c) ? c : '.');
+		}
+		printf("\n");
+	}
+}
+
 static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 {
 	uint8_t pduid, pt;
@@ -937,6 +1048,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 	case AVRCP_CT_BATTERY_STATUS:
 		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);
+		break;
 	default:
 		raw_dump(level, frm);
 	}
-- 
1.7.6

[PATCH hcidump 12/13] Add parsing for AVRCP GetPlayStatus pdu

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:17

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 62 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 49a7145..07a93ad 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -168,6 +168,14 @@
 #define AVRCP_MEDIA_ATTRIBUTE_GENRE	0x6
 #define AVRCP_MEDIA_ATTRIBUTE_PROGRESS	0x7
 
+/* play status */
+#define AVRCP_PLAY_STATUS_STOPPED	0x00
+#define AVRCP_PLAY_STATUS_PLAYING	0x01
+#define AVRCP_PLAY_STATUS_PAUSED	0x02
+#define AVRCP_PLAY_STATUS_FWD_SEEK	0x03
+#define AVRCP_PLAY_STATUS_REV_SEEK	0x04
+#define AVRCP_PLAY_STATUS_ERROR		0xFF
+
 static const char *ctype2str(uint8_t ctype)
 {
 	switch (ctype & 0x0f) {
@@ -990,6 +998,57 @@ response:
 	}
 }
 
+static const char *playstatus2str(uint8_t status)
+{
+	switch (status) {
+	case AVRCP_PLAY_STATUS_STOPPED:
+		return "STOPPED";
+	case AVRCP_PLAY_STATUS_PLAYING:
+		return "PLAYING";
+	case AVRCP_PLAY_STATUS_PAUSED:
+		return "PAUSED";
+	case AVRCP_PLAY_STATUS_FWD_SEEK:
+		return "FWD_SEEK";
+	case AVRCP_PLAY_STATUS_REV_SEEK:
+		return "REV_SEEK";
+	case AVRCP_PLAY_STATUS_ERROR:
+		return "ERROR";
+	default:
+		return "Unknown";
+	}
+}
+
+static void avrcp_get_play_status_dump(int level, struct frame *frm,
+						uint8_t ctype, uint16_t len)
+{
+	uint32_t interval;
+	uint8_t status;
+
+	if (ctype <= AVC_CTYPE_GENERAL_INQUIRY)
+		return;
+
+	p_indent(level, frm);
+
+	if (len < 9) {
+		printf("PDU Malformed\n");
+		raw_dump(level, frm);
+		return;
+	}
+
+	interval = get_u32(frm);
+	printf("SongLength: 0x%08x (%u miliseconds)\n", interval, interval);
+
+	p_indent(level, frm);
+
+	interval = get_u32(frm);
+	printf("SongPosition: 0x%08x (%u miliconds)\n", interval, interval);
+
+	p_indent(level, frm);
+
+	status = get_u8(frm);
+	printf("PlayStatus: 0x%02x (%s)\n", status, playstatus2str(status));
+}
+
 static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 {
 	uint8_t pduid, pt;
@@ -1051,6 +1110,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 	case AVRCP_GET_ELEMENT_ATTRIBUTES:
 		avrcp_get_element_attributes_dump(level + 1, frm, ctype, len);
 		break;
+	case AVRCP_GET_PLAY_STATUS:
+		avrcp_get_play_status_dump(level + 1, frm, ctype, len);
+		break;
 	default:
 		raw_dump(level, frm);
 	}
-- 
1.7.6

[PATCH hcidump 13/13] Add parsing for AVRCP RegisterNotification pdu

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 08:42:18

From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 101 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index 07a93ad..8412ccf 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -1049,6 +1049,104 @@ static void avrcp_get_play_status_dump(int level, struct frame *frm,
 	printf("PlayStatus: 0x%02x (%s)\n", status, playstatus2str(status));
 }
 
+static void avrcp_register_notification_dump(int level, struct frame *frm,
+						uint8_t ctype, uint16_t len)
+{
+	uint8_t event, status;
+	uint32_t interval;
+	uint64_t id;
+
+	p_indent(level, frm);
+
+	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
+		goto response;
+
+	if (len < 5) {
+		printf("PDU Malformed\n");
+		raw_dump(level, frm);
+		return;
+	}
+
+	event = get_u8(frm);
+	printf("EventID: 0x%02x (%s)\n", event, event2str(event));
+
+	p_indent(level, frm);
+
+	interval = get_u32(frm);
+	printf("Interval: 0x%08x (%u seconds)\n", interval, interval);
+
+	return;
+
+response:
+	if (len < 1) {
+		printf("PDU Malformed\n");
+		raw_dump(level, frm);
+		return;
+	}
+
+	event = get_u8(frm);
+	printf("EventID: 0x%02x (%s)\n", event, event2str(event));
+
+	p_indent(level, frm);
+
+	switch (event) {
+	case AVRCP_EVENT_PLAYBACK_STATUS_CHANGED:
+		status = get_u8(frm);
+		printf("PlayStatus: 0x%02x (%s)\n", status,
+						playstatus2str(status));
+		break;
+	case AVRCP_EVENT_TRACK_CHANGED:
+		id = get_u64(frm);
+		printf("Identifier: 0x%jx (%s)\n", id,
+						id ? "Reserved" : "PLAYING");
+		break;
+	case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
+		interval = get_u32(frm);
+		printf("Position: 0x%08x (%u miliseconds)\n", interval,
+								interval);
+		break;
+	case AVRCP_EVENT_BATT_STATUS_CHANGED:
+		status = get_u8(frm);
+		printf("BatteryStatus: 0x%02x (%s)\n", status,
+							status2str(status));
+		break;
+	case AVRCP_EVENT_SYSTEM_STATUS_CHANGED:
+		status = get_u8(frm);
+		printf("SystemStatus: 0x%02x ", status);
+		switch (status) {
+		case 0x00:
+			printf("(POWER_ON)\n");
+		case 0x01:
+			printf("(POWER_OFF)\n");
+		case 0x02:
+			printf("(UNPLUGGED)\n");
+		default:
+			printf("(UNKOWN)\n");
+		}
+		break;
+	case AVRCP_EVENT_PLAYER_APPLICATION_SETTING_CHANGED:
+		status = get_u8(frm);
+		printf("AttributeCount: 0x%02x\n", status);
+
+		for (; status > 0; status--) {
+			uint8_t attr, value;
+
+			p_indent(level, frm);
+
+			attr = get_u8(frm);
+			printf("AttributeID: 0x%02x (%s)\n", attr,
+							attr2str(attr));
+
+			p_indent(level, frm);
+
+			value = get_u8(frm);
+			printf("ValueID: 0x%02x (%s)\n", value,
+						value2str(attr, value));
+		}
+		break;
+	}
+}
+
 static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 {
 	uint8_t pduid, pt;
@@ -1113,6 +1211,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
 	case AVRCP_GET_PLAY_STATUS:
 		avrcp_get_play_status_dump(level + 1, frm, ctype, len);
 		break;
+	case AVRCP_REGISTER_NOTIFICATION:
+		avrcp_register_notification_dump(level + 1, frm, ctype, len);
+		break;
 	default:
 		raw_dump(level, frm);
 	}
-- 
1.7.6

Re: [PATCH hcidump 00/13] AVRCP 1.3 pdus

From: Lucas De Marchi <hidden>
Date: 2011-08-01 13:25:11

Hi Luiz

On Mon, Aug 1, 2011 at 5:42 AM, Luiz Augusto von Dentz
[off-list ref] wrote:
From: Luiz Augusto von Dentz <redacted>

This adds parsing for remaining pdus defined by AVRCP 1.3 spec, here is
an example of what it would generate using current upstream agains Sony
MW600 headset (note that current upstream has a bug in which it sets an
invalid pdu length for not implemented response):
quoted
AVCTP: Command : pt 0x00 transaction 5 pid 0x110e
   AV/C: Status: address 0x48 opcode 0x00
     Subunit: Panel
     Opcode: Vendor Dependent
     Company ID: 0x001958
     AVRCP: GetCapabilities: pt 0x00 len 0x0001
       CapabilityID: 0x02 (CompanyID)
< AVCTP: Response : pt 0x00 transaction 5 pid 0x110e
   AV/C: Not Implemented: address 0x48 opcode 0x00
     Subunit: Panel
     Opcode: Vendor Dependent
     Company ID: 0x001958
     AVRCP: GetCapabilities: pt 0x00 len 0x0001
     PDU Malformed
quoted
AVCTP: Command : pt 0x00 transaction 6 pid 0x110e
   AV/C: Notify: address 0x48 opcode 0x00
     Subunit: Panel
     Opcode: Vendor Dependent
     Company ID: 0x001958
     AVRCP: RegisterNotification: pt 0x00 len 0x0005
       EventID: 0x02 (EVENT_TRACK_CHANGED)
       Interval: 0x0000000a (10 seconds)
< AVCTP: Response : pt 0x00 transaction 6 pid 0x110e
   AV/C: Not Implemented: address 0x48 opcode 0x00
     Subunit: Panel
     Opcode: Vendor Dependent
     Company ID: 0x001958
     AVRCP: RegisterNotification: pt 0x00 len 0x0005
     PDU Malformed

Same thing but now using Lucas's tree:

< AVCTP: Response : pt 0x00 transaction 5 pid 0x110e
   AV/C: Stable: address 0x48 opcode 0x00
     Subunit: Panel
     Opcode: Vendor Dependent
     Company ID: 0x001958
     AVRCP: GetCapabilities: pt 0x00 len 0x0005
       CapabilityID: 0x02 (CompanyID)
       CapabilityCount: 0x01
       CompanyID: 0x001958
quoted
AVCTP: Command : pt 0x00 transaction 6 pid 0x110e
   AV/C: Status: address 0x48 opcode 0x00
     Subunit: Panel
     Opcode: Vendor Dependent
     Company ID: 0x001958
     AVRCP: GetCapabilities: pt 0x00 len 0x0001
       CapabilityID: 0x03 (EventsID)
< AVCTP: Response : pt 0x00 transaction 6 pid 0x110e
   AV/C: Stable: address 0x48 opcode 0x00
     Subunit: Panel
     Opcode: Vendor Dependent
     Company ID: 0x001958
     AVRCP: GetCapabilities: pt 0x00 len 0x0004
       CapabilityID: 0x03 (EventsID)
       CapabilityCount: 0x02
       EventsID: 0x01 (EVENT_PLAYBACK_STATUS_CHANGED)
       EventsID: 0x02 (EVENT_TRACK_CHANGED)
quoted
AVCTP: Command : pt 0x00 transaction 7 pid 0x110e
   AV/C: Notify: address 0x48 opcode 0x00
     Subunit: Panel
     Opcode: Vendor Dependent
     Company ID: 0x001958
     AVRCP: RegisterNotification: pt 0x00 len 0x0005
       EventID: 0x02 (EVENT_TRACK_CHANGED)
       Interval: 0x0000000a (10 seconds)
< AVCTP: Response : pt 0x00 transaction 7 pid 0x110e
   AV/C: Interim: address 0x48 opcode 0x00
     Subunit: Panel
     Opcode: Vendor Dependent
     Company ID: 0x001958
     AVRCP: RegisterNotification: pt 0x00 len 0x0009
       EventID: 0x02 (EVENT_TRACK_CHANGED)
       Identifier: 0xffffffffffffffff (Reserved)
quoted
AVCTP: Command : pt 0x00 transaction 8 pid 0x110e
   AV/C: Status: address 0x48 opcode 0x00
     Subunit: Panel
     Opcode: Vendor Dependent
     Company ID: 0x001958
     AVRCP: GetElementAttributes: pt 0x00 len 0x000d
       Identifier: 0x0 (PLAYING)
       AttributeCount: 0x01
       Attribute: 0x00000001 (Title)
< AVCTP: Response : pt 0x00 transaction 8 pid 0x110e
   AV/C: Stable: address 0x48 opcode 0x00
     Subunit: Panel
     Opcode: Vendor Dependent
     Company ID: 0x001958
     AVRCP: GetElementAttributes: pt 0x00 len 0x0009
       AttributeCount: 0x01
       Attribute: 0x00000001 (Title)
       CharsetID: 0x006a (UTF-8)
       AttributeValueLength: 0x0000
       AttributeValue:
Nice, I've been using this with my implementation of AVRCP 1.3 and
it's working fine.

thanks,
Lucas De Marchi

Re: [PATCH hcidump 01/13] Don't parse response AVRCP pdu if ctype is NOT_IMPLETED

From: Lucas De Marchi <hidden>
Date: 2011-08-01 14:11:39

On Mon, Aug 1, 2011 at 5:42 AM, Luiz Augusto von Dentz
[off-list ref] wrote:
quoted hunk
From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index ff6862d..a1768e3 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -347,6 +347,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
               return;
       }

+       if (ctype == AVC_CTYPE_NOT_IMPLEMENTED)
+               return;
+
From my reading of the spec, this check should be in avrcp_dump()
function -- like you did for skipping non-panel subunit packets. This
is because in the not-implemented case, only the avctp + avrcp headers
are sent, with no operands inside.

In AVRCP 1.3, section 4.3.4:

"All of the operands are optional and are defined based on the values
of ctype, subunit_type, and opcode."

In case ctype == NOT_IMPLEMENTED, there isn't any operand.



Lucas De Marchi

Re: [PATCH hcidump 01/13] Don't parse response AVRCP pdu if ctype is NOT_IMPLETED

From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2011-08-01 15:25:53

Hi Lucas,

On Mon, Aug 1, 2011 at 5:11 PM, Lucas De Marchi
[off-list ref] wrote:
On Mon, Aug 1, 2011 at 5:42 AM, Luiz Augusto von Dentz
[off-list ref] wrote:
quoted
From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index ff6862d..a1768e3 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -347,6 +347,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
               return;
       }

+       if (ctype == AVC_CTYPE_NOT_IMPLEMENTED)
+               return;
+
From my reading of the spec, this check should be in avrcp_dump()
function -- like you did for skipping non-panel subunit packets. This
is because in the not-implemented case, only the avctp + avrcp headers
are sent, with no operands inside.
In AVRCP 1.3, section 4.3.4:

"All of the operands are optional and are defined based on the values
of ctype, subunit_type, and opcode."

In case ctype == NOT_IMPLEMENTED, there isn't any operand.
But apparently the avrcp header indicates it length wrong (!= 0), also
avrcp_pdu_dump is called to print the avrcp header but perhaps the
header itself is already considered an operand and in that should not
even that should be present in the response.


-- 
Luiz Augusto von Dentz

Re: [PATCH hcidump 01/13] Don't parse response AVRCP pdu if ctype is NOT_IMPLETED

From: Lucas De Marchi <hidden>
Date: 2011-08-01 15:44:25

On Mon, Aug 1, 2011 at 12:25 PM, Luiz Augusto von Dentz
[off-list ref] wrote:
Hi Lucas,

On Mon, Aug 1, 2011 at 5:11 PM, Lucas De Marchi
[off-list ref] wrote:
quoted
On Mon, Aug 1, 2011 at 5:42 AM, Luiz Augusto von Dentz
[off-list ref] wrote:
quoted
From: Luiz Augusto von Dentz <redacted>

---
 parser/avrcp.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/parser/avrcp.c b/parser/avrcp.c
index ff6862d..a1768e3 100644
--- a/parser/avrcp.c
+++ b/parser/avrcp.c
@@ -347,6 +347,9 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype)
               return;
       }

+       if (ctype == AVC_CTYPE_NOT_IMPLEMENTED)
+               return;
+
From my reading of the spec, this check should be in avrcp_dump()
function -- like you did for skipping non-panel subunit packets. This
is because in the not-implemented case, only the avctp + avrcp headers
are sent, with no operands inside.
In AVRCP 1.3, section 4.3.4:

"All of the operands are optional and are defined based on the values
of ctype, subunit_type, and opcode."

In case ctype == NOT_IMPLEMENTED, there isn't any operand.
But apparently the avrcp header indicates it length wrong (!= 0), also
You should not be reading this field because:
avrcp_pdu_dump is called to print the avrcp header but perhaps the
header itself is already considered an operand and in that should not
even that should be present in the response.
And it's not in the response as far as I could check.


Lucas De Marchi
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help