This is an automated email from the ASF dual-hosted git repository.
janc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
The following commit(s) were added to refs/heads/master by this push:
new c41feda76 apps/bttester: Add initial support for PACS autopts tests
c41feda76 is described below
commit c41feda76b810cf52651f4bc53f2edcf78a0e103
Author: Szymon Czapracki <[email protected]>
AuthorDate: Fri Apr 5 14:48:45 2024 +0200
apps/bttester: Add initial support for PACS autopts tests
This commit adds support for Published
Audio Capabilities Service in bttester
application.
---
apps/bttester/pkg.yml | 2 +
apps/bttester/src/btp/btp.h | 2 +
apps/bttester/src/btp/btp_pacs.h | 59 +++++++
apps/bttester/src/btp/bttester.h | 7 +
apps/bttester/src/btp_core.c | 10 ++
apps/bttester/src/btp_pacs.c | 333 +++++++++++++++++++++++++++++++++++++++
apps/bttester/syscfg.yml | 1 +
7 files changed, 414 insertions(+)
diff --git a/apps/bttester/pkg.yml b/apps/bttester/pkg.yml
index 0972cb7a2..851119545 100644
--- a/apps/bttester/pkg.yml
+++ b/apps/bttester/pkg.yml
@@ -38,6 +38,8 @@ pkg.deps:
- "@apache-mynewt-nimble/nimble/host/services/gatt"
- "@apache-mynewt-nimble/nimble/host/services/dis"
- "@apache-mynewt-nimble/nimble/host/audio/services/bass"
+ - "@apache-mynewt-nimble/nimble/host/audio/services/pacs"
+ - "@apache-mynewt-nimble/nimble/host/audio/services/pacs/lc3"
- "@apache-mynewt-nimble/nimble/host/store/config"
- "@apache-mynewt-core/hw/drivers/uart"
- "@apache-mynewt-core/hw/drivers/rtt"
diff --git a/apps/bttester/src/btp/btp.h b/apps/bttester/src/btp/btp.h
index 4403a1603..17fe38876 100644
--- a/apps/bttester/src/btp/btp.h
+++ b/apps/bttester/src/btp/btp.h
@@ -33,6 +33,7 @@
#include "btp_gattc.h"
#include "btp_l2cap.h"
#include "btp_mesh.h"
+#include "btp_pacs.h"
#include "btp_bap.h"
#define BTP_MTU MYNEWT_VAL(BTTESTER_BTP_DATA_SIZE_MAX)
@@ -47,6 +48,7 @@
#define BTP_SERVICE_ID_L2CAP 3
#define BTP_SERVICE_ID_MESH 4
#define BTP_SERVICE_ID_GATTC 6
+#define BTP_SERVICE_ID_PACS 12
#define BTP_SERVICE_ID_BAP 14
#define BTP_SERVICE_ID_MAX BTP_SERVICE_ID_BAP
diff --git a/apps/bttester/src/btp/btp_pacs.h b/apps/bttester/src/btp/btp_pacs.h
new file mode 100644
index 000000000..3b9b5b06c
--- /dev/null
+++ b/apps/bttester/src/btp/btp_pacs.h
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef BTP_PACS_H
+#define BTP_PACS_H
+
+#include <stdint.h>
+
+#ifndef __packed
+#define __packed __attribute__((__packed__))
+#endif
+
+#define BTP_PACS_READ_SUPPORTED_COMMANDS 0x01
+struct btp_pacs_read_supported_commands_rp {
+ uint8_t data[0];
+} __packed;
+
+#define BTP_PACS_UPDATE_CHARACTERISTIC 0x02
+struct btp_pacs_update_characteristic_cmd {
+ uint8_t char_id;
+} __packed;
+
+#define BTP_PACS_SET_LOCATION 0x03
+
+#define BTP_PACS_SET_AVAILABLE_CONTEXTS 0x04
+struct btp_pacs_set_available_contexts_cmd {
+ uint16_t sink_contexts;
+ uint16_t source_contexts;
+} __packed;
+
+#define BTP_PACS_SET_SUPPORTED_CONTEXTS 0x05
+struct btp_pacs_set_supported_contexts_cmd {
+ uint16_t sink_contexts;
+ uint16_t source_contexts;
+} __packed;
+
+#define BTP_PACS_CHARACTERISTIC_SINK_PAC 0x01
+#define BTP_PACS_CHARACTERISTIC_SOURCE_PAC 0x02
+#define BTP_PACS_CHARACTERISTIC_SINK_AUDIO_LOCATIONS 0x03
+#define BTP_PACS_CHARACTERISTIC_SOURCE_AUDIO_LOCATIONS 0x04
+#define BTP_PACS_CHARACTERISTIC_AVAILABLE_AUDIO_CONTEXTS 0x05
+
+#endif /* BTP_PACS_H*/
diff --git a/apps/bttester/src/btp/bttester.h b/apps/bttester/src/btp/bttester.h
index 87068d2a7..6e1fb3a87 100644
--- a/apps/bttester/src/btp/bttester.h
+++ b/apps/bttester/src/btp/bttester.h
@@ -149,5 +149,12 @@ uint8_t
tester_unregister_bap(void);
#endif /* MYNEWT_VAL(BLE_AUDIO) */
+#if MYNEWT_VAL(BLE_AUDIO)
+uint8_t
+tester_init_pacs(void);
+uint8_t
+tester_unregister_pacs(void);
+#endif /* MYNEWT_VAL(BLE_AUDIO) */
+
#endif /* __BTTESTER_H__ */
diff --git a/apps/bttester/src/btp_core.c b/apps/bttester/src/btp_core.c
index eeae816a9..a1eafb300 100644
--- a/apps/bttester/src/btp_core.c
+++ b/apps/bttester/src/btp_core.c
@@ -107,6 +107,11 @@ register_service(const void *cmd, uint16_t cmd_len,
status = tester_init_bap();
break;
#endif /* MYNEWT_VAL(BLE_ISO_BROADCASTER) */
+#if MYNEWT_VAL(BLE_AUDIO)
+ case BTP_SERVICE_ID_PACS:
+ status = tester_init_pacs();
+ break;
+#endif /* MYNEWT(BLE_AUDIO) */
case BTP_SERVICE_ID_GATTC:
status = tester_init_gatt_cl();
break;
@@ -164,6 +169,11 @@ unregister_service(const void *cmd, uint16_t cmd_len,
status = tester_unregister_bap();
break;
#endif /* MYNEWT_VAL(BLE_ISO_BROADCAST_SOURCE) */
+#if MYNEWT_VAL(BLE_AUDIO)
+ case BTP_SERVICE_ID_PACS:
+ status = tester_unregister_pacs();
+ break;
+#endif /* MYNEWT_VAL (BLE_AUDIO) */
default:
status = BTP_STATUS_FAILED;
break;
diff --git a/apps/bttester/src/btp_pacs.c b/apps/bttester/src/btp_pacs.c
new file mode 100644
index 000000000..217d44df2
--- /dev/null
+++ b/apps/bttester/src/btp_pacs.c
@@ -0,0 +1,333 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* btp_pacs.c - Bluetooth Published Audio Capacity Service Tester */
+
+#include "audio/ble_audio.h"
+#include "audio/ble_audio_codec.h"
+#include "btp/bttester.h"
+#include "host/ble_gap.h"
+#include "os/util.h"
+#include "syscfg/syscfg.h"
+#include <stdint.h>
+
+#if MYNEWT_VAL(BLE_AUDIO)
+
+#include "btp/btp.h"
+#include "btp/btp_pacs.h"
+#include "services/pacs/ble_audio_svc_pacs.h"
+#include "services/pacs/ble_audio_svc_pacs_lc3.h"
+
+#define BLE_SVC_AUDIO_PACS_LC3_CODEC_ID 0x06
+#define BTTESTER_SUPPORTED_CTXTS 0x07
+
+struct set_avail_cb_data {
+ uint16_t src_ctxts;
+ uint16_t snk_ctxts;
+};
+
+#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SNK_METADATA
+static uint8_t ble_svc_audio_pacs_lc3_snk_metadata[] =
+{ UNMANGLE_MYNEWT_VAL(MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_METADATA)) };
+#endif
+
+static uint8_t ble_svc_audio_pacs_lc3_snk_codec_spec_caps[] =
BLE_AUDIO_BUILD_CODEC_CAPS(
+ MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_SAMPLING_FREQUENCIES),
+ MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_FRAME_DURATIONS),
+ #ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SRC_AUDIO_CHANNEL_COUNTS
+ MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_AUDIO_CHANNEL_COUNTS),
+ #else
+ ,
+ #endif
+ MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_MIN_OCTETS_PER_CODEC_FRAME),
+ MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_MAX_OCTETS_PER_CODEC_FRAME),
+ #ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SRC_MAX_CODEC_FRAMES_PER_SDU
+ MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_MAX_CODEC_FRAMES_PER_SDU),
+ #endif
+);
+
+static uint8_t ble_svc_audio_pacs_lc3_src_codec_spec_caps[] =
BLE_AUDIO_BUILD_CODEC_CAPS(
+ MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_SAMPLING_FREQUENCIES),
+ MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_FRAME_DURATIONS),
+#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SRC_AUDIO_CHANNEL_COUNTS
+ MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_AUDIO_CHANNEL_COUNTS),
+#else
+ ,
+#endif
+ MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_MIN_OCTETS_PER_CODEC_FRAME),
+ MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_MAX_OCTETS_PER_CODEC_FRAME),
+#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SRC_MAX_CODEC_FRAMES_PER_SDU
+ MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_MAX_CODEC_FRAMES_PER_SDU),
+#endif
+);
+
+static struct ble_audio_codec_register_params snk_codec_params = {
+ .codec_id = {
+ .format = BLE_SVC_AUDIO_PACS_LC3_CODEC_ID,
+ .company_id = 0x00,
+ .vendor_specific = 0x00
+ },
+ .codec_spec_caps_len = sizeof(ble_svc_audio_pacs_lc3_snk_codec_spec_caps),
+ .codec_spec_caps = ble_svc_audio_pacs_lc3_snk_codec_spec_caps,
+#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SNK_METADATA
+ .metadata_len = sizeof(ble_svc_audio_pacs_lc3_snk_metadata),
+ .metadata = ble_svc_audio_pacs_lc3_snk_metadata,
+#else
+ .metadata_len = 0,
+#endif
+
+ .direction = BLE_AUDIO_CODEC_DIR_SINK_BIT
+};
+
+static struct ble_audio_codec_register_params src_codec_params = {
+ .codec_id = {
+ .format = BLE_SVC_AUDIO_PACS_LC3_CODEC_ID,
+ .company_id = 0x00,
+ .vendor_specific = 0x00
+ },
+ .codec_spec_caps_len = sizeof(ble_svc_audio_pacs_lc3_src_codec_spec_caps),
+ .codec_spec_caps = ble_svc_audio_pacs_lc3_src_codec_spec_caps,
+#ifdef MYNEWT_VAL_BLE_SVC_AUDIO_PACS_LC3_SRC_METADATA
+ .metadata_len = sizeof(ble_svc_audio_pacs_lc3_src_metadata),
+ .metadata = ble_svc_audio_pacs_lc3_src_metadata,
+#else
+ .metadata_len = 0,
+#endif
+ .direction = BLE_AUDIO_CODEC_DIR_SOURCE_BIT
+};
+
+int
+set_available(uint16_t conn_handle, void *arg)
+{
+ int rc;
+ struct set_avail_cb_data *avail_data = arg;
+
+ rc = ble_svc_audio_pacs_avail_contexts_set(conn_handle,
+ avail_data->snk_ctxts,
+ avail_data->src_ctxts);
+ if (rc) {
+ return BTP_STATUS_FAILED;
+ }
+
+ return BTP_STATUS_SUCCESS;
+}
+
+static uint8_t
+pacs_set_available_contexts(const void *cmd, uint16_t cmd_len,
+ void *rsp, uint16_t *rsp_len)
+{
+ const struct btp_pacs_set_available_contexts_cmd *cp = cmd;
+ uint16_t source_contexts = le16toh(cp->source_contexts);
+ uint16_t sink_conexts = le16toh(cp->sink_contexts);
+ struct set_avail_cb_data cb_data;
+
+ /* If this originated from pacs_update_characteristic - we update with
unspecified */
+ if (sink_conexts == BTP_PACS_CHARACTERISTIC_AVAILABLE_AUDIO_CONTEXTS) {
+ cb_data.snk_ctxts = BLE_AUDIO_CONTEXT_TYPE_UNSPECIFIED;
+ cb_data.src_ctxts = BLE_AUDIO_CONTEXT_TYPE_UNSPECIFIED;
+ } else {
+ cb_data.snk_ctxts = sink_conexts;
+ cb_data.src_ctxts = source_contexts;
+ }
+
+ ble_gap_conn_foreach_handle(set_available, &cb_data);
+
+ return BTP_STATUS_SUCCESS;
+}
+
+static uint8_t
+pacs_set_snk_location(void)
+{
+ int rc;
+ struct ble_svc_audio_pacs_set_param snk_params = {
+ .audio_locations = 0,
+ .supported_contexts =
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SNK_SUP_CONTEXTS)
+ };
+
+ rc = ble_svc_audio_pacs_set(BLE_AUDIO_CODEC_DIR_SINK_BIT, &snk_params);
+ if (rc) {
+ return BTP_STATUS_FAILED;
+ }
+
+ return BTP_STATUS_SUCCESS;
+}
+
+static uint8_t
+pacs_set_src_location(void)
+{
+ int rc;
+ struct ble_svc_audio_pacs_set_param src_params = {
+ .audio_locations = 0,
+ .supported_contexts =
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_SUP_CONTEXTS)
+ };
+
+ rc = ble_svc_audio_pacs_set(BLE_AUDIO_CODEC_DIR_SOURCE_BIT, &src_params);
+ if (rc) {
+ return BTP_STATUS_FAILED;
+ }
+
+ return BTP_STATUS_SUCCESS;
+}
+
+static uint8_t
+pacs_update_characteristic(const void *cmd, uint16_t cmd_len,
+ void *rsp, uint16_t *rsp_len)
+{
+ int rc;
+ const struct btp_pacs_update_characteristic_cmd *cp = cmd;
+
+ switch (cp->char_id) {
+ case BTP_PACS_CHARACTERISTIC_SINK_PAC:
+ rc = ble_audio_codec_register(&snk_codec_params, NULL);
+ if (rc) {
+ return BTP_STATUS_FAILED;
+ }
+ break;
+ case BTP_PACS_CHARACTERISTIC_SOURCE_PAC:
+ rc = ble_audio_codec_register(&src_codec_params, NULL);
+ if (rc) {
+ return BTP_STATUS_FAILED;
+ }
+ break;
+ case BTP_PACS_CHARACTERISTIC_SINK_AUDIO_LOCATIONS:
+ rc = pacs_set_snk_location();
+ if (rc) {
+ return BTP_STATUS_FAILED;
+ }
+ break;
+ case BTP_PACS_CHARACTERISTIC_SOURCE_AUDIO_LOCATIONS:
+ rc = pacs_set_src_location();
+ if (rc) {
+ return BTP_STATUS_FAILED;
+ }
+ break;
+ case BTP_PACS_CHARACTERISTIC_AVAILABLE_AUDIO_CONTEXTS:
+ rc = pacs_set_available_contexts(cmd, cmd_len, rsp, rsp_len);
+ if (rc) {
+ return BTP_STATUS_FAILED;
+ }
+ break;
+ default:
+ return BTP_STATUS_FAILED;
+ }
+
+ return BTP_STATUS_SUCCESS;
+}
+
+static uint8_t
+pacs_set_supported_contexts(const void *cmd, uint16_t cmd_len,
+ void *rsp, uint16_t *rsp_len)
+{
+ int rc;
+ const struct btp_pacs_set_supported_contexts_cmd *sup_ctxts = cmd;
+
+ struct ble_svc_audio_pacs_set_param src_params = {
+ .audio_locations = 0,
+ .supported_contexts = sup_ctxts->source_contexts,
+ };
+ struct ble_svc_audio_pacs_set_param snk_params = {
+ .audio_locations = 0,
+ .supported_contexts = sup_ctxts->sink_contexts,
+ };
+
+ rc = ble_svc_audio_pacs_set(BLE_AUDIO_CODEC_DIR_SOURCE_BIT, &src_params);
+ if (rc) {
+ return BTP_STATUS_FAILED;
+ }
+
+ rc = ble_svc_audio_pacs_set(BLE_AUDIO_CODEC_DIR_SINK_BIT, &snk_params);
+ if (rc) {
+ return BTP_STATUS_FAILED;
+ }
+
+ return BTP_STATUS_SUCCESS;
+}
+
+static uint8_t
+supported_commands(const void *cmd, uint16_t cmd_len,
+ void *rsp, uint16_t *rsp_len)
+{
+ struct btp_pacs_read_supported_commands_rp *rp = rsp;
+
+ /* octet 0 */
+ tester_set_bit(rp->data, BTP_PACS_READ_SUPPORTED_COMMANDS);
+ tester_set_bit(rp->data, BTP_PACS_UPDATE_CHARACTERISTIC);
+ tester_set_bit(rp->data, BTP_PACS_SET_AVAILABLE_CONTEXTS);
+ tester_set_bit(rp->data, BTP_PACS_SET_SUPPORTED_CONTEXTS);
+
+ *rsp_len = sizeof(*rp) + 1;
+
+ return BTP_STATUS_SUCCESS;
+}
+
+static const struct btp_handler handlers[] = {
+ {
+ .opcode = BTP_PACS_READ_SUPPORTED_COMMANDS,
+ .expect_len = 0,
+ .func = supported_commands,
+ },
+ {
+ .opcode = BTP_PACS_UPDATE_CHARACTERISTIC,
+ .expect_len = sizeof(struct btp_pacs_update_characteristic_cmd),
+ .func = pacs_update_characteristic,
+ },
+ {
+ .opcode = BTP_PACS_SET_AVAILABLE_CONTEXTS,
+ .expect_len = sizeof(struct btp_pacs_set_available_contexts_cmd),
+ .func = pacs_set_available_contexts,
+ },
+ {
+ .opcode = BTP_PACS_SET_SUPPORTED_CONTEXTS,
+ .expect_len = sizeof(struct btp_pacs_set_supported_contexts_cmd),
+ .func = pacs_set_supported_contexts,
+ },
+};
+
+uint8_t
+tester_init_pacs(void)
+{
+ int rc;
+ struct ble_svc_audio_pacs_set_param src_params = {
+ .audio_locations =
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_AUDIO_LOCATIONS),
+ .supported_contexts = BTTESTER_SUPPORTED_CTXTS
+ };
+ struct ble_svc_audio_pacs_set_param snk_params = {
+ .audio_locations =
MYNEWT_VAL(BLE_SVC_AUDIO_PACS_LC3_SRC_AUDIO_LOCATIONS),
+ .supported_contexts = BTTESTER_SUPPORTED_CTXTS
+ };
+
+ rc = ble_svc_audio_pacs_set(BLE_AUDIO_CODEC_DIR_SOURCE_BIT, &src_params);
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ rc = ble_svc_audio_pacs_set(BLE_AUDIO_CODEC_DIR_SINK_BIT, &snk_params);
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ tester_register_command_handlers(BTP_SERVICE_ID_PACS, handlers,
+ ARRAY_SIZE(handlers));
+
+ return BTP_STATUS_SUCCESS;
+}
+
+uint8_t
+tester_unregister_pacs(void)
+{
+ return BTP_STATUS_SUCCESS;
+}
+
+#endif /* MYNEWT_VAL(BLE_AUDIO)*/
diff --git a/apps/bttester/syscfg.yml b/apps/bttester/syscfg.yml
index fea32fccd..140b664e7 100644
--- a/apps/bttester/syscfg.yml
+++ b/apps/bttester/syscfg.yml
@@ -87,6 +87,7 @@ syscfg.defs:
value: '"test_broadcast"'
syscfg.vals:
+ BLE_AUDIO_MAX_CODEC_RECORDS: 3
CONSOLE_IMPLEMENTATION: full
LOG_IMPLEMENTATION: full
STATS_IMPLEMENTATION: full