Hi, On 2024/1/3 23:38, Luiz Augusto von Dentz wrote:
Apologies for the misunderstanding earlier. When you mentioned 'outstanding transactions', were you referring to a complete configuration process, rather than a single command? Can I understand it this way: An a2dp discovery command should not be sent before responding to the AVDTP_MSG_TYPE_ACCEPT message? Is it only after sending the AVDTP_MSG_TYPE_ACCEPTHi, On Wed, Jan 3, 2024 at 9:40 AM Xiao Yao <xiaokeqinhealth@xxxxxxx> wrote:From: Xiao Yao <xiaoyao@xxxxxxxxxxxxxx> BLUETOOTH SPECIFICATION Page 61 of 140 Audio/Video Distribution Transport Protocol Specification (V13) 8.4.6 Message integrity verification at receiver side - The receiver of an AVDTP signaling message shall not interpret corrupted messages. Those messages are discarded and no signaling message is returned to the sender if no error code is applicable. Possible corrupted messages are: * Response messages where the transaction label cannot match a previous command sent to the remote device Consider the following scenario: btmon log: ... ... AVDTP: Discover (0x01) Command (0x00) type 0x00 label 5 nosp 0 AVDTP: Discover (0x01) Response Accept (0x02) type 0x00 label 5 nosp 0 AVDTP: Get All Capabilities (0x0c) Command (0x00) type 0x00 label 6 nosp 0 AVDTP: Get All Capabilities (0x0c) Resp Accept (0x02) type 0 label 6 nosp 0 AVDTP: Get All Capabilities (0x0c) Command (0x00) type 0x00 label 7 nosp 0 AVDTP: Get All Capabilities (0x0c) Resp Accept (0x02) type 0 label 7 nosp 0 < AVDTP: Set Configuration (0x03) Command (0x00) type 0x00 label 8 nosp 0 //Currently, a 'set configuration' message has been received from the //sender, which contains a transaction label valued at 8. This message //was then relayed to A2DP backend(PulseAudio/PipeWire) using the dbus //interface. set_configuration()(media.c) dbus_message_new_method_call(..., "SetConfiguration", ...); g_dbus_send_message_with_reply(btd_get_dbus_connection(), ...); dbus_pending_call_set_notify(request->call, endpoint_reply, ...); ...AVDTP: Discover (0x01) Command (0x00) type 0x00 label 0 nosp 0//At this time, the A2DP reverse discovery issued an A2DP discover command. < AVDTP: Discover (0x01) Response Accept (0x02) type 0x00 label 0 nosp 0 //After receiving the discover reply, the session->in.transaction is //changed to 0AVDTP: Set Configuration (0x03) Resp Accept (0x02) type 0 label 0 nosp 0//The audio backend reply the dbus message endpoint_reply (media.c) setconf_cb (avdtp.c) //Here avdtp_send sends an incorrect transaction value, causing //the sender to discard the message. (The correct transaction //value is 8) avdtp_send(session, session->in.transaction, AVDTP_MSG_TYPE_ACCEPT, AVDTP_SET_CONFIGURATION, NULL, 0) AVDTP: Delay Report (0x0d) Command (0x00) type 0x00 label 1 nosp 0 AVDTP: Delay Report (0x0d) Response Accept (0x02) type 0x00 label 1 nosp 0 AVDTP: Get All Capabilities (0x0c) Command (0x00) type 0x00 label 2 nosp 0 AVDTP: Get All Capabilities (0x0c) Resp Accept (0x02) type 0 label 2 nosp 0 ... ... Therefore, a async_transaction that requires asynchronous return is recorded to prevent it from being incorrectly modified. Signed-off-by: Xiao Yao <xiaoyao@xxxxxxxxxxxxxx> --- v1 -> v2: Fixed "session->in.transaction" logic err. v2 -> v3: Fixed some compile warnings --- profiles/audio/avdtp.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c index 10ef380d4..386c7f67c 100644 --- a/profiles/audio/avdtp.c +++ b/profiles/audio/avdtp.c @@ -286,6 +286,7 @@ struct in_buf { gboolean active; int no_of_packets; uint8_t transaction; + uint8_t async_transaction;Didn't I already explain it already that we are not supposed to have 2 outstanding transactions?
response to the remote device that I can proceed with the a2dp discovery?
uint8_t message_type; uint8_t signal_id; uint8_t buf[1024]; @@ -1462,15 +1463,16 @@ static void setconf_cb(struct avdtp *session, struct avdtp_stream *stream, if (err != NULL) { rej.error = AVDTP_UNSUPPORTED_CONFIGURATION; rej.category = err->err.error_code; - avdtp_send(session, session->in.transaction, - AVDTP_MSG_TYPE_REJECT, AVDTP_SET_CONFIGURATION, - &rej, sizeof(rej)); + avdtp_send(session, session->in.async_transaction, + AVDTP_MSG_TYPE_REJECT, AVDTP_SET_CONFIGURATION, + &rej, sizeof(rej)); stream_free(stream); return; } - if (!avdtp_send(session, session->in.transaction, AVDTP_MSG_TYPE_ACCEPT, - AVDTP_SET_CONFIGURATION, NULL, 0)) { + if (!avdtp_send(session, session->in.async_transaction, + AVDTP_MSG_TYPE_ACCEPT, + AVDTP_SET_CONFIGURATION, NULL, 0)) { stream_free(stream); return; } @@ -1569,6 +1571,13 @@ static gboolean avdtp_setconf_cmd(struct avdtp *session, uint8_t transaction, session->version = 0x0103; if (sep->ind && sep->ind->set_configuration) { + /* The setconfig configuration stage is asynchronous; + * high CPU load or other factors can delay dbus message + * responses, potentially altering the transaction value. + * It's essential to record the received transaction value + * for use in the final accept command. + */ + session->in.async_transaction = transaction; if (!sep->ind->set_configuration(session, sep, stream, stream->caps, setconf_cb, base-commit: 7ad5669402c9acff8e4cc808edc12a41df36654e -- 2.34.1