static bool avrcp_pdu_packet(struct avctp_frame *avctp_frame, uint8_t ctype, uint8_t indent) { struct l2cap_frame *frame = &avctp_frame->l2cap_frame; uint8_t pduid; uint16_t len; int i; const struct avrcp_ctrl_pdu_data *ctrl_pdu_data = NULL; if (!l2cap_frame_get_u8(frame, &pduid)) return false; if (!l2cap_frame_get_u8(frame, &avctp_frame->pt)) return false; if (!l2cap_frame_get_be16(frame, &len)) return false; print_indent(indent, COLOR_OFF, "AVRCP: ", pdu2str(pduid), COLOR_OFF, " pt %s len 0x%04x", pt2str(avctp_frame->pt), len); if (frame->size != len) return false; if (ctype == 0xA) return avrcp_rejected_packet(frame, indent + 2); for (i = 0; avrcp_ctrl_pdu_table[i].func; i++) { if (avrcp_ctrl_pdu_table[i].pduid == pduid) { ctrl_pdu_data = &avrcp_ctrl_pdu_table[i]; break; } } if (!ctrl_pdu_data || !ctrl_pdu_data->func) { packet_hexdump(frame->data, frame->size); return true; } return ctrl_pdu_data->func(avctp_frame, ctype, len, indent + 2); }
static void avrcp_pdu_dump(int level, struct frame *frm, uint8_t ctype) { uint8_t pduid, pt; uint16_t len; p_indent(level, frm); pduid = get_u8(frm); pt = get_u8(frm); len = get_u16(frm); printf("AVRCP: %s: pt %s len 0x%04x\n", pdu2str(pduid), pt2str(pt), len); if (len != frm->len) { p_indent(level, frm); printf("PDU Malformed\n"); raw_dump(level, frm); 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); break; 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; case AVRCP_GET_CURRENT_PLAYER_VALUE: 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; case AVRCP_GET_PLAYER_ATTRIBUTE_TEXT: 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; 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; case AVRCP_GET_ELEMENT_ATTRIBUTES: 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); break; case AVRCP_REGISTER_NOTIFICATION: avrcp_register_notification_dump(level + 1, frm, ctype, len); break; case AVRCP_SET_ABSOLUTE_VOLUME: avrcp_set_absolute_volume_dump(level + 1, frm, ctype, len); break; case AVRCP_SET_ADDRESSED_PLAYER: avrcp_set_addressed_player(level + 1, frm, ctype, len); break; case AVRCP_SET_BROWSED_PLAYER: avrcp_set_browsed_player(level + 1, frm, ctype, len); break; default: raw_dump(level, frm); } }