Blame monitor/avdtp.c

Packit Service 8264ee
/*
Packit Service 8264ee
 *
Packit Service 8264ee
 *  BlueZ - Bluetooth protocol stack for Linux
Packit Service 8264ee
 *
Packit Service 8264ee
 *  Copyright (C) 2015  Andrzej Kaczmarek <andrzej.kaczmarek@codecoup.pl>
Packit Service 8264ee
 *
Packit Service 8264ee
 *
Packit Service 8264ee
 *  This library is free software; you can redistribute it and/or
Packit Service 8264ee
 *  modify it under the terms of the GNU Lesser General Public
Packit Service 8264ee
 *  License as published by the Free Software Foundation; either
Packit Service 8264ee
 *  version 2.1 of the License, or (at your option) any later version.
Packit Service 8264ee
 *
Packit Service 8264ee
 *  This library is distributed in the hope that it will be useful,
Packit Service 8264ee
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 8264ee
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 8264ee
 *  Lesser General Public License for more details.
Packit Service 8264ee
 *
Packit Service 8264ee
 *  You should have received a copy of the GNU Lesser General Public
Packit Service 8264ee
 *  License along with this library; if not, write to the Free Software
Packit Service 8264ee
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
Packit Service 8264ee
 *
Packit Service 8264ee
 */
Packit Service 8264ee
Packit Service 8264ee
#ifdef HAVE_CONFIG_H
Packit Service 8264ee
#include <config.h>
Packit Service 8264ee
#endif
Packit Service 8264ee
Packit Service 8264ee
#define _GNU_SOURCE
Packit Service 8264ee
#include <stdio.h>
Packit Service 8264ee
#include <stdlib.h>
Packit Service 8264ee
#include <string.h>
Packit Service 8264ee
Packit Service 8264ee
#include "lib/bluetooth.h"
Packit Service 8264ee
Packit Service 8264ee
#include "src/shared/util.h"
Packit Service 8264ee
#include "bt.h"
Packit Service 8264ee
#include "packet.h"
Packit Service 8264ee
#include "display.h"
Packit Service 8264ee
#include "l2cap.h"
Packit Service 8264ee
#include "avdtp.h"
Packit Service 8264ee
#include "a2dp.h"
Packit Service 8264ee
Packit Service 8264ee
/* Message Types */
Packit Service 8264ee
#define AVDTP_MSG_TYPE_COMMAND		0x00
Packit Service 8264ee
#define AVDTP_MSG_TYPE_GENERAL_REJECT	0x01
Packit Service 8264ee
#define AVDTP_MSG_TYPE_RESPONSE_ACCEPT	0x02
Packit Service 8264ee
#define AVDTP_MSG_TYPE_RESPONSE_REJECT	0x03
Packit Service 8264ee
Packit Service 8264ee
/* Signal Identifiers */
Packit Service 8264ee
#define AVDTP_DISCOVER			0x01
Packit Service 8264ee
#define AVDTP_GET_CAPABILITIES		0x02
Packit Service 8264ee
#define AVDTP_SET_CONFIGURATION		0x03
Packit Service 8264ee
#define AVDTP_GET_CONFIGURATION		0x04
Packit Service 8264ee
#define AVDTP_RECONFIGURE		0x05
Packit Service 8264ee
#define AVDTP_OPEN			0x06
Packit Service 8264ee
#define AVDTP_START			0x07
Packit Service 8264ee
#define AVDTP_CLOSE			0x08
Packit Service 8264ee
#define AVDTP_SUSPEND			0x09
Packit Service 8264ee
#define AVDTP_ABORT			0x0a
Packit Service 8264ee
#define AVDTP_SECURITY_CONTROL		0x0b
Packit Service 8264ee
#define AVDTP_GET_ALL_CAPABILITIES	0x0c
Packit Service 8264ee
#define AVDTP_DELAYREPORT		0x0d
Packit Service 8264ee
Packit Service 8264ee
/* Service Categories */
Packit Service 8264ee
#define AVDTP_MEDIA_TRANSPORT		0x01
Packit Service 8264ee
#define AVDTP_REPORTING			0x02
Packit Service 8264ee
#define AVDTP_RECOVERY			0x03
Packit Service 8264ee
#define AVDTP_CONTENT_PROTECTION	0x04
Packit Service 8264ee
#define AVDTP_HEADER_COMPRESSION	0x05
Packit Service 8264ee
#define AVDTP_MULTIPLEXING		0x06
Packit Service 8264ee
#define AVDTP_MEDIA_CODEC		0x07
Packit Service 8264ee
#define AVDTP_DELAY_REPORTING		0x08
Packit Service 8264ee
Packit Service 8264ee
struct avdtp_frame {
Packit Service 8264ee
	uint8_t hdr;
Packit Service 8264ee
	uint8_t sig_id;
Packit Service 8264ee
	struct l2cap_frame l2cap_frame;
Packit Service 8264ee
};
Packit Service 8264ee
Packit Service 8264ee
static inline bool is_configuration_sig_id(uint8_t sig_id)
Packit Service 8264ee
{
Packit Service 8264ee
	return (sig_id == AVDTP_SET_CONFIGURATION) ||
Packit Service 8264ee
			(sig_id == AVDTP_GET_CONFIGURATION) ||
Packit Service 8264ee
			(sig_id == AVDTP_RECONFIGURE);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static const char *msgtype2str(uint8_t msgtype)
Packit Service 8264ee
{
Packit Service 8264ee
	switch (msgtype) {
Packit Service 8264ee
	case 0:
Packit Service 8264ee
		return "Command";
Packit Service 8264ee
	case 1:
Packit Service 8264ee
		return "General Reject";
Packit Service 8264ee
	case 2:
Packit Service 8264ee
		return "Response Accept";
Packit Service 8264ee
	case 3:
Packit Service 8264ee
		return "Response Reject";
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return "";
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static const char *sigid2str(uint8_t sigid)
Packit Service 8264ee
{
Packit Service 8264ee
	switch (sigid) {
Packit Service 8264ee
	case AVDTP_DISCOVER:
Packit Service 8264ee
		return "Discover";
Packit Service 8264ee
	case AVDTP_GET_CAPABILITIES:
Packit Service 8264ee
		return "Get Capabilities";
Packit Service 8264ee
	case AVDTP_SET_CONFIGURATION:
Packit Service 8264ee
		return "Set Configuration";
Packit Service 8264ee
	case AVDTP_GET_CONFIGURATION:
Packit Service 8264ee
		return "Get Configuration";
Packit Service 8264ee
	case AVDTP_RECONFIGURE:
Packit Service 8264ee
		return "Reconfigure";
Packit Service 8264ee
	case AVDTP_OPEN:
Packit Service 8264ee
		return "Open";
Packit Service 8264ee
	case AVDTP_START:
Packit Service 8264ee
		return "Start";
Packit Service 8264ee
	case AVDTP_CLOSE:
Packit Service 8264ee
		return "Close";
Packit Service 8264ee
	case AVDTP_SUSPEND:
Packit Service 8264ee
		return "Suspend";
Packit Service 8264ee
	case AVDTP_ABORT:
Packit Service 8264ee
		return "Abort";
Packit Service 8264ee
	case AVDTP_SECURITY_CONTROL:
Packit Service 8264ee
		return "Security Control";
Packit Service 8264ee
	case AVDTP_GET_ALL_CAPABILITIES:
Packit Service 8264ee
		return "Get All Capabilities";
Packit Service 8264ee
	case AVDTP_DELAYREPORT:
Packit Service 8264ee
		return "Delay Report";
Packit Service 8264ee
	default:
Packit Service 8264ee
		return "Reserved";
Packit Service 8264ee
	}
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static const char *error2str(uint8_t error)
Packit Service 8264ee
{
Packit Service 8264ee
	switch (error) {
Packit Service 8264ee
	case 0x01:
Packit Service 8264ee
		return "BAD_HEADER_FORMAT";
Packit Service 8264ee
	case 0x11:
Packit Service 8264ee
		return "BAD_LENGTH";
Packit Service 8264ee
	case 0x12:
Packit Service 8264ee
		return "BAD_ACP_SEID";
Packit Service 8264ee
	case 0x13:
Packit Service 8264ee
		return "SEP_IN_USE";
Packit Service 8264ee
	case 0x14:
Packit Service 8264ee
		return "SEP_NOT_IN_USER";
Packit Service 8264ee
	case 0x17:
Packit Service 8264ee
		return "BAD_SERV_CATEGORY";
Packit Service 8264ee
	case 0x18:
Packit Service 8264ee
		return "BAD_PAYLOAD_FORMAT";
Packit Service 8264ee
	case 0x19:
Packit Service 8264ee
		return "NOT_SUPPORTED_COMMAND";
Packit Service 8264ee
	case 0x1a:
Packit Service 8264ee
		return "INVALID_CAPABILITIES";
Packit Service 8264ee
	case 0x22:
Packit Service 8264ee
		return "BAD_RECOVERY_TYPE";
Packit Service 8264ee
	case 0x23:
Packit Service 8264ee
		return "BAD_MEDIA_TRANSPORT_FORMAT";
Packit Service 8264ee
	case 0x25:
Packit Service 8264ee
		return "BAD_RECOVERY_FORMAT";
Packit Service 8264ee
	case 0x26:
Packit Service 8264ee
		return "BAD_ROHC_FORMAT";
Packit Service 8264ee
	case 0x27:
Packit Service 8264ee
		return "BAD_CP_FORMAT";
Packit Service 8264ee
	case 0x28:
Packit Service 8264ee
		return "BAD_MULTIPLEXING_FORMAT";
Packit Service 8264ee
	case 0x29:
Packit Service 8264ee
		return "UNSUPPORTED_CONFIGURATION";
Packit Service 8264ee
	case 0x31:
Packit Service 8264ee
		return "BAD_STATE";
Packit Service 8264ee
	default:
Packit Service 8264ee
		return "Unknown";
Packit Service 8264ee
	}
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static const char *mediatype2str(uint8_t media_type)
Packit Service 8264ee
{
Packit Service 8264ee
	switch (media_type) {
Packit Service 8264ee
	case 0x00:
Packit Service 8264ee
		return "Audio";
Packit Service 8264ee
	case 0x01:
Packit Service 8264ee
		return "Video";
Packit Service 8264ee
	case 0x02:
Packit Service 8264ee
		return "Multimedia";
Packit Service 8264ee
	default:
Packit Service 8264ee
		return "Reserved";
Packit Service 8264ee
	}
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static const char *mediacodec2str(uint8_t codec)
Packit Service 8264ee
{
Packit Service 8264ee
	switch (codec) {
Packit Service 8264ee
	case 0x00:
Packit Service 8264ee
		return "SBC";
Packit Service 8264ee
	case 0x01:
Packit Service 8264ee
		return "MPEG-1,2 Audio";
Packit Service 8264ee
	case 0x02:
Packit Service 8264ee
		return "MPEG-2,4 AAC";
Packit Service 8264ee
	case 0x04:
Packit Service 8264ee
		return "ATRAC Family";
Packit Service 8264ee
	case 0xff:
Packit Service 8264ee
		return "Non-A2DP";
Packit Service 8264ee
	default:
Packit Service 8264ee
		return "Reserved";
Packit Service 8264ee
	}
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static const char *cptype2str(uint8_t cp)
Packit Service 8264ee
{
Packit Service 8264ee
	switch (cp) {
Packit Service 8264ee
	case 0x0001:
Packit Service 8264ee
		return "DTCP";
Packit Service 8264ee
	case 0x0002:
Packit Service 8264ee
		return "SCMS-T";
Packit Service 8264ee
	default:
Packit Service 8264ee
		return "Reserved";
Packit Service 8264ee
	}
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static const char *servicecat2str(uint8_t service_cat)
Packit Service 8264ee
{
Packit Service 8264ee
	switch (service_cat) {
Packit Service 8264ee
	case AVDTP_MEDIA_TRANSPORT:
Packit Service 8264ee
		return "Media Transport";
Packit Service 8264ee
	case AVDTP_REPORTING:
Packit Service 8264ee
		return "Reporting";
Packit Service 8264ee
	case AVDTP_RECOVERY:
Packit Service 8264ee
		return "Recovery";
Packit Service 8264ee
	case AVDTP_CONTENT_PROTECTION:
Packit Service 8264ee
		return "Content Protection";
Packit Service 8264ee
	case AVDTP_HEADER_COMPRESSION:
Packit Service 8264ee
		return "Header Compression";
Packit Service 8264ee
	case AVDTP_MULTIPLEXING:
Packit Service 8264ee
		return "Multiplexing";
Packit Service 8264ee
	case AVDTP_MEDIA_CODEC:
Packit Service 8264ee
		return "Media Codec";
Packit Service 8264ee
	case AVDTP_DELAY_REPORTING:
Packit Service 8264ee
		return "Delay Reporting";
Packit Service 8264ee
	default:
Packit Service 8264ee
		return "Reserved";
Packit Service 8264ee
	}
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_reject_common(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t error;
Packit Service 8264ee
Packit Service 8264ee
	if (!l2cap_frame_get_u8(frame, &error))
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	print_field("Error code: %s (0x%02x)", error2str(error), error);
Packit Service 8264ee
Packit Service 8264ee
	return true;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool service_content_protection(struct avdtp_frame *avdtp_frame,
Packit Service 8264ee
								uint8_t losc)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint16_t type = 0;
Packit Service 8264ee
Packit Service 8264ee
	if (losc < 2)
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	if (!l2cap_frame_get_le16(frame, &type))
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	losc -= 2;
Packit Service 8264ee
Packit Service 8264ee
	print_field("%*cContent Protection Type: %s (0x%04x)", 2, ' ',
Packit Service 8264ee
							cptype2str(type), type);
Packit Service 8264ee
Packit Service 8264ee
	/* TODO: decode protection specific information */
Packit Service 8264ee
	packet_hexdump(frame->data, losc);
Packit Service 8264ee
Packit Service 8264ee
	l2cap_frame_pull(frame, frame, losc);
Packit Service 8264ee
Packit Service 8264ee
	return true;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool service_media_codec(struct avdtp_frame *avdtp_frame, uint8_t losc)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = 0;
Packit Service 8264ee
	uint8_t codec = 0;
Packit Service 8264ee
Packit Service 8264ee
	if (losc < 2)
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	l2cap_frame_get_u8(frame, &type);
Packit Service 8264ee
	l2cap_frame_get_u8(frame, &codec);
Packit Service 8264ee
Packit Service 8264ee
	losc -= 2;
Packit Service 8264ee
Packit Service 8264ee
	print_field("%*cMedia Type: %s (0x%02x)", 2, ' ',
Packit Service 8264ee
					mediatype2str(type >> 4), type >> 4);
Packit Service 8264ee
Packit Service 8264ee
	print_field("%*cMedia Codec: %s (0x%02x)", 2, ' ',
Packit Service 8264ee
					mediacodec2str(codec), codec);
Packit Service 8264ee
Packit Service 8264ee
	if (is_configuration_sig_id(avdtp_frame->sig_id))
Packit Service 8264ee
		return a2dp_codec_cfg(codec, losc, frame);
Packit Service 8264ee
	else
Packit Service 8264ee
		return a2dp_codec_cap(codec, losc, frame);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool decode_capabilities(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t service_cat;
Packit Service 8264ee
	uint8_t losc;
Packit Service 8264ee
Packit Service 8264ee
	while (l2cap_frame_get_u8(frame, &service_cat)) {
Packit Service 8264ee
		print_field("Service Category: %s (0x%02x)",
Packit Service 8264ee
				servicecat2str(service_cat), service_cat);
Packit Service 8264ee
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &losc))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		if (frame->size < losc)
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		switch (service_cat) {
Packit Service 8264ee
		case AVDTP_CONTENT_PROTECTION:
Packit Service 8264ee
			if (!service_content_protection(avdtp_frame, losc))
Packit Service 8264ee
				return false;
Packit Service 8264ee
			break;
Packit Service 8264ee
		case AVDTP_MEDIA_CODEC:
Packit Service 8264ee
			if (!service_media_codec(avdtp_frame, losc))
Packit Service 8264ee
				return false;
Packit Service 8264ee
			break;
Packit Service 8264ee
		case AVDTP_MEDIA_TRANSPORT:
Packit Service 8264ee
		case AVDTP_REPORTING:
Packit Service 8264ee
		case AVDTP_RECOVERY:
Packit Service 8264ee
		case AVDTP_HEADER_COMPRESSION:
Packit Service 8264ee
		case AVDTP_MULTIPLEXING:
Packit Service 8264ee
		case AVDTP_DELAY_REPORTING:
Packit Service 8264ee
		default:
Packit Service 8264ee
			packet_hexdump(frame->data, losc);
Packit Service 8264ee
			l2cap_frame_pull(frame, frame, losc);
Packit Service 8264ee
		}
Packit Service 8264ee
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return true;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_discover(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = avdtp_frame->hdr & 0x03;
Packit Service 8264ee
	uint8_t seid;
Packit Service 8264ee
	uint8_t info;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case AVDTP_MSG_TYPE_COMMAND:
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
Packit Service 8264ee
		while (l2cap_frame_get_u8(frame, &seid)) {
Packit Service 8264ee
			print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
			if (!l2cap_frame_get_u8(frame, &info))
Packit Service 8264ee
				return false;
Packit Service 8264ee
Packit Service 8264ee
			print_field("%*cMedia Type: %s (0x%02x)", 2, ' ',
Packit Service 8264ee
					mediatype2str(info >> 4), info >> 4);
Packit Service 8264ee
			print_field("%*cSEP Type: %s (0x%02x)", 2, ' ',
Packit Service 8264ee
						info & 0x08 ? "SNK" : "SRC",
Packit Service 8264ee
						(info >> 3) & 0x01);
Packit Service 8264ee
			print_field("%*cIn use: %s", 2, ' ',
Packit Service 8264ee
						seid & 0x02 ? "Yes" : "No");
Packit Service 8264ee
		}
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_REJECT:
Packit Service 8264ee
		return avdtp_reject_common(avdtp_frame);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_get_capabilities(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = avdtp_frame->hdr & 0x03;
Packit Service 8264ee
	uint8_t seid;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case AVDTP_MSG_TYPE_COMMAND:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
Packit Service 8264ee
		return decode_capabilities(avdtp_frame);
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_REJECT:
Packit Service 8264ee
		return avdtp_reject_common(avdtp_frame);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_set_configuration(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = avdtp_frame->hdr & 0x03;
Packit Service 8264ee
	uint8_t acp_seid, int_seid;
Packit Service 8264ee
	uint8_t service_cat;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case AVDTP_MSG_TYPE_COMMAND:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &acp_seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", acp_seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &int_seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("INT SEID: %d", int_seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		return decode_capabilities(avdtp_frame);
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_REJECT:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &service_cat))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("Service Category: %s (0x%02x)",
Packit Service 8264ee
				servicecat2str(service_cat), service_cat);
Packit Service 8264ee
Packit Service 8264ee
		return avdtp_reject_common(avdtp_frame);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_get_configuration(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = avdtp_frame->hdr & 0x03;
Packit Service 8264ee
	uint8_t seid;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case AVDTP_MSG_TYPE_COMMAND:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
Packit Service 8264ee
		return decode_capabilities(avdtp_frame);
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_REJECT:
Packit Service 8264ee
		return avdtp_reject_common(avdtp_frame);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_reconfigure(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = avdtp_frame->hdr & 0x03;
Packit Service 8264ee
	uint8_t seid;
Packit Service 8264ee
	uint8_t service_cat;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case AVDTP_MSG_TYPE_COMMAND:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		return decode_capabilities(avdtp_frame);
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_REJECT:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &service_cat))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("Service Category: %s (0x%02x)",
Packit Service 8264ee
				servicecat2str(service_cat), service_cat);
Packit Service 8264ee
Packit Service 8264ee
		return avdtp_reject_common(avdtp_frame);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_open(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = avdtp_frame->hdr & 0x03;
Packit Service 8264ee
	uint8_t seid;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case AVDTP_MSG_TYPE_COMMAND:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_REJECT:
Packit Service 8264ee
		return avdtp_reject_common(avdtp_frame);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_start(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = avdtp_frame->hdr & 0x03;
Packit Service 8264ee
	uint8_t seid;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case AVDTP_MSG_TYPE_COMMAND:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		while (l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_REJECT:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		return avdtp_reject_common(avdtp_frame);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_close(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = avdtp_frame->hdr & 0x03;
Packit Service 8264ee
	uint8_t seid;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case AVDTP_MSG_TYPE_COMMAND:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_REJECT:
Packit Service 8264ee
		return avdtp_reject_common(avdtp_frame);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_suspend(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = avdtp_frame->hdr & 0x03;
Packit Service 8264ee
	uint8_t seid;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case AVDTP_MSG_TYPE_COMMAND:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		while (l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_REJECT:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		return avdtp_reject_common(avdtp_frame);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_abort(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = avdtp_frame->hdr & 0x03;
Packit Service 8264ee
	uint8_t seid;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case AVDTP_MSG_TYPE_COMMAND:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
Packit Service 8264ee
		return true;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_security_control(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = avdtp_frame->hdr & 0x03;
Packit Service 8264ee
	uint8_t seid;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case AVDTP_MSG_TYPE_COMMAND:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		/* TODO: decode more information */
Packit Service 8264ee
		packet_hexdump(frame->data, frame->size);
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
Packit Service 8264ee
		/* TODO: decode more information */
Packit Service 8264ee
		packet_hexdump(frame->data, frame->size);
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_REJECT:
Packit Service 8264ee
		return avdtp_reject_common(avdtp_frame);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_delayreport(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	uint8_t type = avdtp_frame->hdr & 0x03;
Packit Service 8264ee
	uint8_t seid;
Packit Service 8264ee
	uint16_t delay;
Packit Service 8264ee
Packit Service 8264ee
	switch (type) {
Packit Service 8264ee
	case AVDTP_MSG_TYPE_COMMAND:
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &seid))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("ACP SEID: %d", seid >> 2);
Packit Service 8264ee
Packit Service 8264ee
		if (!l2cap_frame_get_be16(frame, &delay))
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		print_field("Delay: %d.%dms", delay / 10, delay % 10);
Packit Service 8264ee
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_ACCEPT:
Packit Service 8264ee
		return true;
Packit Service 8264ee
	case AVDTP_MSG_TYPE_RESPONSE_REJECT:
Packit Service 8264ee
		return avdtp_reject_common(avdtp_frame);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool avdtp_signalling_packet(struct avdtp_frame *avdtp_frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct l2cap_frame *frame = &avdtp_frame->l2cap_frame;
Packit Service 8264ee
	const char *pdu_color;
Packit Service 8264ee
	uint8_t hdr;
Packit Service 8264ee
	uint8_t sig_id;
Packit Service 8264ee
	uint8_t nosp = 0;
Packit Service 8264ee
Packit Service 8264ee
	if (frame->in)
Packit Service 8264ee
		pdu_color = COLOR_MAGENTA;
Packit Service 8264ee
	else
Packit Service 8264ee
		pdu_color = COLOR_BLUE;
Packit Service 8264ee
Packit Service 8264ee
	if (!l2cap_frame_get_u8(frame, &hdr))
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	avdtp_frame->hdr = hdr;
Packit Service 8264ee
Packit Service 8264ee
	/* Continue Packet || End Packet */
Packit Service 8264ee
	if (((hdr & 0x0c) == 0x08) || ((hdr & 0x0c) == 0x0c)) {
Packit Service 8264ee
		/* TODO: handle fragmentation */
Packit Service 8264ee
		packet_hexdump(frame->data, frame->size);
Packit Service 8264ee
		return true;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	/* Start Packet */
Packit Service 8264ee
	if ((hdr & 0x0c) == 0x04) {
Packit Service 8264ee
		if (!l2cap_frame_get_u8(frame, &nosp))
Packit Service 8264ee
			return false;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	if (!l2cap_frame_get_u8(frame, &sig_id))
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	sig_id &= 0x3f;
Packit Service 8264ee
Packit Service 8264ee
	avdtp_frame->sig_id = sig_id;
Packit Service 8264ee
Packit Service 8264ee
	print_indent(6, pdu_color, "AVDTP: ", sigid2str(sig_id), COLOR_OFF,
Packit Service 8264ee
			" (0x%02x) %s (0x%02x) type 0x%02x label %d nosp %d",
Packit Service 8264ee
			sig_id, msgtype2str(hdr & 0x03), hdr & 0x03,
Packit Service 8264ee
			hdr & 0x0c, hdr >> 4, nosp);
Packit Service 8264ee
Packit Service 8264ee
	/* Start Packet */
Packit Service 8264ee
	if ((hdr & 0x0c) == 0x04) {
Packit Service 8264ee
		/* TODO: handle fragmentation */
Packit Service 8264ee
		packet_hexdump(frame->data, frame->size);
Packit Service 8264ee
		return true;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	/* General Reject */
Packit Service 8264ee
	if ((hdr & 0x03) == 0x03)
Packit Service 8264ee
		return true;
Packit Service 8264ee
Packit Service 8264ee
	switch (sig_id) {
Packit Service 8264ee
	case AVDTP_DISCOVER:
Packit Service 8264ee
		return avdtp_discover(avdtp_frame);
Packit Service 8264ee
	case AVDTP_GET_CAPABILITIES:
Packit Service 8264ee
	case AVDTP_GET_ALL_CAPABILITIES:
Packit Service 8264ee
		return avdtp_get_capabilities(avdtp_frame);
Packit Service 8264ee
	case AVDTP_SET_CONFIGURATION:
Packit Service 8264ee
		return avdtp_set_configuration(avdtp_frame);
Packit Service 8264ee
	case AVDTP_GET_CONFIGURATION:
Packit Service 8264ee
		return avdtp_get_configuration(avdtp_frame);
Packit Service 8264ee
	case AVDTP_RECONFIGURE:
Packit Service 8264ee
		return avdtp_reconfigure(avdtp_frame);
Packit Service 8264ee
	case AVDTP_OPEN:
Packit Service 8264ee
		return avdtp_open(avdtp_frame);
Packit Service 8264ee
	case AVDTP_START:
Packit Service 8264ee
		return avdtp_start(avdtp_frame);
Packit Service 8264ee
	case AVDTP_CLOSE:
Packit Service 8264ee
		return avdtp_close(avdtp_frame);
Packit Service 8264ee
	case AVDTP_SUSPEND:
Packit Service 8264ee
		return avdtp_suspend(avdtp_frame);
Packit Service 8264ee
	case AVDTP_ABORT:
Packit Service 8264ee
		return avdtp_abort(avdtp_frame);
Packit Service 8264ee
	case AVDTP_SECURITY_CONTROL:
Packit Service 8264ee
		return avdtp_security_control(avdtp_frame);
Packit Service 8264ee
	case AVDTP_DELAYREPORT:
Packit Service 8264ee
		return avdtp_delayreport(avdtp_frame);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	packet_hexdump(frame->data, frame->size);
Packit Service 8264ee
Packit Service 8264ee
	return true;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
void avdtp_packet(const struct l2cap_frame *frame)
Packit Service 8264ee
{
Packit Service 8264ee
	struct avdtp_frame avdtp_frame;
Packit Service 8264ee
	bool ret;
Packit Service 8264ee
Packit Service 8264ee
	l2cap_frame_pull(&avdtp_frame.l2cap_frame, frame, 0);
Packit Service 8264ee
Packit Service 8264ee
	switch (frame->seq_num) {
Packit Service 8264ee
	case 1:
Packit Service 8264ee
		ret = avdtp_signalling_packet(&avdtp_frame);
Packit Service 8264ee
		break;
Packit Service 8264ee
	default:
Packit Service 8264ee
		if (packet_has_filter(PACKET_FILTER_SHOW_A2DP_STREAM))
Packit Service 8264ee
			packet_hexdump(frame->data, frame->size);
Packit Service 8264ee
		return;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	if (!ret) {
Packit Service 8264ee
		print_text(COLOR_ERROR, "PDU malformed");
Packit Service 8264ee
		packet_hexdump(frame->data, frame->size);
Packit Service 8264ee
	}
Packit Service 8264ee
}