Hi Luiz, On Tue, Sep 13, 2011 at 11:40 AM, Luiz Augusto von Dentz <luiz.dentz@xxxxxxxxx> wrote: > Hi Lucas, > > On Tue, Sep 13, 2011 at 5:21 PM, Lucas De Marchi > <lucas.demarchi@xxxxxxxxxxxxxx> wrote: >> If packet_type is not START or SINGLE, we have to continue where we >> stopped from previous packet. Therefore we must store where we left on >> previous packet due to packet size limit. We store both the number of >> attributes missing and the lenght of the last attribute that is missing. >> >> An example interaction for this implementation, obtained with PTS test >> TC_TG_MDI_BV_04_C (I reduced the MTU in order to reproduce it here and >> values between brackets I added now): >> >>> AVCTP: Command : pt 0x00 transaction 2 pid 0x110e >> AV/C: Status: address 0x48 opcode 0x00 >> Subunit: Panel >> Opcode: Vendor Dependent >> Company ID: 0x001958 >> AVRCP: GetElementAttributes: pt Single len 0x0009 >> Identifier: 0x0 (PLAYING) >> AttributeCount: 0x00 >> < AVCTP: Response : pt 0x00 transaction 2 pid 0x110e >> AV/C: Stable: address 0x48 opcode 0x00 >> Subunit: Panel >> Opcode: Vendor Dependent >> Company ID: 0x001958 >> AVRCP: GetElementAttributes: pt Start len 0x0118 >> AttributeCount: 0x04 >> Attribute: 0x00000001 (Title) >> CharsetID: 0x006a (UTF-8) >> AttributeValueLength: 0x001b >> AttributeValue: isso eh um titulo mei longo >> Attribute: 0x00000003 (Album) >> CharsetID: 0x006a (UTF-8) >> AttributeValueLength: 0x00fe >> AttributeValue: super-long-album-name super-long-album-name >> super-long-album-name super-long-album-name super-long-album >> super-long-album-name [... snip... ] super-long-album-name-1234 >>> AVCTP: Command : pt 0x00 transaction 2 pid 0x110e >> AV/C: Control: address 0x48 opcode 0x00 >> Subunit: Panel >> Opcode: Vendor Dependent >> Company ID: 0x001958 >> AVRCP: RequestContinuingResponse: pt Single len 0x0001 >> < AVCTP: Response : pt 0x00 transaction 2 pid 0x110e >> AV/C: Stable: address 0x48 opcode 0x00 >> Subunit: Panel >> Opcode: Vendor Dependent >> Company ID: 0x001958 >> AVRCP: GetElementAttributes: pt End len 0x002a >> ContinuingAttributeValue: 678900000000000000 >> Attribute: 0x00000005 (Track Total) >> CharsetID: 0x006a (UTF-8) >> AttributeValueLength: 0x0002 >> AttributeValue: 30 >> Attribute: 0x00000006 (Genre) >> CharsetID: 0x006a (UTF-8) >> AttributeValueLength: 0x0006 >> AttributeValue: Gospel >> --- >> parser/avrcp.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++--------- >> 1 files changed, 79 insertions(+), 15 deletions(-) >> >> diff --git a/parser/avrcp.c b/parser/avrcp.c >> index 0b98a3e..65d3bda 100644 >> --- a/parser/avrcp.c >> +++ b/parser/avrcp.c >> @@ -87,6 +87,12 @@ >> #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 >> @@ -176,6 +182,11 @@ >> #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) { >> @@ -224,6 +235,22 @@ static const char *opcode2str(uint8_t opcode) >> } >> } >> >> +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) { >> @@ -917,7 +944,8 @@ static const char *mediattr2str(uint32_t attr) >> } >> >> 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; >> @@ -953,18 +981,45 @@ static void avrcp_get_element_attributes_dump(int level, struct frame *frm, >> 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); >> >> @@ -978,19 +1033,26 @@ response: >> 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) >> @@ -1153,7 +1215,8 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype) >> 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); >> @@ -1198,7 +1261,8 @@ static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype) >> 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); >> -- >> 1.7.6.1 > > Ack, please remember to add hcidump to prefix next time. sorry, my git config was not configured right. Lucas De Marchi -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html