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 bool avrcp_displayable_charset(struct avctp_frame *avctp_frame, uint8_t ctype, uint8_t len, uint8_t indent) { struct l2cap_frame *frame = &avctp_frame->l2cap_frame; uint8_t num; if (ctype > AVC_CTYPE_GENERAL_INQUIRY) return true; if (!l2cap_frame_get_u8(frame, &num)) return false; print_field("%*cCharsetCount: 0x%02x", (indent - 8), ' ', num); for (; num > 0; num--) { uint16_t charset; if (!l2cap_frame_get_be16(frame, &charset)) return false; print_field("%*cCharsetID: 0x%04x (%s)", (indent - 8), ' ', charset, charset2str(charset)); } return true; }
static void avrcp_get_element_attributes_dump(int level, struct frame *frm, uint8_t ctype, uint16_t len, uint8_t pt) { 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 (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); 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"); len -= size; } } while (num > 0 && len > 0) { uint32_t attr; uint16_t charset, attrlen; 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); attrlen = get_u16(frm); printf("AttributeValueLength: 0x%04x\n", attrlen); len -= sizeof(attr) + sizeof(charset) + sizeof(attrlen); num--; p_indent(level, frm); printf("AttributeValue: "); 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 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_set_browsed_player(int level, struct frame *frm, uint8_t ctype, uint16_t len) { uint32_t items; uint16_t id, uids, charset; uint8_t status, folders; p_indent(level, frm); if (ctype > AVC_CTYPE_GENERAL_INQUIRY) goto response; if (len < 2) { printf("PDU Malformed\n"); raw_dump(level, frm); return; } id = get_u16(frm); printf("PlayerID: 0x%04x (%u)", id, id); return; response: if (len != 1 && len < 10) { printf("PDU Malformed\n"); raw_dump(level, frm); return; } status = get_u8(frm); printf("Status: 0x%02x (%s)\n", status, error2str(status)); if (len == 1) return; p_indent(level, frm); uids = get_u16(frm); printf("UIDCounter: 0x%04x (%u)", uids, uids); p_indent(level, frm); items = get_u32(frm); printf("Number of Items: 0x%04x (%u)", items, items); p_indent(level, frm); charset = get_u16(frm); printf("CharsetID: 0x%04x (%s)\n", charset, charset2str(charset)); p_indent(level, frm); folders = get_u8(frm); printf("Folder Depth: 0x%02x (%u)", folders, folders); for (; folders > 0; folders--) { uint16_t len; p_indent(level, frm); len = get_u8(frm); printf("Folder: "); for (; len > 0; len--) { uint8_t c = get_u8(frm); printf("%1c", isprint(c) ? c : '.'); } printf("\n"); } }
static bool avrcp_get_player_value_text(struct avctp_frame *avctp_frame, uint8_t ctype, uint8_t len, uint8_t indent) { struct l2cap_frame *frame = &avctp_frame->l2cap_frame; static uint8_t attr = 0; uint8_t num; if (ctype > AVC_CTYPE_GENERAL_INQUIRY) goto response; if (!l2cap_frame_get_u8(frame, &attr)) return false; print_field("%*cAttributeID: 0x%02x (%s)", (indent - 8), ' ', attr, attr2str(attr)); if (!l2cap_frame_get_u8(frame, &num)) return false; print_field("%*cValueCount: 0x%02x", (indent - 8), ' ', num); for (; num > 0; num--) { uint8_t value; if (!l2cap_frame_get_u8(frame, &value)) return false; print_field("%*cValueID: 0x%02x (%s)", (indent - 8), ' ', value, value2str(attr, value)); } return true; response: if (!l2cap_frame_get_u8(frame, &num)) return false; print_field("%*cValueCount: 0x%02x", (indent - 8), ' ', num); for (; num > 0; num--) { uint8_t value, len; uint16_t charset; if (!l2cap_frame_get_u8(frame, &value)) return false; print_field("%*cValueID: 0x%02x (%s)", (indent - 8), ' ', value, value2str(attr, value)); if (!l2cap_frame_get_be16(frame, &charset)) return false; print_field("%*cCharsetIDID: 0x%02x (%s)", (indent - 8), ' ', charset, charset2str(charset)); if (!l2cap_frame_get_u8(frame, &len)) return false; print_field("%*cStringLength: 0x%02x", (indent - 8), ' ', len); printf("String: "); for (; len > 0; len--) { uint8_t c; if (!l2cap_frame_get_u8(frame, &c)) return false; printf("%1c", isprint(c) ? c : '.'); } printf("\n"); } return true; }
static bool avrcp_get_element_attributes(struct avctp_frame *avctp_frame, uint8_t ctype, uint8_t len, uint8_t indent) { struct l2cap_frame *frame = &avctp_frame->l2cap_frame; uint64_t id; uint8_t num; if (ctype > AVC_CTYPE_GENERAL_INQUIRY) goto response; if (!l2cap_frame_get_be64(frame, &id)) return false; print_field("%*cIdentifier: 0x%jx (%s)", (indent - 8), ' ', id, id ? "Reserved" : "PLAYING"); if (!l2cap_frame_get_u8(frame, &num)) return false; print_field("%*cAttributeCount: 0x%02x", (indent - 8), ' ', num); for (; num > 0; num--) { uint32_t attr; if (!l2cap_frame_get_be32(frame, &attr)) return false; print_field("%*cAttribute: 0x%08x (%s)", (indent - 8), ' ', attr, mediattr2str(attr)); } return true; response: switch (avctp_frame->pt) { case AVRCP_PACKET_TYPE_SINGLE: case AVRCP_PACKET_TYPE_START: if (!l2cap_frame_get_u8(frame, &num)) return false; avrcp_continuing.num = num; print_field("%*cAttributeCount: 0x%02x", (indent - 8), ' ', num); len--; break; case AVRCP_PACKET_TYPE_CONTINUING: case AVRCP_PACKET_TYPE_END: 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; if (!l2cap_frame_get_u8(frame, &c)) goto failed; printf("%1c", isprint(c) ? c : '.'); } printf("\n"); len -= size; } break; default: goto failed; } while (num > 0 && len > 0) { uint32_t attr; uint16_t charset, attrlen; if (!l2cap_frame_get_be32(frame, &attr)) goto failed; print_field("%*cAttribute: 0x%08x (%s)", (indent - 8), ' ', attr, mediattr2str(attr)); if (!l2cap_frame_get_be16(frame, &charset)) goto failed; print_field("%*cCharsetID: 0x%04x (%s)", (indent - 8), ' ', charset, charset2str(charset)); if (!l2cap_frame_get_be16(frame, &attrlen)) goto failed; print_field("%*cAttributeValueLength: 0x%04x", (indent - 8), ' ', attrlen); len -= sizeof(attr) + sizeof(charset) + sizeof(attrlen); num--; print_field("%*cAttributeValue: ", (indent - 8), ' '); for (; attrlen > 0 && len > 0; attrlen--, len--) { uint8_t c; if (!l2cap_frame_get_u8(frame, &c)) goto failed; printf("%1c", isprint(c) ? c : '.'); } if (attrlen > 0) avrcp_continuing.size = attrlen; } avrcp_continuing.num = num; return true; failed: avrcp_continuing.num = 0; avrcp_continuing.size = 0; return false; }