From patchwork Wed Jun 7 08:22:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Silviu Florian Barbulescu X-Patchwork-Id: 690307 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 46F9AC7EE29 for ; Wed, 7 Jun 2023 08:23:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238657AbjFGIXX (ORCPT ); Wed, 7 Jun 2023 04:23:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34798 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237506AbjFGIXV (ORCPT ); Wed, 7 Jun 2023 04:23:21 -0400 Received: from EUR01-VE1-obe.outbound.protection.outlook.com (mail-ve1eur01on2040.outbound.protection.outlook.com [40.107.14.40]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D8F96138 for ; Wed, 7 Jun 2023 01:23:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=PK7eOGI9F05wSRT0UMIYvUZeUPHSAp06xQk9ZgrtsIPUdOFQflu7JvOH29lTlytxLjAD7m/fVsUaEO19znUbMToVBrFCeZbAW2aNTSfACLNhnnss2ezeJS0hdE7IExZA9bk6P1DNzI7D8QWssF71eGWdy6ZeeXLa8/E27uw/SO1tdxMtkufi4AyO3mRW55rCzTInAvN52a3aq/3O5KMJlvvTIO1M4hEonXslOuCfUYVRB026wDzSA+oyfaEwLbpn4lkwi7Q+Z6v4CofaZMVVgV+8nA+jDvdc9StdKzmiMSWxJ9tJHlWRn3N8M3WAWz/vupvPnhcNENyba8vjtqSsig== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=xwOQanpDMzivoZ+6pV9g+FQFRbisslddF1I40+2N2ks=; b=BNGA080vYNWssTbGJDQ2qPF+kEfEgxSnmI4q4KMEjy+JIzLACj0CFZNAKdw89fLrJzU3g0R7UzKifWOuRHkAematq/GQFC9FVPjGAnm53IRAaWfg1zlr/5Ah1h3D7vWSkzBzyvW94bPhbduJ+SFGaYaburcRjcg0C7G9Pdqai0yq2vW54glB+bZytZQynfFfqpU5kDC8IKAyRvLczx8jBj+aNt+Bv5FXpuuflS2cYRKNo2w/NGJOuIAP2JzV9aZEhN8mSL+I2CZbVEQDcE578U38fccmcSF1jbh1pin1G6pJyrcVXWdl4pj1OkcTiIENpx8rvFFPZSp+QAY07GIW7g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass header.d=nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=xwOQanpDMzivoZ+6pV9g+FQFRbisslddF1I40+2N2ks=; b=HEn0cwa/0Sxtx+vCAR2kOaLjcKJB2ZcHw+3/gFwpDlvw/EiBuN285xSOqU6rdXy5GWEnHHFHzHUByOeHiO2ywf9AA0HuyUMxcBGNA95H4xA0j309+7iwSCLGZR5cEkS8eiE4LlLUbA28RGmzx059Fmf6pKXE3sxcAcb8K0obBfA= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from VI1PR04MB5344.eurprd04.prod.outlook.com (2603:10a6:803:4b::31) by DB8PR04MB7114.eurprd04.prod.outlook.com (2603:10a6:10:fe::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6455.32; Wed, 7 Jun 2023 08:23:17 +0000 Received: from VI1PR04MB5344.eurprd04.prod.outlook.com ([fe80::e8eb:cac:f3e3:1085]) by VI1PR04MB5344.eurprd04.prod.outlook.com ([fe80::e8eb:cac:f3e3:1085%4]) with mapi id 15.20.6455.030; Wed, 7 Jun 2023 08:23:16 +0000 From: Silviu Florian Barbulescu To: linux-bluetooth@vger.kernel.org Cc: Silviu Florian Barbulescu Subject: [PATCH v4 1/4] Split bt_bap_qos structure into unicast and broadcast structures Date: Wed, 7 Jun 2023 11:22:57 +0300 Message-Id: <20230607082300.4970-2-silviu.barbulescu@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230607082300.4970-1-silviu.barbulescu@nxp.com> References: <20230607082300.4970-1-silviu.barbulescu@nxp.com> X-ClientProxiedBy: AM4PR0101CA0083.eurprd01.prod.exchangelabs.com (2603:10a6:200:41::51) To VI1PR04MB5344.eurprd04.prod.outlook.com (2603:10a6:803:4b::31) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: VI1PR04MB5344:EE_|DB8PR04MB7114:EE_ X-MS-Office365-Filtering-Correlation-Id: 77903bfa-a12a-44b3-7088-08db673071ab X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: kYqjPkfo5RhH1g3j1UA+bgfjKVx3QvI099j37EZegRZ9StFG7M2clgxdHEtRXTO8NIQjW/PU72flzYm3ifUPPt1KE9R+/gQgXZdM0aKJbxd+rfVGMqh/wxgNbyboID5Mrb3WS2sQsybXwI6y/0fda5v599XDsNV2lX+iRwGA73szkr0HptbQ4F+mmzTP/5kHemWMjm5RNaSi5O8M88q2HulaamI3PmHXcSfT0dQfH4ITiArbbOcOm8CaXcadf30o6ZwDW+g4ucmhFHgiFeBjg2koX8bzK/ZQEnlmC2bxVknLVAPCDm1fxdk6p/1gq42Kswxc8aqn0vNdv7wkYszr2CBgJHQc1n2yUNAjVjQgiGnrBk3WmI596Y/v/iYbFpnYDCtwvOkhoZ5zbIFLL4n25JKtSgSOAYlrTkSezxmIK9IdqRmCJW8/LL1vKlY60aZyn2MAyLLqycSB3s8fHB/MdfFcQp03Ld39BYoMRkReysMCblom8/9/ioY3f4Kehj1GcF3UjonNf7YMeApX4LuUpD/NI82JL+8g+qelLURFIor0wztBvgcpmDdz0oM6srvoiLW1IHh6ndEXZckEbaNRyPDOYfRFHlYmlaqlTQTE3XIhdWqS8NDTMaD/hipeM6HT X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VI1PR04MB5344.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230028)(4636009)(376002)(366004)(396003)(39860400002)(136003)(346002)(451199021)(55236004)(1076003)(6512007)(6506007)(38100700002)(2616005)(41300700001)(38350700002)(6486002)(52116002)(6666004)(186003)(26005)(83380400001)(478600001)(66556008)(6916009)(66476007)(66946007)(316002)(2906002)(8676002)(8936002)(5660300002)(4326008)(30864003)(86362001)(36756003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 554Wcevvb1YcedbCp4GYLJcTJFnCJDgGTP36EiolfgjtJ3TCgdylErxGqykYPf3N5la4EffwcYEpwdurgWQHOLKzKEskoTpYyHk/lNVs0rJhUJZtOzOtMNv+40vsflxICABPtbUF/SZlLL6WnwQ0JAtAU6F87y8qwjexshwhNVyVdcfi2KIpvlNj/2Dm6HVXiIfKUSbg1CADGQ7eTVIviwxt45VJEEx2Q2G9GCDtix74fWPjkIjNUUW0bPqngfnhneSAKtIYeEa9l4rbGelMojNy9zrWENEPEKCkWikLq7FoP+ANp5UU0Fhxg2j+Dp5dYiUoIHeBeXHVsIDZmcC/8K9Efx/DMDNXxJXyad88m887zZ6jTA4o88+ohil32tQuWl1LlkQs+/2pq8lDvnuHIx1jdb4tTQzhGjo6e/tUFoZANXF0LsJTBNjXzkz+/StWZffWQDFZefq4qqJ3dNycoTLDI+5RBB6IqGs8OtpXJMkD0oHu7xKO8QmiEyN/6ED8dWy77tdhKV2YkTJGVS/JIoydJ/VqeUTr7gdtLrSwc6ugF5RfRCI/kpCbCSpqcgvIe0ruslNypCJ8DIXdcL8ngQ6G5Y1r0hKvpz0lSZqUjt0OrlmZ/2bEaOf3nkyb4OywyvXCmEWf37Q4MqNeRntvCwzSTWZmHc4yvVc08ELOUwU04NIPgY5dWIjYSgL9Eq2fTPjsgobOyBCyPCl485fpExCR2Vd5OoKeTBqveeIMAhAHQQq3qVlJ+mp55fpUs7EwqG3WgBs8PlWsSed5Sxi+auL9jrzHlNN3wV/VCgrbrl6u8lwXwXI3c2uKyoiM1eYoif47O4ym7IdOvfFsJRH185CrW7vXRwLP+GulF+8tHxbBpBAeAWTzNFsKuIb/A1IBdVcSVa28+y+tmxO8qiyTzRgDPIOiwungfILqYxujDn3/Vp0BHgcXrx+r412vRMtNkA53TrM5BbFpiwz2SYgNDFLqMwebKOfTk6aMNVuCy4h9ixzSWwKG3hcPT6o505MD5vNIF3NSWclQ/7TTCjWN8szbG6A44A292Nd3Hs7ChMDEjEzXrfKhDLc/sepybMGCYb8acschVLK8+9zCSdM+OqwELV7ctgLVQzr/0tQc4ftyJXMSIO69z1GLO0KxdKQF6ksexvyWtXudot49K/bUQizd8WT4DH5b2u7pi2Wdb8bklL3X4exgKr5Ybx7Zj/bWY0oZDjA/QPMIMFIXjELOCf48Wd7Ian5S/zbUuEsS0dJu1JSRErcbiSPyyR27dQ1S7v7OKXXTNPKdde4CWQi94/Fkx4XL6WYA0i+QNWeIeDfMg3wCCAthEDw5Ka//2Xe+xYDRMBgBWwl5M/yX5l6L3C768d8ZrBO+6yl0HBBWxk7WFnI3mVnU94zho7DLixpeYXe9Ja8X2onAcFwXR161kEQvBmK9K3cyGVfV0jAD4edNtRFjmqSZLiy2H5jnidM3Jre3u0Ls0tmTiQfG8xBnVnuajylOpPFdOVLABnOpsB+s9YmfT1C66GDd2V1AV0NTf51p5ySVq7dP0pfuQaeEHeaJem4W32SJPAH4ZDsk2x1jY60BRk7iNbcks6plnwBjlpGleh3gtUOtC2Ksmz5cqA== X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 77903bfa-a12a-44b3-7088-08db673071ab X-MS-Exchange-CrossTenant-AuthSource: VI1PR04MB5344.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Jun 2023 08:23:16.8998 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: TJL2/nW2J0nRHzsT75mpfvhXNeQ6tYN9QD+P+AJM4bmaj/xc+OM1qzTQ81tD6W1L2CVTc8keEGNXr5z90HjbAagF6lPWrLPTjibFS/xNmHM= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR04MB7114 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This splits bt_bap_qos structure into unicast and broadcast structures. --- profiles/audio/bap.c | 58 +++++++++++++----------- profiles/audio/media.c | 33 ++++++++------ profiles/audio/transport.c | 25 ++++++----- src/shared/bap.c | 92 ++++++++++++++++++++------------------ src/shared/bap.h | 42 ++++++++++++++--- unit/test-bap.c | 75 ++++++++++++++++--------------- 6 files changed, 188 insertions(+), 137 deletions(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index 1a543a9ce..cbaf705c0 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -253,6 +253,7 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps, struct iovec **metadata, struct bt_bap_qos *qos) { const char *key; + struct bt_bap_io_qos io_qos; while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) { DBusMessageIter value, entry; @@ -282,17 +283,17 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps, if (var != DBUS_TYPE_BYTE) goto fail; - dbus_message_iter_get_basic(&value, &qos->cig_id); + dbus_message_iter_get_basic(&value, &qos->ucast.cig_id); } else if (!strcasecmp(key, "CIS")) { if (var != DBUS_TYPE_BYTE) goto fail; - dbus_message_iter_get_basic(&value, &qos->cis_id); + dbus_message_iter_get_basic(&value, &qos->ucast.cis_id); } else if (!strcasecmp(key, "Interval")) { if (var != DBUS_TYPE_UINT32) goto fail; - dbus_message_iter_get_basic(&value, &qos->interval); + dbus_message_iter_get_basic(&value, &io_qos.interval); } else if (!strcasecmp(key, "Framing")) { dbus_bool_t val; @@ -301,7 +302,7 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps, dbus_message_iter_get_basic(&value, &val); - qos->framing = val; + qos->ucast.framing = val; } else if (!strcasecmp(key, "PHY")) { const char *str; @@ -311,42 +312,43 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps, dbus_message_iter_get_basic(&value, &str); if (!strcasecmp(str, "1M")) - qos->phy = 0x01; + io_qos.phy = 0x01; else if (!strcasecmp(str, "2M")) - qos->phy = 0x02; + io_qos.phy = 0x02; else goto fail; } else if (!strcasecmp(key, "SDU")) { if (var != DBUS_TYPE_UINT16) goto fail; - dbus_message_iter_get_basic(&value, &qos->sdu); + dbus_message_iter_get_basic(&value, &io_qos.sdu); } else if (!strcasecmp(key, "Retransmissions")) { if (var != DBUS_TYPE_BYTE) goto fail; - dbus_message_iter_get_basic(&value, &qos->rtn); + dbus_message_iter_get_basic(&value, &io_qos.rtn); } else if (!strcasecmp(key, "Latency")) { if (var != DBUS_TYPE_UINT16) goto fail; - dbus_message_iter_get_basic(&value, &qos->latency); + dbus_message_iter_get_basic(&value, &io_qos.latency); } else if (!strcasecmp(key, "Delay")) { if (var != DBUS_TYPE_UINT32) goto fail; - dbus_message_iter_get_basic(&value, &qos->delay); + dbus_message_iter_get_basic(&value, &qos->ucast.delay); } else if (!strcasecmp(key, "TargetLatency")) { if (var != DBUS_TYPE_BYTE) goto fail; dbus_message_iter_get_basic(&value, - &qos->target_latency); + &qos->ucast.target_latency); } dbus_message_iter_next(props); } + memcpy(&qos->ucast.io_qos, &io_qos, sizeof(io_qos)); return 0; fail: @@ -456,8 +458,8 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg, } /* Mark CIG and CIS to be auto assigned */ - ep->qos.cig_id = BT_ISO_QOS_CIG_UNSET; - ep->qos.cis_id = BT_ISO_QOS_CIS_UNSET; + ep->qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET; + ep->qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET; if (parse_properties(&props, &ep->caps, &ep->metadata, &ep->qos) < 0) { DBG("Unable to parse properties"); @@ -734,11 +736,11 @@ static void bap_iso_qos(struct bt_bap_qos *qos, struct bt_iso_io_qos *io) if (!qos) return; - io->interval = qos->interval; - io->latency = qos->latency; - io->sdu = qos->sdu; - io->phy = qos->phy; - io->rtn = qos->rtn; + io->interval = qos->ucast.io_qos.interval; + io->latency = qos->ucast.io_qos.latency; + io->sdu = qos->ucast.io_qos.sdu; + io->phy = qos->ucast.io_qos.phy; + io->rtn = qos->ucast.io_qos.rtn; } static bool match_stream_qos(const void *data, const void *user_data) @@ -749,10 +751,10 @@ static bool match_stream_qos(const void *data, const void *user_data) qos = bt_bap_stream_get_qos((void *)stream); - if (iso_qos->ucast.cig != qos->cig_id) + if (iso_qos->ucast.cig != qos->ucast.cig_id) return false; - return iso_qos->ucast.cis == qos->cis_id; + return iso_qos->ucast.cis == qos->ucast.cis_id; } static void iso_confirm_cb(GIOChannel *io, void *user_data) @@ -993,8 +995,10 @@ static void bap_create_io(struct bap_data *data, struct bap_ep *ep, } memset(&iso_qos, 0, sizeof(iso_qos)); - iso_qos.ucast.cig = qos[0] ? qos[0]->cig_id : qos[1]->cig_id; - iso_qos.ucast.cis = qos[0] ? qos[0]->cis_id : qos[1]->cis_id; + iso_qos.ucast.cig = qos[0] ? qos[0]->ucast.cig_id : + qos[1]->ucast.cig_id; + iso_qos.ucast.cis = qos[0] ? qos[0]->ucast.cis_id : + qos[1]->ucast.cis_id; bap_iso_qos(qos[0], &iso_qos.ucast.in); bap_iso_qos(qos[1], &iso_qos.ucast.out); @@ -1179,8 +1183,8 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd, g_io_channel_set_close_on_unref(io, FALSE); /* Attempt to get CIG/CIS if they have not been set */ - if (ep->qos.cig_id == BT_ISO_QOS_CIG_UNSET || - ep->qos.cis_id == BT_ISO_QOS_CIS_UNSET) { + if (ep->qos.ucast.cig_id == BT_ISO_QOS_CIG_UNSET || + ep->qos.ucast.cis_id == BT_ISO_QOS_CIS_UNSET) { struct bt_iso_qos qos; GError *err = NULL; @@ -1192,12 +1196,12 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd, return; } - ep->qos.cig_id = qos.ucast.cig; - ep->qos.cis_id = qos.ucast.cis; + ep->qos.ucast.cig_id = qos.ucast.cig; + ep->qos.ucast.cis_id = qos.ucast.cis; } DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd, - ep->qos.cig_id, ep->qos.cis_id); + ep->qos.ucast.cig_id, ep->qos.ucast.cis_id); } static void bap_attached(struct bt_bap *bap, void *user_data) diff --git a/profiles/audio/media.c b/profiles/audio/media.c index 6ce668e31..515263af3 100644 --- a/profiles/audio/media.c +++ b/profiles/audio/media.c @@ -6,7 +6,7 @@ * Copyright (C) 2006-2007 Nokia Corporation * Copyright (C) 2004-2009 Marcel Holtmann * Copyright (C) 2011 BMW Car IT GmbH. All rights reserved. - * + * Copyright 2023 NXP * */ @@ -748,7 +748,10 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec *caps, struct bt_bap_qos *qos) { const char *key; + struct bt_bap_io_qos io_qos; + uint8_t framing = 0; + memset(&io_qos, 0, sizeof(io_qos)); while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) { DBusMessageIter value, entry; int var; @@ -777,17 +780,17 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec *caps, if (var != DBUS_TYPE_BYTE) goto fail; - dbus_message_iter_get_basic(&value, &qos->cig_id); + dbus_message_iter_get_basic(&value, &qos->ucast.cig_id); } else if (!strcasecmp(key, "CIS")) { if (var != DBUS_TYPE_BYTE) goto fail; - dbus_message_iter_get_basic(&value, &qos->cis_id); + dbus_message_iter_get_basic(&value, &qos->ucast.cis_id); } else if (!strcasecmp(key, "Interval")) { if (var != DBUS_TYPE_UINT32) goto fail; - dbus_message_iter_get_basic(&value, &qos->interval); + dbus_message_iter_get_basic(&value, &io_qos.interval); } else if (!strcasecmp(key, "Framing")) { dbus_bool_t val; @@ -796,7 +799,7 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec *caps, dbus_message_iter_get_basic(&value, &val); - qos->framing = val; + framing = val; } else if (!strcasecmp(key, "PHY")) { const char *str; @@ -806,42 +809,44 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec *caps, dbus_message_iter_get_basic(&value, &str); if (!strcasecmp(str, "1M")) - qos->phy = 0x01; + io_qos.phy = 0x01; else if (!strcasecmp(str, "2M")) - qos->phy = 0x02; + io_qos.phy = 0x02; else goto fail; } else if (!strcasecmp(key, "SDU")) { if (var != DBUS_TYPE_UINT16) goto fail; - dbus_message_iter_get_basic(&value, &qos->sdu); + dbus_message_iter_get_basic(&value, &io_qos.sdu); } else if (!strcasecmp(key, "Retransmissions")) { if (var != DBUS_TYPE_BYTE) goto fail; - dbus_message_iter_get_basic(&value, &qos->rtn); + dbus_message_iter_get_basic(&value, &io_qos.rtn); } else if (!strcasecmp(key, "Latency")) { if (var != DBUS_TYPE_UINT16) goto fail; - dbus_message_iter_get_basic(&value, &qos->latency); + dbus_message_iter_get_basic(&value, &io_qos.latency); } else if (!strcasecmp(key, "Delay")) { if (var != DBUS_TYPE_UINT32) goto fail; - dbus_message_iter_get_basic(&value, &qos->delay); + dbus_message_iter_get_basic(&value, &qos->ucast.delay); } else if (!strcasecmp(key, "TargetLatency")) { if (var != DBUS_TYPE_BYTE) goto fail; dbus_message_iter_get_basic(&value, - &qos->target_latency); + &qos->ucast.target_latency); } dbus_message_iter_next(props); } + memcpy(&qos->ucast.io_qos, &io_qos, sizeof(io_qos)); + qos->ucast.framing = framing; return 0; fail: @@ -875,8 +880,8 @@ static void pac_select_cb(struct media_endpoint *endpoint, void *ret, int size, memset(&qos, 0, sizeof(qos)); /* Mark CIG and CIS to be auto assigned */ - qos.cig_id = BT_ISO_QOS_CIG_UNSET; - qos.cis_id = BT_ISO_QOS_CIS_UNSET; + qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET; + qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET; memset(&caps, 0, sizeof(caps)); memset(&meta, 0, sizeof(meta)); diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c index 9172d167e..82f5fa6fe 100644 --- a/profiles/audio/transport.c +++ b/profiles/audio/transport.c @@ -5,6 +5,7 @@ * * Copyright (C) 2006-2007 Nokia Corporation * Copyright (C) 2004-2009 Marcel Holtmann + * Copyright 2023 NXP * * */ @@ -828,7 +829,7 @@ static gboolean qos_exists(const GDBusPropertyTable *property, void *data) struct media_transport *transport = data; struct bap_transport *bap = transport->data; - return bap->qos.phy != 0x00; + return bap->qos.ucast.io_qos.phy != 0x00; } static gboolean get_cig(const GDBusPropertyTable *property, @@ -838,7 +839,7 @@ static gboolean get_cig(const GDBusPropertyTable *property, struct bap_transport *bap = transport->data; dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, - &bap->qos.cig_id); + &bap->qos.ucast.cig_id); return TRUE; } @@ -850,7 +851,7 @@ static gboolean get_cis(const GDBusPropertyTable *property, struct bap_transport *bap = transport->data; dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, - &bap->qos.cis_id); + &bap->qos.ucast.cis_id); return TRUE; } @@ -862,7 +863,7 @@ static gboolean get_interval(const GDBusPropertyTable *property, struct bap_transport *bap = transport->data; dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, - &bap->qos.interval); + &bap->qos.ucast.io_qos.interval); return TRUE; } @@ -872,7 +873,7 @@ static gboolean get_framing(const GDBusPropertyTable *property, { struct media_transport *transport = data; struct bap_transport *bap = transport->data; - dbus_bool_t val = bap->qos.framing; + dbus_bool_t val = bap->qos.ucast.framing; dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val); @@ -885,7 +886,8 @@ static gboolean get_phy(const GDBusPropertyTable *property, struct media_transport *transport = data; struct bap_transport *bap = transport->data; - dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.phy); + dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, + &bap->qos.ucast.io_qos.phy); return TRUE; } @@ -896,7 +898,8 @@ static gboolean get_sdu(const GDBusPropertyTable *property, struct media_transport *transport = data; struct bap_transport *bap = transport->data; - dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &bap->qos.sdu); + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, + &bap->qos.ucast.io_qos.sdu); return TRUE; } @@ -907,7 +910,8 @@ static gboolean get_retransmissions(const GDBusPropertyTable *property, struct media_transport *transport = data; struct bap_transport *bap = transport->data; - dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.rtn); + dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, + &bap->qos.ucast.io_qos.rtn); return TRUE; } @@ -919,7 +923,7 @@ static gboolean get_latency(const GDBusPropertyTable *property, struct bap_transport *bap = transport->data; dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, - &bap->qos.latency); + &bap->qos.ucast.io_qos.latency); return TRUE; } @@ -930,7 +934,8 @@ static gboolean get_delay(const GDBusPropertyTable *property, struct media_transport *transport = data; struct bap_transport *bap = transport->data; - dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &bap->qos.delay); + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, + &bap->qos.ucast.delay); return TRUE; } diff --git a/src/shared/bap.c b/src/shared/bap.c index 7e597c662..05d814cb0 100644 --- a/src/shared/bap.c +++ b/src/shared/bap.c @@ -4,6 +4,7 @@ * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2022 Intel Corporation. All rights reserved. + * Copyright 2023 NXP * */ @@ -861,15 +862,15 @@ static void stream_notify_qos(struct bt_bap_stream *stream) status->state = ep->state; qos = (void *)status->params; - qos->cis_id = stream->qos.cis_id; - qos->cig_id = stream->qos.cig_id; - put_le24(stream->qos.interval, qos->interval); - qos->framing = stream->qos.framing; - qos->phy = stream->qos.phy; - qos->sdu = cpu_to_le16(stream->qos.sdu); - qos->rtn = stream->qos.rtn; - qos->latency = cpu_to_le16(stream->qos.latency); - put_le24(stream->qos.delay, qos->pd); + qos->cis_id = stream->qos.ucast.cis_id; + qos->cig_id = stream->qos.ucast.cig_id; + put_le24(stream->qos.ucast.io_qos.interval, qos->interval); + qos->framing = stream->qos.ucast.framing; + qos->phy = stream->qos.ucast.io_qos.phy; + qos->sdu = cpu_to_le16(stream->qos.ucast.io_qos.sdu); + qos->rtn = stream->qos.ucast.io_qos.rtn; + qos->latency = cpu_to_le16(stream->qos.ucast.io_qos.latency); + put_le24(stream->qos.ucast.delay, qos->pd); gatt_db_attribute_notify(ep->attr, (void *) status, len, bt_bap_get_att(stream->bap)); @@ -898,8 +899,8 @@ static void stream_notify_metadata(struct bt_bap_stream *stream) status->state = ep->state; meta = (void *)status->params; - meta->cis_id = stream->qos.cis_id; - meta->cig_id = stream->qos.cig_id; + meta->cis_id = stream->qos.ucast.cis_id; + meta->cig_id = stream->qos.ucast.cig_id; if (stream->meta) { meta->len = stream->meta->iov_len; @@ -1575,20 +1576,22 @@ static uint8_t ascs_qos(struct bt_ascs *ascs, struct bt_bap *bap, memset(&qos, 0, sizeof(qos)); - qos.cig_id = req->cig; - qos.cis_id = req->cis; - qos.interval = get_le24(req->interval); - qos.framing = req->framing; - qos.phy = req->phy; - qos.sdu = le16_to_cpu(req->sdu); - qos.rtn = req->rtn; - qos.latency = le16_to_cpu(req->latency); - qos.delay = get_le24(req->pd); + qos.ucast.cig_id = req->cig; + qos.ucast.cis_id = req->cis; + qos.ucast.io_qos.interval = get_le24(req->interval); + qos.ucast.framing = req->framing; + qos.ucast.io_qos.phy = req->phy; + qos.ucast.io_qos.sdu = le16_to_cpu(req->sdu); + qos.ucast.io_qos.rtn = req->rtn; + qos.ucast.io_qos.latency = le16_to_cpu(req->latency); + qos.ucast.delay = get_le24(req->pd); DBG(bap, "CIG 0x%02x CIS 0x%02x interval %u framing 0x%02x " "phy 0x%02x SDU %u rtn %u latency %u pd %u", - req->cig, req->cis, qos.interval, qos.framing, qos.phy, - qos.sdu, qos.rtn, qos.latency, qos.delay); + req->cig, req->cis, qos.ucast.io_qos.interval, + qos.ucast.framing, qos.ucast.io_qos.phy, + qos.ucast.io_qos.sdu, qos.ucast.io_qos.rtn, + qos.ucast.io_qos.latency, qos.ucast.delay); ep = bap_get_local_endpoint_id(bap, req->ase); if (!ep) { @@ -3283,13 +3286,13 @@ static void ep_status_qos(struct bt_bap *bap, struct bt_bap_endpoint *ep, if (!ep->stream) return; - ep->stream->qos.interval = interval; - ep->stream->qos.framing = qos->framing; - ep->stream->qos.phy = qos->phy; - ep->stream->qos.sdu = sdu; - ep->stream->qos.rtn = qos->rtn; - ep->stream->qos.latency = latency; - ep->stream->qos.delay = pd; + ep->stream->qos.ucast.io_qos.interval = interval; + ep->stream->qos.ucast.framing = qos->framing; + ep->stream->qos.ucast.io_qos.phy = qos->phy; + ep->stream->qos.ucast.io_qos.sdu = sdu; + ep->stream->qos.ucast.io_qos.rtn = qos->rtn; + ep->stream->qos.ucast.io_qos.latency = latency; + ep->stream->qos.ucast.delay = pd; if (ep->old_state == BT_ASCS_ASE_STATE_CONFIG) bap_stream_config_cfm(ep->stream); @@ -4189,8 +4192,8 @@ unsigned int bt_bap_stream_config(struct bt_bap_stream *stream, memset(&config, 0, sizeof(config)); config.ase = stream->ep->id; - config.latency = qos->target_latency; - config.phy = qos->phy; + config.latency = qos->ucast.target_latency; + config.phy = qos->ucast.io_qos.phy; config.codec = stream->rpac->codec; iov[0].iov_base = &config; @@ -4372,15 +4375,15 @@ unsigned int bt_bap_stream_qos(struct bt_bap_stream *stream, /* TODO: Figure out how to pass these values around */ qos.ase = stream->ep->id; - qos.cig = data->cig_id; - qos.cis = data->cis_id; - put_le24(data->interval, qos.interval); - qos.framing = data->framing; - qos.phy = data->phy; - qos.sdu = cpu_to_le16(data->sdu); - qos.rtn = data->rtn; - qos.latency = cpu_to_le16(data->latency); - put_le24(data->delay, qos.pd); + qos.cig = data->ucast.cig_id; + qos.cis = data->ucast.cis_id; + put_le24(data->ucast.io_qos.interval, qos.interval); + qos.framing = data->ucast.framing; + qos.phy = data->ucast.io_qos.phy; + qos.sdu = cpu_to_le16(data->ucast.io_qos.sdu); + qos.rtn = data->ucast.io_qos.rtn; + qos.latency = cpu_to_le16(data->ucast.io_qos.latency); + put_le24(data->ucast.delay, qos.pd); iov.iov_base = &qos; iov.iov_len = sizeof(qos); @@ -4784,8 +4787,8 @@ int bt_bap_stream_io_link(struct bt_bap_stream *stream, return -EALREADY; if (stream->client != link->client || - stream->qos.cig_id != link->qos.cig_id || - stream->qos.cis_id != link->qos.cis_id) + stream->qos.ucast.cig_id != link->qos.ucast.cig_id || + stream->qos.ucast.cis_id != link->qos.ucast.cis_id) return -EINVAL; if (!stream->links) @@ -4822,7 +4825,7 @@ static void bap_stream_get_in_qos(void *data, void *user_data) struct bt_bap_qos **qos = user_data; if (!qos || *qos || stream->ep->dir != BT_BAP_SOURCE || - !stream->qos.sdu) + !stream->qos.ucast.io_qos.sdu) return; *qos = &stream->qos; @@ -4833,7 +4836,8 @@ static void bap_stream_get_out_qos(void *data, void *user_data) struct bt_bap_stream *stream = data; struct bt_bap_qos **qos = user_data; - if (!qos || *qos || stream->ep->dir != BT_BAP_SINK || !stream->qos.sdu) + if (!qos || *qos || stream->ep->dir != BT_BAP_SINK || + !stream->qos.ucast.io_qos.sdu) return; *qos = &stream->qos; diff --git a/src/shared/bap.h b/src/shared/bap.h index e9f769d0e..0c42e730f 100644 --- a/src/shared/bap.h +++ b/src/shared/bap.h @@ -4,6 +4,7 @@ * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2022 Intel Corporation. All rights reserved. + * Copyright 2023 NXP * */ @@ -49,17 +50,46 @@ struct bt_ltv { uint8_t value[0]; } __packed; -struct bt_bap_qos { +struct bt_bap_io_qos { + uint32_t interval; /* Frame interval */ + uint16_t latency; /* Transport Latency */ + uint16_t sdu; /* Maximum SDU Size */ + uint8_t phy; /* PHY */ + uint8_t rtn; /* Retransmission Effort */ +}; + +struct bt_bap_ucast_qos { uint8_t cig_id; uint8_t cis_id; - uint32_t interval; /* Frame interval */ uint8_t framing; /* Frame framing */ - uint8_t phy; /* PHY */ - uint16_t sdu; /* Maximum SDU Size */ - uint8_t rtn; /* Retransmission Effort */ - uint16_t latency; /* Transport Latency */ uint32_t delay; /* Presentation Delay */ uint8_t target_latency; /* Target Latency */ + struct bt_bap_io_qos io_qos; +}; + +struct bt_bap_bcast_qos { + uint8_t big; + uint8_t bis; + uint8_t sync_interval; + uint8_t packing; + uint8_t framing; + uint8_t encryption; + struct iovec bcode; + uint8_t options; + uint16_t skip; + uint16_t sync_timeout; + uint8_t sync_cte_type; + uint8_t mse; + uint16_t timeout; + uint8_t pa_sync; + struct bt_bap_io_qos io_qos; +}; + +struct bt_bap_qos { + union { + struct bt_bap_ucast_qos ucast; + struct bt_bap_bcast_qos bcast; + }; }; typedef void (*bt_bap_ready_func_t)(struct bt_bap *bap, void *user_data); diff --git a/unit/test-bap.c b/unit/test-bap.c index bf525742d..adade07db 100644 --- a/unit/test-bap.c +++ b/unit/test-bap.c @@ -712,12 +712,15 @@ static void test_disc(void) #define QOS_BALANCED_2M \ { \ .target_latency = BT_BAP_CONFIG_LATENCY_BALANCED, \ - .phy = BT_BAP_CONFIG_PHY_2M, \ + .io_qos.phy = BT_BAP_CONFIG_PHY_2M, \ } - +#define QOS_UCAST \ +{\ + .ucast = QOS_BALANCED_2M, \ +} static struct test_config cfg_snk_8_1 = { .cc = LC3_CONFIG_8_1, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -727,7 +730,7 @@ static struct test_config cfg_snk_8_1 = { static struct test_config cfg_snk_8_2 = { .cc = LC3_CONFIG_8_2, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -737,7 +740,7 @@ static struct test_config cfg_snk_8_2 = { static struct test_config cfg_snk_16_1 = { .cc = LC3_CONFIG_16_1, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -747,7 +750,7 @@ static struct test_config cfg_snk_16_1 = { static struct test_config cfg_snk_16_2 = { .cc = LC3_CONFIG_16_2, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -757,7 +760,7 @@ static struct test_config cfg_snk_16_2 = { static struct test_config cfg_snk_24_1 = { .cc = LC3_CONFIG_24_1, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -767,7 +770,7 @@ static struct test_config cfg_snk_24_1 = { static struct test_config cfg_snk_24_2 = { .cc = LC3_CONFIG_24_2, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -777,7 +780,7 @@ static struct test_config cfg_snk_24_2 = { static struct test_config cfg_snk_32_1 = { .cc = LC3_CONFIG_32_1, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -787,7 +790,7 @@ static struct test_config cfg_snk_32_1 = { static struct test_config cfg_snk_32_2 = { .cc = LC3_CONFIG_32_2, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -797,7 +800,7 @@ static struct test_config cfg_snk_32_2 = { static struct test_config cfg_snk_44_1 = { .cc = LC3_CONFIG_44_1, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -807,7 +810,7 @@ static struct test_config cfg_snk_44_1 = { static struct test_config cfg_snk_44_2 = { .cc = LC3_CONFIG_44_2, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -817,7 +820,7 @@ static struct test_config cfg_snk_44_2 = { static struct test_config cfg_snk_48_1 = { .cc = LC3_CONFIG_48_1, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -827,7 +830,7 @@ static struct test_config cfg_snk_48_1 = { static struct test_config cfg_snk_48_2 = { .cc = LC3_CONFIG_48_2, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -837,7 +840,7 @@ static struct test_config cfg_snk_48_2 = { static struct test_config cfg_snk_48_3 = { .cc = LC3_CONFIG_48_3, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -847,7 +850,7 @@ static struct test_config cfg_snk_48_3 = { static struct test_config cfg_snk_48_4 = { .cc = LC3_CONFIG_48_4, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -857,7 +860,7 @@ static struct test_config cfg_snk_48_4 = { static struct test_config cfg_snk_48_5 = { .cc = LC3_CONFIG_48_5, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -867,7 +870,7 @@ static struct test_config cfg_snk_48_5 = { static struct test_config cfg_snk_48_6 = { .cc = LC3_CONFIG_48_6, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, }; @@ -899,7 +902,7 @@ static struct test_config cfg_snk_48_6 = { static struct test_config cfg_src_8_1 = { .cc = LC3_CONFIG_8_1, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -909,7 +912,7 @@ static struct test_config cfg_src_8_1 = { static struct test_config cfg_src_8_2 = { .cc = LC3_CONFIG_8_2, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -919,7 +922,7 @@ static struct test_config cfg_src_8_2 = { static struct test_config cfg_src_16_1 = { .cc = LC3_CONFIG_16_1, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -929,7 +932,7 @@ static struct test_config cfg_src_16_1 = { static struct test_config cfg_src_16_2 = { .cc = LC3_CONFIG_16_2, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -939,7 +942,7 @@ static struct test_config cfg_src_16_2 = { static struct test_config cfg_src_24_1 = { .cc = LC3_CONFIG_24_1, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -949,7 +952,7 @@ static struct test_config cfg_src_24_1 = { static struct test_config cfg_src_24_2 = { .cc = LC3_CONFIG_24_2, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -959,7 +962,7 @@ static struct test_config cfg_src_24_2 = { static struct test_config cfg_src_32_1 = { .cc = LC3_CONFIG_32_1, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -969,7 +972,7 @@ static struct test_config cfg_src_32_1 = { static struct test_config cfg_src_32_2 = { .cc = LC3_CONFIG_32_2, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -979,7 +982,7 @@ static struct test_config cfg_src_32_2 = { static struct test_config cfg_src_44_1 = { .cc = LC3_CONFIG_44_1, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -989,7 +992,7 @@ static struct test_config cfg_src_44_1 = { static struct test_config cfg_src_44_2 = { .cc = LC3_CONFIG_44_2, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -999,7 +1002,7 @@ static struct test_config cfg_src_44_2 = { static struct test_config cfg_src_48_1 = { .cc = LC3_CONFIG_48_1, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -1009,7 +1012,7 @@ static struct test_config cfg_src_48_1 = { static struct test_config cfg_src_48_2 = { .cc = LC3_CONFIG_48_2, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -1019,7 +1022,7 @@ static struct test_config cfg_src_48_2 = { static struct test_config cfg_src_48_3 = { .cc = LC3_CONFIG_48_3, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -1029,7 +1032,7 @@ static struct test_config cfg_src_48_3 = { static struct test_config cfg_src_48_4 = { .cc = LC3_CONFIG_48_4, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -1039,7 +1042,7 @@ static struct test_config cfg_src_48_4 = { static struct test_config cfg_src_48_5 = { .cc = LC3_CONFIG_48_5, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -1049,7 +1052,7 @@ static struct test_config cfg_src_48_5 = { static struct test_config cfg_src_48_6 = { .cc = LC3_CONFIG_48_6, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, }; @@ -1141,7 +1144,7 @@ static void test_scc_cc_lc3(void) static struct test_config cfg_snk_vs = { .cc = IOV_NULL, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .snk = true, .vs = true, }; @@ -1155,7 +1158,7 @@ static struct test_config cfg_snk_vs = { static struct test_config cfg_src_vs = { .cc = IOV_NULL, - .qos = QOS_BALANCED_2M, + .qos = QOS_UCAST, .src = true, .vs = true, }; From patchwork Wed Jun 7 08:22:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Silviu Florian Barbulescu X-Patchwork-Id: 690635 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 37CE4C7EE43 for ; Wed, 7 Jun 2023 08:23:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239105AbjFGIXZ (ORCPT ); Wed, 7 Jun 2023 04:23:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34806 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239059AbjFGIXX (ORCPT ); Wed, 7 Jun 2023 04:23:23 -0400 Received: from EUR01-VE1-obe.outbound.protection.outlook.com (mail-ve1eur01on2040.outbound.protection.outlook.com [40.107.14.40]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1427E184 for ; Wed, 7 Jun 2023 01:23:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=J87oWInsV6EUX/bCNTBhMWYdQT1n0yRxkuMik4fcjfWNsynuH54cTkyLcqlNY2S6iLrgwoFvoSAtEq87NRGCuTQ/2W1ieFubQvlZmmprvJppCs5f+IRos+yTWM+EQV3RCArIjy582Tz5Jl0Oays51gtf2XjdR4jTNp8868BKlZ2IgVL10jk4Y+smqkKlaBpl4XjhxYQBpd7MWb77T/A4ivSmnNS6fwQ+Hdx+QKjYX6bqgtdxra1H+uwS67kUp7BFMHl2Up7iPODnXuB1pG4OdSO5nJStgAfsCxZ7Bq5SRwaVxlXf5/CnlldU8OYcWAc+owndASdYeGuu3pdwIBQkCw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Be/fnW6tNqM9MDxSHc0sGJX78kUsjaVpfLyV3j2t5ps=; b=JaFihHNiu2OWJC18hKKwIWYMhMnupD3xC3wIjNWwQSsFZirKLs/Mb2N/PX4aRSx1ugaced69dDun2qCT/SJ5xOFhNt8SbEh0EMpla/3h1HMbYeOyTcYh8mjqMY2vfpIZH83YtvRlqoizhJ1cqgGySsB7EGnly3gnHFlSm02mF0Gc82/WWMs3B5z3ba1eDVsvnDOIuXwLULjT/TgiIcMpzc/1X8n87sxE9VvodE2sBP4pelgtOwKahPb6QaZfstrQxxjA1iPPetl+bqzq7A59ERNo3fvIxor3HN8qAOQCNZVS1BPKUWdstjvj//KxXqiJvZV/2AsUQLZpwun+zfg+4A== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass header.d=nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Be/fnW6tNqM9MDxSHc0sGJX78kUsjaVpfLyV3j2t5ps=; b=qDWg/dQ5ACP+f7Rxgib+iF56eXYjYUgu+ScDOue35IT+wIba+8PpSTZr8EgHJwdX2K/lHvOS2J/ZDT/KHluAwlS3ycKcgL5BGHIGd/2I/LGujyNVkgKF+2qm1F2e2v+dcp2Fa+xsuUeqWTJHWikhReVCJFP7YmJRz8G6RfzQPhI= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from VI1PR04MB5344.eurprd04.prod.outlook.com (2603:10a6:803:4b::31) by DB8PR04MB7114.eurprd04.prod.outlook.com (2603:10a6:10:fe::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6455.32; Wed, 7 Jun 2023 08:23:18 +0000 Received: from VI1PR04MB5344.eurprd04.prod.outlook.com ([fe80::e8eb:cac:f3e3:1085]) by VI1PR04MB5344.eurprd04.prod.outlook.com ([fe80::e8eb:cac:f3e3:1085%4]) with mapi id 15.20.6455.030; Wed, 7 Jun 2023 08:23:18 +0000 From: Silviu Florian Barbulescu To: linux-bluetooth@vger.kernel.org Cc: Silviu Florian Barbulescu Subject: [PATCH v4 2/4] Update bluetoothctl with support for broadcast source Date: Wed, 7 Jun 2023 11:22:58 +0300 Message-Id: <20230607082300.4970-3-silviu.barbulescu@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230607082300.4970-1-silviu.barbulescu@nxp.com> References: <20230607082300.4970-1-silviu.barbulescu@nxp.com> X-ClientProxiedBy: AM4PR0101CA0083.eurprd01.prod.exchangelabs.com (2603:10a6:200:41::51) To VI1PR04MB5344.eurprd04.prod.outlook.com (2603:10a6:803:4b::31) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: VI1PR04MB5344:EE_|DB8PR04MB7114:EE_ X-MS-Office365-Filtering-Correlation-Id: 85417808-a3f5-4b54-aec5-08db673072b1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: RsYJAp4O9cG2ClhocUQi5/NvtYSLEfR/seJW+ZX6y22AezRdaLDDA1T4W7Y9p0QNvDjlK0eYPPF9WBO4E7e9zNXDyz5RBaSdE2WJh4zyGhbgHmVrT9rv7SmZUlIoeXxUleaEL6bDuLxmZ8oyIHQzSPqzMRbItun6icxH916PGsCn1xAmBT8Ur0LtQUHNwvnpf/X0NeluN787wzyAGNr2fX/Jhzi7hJR24tEbw0/3rBCj4uIrctUZZB/+g18kE1Y2BV+FzvT4PSq0qcJ62Bh7kQzYbCX4cNYijvSO+70EYUezRGISELwR67W/zCN0brRV6NC2bRQh4gT9yO5G9tF8waqc7DBcutWuL1Vl+rZ3KDU/Q+FegXzdKW3CiHEmlWD2cmhNn/VmObJw2e68AKSuWresu2JZzaS1voLvCE9AiFtt62W3y03Ce0LE1Ckiz9RTLolR6vy5KhfsYLCc9L+u/eWLV1XXc/5kqxOHNAvKDcI7vWCm4VzHVXpBC8WZgPj0hRvJN71ZqC2CRXcbnLWkGkBl2LUDoXHEIB5dXjoIz9l7oZP+h3ZJaCXudKFvJfw2Mn4B9jjwHDz/S1105Pzd0OkAtwkfKMbTo4Dp2AYZTMNe3i6UQ9/lNwIJ/H5G0kB0 X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VI1PR04MB5344.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230028)(4636009)(376002)(366004)(396003)(39860400002)(136003)(346002)(451199021)(55236004)(1076003)(6512007)(6506007)(38100700002)(2616005)(41300700001)(38350700002)(6486002)(52116002)(6666004)(186003)(26005)(83380400001)(478600001)(66556008)(6916009)(66476007)(66946007)(316002)(2906002)(8676002)(8936002)(5660300002)(4326008)(30864003)(86362001)(36756003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: BInOR6uZr9Frns83ckzOpiMmXWnZ7v6mecYL9whEuWZgM+WO+U50GiuzlZtUF12AYZhYQFRuqvTAWhiJrMCu+rzzrsm6MOPduFcT4Ul0Y3yBhzxpkG1cYhQ4TtoH5K65V/h8b+kbXTnmUhhObzplTqX8fADx5TDx+XEA1j7b28+R2rtl3NLKQjtpPvo4JE1Vf3ISo4TVTBYjsJOSAzT/2dEVQTuQFCi7wlwBXW8sfI5lrWcu1y+lNgvMTTjmlO5EzeBFo7VcnEMn1S2XIy0hclkYj8eRenaJ1tZmgp3s6AWjDsec+pmQVgUjuZVxwC+wOvhx1VC1DMtngjJvk6eePCTCefy0s9hQ/SLyl68meDGepNHp2YpfW+658fBOIlJ9/wjZAEGj5B42Q+AJFf5qmZnfeDyM1mgkLeue+bDA5Rfbg3qjzuCaZhKp76fAGu+LPnb7ZxbsV8VHMi3EwY806pPplzmYmHRsL0pQUgxcOfxb2c8NzTex85fd5H1WqBBFq5lsvH5h50x+pwDS93UrbBV4nSEC/5H0Y2mxXM3yHBhkbfgVwEy3nUmy8PW4j9gEu7Mjqa+xUPfxxMOvEF6oSbWWP2wz4eEee4U1xG9oS+7R6kIdY2LEjV1gAI4CAcq+7Qc9R7L3GqcNso4nrQT1JJkQhJFy/devAzEnjrNZcVeXrecR5BeYSMarQ7koRo0WQDV+ILkDPs0HLmpiyHclbKZp30qlrVlfG3J9bRaebfre7tYgAzkxiDjf5NJw6NzZfyJVTOuVCmR47pyZKZgsQaj8OO2eR/NsMb1j+MGcCyGQD5pMKTG/PEvIovXQ8DYxVRwTzHOEpTQwTZ7FLDJCFM5+xAxj5mHq5DAnGv7kSeqHx17KUaVONZ576oIUWz2wMchzERsepPwciBz0ef6nzaa8VsRf1ukLAb19OGUIwxcWi89q+QuqP7SBkjv0xueNFkbI/aJ1l1J3rtwtnr1rUprCpNhUYPEHuIjnzgCsYWIfcPeaV73tX8SqsdFXL6mhnRnQLKgSP5hrGJ+NAmzrzIPztHnygcFw+Ld33LvpAHO23JvFXs0znNc1QUWqwT8ViC7bBGcKH6QIVN3wpbWS7f2eK9+76qWwl4JMxgDN3noFlFHkh1L31QSB5r3ITh52csCmvPgGhhEJKIumHYFc3QxjNRMGGl5PQQndIq+aQiEe+qs91OT0xRRCzuqrzHGRYk1y6WyXxtGVfkJNqQBmRh0fvb8MmQkQi8+kKCCfF7xQ6HYrVhxWCHrHHiByMlNOdtnYwt/WgK2T3BZ6Ka4xfMhfidVxK5p80Cm3nVn1htJgDB5sUg+DF016qW3N/zUExcfR8nlHnXjOeHTewr7Aeugf1UNY1Xxx2IxS0hPU4ohKfVFeZWi0JgWqLaN2qgLuHba6lHmj9tmEoiPdX0cY4ov2v4HI8QPo8v6GWZcN7GO2rSRSgUmUhH7eOhrHKStkUFkIitxWh0B/AFZUSoi7A3gg6KfCVvZDvC4Ze/60TizDkgN+Oqyaz47VoG6V3IGjns6ByrvKqrCfOi5cdWSBIV8l/dtFR5oJpdZdLLoCE1QfsjNRK06i/IY2dJ/CAvIjD4BQcwfNcXZZMGbw6qEIDA== X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 85417808-a3f5-4b54-aec5-08db673072b1 X-MS-Exchange-CrossTenant-AuthSource: VI1PR04MB5344.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Jun 2023 08:23:18.5110 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: aXI8JqEGXEdaFJdU3FtstOTCLATXBt5qU5Jl9muBiO4dXHahfyIde+DsKHiIPDBbk3roTp53RJeGjl52bHvoZ7V0H53HLh+VLsfHm2eJ+jA= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR04MB7114 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This adds bluetoothctl support for broadcast source. To test the current implementation use bluetoothctl with the commands: endpoint.register 00001852-0000-1000-8000-00805f9b34fb 0x06 endpoint.config 16_2_1 transport.acquire transport.send --- client/player.c | 226 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 201 insertions(+), 25 deletions(-) diff --git a/client/player.c b/client/player.c index a9f56fb94..389fc1d07 100644 --- a/client/player.c +++ b/client/player.c @@ -74,11 +74,13 @@ struct endpoint { bool auto_accept; bool acquiring; uint8_t max_transports; - uint8_t cig; - uint8_t cis; + uint8_t iso_group; + uint8_t iso_stream; char *transport; DBusMessage *msg; struct preset *preset; + bool broadcast; + struct iovec *bcode; }; static DBusConnection *dbus_conn; @@ -104,6 +106,22 @@ struct transport { struct io *timer_io; }; +static const uint8_t base_lc3_16_2_1[] = { + 0x28, 0x00, 0x00, /* Presentation Delay */ + 0x01, /* Number of Subgroups */ + 0x01, /* Number of BIS */ + 0x06, 0x00, 0x00, 0x00, 0x00, /* Code ID = LC3 (0x06) */ + 0x11, /* Codec Specific Configuration */ + 0x02, 0x01, 0x03, /* 16 KHZ */ + 0x02, 0x02, 0x01, /* 10 ms */ + 0x05, 0x03, 0x01, 0x00, 0x00, 0x00, /* Front Left */ + 0x03, 0x04, 0x28, 0x00, /* Frame Length 40 bytes */ + 0x04, /* Metadata */ + 0x03, 0x02, 0x02, 0x00, /* Audio Context: Convertional */ + 0x01, /* BIS */ + 0x00, /* Codec Specific Configuration */ +}; + static void endpoint_unregister(void *data) { struct endpoint *ep = data; @@ -1154,6 +1172,16 @@ static const struct capabilities { CODEC_CAPABILITIES(PAC_SOURCE_UUID, LC3_ID, LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY, 3u, 30, 240)), + /* Broadcast LC3 Source: + * + * Frequencies: 8Khz 11Khz 16Khz 22Khz 24Khz 32Khz 44.1Khz 48Khz + * Duration: 7.5 ms 10 ms + * Channel count: 3 + * Frame length: 30-240 + */ + CODEC_CAPABILITIES(BAA_SERVICE_UUID, LC3_ID, + LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY, + 3u, 30, 240)), }; struct codec_qos { @@ -1435,6 +1463,7 @@ static struct preset { PRESET(A2DP_SINK_UUID, A2DP_CODEC_SBC, sbc_presets, 6), PRESET(PAC_SINK_UUID, LC3_ID, lc3_presets, 3), PRESET(PAC_SOURCE_UUID, LC3_ID, lc3_presets, 3), + PRESET(BAA_SERVICE_UUID, LC3_ID, lc3_presets, 3), }; static void parse_vendor_codec(const char *codec, uint16_t *vid, uint16_t *cid) @@ -1707,6 +1736,27 @@ struct endpoint_config { const struct codec_qos *qos; }; +#define BCODE {0x01, 0x02, 0x68, 0x05, 0x53, 0xf1, 0x41, 0x5a, \ + 0xa2, 0x65, 0xbb, 0xaf, 0xc6, 0xea, 0x03, 0xb8} + +static struct bt_iso_qos bcast_qos = { + .bcast = { + .big = BT_ISO_QOS_BIG_UNSET, + .bis = BT_ISO_QOS_BIS_UNSET, + .sync_interval = 0x07, + .packing = 0x00, + .framing = 0x00, + .encryption = 0x00, + .bcode = BCODE, + .options = 0x00, + .skip = 0x0000, + .sync_timeout = 0x4000, + .sync_cte_type = 0x00, + .mse = 0x00, + .timeout = 0x4000, + } + }; + static void append_properties(DBusMessageIter *iter, struct endpoint_config *cfg) { @@ -1714,6 +1764,7 @@ static void append_properties(DBusMessageIter *iter, struct codec_qos *qos = (void *)cfg->qos; const char *key = "Capabilities"; const char *meta = "Metadata"; + const char *keyBCode = "BroadcastCode"; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict); @@ -1742,16 +1793,27 @@ static void append_properties(DBusMessageIter *iter, DBUS_TYPE_BYTE, &cfg->target_latency); } - if (cfg->ep->cig != BT_ISO_QOS_CIG_UNSET) { - bt_shell_printf("CIG 0x%2.2x\n", cfg->ep->cig); + if ((!cfg->ep->broadcast) && + (cfg->ep->iso_group != BT_ISO_QOS_GROUP_UNSET)) { + bt_shell_printf("CIG 0x%2.2x\n", cfg->ep->iso_group); g_dbus_dict_append_entry(&dict, "CIG", DBUS_TYPE_BYTE, - &cfg->ep->cig); + &cfg->ep->iso_group); + } else { + bt_shell_printf("BIG 0x%2.2x\n", bcast_qos.bcast.big); + g_dbus_dict_append_entry(&dict, "BIG", DBUS_TYPE_BYTE, + &bcast_qos.bcast.big); } - if (cfg->ep->cis != BT_ISO_QOS_CIS_UNSET) { - bt_shell_printf("CIS 0x%2.2x\n", cfg->ep->cis); + if ((!cfg->ep->broadcast) && + (cfg->ep->iso_stream != BT_ISO_QOS_STREAM_UNSET)) { + bt_shell_printf("CIS 0x%2.2x\n", cfg->ep->iso_stream); g_dbus_dict_append_entry(&dict, "CIS", DBUS_TYPE_BYTE, - &cfg->ep->cis); + &cfg->ep->iso_stream); + + } else { + bt_shell_printf("BIS 0x%2.2x\n", bcast_qos.bcast.bis); + g_dbus_dict_append_entry(&dict, "BIS", DBUS_TYPE_BYTE, + &bcast_qos.bcast.bis); } bt_shell_printf("Interval %u\n", qos->interval); @@ -1759,10 +1821,19 @@ static void append_properties(DBusMessageIter *iter, g_dbus_dict_append_entry(&dict, "Interval", DBUS_TYPE_UINT32, &qos->interval); - bt_shell_printf("Framing %s\n", qos->framing ? "true" : "false"); + if (!cfg->ep->broadcast) { + bt_shell_printf("Framing %s\n", + qos->framing ? "true" : "false"); - g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN, - &qos->framing); + g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN, + &qos->framing); + } else { + bt_shell_printf("Framing %s\n", + bcast_qos.bcast.framing ? "true" : "false"); + + g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN, + &bcast_qos.bcast.framing); + } bt_shell_printf("PHY %s\n", qos->phy); @@ -1787,6 +1858,57 @@ static void append_properties(DBusMessageIter *iter, g_dbus_dict_append_entry(&dict, "Delay", DBUS_TYPE_UINT32, &qos->delay); + if (!cfg->ep->broadcast) + goto done; + + bt_shell_printf("SyncInterval %u\n", bcast_qos.bcast.sync_interval); + + g_dbus_dict_append_entry(&dict, "SyncInterval", DBUS_TYPE_BYTE, + &bcast_qos.bcast.sync_interval); + + bt_shell_printf("Encryption %u\n", bcast_qos.bcast.encryption); + + g_dbus_dict_append_entry(&dict, "Encryption", DBUS_TYPE_BYTE, + &bcast_qos.bcast.encryption); + + bt_shell_printf("Options %u\n", bcast_qos.bcast.options); + + g_dbus_dict_append_entry(&dict, "Options", DBUS_TYPE_BYTE, + &bcast_qos.bcast.options); + + bt_shell_printf("Skip %u\n", bcast_qos.bcast.skip); + + g_dbus_dict_append_entry(&dict, "Skip", DBUS_TYPE_UINT16, + &bcast_qos.bcast.skip); + + bt_shell_printf("SyncTimeout %u\n", bcast_qos.bcast.sync_timeout); + + g_dbus_dict_append_entry(&dict, "SyncTimeout", DBUS_TYPE_UINT16, + &bcast_qos.bcast.sync_timeout); + + bt_shell_printf("SyncCteType %u\n", bcast_qos.bcast.sync_cte_type); + + g_dbus_dict_append_entry(&dict, "SyncCteType", DBUS_TYPE_BYTE, + &bcast_qos.bcast.sync_cte_type); + + bt_shell_printf("MSE %u\n", bcast_qos.bcast.mse); + + g_dbus_dict_append_entry(&dict, "MSE", DBUS_TYPE_BYTE, + &bcast_qos.bcast.mse); + + bt_shell_printf("Timeout %u\n", bcast_qos.bcast.timeout); + + g_dbus_dict_append_entry(&dict, "Timeout", DBUS_TYPE_UINT16, + &bcast_qos.bcast.timeout); + + bt_shell_printf("BroadcastCode:\n"); + bt_shell_hexdump(cfg->ep->bcode->iov_base, cfg->ep->bcode->iov_len); + + g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &keyBCode, + DBUS_TYPE_BYTE, + &cfg->ep->bcode->iov_base, + cfg->ep->bcode->iov_len); + done: dbus_message_iter_close_container(iter, &dict); } @@ -2239,14 +2361,14 @@ fail: } -static void endpoint_cis(const char *input, void *user_data) +static void endpoint_iso_stream(const char *input, void *user_data) { struct endpoint *ep = user_data; char *endptr = NULL; int value; if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) { - ep->cis = BT_ISO_QOS_CIS_UNSET; + ep->iso_stream = BT_ISO_QOS_STREAM_UNSET; } else { value = strtol(input, &endptr, 0); @@ -2255,20 +2377,20 @@ static void endpoint_cis(const char *input, void *user_data) return bt_shell_noninteractive_quit(EXIT_FAILURE); } - ep->cis = value; + ep->iso_stream = value; } endpoint_register(ep); } -static void endpoint_cig(const char *input, void *user_data) +static void endpoint_iso_group(const char *input, void *user_data) { struct endpoint *ep = user_data; char *endptr = NULL; int value; if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) { - ep->cig = BT_ISO_QOS_CIG_UNSET; + ep->iso_group = BT_ISO_QOS_GROUP_UNSET; } else { value = strtol(input, &endptr, 0); @@ -2277,10 +2399,15 @@ static void endpoint_cig(const char *input, void *user_data) return bt_shell_noninteractive_quit(EXIT_FAILURE); } - ep->cig = value; + ep->iso_group = value; } - bt_shell_prompt_input(ep->path, "CIS (auto/value):", endpoint_cis, ep); + if (!ep->broadcast) + bt_shell_prompt_input(ep->path, "CIS (auto/value):", + endpoint_iso_stream, ep); + else + bt_shell_prompt_input(ep->path, "BIS (auto/value):", + endpoint_iso_stream, ep); } static void endpoint_max_transports(const char *input, void *user_data) @@ -2302,13 +2429,24 @@ static void endpoint_max_transports(const char *input, void *user_data) ep->max_transports = value; } - bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_cig, ep); + if (ep->broadcast) + bt_shell_prompt_input(ep->path, "BIG (auto/value):", + endpoint_iso_group, ep); + else + bt_shell_prompt_input(ep->path, "CIG (auto/value):", + endpoint_iso_group, ep); } static void endpoint_auto_accept(const char *input, void *user_data) { struct endpoint *ep = user_data; + if (!strcmp(ep->uuid, BAA_SERVICE_UUID)) { + ep->broadcast = true; + } else { + ep->broadcast = false; + } + if (!strcasecmp(input, "y") || !strcasecmp(input, "yes")) { ep->auto_accept = true; bt_shell_prompt_input(ep->path, "Max Transports (auto/value):", @@ -2321,7 +2459,12 @@ static void endpoint_auto_accept(const char *input, void *user_data) return bt_shell_noninteractive_quit(EXIT_FAILURE); } - bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_cig, ep); + if (ep->broadcast) + bt_shell_prompt_input(ep->path, "BIG (auto/value):", + endpoint_iso_group, ep); + else + bt_shell_prompt_input(ep->path, "CIG (auto/value):", + endpoint_iso_group, ep); } static void endpoint_set_metadata(const char *input, void *user_data) @@ -2598,9 +2741,17 @@ static void cmd_config_endpoint(int argc, char *argv[]) goto fail; } - /* Copy capabilities */ - iov_append(&cfg->caps, preset->data.iov_base, - preset->data.iov_len); + if (cfg->ep->broadcast) { + iov_append(&cfg->ep->bcode, bcast_qos.bcast.bcode, + sizeof(bcast_qos.bcast.bcode)); + /* Copy capabilities for broadcast*/ + iov_append(&cfg->caps, base_lc3_16_2_1, + sizeof(base_lc3_16_2_1)); + } else { + /* Copy capabilities */ + iov_append(&cfg->caps, preset->data.iov_base, + preset->data.iov_len); + } /* Set QoS parameters */ cfg->qos = &preset->qos; @@ -3050,8 +3201,8 @@ static void register_endpoints(GDBusProxy *proxy) ep->cid); ep->max_transports = UINT8_MAX; ep->auto_accept = true; - ep->cig = BT_ISO_QOS_CIG_UNSET; - ep->cis = BT_ISO_QOS_CIS_UNSET; + ep->iso_group = BT_ISO_QOS_GROUP_UNSET; + ep->iso_stream = BT_ISO_QOS_STREAM_UNSET; endpoint_register(ep); } } @@ -3595,6 +3746,7 @@ static void cmd_acquire_transport(int argc, char *argv[]) { GDBusProxy *proxy; int i; + struct endpoint *ep, *link; for (i = 1; i < argc; i++) { proxy = g_dbus_proxy_lookup(transports, NULL, argv[i], @@ -3610,6 +3762,30 @@ static void cmd_acquire_transport(int argc, char *argv[]) return bt_shell_noninteractive_quit(EXIT_FAILURE); } + ep = find_ep_by_transport(g_dbus_proxy_get_path(proxy)); + if (!ep || ep->acquiring) { + bt_shell_printf( + "Transport %s already in acquiring process\n", + argv[i]); + return bt_shell_noninteractive_quit(EXIT_FAILURE); + } + + ep->acquiring = true; + + link = find_link_by_proxy(proxy); + if (link) { + bt_shell_printf("Link %s found\n", link->transport); + /* If link already acquiring wait it to be complete */ + if (link->acquiring) { + bt_shell_printf( + "Link %s is in acquiring process\n", + argv[i]); + return bt_shell_noninteractive_quit( + EXIT_FAILURE); + } + link->acquiring = true; + } + if (!g_dbus_proxy_method_call(proxy, "Acquire", NULL, acquire_reply, proxy, NULL)) { bt_shell_printf("Failed acquire transport\n"); From patchwork Wed Jun 7 08:22:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Silviu Florian Barbulescu X-Patchwork-Id: 690306 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E5415C77B7A for ; Wed, 7 Jun 2023 08:23:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239278AbjFGIX1 (ORCPT ); Wed, 7 Jun 2023 04:23:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34820 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239059AbjFGIXZ (ORCPT ); Wed, 7 Jun 2023 04:23:25 -0400 Received: from EUR01-VE1-obe.outbound.protection.outlook.com (mail-ve1eur01on2040.outbound.protection.outlook.com [40.107.14.40]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EEE2A138 for ; Wed, 7 Jun 2023 01:23:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=FBtKy4FU2PZzUoe09xGwM4nIYFA+baEAaZ9jEOfmvl9H34kl8lb4vtw4RfJ2ivj8fiY3AFs+oDp/kpLPL/OMx4SwBYKDBuPeKIwd/+cmWIJLf08IaN8nowftuXvbErBQ+xPQeEtoB0as+BgdqBGXYd9uXKR7zS03Pg699MoRWoBvjjll998dymR8BO1XzyR2e/3t4zW2nNlA5aChVHTdaPviULvYLrDpLZbzVaq0IRHIGbdfUY1tEu0H68zmNW6/kVEOlvxK3F+kCFwk7eWZzgudLe16g+DJi9rWbRO1BTRIHyedwWNgoQPMczl3L9EJ3TiDwAu0XY+QUxne9OaWGg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=R4ykWHYTVC54qTXL+A2G37c9A0IHcP+mOdMu6vHMd1c=; b=f7TVmlsMJ/fPOcdd8Wn/e8Qsc8I0BJFOUC1yJzG4cyXLeQQR7EMhAsKiiF6Zm3SqRVIfSSRd1n3kEXYp1fyGoT8o1jUcZeRS5onxhHYUCLbOfidn87TVqbYmRzQjAnC0W+7huCJyl7OmcVsVI5V6RepKCECTVhm0XV1JHBeFVnJVM4LMc5uc/HJjchOzJx/1LnUNLDg3AMphmMLtmmqfW2SSMNQhL+UeygWjrA1o7Oy4ak6rPEJKoNmlI3g3nysJqBhoz3Ydyz7CVYxPvZ0/r/aEGOfwWs4kKyn3ZIRCryln/5+yuEBcxx+53zRm0Og+S5HxEyuQu//iNWN/d4PexQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass header.d=nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=R4ykWHYTVC54qTXL+A2G37c9A0IHcP+mOdMu6vHMd1c=; b=Ox8OrceT5wOH1Fhxx2Gn7dgPQpa60rTGXVR5tKQUQbX7I0PxmdZPRX+O6mL4GdnAIMYyZy+03zOtvPQwDOvrp5580b7UNye/cmc9zaeEpIHEQzLIX/yHpgVGQyHIvPF/5Qo4rH8PKuDEuWXf/jhizixJfeYOsfp3RT6QNhiforw= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from VI1PR04MB5344.eurprd04.prod.outlook.com (2603:10a6:803:4b::31) by DB8PR04MB7114.eurprd04.prod.outlook.com (2603:10a6:10:fe::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6455.32; Wed, 7 Jun 2023 08:23:19 +0000 Received: from VI1PR04MB5344.eurprd04.prod.outlook.com ([fe80::e8eb:cac:f3e3:1085]) by VI1PR04MB5344.eurprd04.prod.outlook.com ([fe80::e8eb:cac:f3e3:1085%4]) with mapi id 15.20.6455.030; Wed, 7 Jun 2023 08:23:19 +0000 From: Silviu Florian Barbulescu To: linux-bluetooth@vger.kernel.org Cc: Silviu Florian Barbulescu Subject: [PATCH v4 3/4] This adds the initial code for BAP broadcast source Date: Wed, 7 Jun 2023 11:22:59 +0300 Message-Id: <20230607082300.4970-4-silviu.barbulescu@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230607082300.4970-1-silviu.barbulescu@nxp.com> References: <20230607082300.4970-1-silviu.barbulescu@nxp.com> X-ClientProxiedBy: AM4PR0101CA0083.eurprd01.prod.exchangelabs.com (2603:10a6:200:41::51) To VI1PR04MB5344.eurprd04.prod.outlook.com (2603:10a6:803:4b::31) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: VI1PR04MB5344:EE_|DB8PR04MB7114:EE_ X-MS-Office365-Filtering-Correlation-Id: 90dd976e-3b01-4d73-f0f3-08db67307379 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: zZxJqpwvMF77WlCBqlTKZ5NOSVXx9W1lQNzhYTJmbaoJ4rPrzK7spQApAM/4AmVf0LldPh2+868d4u+0w3zuW62CQu8kUHo+6Kxxag+mLluQPEHBc5mx/LRdz6YDzDaeDC54vps1Np4TMZgmRaEisFf1CFs64/4jdvVkbCXRoPO8dZOrUrqzfkPO8ddPysMVpTztQHkQr3HcoucWszt1Yjt+Fjxc4d/xc8fUiGbNrNRtAEzj1iEP3BfbahxbPpedpRGzj6IlBTvALN0iQ368dTOD4bOn6aqndlGUXWoAa3gAfwXyIBzp7lZTpx5xiChk8T02BvbspUNDqX667O9EuKogwTRtEAOVyqGcnzhi9uVSyHkUELVnZidqI7wQj716asxNYgdtOc5fjLUaQKD/qkhZZAEprGrd96F7I/gcaJeLZfz+HQYtbA+ShygeKcIo1cD1GVCsnq46oogkOo+VIMFaEv37kMEk2PdA9HbBkYVNEMFxHXXPVlBSHT1Isjalq98c5y7c93rJN8UeV+avcT/jTvEYwQBopfiAC5qjPWLi5fS7N8iV4pwver92/zMgz8rjfzGwbVcWpqdVK7D6q6E5MIJL4Cmgm/8nHC8t/1m9zEnWrCmHy2NaskU+PBVE X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VI1PR04MB5344.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230028)(4636009)(376002)(366004)(396003)(39860400002)(136003)(346002)(451199021)(55236004)(1076003)(6512007)(6506007)(38100700002)(2616005)(41300700001)(38350700002)(6486002)(52116002)(6666004)(186003)(26005)(83380400001)(478600001)(66556008)(6916009)(66476007)(66946007)(316002)(2906002)(8676002)(8936002)(5660300002)(4326008)(30864003)(86362001)(36756003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: IzfWyaK6GBQY1EAVPoAM5Rop/U9fK+KPWYIPNh81IhKj9CUPOSMSh3hT7ozRE9gDhg6KwfxAtswCeJL5eFqcijUmvXXeTPKYy0FGsmbpFuUF9nPWTnMNaeKJr5E7rVIrl+IETKzDKT2BNEMtLD2M24F4d9ERjPktQthUJd94Mp3RVS2BsdZn1QJ0bgQE1FhqTu7xoFsvKS9B4TW8YQfK74XX5Q3JY8UfJlu7FiAew0akuetbKMCa6LZSQlY+UAImBHlw6K2a5xaFQmm9Fc7cjnjWBYHau/kDj8mN0arRh0IjtH+IxSaX/r/vq9T0XcpypuMCBOj/B8EKnjH/lYwV7EYEt3929vWTkES88O+/auixFJlNZykFdhFbY57c36oWZ4MCO56+BpgEVW1zoM7bJfg2ky0fhlQQ/AjTYs9mMmOQ5rS4r0UuqlOjed7E/JT/BMt+SJ7X5XlH+U9LOu64Xv6+UfeR7zvVECpwX45ooksCn63fDkdriXzBLrVtL52G3GD+Jt/EqcBsCQlTOA7ywJukyXbe43G4DYWvTKu+dPfYIBm5q8quDIJQEPs0RaL3SCye4lNHrrw7Esw4/ZWoZAE2yj7RcCLPp97V6nqbFJPvl9pmlKeOiygIR9ty12MEK4HZ8gHFhmawl+nUcvRHuuZTET9gktgkT+uCZqLZ05UXmMAGzMFGTKS/RYEiZy1PGunC2fl4Cbb4dhcBocTe8lOnqDcjsLpl1tGwvhzSqmahozTV7Hsk4KPT4Nk4dYqOg1xZjFYSrcVmUenk9Z2whNCZrykZTOjRzhv4VI0ta24DhP7tUSNrsaYwkR5yqhPT4wBRmv3RRjHKm0BTjmIhGJLjSuOudUNLojDWvzXqTyY7RdrOAwB6emOyZ7ilWDiQWYWzfxvufDUj1CstCOQKipqJEHPvOJ2f9jhQSqkQNSEJRcqjthUwABjxfi/IW37Icx++nl1IL6RLbL46hse49sM9I/I5p6UPWBfpC8veird4Kz3VTy8Jr9sMMG+3Ir2IKo1XndH8GobxVQt1kN7dsaB+G3ho4jqjRGkddphEZTV1NwmTZ5mrWjpZ5TwkDG6JBPPfOXGsQvMaCU0xtE7V0tNIHbPYt5I7ugKWAnpplTf/OLTLvkxsCHCQFX2xaikqKjbRo/Rotq6b5SNWbXUyZN6nj2dIQ19FM2xl9I1RTazPfuN/TpgytKwgZqc0BnyNSajoGJlFC78hMyWtL4kg0ccSqHauc3FYTrZoPZ4qR8Vtui+lYSxDHO3OB7zezlNjxXLp3DpgqR0+3SowUX+uViZcWVOqAOLsFEOKoR7vNT+qdx4TNj9CbWFUeuBpoXNEBC/vyAqiGMlfmFWaMP8xFTa5AKmKUX1SNpOp33K3ZtiGc1ogK4ekf2jzT6HUJAVKu/QdNhma4cTxOT7iz+ynmbnaHTPfKHqzXL6kJuogwxQGbpW66RhX3d9Avy5xIcHrsmt6cXsULp/iCwkx93bX6IGSeqafwLG/T7saYSGsam4uc7+aw//ecyxeVdNaeyQ40TSveBknCzFhhuKs2w1HrZ3JOL6OFqwmeUuNK3753TqaXpbcwAd4bWum+t4rEY7G3I7f6udcBy7ejpdhUw4kqg== X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 90dd976e-3b01-4d73-f0f3-08db67307379 X-MS-Exchange-CrossTenant-AuthSource: VI1PR04MB5344.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Jun 2023 08:23:19.7961 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: D2l7YeYQK8EhCGGfLd/VyYYZ+MxGEYP45vw95yI2HMSzYdK0WXx1Pb8PDFUEGutOZUM0nBgbnDZekBlGEQ11uCkiXKB/YXrcQiKqfMU1lT4= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR04MB7114 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This adds initial support for BAP broadcast source. --- src/shared/bap.c | 241 ++++++++++++++++++++++++++++++++++++++++------- src/shared/bap.h | 9 ++ 2 files changed, 214 insertions(+), 36 deletions(-) diff --git a/src/shared/bap.c b/src/shared/bap.c index 05d814cb0..9c80d21d1 100644 --- a/src/shared/bap.c +++ b/src/shared/bap.c @@ -121,6 +121,8 @@ struct bt_bap_db { struct bt_ascs *ascs; struct queue *sinks; struct queue *sources; + struct queue *broadcast_sources; + struct queue *broadcast_sinks; }; struct bt_bap_req { @@ -623,6 +625,18 @@ static struct bt_bap_endpoint *bap_endpoint_new(struct bt_bap_db *bdb, return ep; } +static struct bt_bap_endpoint *bap_endpoint_new_broacast(struct bt_bap_db *bdb) +{ + struct bt_bap_endpoint *ep; + + ep = new0(struct bt_bap_endpoint, 1); + ep->bdb = bdb; + ep->attr = NULL; + ep->dir = BT_BAP_BCAST_SOURCE; + + return ep; +} + static struct bt_bap_endpoint *bap_get_endpoint(struct queue *endpoints, struct bt_bap_db *db, struct gatt_db_attribute *attr) @@ -645,6 +659,30 @@ static struct bt_bap_endpoint *bap_get_endpoint(struct queue *endpoints, return ep; } +static struct bt_bap_endpoint *bap_get_endpoint_bcast(struct queue *endpoints, + struct bt_bap_db *db) +{ + struct bt_bap_endpoint *ep; + + if (!db) + return NULL; + /* + * We have support for only one stream so we will have + * only one endpoint. + * TO DO add support for more then one stream + */ + if (queue_length(endpoints) > 0) + return queue_peek_head(endpoints); + + ep = bap_endpoint_new_broacast(db); + if (!ep) + return NULL; + + queue_push_tail(endpoints, ep); + + return ep; +} + static bool bap_endpoint_match_id(const void *data, const void *match_data) { const struct bt_bap_endpoint *ep = data; @@ -1261,6 +1299,37 @@ static void bap_stream_state_changed(struct bt_bap_stream *stream) bt_bap_unref(bap); } +static void stream_set_state_broadcast(struct bt_bap_stream *stream, + uint8_t state) +{ + struct bt_bap_endpoint *ep = stream->ep; + struct bt_bap *bap = stream->bap; + const struct queue_entry *entry; + + ep->old_state = ep->state; + ep->state = state; + + bt_bap_ref(bap); + + for (entry = queue_get_entries(bap->state_cbs); entry; + entry = entry->next) { + struct bt_bap_state *state = entry->data; + + if (state->func) + state->func(stream, stream->ep->old_state, + stream->ep->state, state->data); + } + + /* Post notification updates */ + switch (stream->ep->state) { + case BT_ASCS_ASE_STATE_IDLE: + bap_stream_detach(stream); + break; + } + + bt_bap_unref(bap); +} + static void stream_set_state(struct bt_bap_stream *stream, uint8_t state) { struct bt_bap_endpoint *ep = stream->ep; @@ -1397,6 +1466,11 @@ static void ep_config_cb(struct bt_bap_stream *stream, int err) if (err) return; + if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) { + stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_CONFIG); + return; + } + stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG); } @@ -2222,6 +2296,8 @@ static struct bt_bap_db *bap_db_new(struct gatt_db *db) bdb->db = gatt_db_ref(db); bdb->sinks = queue_new(); bdb->sources = queue_new(); + bdb->broadcast_sources = queue_new(); + bdb->broadcast_sinks = queue_new(); if (!bap_db) bap_db = queue_new(); @@ -2397,6 +2473,16 @@ static void bap_add_source(struct bt_bap_pac *pac) iov.iov_len, NULL); } +static void bap_add_broadcast_source(struct bt_bap_pac *pac) +{ + queue_push_tail(pac->bdb->broadcast_sources, pac); +} + +static void bap_add_broadcast_sink(struct bt_bap_pac *pac) +{ + queue_push_tail(pac->bdb->broadcast_sinks, pac); +} + static void notify_pac_added(void *data, void *user_data) { struct bt_bap_pac_changed *changed = data; @@ -2421,7 +2507,7 @@ struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db, struct iovec *metadata) { struct bt_bap_db *bdb; - struct bt_bap_pac *pac; + struct bt_bap_pac *pac, *pac_brodcast_sink; struct bt_bap_codec codec; if (!db) @@ -2447,6 +2533,13 @@ struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db, case BT_BAP_SOURCE: bap_add_source(pac); break; + case BT_BAP_BCAST_SOURCE: + // For broadcast add local pac and remote pac + bap_add_broadcast_source(pac); + pac_brodcast_sink = bap_pac_new(bdb, name, type, &codec, qos, + data, metadata); + bap_add_broadcast_sink(pac_brodcast_sink); + break; default: bap_pac_free(pac); return NULL; @@ -2489,6 +2582,21 @@ uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac) } } +uint8_t bt_bap_stream_get_type(struct bt_bap_stream *stream) +{ + if (!stream) + return BT_BAP_STREAM_TYPE_UNKNOWN; + + if ((bt_bap_pac_get_type(stream->lpac) == BT_BAP_SINK) || + (bt_bap_pac_get_type(stream->lpac) == BT_BAP_SOURCE)) + return BT_BAP_STREAM_TYPE_UNICAST; + else if ((bt_bap_pac_get_type(stream->lpac) == BT_BAP_BCAST_SOURCE) || + (bt_bap_pac_get_type(stream->lpac) == BT_BAP_BCAST_SINK)) + return BT_BAP_STREAM_TYPE_BROADCAST; + else + return BT_BAP_STREAM_TYPE_UNKNOWN; +} + static void notify_pac_removed(void *data, void *user_data) { struct bt_bap_pac_changed *changed = data; @@ -2547,6 +2655,9 @@ bool bt_bap_remove_pac(struct bt_bap_pac *pac) if (queue_remove_if(pac->bdb->sources, NULL, pac)) goto found; + if (queue_remove_if(pac->bdb->broadcast_sources, NULL, pac)) + goto found; + return false; found: @@ -3867,6 +3978,25 @@ clone: return true; } +bool bt_bap_attach_broadcast(struct bt_bap *bap) +{ + struct bt_bap_endpoint *ep; + + if (queue_find(sessions, NULL, bap)) + return true; + + if (!sessions) + sessions = queue_new(); + + queue_push_tail(sessions, bap); + + ep = bap_get_endpoint_bcast(bap->remote_eps, bap->ldb); + if (ep) + ep->bap = bap; + + return true; +} + static void stream_foreach_detach(void *data, void *user_data) { struct bt_bap_stream *stream = data; @@ -4071,7 +4201,11 @@ void bt_bap_foreach_pac(struct bt_bap *bap, uint8_t type, func, user_data); case BT_BAP_SOURCE: return bap_foreach_pac(bap->ldb->sinks, bap->rdb->sources, - func, user_data); + func, user_data); + case BT_BAP_BCAST_SOURCE: + return bap_foreach_pac(bap->ldb->broadcast_sources, + bap->ldb->broadcast_sinks, + func, user_data); } } @@ -4184,42 +4318,51 @@ unsigned int bt_bap_stream_config(struct bt_bap_stream *stream, if (!bap_stream_valid(stream)) return 0; - if (!stream->client) { - stream_config(stream, data, NULL); - return 0; - } + if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) { + if (!stream->client) { + stream_config(stream, data, NULL); + return 0; + } - memset(&config, 0, sizeof(config)); + memset(&config, 0, sizeof(config)); - config.ase = stream->ep->id; - config.latency = qos->ucast.target_latency; - config.phy = qos->ucast.io_qos.phy; - config.codec = stream->rpac->codec; + config.ase = stream->ep->id; + config.latency = qos->ucast.target_latency; + config.phy = qos->ucast.io_qos.phy; + config.codec = stream->rpac->codec; - iov[0].iov_base = &config; - iov[0].iov_len = sizeof(config); + iov[0].iov_base = &config; + iov[0].iov_len = sizeof(config); - if (data) { - if (!bap_print_cc(data->iov_base, data->iov_len, - stream->bap->debug_func, - stream->bap->debug_data)) - return 0; + if (data) { + if (!bap_print_cc(data->iov_base, data->iov_len, + stream->bap->debug_func, + stream->bap->debug_data)) + return 0; - config.cc_len = data->iov_len; - iov[1] = *data; - iovlen++; - } + config.cc_len = data->iov_len; + iov[1] = *data; + iovlen++; + } - req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen, func, user_data); + req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen, + func, user_data); - if (!bap_queue_req(stream->bap, req)) { - bap_req_free(req); - return 0; - } + if (!bap_queue_req(stream->bap, req)) { + bap_req_free(req); + return 0; + } - stream->qos = *qos; + stream->qos = *qos; - return req->id; + return req->id; + } else if (bt_bap_stream_get_type(stream) == + BT_BAP_STREAM_TYPE_BROADCAST) { + stream->qos = *qos; + return 1; + } else { + return 0; + } } static bool match_pac(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, @@ -4345,6 +4488,10 @@ bool bt_bap_stream_set_user_data(struct bt_bap_stream *stream, void *user_data) stream->user_data = user_data; + if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) + stream->lpac->ops->config(stream, stream->cc, &stream->qos, + ep_config_cb, stream->lpac->user_data); + return true; } @@ -4454,7 +4601,7 @@ unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream, bt_bap_stream_func_t func, void *user_data) { - int ret; + int ret = 0; /* Table 3.2: ASE state machine transition * Initiating device - client Only @@ -4462,12 +4609,19 @@ unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream, if (!bap_stream_valid(stream) || !stream->client) return 0; - ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, func, - user_data); - if (!ret || !enable_links) - return ret; + if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) { + ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, + func, user_data); + if (!ret || !enable_links) + return ret; - queue_foreach(stream->links, bap_stream_enable_link, metadata); + queue_foreach(stream->links, bap_stream_enable_link, metadata); + } else if (bt_bap_stream_get_type(stream) == + BT_BAP_STREAM_TYPE_BROADCAST) { + stream_set_state_broadcast(stream, + BT_BAP_STREAM_STATE_STREAMING); + return 1; + } return ret; } @@ -4646,6 +4800,16 @@ unsigned int bt_bap_stream_release(struct bt_bap_stream *stream, bap = stream->bap; + /* If stream is broadcast, no BT_ASCS_RELEASE is required */ + if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) { + if (!bap_stream_valid(stream)) { + stream_set_state_broadcast(stream, + BT_BAP_STREAM_STATE_IDLE); + stream = NULL; + } + return 0; + } + /* 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); @@ -4681,8 +4845,13 @@ uint32_t bt_bap_stream_get_location(struct bt_bap_stream *stream) if (stream->ep->dir == BT_BAP_SOURCE) return pacs->source_loc_value; - else + else if (stream->ep->dir == BT_BAP_SINK) return pacs->sink_loc_value; + else + /* TO DO get the location values from metadata + * for brodcast source and sink + */ + return stream->bap->ldb->pacs->source_loc_value; } struct iovec *bt_bap_stream_get_config(struct bt_bap_stream *stream) diff --git a/src/shared/bap.h b/src/shared/bap.h index 0c42e730f..891b4b5d8 100644 --- a/src/shared/bap.h +++ b/src/shared/bap.h @@ -17,6 +17,12 @@ #define BT_BAP_SINK 0x01 #define BT_BAP_SOURCE 0x02 +#define BT_BAP_BCAST_SOURCE 0x03 +#define BT_BAP_BCAST_SINK 0x04 + +#define BT_BAP_STREAM_TYPE_UNICAST 0x01 +#define BT_BAP_STREAM_TYPE_BROADCAST 0x02 +#define BT_BAP_STREAM_TYPE_UNKNOWN 0x03 #define BT_BAP_STREAM_STATE_IDLE 0x00 #define BT_BAP_STREAM_STATE_CONFIG 0x01 @@ -160,6 +166,8 @@ uint8_t bt_bap_pac_get_type(struct bt_bap_pac *pac); uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac); +uint8_t bt_bap_stream_get_type(struct bt_bap_stream *stream); + struct bt_bap_stream *bt_bap_pac_get_stream(struct bt_bap_pac *pac); /* Session related function */ @@ -179,6 +187,7 @@ struct bt_bap *bt_bap_ref(struct bt_bap *bap); void bt_bap_unref(struct bt_bap *bap); bool bt_bap_attach(struct bt_bap *bap, struct bt_gatt_client *client); +bool bt_bap_attach_broadcast(struct bt_bap *bap); void bt_bap_detach(struct bt_bap *bap); bool bt_bap_set_debug(struct bt_bap *bap, bt_bap_debug_func_t cb, From patchwork Wed Jun 7 08:23:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Silviu Florian Barbulescu X-Patchwork-Id: 690634 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BD1ADC77B7A for ; Wed, 7 Jun 2023 08:23:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239299AbjFGIXb (ORCPT ); Wed, 7 Jun 2023 04:23:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34864 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239059AbjFGIX3 (ORCPT ); Wed, 7 Jun 2023 04:23:29 -0400 Received: from EUR01-VE1-obe.outbound.protection.outlook.com (mail-ve1eur01on2040.outbound.protection.outlook.com [40.107.14.40]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EF352189 for ; Wed, 7 Jun 2023 01:23:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lBOmp5VcxdmWXmV508CPjwx8zXmO+phmVMMQMwbyQssih2a+Px5rku3bIk/EdDeUYh0wrQnzN51vt7/DT5pQBz8vee1Px91U1cONram1+GtgYCKL2JV3lw1Zly5DfAtifJ4kCj8dHOjOTfG01E2XSIik0Z30plB46UwqN9GFMQnGWPsRkTWRXWSKcF5ZyncB8MW5xt73g613mMr5MxHRbzqk63C8TYcJcOlwMApjeiARaEapIIQOmHxXIJSTo0Mt0Zmd0PrhUCsk84qJT6R2p1nQWyD2iolul3IZP0aFRY4QBpYAXE/lZ8/XvGbo8nXf74EMOcTdxQT8e4Q/Ze1shQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=vIe1cRrw9cgVyKLalOR5UZUitV/XQqnreTvaegGXfdA=; b=RGOvl0RIMqKft0guH+Zb9s6GskUU5wB+BZ5E/RatYRFnTC5B+SMCfQPjOuJkhtHO3D4OFaofPUp1rRPNKpwwnzLpfcPhGvFScoXynFSPNZEHk2nNNF1/oF9FRMxwJz2a458CwvyGC0FUo8LDsD5q3sDbqpkghNbwFovH2jZdYOVw5K5dxJWWDVcIxEvDlB/gxiqAsM5UlBAcHspGHXbCGqI8yjTG2i0e0DvsMIPL/Mnu+ujkSstugh/L8j+QZp4C+dCbGFYd1k/zJ5ueXgHC6SaPf4/8dZNCn85pQCE0/DfIlJkug42vMFBsTaVP6lRTuBsJoQmrHquYuDhNoYPZ8w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass header.d=nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=vIe1cRrw9cgVyKLalOR5UZUitV/XQqnreTvaegGXfdA=; b=lUckazT812ox7gG+xXD8DUBdX4aEn/r+AJbQmUIdNwMrkR8pxWA5gBE3MBK/76kgg9bv+srV2PuKkPJUguRMyNej4u1FgGPWZOrwB449k8FCsSMPyIEkf6R+zDBhw6aA2y2YUrYiVevk1kZNDQOv5C7AYI7g5FlK2Yz/Eq+JvV8= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nxp.com; Received: from VI1PR04MB5344.eurprd04.prod.outlook.com (2603:10a6:803:4b::31) by DB8PR04MB7114.eurprd04.prod.outlook.com (2603:10a6:10:fe::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6455.32; Wed, 7 Jun 2023 08:23:21 +0000 Received: from VI1PR04MB5344.eurprd04.prod.outlook.com ([fe80::e8eb:cac:f3e3:1085]) by VI1PR04MB5344.eurprd04.prod.outlook.com ([fe80::e8eb:cac:f3e3:1085%4]) with mapi id 15.20.6455.030; Wed, 7 Jun 2023 08:23:21 +0000 From: Silviu Florian Barbulescu To: linux-bluetooth@vger.kernel.org Cc: Silviu Florian Barbulescu Subject: [PATCH v4 4/4] Update BAP plugin with broadcast source support Date: Wed, 7 Jun 2023 11:23:00 +0300 Message-Id: <20230607082300.4970-5-silviu.barbulescu@nxp.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230607082300.4970-1-silviu.barbulescu@nxp.com> References: <20230607082300.4970-1-silviu.barbulescu@nxp.com> X-ClientProxiedBy: AM4PR0101CA0083.eurprd01.prod.exchangelabs.com (2603:10a6:200:41::51) To VI1PR04MB5344.eurprd04.prod.outlook.com (2603:10a6:803:4b::31) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: VI1PR04MB5344:EE_|DB8PR04MB7114:EE_ X-MS-Office365-Filtering-Correlation-Id: 8f3612d1-f78b-43d6-956d-08db67307444 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: HmxLEL8JOodausofhP6dZUpvpoY1/IGA5HoxPiBV92FYr3fxs1J7dAe8zetTq7VkATEbm3tAIM7kTYsAQ6UckfUxn0qepH4vFlRYvDZHsIDlt/sln55K0cDRslK9GkIlmQUJbMVbYXN8y6oft5ZTpi7fNh905WgYNPwuw9HN/rTXfTMot/bnjvdqLBaBnHWPduydeWuQ2tS1eHYi1nNU0JYqw8K78aiyZjDM2r4WBbsYEAWYq0/VXm8k/hbui37Gar2ulvundAcSLGr2ufsy4Vw6+MSUCfmHdSkdZMpZYdWmqmD4EXp0zE7VX0uS54ZCmsoRrydRhsHPJ1PGMRvOn4L0e5fImTUkm3sDRWA2bmxNRrbikvkTEyNId041CiF2Vh9ggsqi9Tyb1hwn7Gmv6Q2zmhui0iNvJ0ILgEuGGcKj99hqREcWsAKLOHYV0ZyQQhcyh4BXyhl5+b4FRt3qGEpN2PUoHfTmmiqi2Fyv5dx6Mj4rN3qol/4TH0YXTLBaZK8nkt1SFdDc8UiRWPGzdlgClLAvz8fqMcLy6qjgOMnPr21+z053D3BeOa1BY3SJv+Em5iqCSh4ZuziXCR//Oa1Xm81cDOOHnhyn6JoD8Mp3yApiVmkq43+yf6nE81Ka X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VI1PR04MB5344.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230028)(4636009)(376002)(366004)(396003)(39860400002)(136003)(346002)(451199021)(55236004)(1076003)(6512007)(6506007)(38100700002)(2616005)(41300700001)(38350700002)(6486002)(52116002)(6666004)(186003)(26005)(83380400001)(478600001)(66556008)(6916009)(66476007)(66946007)(316002)(2906002)(8676002)(8936002)(5660300002)(4326008)(30864003)(86362001)(15650500001)(36756003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: SyL2QEZW6VJuUtaPIgNu4uk59qUQpM7AzcC370WwLaSYnii+668nmcta4n2+e3kSdKPPyRrNw3ZA1nn88t33iRmyBeK7vTGwWy0/NrCrn4EGWS/hC/XfgtPGQNFXmk6bzzOMhgU+3mEqsYsaR/8IxfzWaawHF5uU+N4fo0UoWLBUnp2fCpObVABNcLpEkRsJ0FZNayDamkg7pVgB5ZT6KdJVZQY157ezBSr8cOxvuCSwVS05yVMF51EbsHU8JYdU9Dx+GPuCqKMwhVg+YXEHmvsuu0LMvyzYgZNxLDx1skAZOw525iw1OOF3c5OY0as1Lp3W5SpdgZJeDb5Eym9883R4nC0aVf+sv5oAiYhVYQbteyE9hXTTLmTSRxn2mzA86cDKkE3rkZ3jHq7rtV6R1lzj62jDOJZOm+g/azgUVzhUxWVN8UZZsdIdIQNbDza1L4CBRFqcIqfiBFgNVsxs6mmXyQ5d1F6pmo2ntThcA/vsW4GTDXw7IdfLOhIp+wkCrVeltL3I0Q82K/q9eicKOmfRyo7lf+VpQfSqTRl9bwpJ5f2cRGlFeZd6o9J8YCkpcWz8plm7n5FYiJZWcPJYRs2/M6W1uJv6ui8UvkE0x3NvVAF1gqxExUnaW7rGlMlmmZPo/9JekkogzbbTRNG6vBEIJW5nULh5cThz+PsZ5WZ9K89VasxpMLqMFHPlWb7za4zftgWotsLBP7AH0/T74x73l0rzJc+sLD0K90cnIvEaH/wL+sn6+LYaKliGfn9VZmuR6g8rvy2Gyl9GtLU9cRnJg6S4U7iSjbH92P3QEc5WSE3hav4bckuNMafpNve899OjnoVn7aNF55PbmtZYR3WZUKLpBV3dx43nBVPe9gN/LuOEZ1/lWa74CmjwFQXTmsj1FdYqDjAB0xx7bIsw1yP/blq2TsaudsbviR0w5WigI3PPjZkuhvwznGI2GSuAjeBeWc/1cONarGJixde7jPOGid+fkipnNIN0EJG/vxAr5HLS8NjGJUiQNDe2pw4ZX7gIMawPPRt8qUNYH1SYCCN6NPEF6uq6pBXgniPECjfu2M0DZQdFcEHoCCR/pPUjxcOGYB3otxsjWXzLGIwj9zWECai326LseLvBpA5mcz8d29NY9kLLFaVATBs8VhhTxWnShYHyXCjq/RE2a1eDsQnPUKhoqrwl1C1HQrpvirP10vd8IkeaEVFT43zDtFlG1XRbnM5Twt7EikYBclp/NjbQHdwD81Iqsxs75aLy6oEyMkO0ELblzV9UT2peJHb6nhSLSWH3HS17NUBGoyecPbcBFyM5jRluidHQxf074MW/TM5lTYVU3Cmyf+j9zoQZGDk5hzYKEzqqGjjuN5th+YP/wpmsUMxsd0+RujasFB73appwXxL/q6h1G2qvLjwj+nyJV1XeVJ6EiLjYr1GeWNyqDFP2gALCgC9zvFnu4aOQJAyA4PfBiRGyHTCZwNwjhpvdsNU9ivmwv+OgKImXVZN/g0wH++zolCuKeUrIgFA4Bti3b2GjoU/uOhBiVym9rQ833mfPtY8EkRib7P6TA9WT1WwAIsbx4lT+nkWbCnzVKV3r/iSuexme7j0feCK1t7AOH6VNDrzlrNoxz3MU3Q== X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8f3612d1-f78b-43d6-956d-08db67307444 X-MS-Exchange-CrossTenant-AuthSource: VI1PR04MB5344.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Jun 2023 08:23:21.1231 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: d2L8ixaAeFvLs4PPq8xTZUbAdKilWB6nbaB0TvvfZ9jGVvEU26SVkK6sBCBzhcJXJCgdH1+HGTNQLTsvOPeLMESDkUwdJGZvEJ0yN3tYu/0= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR04MB7114 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org This updates BAP plugin with broadcast source support. --- profiles/audio/bap.c | 515 +++++++++++++++++++++++++++++++++---- profiles/audio/media.c | 82 ++++-- profiles/audio/media.h | 2 + profiles/audio/transport.c | 59 +++-- 4 files changed, 581 insertions(+), 77 deletions(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index cbaf705c0..cbe3c4b97 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -75,6 +75,7 @@ struct bap_ep { struct bap_data { struct btd_device *device; + struct btd_adapter *adapter; struct btd_service *service; struct bt_bap *bap; unsigned int ready_id; @@ -82,13 +83,25 @@ struct bap_data { unsigned int pac_id; struct queue *srcs; struct queue *snks; + struct queue *bcast; struct queue *streams; GIOChannel *listen_io; int selecting; + void *user_data; }; static struct queue *sessions; +static bool bap_data_set_user_data(struct bap_data *data, void *user_data) +{ + if (!data) + return false; + + data->user_data = user_data; + + return true; +} + static void bap_debug(const char *str, void *user_data) { DBG_IDX(0xffff, "%s", str); @@ -167,8 +180,10 @@ static gboolean get_uuid(const GDBusPropertyTable *property, if (queue_find(ep->data->snks, NULL, ep)) uuid = PAC_SINK_UUID; - else + if (queue_find(ep->data->srcs, NULL, ep)) uuid = PAC_SOURCE_UUID; + else + uuid = BAA_SERVICE_UUID; dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid); @@ -214,7 +229,10 @@ static gboolean get_device(const GDBusPropertyTable *property, struct bap_ep *ep = data; const char *path; - path = device_get_path(ep->data->device); + if (bt_bap_pac_get_type(ep->lpac) == BT_BAP_BCAST_SOURCE) + path = adapter_get_path(ep->data->adapter); + else + path = device_get_path(ep->data->device); dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path); @@ -254,7 +272,10 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps, { const char *key; struct bt_bap_io_qos io_qos; + uint8_t framing = 0; + bool broadcast = false; + memset(&io_qos, 0, sizeof(io_qos)); while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) { DBusMessageIter value, entry; int var; @@ -284,11 +305,21 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps, goto fail; dbus_message_iter_get_basic(&value, &qos->ucast.cig_id); + } else if (!strcasecmp(key, "BIG")) { + if (var != DBUS_TYPE_BYTE) + goto fail; + + dbus_message_iter_get_basic(&value, &qos->bcast.big); } else if (!strcasecmp(key, "CIS")) { if (var != DBUS_TYPE_BYTE) goto fail; dbus_message_iter_get_basic(&value, &qos->ucast.cis_id); + } else if (!strcasecmp(key, "BIS")) { + if (var != DBUS_TYPE_BYTE) + goto fail; + + dbus_message_iter_get_basic(&value, &qos->bcast.bis); } else if (!strcasecmp(key, "Interval")) { if (var != DBUS_TYPE_UINT32) goto fail; @@ -302,7 +333,7 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps, dbus_message_iter_get_basic(&value, &val); - qos->ucast.framing = val; + framing = val; } else if (!strcasecmp(key, "PHY")) { const char *str; @@ -342,13 +373,78 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps, goto fail; dbus_message_iter_get_basic(&value, - &qos->ucast.target_latency); + &qos->ucast.target_latency); + } else if (!strcasecmp(key, "Encryption")) { + if (var != DBUS_TYPE_BYTE) + goto fail; + + dbus_message_iter_get_basic(&value, + &qos->bcast.encryption); + broadcast = true; + } else if (!strcasecmp(key, "Options")) { + if (var != DBUS_TYPE_BYTE) + goto fail; + + dbus_message_iter_get_basic(&value, + &qos->bcast.options); + } else if (!strcasecmp(key, "Skip")) { + if (var != DBUS_TYPE_UINT16) + goto fail; + + dbus_message_iter_get_basic(&value, + &qos->bcast.skip); + } else if (!strcasecmp(key, "SyncTimeout")) { + if (var != DBUS_TYPE_UINT16) + goto fail; + + dbus_message_iter_get_basic(&value, + &qos->bcast.sync_timeout); + } else if (!strcasecmp(key, "SyncCteType")) { + if (var != DBUS_TYPE_BYTE) + goto fail; + + dbus_message_iter_get_basic(&value, + &qos->bcast.sync_cte_type); + + } else if (!strcasecmp(key, "SyncInterval")) { + if (var != DBUS_TYPE_BYTE) + goto fail; + + dbus_message_iter_get_basic(&value, + &qos->bcast.sync_interval); + } else if (!strcasecmp(key, "MSE")) { + if (var != DBUS_TYPE_BYTE) + goto fail; + + dbus_message_iter_get_basic(&value, + &qos->bcast.mse); + } else if (!strcasecmp(key, "Timeout")) { + if (var != DBUS_TYPE_UINT16) + goto fail; + + dbus_message_iter_get_basic(&value, + &qos->bcast.timeout); + } else if (!strcasecmp(key, "BroadcastCode")) { + struct iovec *iov; + + if (var != DBUS_TYPE_ARRAY) + goto fail; + iov = &qos->bcast.bcode; + parse_array(&value, &iov); } dbus_message_iter_next(props); } - memcpy(&qos->ucast.io_qos, &io_qos, sizeof(io_qos)); + if (broadcast) { + memcpy(&qos->bcast.io_qos, &io_qos, sizeof(io_qos)); + qos->bcast.framing = framing; + + } else { + memcpy(&qos->ucast.io_qos, &io_qos, sizeof(io_qos)); + qos->ucast.framing = framing; + } + return 0; fail: @@ -457,9 +553,15 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg, bt_bap_stream_io_connecting(ep->stream, -1); } - /* Mark CIG and CIS to be auto assigned */ - ep->qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET; - ep->qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET; + if (bt_bap_pac_get_type(ep->lpac) == BT_BAP_BCAST_SOURCE) { + /* Mark CIG and CIS to be auto assigned */ + ep->qos.bcast.big = BT_ISO_QOS_BIG_UNSET; + ep->qos.bcast.bis = BT_ISO_QOS_BIS_UNSET; + } else { + /* Mark CIG and CIS to be auto assigned */ + ep->qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET; + ep->qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET; + } if (parse_properties(&props, &ep->caps, &ep->metadata, &ep->qos) < 0) { DBG("Unable to parse properties"); @@ -482,6 +584,10 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg, return btd_error_invalid_args(msg); } + if (bt_bap_stream_get_type(ep->stream) == + BT_BAP_STREAM_TYPE_BROADCAST) + ep->id = 0; // No message sent over the air for broadcast + bt_bap_stream_set_user_data(ep->stream, ep->path); ep->msg = dbus_message_ref(msg); @@ -510,6 +616,8 @@ static void ep_free(void *data) util_iov_free(ep->caps, 1); util_iov_free(ep->metadata, 1); + if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_BROADCAST) + util_iov_free(&ep->qos.bcast.bcode, 1); free(ep->path); free(ep); } @@ -530,6 +638,63 @@ static bool match_ep(const void *data, const void *user_data) return ep->rpac == match->rpac; } +static struct bap_ep *ep_register_bcast(struct bap_data *data, + struct bt_bap_pac *lpac, + struct bt_bap_pac *rpac) +{ + struct btd_adapter *adapter = data->user_data; + struct bap_ep *ep; + struct queue *queue; + int i, err; + const char *suffix; + struct match_ep match = { lpac, rpac }; + + switch (bt_bap_pac_get_type(rpac)) { + case BT_BAP_BCAST_SOURCE: + queue = data->bcast; + i = queue_length(data->bcast); + suffix = "bcast"; + break; + default: + return NULL; + } + + ep = queue_find(queue, match_ep, &match); + if (ep) + return ep; + + ep = new0(struct bap_ep, 1); + ep->data = data; + ep->lpac = lpac; + ep->rpac = rpac; + + err = asprintf(&ep->path, "%s/pac_%s%d", adapter_get_path(adapter), + suffix, i); + if (err < 0) { + error("Could not allocate path for remote pac %s/pac%d", + adapter_get_path(adapter), i); + free(ep); + return NULL; + } + + if (g_dbus_register_interface(btd_get_dbus_connection(), + ep->path, MEDIA_ENDPOINT_INTERFACE, + ep_methods, NULL, ep_properties, + ep, ep_free) == FALSE) { + error("Could not register remote ep %s", ep->path); + ep_free(ep); + return NULL; + } + + bt_bap_pac_set_user_data(rpac, ep->path); + + DBG("ep %p lpac %p rpac %p path %s", ep, ep->lpac, ep->rpac, ep->path); + + queue_push_tail(queue, ep); + + return ep; +} + static struct bap_ep *ep_register(struct btd_service *service, struct bt_bap_pac *lpac, struct bt_bap_pac *rpac) @@ -677,6 +842,23 @@ static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, return true; } +static bool pac_found_bcast(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac, + void *user_data) +{ + struct bap_ep *ep; + + DBG("lpac %p rpac %p", lpac, rpac); + + ep = ep_register_bcast(user_data, lpac, rpac); + if (!ep) { + error("Unable to register endpoint for pac %p", rpac); + return true; + } + + return true; +} + + static void bap_ready(struct bt_bap *bap, void *user_data) { struct btd_service *service = user_data; @@ -700,11 +882,18 @@ static struct bap_ep *bap_find_ep_by_stream(struct bap_data *data, { struct bap_ep *ep; - ep = queue_find(data->snks, match_ep_by_stream, stream); - if (ep) - return ep; + if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) { + ep = queue_find(data->snks, match_ep_by_stream, stream); + if (ep) + return ep; - return queue_find(data->srcs, match_ep_by_stream, stream); + return queue_find(data->srcs, match_ep_by_stream, stream); + } else if (bt_bap_stream_get_type(stream) == + BT_BAP_STREAM_TYPE_BROADCAST) { + + return queue_find(data->bcast, match_ep_by_stream, stream); + } else + return NULL; } static void iso_connect_cb(GIOChannel *chan, GError *err, gpointer user_data) @@ -943,6 +1132,62 @@ static void bap_connect_io(struct bap_data *data, struct bap_ep *ep, bt_bap_stream_io_connecting(stream, g_io_channel_unix_get_fd(io)); } +static void bap_connect_io_broadcast(struct bap_data *data, struct bap_ep *ep, + struct bt_bap_stream *stream, + struct bt_iso_qos *qos) +{ + struct btd_adapter *adapter = data->user_data; + GIOChannel *io = NULL; + GError *err = NULL; + bdaddr_t dst_addr = {0}; + char addr[18]; + struct bt_iso_base base; + + /* If IO already set and we are in the creation step, + * skip creating it again + */ + if (bt_bap_stream_get_io(stream)) + return; + + if (ep->io_id) { + g_source_remove(ep->io_id); + ep->io_id = 0; + } + base.base_len = ep->caps->iov_len; + + memset(base.base, 0, 248); + memcpy(base.base, ep->caps->iov_base, base.base_len); + DBG("ep %p stream %p ", ep, stream); + ba2str(btd_adapter_get_address(adapter), addr); + + io = bt_io_connect(bap_connect_io_cb, ep, NULL, &err, + BT_IO_OPT_SOURCE_BDADDR, + btd_adapter_get_address(adapter), + BT_IO_OPT_DEST_BDADDR, + &dst_addr, + BT_IO_OPT_DEST_TYPE, + BDADDR_LE_PUBLIC, + BT_IO_OPT_MODE, BT_IO_MODE_ISO, + BT_IO_OPT_QOS, qos, + BT_IO_OPT_BASE, &base, + BT_IO_OPT_DEFER_TIMEOUT, false, + BT_IO_OPT_INVALID); + + if (!io) { + error("%s", err->message); + g_error_free(err); + return; + } + + ep->io_id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL, + bap_io_disconnected, ep); + + ep->io = io; + + bt_bap_stream_io_connecting(stream, + g_io_channel_unix_get_fd(io)); +} + static void bap_listen_io(struct bap_data *data, struct bt_bap_stream *stream, struct bt_iso_qos *qos) { @@ -989,22 +1234,53 @@ static void bap_create_io(struct bap_data *data, struct bap_ep *ep, if (!queue_find(data->streams, NULL, stream)) queue_push_tail(data->streams, stream); - if (!bt_bap_stream_io_get_qos(stream, &qos[0], &qos[1])) { - error("bt_bap_stream_get_qos_links: failed"); - return; - } - memset(&iso_qos, 0, sizeof(iso_qos)); - iso_qos.ucast.cig = qos[0] ? qos[0]->ucast.cig_id : + + if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) { + if (!bt_bap_stream_io_get_qos(stream, &qos[0], &qos[1])) { + error("bt_bap_stream_get_qos_links: failed"); + return; + } + + iso_qos.ucast.cig = qos[0] ? qos[0]->ucast.cig_id : qos[1]->ucast.cig_id; - iso_qos.ucast.cis = qos[0] ? qos[0]->ucast.cis_id : + iso_qos.ucast.cis = qos[0] ? qos[0]->ucast.cis_id : qos[1]->ucast.cis_id; - bap_iso_qos(qos[0], &iso_qos.ucast.in); - bap_iso_qos(qos[1], &iso_qos.ucast.out); + bap_iso_qos(qos[0], &iso_qos.ucast.in); + bap_iso_qos(qos[1], &iso_qos.ucast.out); + } else if (bt_bap_stream_get_type(stream) == + BT_BAP_STREAM_TYPE_BROADCAST) { + if (defer == true) { + iso_qos.bcast.big = ep->qos.bcast.big; + iso_qos.bcast.bis = ep->qos.bcast.bis; + iso_qos.bcast.sync_interval = + ep->qos.bcast.sync_interval; + iso_qos.bcast.packing = ep->qos.bcast.packing; + iso_qos.bcast.framing = ep->qos.bcast.framing; + iso_qos.bcast.encryption = ep->qos.bcast.encryption; + memcpy(iso_qos.bcast.bcode, + ep->qos.bcast.bcode.iov_base, 16); + iso_qos.bcast.options = ep->qos.bcast.options; + iso_qos.bcast.skip = ep->qos.bcast.skip; + iso_qos.bcast.sync_timeout = ep->qos.bcast.sync_timeout; + iso_qos.bcast.sync_cte_type = + ep->qos.bcast.sync_cte_type; + iso_qos.bcast.mse = ep->qos.bcast.mse; + iso_qos.bcast.timeout = ep->qos.bcast.timeout; + memcpy(&iso_qos.bcast.out, &ep->qos.bcast.io_qos, + sizeof(struct bt_iso_io_qos)); + } + } else + return; if (ep) - bap_connect_io(data, ep, stream, &iso_qos, defer); + if (bt_bap_stream_get_type(stream) == + BT_BAP_STREAM_TYPE_BROADCAST) + bap_connect_io_broadcast(data, ep, stream, + &iso_qos); + else + bap_connect_io(data, ep, stream, &iso_qos, defer); else bap_listen_io(data, stream, &iso_qos); } @@ -1043,12 +1319,16 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state, } - /* Wait QoS response to respond */ - ep->id = bt_bap_stream_qos(stream, &ep->qos, qos_cb, - ep); - if (!ep->id) { - error("Failed to Configure QoS"); - bt_bap_stream_release(stream, NULL, NULL); + if (bt_bap_stream_get_type(stream) == + BT_BAP_STREAM_TYPE_UNICAST) { + /* Wait QoS response to respond */ + ep->id = bt_bap_stream_qos(stream, &ep->qos, + qos_cb, ep); + if (!ep->id) { + error("Failed to Configure QoS"); + bt_bap_stream_release(stream, + NULL, NULL); + } } } break; @@ -1059,6 +1339,13 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state, if (ep) bap_create_io(data, ep, stream, false); break; + case BT_BAP_STREAM_STATE_STREAMING: + if (bt_bap_stream_get_type(stream) == + BT_BAP_STREAM_TYPE_BROADCAST) { + if (ep) + bap_create_io(data, ep, stream, false); + } + break; } } @@ -1078,6 +1365,18 @@ static void pac_added(struct bt_bap_pac *pac, void *user_data) bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_found, service); } +static void pac_added_broadcast(struct bt_bap_pac *pac, void *user_data) +{ + struct bap_data *data = user_data; + + if (bt_bap_pac_get_type(pac) == BT_BAP_BCAST_SOURCE) { + DBG("pac %p", pac); + + bt_bap_foreach_pac(data->bap, BT_BAP_BCAST_SOURCE, + pac_found_bcast, data); + } +} + static bool ep_match_pac(const void *data, const void *match_data) { const struct bap_ep *ep = data; @@ -1118,6 +1417,38 @@ static void pac_removed(struct bt_bap_pac *pac, void *user_data) ep_unregister(ep); } +static void pac_removed_broadcast(struct bt_bap_pac *pac, void *user_data) +{ + struct btd_service *service = user_data; + struct bap_data *data; + struct queue *queue; + struct bap_ep *ep; + + DBG("pac %p", pac); + + data = btd_service_get_user_data(service); + + switch (bt_bap_pac_get_type(pac)) { + case BT_BAP_SINK: + queue = data->srcs; + break; + case BT_BAP_SOURCE: + queue = data->snks; + break; + case BT_BAP_BCAST_SOURCE: + queue = data->bcast; + break; + default: + return; + } + + ep = queue_remove_if(queue, ep_match_pac, pac); + if (!ep) + return; + + ep_unregister(ep); +} + static struct bap_data *bap_data_new(struct btd_device *device) { struct bap_data *data; @@ -1126,6 +1457,7 @@ static struct bap_data *bap_data_new(struct btd_device *device) data->device = device; data->srcs = queue_new(); data->snks = queue_new(); + data->bcast = queue_new(); return data; } @@ -1158,6 +1490,14 @@ static bool match_data(const void *data, const void *match_data) return bdata->bap == bap; } +static bool match_data_bap_data(const void *data, const void *match_data) +{ + const struct bap_data *bdata = data; + const struct btd_adapter *adapter = match_data; + + return bdata->user_data == adapter; +} + static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd, void *user_data) { @@ -1182,26 +1522,50 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd, g_io_channel_set_close_on_unref(io, FALSE); - /* Attempt to get CIG/CIS if they have not been set */ - if (ep->qos.ucast.cig_id == BT_ISO_QOS_CIG_UNSET || + if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_UNICAST) { + /* Attempt to get CIG/CIS if they have not been set */ + if (ep->qos.ucast.cig_id == BT_ISO_QOS_CIG_UNSET || ep->qos.ucast.cis_id == BT_ISO_QOS_CIS_UNSET) { - struct bt_iso_qos qos; - GError *err = NULL; - - if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos, - BT_IO_OPT_INVALID)) { - error("%s", err->message); - g_error_free(err); - g_io_channel_unref(io); - return; - } + struct bt_iso_qos qos; + GError *err = NULL; + + if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos, + BT_IO_OPT_INVALID)) { + error("%s", err->message); + g_error_free(err); + g_io_channel_unref(io); + return; + } - ep->qos.ucast.cig_id = qos.ucast.cig; - ep->qos.ucast.cis_id = qos.ucast.cis; - } + ep->qos.ucast.cig_id = qos.ucast.cig; + ep->qos.ucast.cis_id = qos.ucast.cis; + } - DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd, + DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd, ep->qos.ucast.cig_id, ep->qos.ucast.cis_id); + } else if (bt_bap_stream_get_type(ep->stream) == + BT_BAP_STREAM_TYPE_BROADCAST) { + /* Attempt to get BIG/BIS if they have not been set */ + if (ep->qos.bcast.big == BT_ISO_QOS_BIG_UNSET || + ep->qos.bcast.bis == BT_ISO_QOS_BIS_UNSET) { + struct bt_iso_qos qos; + GError *err = NULL; + + if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos, + BT_IO_OPT_INVALID)) { + error("%s", err->message); + g_error_free(err); + g_io_channel_unref(io); + return; + } + + ep->qos.bcast.big = qos.bcast.big; + ep->qos.bcast.bis = qos.bcast.bis; + } + + DBG("stream %p fd %d: BIG 0x%02x BIS 0x%02x", stream, fd, + ep->qos.bcast.big, ep->qos.bcast.bis); + } } static void bap_attached(struct bt_bap *bap, void *user_data) @@ -1349,6 +1713,67 @@ static int bap_disconnect(struct btd_service *service) return 0; } +static int bap_adapter_probe(struct btd_profile *p, + struct btd_adapter *adapter) +{ + struct btd_gatt_database *database = btd_adapter_get_database(adapter); + struct bap_data *data; + char addr[18]; + + ba2str(btd_adapter_get_address(adapter), addr); + DBG("%s", addr); + + if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET)) { + error("BAP requires ISO Socket which is not enabled"); + return -ENOTSUP; + } + + data = bap_data_new(NULL); + data->adapter = adapter; + + data->bap = bt_bap_new(btd_gatt_database_get_db(database), + btd_gatt_database_get_db(database)); + if (!data->bap) { + error("Unable to create BAP instance"); + free(data); + return -EINVAL; + } + + bap_data_add(data); + + if (!bt_bap_attach_broadcast(data->bap)) { + error("BAP unable to attach"); + return -EINVAL; + } + + data->state_id = bt_bap_state_register(data->bap, bap_state, + bap_connecting, data, NULL); + data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast, + pac_removed_broadcast, data, NULL); + + bt_bap_set_user_data(data->bap, adapter); + bap_data_set_user_data(data, adapter); + return 0; +} + +static void bap_adapter_remove(struct btd_profile *p, + struct btd_adapter *adapter) +{ + struct bap_data *data = queue_find(sessions, match_data_bap_data, + adapter); + char addr[18]; + + ba2str(btd_adapter_get_address(adapter), addr); + DBG("%s", addr); + + if (!data) { + error("BAP service not handled by profile"); + return; + } + + bap_data_remove(data); +} + static struct btd_profile bap_profile = { .name = "bap", .priority = BTD_PROFILE_PRIORITY_MEDIUM, @@ -1357,6 +1782,8 @@ static struct btd_profile bap_profile = { .device_remove = bap_remove, .accept = bap_accept, .disconnect = bap_disconnect, + .adapter_probe = bap_adapter_probe, + .adapter_remove = bap_adapter_remove, .auto_connect = true, .experimental = true, }; diff --git a/profiles/audio/media.c b/profiles/audio/media.c index 515263af3..8280101af 100644 --- a/profiles/audio/media.c +++ b/profiles/audio/media.c @@ -1041,28 +1041,50 @@ static int pac_config(struct bt_bap_stream *stream, struct iovec *cfg, transport = find_transport(endpoint, stream); if (!transport) { struct bt_bap *bap = bt_bap_stream_get_session(stream); - struct btd_service *service = bt_bap_get_user_data(bap); - struct btd_device *device; + if (bt_bap_stream_get_type(stream) == + BT_BAP_STREAM_TYPE_UNICAST) { + struct btd_service *service = bt_bap_get_user_data(bap); + struct btd_device *device; + + if (service) + device = btd_service_get_device(service); + else { + struct bt_att *att = bt_bap_get_att(bap); + int fd = bt_att_get_fd(att); + + device = btd_adapter_find_device_by_fd(fd); + } + + if (!device) { + error("Unable to find device"); + return -EINVAL; + } - if (service) - device = btd_service_get_device(service); - else { - struct bt_att *att = bt_bap_get_att(bap); - int fd = bt_att_get_fd(att); + path = bt_bap_stream_get_user_data(stream); - device = btd_adapter_find_device_by_fd(fd); - } + transport = media_transport_create(device, path, + cfg->iov_base, + cfg->iov_len, + endpoint, + stream); + } else if (bt_bap_stream_get_type(stream) == + BT_BAP_STREAM_TYPE_BROADCAST) { + struct btd_adapter *adapter = bt_bap_get_user_data(bap); - if (!device) { - error("Unable to find device"); - return -EINVAL; - } + if (!adapter) { + error("Unable to find adapter"); + return -EINVAL; + } + + path = bt_bap_stream_get_user_data(stream); - path = bt_bap_stream_get_user_data(stream); + transport = media_transport_create(NULL, path, + cfg->iov_base, + cfg->iov_len, + endpoint, + stream); + } - transport = media_transport_create(device, path, cfg->iov_base, - cfg->iov_len, endpoint, - stream); if (!transport) return -EINVAL; @@ -1198,6 +1220,12 @@ static bool endpoint_init_pac_source(struct media_endpoint *endpoint, int *err) return endpoint_init_pac(endpoint, BT_BAP_SOURCE, err); } +static bool endpoint_init_broadcast_source(struct media_endpoint *endpoint, + int *err) +{ + return endpoint_init_pac(endpoint, BT_BAP_BCAST_SOURCE, err); +} + static bool endpoint_properties_exists(const char *uuid, struct btd_device *dev, void *user_data) @@ -1300,6 +1328,18 @@ static bool experimental_endpoint_supported(struct btd_adapter *adapter) return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL; } +static bool experimental_broadcaster_ep_supported(struct btd_adapter *adapter) +{ + + if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET)) + return false; + + if (!btd_adapter_has_settings(adapter, MGMT_SETTING_ISO_BROADCASTER)) + return false; + + return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL; +} + static struct media_endpoint_init { const char *uuid; bool (*func)(struct media_endpoint *endpoint, int *err); @@ -1313,6 +1353,8 @@ static struct media_endpoint_init { experimental_endpoint_supported }, { PAC_SOURCE_UUID, endpoint_init_pac_source, experimental_endpoint_supported }, + { BAA_SERVICE_UUID, endpoint_init_broadcast_source, + experimental_broadcaster_ep_supported }, }; static struct media_endpoint * @@ -3185,3 +3227,9 @@ uint8_t media_endpoint_get_codec(struct media_endpoint *endpoint) { return endpoint->codec; } + +struct btd_adapter *media_endpoint_get_btd_adapter( + struct media_endpoint *endpoint) +{ + return endpoint->adapter->btd_adapter; +} diff --git a/profiles/audio/media.h b/profiles/audio/media.h index 96bea9db4..1de84a8ff 100644 --- a/profiles/audio/media.h +++ b/profiles/audio/media.h @@ -20,5 +20,7 @@ void media_unregister(struct btd_adapter *btd_adapter); struct a2dp_sep *media_endpoint_get_sep(struct media_endpoint *endpoint); const char *media_endpoint_get_uuid(struct media_endpoint *endpoint); uint8_t media_endpoint_get_codec(struct media_endpoint *endpoint); +struct btd_adapter *media_endpoint_get_btd_adapter( + struct media_endpoint *endpoint); int8_t media_player_get_device_volume(struct btd_device *device); diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c index 82f5fa6fe..773be8411 100644 --- a/profiles/audio/transport.c +++ b/profiles/audio/transport.c @@ -91,6 +91,7 @@ struct bap_transport { struct media_transport { char *path; /* Transport object path */ struct btd_device *device; /* Transport device */ + struct btd_adapter *adapter; /* Transport adapter bcast*/ const char *remote_endpoint; /* Transport remote SEP */ struct media_endpoint *endpoint; /* Transport endpoint */ struct media_owner *owner; /* Transport owner */ @@ -526,6 +527,13 @@ static void media_owner_add(struct media_owner *owner, owner->pending = req; } +static void *get_stream_bap(struct media_transport *transport) +{ + struct bap_transport *bap = transport->data; + + return bap->stream; +} + static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -541,15 +549,24 @@ static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg, return btd_error_not_authorized(msg); owner = media_owner_create(msg); + if (bt_bap_stream_get_type(get_stream_bap(transport)) == + BT_BAP_STREAM_TYPE_BROADCAST) { + req = media_request_create(msg, 0x00); + media_owner_add(owner, req); + media_transport_set_owner(transport, owner); + } id = transport->resume(transport, owner); if (id == 0) { media_owner_free(owner); return btd_error_not_authorized(msg); } - req = media_request_create(msg, id); - media_owner_add(owner, req); - media_transport_set_owner(transport, owner); + if (bt_bap_stream_get_type(get_stream_bap(transport)) == + BT_BAP_STREAM_TYPE_UNICAST) { + req = media_request_create(msg, id); + media_owner_add(owner, req); + media_transport_set_owner(transport, owner); + } return NULL; } @@ -628,7 +645,12 @@ static gboolean get_device(const GDBusPropertyTable *property, DBusMessageIter *iter, void *data) { struct media_transport *transport = data; - const char *path = device_get_path(transport->device); + const char *path; + + if (transport->device) + path = device_get_path(transport->device); + else + path = adapter_get_path(transport->adapter); dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path); @@ -1483,13 +1505,6 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd, bap_update_links(transport); } -static void *get_stream_bap(struct media_transport *transport) -{ - struct bap_transport *bap = transport->data; - - return bap->stream; -} - static void free_bap(void *data) { struct bap_transport *bap = data; @@ -1539,15 +1554,26 @@ struct media_transport *media_transport_create(struct btd_device *device, const GDBusPropertyTable *properties; transport = g_new0(struct media_transport, 1); - transport->device = device; + if (device) + transport->device = device; + else + transport->adapter = media_endpoint_get_btd_adapter(endpoint); transport->endpoint = endpoint; transport->configuration = g_new(uint8_t, size); memcpy(transport->configuration, configuration, size); transport->size = size; transport->remote_endpoint = remote_endpoint; - transport->path = g_strdup_printf("%s/fd%d", - remote_endpoint ? remote_endpoint : - device_get_path(device), fd++); + if (device) + transport->path = g_strdup_printf("%s/fd%d", + remote_endpoint ? remote_endpoint : + device_get_path(device), fd++); + else + transport->path = g_strdup_printf("%s/fd%d", + remote_endpoint ? remote_endpoint : + adapter_get_path( + media_endpoint_get_btd_adapter( + endpoint)), + fd++); transport->fd = -1; uuid = media_endpoint_get_uuid(endpoint); @@ -1560,7 +1586,8 @@ struct media_transport *media_transport_create(struct btd_device *device, goto fail; properties = a2dp_properties; } else if (!strcasecmp(uuid, PAC_SINK_UUID) || - !strcasecmp(uuid, PAC_SOURCE_UUID)) { + !strcasecmp(uuid, PAC_SOURCE_UUID) || + !strcasecmp(uuid, BAA_SERVICE_UUID)) { if (media_transport_init_bap(transport, stream) < 0) goto fail; properties = bap_properties;