diff --git a/apps/bttester/pkg.yml b/apps/bttester/pkg.yml index e763185fe5..ce0fa25549 100644 --- a/apps/bttester/pkg.yml +++ b/apps/bttester/pkg.yml @@ -32,11 +32,13 @@ pkg.deps: - "@apache-mynewt-core/sys/stats" - "@apache-mynewt-core/sys/shell" - "@apache-mynewt-nimble/nimble/host" + - "@apache-mynewt-nimble/nimble/host/audio" - "@apache-mynewt-nimble/nimble/host/util" - "@apache-mynewt-nimble/nimble/host/services/gap" - "@apache-mynewt-nimble/nimble/host/services/gatt" - "@apache-mynewt-nimble/nimble/host/services/dis" + - "@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 4403a16038..17fe388767 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 0000000000..73da8dad80 --- /dev/null +++ b/apps/bttester/src/btp/btp_pacs.h @@ -0,0 +1,43 @@ +/* + * 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 + +#ifndef __packed +#define __packed __attribute__((__packed__)) +#endif + +#define BTP_PACS_READ_SUPPORTED_COMMANDS 0x01 +#define BTP_PACS_UPDATE_CHARACTERISTIC 0x02 +#define BTP_PACS_SET_LOCATION 0x03 +#define BTP_PACS_SET_AVAILABLE_CONTEXTS 0x04 +#define BTP_PACS_SET_SUPPORTED_CONTEXTS 0x05 + +struct btp_pacs_read_supported_commands_rp { + uint8_t data[0]; +} __packed; + +struct pacs_update_characteristic_cmd { + uint8_t char_id; +} __packed; + +#endif /* BTP_PACS_H*/ diff --git a/apps/bttester/src/btp/bttester.h b/apps/bttester/src/btp/bttester.h index 5d7e1219d2..8dd9d3691e 100644 --- a/apps/bttester/src/btp/bttester.h +++ b/apps/bttester/src/btp/bttester.h @@ -32,6 +32,7 @@ #include "syscfg/syscfg.h" #include "host/ble_gatt.h" #include "os/os_mbuf.h" +#include #include #define BIT(n) (1UL << (n)) @@ -149,5 +150,12 @@ uint8_t tester_unregister_bap(void); #endif /* MYNEWT_VAL(BLE_ISO_BROADCASTER) */ +#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 f7a4bc4f92..8b6903f85d 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_BROADCASTER) */ +#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 0000000000..4594dcbc60 --- /dev/null +++ b/apps/bttester/src/btp_pacs.c @@ -0,0 +1,288 @@ +/* + * 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 "host/ble_gap.h" +#include "syscfg/syscfg.h" +#include + +#if MYNEWT_VAL(BLE_AUDIO) + +#include "btp/btp.h" +#include "btp/btp_pacs.h" +#include "services/pacs/ble_audio_svc_pacs.h" + +#define BLE_SVC_AUDIO_PACS_LC3_CODEC_ID 0x06 + +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 = + (struct set_avail_cb_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() +{ + struct set_avail_cb_data cb_data; + + cb_data.snk_ctxts = 5; + cb_data.src_ctxts = 5; + + ble_gap_conn_foreach_handle(set_available, (void *)&cb_data); + + return BTP_STATUS_SUCCESS; +} + +static uint8_t +pacs_set_snk_location() +{ + 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() +{ + 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 pacs_update_characteristic_cmd *char_cmd = cmd; + switch (char_cmd->char_id) { + case 0x01: + rc = ble_audio_codec_register(&snk_codec_params, NULL); + if (rc) { + return BTP_STATUS_FAILED; + } + case 0x02: + rc = ble_audio_codec_register(&src_codec_params, NULL); + if (rc) { + return BTP_STATUS_FAILED; + } + case 0x03: + rc = pacs_set_snk_location(); + if (rc) { + return BTP_STATUS_FAILED; + } + case 0x04: + rc = pacs_set_src_location(); + if (rc) { + return BTP_STATUS_FAILED; + } + case 0x05: + rc = pacs_set_available_contexts(); + if (rc) { + 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) +{ + return BTP_STATUS_SUCCESS; +} + +static uint8_t +pacs_set_location_dummy(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + 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_LOCATION); + tester_set_bit(rp->data, BTP_PACS_SET_AVAILABLE_CONTEXTS); + tester_set_bit(rp->data, BTP_PACS_SET_SUPPORTED_CONTEXTS); + + *rsp_len = sizeof(*rp) + 2; + + 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 = BTP_HANDLER_LENGTH_VARIABLE, + .func = pacs_update_characteristic, + }, + { + .opcode = BTP_PACS_SET_LOCATION, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = pacs_set_location_dummy, + }, + { + .opcode = BTP_PACS_SET_AVAILABLE_CONTEXTS, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = pacs_update_characteristic, + }, + { + .opcode = BTP_PACS_SET_SUPPORTED_CONTEXTS, + .expect_len = BTP_HANDLER_LENGTH_VARIABLE, + .func = pacs_set_supported_contexts, + }, +}; + +uint8_t +tester_init_pacs(void) +{ + 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)*/ \ No newline at end of file diff --git a/apps/bttester/syscfg.yml b/apps/bttester/syscfg.yml index bb4d6f775f..42ae3a2199 100644 --- a/apps/bttester/syscfg.yml +++ b/apps/bttester/syscfg.yml @@ -86,7 +86,9 @@ syscfg.defs: description: Broadcast name value: '"test_broadcast"' + syscfg.vals: + BLE_AUDIO_MAX_CODEC_RECORDS: 5 CONSOLE_IMPLEMENTATION: full LOG_IMPLEMENTATION: full STATS_IMPLEMENTATION: full @@ -161,5 +163,10 @@ syscfg.vals: BLE_MESH_TX_SEG_MSG_COUNT: 2 BLE_MAX_CONNECTIONS: 8 - +syscfg.vals.BSP_NRF5340: + MCU_MPU_ENABLE: 1 + MCU_CACHE_ENABLED: 1 + BSP_NRF5340_NET_ENABLE: 1 + NRF5340_EMBED_NET_CORE: 1 + NET_CORE_IMAGE_TARGET_NAME: "@apache-mynewt-nimble/targets/nordic_pca10095_net-blehci_broadcaster" diff --git a/nimble/host/audio/services/pacs/src/ble_audio_svc_pacs.c b/nimble/host/audio/services/pacs/src/ble_audio_svc_pacs.c index 9b124a5a97..d91722fc8d 100644 --- a/nimble/host/audio/services/pacs/src/ble_audio_svc_pacs.c +++ b/nimble/host/audio/services/pacs/src/ble_audio_svc_pacs.c @@ -385,7 +385,7 @@ ble_svc_audio_pacs_set(uint8_t flags, struct ble_svc_audio_pacs_set_param *param if (flags & BLE_AUDIO_CODEC_DIR_SINK_BIT) { ble_svc_audio_pacs_sink_audio_locations = param->audio_locations; ble_svc_audio_pacs_sup_sink_contexts = param->supported_contexts; - rc = pac_notify(BLE_SVC_AUDIO_PACS_CHR_UUID16_SOURCE_AUDIO_LOCATIONS); + rc = pac_notify(BLE_SVC_AUDIO_PACS_CHR_UUID16_SINK_AUDIO_LOCATIONS); if (rc != 0) { return rc; }