All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrzej Kaczmarek <andrzej.kaczmarek@codecoup.pl>
To: linux-bluetooth@vger.kernel.org
Cc: Andrzej Kaczmarek <andrzej.kaczmarek@codecoup.pl>
Subject: [PATCH v2 21/22] monitor/a2dp: Decode aptX capabilities
Date: Fri, 20 Nov 2015 15:13:39 +0100	[thread overview]
Message-ID: <1448028820-25330-22-git-send-email-andrzej.kaczmarek@codecoup.pl> (raw)
In-Reply-To: <1448028820-25330-1-git-send-email-andrzej.kaczmarek@codecoup.pl>

> ACL Data RX: Handle 5 flags 0x02 dlen 23
      Channel: 65 len 19 [PSM 25 mode 0] {chan 1}
      AVDTP: Get Capabilities (0x02) Response Accept (0x02) type 0x00 label 12 nosp 0
        Service Category: Media Transport (0x01)
        Service Category: Media Codec (0x07)
          Media Type: Audio (0x00)
          Media Codec: Non-A2DP (0xff)
            Vendor ID: APT Licensing Ltd. (0x0000004f)
            Vendor Specific Codec ID: aptX (0x0001)
              Frequency: 0x30
                44100
                48000
              Channel Mode: 0x02
                Stereo
        Service Category: Content Protection (0x04)
          Content Protection Type: SCMS-T (0x0002)

< ACL Data TX: Handle 5 flags 0x00 dlen 21
      Channel: 193 len 17 [PSM 25 mode 0] {chan 1}
      AVDTP: Set Configuration (0x03) Command (0x00) type 0x00 label 14 nosp 0
        ACP SEID: 3
        INT SEID: 1
        Service Category: Media Transport (0x01)
        Service Category: Media Codec (0x07)
          Media Type: Audio (0x00)
          Media Codec: Non-A2DP (0xff)
            Vendor ID: APT Licensing Ltd. (0x0000004f)
            Vendor Specific Codec ID: aptX (0x0001)
              Frequency: 48000 (0x10)
              Channel Mode: Stereo (0x02)
---
 monitor/a2dp.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/monitor/a2dp.c b/monitor/a2dp.c
index 51fffd4..d438db0 100644
--- a/monitor/a2dp.c
+++ b/monitor/a2dp.c
@@ -47,6 +47,10 @@
 #define A2DP_CODEC_ATRAC	0x04
 #define A2DP_CODEC_VENDOR	0xff
 
+/* Vendor Specific A2DP Codecs */
+#define APTX_VENDOR_ID		0x0000004f
+#define APTX_CODEC_ID		0x0001
+
 struct bit_desc {
 	uint8_t bit;
 	const char *str;
@@ -166,6 +170,20 @@ static const struct bit_desc aac_channels_table[] = {
 	{ }
 };
 
+static const struct bit_desc aptx_frequency_table[] = {
+	{  7, "16000" },
+	{  6, "32000" },
+	{  5, "44100" },
+	{  4, "48000" },
+	{ }
+};
+
+static const struct bit_desc aptx_channel_mode_table[] = {
+	{  0, "Mono" },
+	{  1, "Stereo" },
+	{ }
+};
+
 static void print_value_bits(uint8_t indent, uint32_t value,
 						const struct bit_desc *table)
 {
@@ -190,6 +208,14 @@ static const char *find_value_bit(uint32_t value,
 	return "Unknown";
 }
 
+static const char *vndcodec2str(uint32_t vendor_id, uint16_t codec_id)
+{
+	if (vendor_id == APTX_VENDOR_ID && codec_id == APTX_CODEC_ID)
+		return "aptX";
+
+	return "Unknown";
+}
+
 static bool codec_sbc_cap(uint8_t losc, struct l2cap_frame *frame)
 {
 	uint8_t cap = 0;
@@ -458,6 +484,103 @@ static bool codec_aac_cfg(uint8_t losc, struct l2cap_frame *frame)
 	return true;
 }
 
+static bool codec_vendor_aptx_cap(uint8_t losc, struct l2cap_frame *frame)
+{
+	uint8_t cap = 0;
+
+	if (losc != 1)
+		return false;
+
+	l2cap_frame_get_u8(frame, &cap);
+
+	print_field("%*cFrequency: 0x%02x", BASE_INDENT + 2, ' ', cap & 0xf0);
+	print_value_bits(BASE_INDENT + 2, cap & 0xf0, aptx_frequency_table);
+
+	print_field("%*cChannel Mode: 0x%02x", BASE_INDENT + 2, ' ',
+								cap & 0x0f);
+	print_value_bits(BASE_INDENT + 2, cap & 0x0f, aptx_channel_mode_table);
+
+	return true;
+}
+
+static bool codec_vendor_cap(uint8_t losc, struct l2cap_frame *frame)
+{
+	uint32_t vendor_id = 0;
+	uint16_t codec_id = 0;
+
+	if (losc < 6)
+		return false;
+
+	l2cap_frame_get_le32(frame, &vendor_id);
+	l2cap_frame_get_le16(frame, &codec_id);
+
+	losc -= 6;
+
+	print_field("%*cVendor ID: %s (0x%08x)", BASE_INDENT, ' ',
+					bt_compidtostr(vendor_id),  vendor_id);
+
+	print_field("%*cVendor Specific Codec ID: %s (0x%04x)", BASE_INDENT,
+			' ', vndcodec2str(vendor_id, codec_id), codec_id);
+
+	if (vendor_id == APTX_VENDOR_ID && codec_id == APTX_CODEC_ID) {
+		codec_vendor_aptx_cap(losc, frame);
+	} else {
+		packet_hexdump(frame->data, losc);
+		l2cap_frame_pull(frame, frame, losc);
+	}
+
+	return true;
+}
+
+static bool codec_vendor_aptx_cfg(uint8_t losc, struct l2cap_frame *frame)
+{
+	uint8_t cap = 0;
+
+	if (losc != 1)
+		return false;
+
+	l2cap_frame_get_u8(frame, &cap);
+
+	print_field("%*cFrequency: %s (0x%02x)", BASE_INDENT + 2, ' ',
+			find_value_bit(cap & 0xf0, aptx_frequency_table),
+			cap & 0xf0);
+
+	print_field("%*cChannel Mode: %s (0x%02x)", BASE_INDENT + 2, ' ',
+			find_value_bit(cap & 0x0f, aptx_channel_mode_table),
+			cap & 0x0f);
+
+	return true;
+}
+
+static bool codec_vendor_cfg(uint8_t losc, struct l2cap_frame *frame)
+{
+	uint32_t vendor_id = 0;
+	uint16_t codec_id = 0;
+
+	if (losc < 6)
+		return false;
+
+	l2cap_frame_get_le32(frame, &vendor_id);
+	l2cap_frame_get_le16(frame, &codec_id);
+
+	losc -= 6;
+
+	print_field("%*cVendor ID: %s (0x%08x)", BASE_INDENT, ' ',
+					bt_compidtostr(vendor_id),  vendor_id);
+
+	print_field("%*cVendor Specific Codec ID: %s (0x%04x)", BASE_INDENT,
+			' ', vndcodec2str(vendor_id, codec_id), codec_id);
+
+	if (vendor_id == APTX_VENDOR_ID && codec_id == APTX_CODEC_ID) {
+		codec_vendor_aptx_cfg(losc, frame);
+	} else {
+		packet_hexdump(frame->data, losc);
+		l2cap_frame_pull(frame, frame, losc);
+	}
+
+	return true;
+}
+
 bool a2dp_codec_cap(uint8_t codec, uint8_t losc, struct l2cap_frame *frame)
 {
 	switch (codec) {
@@ -467,6 +590,8 @@ bool a2dp_codec_cap(uint8_t codec, uint8_t losc, struct l2cap_frame *frame)
 		return codec_mpeg12_cap(losc, frame);
 	case A2DP_CODEC_MPEG24:
 		return codec_aac_cap(losc, frame);
+	case A2DP_CODEC_VENDOR:
+		return codec_vendor_cap(losc, frame);
 	default:
 		packet_hexdump(frame->data, losc);
 		l2cap_frame_pull(frame, frame, losc);
@@ -483,6 +608,8 @@ bool a2dp_codec_cfg(uint8_t codec, uint8_t losc, struct l2cap_frame *frame)
 		return codec_mpeg12_cfg(losc, frame);
 	case A2DP_CODEC_MPEG24:
 		return codec_aac_cfg(losc, frame);
+	case A2DP_CODEC_VENDOR:
+		return codec_vendor_cfg(losc, frame);
 	default:
 		packet_hexdump(frame->data, losc);
 		l2cap_frame_pull(frame, frame, losc);
-- 
2.6.2


  parent reply	other threads:[~2015-11-20 14:13 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-20 14:13 [PATCH v2 00/22] Add AVDTP/A2DP decoding to btmon Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 01/22] monitor/l2cap: Add channel sequence number Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 02/22] monitor/avdtp: Add basic decoding of AVDTP signalling Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 03/22] monitor/avdtp: Decode AVDTP_DISCOVER Andrzej Kaczmarek
2015-11-20 16:50   ` Szymon Janc
2015-11-20 14:13 ` [PATCH v2 04/22] monitor/avdtp: Decode AVDTP_GET_CAPABILITIES Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 05/22] monitor/avdtp: Decode AVDTP_SET_CONFIGURATION Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 06/22] monitor/avdtp: Decode AVDTP_GET_CONFIGURATION Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 07/22] monitor/avdtp: Decode AVDTP_RECONFIGURE Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 08/22] monitor/avdtp: Decode AVDTP_OPEN Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 09/22] monitor/avdtp: Decode AVDTP_START Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 10/22] monitor/avdtp: Decode AVDTP_CLOSE Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 11/22] monitor/avdtp: Decode AVDTP_SUSPEND Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 12/22] monitor/avdtp: Decode AVDTP_ABORT Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 13/22] monitor/avdtp: Decode AVDTP_SECURITY_CONTROL Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 14/22] monitor/avdtp: Decode AVDTP_GET_ALL_CAPABILITIES Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 15/22] monitor/avdtp: Decode AVDTP_DELAYREPORT Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 16/22] monitor/avdtp: Decode basic Media Codec capabilities Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 17/22] monitor/avdtp: Decode basic Content Protection capabilities Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 18/22] monitor/a2dp: Decode SBC capabilities Andrzej Kaczmarek
2015-11-20 16:35   ` Szymon Janc
2015-11-20 14:13 ` [PATCH v2 19/22] monitor/a2dp: Decode MPEG-1,2 capabilities Andrzej Kaczmarek
2015-11-20 14:13 ` [PATCH v2 20/22] monitor/a2dp: Decode AAC capabilities Andrzej Kaczmarek
2015-11-20 14:13 ` Andrzej Kaczmarek [this message]
2015-11-20 14:13 ` [PATCH v2 22/22] monitor/a2dp: Decode LDAC capabilities Andrzej Kaczmarek
2015-11-20 16:40   ` Szymon Janc
2015-11-20 16:37 ` [PATCH v2 00/22] Add AVDTP/A2DP decoding to btmon Andrzej Kaczmarek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1448028820-25330-22-git-send-email-andrzej.kaczmarek@codecoup.pl \
    --to=andrzej.kaczmarek@codecoup.pl \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.