* [PATCH BlueZ v2 1/2] audio: Add support for specific error codes for A2DP configuration
@ 2025-09-11 15:19 Per Waagø
2025-09-11 15:19 ` [PATCH BlueZ v2 2/2] doc: Document error codes for A2DP MediaEndpoints Per Waagø
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Per Waagø @ 2025-09-11 15:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Per Waagø
The A2DP specification defines error codes that shall be used if
the codec capabilities contain improper settings. This change allows
clients to trigger the sending of these specific error codes by
returning the corresponding error messages from
MediaEndpoint1.SetConfiguration.
This update is fully backwards compatible: clients passing other error
messages will continue to receive the default error code as before. On
older BlueZ versions, these new errors will also result in the default
error code, enabling clients to implement support for the new errors
without breaking compatibility.
This change enables passing A2DP/SNK/AVP/* and A2DP/SRC/AVP/*
qualification tests.
---
profiles/audio/a2dp.c | 78 ++++++++++++++++++++++++++++++++++++++----
profiles/audio/a2dp.h | 43 ++++++++++++++++++++++-
profiles/audio/avdtp.c | 4 +--
profiles/audio/media.c | 20 ++++++-----
4 files changed, 128 insertions(+), 17 deletions(-)
diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index c0a53eae9..661843a89 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -157,6 +157,73 @@ static GSList *servers = NULL;
static GSList *setups = NULL;
static unsigned int cb_id = 0;
+struct a2dp_error {
+ const char *error_name;
+ uint8_t error_code;
+};
+
+#define A2DP_ERROR_PREFIX ERROR_INTERFACE ".A2DP."
+
+static struct a2dp_error config_errors[] = {
+ {"InvalidCodecType", A2DP_INVALID_CODEC_TYPE},
+ {"NotSupportedCodecType", A2DP_NOT_SUPPORTED_CODEC_TYPE},
+ {"InvalidSamplingFrequency", A2DP_INVALID_SAMPLING_FREQUENCY},
+ {"NotSupportedSamplingFrequency",
+ A2DP_NOT_SUPPORTED_SAMPLING_FREQUENCY},
+ {"InvalidChannelMode", A2DP_INVALID_CHANNEL_MODE},
+ {"NotSupportedChannelMode", A2DP_NOT_SUPPORTED_CHANNEL_MODE},
+ {"InvalidSubbands", A2DP_INVALID_SUBBANDS},
+ {"NotSupportedSubbands", A2DP_NOT_SUPPORTED_SUBBANDS},
+ {"InvalidAllocationMethod", A2DP_INVALID_ALLOCATION_METHOD},
+ {"NotSupportedAllocationMethod", A2DP_NOT_SUPPORTED_ALLOCATION_METHOD},
+ {"InvalidMinimumBitpoolValue",
+ A2DP_INVALID_MINIMUM_BITPOOL_VALUE},
+ {"NotSupportedMinimumBitpoolValue",
+ A2DP_NOT_SUPPORTED_MINIMUM_BITPOOL_VALUE},
+ {"InvalidMaximumBitpoolValue", A2DP_INVALID_MAXIMUM_BITPOOL_VALUE},
+ {"NotSupportedMaximumBitpoolValue",
+ A2DP_NOT_SUPPORTED_MAXIMUM_BITPOOL_VALUE},
+ {"InvalidInvalidLayer", A2DP_INVALID_INVALID_LAYER},
+ {"NotSupportedLayer", A2DP_NOT_SUPPORTED_LAYER},
+ {"NotSupporterdCRC", A2DP_NOT_SUPPORTERD_CRC},
+ {"NotSupporterdMPF", A2DP_NOT_SUPPORTERD_MPF},
+ {"NotSupporterdVBR", A2DP_NOT_SUPPORTERD_VBR},
+ {"InvalidBitRate", A2DP_INVALID_BIT_RATE},
+ {"NotSupportedBitRate", A2DP_NOT_SUPPORTED_BIT_RATE},
+ {"InvalidObjectType", A2DP_INVALID_OBJECT_TYPE},
+ {"NotSupportedObjectType", A2DP_NOT_SUPPORTED_OBJECT_TYPE},
+ {"InvalidChannels", A2DP_INVALID_CHANNELS},
+ {"NotSupportedChannels", A2DP_NOT_SUPPORTED_CHANNELS},
+ {"InvalidVersion", A2DP_INVALID_VERSION},
+ {"NotSupportedVersion", A2DP_NOT_SUPPORTED_VERSION},
+ {"NotSupportedMaximumSUL", A2DP_NOT_SUPPORTED_MAXIMUM_SUL},
+ {"InvalidBlockLength", A2DP_INVALID_BLOCK_LENGTH},
+ {"InvalidCPType", A2DP_INVALID_CP_TYPE},
+ {"InvalidCPFormat", A2DP_INVALID_CP_FORMAT},
+ {"InvalidCodecParameter", A2DP_INVALID_CODEC_PARAMETER},
+ {"NotSupportedCodecParameter", A2DP_NOT_SUPPORTED_CODEC_PARAMETER},
+ {"InvalidDRC", A2DP_INVALID_DRC},
+ {"NotSupportedDRC", A2DP_NOT_SUPPORTED_DRC}
+};
+
+uint8_t a2dp_parse_config_error(const char *error_name)
+{
+ size_t prefix_length;
+ size_t i;
+
+ prefix_length = strlen(A2DP_ERROR_PREFIX);
+ if (strncmp(A2DP_ERROR_PREFIX, error_name, prefix_length))
+ return AVDTP_UNSUPPORTED_CONFIGURATION;
+
+ error_name += prefix_length;
+ for (i = 0; i < ARRAY_SIZE(config_errors); i++) {
+ if (strcmp(config_errors[i].error_name, error_name) == 0)
+ return config_errors[i].error_code;
+ }
+
+ return AVDTP_UNSUPPORTED_CONFIGURATION;
+}
+
static struct a2dp_setup *setup_ref(struct a2dp_setup *setup)
{
setup->ref++;
@@ -688,11 +755,10 @@ done:
return FALSE;
}
-static void endpoint_setconf_cb(struct a2dp_setup *setup, gboolean ret)
+static void endpoint_setconf_cb(struct a2dp_setup *setup, uint8_t error_code)
{
- if (ret == FALSE)
- setup_error_init(setup, AVDTP_MEDIA_CODEC,
- AVDTP_UNSUPPORTED_CONFIGURATION);
+ if (error_code != 0)
+ setup_error_init(setup, AVDTP_MEDIA_CODEC, error_code);
auto_config(setup);
setup_unref(setup);
@@ -865,11 +931,11 @@ static gboolean endpoint_getcap_ind(struct avdtp *session,
return TRUE;
}
-static void endpoint_open_cb(struct a2dp_setup *setup, gboolean ret)
+static void endpoint_open_cb(struct a2dp_setup *setup, uint8_t error_code)
{
int err = error_to_errno(setup->err);
- if (ret == FALSE) {
+ if (error_code != 0) {
setup->stream = NULL;
finalize_setup_errno(setup, -EPERM, finalize_config, NULL);
goto done;
diff --git a/profiles/audio/a2dp.h b/profiles/audio/a2dp.h
index c698bc983..bcdb4d43f 100644
--- a/profiles/audio/a2dp.h
+++ b/profiles/audio/a2dp.h
@@ -15,7 +15,8 @@ struct a2dp_setup;
typedef void (*a2dp_endpoint_select_t) (struct a2dp_setup *setup, void *ret,
int size);
-typedef void (*a2dp_endpoint_config_t) (struct a2dp_setup *setup, gboolean ret);
+typedef void (*a2dp_endpoint_config_t) (struct a2dp_setup *setup,
+ uint8_t error_code);
struct a2dp_endpoint {
const char *(*get_name) (struct a2dp_sep *sep, void *user_data);
@@ -70,6 +71,8 @@ unsigned int a2dp_select_capabilities(struct avdtp *session,
unsigned int a2dp_config(struct avdtp *session, struct a2dp_sep *sep,
a2dp_config_cb_t cb, GSList *caps,
void *user_data);
+uint8_t a2dp_parse_config_error(const char *error_name);
+
unsigned int a2dp_resume(struct avdtp *session, struct a2dp_sep *sep,
a2dp_stream_cb_t cb, void *user_data);
unsigned int a2dp_suspend(struct avdtp *session, struct a2dp_sep *sep,
@@ -83,3 +86,41 @@ struct avdtp_stream *a2dp_sep_get_stream(struct a2dp_sep *sep,
struct btd_device *a2dp_setup_get_device(struct a2dp_setup *setup);
const char *a2dp_setup_remote_path(struct a2dp_setup *setup);
struct avdtp *a2dp_avdtp_get(struct btd_device *device);
+
+enum a2dp_error_codes {
+ A2DP_INVALID_CODEC_TYPE = 0xc1,
+ A2DP_NOT_SUPPORTED_CODEC_TYPE = 0xc2,
+ A2DP_INVALID_SAMPLING_FREQUENCY = 0xc3,
+ A2DP_NOT_SUPPORTED_SAMPLING_FREQUENCY = 0xc4,
+ A2DP_INVALID_CHANNEL_MODE = 0xc5,
+ A2DP_NOT_SUPPORTED_CHANNEL_MODE = 0xc6,
+ A2DP_INVALID_SUBBANDS = 0xc7,
+ A2DP_NOT_SUPPORTED_SUBBANDS = 0xc8,
+ A2DP_INVALID_ALLOCATION_METHOD = 0xc9,
+ A2DP_NOT_SUPPORTED_ALLOCATION_METHOD = 0xca,
+ A2DP_INVALID_MINIMUM_BITPOOL_VALUE = 0xcb,
+ A2DP_NOT_SUPPORTED_MINIMUM_BITPOOL_VALUE = 0xcc,
+ A2DP_INVALID_MAXIMUM_BITPOOL_VALUE = 0xcd,
+ A2DP_NOT_SUPPORTED_MAXIMUM_BITPOOL_VALUE = 0xce,
+ A2DP_INVALID_INVALID_LAYER = 0xcf,
+ A2DP_NOT_SUPPORTED_LAYER = 0xd0,
+ A2DP_NOT_SUPPORTERD_CRC = 0xd1,
+ A2DP_NOT_SUPPORTERD_MPF = 0xd2,
+ A2DP_NOT_SUPPORTERD_VBR = 0xd3,
+ A2DP_INVALID_BIT_RATE = 0xd4,
+ A2DP_NOT_SUPPORTED_BIT_RATE = 0xd5,
+ A2DP_INVALID_OBJECT_TYPE = 0xd6,
+ A2DP_NOT_SUPPORTED_OBJECT_TYPE = 0xd7,
+ A2DP_INVALID_CHANNELS = 0xd8,
+ A2DP_NOT_SUPPORTED_CHANNELS = 0xd9,
+ A2DP_INVALID_VERSION = 0xda,
+ A2DP_NOT_SUPPORTED_VERSION = 0xdb,
+ A2DP_NOT_SUPPORTED_MAXIMUM_SUL = 0xdc,
+ A2DP_INVALID_BLOCK_LENGTH = 0xdd,
+ A2DP_INVALID_CP_TYPE = 0xe0,
+ A2DP_INVALID_CP_FORMAT = 0xe1,
+ A2DP_INVALID_CODEC_PARAMETER = 0xe2,
+ A2DP_NOT_SUPPORTED_CODEC_PARAMETER = 0xe3,
+ A2DP_INVALID_DRC = 0xe4,
+ A2DP_NOT_SUPPORTED_DRC = 0xe5,
+};
diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index 30648251f..ed4e22b26 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -1494,8 +1494,8 @@ static void setconf_cb(struct avdtp *session, struct avdtp_stream *stream,
struct conf_rej rej;
if (err != NULL) {
- rej.error = AVDTP_UNSUPPORTED_CONFIGURATION;
- rej.category = err->err.error_code;
+ rej.error = err->err.error_code;
+ rej.category = AVDTP_UNSUPPORTED_CONFIGURATION;
avdtp_send(session, session->in_cmd.transaction,
AVDTP_MSG_TYPE_REJECT, AVDTP_SET_CONFIGURATION,
&rej, sizeof(rej));
diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 9b3042c18..332f643bb 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -333,7 +333,7 @@ static void endpoint_reply(DBusPendingCall *call, void *user_data)
DBusMessage *reply;
DBusMessageIter args, props;
DBusError err;
- gboolean value;
+ uint8_t error_code;
void *ret = NULL;
int size = -1;
@@ -356,8 +356,12 @@ static void endpoint_reply(DBusPendingCall *call, void *user_data)
if (dbus_message_is_method_call(request->msg,
MEDIA_ENDPOINT_INTERFACE,
- "SetConfiguration"))
+ "SetConfiguration")) {
endpoint_remove_transport(endpoint, request->transport);
+ error_code = a2dp_parse_config_error(err.name);
+ ret = &error_code;
+ size = 1;
+ }
dbus_error_free(&err);
goto done;
@@ -390,8 +394,8 @@ static void endpoint_reply(DBusPendingCall *call, void *user_data)
}
size = 1;
- value = TRUE;
- ret = &value;
+ error_code = 0;
+ ret = &error_code;
done:
dbus_message_unref(reply);
@@ -634,9 +638,9 @@ static void config_cb(struct media_endpoint *endpoint, void *ret, int size,
void *user_data)
{
struct a2dp_config_data *data = user_data;
- gboolean *ret_value = ret;
+ uint8_t *ret_value = ret;
- data->cb(data->setup, ret_value ? *ret_value : FALSE);
+ data->cb(data->setup, ret_value ? *ret_value : 1);
}
static int set_config(struct a2dp_sep *sep, uint8_t *configuration,
@@ -1098,7 +1102,7 @@ static void pac_config_cb(struct media_endpoint *endpoint, void *ret, int size,
void *user_data)
{
struct pac_config_data *data = user_data;
- gboolean *ret_value = ret;
+ uint8_t *error_code = ret;
struct media_transport *transport;
/* If transport was cleared, configuration was cancelled */
@@ -1106,7 +1110,7 @@ static void pac_config_cb(struct media_endpoint *endpoint, void *ret, int size,
if (!transport)
return;
- data->cb(data->stream, ret_value ? 0 : -EINVAL);
+ data->cb(data->stream, error_code == 0 ? 0 : -EINVAL);
}
static struct media_transport *pac_ucast_config(struct bt_bap_stream *stream,
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH BlueZ v2 2/2] doc: Document error codes for A2DP MediaEndpoints
2025-09-11 15:19 [PATCH BlueZ v2 1/2] audio: Add support for specific error codes for A2DP configuration Per Waagø
@ 2025-09-11 15:19 ` Per Waagø
2025-09-14 21:57 ` Arkadiusz Bokowy
2025-09-11 16:46 ` [BlueZ,v2,1/2] audio: Add support for specific error codes for A2DP configuration bluez.test.bot
2025-09-11 19:50 ` [PATCH BlueZ v2 1/2] " patchwork-bot+bluetooth
2 siblings, 1 reply; 6+ messages in thread
From: Per Waagø @ 2025-09-11 15:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Per Waagø
---
doc/org.bluez.MediaEndpoint.rst | 37 +++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/doc/org.bluez.MediaEndpoint.rst b/doc/org.bluez.MediaEndpoint.rst
index 474cc1160..bbe00b637 100644
--- a/doc/org.bluez.MediaEndpoint.rst
+++ b/doc/org.bluez.MediaEndpoint.rst
@@ -54,6 +54,43 @@ be configured and the properties must contain the following properties:
See **org.bluez.MediaTransport(5)** QoS property.
+Possible errors for A2DP endpoints:
+ :org.bluez.Error.A2DP.InvalidCodecType:
+ :org.bluez.Error.A2DP.NotSupportedCodecType:
+ :org.bluez.Error.A2DP.InvalidSamplingFrequency:
+ :org.bluez.Error.A2DP.NotSupportedSamplingFrequency:
+ :org.bluez.Error.A2DP.InvalidChannelMode:
+ :org.bluez.Error.A2DP.NotSupportedChannelMode:
+ :org.bluez.Error.A2DP.InvalidSubbands:
+ :org.bluez.Error.A2DP.NotSupportedSubbands:
+ :org.bluez.Error.A2DP.InvalidAllocationMethod:
+ :org.bluez.Error.A2DP.NotSupportedAllocationMethod:
+ :org.bluez.Error.A2DP.InvalidMinimumBitpoolValue:
+ :org.bluez.Error.A2DP.NotSupportedMinimumBitpoolValue:
+ :org.bluez.Error.A2DP.InvalidMaximumBitpoolValue:
+ :org.bluez.Error.A2DP.NotSupportedMaximumBitpoolValue:
+ :org.bluez.Error.A2DP.InvalidInvalidLayer:
+ :org.bluez.Error.A2DP.NotSupportedLayer:
+ :org.bluez.Error.A2DP.NotSupporterdCRC:
+ :org.bluez.Error.A2DP.NotSupporterdMPF:
+ :org.bluez.Error.A2DP.NotSupporterdVBR:
+ :org.bluez.Error.A2DP.InvalidBitRate:
+ :org.bluez.Error.A2DP.NotSupportedBitRate:
+ :org.bluez.Error.A2DP.InvalidObjectType:
+ :org.bluez.Error.A2DP.NotSupportedObjectType:
+ :org.bluez.Error.A2DP.InvalidChannels:
+ :org.bluez.Error.A2DP.NotSupportedChannels:
+ :org.bluez.Error.A2DP.InvalidVersion:
+ :org.bluez.Error.A2DP.NotSupportedVersion:
+ :org.bluez.Error.A2DP.NotSupportedMaximumSUL:
+ :org.bluez.Error.A2DP.InvalidBlockLength:
+ :org.bluez.Error.A2DP.InvalidCPType:
+ :org.bluez.Error.A2DP.InvalidCPFormat:
+ :org.bluez.Error.A2DP.InvalidCodecParameter:
+ :org.bluez.Error.A2DP.NotSupportedCodecParameter:
+ :org.bluez.Error.A2DP.InvalidDRC:
+ :org.bluez.Error.A2DP.NotSupportedDRC:
+
array{byte} SelectConfiguration(array{byte} capabilities)
`````````````````````````````````````````````````````````
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* RE: [BlueZ,v2,1/2] audio: Add support for specific error codes for A2DP configuration
2025-09-11 15:19 [PATCH BlueZ v2 1/2] audio: Add support for specific error codes for A2DP configuration Per Waagø
2025-09-11 15:19 ` [PATCH BlueZ v2 2/2] doc: Document error codes for A2DP MediaEndpoints Per Waagø
@ 2025-09-11 16:46 ` bluez.test.bot
2025-09-11 19:50 ` [PATCH BlueZ v2 1/2] " patchwork-bot+bluetooth
2 siblings, 0 replies; 6+ messages in thread
From: bluez.test.bot @ 2025-09-11 16:46 UTC (permalink / raw)
To: linux-bluetooth, pwaago
[-- Attachment #1: Type: text/plain, Size: 1262 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1001420
---Test result---
Test Summary:
CheckPatch PENDING 0.28 seconds
GitLint PENDING 0.27 seconds
BuildEll PASS 20.56 seconds
BluezMake PASS 2784.33 seconds
MakeCheck PASS 20.54 seconds
MakeDistcheck PASS 188.52 seconds
CheckValgrind PASS 238.72 seconds
CheckSmatch PASS 309.96 seconds
bluezmakeextell PASS 129.59 seconds
IncrementalBuild PENDING 0.26 seconds
ScanBuild PASS 935.52 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH BlueZ v2 1/2] audio: Add support for specific error codes for A2DP configuration
2025-09-11 15:19 [PATCH BlueZ v2 1/2] audio: Add support for specific error codes for A2DP configuration Per Waagø
2025-09-11 15:19 ` [PATCH BlueZ v2 2/2] doc: Document error codes for A2DP MediaEndpoints Per Waagø
2025-09-11 16:46 ` [BlueZ,v2,1/2] audio: Add support for specific error codes for A2DP configuration bluez.test.bot
@ 2025-09-11 19:50 ` patchwork-bot+bluetooth
2 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+bluetooth @ 2025-09-11 19:50 UTC (permalink / raw)
To: =?utf-8?b?UGVyIFdhYWfDuCA8cHdhYWdvQGNpc2NvLmNvbT4=?=; +Cc: linux-bluetooth
Hello:
This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Thu, 11 Sep 2025 17:19:29 +0200 you wrote:
> The A2DP specification defines error codes that shall be used if
> the codec capabilities contain improper settings. This change allows
> clients to trigger the sending of these specific error codes by
> returning the corresponding error messages from
> MediaEndpoint1.SetConfiguration.
>
> This update is fully backwards compatible: clients passing other error
> messages will continue to receive the default error code as before. On
> older BlueZ versions, these new errors will also result in the default
> error code, enabling clients to implement support for the new errors
> without breaking compatibility.
>
> [...]
Here is the summary with links:
- [BlueZ,v2,1/2] audio: Add support for specific error codes for A2DP configuration
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=a887b1a1b91f
- [BlueZ,v2,2/2] doc: Document error codes for A2DP MediaEndpoints
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=befdacd236c3
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-09-15 7:23 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-11 15:19 [PATCH BlueZ v2 1/2] audio: Add support for specific error codes for A2DP configuration Per Waagø
2025-09-11 15:19 ` [PATCH BlueZ v2 2/2] doc: Document error codes for A2DP MediaEndpoints Per Waagø
2025-09-14 21:57 ` Arkadiusz Bokowy
2025-09-15 7:23 ` Per Waago (pwaago)
2025-09-11 16:46 ` [BlueZ,v2,1/2] audio: Add support for specific error codes for A2DP configuration bluez.test.bot
2025-09-11 19:50 ` [PATCH BlueZ v2 1/2] " patchwork-bot+bluetooth
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox