diff --git a/nimble/host/audio/include/host/audio/ble_audio.h b/nimble/host/audio/include/host/audio/ble_audio.h new file mode 100644 index 000000000..52d1e8a05 --- /dev/null +++ b/nimble/host/audio/include/host/audio/ble_audio.h @@ -0,0 +1,155 @@ +/* + * 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 H_BLE_AUDIO_ +#define H_BLE_AUDIO_ + +#include + +#include "host/ble_audio_common.h" + +/** + * BASE iterator + * + * The iterator structure used by @ref ble_audio_base_subgroup_iter and + * @ble_audio_base_bis_iter functions to iterate the BASE Level 2 and 3 elements + * (Subgroups and BISes). + * This should be used as an opaque structure and not modified manually. + * + * Example: + * @code{.c} + * struct ble_audio_base_iter subgroup_iter; + * struct ble_audio_base_iter bis_iter; + * struct ble_audio_base_group group; + * struct ble_audio_base_subgroup subgroup; + * struct ble_audio_base_bis bis; + * + * rc = ble_audio_base_parse(data, data_size, &group, &subgroup_iter); + * if (rc == 0) { + * for (uint8_t i = 0; i < group->num_subgroups; i++) { + * rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + * if (rc == 0) { + * for (uint8_t j = 0; j < subgroup->num_bis; j++) { + * rc = ble_audio_base_bis_iter(&bis_iter, &bis); + * if (rc == 0) { + * foo(&group, &subgroup, &bis); + * } + * } + * } + * } + * } + * @endcode + */ +struct ble_audio_base_iter { + /** Data pointer */ + const uint8_t *data; + + /** Base length */ + uint8_t buf_len; + + /** Original BASE pointer */ + const uint8_t *buf; + + /** Remaining number of elements */ + uint8_t num_elements; +}; + +/** @brief Broadcast Audio Source Endpoint Group structure */ +struct ble_audio_base_group { + /** Presentation Delay */ + uint32_t presentation_delay; + + /** Number of subgroups */ + uint8_t num_subgroups; +}; + +/** + * Parse the BASE received from Basic Audio Announcement data. + * + * @param[in] data Pointer to the BASE data buffer to parse. + * @param[in] data_len Length of the BASE data buffer. + * @param[out] group Group object. + * @param[out] subgroup_iter Subgroup iterator object. + * + * @return 0 on success; nonzero on failure. + */ +int ble_audio_base_parse(const uint8_t *data, uint8_t data_len, + struct ble_audio_base_group *group, + struct ble_audio_base_iter *subgroup_iter); + +/** @brief Broadcast Audio Source Endpoint Subgroup structure */ +struct ble_audio_base_subgroup { + /** Codec information for the subgroup */ + struct ble_audio_codec_id codec_id; + + /** Length of the Codec Specific Configuration for the subgroup */ + uint8_t codec_spec_config_len; + + /** Codec Specific Configuration for the subgroup */ + const uint8_t *codec_spec_config; + + /** Length of the Metadata for the subgroup */ + uint8_t metadata_len; + + /** Series of LTV structures containing Metadata */ + const uint8_t *metadata; + + /** Number of BISes in the subgroup */ + uint8_t num_bis; +}; + +/** + * @brief Basic Audio Announcement Subgroup information + * + * @param[in] subgroup_iter Subgroup iterator object. + * @param[out] subgroup Subgroup object. + * @param[out] bis_iter BIS iterator object. + * + * @return 0 on success; + * A non-zero value on failure. + */ +int ble_audio_base_subgroup_iter(struct ble_audio_base_iter *subgroup_iter, + struct ble_audio_base_subgroup *subgroup, + struct ble_audio_base_iter *bis_iter); + +/** @brief Broadcast Audio Source Endpoint BIS structure */ +struct ble_audio_base_bis { + /** BIS_index value for the BIS */ + uint8_t index; + + /** Length of the Codec Specific Configuration for the BIS */ + uint8_t codec_spec_config_len; + + /** Codec Specific Configuration for the BIS */ + const uint8_t *codec_spec_config; +}; + +/** + * @brief Basic Audio Announcement Subgroup information + * + * @param[in] bis_iter BIS iterator object. + * @param[out] bis BIS object. + * + * @return 0 on success; + * A non-zero value on failure. + */ +int ble_audio_base_bis_iter(struct ble_audio_base_iter *bis_iter, + struct ble_audio_base_bis *bis); + +#endif /* H_BLE_AUDIO_ */ diff --git a/nimble/host/audio/pkg.yml b/nimble/host/audio/pkg.yml new file mode 100644 index 000000000..66d418d31 --- /dev/null +++ b/nimble/host/audio/pkg.yml @@ -0,0 +1,32 @@ +# +# 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. +# + +pkg.name: nimble/host/audio +pkg.description: Bluetooth LE Audio +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.experimental: 1 +pkg.keywords: + - ble + - bluetooth + - audio + +pkg.deps: + - nimble + - nimble/host diff --git a/nimble/host/audio/src/ble_audio.c b/nimble/host/audio/src/ble_audio.c new file mode 100644 index 000000000..2ac5c68e3 --- /dev/null +++ b/nimble/host/audio/src/ble_audio.c @@ -0,0 +1,298 @@ +/* + * 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. + */ + +#include +#include + +#include "host/ble_hs.h" +#include "host/audio/ble_audio.h" + +/* Get the next subgroup data pointer */ +static const uint8_t * +ble_audio_base_subgroup_next(uint8_t num_bis, const uint8_t *data, + uint8_t data_len) +{ + uint8_t offset = 0; + + for (uint8_t i = 0; i < num_bis; i++) { + uint8_t codec_specific_config_len; + + /* BIS_index[i[k]] + Codec_Specific_Configuration_Length[i[k]] */ + if ((data_len - offset) < 2) { + return NULL; + } + + /* Skip BIS_index[i[k]] */ + offset++; + + codec_specific_config_len = data[offset]; + offset++; + + if ((data_len - offset) < codec_specific_config_len) { + return NULL; + } + + offset += codec_specific_config_len; + } + + return &data[offset]; +} + +int +ble_audio_base_parse(const uint8_t *data, uint8_t data_len, + struct ble_audio_base_group *group, + struct ble_audio_base_iter *subgroup_iter) +{ + uint8_t offset = 0; + + if (data == NULL) { + BLE_HS_LOG_ERROR("NULL data!\n"); + return BLE_HS_EINVAL; + } + + if (group == NULL) { + BLE_HS_LOG_ERROR("NULL group!\n"); + return BLE_HS_EINVAL; + } + + /* Presentation_Delay + Num_Subgroups */ + if (data_len < 4) { + return BLE_HS_EMSGSIZE; + } + + group->presentation_delay = get_le24(data); + offset += 3; + + group->num_subgroups = data[offset]; + offset++; + + if (group->num_subgroups < 1) { + BLE_HS_LOG_ERROR("Invalid BASE: no subgroups!\n"); + return BLE_HS_EINVAL; + } + + if (subgroup_iter != NULL) { + subgroup_iter->data = &data[offset]; + subgroup_iter->buf_len = data_len; + subgroup_iter->buf = data; + subgroup_iter->num_elements = group->num_subgroups; + } + + return 0; +} + +int +ble_audio_base_subgroup_iter(struct ble_audio_base_iter *subgroup_iter, + struct ble_audio_base_subgroup *subgroup, + struct ble_audio_base_iter *bis_iter) +{ + const uint8_t *data; + uint8_t data_len; + ptrdiff_t offset; + uint8_t num_subgroups; + + if (subgroup_iter == NULL) { + BLE_HS_LOG_ERROR("NULL subgroup_iter!\n"); + return BLE_HS_EINVAL; + } + + if (subgroup == NULL) { + BLE_HS_LOG_ERROR("NULL subgroup!\n"); + return BLE_HS_EINVAL; + } + + data = subgroup_iter->data; + if (data == NULL) { + return BLE_HS_ENOENT; + } + + offset = data - subgroup_iter->buf; + if (offset < 0 || offset > subgroup_iter->buf_len) { + return BLE_HS_EINVAL; + } + + num_subgroups = subgroup_iter->num_elements; + if (num_subgroups == 0) { + /* All subgroups have been parsed */ + return BLE_HS_ENOENT; + } + + data_len = subgroup_iter->buf_len - offset; + + /* Reset the offset */ + offset = 0; + + memset(subgroup, 0, sizeof(*subgroup)); + + /* Num_BIS + Codec_ID + Codec_Specific_Configuration_Length[i] */ + if (data_len < 7) { + return BLE_HS_EMSGSIZE; + } + + subgroup->num_bis = data[offset]; + offset++; + + if (subgroup->num_bis < 1) { + BLE_HS_LOG_ERROR("Invalid BASE: no BISes!\n"); + return BLE_HS_EINVAL; + } + + subgroup->codec_id.format = data[offset]; + offset++; + + subgroup->codec_id.company_id = get_le16(&data[offset]); + offset += 2; + + subgroup->codec_id.vendor_specific = get_le16(&data[offset]); + offset += 2; + + subgroup->codec_spec_config_len = data[offset]; + offset++; + + if (subgroup->codec_spec_config_len < 1) { + BLE_HS_LOG_DEBUG("Rule 4: Codec_Specific_Configuration parameters shall" + "be present at Level 2\n"); + } + + if ((data_len - offset) < subgroup->codec_spec_config_len) { + return BLE_HS_EMSGSIZE; + } + + subgroup->codec_spec_config = &data[offset]; + offset += subgroup->codec_spec_config_len; + + /* Metadata_Length[i] */ + if ((data_len - offset) < 1) { + return BLE_HS_EMSGSIZE; + } + + subgroup->metadata_len = data[offset]; + offset++; + + if (subgroup->metadata_len > 0) { + if ((data_len - offset) < subgroup->metadata_len) { + return BLE_HS_EMSGSIZE; + } + + subgroup->metadata = &data[offset]; + offset += subgroup->metadata_len; + } else { + subgroup->metadata = NULL; + } + + if (bis_iter != 0) { + bis_iter->data = &data[offset]; + bis_iter->buf_len = subgroup_iter->buf_len; + bis_iter->buf = subgroup_iter->buf; + bis_iter->num_elements = subgroup->num_bis; + } + + num_subgroups--; + + /* Update iterator */ + subgroup_iter->num_elements = num_subgroups; + + if (num_subgroups > 0) { + subgroup_iter->data = ble_audio_base_subgroup_next(subgroup->num_bis, + &data[offset], + data_len - offset); + } else { + subgroup_iter->data = NULL; + } + + return 0; +} + +int +ble_audio_base_bis_iter(struct ble_audio_base_iter *bis_iter, + struct ble_audio_base_bis *bis) +{ + const uint8_t *data; + uint8_t data_len; + ptrdiff_t offset; + uint8_t num_bis; + + if (bis_iter == NULL) { + BLE_HS_LOG_ERROR("NULL bis_iter!\n"); + return BLE_HS_EINVAL; + } + + if (bis == NULL) { + BLE_HS_LOG_ERROR("NULL bis!\n"); + return BLE_HS_EINVAL; + } + + data = bis_iter->data; + if (data == NULL) { + return BLE_HS_ENOENT; + } + + offset = data - bis_iter->buf; + if (offset < 0 || offset > bis_iter->buf_len) { + return BLE_HS_EINVAL; + } + + num_bis = bis_iter->num_elements; + if (num_bis == 0) { + /* All BISes have been parsed */ + return BLE_HS_ENOENT; + } + + data_len = bis_iter->buf_len - offset; + + /* Reset the offset */ + offset = 0; + + memset(bis, 0, sizeof(*bis)); + + /* BIS_index[i[k]] + Codec_Specific_Configuration_Length[i[k]] */ + if (data_len < 2) { + return BLE_HS_EMSGSIZE; + } + + bis->index = data[0]; + offset++; + + bis->codec_spec_config_len = data[offset]; + offset++; + + if (bis->codec_spec_config_len > 0) { + if ((data_len - offset) < bis->codec_spec_config_len) { + return BLE_HS_EMSGSIZE; + } + + bis->codec_spec_config = &data[offset]; + offset += bis->codec_spec_config_len; + } else { + bis->codec_spec_config = NULL; + } + + num_bis--; + + /* Update iterator */ + bis_iter->num_elements = num_bis; + + if (num_bis > 0) { + bis_iter->data = &data[offset]; + } else { + bis_iter->data = NULL; + } + + return 0; +} diff --git a/nimble/host/audio/syscfg.yml b/nimble/host/audio/syscfg.yml new file mode 100644 index 000000000..d7af13d1a --- /dev/null +++ b/nimble/host/audio/syscfg.yml @@ -0,0 +1,21 @@ +# 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. +# + +syscfg.defs: + +syscfg.logs: diff --git a/nimble/host/audio/test/pkg.yml b/nimble/host/audio/test/pkg.yml new file mode 100644 index 000000000..5020e9fa4 --- /dev/null +++ b/nimble/host/audio/test/pkg.yml @@ -0,0 +1,38 @@ +# +# 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. +# + +pkg.name: nimble/host/audio/test +pkg.type: unittest +pkg.description: "BLE Audio unit tests." +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + +pkg.deps: + - "@apache-mynewt-core/test/testutil" + - nimble/host/audio + +pkg.deps.SELFTEST: + - "@apache-mynewt-core/sys/console/stub" + - "@apache-mynewt-core/sys/log/full" + - "@apache-mynewt-core/sys/stats/stub" + - nimble/drivers/native + +pkg.apis: + - ble_driver diff --git a/nimble/host/audio/test/src/ble_audio_test.c b/nimble/host/audio/test/src/ble_audio_test.c new file mode 100644 index 000000000..14fcf15f5 --- /dev/null +++ b/nimble/host/audio/test/src/ble_audio_test.c @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#include "sysinit/sysinit.h" +#include "testutil/testutil.h" + +TEST_SUITE_DECL(ble_audio_base_parse_test_suite); + +TEST_SUITE(ble_audio_test) +{ + ble_audio_base_parse_test_suite(); +} + +int +main(int argc, char **argv) +{ + sysinit(); + + ble_audio_test(); + + return tu_any_failed; +} diff --git a/nimble/host/audio/test/src/testcases/ble_audio_base_parse_test.c b/nimble/host/audio/test/src/testcases/ble_audio_base_parse_test.c new file mode 100644 index 000000000..2398d62dd --- /dev/null +++ b/nimble/host/audio/test/src/testcases/ble_audio_base_parse_test.c @@ -0,0 +1,361 @@ +/* + * 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. + */ + +#include "testutil/testutil.h" + +#include "host/ble_hs.h" +#include "host/audio/ble_audio.h" + +/** + * BAP_v1.0.1 Table 3.16 + * BASE structure for the logical BASE structure example + */ +static const uint8_t example_base[] = { + 0x1e, 0x00, 0x00, /* Presentation_Delay: 40 ms */ + 0x02, /* Num_Subgroups: 2 Subgroups */ + 0x02, /* Num_BIS[0]: 2 BIS in Subgroup[0] */ + 0x06, 0x00, 0x00, 0x00, 0x00, /* Codec_ID[0]: LC3 */ + 0x0a, /* Codec_Specific_Configuration_Length[0] */ + 0x02, 0x01, 0x08, /* LTV 1: Sampling_Frequency: 48000 Hz */ + 0x02, 0x02, 0x02, /* LTV 2: Frame_Duration: 10 ms */ + 0x03, 0x04, 0x64, 0x00, /* LTV 3: Octets_Per_Codec_Frame: 100 octets */ + 0x09, /* Metadata_Length[0] */ + 0x03, 0x02, 0x04, 0x00, /* LTV 1: Streaming_Audio_Contexts: Media */ + 0x04, 0x04, 0x73, 0x70, 0x61, /* LTV 2: Language: Spanish */ + 0x01, /* BIS_index[0[0]] */ + 0x06, /* Codec_Specific_Configuration_Length[0[0]] */ + 0x05, 0x03, 0x01, 0x00, 0x00, 0x00, /* LTV 1 = Audio_Channel_Allocation: FL */ + 0x02, /* BIS_index[0[1]] */ + 0x06, /* Codec_Specific_Configuration_Length[0[1]] */ + 0x05, 0x03, 0x02, 0x00, 0x00, 0x00, /* LTV 1 = Audio_Channel_Allocation: FR */ + 0x02, /* Num_BIS[1]: 2 BIS in Subgroup[0] */ + 0x06, 0x00, 0x00, 0x00, 0x00, /* Codec_ID[1]: LC3 */ + 0x0a, /* Codec_Specific_Configuration_Length[1] */ + 0x02, 0x01, 0x08, /* LTV 1: Sampling_Frequency: 48000 Hz */ + 0x02, 0x02, 0x02, /* LTV 2: Frame_Duration: 10 ms */ + 0x03, 0x04, 0x64, 0x00, /* LTV 3: Octets_Per_Codec_Frame: 100 octets */ + 0x09, /* Metadata_Length[1] */ + 0x03, 0x02, 0x04, 0x00, /* LTV 1: Streaming_Audio_Contexts: Media */ + 0x04, 0x04, 0x65, 0x6e, 0x67, /* LTV 2: Language: English */ + 0x03, /* BIS_index[1[0]] */ + 0x06, /* Codec_Specific_Configuration_Length[1[0]] */ + 0x05, 0x03, 0x01, 0x00, 0x00, 0x00, /* LTV 1 = Audio_Channel_Allocation: FL */ + 0x04, /* BIS_index[1[1]] */ + 0x06, /* Codec_Specific_Configuration_Length[1[1]] */ + 0x05, 0x03, 0x02, 0x00, 0x00, 0x00, /* LTV 1 = Audio_Channel_Allocation: FR */ +}; + +TEST_CASE_SELF(ble_audio_base_parse_test) +{ + struct ble_audio_base_subgroup subgroup; + struct ble_audio_base_group group; + struct ble_audio_base_bis bis; + struct ble_audio_base_iter subgroup_iter; + struct ble_audio_base_iter bis_iter; + int rc; + + rc = ble_audio_base_parse(example_base, (uint8_t)sizeof(example_base), + &group, &subgroup_iter); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(group.presentation_delay == 30); + TEST_ASSERT(group.num_subgroups == 2); + + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(subgroup.codec_id.format == 0x06); + TEST_ASSERT(subgroup.codec_id.company_id == 0x0000); + TEST_ASSERT(subgroup.codec_id.vendor_specific == 0x0000); + TEST_ASSERT(subgroup.codec_spec_config_len == 10); + TEST_ASSERT(subgroup.codec_spec_config != NULL); + TEST_ASSERT(subgroup.metadata_len == 9); + TEST_ASSERT(subgroup.num_bis == 2); + + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(bis.index == 0x01); + TEST_ASSERT(bis.codec_spec_config_len == 6); + TEST_ASSERT(bis.codec_spec_config != NULL); + + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(bis.index == 0x02); + TEST_ASSERT(bis.codec_spec_config_len == 6); + TEST_ASSERT(bis.codec_spec_config != NULL); + + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_ENOENT); + + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(subgroup.codec_id.format == 0x06); + TEST_ASSERT(subgroup.codec_id.company_id == 0x0000); + TEST_ASSERT(subgroup.codec_id.vendor_specific == 0x0000); + TEST_ASSERT(subgroup.codec_spec_config_len == 10); + TEST_ASSERT(subgroup.codec_spec_config != NULL); + TEST_ASSERT(subgroup.metadata_len == 9); + TEST_ASSERT(subgroup.num_bis == 2); + + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(bis.index == 0x03); + TEST_ASSERT(bis.codec_spec_config_len == 6); + TEST_ASSERT(bis.codec_spec_config != NULL); + + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(bis.index == 0x04); + TEST_ASSERT(bis.codec_spec_config_len == 6); + TEST_ASSERT(bis.codec_spec_config != NULL); + + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_ENOENT); + + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_ENOENT); +} + +TEST_CASE_SELF(ble_audio_base_parse_test_params) +{ + struct ble_audio_base_subgroup subgroup; + struct ble_audio_base_group group; + struct ble_audio_base_bis bis; + struct ble_audio_base_iter subgroup_iter; + struct ble_audio_base_iter bis_iter; + int rc; + + rc = ble_audio_base_parse(NULL, (uint8_t)sizeof(example_base), &group, &subgroup_iter); + TEST_ASSERT(rc == BLE_HS_EINVAL); + + rc = ble_audio_base_parse(NULL, (uint8_t)sizeof(example_base), NULL, &subgroup_iter); + TEST_ASSERT(rc == BLE_HS_EINVAL); + + rc = ble_audio_base_parse(example_base, (uint8_t)sizeof(example_base), &group, NULL); + TEST_ASSERT(rc == 0); + + rc = ble_audio_base_parse(example_base, (uint8_t)sizeof(example_base), &group, &subgroup_iter); + TEST_ASSERT(rc == 0); + + rc = ble_audio_base_subgroup_iter(NULL, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EINVAL); + + rc = ble_audio_base_subgroup_iter(&subgroup_iter, NULL, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EINVAL); + + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, NULL); + TEST_ASSERT(rc == 0); + + rc = ble_audio_base_bis_iter(NULL, &bis); + TEST_ASSERT(rc == BLE_HS_EINVAL); + + rc = ble_audio_base_bis_iter(&bis_iter, NULL); + TEST_ASSERT(rc == BLE_HS_EINVAL); +} + +TEST_CASE_SELF(ble_audio_base_parse_test_data_length) +{ + struct ble_audio_base_subgroup subgroup; + struct ble_audio_base_group group; + struct ble_audio_base_bis bis; + struct ble_audio_base_iter subgroup_iter; + struct ble_audio_base_iter bis_iter; + int rc; + + /* Incomplete: empty */ + rc = ble_audio_base_parse(example_base, 0, &group, &subgroup_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Truncated: Presentation_Delay Parameter */ + rc = ble_audio_base_parse(example_base, 2, &group, &subgroup_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no Num_Subgroups[0] Parameter */ + rc = ble_audio_base_parse(example_base, 3, &group, &subgroup_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no Num_BIS[0] Parameter */ + rc = ble_audio_base_parse(example_base, 4, &group, &subgroup_iter); + TEST_ASSERT(rc == 0); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Truncated: Codec_ID[0] Parameter */ + rc = ble_audio_base_parse(example_base, 9, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no Codec_Specific_Configuration_Length[0] Parameter */ + rc = ble_audio_base_parse(example_base, 13, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Truncated: Codec_Specific_Configuration[0] Parameter */ + rc = ble_audio_base_parse(example_base, 14, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no Metadata_Length[0] Parameter */ + rc = ble_audio_base_parse(example_base, 21, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Truncated: Metadata[0] Parameter */ + rc = ble_audio_base_parse(example_base, 30, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no BIS_index[0[0]] Parameter */ + rc = ble_audio_base_parse(example_base, 31, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == 0); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no Codec_Specific_Configuration_Length[0[0]] Parameter */ + rc = ble_audio_base_parse(example_base, 32, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Truncated: Codec_Specific_Configuration_Length[0[0]] Parameter */ + rc = ble_audio_base_parse(example_base, 38, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no BIS_index[0[1]] Parameter */ + rc = ble_audio_base_parse(example_base, 39, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == 0); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no Codec_Specific_Configuration_Length[0[1]] Parameter */ + rc = ble_audio_base_parse(example_base, 40, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Truncated: Codec_Specific_Configuration_Length[0[1]] Parameter */ + rc = ble_audio_base_parse(example_base, 46, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == 0); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no Num_BIS[1] Parameter */ + rc = ble_audio_base_parse(example_base, 47, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == 0); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Truncated: Codec_ID[1] Parameter */ + rc = ble_audio_base_parse(example_base, 52, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no Codec_Specific_Configuration_Length[1] Parameter */ + rc = ble_audio_base_parse(example_base, 53, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Truncated: Codec_Specific_Configuration[1] Parameter */ + rc = ble_audio_base_parse(example_base, 63, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no Metadata_Length[1] Parameter */ + rc = ble_audio_base_parse(example_base, 64, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Truncated: Metadata[1] Parameter */ + rc = ble_audio_base_parse(example_base, 73, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no BIS_index[1[0]] Parameter */ + rc = ble_audio_base_parse(example_base, 74, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + TEST_ASSERT(rc == 0); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no Codec_Specific_Configuration_Length[1[0]] Parameter */ + rc = ble_audio_base_parse(example_base, 75, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Truncated: Codec_Specific_Configuration_Length[1[0]] Parameter */ + rc = ble_audio_base_parse(example_base, 81, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no BIS_index[1[1]] Parameter */ + rc = ble_audio_base_parse(example_base, 82, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == 0); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Incomplete: no Codec_Specific_Configuration_Length[1[1]] Parameter */ + rc = ble_audio_base_parse(example_base, 83, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); + + /* Truncated: Codec_Specific_Configuration_Length[0[1]] Parameter */ + rc = ble_audio_base_parse(example_base, 89, &group, &subgroup_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_subgroup_iter(&subgroup_iter, &subgroup, &bis_iter); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + rc = ble_audio_base_bis_iter(&bis_iter, &bis); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); +} + +TEST_SUITE(ble_audio_base_parse_test_suite) +{ + ble_audio_base_parse_test(); + ble_audio_base_parse_test_params(); + ble_audio_base_parse_test_data_length(); +} diff --git a/nimble/host/audio/test/syscfg.yml b/nimble/host/audio/test/syscfg.yml new file mode 100644 index 000000000..3c760594c --- /dev/null +++ b/nimble/host/audio/test/syscfg.yml @@ -0,0 +1,29 @@ +# +# 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. +# + +syscfg.defs: + +syscfg.vals: + # Prevent priority conflict with controller task. + MCU_TIMER_POLLER_PRIO: 1 + MCU_UART_POLLER_PRIO: 2 + NATIVE_SOCKETS_PRIO: 3 + + BLE_VERSION: 54 + BLE_HS_DEBUG: 1