From patchwork Sun May 4 16:01:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 887242 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7CFD725771 for ; Sun, 4 May 2025 16:02:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374539; cv=pass; b=DzvnA9fyAr3eZeRBlLacUckci7juC2rNW9u19bK08pyxch8Kvhb9WKuRXsxYLUL4KC2Tgp3lZyWgmpiWsIhUAVGzvmjuL7OdS6KmWMp5gLnnKUOzx8rbWtY1CDZK+hB6tskDeWfNV2ies0D18WpmvFbeyqljkPbhfVRdmx8ESSY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374539; c=relaxed/simple; bh=mT0gdvBJeiu47wyrF8Nbef7AIzSwgfEQZO9pcf0k4Ew=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=qvTJIOqf+YSdmahA54pHGglIhHzKtW0uQFmbSZggZWaPh9Pe/ZcpCVtGs585BP8ESr3Cgt0rS+mAYf3Ey65OLmuvSbmyf5NbQ+8igawn+pxjxVgn/EzpOiuNjRvohhsuiBgCqjUJmb9rlrMsNDTM1smOsi+bpPI3QgYAdklDB0s= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=toRbJeF4; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="toRbJeF4" 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 meesny.iki.fi (Postfix) with ESMTPSA id 4Zr8YY43WVzyNC; Sun, 4 May 2025 19:02:09 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374529; 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=M5ATRzSEdlEHRHON0Vd/Laqho58L9AH19ahm2wENUhM=; b=toRbJeF40gAO4VG3b6QouYEh9giv3qrRhm/lY2orS8rdw4ezSnAEA4ZLggqM+M5I+LdaiF 3HbSXUsikQSbxEOwiZra2GKrZKt7RR/eXJV3hdvg+2uzIXqMqooBJuLPXndrDu4K6qr/vu XbK/3KMBwnkjATgYx3I6YVfMu4TAW7w= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374529; 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=M5ATRzSEdlEHRHON0Vd/Laqho58L9AH19ahm2wENUhM=; b=JSteS2rK8UDarrXIFn7cKvWS5lfSicwAoGj05f/2Z68/2nZr84sGRziRsBqAywd3DjMqZx 6nKv44JTyiJqBVrYBxHv28JjR1CwaIy8x10DZ2g6k51wHfWSa1ml1SXGsc8gF74kByLyqa Fg5Kx5sCbdmdz++VTvT3aLxgIdK603g= ARC-Seal: i=1; s=meesny; d=iki.fi; t=1746374529; a=rsa-sha256; cv=none; b=EMWMgdQpOUrsZKVL5Jh/IILgZ4N8vqz/7xIVUSUktMzNqySwhH+T6PqFRwFM22IFWi4+5C q1OitGER+pS4w4b0wh8MNgOjWvrkd/Kcot8rvhMGPZ6Oi9RiPLfw229CWyPshkvSGwU+mu L76r0TciT1sp++mD2JCVfb1N+vfSn1E= 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: [RFC PATCH BlueZ v2 01/11] org.bluez.MediaEndpoint: removing BAP streams with ClearConfiguration Date: Sun, 4 May 2025 19:01:53 +0300 Message-ID: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> X-Mailer: git-send-email 2.49.0 Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Allow user to remove specific streams by calling ClearConfiguration(transport_path) on the endpoint. If the path is the endpoint path instead, clear all streams associated with the endpoint. --- Notes: Whole patch series: Pipewire side: https://gitlab.freedesktop.org/pvir/pipewire/-/commits/bap-codec-switch-select Tested with - Sony Linkbuds S: switching between AC 6(ii), 7(ii), 8(ii), 11(ii) - Earfun Air Pro 3: switching between AC 6(i), 11(i) TODO: - Enabling/Disabling while Reconfigure/ClearConfiguration is in progress should be handled better. Stream QoS should be delayed until CIG is no longer busy. doc/org.bluez.MediaEndpoint.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/org.bluez.MediaEndpoint.rst b/doc/org.bluez.MediaEndpoint.rst index f2b830ab0..b81106f0b 100644 --- a/doc/org.bluez.MediaEndpoint.rst +++ b/doc/org.bluez.MediaEndpoint.rst @@ -109,6 +109,12 @@ void ClearConfiguration(object transport) Clear transport configuration. + **Server role:** [ISO only] + + Close the stream associated with the given transport. If the + path given is the path of this endpoint, all its streams are + closed. + void Release() `````````````` From patchwork Sun May 4 16:01:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 887240 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 91BDA146A72 for ; Sun, 4 May 2025 16:02:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374542; cv=pass; b=cjUKuPvjgD34XZi9YooXELw25s7krHAi6WfjO9SLMFzz1NdLbiGEjTlQ9uxNf0/zkbvpTNXnYyyrIYHwtuKUDfp1/K/YVebvLJ3T7+tE/a50uEEiL9o4FOsrPBcEzgRicfb/9hzKjCEpPUczrHZ+sABY6+ag1oQXx9vmgLJ4nHE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374542; c=relaxed/simple; bh=CVDQ1Ecq32mkVTv2WTPthkWQ3lAZURlPO2+YdOHSRFM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XNK2SPohb5BeF40yVNbeogIrDfyEsSHkFQGaKtWGbycp8GGFqyHXsetWvCVnFLdktb/LV0TCk687HxMYUrHzMhkCDcHn1NYHT2ewdEn3RM3mAPIlF4mDzQQUCPHOnAMOg20RyWMSPFEzWdiPtmjZb7UNtD5jpAZs1rYMrloYaIo= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=cBROGUpz; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="cBROGUpz" 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 meesny.iki.fi (Postfix) with ESMTPSA id 4Zr8YZ1rCLzyfh; Sun, 4 May 2025 19:02:10 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374530; 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=msJ5a0oYaJ/s3qvajVISY/Q6bQeFQhIlLqczm9Yoj+A=; b=cBROGUpzfJ/1JV7X/D3ioCfQIO7ZYv38GL6hcNtOOi5Ys0tHtVehgS+JHJHsXaqmlm0S+W uAfteIKt1IpjBhEHdscEeu8tZPPFSaFiJAbyHW/7dcunQIZW5zUGx5/Kau7oqZgsRXOV7k tstU9E8SEM596m9wOGSOkRum6uOaC0g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374530; 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=msJ5a0oYaJ/s3qvajVISY/Q6bQeFQhIlLqczm9Yoj+A=; b=YFLBepgOlRJ4haCzgpLdPLgN0coHZanvvNKZNQIB3xmAj7FTdsKRN7VVtJvoJFIy156qfE t0eoP1oCFbylqF/pUSYARa49hQm3rmPPK+hfljI8ZBHE4kiwWtXWzRJch4b7VPBcRF47wg uGom5p7J82uIlArjlja6pWUN6SfURA8= ARC-Seal: i=1; s=meesny; d=iki.fi; t=1746374530; a=rsa-sha256; cv=none; b=vt8OBXwovLWEO3I8aSw9RMneimIAG/tgV3Gdr3/EnFRH2xTnCwfvvQPEGVgWBIL6EafQz/ k4k8OZ0U/G0+nTTZPmRd5xpzolrXFzui1y7PfLvyGiP7eni403gg6PNulxBzEtYFr6xQHp m80vY2+jPrTE019/2aSTh+U4xvdpzIo= 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: [RFC PATCH BlueZ v2 02/11] org.bluez.MediaEndpoint: add client role Reconfigure Date: Sun, 4 May 2025 19:01:54 +0300 Message-ID: X-Mailer: git-send-email 2.49.0 In-Reply-To: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> References: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add a simple way for the sound server to reconfigure a BAP unicast endpoint, by calling org.bluez.MediaEndpoint.Reconfigure(). This shall destroy all streams of the endpoint, and restart the SelectProperties() configuration flow from the beginning. Since it may be necessary to reconfigure multiple endpoints at once to correctly make bidirectional CIS, add Defer argument to just mark eps for configuration. In future, org.bluez.MediaEndpoint.SetConfiguration() could be changed to handle unicast in the same way as broadcast: only create streams. This allows sound server to have full control over stream configuration itself, and not rely on bt_bap_select(). --- doc/org.bluez.MediaEndpoint.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/org.bluez.MediaEndpoint.rst b/doc/org.bluez.MediaEndpoint.rst index b81106f0b..ea555a7d3 100644 --- a/doc/org.bluez.MediaEndpoint.rst +++ b/doc/org.bluez.MediaEndpoint.rst @@ -115,6 +115,28 @@ void ClearConfiguration(object transport) path given is the path of this endpoint, all its streams are closed. +void Reconfigure(dict properties) +````````````````````````````````` + + [ISO only] + + Reconfigure a BAP unicast endpoint. This closes all existing + streams of the endpoint, and restarts the configuration + selection flow which e.g. triggers calls to *SelectProperties* + allowing the sound server to modify the configuration. + + The following arguments are taken in *properties*: + + :boolean Defer [optional]: + + If True, mark endpoint for reconfiguration, but + postpone it until a non-deferred *Reconfigure()* + operation is made on an endpoint of the same device. + + This is necessary to use when reconfiguring source and + sink streams with the intention that they be combined + into the same CIG, possibly forming bidirectional CIS. + void Release() `````````````` From patchwork Sun May 4 16:01:55 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 887613 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 016C81A8412 for ; Sun, 4 May 2025 16:02:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374540; cv=pass; b=mnoY0aJ3JI+qGsykHZAyV/VkGCYbS+XREaJGcomFYcZg/RwY/MI7FpOmRK4h0svErKkyf5KdARUH11dgGSEfUqlym/GBt4wUmBPAvpJ18gCbd0VRgePFMVfVuYOLIWHFu4hzldHqt6Rlnqh/vEsXyPiIXrjPDShOGPMKyDEmS8w= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374540; c=relaxed/simple; bh=hcp94CFS3/8Y26XHqPdYir6yRbyHVLuaUd0ntDZZuHo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=e9oKu6lL9R72D2ghi51BktcIQar2hTPamoKJZJsbLySx20c9tQldWiyfDk9iQVPWdstSVOataVPzfsBMCgn/Zd56qplsvEfKc2WDUAz+0tkOvY5Msz91KO0YNlAlsjuPvuPr5gpKyw6NbZqgMHuvqpuor455uZ7KKUQ5GC1rZpE= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=pURK+tuJ; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="pURK+tuJ" 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 meesny.iki.fi (Postfix) with ESMTPSA id 4Zr8YZ4GhZzyhM; Sun, 4 May 2025 19:02:10 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374530; 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=C19BSes2JmticcW4n62vIpebJ0mXQTimRvohvx3fSkY=; b=pURK+tuJq3UrKsZ5VpgPLbVn7GZvyAKlo9wOLd1YCs9YgMCLvXqHnIIcZbaK/sQ6EZB3Ep ogZciKGH1DJLv1wHFWtsg9alqY1kGOikwJMLgWicg1Yvwr8069WJUSIqIkU33AFA/EC7LR Y2EZJpL/yJMIiFxlSriQQPLg54FO6lk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374530; 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=C19BSes2JmticcW4n62vIpebJ0mXQTimRvohvx3fSkY=; b=Q98m2IAp5Y76OxycX3iZgFMczrKwSlMljvQAZr80DFSz50nDKVl316WVWu+mZJmxcAFh4W 7NZyLA71UeZqFG9bJIqwu8O2xex2NrMuxja4mz1sZcGTLIndhQHDMVnneBC3BJC2F5Xucj 28w7HQZSvMV0Nl7veWfCFmGCWLRB9Ok= ARC-Seal: i=1; s=meesny; d=iki.fi; t=1746374530; a=rsa-sha256; cv=none; b=IaTfLoC71E4aj8yoNtyq7u0CCTzl+Gu02ZOeokQnDYE4P4aeuu973x4OWHQ8WAR4nFFc3E qWvHfRlXJ+EJVzAKacXxc4QbF7oqWShoD+ktyWRUJF3CCErukmziuu6E0DEAbHdl4W8DAo rxM8I2Wmfs5Cj6AAdcOrwg2Roa5GYpk= 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: [RFC PATCH BlueZ v2 03/11] shared/bap: bap_abort_stream_req() should cancel also current req Date: Sun, 4 May 2025 19:01:55 +0300 Message-ID: <4c8142e02e4b63d181e05baf7f0e849ec9a19b90.1746374514.git.pav@iki.fi> X-Mailer: git-send-email 2.49.0 In-Reply-To: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> References: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 After bap_abort_stream_req() no req callbacks for stream shall be called, so it has to fail also the currently in-flight request. --- src/shared/bap.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/shared/bap.c b/src/shared/bap.c index 2a08f3eea..976e3c0b1 100644 --- a/src/shared/bap.c +++ b/src/shared/bap.c @@ -1298,6 +1298,13 @@ static void bap_abort_stream_req(struct bt_bap *bap, struct bt_bap_stream *stream) { queue_remove_all(bap->reqs, match_req_stream, stream, bap_req_abort); + + if (bap->req && bap->req->stream == stream) { + struct bt_bap_req *req = bap->req; + + bap->req = NULL; + bap_req_complete(req, NULL); + } } static void bt_bap_stream_unref(void *data) From patchwork Sun May 4 16:01:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 887241 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0167319E98A for ; Sun, 4 May 2025 16:02:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374541; cv=pass; b=tMFXDuWHE6TdsQ62+eMuZJ0uJQZ0FxngIykrW1XwowEl0JnBRfw8P5fcLLRBMl7SwmVhWYi9Xyw+9933+NoHGSUw1bHLAeGR9t81AOl2M3o9Jt6+ZY/TidliR7tuPW6y/zvBD4rN7XPeLdEoLlP0L5lpCMqwbLRXf2NvGyRG7yQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374541; c=relaxed/simple; bh=ZFgLKB+yGNvsbEoUL9e9E+4HVLNg2ks77/v8bzNS5cg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ViE/m6lqBNAaVYD7pieIYmI2mgQkXWJwYmjaAP5KCluTrCJMtlEa7ANI9KH1OCCtidT10BWP+K2DJ1/9efM6S2vRXm3g/z60YS0yWpW/j8oactlY2aXTYzsq+FOaJyZ/KEqE6QQrJVHsdySAtS3n8n/dx0EJiTkww2Weh81/ZIM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=qv/qYKLW; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="qv/qYKLW" 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 meesny.iki.fi (Postfix) with ESMTPSA id 4Zr8YZ6yJlzyhZ; Sun, 4 May 2025 19:02:10 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374531; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rv5HovNWEEmO/z125kMRxUFsKXAiN1VGj2tceppLErw=; b=qv/qYKLWBioCzVJJ3hCGWG6C1sz8yBAoqV67tiI5fekGUb9IkwU3UO11erO6oUtX5EjKlD yLRQwPTcKzTKlOw16bmxoo3CRG4dbCSGG8ZICOgivqHdh0q4cM4sKwUDEiGJDEqK0QJT+w swuxaF2+H2GvQrDiSPbfW9aSIu0bErc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374531; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rv5HovNWEEmO/z125kMRxUFsKXAiN1VGj2tceppLErw=; b=L3uXCZ6jZeGxKBVSP8YZ2/jPkWm89P8nfbGuxBqcZmHuwIThSGzw9x0/4Mh/5DWFmqY1Cq B1U2SIstf8VTg8IOpTRuu14LTSg7q9TWzwFHHtxkwJrFR8jlAt/8ZeMXJEwn6SL1FMJtBc puWWoYjoSuqMTBe33brGkGwV6DefZs0= ARC-Seal: i=1; s=meesny; d=iki.fi; t=1746374531; a=rsa-sha256; cv=none; b=xUcw5ZeTcJiXT02kdLew/DFHWH7lYaIy5U1xE/+G4cyDbI+jFi6oB5pxVrsr8Xx8jg9tQL erCM3exod7nRPiglGCrBbrUz5Q4dgc/FNoB0oTy4fcfuy9LekxhsELIn3QdT8pEzwzBTCv ixA13EmRvvB+3NIqAinrFu7CzCP7jCk= 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: [RFC PATCH BlueZ v2 04/11] shared/bap: fix ucast client ASE usage Date: Sun, 4 May 2025 19:01:56 +0300 Message-ID: <52645e73ab0c6f12d2a29b17259222417cf81a93.1746374514.git.pav@iki.fi> X-Mailer: git-send-email 2.49.0 In-Reply-To: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> References: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The ucast client stream design has issues: * Assuming lpac & rpac pair uniquely identifies a stream. False for AC6(i) and other multi-stream configs. * No way for ASE in Config state be configured with different codec. * Assuming ASE enters idle state at end of stream life cycle. False for some devices like Sony headsets, which always cache codec config so RELEASING -> CONFIG always, never RELEASING -> IDLE, so ASE never go IDLE again. * Assuming Unicast Client upper layer always creates streams for all non-idle ASEs. False, as when switching between duplex & sink-only modes, only some streams shall be used regardless of whether Server is caching config or not. In practice, these currently prevent reconfiguring ASEs on devices which cache codec config, and multi-stream configs work only accidentally (and fail if server does Config codec itself, like some devices do). Minimally fixed design for Unicast Client streams: Streams correspond 1-to-1 to ASEs in non-IDLE state. Track explicitly which streams upper level is using: - bt_bap_stream_new() always makes new stream with client_active=true - bt_bap_stream_discard() releases stream and marks client_active=false Streams (ASEs) with no active client may be reused when upper level asks for a new stream. Streams with no active client may have their lpac changed. The need_reconfig state is a bit ugly, but not really avoidable. Streams with no active client shall be ignored when constructing bidirectional CIS pairs. Streams shall clear transport and detach io on RELEASING. (cf BAP v1.0.2 ยง5.6.6). Also unlink them since QoS is gone at that point. Streams shall have transport only for >= QOS state. (Server streams work differently, which makes sense since upper level cannot acquire them before they are pending.) --- src/shared/bap.c | 170 +++++++++++++++++++++++++++++++++-------------- src/shared/bap.h | 2 + 2 files changed, 123 insertions(+), 49 deletions(-) diff --git a/src/shared/bap.c b/src/shared/bap.c index 976e3c0b1..456450d40 100644 --- a/src/shared/bap.c +++ b/src/shared/bap.c @@ -296,6 +296,8 @@ struct bt_bap_stream { struct queue *pending_states; bool no_cache_config; bool client; + bool client_active; + bool need_reconfig; void *user_data; }; @@ -1488,6 +1490,13 @@ static void bap_stream_state_changed(struct bt_bap_stream *stream) if (stream->client) bt_bap_stream_stop(stream, stream_stop_complete, NULL); break; + case BT_ASCS_ASE_STATE_RELEASING: + if (stream->client) { + bap_stream_clear_cfm(stream); + bap_stream_io_detach(stream); + bt_bap_stream_io_unlink(stream, NULL); + } + break; } } @@ -1898,6 +1907,9 @@ static unsigned int bap_ucast_qos(struct bt_bap_stream *stream, if (!stream->client) return 0; + if (stream->need_reconfig) + return 0; + memset(&qos, 0, sizeof(qos)); /* TODO: Figure out how to pass these values around */ @@ -2300,7 +2312,6 @@ static unsigned int bap_ucast_release(struct bt_bap_stream *stream, /* If stream does not belong to a client session, clean it up now */ if (!bap_stream_valid(stream)) { stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE); - stream = NULL; return 0; } @@ -2583,6 +2594,9 @@ static int bap_ucast_io_link(struct bt_bap_stream *stream, stream->ep->dir == link->ep->dir) return -EINVAL; + if (stream->client && !(stream->client_active && link->client_active)) + return -EINVAL; + if (!stream->links) stream->links = queue_new(); @@ -2603,6 +2617,30 @@ static int bap_ucast_io_link(struct bt_bap_stream *stream, return 0; } +static void stream_unlink_ucast(void *data) +{ + struct bt_bap_stream *link = data; + + DBG(link->bap, "stream %p unlink", link); + + queue_destroy(link->links, NULL); + link->links = NULL; +} + +static int bap_ucast_io_unlink(struct bt_bap_stream *stream, + struct bt_bap_stream *link) +{ + if (!stream) + return -EINVAL; + + queue_destroy(stream->links, stream_unlink_ucast); + stream->links = NULL; + + DBG(stream->bap, "stream %p unlink", stream); + return 0; + +} + static void stream_link(void *data, void *user_data) { struct bt_bap_stream *stream = (void *)data; @@ -2708,7 +2746,7 @@ static const struct bt_bap_stream_ops stream_ops[] = { bap_ucast_release, bap_ucast_detach, bap_ucast_set_io, bap_ucast_get_io, bap_ucast_io_dir, bap_ucast_io_link, - NULL), + bap_ucast_io_unlink), STREAM_OPS(BT_BAP_SOURCE, bap_ucast_set_state, bap_ucast_get_state, bap_ucast_config, bap_ucast_qos, bap_ucast_enable, @@ -2718,7 +2756,7 @@ static const struct bt_bap_stream_ops stream_ops[] = { bap_ucast_release, bap_ucast_detach, bap_ucast_set_io, bap_ucast_get_io, bap_ucast_io_dir, bap_ucast_io_link, - NULL), + bap_ucast_io_unlink), STREAM_OPS(BT_BAP_BCAST_SINK, bap_bcast_set_state, bap_bcast_get_state, bap_bcast_config, bap_bcast_qos, bap_bcast_sink_enable, @@ -5015,6 +5053,8 @@ static void ep_status_config(struct bt_bap *bap, struct bt_bap_endpoint *ep, ep->stream->cc = new0(struct iovec, 1); util_iov_memcpy(ep->stream->cc, cfg->cc, cfg->cc_len); + + ep->stream->need_reconfig = false; } static void bap_stream_config_cfm_cb(struct bt_bap_stream *stream, int err) @@ -5922,43 +5962,6 @@ bool bt_bap_pac_bcast_is_local(struct bt_bap *bap, struct bt_bap_pac *pac) return false; } -static bool find_ep_unused(const void *data, const void *user_data) -{ - const struct bt_bap_endpoint *ep = data; - const struct match_pac *match = user_data; - - if (ep->stream) - return false; - - if (match->rpac) - return ep->dir == match->rpac->type; - else - return true; -} - -static bool find_ep_pacs(const void *data, const void *user_data) -{ - const struct bt_bap_endpoint *ep = data; - const struct match_pac *match = user_data; - - if (!ep->stream) - return false; - - if (ep->stream->lpac != match->lpac) - return false; - - if (ep->stream->rpac != match->rpac) - return false; - - switch (ep->state) { - case BT_BAP_STREAM_STATE_CONFIG: - case BT_BAP_STREAM_STATE_QOS: - return true; - } - - return false; -} - static bool find_ep_source(const void *data, const void *user_data) { const struct bt_bap_endpoint *ep = data; @@ -6136,6 +6139,48 @@ static struct bt_bap_stream *bap_bcast_stream_new(struct bt_bap *bap, return stream; } +static bool find_ep_ucast(const void *data, const void *user_data) +{ + const struct bt_bap_endpoint *ep = data; + const struct match_pac *match = user_data; + + if (ep->stream) { + if (!ep->stream->client) + return false; + if (ep->stream->client_active) + return false; + if (!queue_isempty(ep->stream->pending_states)) + return false; + + switch (ep->stream->state) { + case BT_BAP_STREAM_STATE_IDLE: + case BT_BAP_STREAM_STATE_CONFIG: + case BT_BAP_STREAM_STATE_QOS: + break; + default: + return false; + } + } + + if (ep->dir != match->rpac->type) + return false; + + switch (match->lpac->type) { + case BT_BAP_SOURCE: + if (ep->dir != BT_BAP_SINK) + return false; + break; + case BT_BAP_SINK: + if (ep->dir != BT_BAP_SOURCE) + return false; + break; + default: + return false; + } + + return true; +} + static struct bt_bap_stream *bap_ucast_stream_new(struct bt_bap *bap, struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, @@ -6153,21 +6198,28 @@ static struct bt_bap_stream *bap_ucast_stream_new(struct bt_bap *bap, match.lpac = lpac; match.rpac = rpac; - /* Check for existing stream */ - ep = queue_find(bap->remote_eps, find_ep_pacs, &match); + /* Get free ASE */ + ep = queue_find(bap->remote_eps, find_ep_ucast, &match); if (!ep) { - /* Check for unused ASE */ - ep = queue_find(bap->remote_eps, find_ep_unused, &match); - if (!ep) { - DBG(bap, "Unable to find unused ASE"); - return NULL; - } + DBG(bap, "Unable to find usable ASE"); + return NULL; } stream = ep->stream; - if (!stream) + if (stream) { + /* Replace lpac: the stream generally needs to be reconfigured + * after this, otherwise things like codec config not match. + */ + bap_stream_clear_cfm(stream); + stream->lpac = lpac; + util_iov_free(stream->cc, 1); + stream->cc = util_iov_dup(data, 1); + stream->need_reconfig = true; + } else { stream = bap_stream_new(bap, ep, lpac, rpac, data, true); + } + stream->client_active = true; return stream; } @@ -6187,6 +6239,26 @@ struct bt_bap_stream *bt_bap_stream_new(struct bt_bap *bap, return bap_bcast_stream_new(bap, lpac, pqos, data); } +void bt_bap_stream_discard(struct bt_bap_stream *stream) +{ + if (!stream || !stream->client) + return; + + stream->client_active = false; + + switch (stream->ep->state) { + case BT_BAP_STREAM_STATE_IDLE: + case BT_BAP_STREAM_STATE_RELEASING: + break; + case BT_BAP_STREAM_STATE_CONFIG: + if (stream->ep->old_state == BT_BAP_STREAM_STATE_RELEASING) + break; + /* Fallthrough */ + default: + bt_bap_stream_release(stream, NULL, NULL); + } +} + struct bt_bap *bt_bap_stream_get_session(struct bt_bap_stream *stream) { if (!stream) diff --git a/src/shared/bap.h b/src/shared/bap.h index d10581428..5949eb4b1 100644 --- a/src/shared/bap.h +++ b/src/shared/bap.h @@ -183,6 +183,8 @@ struct bt_bap_stream *bt_bap_stream_new(struct bt_bap *bap, struct bt_bap_qos *pqos, struct iovec *data); +void bt_bap_stream_discard(struct bt_bap_stream *stream); + struct bt_bap *bt_bap_stream_get_session(struct bt_bap_stream *stream); uint8_t bt_bap_stream_get_state(struct bt_bap_stream *stream); From patchwork Sun May 4 16:01:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 887612 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D147D746E for ; Sun, 4 May 2025 16:02:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374541; cv=pass; b=sJ9Y8lO5klMBU88GHPvN7BzTQRWGIknTojgsdpzMtlqq7yM9VKjejv+7k4nTMNrIzKZzVPna5LVz2qxmPaqPDrelskiOEzT59LJg3LdU9ILDljMN/eD5uEvPvrl7JPTZNiAD0j9lBRWpEwzN2N+lhGXuC5wqGPHgzg4y8/1S71g= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374541; c=relaxed/simple; bh=q/k+32eQUkfF07uADCynUv8GmMxyXNjW+VfHrKMBBSk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fxt0O5DKsDdBmH72Gxmd4sUOJJ1w2iKM89PNjqck7Gk2+XMZExcfsxsEYEI07FSieHjMiDd39jlfLh7EgqEQX0eA2sCQTyHLKif7Li2IF3w+ltIPTdEI0AElBehjVvLtVBOd5eI745RKElsLgIiFfdh8Zi1tPeYo6GGW4SksddA= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=JiaUBpoU; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="JiaUBpoU" 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 meesny.iki.fi (Postfix) with ESMTPSA id 4Zr8Yb2Vz0zyjW; Sun, 4 May 2025 19:02:11 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374531; 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=LsaaOy6w49amGE3uN/ijiZWFt0jKsYuBNPhXmkFGlGs=; b=JiaUBpoUsNAxsmPp7CHAuki/PqfqyooQIlh5l+09xX30TtNOAVJex+cQzEB8HJpQiJnLTG 6KA7Wv8nS2A/l4VZ9biZnbJ9PBf04J1QzD3qj/FcXh/O8x633zNVKrCjrSHZPhyIzaMD5B hcU0j9FW99j/QOr9mA2vQQKM0EuRdWc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374531; 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=LsaaOy6w49amGE3uN/ijiZWFt0jKsYuBNPhXmkFGlGs=; b=y84uihwDzPlPrXRGslWj8o3vBt5dbl4Abn6dai6tjyakmN223hwc6r/wAMfeEamMsalipZ +mXM1al1mXYJiLUUieNG4znY410ul2WwgcVIqGo6aDYN2gx77BrneZhJMO6iIg7Le9BZaN QXl/ns1WbrYyvwvb7KzN6S2yhJ0NY7I= ARC-Seal: i=1; s=meesny; d=iki.fi; t=1746374531; a=rsa-sha256; cv=none; b=l60aVquznkW6HIF56rmGiT53wiTHZoRpdGTYCT7093IcUTpa7vA4tIM+4njnDu/I4OZ8P9 FvaOSpAhlXRBlmlo1LL+JGijkguATqjoaXXNtTrOsWq+EEpcHrj6wGyek73OsmKPKSJ6W/ 64jSoQBj/TvLpCqrKOW9YC6y4+0h1mc= 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: [RFC PATCH BlueZ v2 05/11] bap: discard stream when no longer in use Date: Sun, 4 May 2025 19:01:57 +0300 Message-ID: <52aedc2746a92078b74c06899ab6d82dd509d14d.1746374514.git.pav@iki.fi> X-Mailer: git-send-email 2.49.0 In-Reply-To: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> References: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Indicate to lower layer that the stream will not be used any more. --- profiles/audio/bap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index ee7c8bc49..dcef98148 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -860,6 +860,8 @@ static void setup_free(void *data) if (setup->destroy) setup->destroy(setup); + bt_bap_stream_discard(setup->stream); + free(setup); } From patchwork Sun May 4 16:01:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 887611 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A32661DE4CA for ; Sun, 4 May 2025 16:02:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374543; cv=pass; b=Wd7FNnBoV1TKMAId2b67JUs9wOvESkjAg/kHddQL+1QxxUBkDYWADciWt5zJ8PNdML5fmdcEwo12mZovIGkcNob1bcsUyek3uLdJXr4l66xdf9lYy7rzhluE/KPvTXGM9jNtBhXlG/A2JareMMb3HtVlkDRyzORizgQ3HTlDc6c= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374543; c=relaxed/simple; bh=ImCUGNYSigWSXsLnybzruU6uBY2ULonkAGOC2F/XR+o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CtoBBk7Z06IFNHDu6576m4HkvXCpvlE9E2k2Fw2t3YuKBsv85IJu9xBBXYm0JglKYolO68CYleG26Ww98FOanYl4KdpkHrbBKmpTj2mg4SgKtbDa/mWnxHFj73qijcaRQNcBBWKRFWvQk8/11yIaSzfoSg/H04npFNSeiHVuF1Y= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=IxParE8f; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="IxParE8f" 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 meesny.iki.fi (Postfix) with ESMTPSA id 4Zr8Yc0pVSz109d; Sun, 4 May 2025 19:02:12 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374532; 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=e+vaWcprgXsakvH71ixpQA+PrGwhO4jcBa7JNlxmpH0=; b=IxParE8fyKvfHEVUn7phang53WmMRCdylCXLclRHQEdD4AqGRsQwKoV9Li3xFvaYId1X/O 6m4Q0t05xWGuAWIShLdSW49kOJIIF8j370orzv826HZhxjxXTNhzTvf8OG9hdzPHSVrjGw ZJY44im2E241szIW4mu5CxP0QI67te0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374532; 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=e+vaWcprgXsakvH71ixpQA+PrGwhO4jcBa7JNlxmpH0=; b=HRUm/tdKWYrld2Br2Q7fBWaYPVjZF8iKqTHmeNU0PjJEryTa7HumSVmNkpzVr9hx+BOpof teSqBtBBZ4meOdUxo7lQoNpvJ5lJLfG4kr/I8Gj92AIkv/t+FUsOXIbeZx2Ya9UYwN/Cmt 8pSpIawRb0ohurXRdtceexeono2pBhs= ARC-Seal: i=1; s=meesny; d=iki.fi; t=1746374532; a=rsa-sha256; cv=none; b=JgbkVNKexv11JmX9KlHVoKfJFhc5+5TI5lD6xJV1Pm41+r3aGJEfgeBFwNcAwE7YQOcjac yLG36PXpLJNZ6xJ8qqP1+aAiR1wmyPjl68i8itzTgharuwwzHddXi7IX2bHVnhVbv3UGUD +b7PofrUk5AKW6U/gDWCq2ogPymYdoc= 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: [RFC PATCH BlueZ v2 06/11] bap: do not try QoS before links are updated & io created Date: Sun, 4 May 2025 19:01:58 +0300 Message-ID: <3c011d53782206ba0f8f6e7434166df46525d5a7.1746374514.git.pav@iki.fi> X-Mailer: git-send-email 2.49.0 In-Reply-To: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> References: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In setup config, QoS must be done after corresponding bap_state callback, because stream links are updated only at that point. If the ASE was in CONFIG state before reconfiguration, this gets done in wrong order. Track explicitly that bap_state() is done after bt_bap_stream_config(), before proceeding to QoS. --- profiles/audio/bap.c | 82 ++++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index dcef98148..9b3bd405f 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -75,6 +75,7 @@ struct bap_setup { bool recreate; bool cig_active; uint8_t sid; + bool config_pending; struct iovec *caps; struct iovec *metadata; unsigned int id; @@ -720,6 +721,46 @@ static void qos_cb(struct bt_bap_stream *stream, uint8_t code, uint8_t reason, setup->msg = NULL; } +static void setup_create_io(struct bap_data *data, struct bap_setup *setup, + struct bt_bap_stream *stream, int defer); + +static int setup_qos(struct bap_setup *setup) +{ + struct bap_data *data = setup->ep->data; + struct bt_bap_stream *stream = setup->stream; + + if (!stream) + return -EINVAL; + if (bt_bap_stream_get_state(stream) != BT_BAP_STREAM_STATE_CONFIG) + goto error; + if (setup->id) + goto error; + + setup_create_io(data, setup, stream, true); + if (!setup->io) { + error("Unable to create io"); + goto error; + } + + /* Wait QoS response to respond */ + setup->id = bt_bap_stream_qos(stream, &setup->qos, qos_cb, setup); + if (!setup->id) { + error("Failed to Configure QoS"); + goto error; + } + + /* Bcast does not call the callback */ + if (bt_bap_stream_get_type(setup->stream) == BT_BAP_STREAM_TYPE_BCAST) + setup->id = 0; + + return 0; + +error: + if (bt_bap_stream_get_state(stream) != BT_BAP_STREAM_STATE_RELEASING) + bt_bap_stream_release(stream, NULL, NULL); + return -EIO; +} + static void config_cb(struct bt_bap_stream *stream, uint8_t code, uint8_t reason, void *user_data) @@ -732,17 +773,8 @@ static void config_cb(struct bt_bap_stream *stream, setup->id = 0; if (!code) { - /* Check state is already set to config then proceed to qos */ - if (bt_bap_stream_get_state(stream) == - BT_BAP_STREAM_STATE_CONFIG) { - setup->id = bt_bap_stream_qos(stream, &setup->qos, - qos_cb, setup); - if (!setup->id) { - error("Failed to Configure QoS"); - bt_bap_stream_release(stream, NULL, NULL); - } - } - + if (!setup->config_pending) + setup_qos(setup); return; } @@ -986,6 +1018,7 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg, setup->stream = bt_bap_stream_new(ep->data->bap, ep->lpac, ep->rpac, &setup->qos, setup->caps); bt_bap_stream_set_user_data(setup->stream, ep->path); + setup->config_pending = true; setup->id = bt_bap_stream_config(setup->stream, &setup->qos, setup->caps, config_cb, setup); if (!setup->id) { @@ -1005,6 +1038,7 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg, case BT_BAP_STREAM_TYPE_BCAST: /* No message sent over the air for broadcast */ setup->id = 0; + setup->config_pending = false; if (ep->data->service) service_set_connecting(ep->data->service); @@ -1403,6 +1437,7 @@ static void setup_config(void *data, void *user_data) ep->rpac, &setup->qos, setup->caps); + setup->config_pending = true; setup->id = bt_bap_stream_config(setup->stream, &setup->qos, setup->caps, config_cb, setup); if (!setup->id) { @@ -1807,9 +1842,6 @@ static bool is_cig_busy(struct bap_data *data, uint8_t cig) return queue_find(sessions, cig_busy_session, &info); } -static void setup_create_io(struct bap_data *data, struct bap_setup *setup, - struct bt_bap_stream *stream, int defer); - static gboolean setup_io_recreate(void *user_data) { struct bap_setup *setup = user_data; @@ -2189,25 +2221,9 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state, queue_remove(data->server_streams, stream); break; case BT_BAP_STREAM_STATE_CONFIG: - if (setup && !setup->id) { - setup_create_io(data, setup, stream, true); - if (!setup->io) { - error("Unable to create io"); - if (old_state != BT_BAP_STREAM_STATE_RELEASING) - bt_bap_stream_release(stream, NULL, - NULL); - return; - } - - /* Wait QoS response to respond */ - setup->id = bt_bap_stream_qos(stream, - &setup->qos, - qos_cb, setup); - if (!setup->id) { - error("Failed to Configure QoS"); - bt_bap_stream_release(stream, - NULL, NULL); - } + if (setup) { + setup->config_pending = false; + setup_qos(setup); } break; case BT_BAP_STREAM_STATE_QOS: From patchwork Sun May 4 16:01:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 887239 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A320A1DE4C3 for ; Sun, 4 May 2025 16:02:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374543; cv=pass; b=jAL7c2hK37ueMPHZ2dS8MT/sB1ocPr+8KnNbEo/MtdqIL4VPGYqtLNjGqTQBsWhEu9lsn5wmVSeDVKLH3+KFOk1XveWJqdlw9LoAj1M6RDqiixL/TN6lZDl05VEliy8xYmP5PAvOcX2Ar7wwaRQEMrRR3BlLlAtf4sqpXZ1Apes= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374543; c=relaxed/simple; bh=QvvS8q98VXG7s65wbCS5q/NtvsC/L66+sEXrKrH+bMY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jS8io/p3FlUT2S5rjtX1B890q8FidP5su4gVfjw1UM9HrFADhRryQxIWHSt46OLY1l9xNy0yVxxC9GtzCGNPy54PD6IhRlmCld7uHOemzqtj/3XUfk0Y3RgVCwiqWfZbnsJDefXt8OHGwaIjQ/31jPXFKwl2AwUQMQQKK+gBd/E= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=q+5J2V2e; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="q+5J2V2e" 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 meesny.iki.fi (Postfix) with ESMTPSA id 4Zr8Yd2K8HzyhK; Sun, 4 May 2025 19:02:13 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374533; 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=1bssVK4Ujy1bynopl6RC4C98wlF4R/1WwZP8kRyJLpk=; b=q+5J2V2eS3lLQP8GlBgUvALIxixHQcxACUqXwP+/pfO4MK20qT4K1ZedFOaQv7/0E9tIS/ Ra+YRZ/EsFRRtAZAfafZlmslGeNbKYX3eqWqAG54xqbnV+54RL/N5zlBgEnaNP+689IgR9 AAU+CKQL2AeGAiru38TInO+rCbrwdIg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374533; 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=1bssVK4Ujy1bynopl6RC4C98wlF4R/1WwZP8kRyJLpk=; b=YT8BXX34KLKEMoqQYOxCqU7Zfr3NtpVVS0NhHKoxMovbIUYRAwRR9jCc3Ot+tZdd+Ft9EZ 4Sm9CBv9lcIeYIIPvUUPNY0AgsOBOm805CJ2wGAbZXlevNUGIsv6fwYVkBlpoTq90QLgWu Vq4nsrzWr9LFKcS3JNiWa1PataOkwIg= ARC-Seal: i=1; s=meesny; d=iki.fi; t=1746374533; a=rsa-sha256; cv=none; b=dPrUWs62oe7g955aK5Ox5ueC3HqhNLTCHm9dCXo+z/j8TzJNi1+eEQqS9k+7jcGFsDwF0I LQ6wJXWTvS/nZTblF3T0Cr3zcBF0YSKXAg/ZsQtP3rxKf/fKlXscZSCArmcQvNBZWPP6hZ 6eby24RV5NDHLvnqggIGQ7f9g0a9ktI= 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: [RFC PATCH BlueZ v2 07/11] bap: add ready callback for setup configuration Date: Sun, 4 May 2025 19:01:59 +0300 Message-ID: X-Mailer: git-send-email 2.49.0 In-Reply-To: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> References: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Operations like SetConfiguration need to wait until setup configuration finishes. Abstract this to a setup_config() callback emitted on QoS completion or failure, instead of hardcoding DBus reply. --- profiles/audio/bap.c | 176 +++++++++++++++++++++++++++---------------- 1 file changed, 110 insertions(+), 66 deletions(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index 9b3bd405f..64dee8f9d 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -63,6 +63,11 @@ #define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint1" #define MEDIA_INTERFACE "org.bluez.Media1" +struct bap_setup; + +typedef void (*bap_setup_ready_func_t)(struct bap_setup *setup, int code, + uint8_t reason, void *data); + struct bap_setup { struct bap_ep *ep; struct bap_data *data; @@ -80,7 +85,8 @@ struct bap_setup { struct iovec *metadata; unsigned int id; struct iovec *base; - DBusMessage *msg; + bap_setup_ready_func_t ready_cb; + void *ready_cb_data; void (*destroy)(struct bap_setup *setup); }; @@ -116,6 +122,10 @@ struct bap_data { static struct queue *sessions; +static int setup_config(struct bap_setup *setup, bap_setup_ready_func_t cb, + void *user_data); + + static bool bap_data_set_user_data(struct bap_data *data, void *user_data) { if (!data) @@ -697,28 +707,28 @@ fail: return -EINVAL; } +static void setup_ready(struct bap_setup *setup, int code, + uint8_t reason) +{ + if (!setup->ready_cb) + return; + + setup->ready_cb(setup, code, reason, setup->ready_cb_data); + setup->ready_cb = NULL; + setup->ready_cb_data = NULL; +} + static void qos_cb(struct bt_bap_stream *stream, uint8_t code, uint8_t reason, void *user_data) { struct bap_setup *setup = user_data; - DBusMessage *reply; DBG("stream %p code 0x%02x reason 0x%02x", stream, code, reason); setup->id = 0; - if (!setup->msg) - return; - - if (!code) - reply = dbus_message_new_method_return(setup->msg); - else - reply = btd_error_failed(setup->msg, "Unable to configure"); - - g_dbus_send_message(btd_get_dbus_connection(), reply); - - dbus_message_unref(setup->msg); - setup->msg = NULL; + if (code) + setup_ready(setup, code, reason); } static void setup_create_io(struct bap_data *data, struct bap_setup *setup, @@ -766,26 +776,19 @@ static void config_cb(struct bt_bap_stream *stream, void *user_data) { struct bap_setup *setup = user_data; - DBusMessage *reply; + int err = 0; DBG("stream %p code 0x%02x reason 0x%02x", stream, code, reason); setup->id = 0; - if (!code) { - if (!setup->config_pending) - setup_qos(setup); - return; - } + if (code) + err = code; + else if (!setup->config_pending) + err = setup_qos(setup); - if (!setup->msg) - return; - - reply = btd_error_failed(setup->msg, "Unable to configure"); - g_dbus_send_message(btd_get_dbus_connection(), reply); - - dbus_message_unref(setup->msg); - setup->msg = NULL; + if (err) + setup_ready(setup, err, reason); } static void setup_io_close(void *data, void *user_data) @@ -864,22 +867,16 @@ static struct bap_setup *setup_new(struct bap_ep *ep) static void setup_free(void *data) { struct bap_setup *setup = data; - DBusMessage *reply; DBG("%p", setup); + setup_ready(setup, -ECANCELED, 0); + if (setup->stream && setup->id) { bt_bap_stream_cancel(setup->stream, setup->id); setup->id = 0; } - if (setup->msg) { - reply = btd_error_failed(setup->msg, "Canceled"); - g_dbus_send_message(btd_get_dbus_connection(), reply); - dbus_message_unref(setup->msg); - setup->msg = NULL; - } - if (setup->ep) queue_remove(setup->ep->setups, setup); @@ -974,6 +971,34 @@ static bool setup_mismatch_qos(const void *data, const void *user_data) return !match_bcast_qos(&setup->qos.bcast, &match->qos.bcast); } +struct set_configuration_data { + struct bap_setup *setup; + DBusMessage *msg; +}; + +static void set_configuration_ready(struct bap_setup *setup, int code, + uint8_t reason, void *user_data) +{ + struct set_configuration_data *data = user_data; + DBusMessage *reply; + + if (!data->msg) { + free(data); + return; + } + + if (!code) + reply = dbus_message_new_method_return(data->msg); + else if (code == -ECANCELED) + reply = btd_error_failed(data->msg, "Canceled"); + else + reply = btd_error_failed(data->msg, "Unable to configure"); + + g_dbus_send_message(btd_get_dbus_connection(), reply); + dbus_message_unref(data->msg); + free(data); +} + static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -981,6 +1006,7 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg, struct bap_setup *setup; const char *path; DBusMessageIter args, props; + struct set_configuration_data *cbdata; dbus_message_iter_init(msg, &args); @@ -1015,35 +1041,22 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg, return btd_error_invalid_args(msg); } - setup->stream = bt_bap_stream_new(ep->data->bap, ep->lpac, ep->rpac, - &setup->qos, setup->caps); - bt_bap_stream_set_user_data(setup->stream, ep->path); - setup->config_pending = true; - setup->id = bt_bap_stream_config(setup->stream, &setup->qos, - setup->caps, config_cb, setup); - if (!setup->id) { + cbdata = new0(struct set_configuration_data, 1); + cbdata->setup = setup; + + if (setup_config(setup, set_configuration_ready, cbdata)) { DBG("Unable to config stream"); setup_free(setup); return btd_error_invalid_args(msg); } - if (setup->metadata && setup->metadata->iov_len) - bt_bap_stream_metadata(setup->stream, setup->metadata, NULL, - NULL); + cbdata->msg = dbus_message_ref(msg); switch (bt_bap_stream_get_type(setup->stream)) { - case BT_BAP_STREAM_TYPE_UCAST: - setup->msg = dbus_message_ref(msg); - break; case BT_BAP_STREAM_TYPE_BCAST: - /* No message sent over the air for broadcast */ - setup->id = 0; - setup->config_pending = false; - if (ep->data->service) service_set_connecting(ep->data->service); - - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + break; } return NULL; @@ -1421,11 +1434,17 @@ static struct bap_ep *ep_register(struct btd_service *service, return ep; } -static void setup_config(void *data, void *user_data) +static int setup_config(struct bap_setup *setup, bap_setup_ready_func_t cb, + void *user_data) { - struct bap_setup *setup = data; struct bap_ep *ep = setup->ep; + if (setup->ready_cb) + return -EBUSY; + + setup->ready_cb = cb; + setup->ready_cb_data = user_data; + DBG("setup %p caps %p metadata %p", setup, setup->caps, setup->metadata); @@ -1437,27 +1456,45 @@ static void setup_config(void *data, void *user_data) ep->rpac, &setup->qos, setup->caps); - setup->config_pending = true; + bt_bap_stream_set_user_data(setup->stream, ep->path); setup->id = bt_bap_stream_config(setup->stream, &setup->qos, setup->caps, config_cb, setup); - if (!setup->id) { - DBG("Unable to config stream"); - setup_free(setup); - return; + if (!setup->id) + return -EINVAL; + + switch (bt_bap_stream_get_type(setup->stream)) { + case BT_BAP_STREAM_TYPE_UCAST: + setup->config_pending = true; + break; + case BT_BAP_STREAM_TYPE_BCAST: + /* Broadcast does not call the callback */ + setup->id = 0; + break; } if (setup->metadata && setup->metadata->iov_len) bt_bap_stream_metadata(setup->stream, setup->metadata, NULL, NULL); - bt_bap_stream_set_user_data(setup->stream, ep->path); + return 0; +} + +static void bap_config_setup(void *data, void *user_data) +{ + struct bap_setup *setup = data; + + if (setup_config(setup, NULL, NULL)) { + DBG("Unable to config stream"); + setup_free(setup); + return; + } } static void bap_config(void *data, void *user_data) { struct bap_ep *ep = data; - queue_foreach(ep->setups, setup_config, NULL); + queue_foreach(ep->setups, bap_config_setup, NULL); } static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps, @@ -2223,11 +2260,18 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state, case BT_BAP_STREAM_STATE_CONFIG: if (setup) { setup->config_pending = false; - setup_qos(setup); + if (!setup->id) { + int err = setup_qos(setup); + + if (err) + setup_ready(setup, err, 0); + } } break; case BT_BAP_STREAM_STATE_QOS: - setup_create_io(data, setup, stream, true); + setup_create_io(data, setup, stream, true); + if (setup) + setup_ready(setup, 0, 0); break; case BT_BAP_STREAM_STATE_ENABLING: if (setup) From patchwork Sun May 4 16:02:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 887610 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D68C1DEFD6 for ; Sun, 4 May 2025 16:02:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374544; cv=pass; b=rurNZVjPJcVWS5F59P0hNb9nxAMIugMHA4S2x+CoEspnhzVaxZtKszNh2XoMyuP6wFWiztq7ZrsXNNUmRL9V17BSVL0oUqg8EHYkhIFlCtlMXPDCXkV31jQEqcGKGlUIer5AOUmIlgEb0Y6SDmcPAXj5vwxMUxs8KJTipc4wDIs= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374544; c=relaxed/simple; bh=ORsc7z4iaM78BNUqt32yk6J23LhXcoE5vyfgd8rM2f8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IBxfJGDZ/M7QEfZYNb1cfZS7WG2Zv40sxU5QxQC7OIqCYaZNkueP9gIfJdCO4uLpU+7smXuUVB4ciBWvcEuNNs3rQIsIg3FhUBlIasjOM43mXFeuMnRr0BdT8k/0XNCc04/cKb/p1XNufpbdieMlSEghzEStA4vOXSa2NP3PCc0= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=CIpwhXof; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="CIpwhXof" 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 meesny.iki.fi (Postfix) with ESMTPSA id 4Zr8Yf21Wczyjb; Sun, 4 May 2025 19:02:14 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374534; 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=x/K/c98BkTGAf5Tn7q5pM4PcRGNxc1xhLqLZmL4BSeU=; b=CIpwhXofuIay/fLNs7OnOS805f/lqILTWyMW4RJH3x/8ErMeoW5e94+TzO4MPlSd4OkC0P Fflt4eGiED2gFdu/YY0YS8XDc0XzLdD/LtXPIXR9Ssykuq4eHhTECn6mXQD38vnavPfatP Y7YGVNDOotYFjnmcNIdJpzmmigm5gZM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374534; 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=x/K/c98BkTGAf5Tn7q5pM4PcRGNxc1xhLqLZmL4BSeU=; b=n+ZcAlK+LNWMsu+vLkiRIIJ8YSwCOGJHy5f6Lh4kjkR7yr0MlljnBMaOXoNMzOhwX9+gyI vjSc6PzxO2xJurdgakHA5+UEDvG0kOAcz1atKGeivlnrnTIpuFVvAd0X7/WvUBzYAdXO2b 3HiawdBWHiZCwO69yzNbfXFthzJTbPY= ARC-Seal: i=1; s=meesny; d=iki.fi; t=1746374534; a=rsa-sha256; cv=none; b=qHKRCeHXSfqWRqxk06rYnyqezzlDj6RLOZ8CXq+bT/9XZ1/7ACCfjVuCCNrEsfXvPUYq7P pQNty8nQ0XWsvFskm5EfXvG8dCmrXtfRdwbiZ12fjl2PAA8O3qPaP95RmnWK33ha6MPAJ+ 6HeKRjzCpSge9WYN5sKdZ3az1SWg09Y= 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: [RFC PATCH BlueZ v2 08/11] bap: support removing streams with ClearConfiguration() Date: Sun, 4 May 2025 19:02:00 +0300 Message-ID: X-Mailer: git-send-email 2.49.0 In-Reply-To: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> References: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Implement removing streams via ClearConfiguration(). --- profiles/audio/bap.c | 154 +++++++++++++++++++++++++++++++++++-- profiles/audio/transport.c | 17 ++++ profiles/audio/transport.h | 1 + 3 files changed, 166 insertions(+), 6 deletions(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index 64dee8f9d..c9755ad96 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -57,6 +57,8 @@ #include "src/log.h" #include "src/error.h" +#include "transport.h" + #define ISO_SOCKET_UUID "6fbaf188-05e0-496a-9885-d6ddfdb4e03e" #define PACS_UUID_STR "00001850-0000-1000-8000-00805f9b34fb" #define BCAAS_UUID_STR "00001852-0000-1000-8000-00805f9b34fb" @@ -67,6 +69,7 @@ struct bap_setup; typedef void (*bap_setup_ready_func_t)(struct bap_setup *setup, int code, uint8_t reason, void *data); +typedef void (*bap_setup_close_func_t)(struct bap_setup *setup, void *data); struct bap_setup { struct bap_ep *ep; @@ -81,12 +84,15 @@ struct bap_setup { bool cig_active; uint8_t sid; bool config_pending; + bool closing; struct iovec *caps; struct iovec *metadata; unsigned int id; struct iovec *base; bap_setup_ready_func_t ready_cb; void *ready_cb_data; + bap_setup_close_func_t close_cb; + void *close_cb_data; void (*destroy)(struct bap_setup *setup); }; @@ -741,6 +747,8 @@ static int setup_qos(struct bap_setup *setup) if (!stream) return -EINVAL; + if (setup->closing) + return -EINVAL; if (bt_bap_stream_get_state(stream) != BT_BAP_STREAM_STATE_CONFIG) goto error; if (setup->id) @@ -817,12 +825,87 @@ static void setup_io_close(void *data, void *user_data) bt_bap_stream_io_connecting(setup->stream, -1); } -static void ep_close(struct bap_ep *ep) +static int setup_close(struct bap_setup *setup, bap_setup_close_func_t cb, + void *user_data) { - if (!ep) + if (setup->closing) + return -EBUSY; + + DBG("%p", setup); + + setup->close_cb = cb; + setup->close_cb_data = user_data; + setup->closing = true; + + if (!setup->stream) { + setup_free(setup); + return 0; + } + + bt_bap_stream_discard(setup->stream); + return 0; +} + +struct ep_close_data { + int remaining; + int count; + const char *path; + void (*cb)(int count, void *user_data); + void *user_data; +}; + +static void ep_close_setup_cb(struct bap_setup *setup, void *user_data) +{ + struct ep_close_data *epdata = user_data; + + epdata->remaining--; + + DBG("closed setup %p remain %d", setup, epdata->remaining); + + if (epdata->remaining) return; - queue_foreach(ep->setups, setup_io_close, NULL); + if (epdata->cb) + epdata->cb(epdata->count, epdata->user_data); + + free(epdata); +} + +static void ep_close_setup(void *data, void *user_data) +{ + struct bap_setup *setup = data; + struct ep_close_data *epdata = user_data; + struct bt_bap_stream *stream = setup->stream; + const char *path = media_transport_stream_path(stream); + + if (epdata->path && (!path || strcmp(epdata->path, path))) + return; + + epdata->remaining++; + if (setup_close(setup, ep_close_setup_cb, epdata)) + epdata->remaining--; + else + epdata->count++; +} + +static void ep_close(struct bap_ep *ep, const char *transport_path, + void (*cb)(int count, void *user_data), void *user_data) +{ + struct ep_close_data *epdata; + + DBG("close ep %p path %s", ep, transport_path ? transport_path : "-"); + + epdata = new0(struct ep_close_data, 1); + epdata->cb = cb; + epdata->path = transport_path; + epdata->user_data = user_data; + epdata->remaining = 1; + + if (ep) + queue_foreach(ep->setups, ep_close_setup, epdata); + + epdata->path = NULL; + ep_close_setup_cb(NULL, epdata); } static struct bap_setup *setup_new(struct bap_ep *ep) @@ -872,6 +955,9 @@ static void setup_free(void *data) setup_ready(setup, -ECANCELED, 0); + if (setup->closing && setup->close_cb) + setup->close_cb(setup, setup->close_cb_data); + if (setup->stream && setup->id) { bt_bap_stream_cancel(setup->stream, setup->id); setup->id = 0; @@ -1022,7 +1108,7 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg, * TO DO reconfiguration of a BIS. */ if (bt_bap_pac_get_type(ep->lpac) != BT_BAP_BCAST_SOURCE) - ep_close(ep); + ep_close(ep, NULL, NULL, NULL); setup = setup_new(ep); @@ -1062,6 +1148,51 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg, return NULL; } +struct clear_configuration_data { + DBusMessage *msg; + bool all; +}; + +static void clear_configuration_cb(int count, void *user_data) +{ + struct clear_configuration_data *data = user_data; + DBusMessage *reply; + + DBG("%p", data); + + if (!data->all && count == 0) + reply = btd_error_invalid_args(data->msg); + else + reply = dbus_message_new_method_return(data->msg); + + g_dbus_send_message(btd_get_dbus_connection(), reply); + dbus_message_unref(data->msg); + free(data); +} + +static DBusMessage *clear_configuration(DBusConnection *conn, DBusMessage *msg, + void *data) +{ + struct bap_ep *ep = data; + const char *path; + struct clear_configuration_data *cbdata; + DBusMessageIter args; + + dbus_message_iter_init(msg, &args); + dbus_message_iter_get_basic(&args, &path); + + if (strcmp(path, ep->path) == 0) + path = NULL; + + cbdata = new0(struct clear_configuration_data, 1); + cbdata->msg = dbus_message_ref(msg); + cbdata->all = (path == NULL); + + DBG("%p %s %s", cbdata, ep->path, path ? path : "NULL"); + ep_close(ep, path, clear_configuration_cb, cbdata); + return NULL; +} + static bool stream_io_unset(const void *data, const void *user_data) { struct bt_bap_stream *stream = (struct bt_bap_stream *)data; @@ -1234,6 +1365,9 @@ static const GDBusMethodTable ep_methods[] = { GDBUS_ARGS({ "endpoint", "o" }, { "Configuration", "a{sv}" } ), NULL, set_configuration) }, + { GDBUS_EXPERIMENTAL_ASYNC_METHOD("ClearConfiguration", + GDBUS_ARGS({ "transport", "o" }), + NULL, clear_configuration) }, { }, }; @@ -1244,10 +1378,9 @@ static void ep_free(void *data) struct bap_ep *ep = data; struct queue *setups = ep->setups; - ep_cancel_select(ep); - ep->setups = NULL; queue_destroy(setups, setup_free); + ep_cancel_select(ep); free(ep->path); free(ep); } @@ -1441,6 +1574,8 @@ static int setup_config(struct bap_setup *setup, bap_setup_ready_func_t cb, if (setup->ready_cb) return -EBUSY; + if (setup->closing) + return -EINVAL; setup->ready_cb = cb; setup->ready_cb_data = user_data; @@ -2249,6 +2384,13 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state, setup = bap_find_setup_by_stream(data, stream); + if (setup && setup->closing) { + if (old_state == BT_BAP_STREAM_STATE_RELEASING) { + setup_free(setup); + return; + } + } + switch (new_state) { case BT_BAP_STREAM_STATE_IDLE: /* Release stream if idle */ diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c index 3d1f55b70..b399d0f35 100644 --- a/profiles/audio/transport.c +++ b/profiles/audio/transport.c @@ -2670,3 +2670,20 @@ void media_transport_update_device_volume(struct btd_device *dev, btd_device_set_volume(dev, volume); } + +const char *media_transport_stream_path(void *stream) +{ + GSList *l; + + if (!stream) + return NULL; + + for (l = transports; l; l = l->next) { + struct media_transport *transport = l->data; + + if (media_transport_get_stream(transport) == stream) + return transport->path; + } + + return NULL; +} diff --git a/profiles/audio/transport.h b/profiles/audio/transport.h index 808e1a193..7c107281a 100644 --- a/profiles/audio/transport.h +++ b/profiles/audio/transport.h @@ -33,3 +33,4 @@ void transport_get_properties(struct media_transport *transport, int media_transport_get_device_volume(struct btd_device *dev); void media_transport_update_device_volume(struct btd_device *dev, int volume); +const char *media_transport_stream_path(void *stream); From patchwork Sun May 4 16:02:01 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 887238 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D6E61DEFE4 for ; Sun, 4 May 2025 16:02:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374544; cv=pass; b=MFtlL+H1Yvxbv3SpCsB/xtOvW2mBjP6XZzIJgmcQTrKBxGioRt2SsJAcijB+WSL0UocFxhdF8URVG9wR7jwlUiBfgm9x1eFOGfo6mh8eDu7/dbk621F/29w6Awqst4aE2bA6DL1UvKwRFyPqvFcnvyMWUdcwXn+BJlRH97mtWoA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374544; c=relaxed/simple; bh=Z9XUNkrNdZxYdwX5JjhdtlLBvrYW9KzxIiTiXUO36yk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JkKODI9MZAbEs7AqS5tCL1nU+OzDTtNJtaaZTFP7TQ3zFqrDWCz4EuyKiw9L7c+GIJANwlsLdKtdPjH04IFrUo3s7GdwjzORlCPycvawnKo/3ZNLj29wbEQWZV9msSIt2QnecU841H4HMKbajO3zgULm6Kui03CbQQgpuOWohLQ= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=hemBsBFA; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="hemBsBFA" 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 meesny.iki.fi (Postfix) with ESMTPSA id 4Zr8Yg46zZzyVF; Sun, 4 May 2025 19:02:15 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374535; 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=tB7woLWWJlDYT6FjDYIsVt2IIHAW//8aLBaypFnlWMU=; b=hemBsBFA5A5vC2zmvl5w5reUgZs61sQ5pqYAjC78JCd99/oJErcOoUv1POS3oZyrRFeq7y hruhaZ9Eq5GV2ZuLeW7oJtnlPBgg2YINsatIBFT4ZyuHOQNIhhkCNscz/44r8s7zZkBawq rL9RU9B+ymJ9GbABi7pIpKGr5+q9kFo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374535; 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=tB7woLWWJlDYT6FjDYIsVt2IIHAW//8aLBaypFnlWMU=; b=QCXwstemK/mLY9ObRXkCL/01NhKW9V/ZH9jVDvg9P7wwDR9V74c4JlH8VCnGwoRHA00f3f OC/e1+1WgVpa7syhSpGd5PwOF/1dDfm4mOq9cL/KMfsP165PfNVhY1yzN4+YcFmCx89gDg Lp/9Vw9xxSt51+c/PUQwSRbZA7o7X9M= ARC-Seal: i=1; s=meesny; d=iki.fi; t=1746374535; a=rsa-sha256; cv=none; b=uQhFKXsSRYmiSQJUFIk2MhZ34r8IjxfFv7ZAwIw/pZ522TtlR1hZU8oDHDwvJDMplod5Nx Q++gJwsn/qioneSqJNaWIDUS4wOff7Vs4nkvf3Dm7qYTrvaztnW4cC8Wu39EqKYHSXfGyM OG0fp3besMjsRJZmjOwrkany9+UFDyw= 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: [RFC PATCH BlueZ v2 09/11] bap: add callback at the end of ucast client select/config Date: Sun, 4 May 2025 19:02:01 +0300 Message-ID: X-Mailer: git-send-email 2.49.0 In-Reply-To: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> References: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Restructure pac_select() and add a callback that is called when all setups reach QoS. --- profiles/audio/bap.c | 173 +++++++++++++++++++++++++++++++++---------- 1 file changed, 134 insertions(+), 39 deletions(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index c9755ad96..89900602f 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -66,10 +66,12 @@ #define MEDIA_INTERFACE "org.bluez.Media1" struct bap_setup; +struct bap_select; typedef void (*bap_setup_ready_func_t)(struct bap_setup *setup, int code, uint8_t reason, void *data); typedef void (*bap_setup_close_func_t)(struct bap_setup *setup, void *data); +typedef void (*bap_select_done_t)(int err, void *data); struct bap_setup { struct bap_ep *ep; @@ -96,6 +98,15 @@ struct bap_setup { void (*destroy)(struct bap_setup *setup); }; +struct bap_select { + struct bap_data *data; + struct queue *eps; + int remaining; + int err; + bap_select_done_t done_cb; + void *done_cb_data; +}; + struct bap_ep { char *path; struct bap_data *data; @@ -105,6 +116,7 @@ struct bap_ep { uint16_t supported_context; uint16_t context; struct queue *setups; + struct bap_select *select; }; struct bap_data { @@ -122,7 +134,6 @@ struct bap_data { struct queue *server_streams; GIOChannel *listen_io; unsigned int io_id; - int selecting; void *user_data; }; @@ -1614,14 +1625,37 @@ static int setup_config(struct bap_setup *setup, bap_setup_ready_func_t cb, return 0; } -static void bap_config_setup(void *data, void *user_data) +static void bap_config_setup_cb(struct bap_setup *setup, int code, + uint8_t reason, void *user_data) { - struct bap_setup *setup = data; + struct bap_select *select = user_data; - if (setup_config(setup, NULL, NULL)) { + select->remaining--; + + DBG("setup %p code %d remain %d", setup, code, select->remaining); + + if (code) + select->err = code; + + if (select->remaining) + return; + + if (select->done_cb) + select->done_cb(select->err, select->done_cb_data); + + free(select); +} + +static void bap_config_setup(void *item, void *user_data) +{ + struct bap_setup *setup = item; + struct bap_select *select = user_data; + + select->remaining++; + if (setup_config(setup, bap_config_setup_cb, select)) { DBG("Unable to config stream"); setup_free(setup); - return; + select->remaining--; } } @@ -1629,7 +1663,37 @@ static void bap_config(void *data, void *user_data) { struct bap_ep *ep = data; - queue_foreach(ep->setups, bap_config_setup, NULL); + queue_foreach(ep->setups, bap_config_setup, user_data); +} + +static void pac_select_clear_ep(void *data) +{ + struct bap_ep *ep = data; + + ep->select = NULL; +} + +static void bap_select_complete_select(struct bap_select *select) +{ + select->remaining--; + + DBG("selecting %d", select->remaining); + + if (select->remaining) + return; + + DBG("configure (err %d)", select->err); + + queue_destroy(select->eps, pac_select_clear_ep); + + select->remaining++; + + if (!select->err) { + queue_foreach(select->data->srcs, bap_config, select); + queue_foreach(select->data->snks, bap_config, select); + } + + bap_config_setup_cb(NULL, 0, 0, select); } static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps, @@ -1637,11 +1701,11 @@ static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps, void *user_data) { struct bap_ep *ep = user_data; + struct bap_select *select = ep->select; struct bap_setup *setup; if (err) { error("err %d", err); - ep->data->selecting--; goto done; } @@ -1650,38 +1714,15 @@ static void select_cb(struct bt_bap_pac *pac, int err, struct iovec *caps, setup->metadata = util_iov_dup(metadata, 1); setup->qos = *qos; - DBG("selecting %d", ep->data->selecting); - ep->data->selecting--; - done: - if (ep->data->selecting) - return; - - queue_foreach(ep->data->srcs, bap_config, NULL); - queue_foreach(ep->data->snks, bap_config, NULL); - queue_foreach(ep->data->bcast, bap_config, NULL); -} - -static bool pac_register(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, - void *user_data) -{ - struct btd_service *service = user_data; - struct bap_ep *ep; - - DBG("lpac %p rpac %p", lpac, rpac); - - ep = ep_register(service, lpac, rpac); - if (!ep) - error("Unable to register endpoint for pac %p", rpac); - - return true; + bap_select_complete_select(select); } static bool pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, void *user_data) { - struct btd_service *service = user_data; - struct bap_data *data = btd_service_get_user_data(service); + struct bap_select *select = user_data; + struct bap_data *data = select->data; struct match_ep match = { lpac, rpac }; struct queue *queue; struct bap_ep *ep; @@ -1703,9 +1744,57 @@ static bool pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, return true; } + if (ep->select && ep->select != select) { + select->err = -EBUSY; + return true; + } + /* TODO: Cache LRU? */ - if (btd_service_is_initiator(service)) - bt_bap_select(lpac, rpac, &ep->data->selecting, select_cb, ep); + + if (!ep->select) { + ep->select = select; + queue_push_tail(select->eps, ep); + } + + bt_bap_select(lpac, rpac, &select->remaining, select_cb, ep); + + return true; +} + +static int bap_select_all(struct bap_data *data, bap_select_done_t cb, + void *user_data) +{ + struct bap_select *select; + + if (!btd_service_is_initiator(data->service)) + return -EINVAL; + + select = new0(struct bap_select, 1); + select->remaining = 1; + select->data = data; + select->eps = queue_new(); + select->done_cb = cb; + select->done_cb_data = user_data; + + bt_bap_foreach_pac(data->bap, BT_BAP_SOURCE, pac_select, select); + bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_select, select); + + bap_select_complete_select(select); + + return 0; +} + +static bool pac_register(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, + void *user_data) +{ + struct btd_service *service = user_data; + struct bap_ep *ep; + + DBG("lpac %p rpac %p", lpac, rpac); + + ep = ep_register(service, lpac, rpac); + if (!ep) + error("Unable to register endpoint for pac %p", rpac); return true; } @@ -1723,9 +1812,16 @@ static bool pac_cancel_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, static void ep_cancel_select(struct bap_ep *ep) { struct bt_bap *bap = ep->data->bap; + struct bap_select *select; bt_bap_foreach_pac(bap, BT_BAP_SOURCE, pac_cancel_select, ep); bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_cancel_select, ep); + + select = ep->select; + if (select) { + queue_remove(select->eps, ep); + ep->select = NULL; + } } static bool pac_found_bcast(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, @@ -1752,6 +1848,7 @@ static bool pac_found_bcast(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, static void bap_ready(struct bt_bap *bap, void *user_data) { struct btd_service *service = user_data; + struct bap_data *data = btd_service_get_user_data(service); DBG("bap %p", bap); @@ -1761,8 +1858,7 @@ static void bap_ready(struct bt_bap *bap, void *user_data) bt_bap_foreach_pac(bap, BT_BAP_SOURCE, pac_register, service); bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_register, service); - bt_bap_foreach_pac(bap, BT_BAP_SOURCE, pac_select, service); - bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_select, service); + bap_select_all(data, NULL, NULL); } static bool match_setup_stream(const void *data, const void *user_data) @@ -2716,8 +2812,7 @@ static void pac_added(struct bt_bap_pac *pac, void *user_data) bt_bap_foreach_pac(data->bap, BT_BAP_SOURCE, pac_register, service); bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_register, service); - bt_bap_foreach_pac(data->bap, BT_BAP_SOURCE, pac_select, service); - bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_select, service); + bap_select_all(data, NULL, NULL); } static void pac_added_broadcast(struct bt_bap_pac *pac, void *user_data) From patchwork Sun May 4 16:02:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 887609 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B96171DF24E for ; Sun, 4 May 2025 16:02:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374544; cv=pass; b=vEHK9EfqtXzQl3o86S+38+nKgoQP/Oh+8qwDUv0972NihTD+jAMUo9d7DE3krqaNlSCiYUFshMaWjoCDfIPZ3JXDPJxGhGyWLYSXnOQj1Z1zLjxJGw3UqhIbQA5CVhG20L7ADxU5gggKMdIIwZ7jr5JdR9zlc6lrrnP0eoPbnUI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374544; c=relaxed/simple; bh=ZLoCcrMVEb9Ry5kGpEgWY2awpGFpIU22QYyUKaMMy68=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=R25OWTvMOlExw/oOcrQ5pw55rAUk1unRsgKGKcuPih2643oFKsN9X9KqKaAAZsys/l2XT69ww0M4Ghm9to+aW8b8ANl9xdakr+TDWSm957itZNpTojAHhaVn5U8/alc54EetqZpG+faW73DZpn3XTUJoAMfSd6eQXbX+6tjBWGE= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=KJgoC1Tw; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="KJgoC1Tw" 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 meesny.iki.fi (Postfix) with ESMTPSA id 4Zr8Yh1XgnzyhX; Sun, 4 May 2025 19:02:16 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374536; 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=uLb7eojkTrm3F+ZawmAtGumIKS8R8XPMJzf6wshVLY4=; b=KJgoC1TwZcMsBkrVGtSkzF9J0RpUpYDyVtTwTnihFZ6WdYBPaZ4rX3sKNRWFYkz6It2J3d 1toNsjLMD2Bd103di1G7jZDIDzkZ+kTeS3ZZzmU3xAzGnFxHfVSrWZW2Bm0cTZvw4dR+e9 2mBf1pXx/fj/p3KWSSDTW/YJ9djXiHI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374536; 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=uLb7eojkTrm3F+ZawmAtGumIKS8R8XPMJzf6wshVLY4=; b=feVqa48dt9dPCgnpzGuAGhUVGE1Di19p3GJmk9YQvp1dsM+13kiClps+99S9sNC+YEEwEF M1JGTr23XJ9Z1uZR6h5ku+czRDnS0JVtIbTjOn+CiLwyYtTFMOTnq2PwONpUS0JLTG0en9 6osEqJBVFszKcrQIMz9ICe2lwB+Kclw= ARC-Seal: i=1; s=meesny; d=iki.fi; t=1746374536; a=rsa-sha256; cv=none; b=bU6behfJdeR3VIBX6sVOWVEoYyrRgk3CCrsDy7Q+7Dyc8WWmhhykTwUylUpBUyRpTmIqwp Ei4fe7QuVRnFZB4zbeFmsGKQtyWEi4jcakRIx0RlRhGnYZEUXKn6LYtP6398Ar9HzGnCsJ h1yhgynVB6dD392LHtTSJiy+W5JwTWk= 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: [RFC PATCH BlueZ v2 10/11] bap: implement Reconfigure() Date: Sun, 4 May 2025 19:02:02 +0300 Message-ID: <582d3a955636d24d20b959d83cd766fcc4af2528.1746374514.git.pav@iki.fi> X-Mailer: git-send-email 2.49.0 In-Reply-To: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> References: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add Reconfigure() on a BAP unicast endpoint, which triggers its reconfiguration or marks it for reconfiguration. First, all associated streams are closed. After that, endpoints marked for reconfiguration are reconfigured using the same flow as in the initial configuration. --- profiles/audio/bap.c | 151 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 146 insertions(+), 5 deletions(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index 89900602f..20d610e6f 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -101,6 +101,7 @@ struct bap_setup { struct bap_select { struct bap_data *data; struct queue *eps; + bool reconfigure; int remaining; int err; bap_select_done_t done_cb; @@ -117,6 +118,7 @@ struct bap_ep { uint16_t context; struct queue *setups; struct bap_select *select; + bool reconfigure; }; struct bap_data { @@ -141,7 +143,8 @@ static struct queue *sessions; static int setup_config(struct bap_setup *setup, bap_setup_ready_func_t cb, void *user_data); - +static int bap_select_all(struct bap_data *data, bool reconfigure, + bap_select_done_t cb, void *user_data); static bool bap_data_set_user_data(struct bap_data *data, void *user_data) { @@ -1204,6 +1207,132 @@ static DBusMessage *clear_configuration(DBusConnection *conn, DBusMessage *msg, return NULL; } +static int reconfigure_parse(DBusMessageIter *props, bool *defer) +{ + const char *key; + + if (dbus_message_iter_get_arg_type(props) != DBUS_TYPE_DICT_ENTRY) + return -EINVAL; + + while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter value, entry; + int var; + + dbus_message_iter_recurse(props, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &value); + + var = dbus_message_iter_get_arg_type(&value); + + if (!strcasecmp(key, "Defer")) { + dbus_bool_t flag; + + if (var != DBUS_TYPE_BOOLEAN) + goto fail; + + dbus_message_iter_get_basic(&value, &flag); + *defer = flag; + } + + dbus_message_iter_next(props); + } + + return 0; + +fail: + DBG("Failed parsing %s", key); + + return -EINVAL; +} + +struct reconfigure_data { + int remaining; + struct bap_data *data; + DBusMessage *msg; +}; + +static void reconfigure_select_cb(int err, void *user_data) +{ + struct reconfigure_data *data = user_data; + DBusMessage *reply; + + if (!err) + reply = dbus_message_new_method_return(data->msg); + else + reply = btd_error_failed(data->msg, "Failed to configure"); + + g_dbus_send_message(btd_get_dbus_connection(), reply); + dbus_message_unref(data->msg); + free(data); +} + +static void reconfigure_close_cb(int count, void *user_data) +{ + struct reconfigure_data *data = user_data; + + data->remaining--; + + DBG("remain %d", data->remaining); + + if (data->remaining) + return; + + bap_select_all(data->data, true, reconfigure_select_cb, data); +} + +static void ep_close_if_reconfigure(void *obj, void *user_data) +{ + struct bap_ep *ep = obj; + struct reconfigure_data *data = user_data; + + if (ep->reconfigure) { + data->remaining++; + ep_close(ep, NULL, reconfigure_close_cb, data); + } +} + +static DBusMessage *reconfigure(DBusConnection *conn, DBusMessage *msg, + void *user_data) +{ + struct bap_ep *ep = user_data; + struct bap_data *data = ep->data; + struct reconfigure_data *cbdata; + bool defer = false; + DBusMessageIter args, props; + + switch (bt_bap_pac_get_type(ep->lpac)) { + case BT_BAP_SOURCE: + case BT_BAP_SINK: + break; + default: + return btd_error_invalid_args(msg); + } + + dbus_message_iter_init(msg, &args); + dbus_message_iter_recurse(&args, &props); + if (reconfigure_parse(&props, &defer)) + return btd_error_invalid_args(msg); + + DBG("%s defer %d", ep->path, (int)defer); + + ep->reconfigure = true; + if (defer) + return dbus_message_new_method_return(msg); + + cbdata = new0(struct reconfigure_data, 1); + cbdata->data = ep->data; + cbdata->msg = dbus_message_ref(msg); + cbdata->remaining = 1; + + queue_foreach(data->snks, ep_close_if_reconfigure, cbdata); + queue_foreach(data->srcs, ep_close_if_reconfigure, cbdata); + + reconfigure_close_cb(0, cbdata); + return NULL; +} + static bool stream_io_unset(const void *data, const void *user_data) { struct bt_bap_stream *stream = (struct bt_bap_stream *)data; @@ -1379,6 +1508,10 @@ static const GDBusMethodTable ep_methods[] = { { GDBUS_EXPERIMENTAL_ASYNC_METHOD("ClearConfiguration", GDBUS_ARGS({ "transport", "o" }), NULL, clear_configuration) }, + { GDBUS_EXPERIMENTAL_ASYNC_METHOD("Reconfigure", + GDBUS_ARGS( + { "properties", "a{sv}" }), + NULL, reconfigure) }, { }, }; @@ -1749,6 +1882,11 @@ static bool pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, return true; } + if (select->reconfigure && !ep->reconfigure) + return true; + + ep->reconfigure = false; + /* TODO: Cache LRU? */ if (!ep->select) { @@ -1761,15 +1899,18 @@ static bool pac_select(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, return true; } -static int bap_select_all(struct bap_data *data, bap_select_done_t cb, - void *user_data) +static int bap_select_all(struct bap_data *data, bool reconfigure, + bap_select_done_t cb, void *user_data) { struct bap_select *select; if (!btd_service_is_initiator(data->service)) return -EINVAL; + DBG("data %p reconfig %d", data, (int)reconfigure); + select = new0(struct bap_select, 1); + select->reconfigure = reconfigure; select->remaining = 1; select->data = data; select->eps = queue_new(); @@ -1858,7 +1999,7 @@ static void bap_ready(struct bt_bap *bap, void *user_data) bt_bap_foreach_pac(bap, BT_BAP_SOURCE, pac_register, service); bt_bap_foreach_pac(bap, BT_BAP_SINK, pac_register, service); - bap_select_all(data, NULL, NULL); + bap_select_all(data, false, NULL, NULL); } static bool match_setup_stream(const void *data, const void *user_data) @@ -2812,7 +2953,7 @@ static void pac_added(struct bt_bap_pac *pac, void *user_data) bt_bap_foreach_pac(data->bap, BT_BAP_SOURCE, pac_register, service); bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_register, service); - bap_select_all(data, NULL, NULL); + bap_select_all(data, false, NULL, NULL); } static void pac_added_broadcast(struct bt_bap_pac *pac, void *user_data) From patchwork Sun May 4 16:02:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Virtanen X-Patchwork-Id: 887237 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1B80D146A72 for ; Sun, 4 May 2025 16:02:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374544; cv=pass; b=q8+qC8FIrW1ahbGBYR53FFBff3DBqaAwiU9wnvfTTivAMwnNue5vZxU4yOxzq8kO6Sge9NieLaDurd86uuhuXLVNYukLqeGVeZZ8MRo6SCgvknzQVwxP/vsH8tk29bF0KxglmfRggXnqSjgdCaB0FIKLr819ocEFM5eIB/80vaY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746374544; c=relaxed/simple; bh=UNT2KJVtcRN5DvwjG1mcVTLxxALZm78kpkCPz0Va+nQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ovEVy81hswedcQ4poN5Ty/9qfFQeHgmBFp1iRrDwmIB94FJpxF9WJoa4k6awCIuX/HmiViaXd4R9s5yMlQ9irf/wqZWF5ta6waFw7cpPAYHfd/+gXYXBV8EHZKeQimI9IkEGkPEApNvT9x5WCZkfQbBtp4rFLVGMEDpfEeQp3CU= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=Zk+OAECg; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="Zk+OAECg" 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 meesny.iki.fi (Postfix) with ESMTPSA id 4Zr8Yh45Vgz10F9; Sun, 4 May 2025 19:02:16 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374536; 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=p91dG9VMLPxEXrslQmhBYgA9RFNaQ1iKD+9yuU5bGg0=; b=Zk+OAECgqWFby9W79Y8SgEeAW8c38TgwvaxV93+ETaUYqN2JDV2M78k+cgXiHfLlq+mg42 Rmcs8k6Bv9MNDga8mT2Oz4HnwaCRQOVlZ//UzV/0sRRaT+ldagrQY3AB5xiwL7i2jZ2cLU zxbnRg1jiDKSYL5biQr2twR39e/K6v8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1746374536; 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=p91dG9VMLPxEXrslQmhBYgA9RFNaQ1iKD+9yuU5bGg0=; b=Q6IEXALTsDaWyQ/ZaK0y8md0iMGcPsqyZeOggXZL/0DWQ6SY1vAL3KcbJVeSmHQklXGwU6 giouYxNVsmXfuTOI+RJlMKoGsMyPaK/jCF8glubaJomSOyafd8cIftVLJZK5tuMHcwzurW 8/QBkXaQLDTfPpbkkfb0JQnaTwr4IBE= ARC-Seal: i=1; s=meesny; d=iki.fi; t=1746374536; a=rsa-sha256; cv=none; b=tTJGs/Hjcy6Anfk/HQ7r1rYHPM4MELrsxz0gvJCBoy7iPnqJTpqtUsE35w3dJr/vHVnhmq yC28xLhSTcwO++0lG6w4gGod4VKutFijLNor34jfyM+3k1CqNgXIUgYRxRwfaDtBn1uyWy TQjjI5Cfpyc4eWdWwuJYwrvQdOQk1Nw= 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: [RFC PATCH BlueZ v2 11/11] bap: delay recreating IO after ongoing configuration Date: Sun, 4 May 2025 19:02:03 +0300 Message-ID: <04be9eb6246b1dad5234c3ddcb8eeda4ba3500aa.1746374514.git.pav@iki.fi> X-Mailer: git-send-email 2.49.0 In-Reply-To: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> References: <3c9eb72cf7b16ea0b710d62221436e2777f7360b.1746374514.git.pav@iki.fi> Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Delay creating IO if setup reconfiguration is ongoing. TODO: this is not fully right, also new stream QoS should be delayed if CIG is active, so that it doesn't get assigned into a new CIG which controllers may not support --- profiles/audio/bap.c | 108 ++++++++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 27 deletions(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index 20d610e6f..ce1c349c6 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -86,6 +86,7 @@ struct bap_setup { bool cig_active; uint8_t sid; bool config_pending; + bool readying; bool closing; struct iovec *caps; struct iovec *metadata; @@ -727,15 +728,23 @@ fail: return -EINVAL; } +static void setup_recreate_cig(struct bap_setup *setup); + static void setup_ready(struct bap_setup *setup, int code, uint8_t reason) { - if (!setup->ready_cb) + if (!setup->readying) return; - setup->ready_cb(setup, code, reason, setup->ready_cb_data); - setup->ready_cb = NULL; - setup->ready_cb_data = NULL; + setup->readying = false; + + if (setup->ready_cb) { + setup->ready_cb(setup, code, reason, setup->ready_cb_data); + setup->ready_cb = NULL; + setup->ready_cb_data = NULL; + } + + setup_recreate_cig(setup); } static void qos_cb(struct bt_bap_stream *stream, uint8_t code, uint8_t reason, @@ -770,7 +779,7 @@ static int setup_qos(struct bap_setup *setup) setup_create_io(data, setup, stream, true); if (!setup->io) { - error("Unable to create io"); + DBG("io pending"); goto error; } @@ -1741,6 +1750,8 @@ static int setup_config(struct bap_setup *setup, bap_setup_ready_func_t cb, if (!setup->id) return -EINVAL; + setup->readying = true; + switch (bt_bap_stream_get_type(setup->stream)) { case BT_BAP_STREAM_TYPE_UCAST: setup->config_pending = true; @@ -2215,7 +2226,11 @@ static bool match_cig_active(const void *data, const void *match_data) const struct bap_setup *setup = data; const struct cig_busy_data *info = match_data; - return (setup->qos.ucast.cig_id == info->cig) && setup->cig_active; + if (info->cig != BT_ISO_QOS_CIG_UNSET && + setup->qos.ucast.cig_id != info->cig) + return false; + + return setup->cig_active || setup->readying; } static bool cig_busy_ep(const void *data, const void *match_data) @@ -2242,6 +2257,10 @@ static bool is_cig_busy(struct bap_data *data, uint8_t cig) { struct cig_busy_data info; + /* TODO: this is not quite right --- it may results to allocation of a + * new CIG which won't work if controller supports only one. Instead we + * should be delaying stream QoS until CIG deactivates. + */ if (cig == BT_ISO_QOS_CIG_UNSET) return false; @@ -2251,30 +2270,22 @@ static bool is_cig_busy(struct bap_data *data, uint8_t cig) return queue_find(sessions, cig_busy_session, &info); } -static gboolean setup_io_recreate(void *user_data) -{ - struct bap_setup *setup = user_data; - - DBG("%p", setup); - - setup->io_id = 0; - - setup_create_io(setup->ep->data, setup, setup->stream, true); - - return FALSE; -} - static void setup_recreate(void *data, void *match_data) { struct bap_setup *setup = data; struct cig_busy_data *info = match_data; - if (setup->qos.ucast.cig_id != info->cig || !setup->recreate || - setup->io_id) + if (info->cig != BT_ISO_QOS_CIG_UNSET && + setup->qos.ucast.cig_id != BT_ISO_QOS_CIG_UNSET && + setup->qos.ucast.cig_id != info->cig) + return; + if (!setup->recreate || !setup->stream) return; + DBG("%p", setup); + setup->recreate = false; - setup->io_id = g_idle_add(setup_io_recreate, setup); + setup_create_io(setup->ep->data, setup, setup->stream, true); } static void recreate_cig_ep(void *data, void *match_data) @@ -2284,6 +2295,34 @@ static void recreate_cig_ep(void *data, void *match_data) queue_foreach(ep->setups, setup_recreate, match_data); } +static void setup_reenable(void *data, void *match_data) +{ + struct bap_setup *setup = data; + struct cig_busy_data *info = match_data; + + if (info->cig != BT_ISO_QOS_CIG_UNSET && + setup->qos.ucast.cig_id != BT_ISO_QOS_CIG_UNSET && + setup->qos.ucast.cig_id != info->cig) + return; + if (!setup->recreate || !setup->stream) + return; + + DBG("%p", setup); + + switch (bt_bap_stream_get_state(setup->stream)) { + case BT_BAP_STREAM_STATE_ENABLING: + setup_create_io(setup->ep->data, setup, setup->stream, false); + break; + } +} + +static void reenable_cig_ep(void *data, void *match_data) +{ + struct bap_ep *ep = data; + + queue_foreach(ep->setups, setup_reenable, match_data); +} + static void recreate_cig_session(void *data, void *match_data) { struct bap_data *session = data; @@ -2294,13 +2333,19 @@ static void recreate_cig_session(void *data, void *match_data) queue_foreach(session->snks, recreate_cig_ep, match_data); queue_foreach(session->srcs, recreate_cig_ep, match_data); + + queue_foreach(session->snks, reenable_cig_ep, match_data); + queue_foreach(session->srcs, reenable_cig_ep, match_data); } -static void recreate_cig(struct bap_setup *setup) +static void setup_recreate_cig(struct bap_setup *setup) { struct bap_data *data = setup->ep->data; struct cig_busy_data info; + if (is_cig_busy(setup->ep->data, setup->qos.ucast.cig_id)) + return; + info.adapter = device_get_adapter(data->device); info.cig = setup->qos.ucast.cig_id; @@ -2309,25 +2354,34 @@ static void recreate_cig(struct bap_setup *setup) if (setup->qos.ucast.cig_id == BT_ISO_QOS_CIG_UNSET) { recreate_cig_ep(setup->ep, &info); + reenable_cig_ep(setup->ep, &info); return; } queue_foreach(sessions, recreate_cig_session, &info); } +static gboolean recreate_cig_cb(void *user_data) +{ + struct bap_setup *setup = user_data; + + setup->io_id = 0; + setup_recreate_cig(setup); + return FALSE; +} + static void setup_io_disconnected(int cond, void *user_data) { struct bap_setup *setup = user_data; - DBG("%p recreate %s", setup, setup->recreate ? "true" : "false"); - setup->io_id = 0; + DBG("%p recreate %s", setup, setup->recreate ? "true" : "false"); + setup_io_close(setup, NULL); /* Check if connecting recreate IO */ - if (!is_cig_busy(setup->ep->data, setup->qos.ucast.cig_id)) - recreate_cig(setup); + setup->io_id = g_idle_add(recreate_cig_cb, setup); } static void bap_connect_bcast_io_cb(GIOChannel *chan, GError *err,