From patchwork Sat Oct 28 14:39:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 739350 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E2A3FC27C49 for ; Sat, 28 Oct 2023 14:39:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229495AbjJ1Ojk (ORCPT ); Sat, 28 Oct 2023 10:39:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45838 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229454AbjJ1Ojj (ORCPT ); Sat, 28 Oct 2023 10:39:39 -0400 Received: from lahtoruutu.iki.fi (lahtoruutu.iki.fi [185.185.170.37]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A2FE9EB for ; Sat, 28 Oct 2023 07:39:36 -0700 (PDT) Received: from monolith.lan (unknown [185.77.218.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 4SHhxx6CdJz49Q1r; Sat, 28 Oct 2023 17:39:30 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1698503974; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=1JoB0vBQeH9DHZhC/FVS19u5LaJyPeROD0zgzxDh1nc=; b=VCgcUmX3NmqD3k48nTLj4qWDAcNceco61J7KjjKPHupI2vNtwkwordaSjD/eBg8xwRuSfv PIn2BKrhK3KKGdwO5xSS6arBQMgktGqFSZGUPImdQkI8NVT9CGeK3+Bo367lmq+G29W0f+ UW3mWdQPx6iX7nW7AKGvgIpC8MLZIr9TM4+XQW8DgbeqcOvmp/3a2GUdx0L0nDEsPlETZX SmxlrI8RHkRJ0y+EKHMS1KkI0SIstMj8JJ8h0oWh54oarHGdOSRSYEWuy0OU9Fk6GjtqRY BZ8Zf2Bz7AdsbW+dedz1GOEGtcaSrgKLGe61Go1wx/rqfLJ1JMHFAEy7QL8r6w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1698503974; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=1JoB0vBQeH9DHZhC/FVS19u5LaJyPeROD0zgzxDh1nc=; b=mu2AZTSS1jd2DazkvUJET3+YorA0AAlqeLaPDOwamZZz5+PEcrg+iNN7AOihQDO48adywT ZVw9nOJl0rctVvKL2aHEFR+RrG8/2dWjvhnwewF+ohsHGKVevLHrr8uNDYIQMSWFbXN83e 2tpO1bWogfUov1c2kOMyuGUM0d6/6nUB+fLjaA9W5lS/yY7FaTaG9E9J+cUVPMf61xz1A6 T/2kp6wbCa+dJHr9e4jjjqeNErRPPYyB8NVsdEaVIzjgOuqJktu9BamNr2dH+dl+wyM5WO HZaB7d0UzMmxKpCbxIDp+DihIs2md/OMNROsQQEmJOb5KS7LZK+PHgv/wXQRKw== ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1698503974; a=rsa-sha256; cv=none; b=J81bWAh04MB3FaiUU0MybGj18icyzjVrKZONqTFGYqrGjX/gZmE6OYPX+CapMkZhfQwMlp 6uv3p70JYWI7HeKPVSUz7EGH5ByFHlk0PeTSWsMDNvXPAp28tqriObH4DJZzN580uKRMFj SwKRj1lhwHp/ZkaX9l3QNNtMoEHKYEZgw0DP82jEhHnSaSodHvAB2MinvSj7vceQ6y+1bA UJFfCXf4E6wkt4Ka3Y08PZXUlij5Y9XnGUIB5+J0U+d3d4oHH+GFQt0faNT2n3KjV0qYqT gQlYbkFzNk4nLZaYH9C3k77VsxPAuK1jWEWTZAKT9k9ZUakLUwvEOZhPiK+pMw== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen Subject: [PATCH BlueZ 1/4] doc: extend MediaEndpoint1 API with SelectQoS Date: Sat, 28 Oct 2023 17:39:26 +0300 Message-ID: <6f03ad1eaaa00f84db8cd6a4a4b88ee83078951d.1698503903.git.pav@iki.fi> X-Mailer: git-send-email 2.41.0 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Change unicast BAP configuration to proceed as: 0. SelectProperties(endpoint) 1. ASCS Config Codec 2. ASCS Server notifies ASE 3. SelectQoS(configuration) [optional] 4. ASCS Config QoS 5. SetConfiguration(transport) Previously, SelectProperties had to return also the QoS configuration. However, it is impossible for it to provide it properly, because the values supported by the server are known only after ASCS Config Codec. This resolves the issue by adding a new method call, which is supposed to return suitable QoS values. Remove the QoS input parameter from the SelectProperties() call, as the server supported QoS settings may depend on the codec configuration, and are not known yet at that point. For convenience, e.g. when mandatory QoS presets are used, the endpoint does not need to implement SelectQoS(). In this case the QoS values returned by SelectProperties are used. --- Notes: Alternative to this is calling SelectProperties() twice at the two different stages of the ASE setup steps. However, if the second SelectProperties() call returns a different Capabilities configuration, we'd need to either (i) do Config Codec again or (ii) fail the configuration. Doing Config Codec again introduces a chance of getting stuck looping, if client is not behaving correctly, which doesn't sound like good design. Failing the configuration raises question why have the Capabilities as return parameters at all. So instead, make it a separate method. *** If two methods is too much, we could in principle get rid of the SelectProperties() call and leave only SelectQoS. Instead, the sound server would call SetConfiguration() on a remote endpoint it chooses, and provide the configuration parameters there. IIUC, this is how it is supposed to work for BAP Broadcast currently. This might need some sort of "Ready" property on the Device1 DBus object or elsewhere (e.g. the endpoints), so that it's simple for the sound server to wait until all endpoints have been exposed in DBus. This might also be preferable way to do it, since only the component closer to the user i.e. the sound server knows which endpoint the user wanted to use, and when BlueZ guesses wrong it avoids needing to tear down the old configuration and reconfigure (which we have to do for A2DP). *** This series was tested also vs. this https://gitlab.freedesktop.org/pvir/pipewire/-/commits/bap-selectqos doc/org.bluez.MediaEndpoint.rst | 66 +++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/doc/org.bluez.MediaEndpoint.rst b/doc/org.bluez.MediaEndpoint.rst index 6754d6e3b..4ffe6951c 100644 --- a/doc/org.bluez.MediaEndpoint.rst +++ b/doc/org.bluez.MediaEndpoint.rst @@ -66,6 +66,8 @@ array{byte} SelectConfiguration(array{byte} capabilities) Note: There is no need to cache the selected configuration since on success the configuration is send back as parameter of SetConfiguration. +.. _SelectProperties: + dict SelectProperties(dict capabilities) ```````````````````````````````````````` @@ -79,8 +81,58 @@ dict SelectProperties(dict capabilities) :uint32 Locations: + See `MediaEndpoint Properties`_ for their possible values. + + Returns a configuration which can be used to setup a transport: + + :array{byte} Capabilities: + + See **org.bluez.MediaTransport(5)**. + + :array{byte} Metadata [optional]: + + See **org.bluez.MediaTransport(5)**. + + :dict QoS: + + See **org.bluez.MediaTransport(5)**. + + The following fields shall be provided: + + :byte TargetLatency: + :byte PHY: + + If `SelectQoS`_ is not implemented, then values for + all other ``QoS`` fields are also determined by the + value returned here. + + Note: There is no need to cache the selected properties since + on success the configuration is sent back as parameter of + `SetConfiguration`_ and `SelectQoS`_. + +.. _SelectQoS: + +dict SelectQoS(dict configuration) +`````````````````````````````````` + + Select BAP unicast QoS to be used for a transport, based on + server capabilities and selected configuration. + + :object Endpoint: + + :array{byte} Capabilities: + + The configuration, as returned by `SelectProperties`_. + + :array{byte} Metadata [optional]: + + The metadata, as returned by `SelectProperties`_. + :dict QoS: + Server endpoint supported and preferred values. See + `MediaEndpoint Properties`_ for their possible values. + :byte Framing: :byte PHY: :uint16 MaximumLatency: @@ -89,18 +141,16 @@ dict SelectProperties(dict capabilities) :uint32 PreferredMinimumDelay: :uint32 PreferredMaximumDelay: - See `MediaEndpoint Properties`_ for their possible values. + Returns a QoS configuration which can be used to setup a transport: - Returns a configuration which can be used to setup a transport: - - :array{byte} Capabilities: - :array{byte} Metadata [optional]: :dict QoS: - See `SetConfiguration`_ for their possible values. + See **org.bluez.MediaTransport(5)** QoS property for + possible values. - Note: There is no need to cache the selected properties since on - success the configuration is send back as parameter of SetConfiguration. + Note: There is no need to cache the selected properties since + on success the configuration is sent back as parameter of + `SetConfiguration`_. void ClearConfiguration(object transport) ````````````````````````````````````````` From patchwork Sat Oct 28 14:39:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 739004 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 577E5C27C4A for ; Sat, 28 Oct 2023 14:39:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229502AbjJ1Ojl (ORCPT ); Sat, 28 Oct 2023 10:39:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45840 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229488AbjJ1Ojk (ORCPT ); Sat, 28 Oct 2023 10:39:40 -0400 Received: from lahtoruutu.iki.fi (lahtoruutu.iki.fi [IPv6:2a0b:5c81:1c1::37]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 181EDF0 for ; Sat, 28 Oct 2023 07:39:37 -0700 (PDT) Received: from monolith.lan (unknown [185.77.218.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 4SHhxy4tWZz49Q4M; Sat, 28 Oct 2023 17:39:34 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1698503974; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=82Pvx/CWmqLa+M7kmnpR+VTuTlcjdGYixQptc74mRdU=; b=URVJ95tNWCvXW+5ag3BHIuVjQ38pwrWrTq69zgk+2lfHmA7cZu6OUdDPEb8h9O1tj1DpSn Gn+McweMjJGC0ubF/IkpyA4iU0Lvuz1lULVSSJqxvCLjkDSPVS39WI+RjjCyqpcS2FhNyI hxiIUY/4i/gn0u0Vpldvf5iqng0K4SzuLkh6lOWBDf9QyBRhjIIThJ4s6BTO4hlyJWrZ6k eteizI3FiXxKlM5UsLJjN9bPFQdBp7X2GMHrGEQqT71MYz/Np64H3M2ciojWJd1EZja2Hh Gp75YY52GvTqVKRxn6Cpi4MPjF4mqTv5qMUiJZIh3CjhsE/DauVVZnU8C3og/g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1698503974; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=82Pvx/CWmqLa+M7kmnpR+VTuTlcjdGYixQptc74mRdU=; b=Gyu1vecPlH6MXDhmNq7+TzNmkgU1cvlWmFy68KpLOmMsVLyCo86tc1DVPOh9e+0kvTeVVq LJWNvTNj4IwimBUKhYKAFke8Y5kakqvtpOX3Sh/4cwPlrDdBgoZkdmvISqcZCzJ+LCZE3h 33HKtRvZsxTIABJ/ndgAGGyH48kQq9hKif7JL/kwe0bx2iYbJesbps1rTQiGioET/hdzIR DCsrZjZjRNeDk02aXiG6rcm7KTI/tesO3JF5cCsw9UuE9uenegj7q/MA0z5TJjN0/mU2sn X6ayVf0+lXOTd3c70E87cW2jX/s+jJVekoNWjhHcHuVywG7KedvQc5LAzlqHsg== ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1698503974; a=rsa-sha256; cv=none; b=MsLxW2hjE4ZKUCHNlXciHC7rUSFG8VWp8AH5JvKFqbGeFCzANaYrIB3n9bjXsnNs9OEmQZ dNunanRj8Vr6Pp6VVjzkIzqePYfaDNFkC6UNxt6XqNvUuRoy/BedORcALIfdftkKJ9SO8v ijzWU7wLyVfHUc/4Ix6J2alozVZQQRZN/ZXoUodkCPGcvrDspdieKzcQ2plYN++UYKd/Ll 0JirbZ1s7vaG4vL+rmBRQO7xpxtg3F3CnkIBzAoTFhTbev5tHVsikF1tDJOjqzXoN7VSzS 4kzjvak4rAtFsCflF6HV6XHCi/BDrSJSFAgTRuCydRoviCXTWz6w8c9+z6VaJA== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen Subject: [PATCH BlueZ 2/4] shared/bap: rename PAC op select -> select_codec, add select_qos Date: Sat, 28 Oct 2023 17:39:27 +0300 Message-ID: <2cbda517f3818b68bc3e2e44328116e76b9bb3b7.1698503903.git.pav@iki.fi> X-Mailer: git-send-email 2.41.0 In-Reply-To: <6f03ad1eaaa00f84db8cd6a4a4b88ee83078951d.1698503903.git.pav@iki.fi> References: <6f03ad1eaaa00f84db8cd6a4a4b88ee83078951d.1698503903.git.pav@iki.fi> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org The BAP Unicast Client stream configuration flow has two steps, Config Codec and Config QoS. Previously both the ASE Codec & QoS configuration was obtained from the local PAC via bt_bap_pac_ops.select, but the information what the BAP Server supports becomes available only after Config Codec completes successfully. So the single-step configuration doesn't work out correctly in the API. Split out the QoS configuration to a separate PAC operation. Rename "select" to "select_codec", and add select_qos and bt_bap_stream_select_qos for the QoS configuration step. Also add bt_bap_stream_get_lpac/rpac, which will be needed in the QoS configuration callback. --- src/shared/bap.c | 37 ++++++++++++++++++++++++++++++++----- src/shared/bap.h | 23 +++++++++++++++++------ 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/shared/bap.c b/src/shared/bap.c index 13bbcf793..6155b8640 100644 --- a/src/shared/bap.c +++ b/src/shared/bap.c @@ -4617,17 +4617,34 @@ static bool match_pac(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, return false; } -int bt_bap_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, - bt_bap_pac_select_t func, void *user_data) +int bt_bap_select_codec(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, + bt_bap_pac_select_codec_t func, void *user_data) { if (!lpac || !rpac || !func) return -EINVAL; - if (!lpac->ops || !lpac->ops->select) + if (!lpac->ops || !lpac->ops->select_codec) return -EOPNOTSUPP; - lpac->ops->select(lpac, rpac, &rpac->qos, - func, user_data, lpac->user_data); + lpac->ops->select_codec(lpac, rpac, func, user_data, lpac->user_data); + + return 0; +} + +int bt_bap_stream_select_qos(struct bt_bap_stream *stream, + bt_bap_pac_select_qos_t func, void *user_data) +{ + struct bt_bap_pac *lpac = stream->lpac; + struct bt_bap_pac *rpac = stream->rpac; + + if (!lpac || !rpac || !func) + return -EINVAL; + + if (!lpac->ops || !lpac->ops->select_qos) + return -EOPNOTSUPP; + + lpac->ops->select_qos(stream, &rpac->qos, func, user_data, + lpac->user_data); return 0; } @@ -5124,6 +5141,16 @@ uint32_t bt_bap_stream_get_location(struct bt_bap_stream *stream) return stream->bap->ldb->pacs->source_loc_value; } +struct bt_bap_pac *bt_bap_stream_get_lpac(struct bt_bap_stream *stream) +{ + return stream->lpac; +} + +struct bt_bap_pac *bt_bap_stream_get_rpac(struct bt_bap_stream *stream) +{ + return stream->rpac; +} + struct iovec *bt_bap_stream_get_config(struct bt_bap_stream *stream) { if (!stream) diff --git a/src/shared/bap.h b/src/shared/bap.h index 23edbf4c6..d8fae0ef8 100644 --- a/src/shared/bap.h +++ b/src/shared/bap.h @@ -104,12 +104,15 @@ typedef void (*bt_bap_pac_func_t)(struct bt_bap_pac *pac, void *user_data); typedef bool (*bt_bap_pac_foreach_t)(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, void *user_data); -typedef void (*bt_bap_pac_select_t)(struct bt_bap_pac *pac, int err, +typedef void (*bt_bap_pac_select_codec_t)(struct bt_bap_pac *pac, int err, struct iovec *caps, struct iovec *metadata, struct bt_bap_qos *qos, void *user_data); typedef void (*bt_bap_pac_config_t)(struct bt_bap_stream *stream, int err); +typedef void (*bt_bap_pac_select_qos_t)(struct bt_bap_stream *stream, + int err, struct bt_bap_qos *qos, + void *user_data); typedef void (*bt_bap_state_func_t)(struct bt_bap_stream *stream, uint8_t old_state, uint8_t new_state, void *user_data); @@ -150,9 +153,12 @@ struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name, struct iovec *metadata); struct bt_bap_pac_ops { - int (*select)(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, - struct bt_bap_pac_qos *qos, - bt_bap_pac_select_t cb, void *cb_data, void *user_data); + int (*select_codec)(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, + bt_bap_pac_select_codec_t cb, void *cb_data, + void *user_data); + int (*select_qos)(struct bt_bap_stream *stream, + struct bt_bap_pac_qos *qos, bt_bap_pac_select_qos_t cb, + void *cb_data, void *user_data); int (*config)(struct bt_bap_stream *stream, struct iovec *cfg, struct bt_bap_qos *qos, bt_bap_pac_config_t cb, void *user_data); @@ -233,8 +239,8 @@ void bt_bap_pac_set_user_data(struct bt_bap_pac *pac, void *user_data); void *bt_bap_pac_get_user_data(struct bt_bap_pac *pac); /* Stream related functions */ -int bt_bap_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, - bt_bap_pac_select_t func, void *user_data); +int bt_bap_select_codec(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, + bt_bap_pac_select_codec_t func, void *user_data); struct bt_bap_stream *bt_bap_stream_new(struct bt_bap *bap, struct bt_bap_pac *lpac, @@ -249,6 +255,9 @@ bool bt_bap_stream_set_user_data(struct bt_bap_stream *stream, void *user_data); void *bt_bap_stream_get_user_data(struct bt_bap_stream *stream); +int bt_bap_stream_select_qos(struct bt_bap_stream *stream, + bt_bap_pac_select_qos_t func, void *user_data); + unsigned int bt_bap_stream_config(struct bt_bap_stream *stream, struct bt_bap_qos *pqos, struct iovec *data, @@ -293,6 +302,8 @@ uint32_t bt_bap_stream_get_location(struct bt_bap_stream *stream); struct iovec *bt_bap_stream_get_config(struct bt_bap_stream *stream); struct bt_bap_qos *bt_bap_stream_get_qos(struct bt_bap_stream *stream); struct iovec *bt_bap_stream_get_metadata(struct bt_bap_stream *stream); +struct bt_bap_pac *bt_bap_stream_get_lpac(struct bt_bap_stream *stream); +struct bt_bap_pac *bt_bap_stream_get_rpac(struct bt_bap_stream *stream); struct io *bt_bap_stream_get_io(struct bt_bap_stream *stream); bool bt_bap_match_bcast_sink_stream(const void *data, const void *user_data); From patchwork Sat Oct 28 14:39:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 739351 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CD83DC27C47 for ; Sat, 28 Oct 2023 14:39:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229496AbjJ1Ojl (ORCPT ); Sat, 28 Oct 2023 10:39:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45852 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229492AbjJ1Ojk (ORCPT ); Sat, 28 Oct 2023 10:39:40 -0400 Received: from lahtoruutu.iki.fi (lahtoruutu.iki.fi [185.185.170.37]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A3116ED for ; Sat, 28 Oct 2023 07:39:36 -0700 (PDT) Received: from monolith.lan (unknown [185.77.218.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 4SHhxy5TyGz49Q53; Sat, 28 Oct 2023 17:39:34 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1698503974; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PgupAMjxf3FZg7KbfgWCwoQzp7gmc4UrEkOyEJnGf4k=; b=KKl896c/XVuEUPis+8DHmFRiW1/Ty+ybQV/G4tHn+lmKApLxq0Y28rvOsI24q6mB+ReyQe y8r6o1bO+gTHoc0OzZki6A21nfvJB5rpZajn1hSurY8/GyUmrJvt0IYZEI7jrNumJvNltg AslPpo4HqY/QVty+5oit6eEbFOT5v5FeL8SkmxhWSjA8rO2b+NknAlYMdwwfrN+nFkCtYS Qvkj3B9d5HCpX5H1b8kz7Wnfsw/BRBIRKWqaGbam6wDuiGGQA073PUfp/G7cycHjm2kn6D LNDXNgfiN8km5MpGvX5BMjuw6RR/wzZPk6+k8M5tNcflZe54B8o1DnrE/5lgnA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1698503974; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PgupAMjxf3FZg7KbfgWCwoQzp7gmc4UrEkOyEJnGf4k=; b=kJ1jxV7mv5FIVq6PRnl21phJ/li0ZWc21dkevLaiRFdoTYxP280K4JKGU9RJ7lzZRaC77k rDe59aiXgIFlXSbS78vTmcwj0lRXs18c80G3ib6UxRI5qlHRpmLnsgHsec444JxLFAyeAY ECBLf9TjCZwTLfi8d6Usf6MKaEwaZvIZ77DoFJRYDAe6ylhLEiQMw4SAPTolPRzjRYNiue RVJniMEkjbQUeeJPf1BSVri51+RRrFv+oxkpz/llDEgKtM3wdsD6pD5Vclw1CcsVP2su1n /HzZFxInJ8U6kw4dTIyUDyQEl4IV6dL0GAbnPCEcPA5Pk60W5JMyKrU+5Rs3Kg== ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1698503974; a=rsa-sha256; cv=none; b=vP7qVmBnVXQYuiPuzU79e2JhCbvZk82CVdq4enLF4bu/pcg85W4iiRmdi//e50jg4DB26e /d/EKIy6alZM8Lks9DuMH8Q1HihW3fWcWZB99XEiBWxZ+TCLEbU9C8EP390QsHMHXG9lTQ EaWMEEGMzNYrrUkoVXWpvUkgdhPXew0G5jDXYrCe8TNwQVVIl6t/YQWwJo2ZumkpjWAAZk FlLx2wYbnC+rgqLve7WRoOT6nOgaxo2472Y5ARevz8flpZNVnkv0c3aWYzNteaYQ9BfEBF FLmmJ/N0DOS5+jozF120jnjsVTQpaHqSUljlNWPxxLOHi7Gm+0BsneAfjZ9FGA== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen Subject: [PATCH BlueZ 3/4] bap: obtain BAP ucast client QoS via calling endpoint SelectQoS() Date: Sat, 28 Oct 2023 17:39:28 +0300 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: <6f03ad1eaaa00f84db8cd6a4a4b88ee83078951d.1698503903.git.pav@iki.fi> References: <6f03ad1eaaa00f84db8cd6a4a4b88ee83078951d.1698503903.git.pav@iki.fi> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Enable the client endpoint to implement SelectQoS() to configure the QoS as a second step in the configuration flow. Remove the QoS parameter from SelectProperties(), as the values are not actually know at that point of the configuration flow. If the client does not implement SelectQoS() we will just use all the QoS values returned by SelectProperties(). If they are one of the mandatory configurations, then maybe devices will accept them. --- profiles/audio/bap.c | 98 +++++++++++++------- profiles/audio/media.c | 201 +++++++++++++++++++++++++++++++++-------- 2 files changed, 225 insertions(+), 74 deletions(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index b74498c4c..a289daf15 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -725,23 +725,17 @@ fail: return -EINVAL; } -static void qos_cb(struct bt_bap_stream *stream, uint8_t code, uint8_t reason, - void *user_data) +static void ep_reply_msg(struct bap_ep *ep, const char *error) { - struct bap_ep *ep = user_data; DBusMessage *reply; - DBG("stream %p code 0x%02x reason 0x%02x", stream, code, reason); - - ep->id = 0; - if (!ep->msg) return; - if (!code) + if (!error) reply = dbus_message_new_method_return(ep->msg); else - reply = btd_error_failed(ep->msg, "Unable to configure"); + reply = btd_error_failed(ep->msg, error); g_dbus_send_message(btd_get_dbus_connection(), reply); @@ -749,28 +743,30 @@ static void qos_cb(struct bt_bap_stream *stream, uint8_t code, uint8_t reason, ep->msg = NULL; } -static void config_cb(struct bt_bap_stream *stream, - uint8_t code, uint8_t reason, +static void qos_cb(struct bt_bap_stream *stream, uint8_t code, uint8_t reason, void *user_data) { struct bap_ep *ep = user_data; - DBusMessage *reply; DBG("stream %p code 0x%02x reason 0x%02x", stream, code, reason); ep->id = 0; - if (!code) - return; + ep_reply_msg(ep, code ? "Unable to configure" : NULL); +} - if (!ep->msg) - return; +static void config_cb(struct bt_bap_stream *stream, + uint8_t code, uint8_t reason, + void *user_data) +{ + struct bap_ep *ep = user_data; - reply = btd_error_failed(ep->msg, "Unable to configure"); - g_dbus_send_message(btd_get_dbus_connection(), reply); + DBG("stream %p code 0x%02x reason 0x%02x", stream, code, reason); - dbus_message_unref(ep->msg); - ep->msg = NULL; + ep->id = 0; + + if (code) + ep_reply_msg(ep, "Unable to configure"); } static void bap_io_close(struct bap_ep *ep) @@ -1202,7 +1198,7 @@ static void bap_config(void *data, void *user_data) bt_bap_stream_set_user_data(ep->stream, ep->path); } -static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps, +static void select_codec_cb(struct bt_bap_pac *pac, int err, struct iovec *caps, struct iovec *metadata, struct bt_bap_qos *qos, void *user_data) { @@ -1252,7 +1248,7 @@ static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, /* TODO: Cache LRU? */ if (btd_service_is_initiator(service)) { - if (!bt_bap_select(lpac, rpac, select_cb, ep)) + if (!bt_bap_select_codec(lpac, rpac, select_codec_cb, ep)) ep->data->selecting++; } @@ -1877,6 +1873,36 @@ static void bap_create_io(struct bap_data *data, struct bap_ep *ep, } } +static void select_qos_cb(struct bt_bap_stream *stream, int err, + struct bt_bap_qos *qos, void *user_data) +{ + struct bap_ep *ep = user_data; + + DBG("stream %p err %d qos %p", stream, err, qos); + + if (err || ep->id) + goto fail; + + if (qos) + ep->qos = *qos; + + bap_create_io(ep->data, ep, stream, true); + if (!ep->io) { + error("Unable to create io"); + goto fail; + } + + ep->id = bt_bap_stream_qos(stream, &ep->qos, qos_cb, ep); + if (!ep->id) + goto fail; + + return; + +fail: + error("Failed to Configure QoS"); + ep_reply_msg(ep, "Unable to configure"); +} + static void bap_state(struct bt_bap_stream *stream, uint8_t old_state, uint8_t new_state, void *user_data) { @@ -1902,25 +1928,27 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state, queue_remove(data->streams, stream); break; case BT_BAP_STREAM_STATE_CONFIG: - if (ep && !ep->id) { + if (!ep || ep->id) + break; + + switch (bt_bap_stream_get_type(stream)) { + case BT_BAP_STREAM_TYPE_UCAST: + if (bt_bap_stream_select_qos(stream, + select_qos_cb, ep)) { + error("Failed to Configure QoS"); + bt_bap_stream_release(stream, + NULL, NULL); + return; + } + break; + case BT_BAP_STREAM_TYPE_BCAST: bap_create_io(data, ep, stream, true); if (!ep->io) { error("Unable to create io"); bt_bap_stream_release(stream, NULL, NULL); return; } - - if (bt_bap_stream_get_type(stream) == - BT_BAP_STREAM_TYPE_UCAST) { - /* Wait QoS response to respond */ - ep->id = bt_bap_stream_qos(stream, &ep->qos, - qos_cb, ep); - if (!ep->id) { - error("Failed to Configure QoS"); - bt_bap_stream_release(stream, - NULL, NULL); - } - } + break; } break; case BT_BAP_STREAM_STATE_QOS: diff --git a/profiles/audio/media.c b/profiles/audio/media.c index 4d9a6aa03..42bc21386 100644 --- a/profiles/audio/media.c +++ b/profiles/audio/media.c @@ -318,6 +318,17 @@ static void endpoint_reply(DBusPendingCall *call, void *user_data) dbus_error_init(&err); if (dbus_set_error_from_message(&err, reply)) { + /* Endpoint is not required to implement SelectQoS */ + if (dbus_error_has_name(&err, DBUS_ERROR_UNKNOWN_METHOD) && + dbus_message_is_method_call(request->msg, + MEDIA_ENDPOINT_INTERFACE, "SelectQoS")) { + dbus_error_free(&err); + value = FALSE; + size = sizeof(value); + ret = &value; + goto done; + } + error("Endpoint replied with an error: %s", err.name); @@ -358,6 +369,13 @@ static void endpoint_reply(DBusPendingCall *call, void *user_data) dbus_message_iter_recurse(&args, &props); ret = &props; goto done; + } else if (dbus_message_is_method_call(request->msg, + MEDIA_ENDPOINT_INTERFACE, + "SelectQoS")) { + dbus_message_iter_init(reply, &args); + dbus_message_iter_recurse(&args, &props); + ret = &props; + goto done; } else if (!dbus_message_get_args(reply, &err, DBUS_TYPE_INVALID)) { error("Wrong reply signature: %s", err.message); dbus_error_free(&err); @@ -725,9 +743,9 @@ static bool endpoint_init_a2dp_sink(struct media_endpoint *endpoint, int *err) return true; } -struct pac_select_data { +struct pac_select_codec_data { struct bt_bap_pac *pac; - bt_bap_pac_select_t cb; + bt_bap_pac_select_codec_t cb; void *user_data; }; @@ -881,10 +899,10 @@ fail: return -EINVAL; } -static void pac_select_cb(struct media_endpoint *endpoint, void *ret, int size, - void *user_data) +static void pac_select_codec_cb(struct media_endpoint *endpoint, void *ret, + int size, void *user_data) { - struct pac_select_data *data = user_data; + struct pac_select_codec_data *data = user_data; DBusMessageIter *iter = ret; int err; struct iovec caps, meta; @@ -920,15 +938,15 @@ done: data->cb(data->pac, err, &caps, &meta, &qos, data->user_data); } -static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, - struct bt_bap_pac_qos *qos, - bt_bap_pac_select_t cb, void *cb_data, void *user_data) +static int pac_select_codec(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, + bt_bap_pac_select_codec_t cb, void *cb_data, + void *user_data) { struct media_endpoint *endpoint = user_data; struct iovec *caps; struct iovec *metadata; const char *endpoint_path; - struct pac_select_data *data; + struct pac_select_codec_data *data; DBusMessage *msg; DBusMessageIter iter, dict; const char *key = "Capabilities"; @@ -946,7 +964,7 @@ static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, return -ENOMEM; } - data = new0(struct pac_select_data, 1); + data = new0(struct pac_select_codec_data, 1); data->pac = lpac; data->cb = cb; data->user_data = cb_data; @@ -977,47 +995,151 @@ static int pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, metadata->iov_len); } - if (qos && qos->phy) { - DBusMessageIter entry, variant, qos_dict; + dbus_message_iter_close_container(&iter, &dict); + + return media_endpoint_async_call(msg, endpoint, NULL, + pac_select_codec_cb, data, free); +} + +struct pac_select_qos_data { + struct bt_bap_stream *stream; + bt_bap_pac_select_qos_t cb; + void *user_data; +}; + +static void pac_select_qos_cb(struct media_endpoint *endpoint, void *ret, + int size, void *user_data) +{ + struct pac_select_qos_data *data = user_data; + DBusMessageIter *iter = ret; + int err; + struct bt_bap_qos qos; + + if (!ret) { + data->cb(data->stream, -EPERM, NULL, data->user_data); + return; + } else if (size > 0) { + /* Endpoint doesn't implement the method, use old values */ + data->cb(data->stream, 0, NULL, data->user_data); + return; + } + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) { + DBG("Unexpected argument type: %c != %c", + dbus_message_iter_get_arg_type(iter), + DBUS_TYPE_DICT_ENTRY); + data->cb(data->stream, -EINVAL, NULL, data->user_data); + return; + } + + memset(&qos, 0, sizeof(qos)); + + /* Mark CIG and CIS to be auto assigned */ + qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET; + qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET; + + err = parse_select_properties(iter, NULL, NULL, &qos); + if (err < 0) + DBG("Unable to parse properties"); + + data->cb(data->stream, err, &qos, data->user_data); +} - key = "QoS"; - dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, - NULL, &entry); - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); - dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, - "a{sv}", &variant); - dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, - "{sv}", &qos_dict); +static int pac_select_qos(struct bt_bap_stream *stream, + struct bt_bap_pac_qos *qos, bt_bap_pac_select_qos_t cb, + void *cb_data, void *user_data) +{ + struct media_endpoint *endpoint = user_data; + struct bt_bap_pac *rpac; + const char *endpoint_path; + struct pac_select_qos_data *data; + struct iovec *caps, *metadata; + DBusMessage *msg; + DBusMessageIter iter, dict; + DBusMessageIter entry, variant, qos_dict; + const char *key = "Capabilities"; + + rpac = bt_bap_stream_get_rpac(stream); + if (!rpac) + return -EINVAL; - g_dbus_dict_append_entry(&qos_dict, "Framing", DBUS_TYPE_BYTE, - &qos->framing); + caps = bt_bap_stream_get_config(stream); + if (!caps) + return -EINVAL; - g_dbus_dict_append_entry(&qos_dict, "PHY", DBUS_TYPE_BYTE, - &qos->phy); + msg = dbus_message_new_method_call(endpoint->sender, endpoint->path, + MEDIA_ENDPOINT_INTERFACE, + "SelectQoS"); + if (msg == NULL) { + error("Couldn't allocate D-Bus message"); + return -ENOMEM; + } - g_dbus_dict_append_entry(&qos_dict, "MaximumLatency", - DBUS_TYPE_UINT16, &qos->latency); + data = new0(struct pac_select_qos_data, 1); + data->stream = stream; + data->cb = cb; + data->user_data = cb_data; - g_dbus_dict_append_entry(&qos_dict, "MinimumDelay", - DBUS_TYPE_UINT32, &qos->pd_min); + dbus_message_iter_init_append(msg, &iter); - g_dbus_dict_append_entry(&qos_dict, "MaximumDelay", - DBUS_TYPE_UINT32, &qos->pd_max); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict); - g_dbus_dict_append_entry(&qos_dict, "PreferredMinimumDelay", - DBUS_TYPE_UINT32, &qos->ppd_min); + endpoint_path = bt_bap_pac_get_user_data(rpac); + if (endpoint_path) + g_dbus_dict_append_entry(&dict, "Endpoint", + DBUS_TYPE_OBJECT_PATH, &endpoint_path); - g_dbus_dict_append_entry(&qos_dict, "PreferredMaximumDelay", - DBUS_TYPE_UINT32, &qos->ppd_max); + key = "Capabilities"; + g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &key, + DBUS_TYPE_BYTE, &caps->iov_base, + caps->iov_len); - dbus_message_iter_close_container(&variant, &qos_dict); - dbus_message_iter_close_container(&entry, &variant); - dbus_message_iter_close_container(&dict, &entry); + metadata = bt_bap_stream_get_metadata(stream); + if (metadata) { + key = "Metadata"; + g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &key, + DBUS_TYPE_BYTE, + &metadata->iov_base, + metadata->iov_len); } + key = "QoS"; + dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, + NULL, &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); + dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, + "a{sv}", &variant); + dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, + "{sv}", &qos_dict); + + g_dbus_dict_append_entry(&qos_dict, "Framing", DBUS_TYPE_BYTE, + &qos->framing); + + g_dbus_dict_append_entry(&qos_dict, "PHY", DBUS_TYPE_BYTE, + &qos->phy); + + g_dbus_dict_append_entry(&qos_dict, "MaximumLatency", + DBUS_TYPE_UINT16, &qos->latency); + + g_dbus_dict_append_entry(&qos_dict, "MinimumDelay", + DBUS_TYPE_UINT32, &qos->pd_min); + + g_dbus_dict_append_entry(&qos_dict, "MaximumDelay", + DBUS_TYPE_UINT32, &qos->pd_max); + + g_dbus_dict_append_entry(&qos_dict, "PreferredMinimumDelay", + DBUS_TYPE_UINT32, &qos->ppd_min); + + g_dbus_dict_append_entry(&qos_dict, "PreferredMaximumDelay", + DBUS_TYPE_UINT32, &qos->ppd_max); + + dbus_message_iter_close_container(&variant, &qos_dict); + dbus_message_iter_close_container(&entry, &variant); + dbus_message_iter_close_container(&dict, &entry); + dbus_message_iter_close_container(&iter, &dict); - return media_endpoint_async_call(msg, endpoint, NULL, pac_select_cb, + return media_endpoint_async_call(msg, endpoint, NULL, pac_select_qos_cb, data, free); } @@ -1187,8 +1309,9 @@ static void pac_clear(struct bt_bap_stream *stream, void *user_data) } static struct bt_bap_pac_ops pac_ops = { - .select = pac_select, + .select_codec = pac_select_codec, .config = pac_config, + .select_qos = pac_select_qos, .clear = pac_clear, }; From patchwork Sat Oct 28 14:39:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 739005 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7ED54C0032E for ; Sat, 28 Oct 2023 14:39:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229479AbjJ1Ojj (ORCPT ); Sat, 28 Oct 2023 10:39:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45832 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229449AbjJ1Ojj (ORCPT ); Sat, 28 Oct 2023 10:39:39 -0400 Received: from lahtoruutu.iki.fi (lahtoruutu.iki.fi [185.185.170.37]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A2F89CC for ; Sat, 28 Oct 2023 07:39:36 -0700 (PDT) Received: from monolith.lan (unknown [185.77.218.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by lahtoruutu.iki.fi (Postfix) with ESMTPSA id 4SHhxz0mp1z49Q5M; Sat, 28 Oct 2023 17:39:35 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1698503975; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8gyxvYQlCsyGRbzKojenkvssi/QhYUN27zqvGG7nZXU=; b=o4P2RMFml3l4JPdws69E9L3wULEoQeqflMkhqbpgeSgLtbWK2TCWfY1Ewj1V49tWLLOYdH 1kJQoqZjbZuRhsUUcDsxcSOFRZmUHJUCjjRbv1p6FSeCtrqOOPJgXDlAN+pSDPguDqsbVr xw5hLLabfVwkqv7T9sEL6aQCVajeVPVd/48d7IJ5JtDx3hQytTlcDYBWIQY5yT+HAEmNQE +cz9XwZeqgXHE+QJ8UKlJRclAH5I0DO+4E2ISBEwFiiPZwDHYFMButXh9hlic7E/TddLea r9dLwK8cmQIyvotqmXl8R0jfyybXkj5lc4jGX9uTBrXHZ53pS5Eon4kRFw57kg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=lahtoruutu; t=1698503975; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8gyxvYQlCsyGRbzKojenkvssi/QhYUN27zqvGG7nZXU=; b=N8JYgrfP40e/NSImDJes04ZzCmmlljtDyqOqpRFLT/z03YxCozdUWZdaKpijT94vU7IiqL stBx7QbJf3PCpQnPJ9szGRiZZ8x5wKyOZRcxT2J6Wf1YyRuJRblEJLwIA0VwWaAlUJfTzf 4SbUh1giFErhVx7EgFXZz8p5uwXeVzEryD5S1JGQtBcoHU7Nzx8JOKDMBpzbplG+QRfsOV xu4S9qyzts0iYzQX87ptBLsuXV4dvDRs/uszqdvKDjpRuzNUCoTGfhIR2ORVfjO7fu/TSy 7SEMgddF7x4PpWoMAbuVuzKfzfbmyrGp+0nzBEdYsHTV+Z7i7y/TAqlqST2RsQ== ARC-Seal: i=1; s=lahtoruutu; d=iki.fi; t=1698503975; a=rsa-sha256; cv=none; b=lWVkK2noey8TWLgQHoKIxHM7w0By7p2+vlt6ZUZU5ugQw5IlXus/42PLh0+KbXCI4hfpuD +5flEBAfsOZJMPvjQSwMHSMlX05tDpiaqS3YPLK4crd/htnISDWFkO3bv727c2q/M4J/+3 fT64g+JVxvuLjNC8S1H2xqJkXgDlUa38zEk3H7+/FDAB7r7m+o6/Z1QRbr55NIhqmgk1vL 6qczt3crMRY81IKJc51D/j+Ar1e1HlVozxP3jQghsMuI54I4OSBtSLf/jC/5d00Q0/ZlR5 kML7aFCRfMCRprmHpf2erFh0duavhdRPCyFZYCWEBtnAtnR4Y6JRfwBkh0ufCw== ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen Subject: [PATCH BlueZ 4/4] client: implement SelectQoS Date: Sat, 28 Oct 2023 17:39:29 +0300 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: <6f03ad1eaaa00f84db8cd6a4a4b88ee83078951d.1698503903.git.pav@iki.fi> References: <6f03ad1eaaa00f84db8cd6a4a4b88ee83078951d.1698503903.git.pav@iki.fi> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Implement SelectQoS() so that the server-provided values get printed. We don't take them into account yet otherwise, though. --- client/player.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/client/player.c b/client/player.c index 715598aa9..4ad6b99d9 100644 --- a/client/player.c +++ b/client/player.c @@ -91,6 +91,7 @@ struct endpoint { struct queue *transports; DBusMessage *msg; struct preset *preset; + struct codec_preset *codec_preset; bool broadcast; struct iovec *bcode; }; @@ -2078,6 +2079,8 @@ static void select_properties_response(const char *input, void *user_data) p = preset_find_name(ep->preset, input); if (p) { reply = endpoint_select_properties_reply(ep, ep->msg, p); + if (reply) + ep->codec_preset = p; goto done; } @@ -2130,6 +2133,49 @@ static DBusMessage *endpoint_select_properties(DBusConnection *conn, return reply; } +static DBusMessage *endpoint_select_qos(DBusConnection *conn, + DBusMessage *msg, void *user_data) +{ + struct endpoint *ep = user_data; + struct codec_preset *preset = ep->codec_preset; + DBusMessageIter args; + DBusMessageIter iter, dict; + DBusMessage *reply; + struct endpoint_config cfg; + + dbus_message_iter_init(msg, &args); + + bt_shell_printf("Endpoint: SelectQoS\n"); + print_iter("\t", "Properties", &args); + + if (!preset) + return g_dbus_create_error(msg, "org.bluez.Error.Rejected", + "No previous codec preset"); + + reply = dbus_message_new_method_return(msg); + if (!reply) + return NULL; + + dbus_message_iter_init_append(reply, &iter); + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict); + + /* TODO: we ignore BAP Server supported values here. If they are not + * suitable for the preset, we should prompt for a preset again, and + * call SetConfiguration on the remote endpoint with the new + * configuration to retry. + */ + + memset(&cfg, 0, sizeof(cfg)); + cfg.ep = ep; + cfg.qos = &preset->qos; + append_qos(&dict, &cfg); + + dbus_message_iter_close_container(&iter, &dict); + + return reply; +} + static bool match_str(const void *data, const void *user_data) { return !strcmp(data, user_data); @@ -2248,6 +2294,10 @@ static const GDBusMethodTable endpoint_methods[] = { GDBUS_ARGS({ "properties", "a{sv}" } ), GDBUS_ARGS({ "properties", "a{sv}" } ), endpoint_select_properties) }, + { GDBUS_ASYNC_METHOD("SelectQoS", + GDBUS_ARGS({ "properties", "a{sv}" } ), + GDBUS_ARGS({ "properties", "a{sv}" } ), + endpoint_select_qos) }, { GDBUS_ASYNC_METHOD("ClearConfiguration", GDBUS_ARGS({ "transport", "o" } ), NULL, endpoint_clear_configuration) },