From 3a0e4d73235e539cb75298efaf429dc4d2ba5266 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Fri, 18 Sep 2026 23:02:48 +0200 Subject: [PATCH 01/16] Update CommonHeader to API guide and prepare for V1 support Signed-off-by: Sebastian Schildt --- examples/acf-can/linux-kernel-mod/Makefile | 2 +- include/avtp/CommonHeader.h | 141 +++++++++++------- src/avtp/CommonHeader.c | 124 ---------------- src/avtp/export/InlineExports.c | 2 +- unit/CMakeLists.txt | 1 - unit/test-avtp.c | 158 --------------------- unit/test-commonheader.c | 18 +++ 7 files changed, 107 insertions(+), 339 deletions(-) delete mode 100644 src/avtp/CommonHeader.c delete mode 100644 unit/test-avtp.c diff --git a/examples/acf-can/linux-kernel-mod/Makefile b/examples/acf-can/linux-kernel-mod/Makefile index 7640b5f8..467dac48 100644 --- a/examples/acf-can/linux-kernel-mod/Makefile +++ b/examples/acf-can/linux-kernel-mod/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_ACF_CAN) += acfcan.o -acfcan-objs := acfcanmain.o 1722ethernet.o ../../../src/avtp/Utils.o ../../../src/avtp/CommonHeader.o +acfcan-objs := acfcanmain.o 1722ethernet.o ../../../src/avtp/Utils.o ccflags-y += -DLINUX_KERNEL1722=1 ccflags-y += -I $(src)/../../../include diff --git a/include/avtp/CommonHeader.h b/include/avtp/CommonHeader.h index 035275ff..b8998f49 100644 --- a/include/avtp/CommonHeader.h +++ b/include/avtp/CommonHeader.h @@ -35,32 +35,45 @@ */ #pragma once +#include "avtp/Inline.h" + +#ifdef LINUX_KERNEL1722 +#include +#else +#include +#include +#endif #include "avtp/Defines.h" +#include "avtp/Utils.h" #ifdef __cplusplus extern "C" { #endif -#define AVTP_COMMON_HEADER_LEN (1 * AVTP_QUADLET_SIZE) +#define AVTPDU_COMMON_LEN (1 * AVTP_QUADLET_SIZE) + +/* Version field values (IEEE 1722-2025, 4.7.3.4). */ +#define AVTP_VERSION_0 0 +#define AVTP_VERSION_1 1 typedef struct { - uint8_t header[AVTP_COMMON_HEADER_LEN]; + uint8_t header[AVTPDU_COMMON_LEN]; uint8_t payload[0]; } Avtp_CommonHeader_t; /** - * Enumeration over all IEEE 1722 header fields. The naming convention used is - * AVTP__FIELD_. + * Enumeration over all IEEE 1722 common header fields. The naming convention + * used is AVTPDU_
_FIELD_. */ typedef enum Avtp_CommonHeaderField { /* Common AVTP header fields */ - AVTP_COMMON_HEADER_FIELD_SUBTYPE = 0, - AVTP_COMMON_HEADER_FIELD_H, - AVTP_COMMON_HEADER_FIELD_VERSION, + AVTPDU_COMMON_FIELD_SUBTYPE = 0, + AVTPDU_COMMON_FIELD_H, + AVTPDU_COMMON_FIELD_VERSION, /* Count number of fields for bound checks */ - AVTP_COMMON_HEADER_FIELD_MAX + AVTPDU_COMMON_FIELD_MAX } Avtp_CommonHeaderField_t; typedef enum { @@ -87,6 +100,38 @@ typedef enum { AVTP_SUBTYPE_EF_CONTROL = 0xFF, } Avtp_AvtpSubtype_t; +#define GET_COMMON_HEADER_FIELD(field) \ + (Avtp_GetField(Avtp_CommonHeaderFieldDesc, AVTPDU_COMMON_FIELD_MAX, (const uint8_t *)pdu, \ + field)) +#define SET_COMMON_HEADER_FIELD(field, value) \ + (Avtp_SetField(Avtp_CommonHeaderFieldDesc, AVTPDU_COMMON_FIELD_MAX, (uint8_t *)pdu, field, \ + value)) + +/** + * This table maps all IEEE 1722 common header fields to a descriptor. + */ +static const Avtp_FieldDescriptor_t Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_MAX] = { + /* Common AVTP header */ + [AVTPDU_COMMON_FIELD_SUBTYPE] = {.quadlet = 0, .offset = 0, .bits = 8}, + [AVTPDU_COMMON_FIELD_H] = {.quadlet = 0, .offset = 8, .bits = 1}, + [AVTPDU_COMMON_FIELD_VERSION] = {.quadlet = 0, .offset = 9, .bits = 3}, +}; + +/** + * Returns true if the given AVTP version is present in the supported-version mask. + * + * @param versionMask Bit mask in which bit N marks version N as supported. + * @param version Version number to test (0 to 7). + * @returns true if the version is supported, false otherwise. + */ +OPEN1722_INLINE bool Avtp_Version_IsSupported(uint8_t versionMask, uint8_t version) +{ + if (version >= 8U) { + return false; + } + return ((versionMask >> version) & 0x01U) != 0U; +} + /** * Returns the value of an an AVTP common header field as specified in the IEEE 1722 Specification. * @@ -94,13 +139,19 @@ typedef enum { * @param field Specifies the position of the data field to be read * @returns This function the value of the specified PDU field */ -uint64_t Avtp_CommonHeader_GetField(const Avtp_CommonHeader_t *const pdu, - Avtp_CommonHeaderField_t field); +OPEN1722_INLINE uint64_t Avtp_CommonHeader_GetField(const Avtp_CommonHeader_t *const pdu, + Avtp_CommonHeaderField_t field) +{ + return GET_COMMON_HEADER_FIELD(field); +} /** * Returns the subtype field of the AVTP common header. */ -uint8_t Avtp_CommonHeader_GetSubtype(const Avtp_CommonHeader_t *const pdu); +OPEN1722_INLINE uint8_t Avtp_CommonHeader_GetSubtype(const Avtp_CommonHeader_t *const pdu) +{ + return (uint8_t)GET_COMMON_HEADER_FIELD(AVTPDU_COMMON_FIELD_SUBTYPE); +} /** * Returns the h (header specific) bit of the AVTP common header. The meaning of this bit is defined @@ -108,12 +159,18 @@ uint8_t Avtp_CommonHeader_GetSubtype(const Avtp_CommonHeader_t *const pdu); * it as sv (stream_id valid), while formats using the alternative header (4.7.6) define it * themselves or leave it reserved. */ -uint8_t Avtp_CommonHeader_GetH(const Avtp_CommonHeader_t *const pdu); +OPEN1722_INLINE uint8_t Avtp_CommonHeader_GetH(const Avtp_CommonHeader_t *const pdu) +{ + return (uint8_t)GET_COMMON_HEADER_FIELD(AVTPDU_COMMON_FIELD_H); +} /** * Returns the version field of the AVTP common header. */ -uint8_t Avtp_CommonHeader_GetVersion(const Avtp_CommonHeader_t *const pdu); +OPEN1722_INLINE uint8_t Avtp_CommonHeader_GetVersion(const Avtp_CommonHeader_t *const pdu) +{ + return (uint8_t)GET_COMMON_HEADER_FIELD(AVTPDU_COMMON_FIELD_VERSION); +} /** * Sets the value of an an AVTP common header field as specified in the IEEE 1722 Specification. @@ -122,60 +179,36 @@ uint8_t Avtp_CommonHeader_GetVersion(const Avtp_CommonHeader_t *const pdu); * @param field Specifies the position of the data field to be read * @param value Pointer to location to store the value. */ -void Avtp_CommonHeader_SetField(Avtp_CommonHeader_t *pdu, Avtp_CommonHeaderField_t field, - uint64_t value); +OPEN1722_INLINE void Avtp_CommonHeader_SetField(Avtp_CommonHeader_t *pdu, + Avtp_CommonHeaderField_t field, uint64_t value) +{ + SET_COMMON_HEADER_FIELD(field, value); +} /** * Set the subtype field of the AVTP common header. */ -void Avtp_CommonHeader_SetSubtype(Avtp_CommonHeader_t *pdu, uint8_t value); +OPEN1722_INLINE void Avtp_CommonHeader_SetSubtype(Avtp_CommonHeader_t *pdu, uint8_t value) +{ + SET_COMMON_HEADER_FIELD(AVTPDU_COMMON_FIELD_SUBTYPE, value); +} /** * Sets the h (header specific) bit of the AVTP common header. See Avtp_CommonHeader_GetH for the * definition of this bit. */ -void Avtp_CommonHeader_SetH(Avtp_CommonHeader_t *pdu, uint8_t value); +OPEN1722_INLINE void Avtp_CommonHeader_SetH(Avtp_CommonHeader_t *pdu, uint8_t value) +{ + SET_COMMON_HEADER_FIELD(AVTPDU_COMMON_FIELD_H, value); +} /** * Set the version field of the AVTP common header. */ -void Avtp_CommonHeader_SetVersion(Avtp_CommonHeader_t *pdu, uint8_t value); - -/****************************************************************************** - * Legacy API (deprecated) - *****************************************************************************/ - -struct avtp_common_pdu { - uint32_t subtype_data; - uint8_t pdu_specific[0]; -} __attribute__((__packed__)); - -#define AVTP_FIELD_SUBTYPE (AVTP_COMMON_HEADER_FIELD_SUBTYPE) -#define AVTP_FIELD_VERSION (AVTP_COMMON_HEADER_FIELD_VERSION) -#define AVTP_FIELD_MAX (AVTP_COMMON_HEADER_FIELD_MAX) - -/* Get value from Common AVTPDU field. - * @pdu: Pointer to PDU struct. - * @field: PDU field to be retrieved. - * @val: Pointer to variable which the retrieved value should be saved. - * - * Returns: - * 0: Success. - * -EINVAL: If any argument is invalid. - */ -int avtp_pdu_get(const struct avtp_common_pdu *const pdu, Avtp_CommonHeaderField_t field, - uint32_t *val); - -/* Set value from Common AVTPDU field. - * @pdu: Pointer to PDU struct. - * @field: PDU field to be set. - * @val: Value to be set. - * - * Returns: - * 0: Success. - * -EINVAL: If any argument is invalid. - */ -int avtp_pdu_set(struct avtp_common_pdu *pdu, Avtp_CommonHeaderField_t field, uint32_t val); +OPEN1722_INLINE void Avtp_CommonHeader_SetVersion(Avtp_CommonHeader_t *pdu, uint8_t value) +{ + SET_COMMON_HEADER_FIELD(AVTPDU_COMMON_FIELD_VERSION, value); +} #ifdef __cplusplus } diff --git a/src/avtp/CommonHeader.c b/src/avtp/CommonHeader.c deleted file mode 100644 index 28ccdab8..00000000 --- a/src/avtp/CommonHeader.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2024, COVESA - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of COVESA nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifdef LINUX_KERNEL1722 -#include -#include -#else -#include -#include -#endif - -#include "avtp/CommonHeader.h" -#include "avtp/Utils.h" -#include "avtp/Defines.h" - -#define GET_FIELD(field) \ - (Avtp_GetField(Avtp_CommonHeaderFieldDesc, AVTP_COMMON_HEADER_FIELD_MAX, (const uint8_t *)pdu, \ - field)) -#define SET_FIELD(field, value) \ - (Avtp_SetField(Avtp_CommonHeaderFieldDesc, AVTP_COMMON_HEADER_FIELD_MAX, (uint8_t *)pdu, \ - field, value)) - -/** - * This table maps all IEEE 1722 common header fields to a descriptor. - */ -static const Avtp_FieldDescriptor_t Avtp_CommonHeaderFieldDesc[AVTP_COMMON_HEADER_FIELD_MAX] = { - /* Common AVTP header */ - [AVTP_COMMON_HEADER_FIELD_SUBTYPE] = {.quadlet = 0, .offset = 0, .bits = 8}, - [AVTP_COMMON_HEADER_FIELD_H] = {.quadlet = 0, .offset = 8, .bits = 1}, - [AVTP_COMMON_HEADER_FIELD_VERSION] = {.quadlet = 0, .offset = 9, .bits = 3}, -}; - -uint64_t Avtp_CommonHeader_GetField(const Avtp_CommonHeader_t *const pdu, - Avtp_CommonHeaderField_t field) -{ - return GET_FIELD(field); -} - -uint8_t Avtp_CommonHeader_GetSubtype(const Avtp_CommonHeader_t *const pdu) -{ - return (uint8_t)GET_FIELD(AVTP_COMMON_HEADER_FIELD_SUBTYPE); -} - -uint8_t Avtp_CommonHeader_GetH(const Avtp_CommonHeader_t *const pdu) -{ - return (uint8_t)GET_FIELD(AVTP_COMMON_HEADER_FIELD_H); -} - -uint8_t Avtp_CommonHeader_GetVersion(const Avtp_CommonHeader_t *const pdu) -{ - return (uint8_t)GET_FIELD(AVTP_COMMON_HEADER_FIELD_VERSION); -} - -void Avtp_CommonHeader_SetField(Avtp_CommonHeader_t *pdu, Avtp_CommonHeaderField_t field, - uint64_t value) -{ - SET_FIELD(field, value); -} - -void Avtp_CommonHeader_SetSubtype(Avtp_CommonHeader_t *pdu, uint8_t value) -{ - SET_FIELD(AVTP_COMMON_HEADER_FIELD_SUBTYPE, value); -} - -void Avtp_CommonHeader_SetH(Avtp_CommonHeader_t *pdu, uint8_t value) -{ - SET_FIELD(AVTP_COMMON_HEADER_FIELD_H, value); -} - -void Avtp_CommonHeader_SetVersion(Avtp_CommonHeader_t *pdu, uint8_t value) -{ - SET_FIELD(AVTP_COMMON_HEADER_FIELD_VERSION, value); -} - -/****************************************************************************** - * Legacy API - *****************************************************************************/ -int avtp_pdu_get(const struct avtp_common_pdu *const pdu, Avtp_CommonHeaderField_t field, - uint32_t *val) -{ - if (pdu == NULL || val == NULL || field >= AVTP_COMMON_HEADER_FIELD_MAX) { - return -EINVAL; - } else { - uint64_t temp = Avtp_CommonHeader_GetField((const Avtp_CommonHeader_t *const)pdu, field); - *val = (uint32_t)temp; - return 0; - } -} - -int avtp_pdu_set(struct avtp_common_pdu *pdu, Avtp_CommonHeaderField_t field, uint32_t value) -{ - if (pdu == NULL || field >= AVTP_COMMON_HEADER_FIELD_MAX) { - return -EINVAL; - } else { - Avtp_CommonHeader_SetField((Avtp_CommonHeader_t *)pdu, field, value); - return 0; - } -} diff --git a/src/avtp/export/InlineExports.c b/src/avtp/export/InlineExports.c index 8122ff97..e072b660 100644 --- a/src/avtp/export/InlineExports.c +++ b/src/avtp/export/InlineExports.c @@ -45,7 +45,6 @@ #include "avtp/Defines.h" #include "avtp/Byteorder.h" #include "avtp/Utils.h" -#include "avtp/CommonHeader.h" #include "avtp/acf/AcfCommon.h" /* --- Phase 2: target headers (extern-definition mode) ---------------- */ @@ -53,6 +52,7 @@ #undef OPEN1722_INLINE #define OPEN1722_INLINE +#include "avtp/CommonHeader.h" #include "avtp/Udp.h" #include "avtp/Crf.h" diff --git a/unit/CMakeLists.txt b/unit/CMakeLists.txt index 54a2f4e8..edfa672b 100644 --- a/unit/CMakeLists.txt +++ b/unit/CMakeLists.txt @@ -71,7 +71,6 @@ endfunction() add_dual_test(test-can test-can.c m) add_dual_test(test-aaf test-aaf.c) add_dual_test(test-pcm test-pcm.c) -add_dual_test(test-avtp test-avtp.c) add_dual_test(test-crf test-crf.c) add_dual_test(test-cvf test-cvf.c) add_dual_test(test-rvf test-rvf.c) diff --git a/unit/test-avtp.c b/unit/test-avtp.c deleted file mode 100644 index 1bf2a74a..00000000 --- a/unit/test-avtp.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2017, Intel Corporation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include -#include -#if defined(__cplusplus) -extern "C" { -#include -} -#else -#include -#endif -#include -#include - -#include "avtp/CommonHeader.h" - -static void get_field_null_pdu(void **state) -{ - int res; - uint32_t val = AVTP_SUBTYPE_MAAP; - - res = avtp_pdu_get(NULL, AVTP_FIELD_SUBTYPE, &val); - - assert_int_equal(res, -EINVAL); -} - -static void get_field_null_val(void **state) -{ - int res; - struct avtp_common_pdu pdu = {0}; - - res = avtp_pdu_get(&pdu, AVTP_FIELD_SUBTYPE, NULL); - - assert_int_equal(res, -EINVAL); -} - -static void get_field_invalid_field(void **state) -{ - int res; - uint32_t val = AVTP_SUBTYPE_MAAP; - struct avtp_common_pdu pdu = {0}; - - res = avtp_pdu_get(&pdu, AVTP_FIELD_MAX, &val); - - assert_int_equal(res, -EINVAL); -} - -static void get_field_subtype(void **state) -{ - int res; - uint32_t val; - struct avtp_common_pdu pdu = {0}; - - /* Set 'subtype' field to 0xFE (AVTP_SUBTYPE_MAAP). */ - pdu.subtype_data = htonl(0xFE000000); - - res = avtp_pdu_get(&pdu, AVTP_FIELD_SUBTYPE, &val); - - assert_int_equal(res, 0); - assert_true(val == AVTP_SUBTYPE_MAAP); -} - -static void get_field_version(void **state) -{ - int res; - uint32_t val; - struct avtp_common_pdu pdu = {0}; - - /* Set 'version' field to 5. */ - pdu.subtype_data = htonl(0x00500000); - - res = avtp_pdu_get(&pdu, AVTP_FIELD_VERSION, &val); - - assert_int_equal(res, 0); - assert_true(val == 5); -} - -static void set_field_null_pdu(void **state) -{ - int res; - - res = avtp_pdu_set(NULL, AVTP_FIELD_SUBTYPE, AVTP_SUBTYPE_MAAP); - - assert_int_equal(res, -EINVAL); -} - -static void set_field_invalid_field(void **state) -{ - int res; - struct avtp_common_pdu pdu = {0}; - - res = avtp_pdu_set(&pdu, AVTP_FIELD_MAX, 1); - - assert_int_equal(res, -EINVAL); -} - -static void set_field_subtype(void **state) -{ - int res; - struct avtp_common_pdu pdu = {0}; - - res = avtp_pdu_set(&pdu, AVTP_FIELD_SUBTYPE, AVTP_SUBTYPE_MAAP); - - assert_int_equal(res, 0); - assert_true(ntohl(pdu.subtype_data) == 0xFE000000); -} - -static void set_field_version(void **state) -{ - int res; - struct avtp_common_pdu pdu = {0}; - - res = avtp_pdu_set(&pdu, AVTP_FIELD_VERSION, 5); - - assert_int_equal(res, 0); - assert_true(ntohl(pdu.subtype_data) == 0x00500000); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(get_field_null_pdu), cmocka_unit_test(get_field_null_val), - cmocka_unit_test(get_field_invalid_field), cmocka_unit_test(get_field_subtype), - cmocka_unit_test(get_field_version), cmocka_unit_test(set_field_null_pdu), - cmocka_unit_test(set_field_invalid_field), cmocka_unit_test(set_field_subtype), - cmocka_unit_test(set_field_version), - }; - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/unit/test-commonheader.c b/unit/test-commonheader.c index dbbde112..5c363a43 100644 --- a/unit/test-commonheader.c +++ b/unit/test-commonheader.c @@ -76,6 +76,7 @@ static void common_header_get_set_fields(void **state) static void common_header_subtypes(void **state) { + (void)state; assert_int_equal(AVTP_SUBTYPE_AAF, 0x2); assert_int_equal(AVTP_SUBTYPE_CVF, 0x3); assert_int_equal(AVTP_SUBTYPE_CRF, 0x4); @@ -84,11 +85,28 @@ static void common_header_subtypes(void **state) assert_int_equal(AVTP_SUBTYPE_NTSCF, 0x82); } +static void common_header_version_support(void **state) +{ + (void)state; + uint8_t both = (uint8_t)((1U << AVTP_VERSION_0) | (1U << AVTP_VERSION_1)); + + assert_int_equal(AVTP_VERSION_0, 0); + assert_int_equal(AVTP_VERSION_1, 1); + + assert_true(Avtp_Version_IsSupported(both, AVTP_VERSION_0)); + assert_true(Avtp_Version_IsSupported(both, AVTP_VERSION_1)); + assert_false(Avtp_Version_IsSupported(both, 2)); + assert_false(Avtp_Version_IsSupported((uint8_t)(1U << AVTP_VERSION_0), AVTP_VERSION_1)); + assert_false(Avtp_Version_IsSupported(0, AVTP_VERSION_0)); + assert_false(Avtp_Version_IsSupported(0xFF, 8)); +} + int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(common_header_get_set_fields), cmocka_unit_test(common_header_subtypes), + cmocka_unit_test(common_header_version_support), }; return cmocka_run_group_tests(tests, NULL, NULL); From eef61c3362fa897c7c656db77f344b3c4350295b Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Fri, 18 Sep 2026 23:19:29 +0200 Subject: [PATCH 02/16] Add Common Stream Header V0 and V1 Signed-off-by: Sebastian Schildt --- include/avtp/CommonStreamHeader.h | 421 ++++++++++++++++++++++++++++++ src/avtp/export/InlineExports.c | 1 + unit/CMakeLists.txt | 1 + unit/test-commonstreamheader.c | 220 ++++++++++++++++ 4 files changed, 643 insertions(+) create mode 100644 include/avtp/CommonStreamHeader.h create mode 100644 unit/test-commonstreamheader.c diff --git a/include/avtp/CommonStreamHeader.h b/include/avtp/CommonStreamHeader.h new file mode 100644 index 00000000..82c12e63 --- /dev/null +++ b/include/avtp/CommonStreamHeader.h @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2026, COVESA + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of COVESA nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * This file contains the field descriptions of the IEEE 1722 AVTPDU common + * stream header (4.7.4) for versions 0 and 1 and functions to invoke the + * corresponding parser and deparser. The format-specific data slots 2 and 3 + * are not covered here; their contents are defined by the individual formats. + */ + +#pragma once +#include "avtp/Inline.h" + +#ifdef LINUX_KERNEL1722 +#include +#else +#include +#include +#endif + +#include "avtp/Defines.h" +#include "avtp/Utils.h" +#include "avtp/CommonHeader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* AVTPDU common stream header length in octets (IEEE 1722-2025, 4.7.4). */ +#define AVTPDU_CSH_LEN_V0 (6 * AVTP_QUADLET_SIZE) /* 24 */ +#define AVTPDU_CSH_LEN_V1 (10 * AVTP_QUADLET_SIZE) /* 40 */ + +/** + * View type for the AVTPDU common stream header. The header is 24 octets for + * version 0 and 40 octets for version 1, so the view is sized for the largest + * version. Every accessor dispatches on the version field of the common header. + */ +typedef struct { + uint8_t header[AVTPDU_CSH_LEN_V1]; + uint8_t payload[0]; +} Avtp_CommonStreamHeader_t; + +/** + * Enumeration over all IEEE 1722 AVTPDU common stream header fields. The + * naming convention used is AVTPDU_
_FIELD_. + */ +typedef enum { + AVTPDU_CSH_FIELD_SV = 0, + AVTPDU_CSH_FIELD_MR, + AVTPDU_CSH_FIELD_FSD, + AVTPDU_CSH_FIELD_TV, + AVTPDU_CSH_FIELD_SEQUENCE_NUM, + AVTPDU_CSH_FIELD_FSD0, + AVTPDU_CSH_FIELD_FSD1, + AVTPDU_CSH_FIELD_TU, + AVTPDU_CSH_FIELD_STREAM_ID, + AVTPDU_CSH_FIELD_AVTP_TIMESTAMP, + AVTPDU_CSH_FIELD_PTP_GRANDMASTER_IDENTITY, + AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH, + + /* Count number of fields for bound checks */ + AVTPDU_CSH_FIELD_MAX +} Avtp_CommonStreamHeaderField_t; + +/** + * These tables map all IEEE 1722 AVTPDU common stream header fields to a + * descriptor, one table per version. Fields that are absent from a version + * have a zero-initialized descriptor (bits = 0): reading them returns 0 and + * writing them is a no-op. The accessors select the table that matches the + * version field of the PDU. + */ +static const Avtp_FieldDescriptor_t Avtp_CshFieldDescV0[AVTPDU_CSH_FIELD_MAX] = { + [AVTPDU_CSH_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, + [AVTPDU_CSH_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, + [AVTPDU_CSH_FIELD_FSD] = {.quadlet = 0, .offset = 13, .bits = 2}, + [AVTPDU_CSH_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, + [AVTPDU_CSH_FIELD_SEQUENCE_NUM] = {.quadlet = 0, .offset = 16, .bits = 8}, + [AVTPDU_CSH_FIELD_FSD0] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTPDU_CSH_FIELD_FSD1] = {.quadlet = 0, .offset = 24, .bits = 7}, + [AVTPDU_CSH_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, + [AVTPDU_CSH_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, + [AVTPDU_CSH_FIELD_AVTP_TIMESTAMP] = {.quadlet = 3, .offset = 0, .bits = 32}, + [AVTPDU_CSH_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 5, .offset = 0, .bits = 16}, +}; + +static const Avtp_FieldDescriptor_t Avtp_CshFieldDescV1[AVTPDU_CSH_FIELD_MAX] = { + [AVTPDU_CSH_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, + [AVTPDU_CSH_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, + [AVTPDU_CSH_FIELD_FSD] = {.quadlet = 0, .offset = 13, .bits = 2}, + [AVTPDU_CSH_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, + [AVTPDU_CSH_FIELD_SEQUENCE_NUM] = {.quadlet = 3, .offset = 0, .bits = 32}, + [AVTPDU_CSH_FIELD_FSD0] = {.quadlet = 0, .offset = 16, .bits = 8}, + [AVTPDU_CSH_FIELD_FSD1] = {.quadlet = 0, .offset = 24, .bits = 7}, + [AVTPDU_CSH_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, + [AVTPDU_CSH_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, + [AVTPDU_CSH_FIELD_AVTP_TIMESTAMP] = {.quadlet = 4, .offset = 0, .bits = 64}, + [AVTPDU_CSH_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 6, .offset = 0, .bits = 64}, + [AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 9, .offset = 0, .bits = 16}, +}; + +/** + * Returns the raw version field of the AVTPDU common header. Values other than + * 0 or 1 are reserved; the accessors treat anything other than 1 as version 0. + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetVersion(const Avtp_CommonStreamHeader_t *const pdu) +{ + return Avtp_CommonHeader_GetVersion((const Avtp_CommonHeader_t *)pdu); +} + +/** + * Returns the length of the common stream header in octets (24 or 40). + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetHeaderLen(const Avtp_CommonStreamHeader_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1 ? (uint8_t)AVTPDU_CSH_LEN_V1 + : (uint8_t)AVTPDU_CSH_LEN_V0; +} + +/** + * Returns the byte offset of the format-specific data area relative to the + * version 0 layout: 0 for version 0 and 16 for version 1. Format field + * descriptor tables are written in version 0 coordinates and add this offset + * to the PDU pointer. + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetFormatOffset(const Avtp_CommonStreamHeader_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1 + ? (uint8_t)(AVTPDU_CSH_LEN_V1 - AVTPDU_CSH_LEN_V0) + : 0; +} + +/** + * Returns the value of an AVTPDU common stream header field. + * + * @param pdu Pointer to the first bit of an 1722 AVTP PDU. + * @param field Specifies the position of the data field to be read. + * @returns The value of the specified field. + */ +OPEN1722_INLINE uint64_t Avtp_CommonStreamHeader_GetField( + const Avtp_CommonStreamHeader_t *const pdu, Avtp_CommonStreamHeaderField_t field) +{ + const Avtp_FieldDescriptor_t *desc = Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1 + ? Avtp_CshFieldDescV1 + : Avtp_CshFieldDescV0; + return Avtp_GetField(desc, AVTPDU_CSH_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); +} + +/** + * Sets the value of an AVTPDU common stream header field. Fields absent from + * the version in use are left untouched. + * + * @param pdu Pointer to the first bit of an 1722 AVTP PDU. + * @param field Specifies the position of the data field to be written. + * @param value The value to set. + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetField(Avtp_CommonStreamHeader_t *pdu, + Avtp_CommonStreamHeaderField_t field, + uint64_t value) +{ + const Avtp_FieldDescriptor_t *desc = Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1 + ? Avtp_CshFieldDescV1 + : Avtp_CshFieldDescV0; + Avtp_SetField(desc, AVTPDU_CSH_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Returns the sv (stream_id valid) bit of the AVTPDU common stream header. + */ +OPEN1722_INLINE bool Avtp_CommonStreamHeader_IsSv(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (bool)Avtp_CommonStreamHeader_GetField(pdu, AVTPDU_CSH_FIELD_SV); +} + +/** + * Sets the sv (stream_id valid) bit of the AVTPDU common stream header. + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetSv(Avtp_CommonStreamHeader_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_SV, sv); +} + +/** + * Returns the mr (media clock restart) bit of the AVTPDU common stream header. + */ +OPEN1722_INLINE bool Avtp_CommonStreamHeader_IsMr(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (bool)Avtp_CommonStreamHeader_GetField(pdu, AVTPDU_CSH_FIELD_MR); +} + +/** + * Sets the mr (media clock restart) bit of the AVTPDU common stream header. + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetMr(Avtp_CommonStreamHeader_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_MR, mr); +} + +/** + * Returns the tv (avtp_timestamp valid) bit of the AVTPDU common stream header. + */ +OPEN1722_INLINE bool Avtp_CommonStreamHeader_IsTv(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (bool)Avtp_CommonStreamHeader_GetField(pdu, AVTPDU_CSH_FIELD_TV); +} + +/** + * Sets the tv (avtp_timestamp valid) bit of the AVTPDU common stream header. + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetTv(Avtp_CommonStreamHeader_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_TV, tv); +} + +/** + * Returns the tu (timestamp uncertain) bit of the AVTPDU common stream header. + */ +OPEN1722_INLINE bool Avtp_CommonStreamHeader_IsTu(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (bool)Avtp_CommonStreamHeader_GetField(pdu, AVTPDU_CSH_FIELD_TU); +} + +/** + * Sets the tu (timestamp uncertain) bit of the AVTPDU common stream header. + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetTu(Avtp_CommonStreamHeader_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_TU, tu); +} + +/** + * Returns the f_s_d (format-specific data) field of the AVTPDU common stream + * header. Its interpretation is defined by the format. + */ +OPEN1722_INLINE uint8_t Avtp_CommonStreamHeader_GetFsd(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint8_t)Avtp_CommonStreamHeader_GetField(pdu, AVTPDU_CSH_FIELD_FSD); +} + +/** + * Sets the f_s_d (format-specific data) field of the AVTPDU common stream + * header. Its interpretation is defined by the format. + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetFsd(Avtp_CommonStreamHeader_t *pdu, uint8_t fsd) +{ + Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_FSD, fsd); +} + +/** + * Returns the format_specific_data_0 field of the AVTPDU common stream header. + * The field only exists in version 1; version 0 returns 0. + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetFormatSpecificData0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint8_t)Avtp_CommonStreamHeader_GetField(pdu, AVTPDU_CSH_FIELD_FSD0); +} + +/** + * Sets the format_specific_data_0 field of the AVTPDU common stream header. + * The field only exists in version 1; on version 0 this is a no-op. + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetFormatSpecificData0(Avtp_CommonStreamHeader_t *pdu, + uint8_t value) +{ + Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_FSD0, value); +} + +/** + * Returns the format_specific_data_1 field of the AVTPDU common stream header. + * Its interpretation is defined by the format. + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetFormatSpecificData1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint8_t)Avtp_CommonStreamHeader_GetField(pdu, AVTPDU_CSH_FIELD_FSD1); +} + +/** + * Sets the format_specific_data_1 field of the AVTPDU common stream header. + * Its interpretation is defined by the format. + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetFormatSpecificData1(Avtp_CommonStreamHeader_t *pdu, + uint8_t value) +{ + Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_FSD1, value); +} + +/** + * Returns the sequence_num field of the AVTPDU common stream header. The field + * is 8 bits in version 0 and 32 bits in version 1. + */ +OPEN1722_INLINE uint32_t +Avtp_CommonStreamHeader_GetSequenceNum(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint32_t)Avtp_CommonStreamHeader_GetField(pdu, AVTPDU_CSH_FIELD_SEQUENCE_NUM); +} + +/** + * Sets the sequence_num field of the AVTPDU common stream header. The field is + * 8 bits in version 0 and 32 bits in version 1; values are truncated to the + * width of the version in use. + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetSequenceNum(Avtp_CommonStreamHeader_t *pdu, + uint32_t value) +{ + Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_SEQUENCE_NUM, value); +} + +/** + * Returns the stream_id field of the AVTPDU common stream header. + */ +OPEN1722_INLINE uint64_t +Avtp_CommonStreamHeader_GetStreamId(const Avtp_CommonStreamHeader_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetField(pdu, AVTPDU_CSH_FIELD_STREAM_ID); +} + +/** + * Sets the stream_id field of the AVTPDU common stream header. + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetStreamId(Avtp_CommonStreamHeader_t *pdu, + uint64_t value) +{ + Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_STREAM_ID, value); +} + +/** + * Returns the avtp_timestamp field of the AVTPDU common stream header. The + * field is 32 bits in version 0 and 64 bits in version 1. + */ +OPEN1722_INLINE uint64_t +Avtp_CommonStreamHeader_GetAvtpTimestamp(const Avtp_CommonStreamHeader_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetField(pdu, AVTPDU_CSH_FIELD_AVTP_TIMESTAMP); +} + +/** + * Sets the avtp_timestamp field of the AVTPDU common stream header. The field + * is 32 bits in version 0 and 64 bits in version 1; values are truncated to + * the width of the version in use. + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetAvtpTimestamp(Avtp_CommonStreamHeader_t *pdu, + uint64_t value) +{ + Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_AVTP_TIMESTAMP, value); +} + +/** + * Returns the ptp_grandmaster_identity field of the AVTPDU common stream + * header. The field only exists in version 1; version 0 returns 0. + */ +OPEN1722_INLINE uint64_t +Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity(const Avtp_CommonStreamHeader_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetField(pdu, AVTPDU_CSH_FIELD_PTP_GRANDMASTER_IDENTITY); +} + +/** + * Sets the ptp_grandmaster_identity field of the AVTPDU common stream header. + * The field only exists in version 1; on version 0 this is a no-op. + */ +OPEN1722_INLINE void +Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity(Avtp_CommonStreamHeader_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_PTP_GRANDMASTER_IDENTITY, value); +} + +/** + * Returns the stream_data_length field of the AVTPDU common stream header. The + * value is the length in octets of the stream_data_payload field. + */ +OPEN1722_INLINE uint16_t +Avtp_CommonStreamHeader_GetStreamDataLength(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint16_t)Avtp_CommonStreamHeader_GetField(pdu, AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH); +} + +/** + * Sets the stream_data_length field of the AVTPDU common stream header. The + * value is the length in octets of the stream_data_payload field. + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetStreamDataLength(Avtp_CommonStreamHeader_t *pdu, + uint16_t value) +{ + Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH, value); +} + +#ifdef __cplusplus +} +#endif diff --git a/src/avtp/export/InlineExports.c b/src/avtp/export/InlineExports.c index e072b660..4f903c79 100644 --- a/src/avtp/export/InlineExports.c +++ b/src/avtp/export/InlineExports.c @@ -53,6 +53,7 @@ #define OPEN1722_INLINE #include "avtp/CommonHeader.h" +#include "avtp/CommonStreamHeader.h" #include "avtp/Udp.h" #include "avtp/Crf.h" diff --git a/unit/CMakeLists.txt b/unit/CMakeLists.txt index edfa672b..88c02cc8 100644 --- a/unit/CMakeLists.txt +++ b/unit/CMakeLists.txt @@ -84,6 +84,7 @@ add_dual_test(test-gpc test-gpc.c) add_dual_test(test-sensor test-sensor.c) add_dual_test(test-udp test-udp.c) add_dual_test(test-commonheader test-commonheader.c) +add_dual_test(test-commonstreamheader test-commonstreamheader.c) add_dual_test(test-gisf test-gisf.c) add_dual_test(test-abb test-abb.c) add_dual_test(test-gbb test-gbb.c) diff --git a/unit/test-commonstreamheader.c b/unit/test-commonstreamheader.c new file mode 100644 index 00000000..5ef3ad04 --- /dev/null +++ b/unit/test-commonstreamheader.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2026, COVESA + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of COVESA nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#if defined(__cplusplus) +extern "C" { +#include +} +#else +#include +#endif +#include +#include + +#include "avtp/CommonStreamHeader.h" + +static uint32_t read_quadlet(const uint8_t *pdu, size_t quadlet) +{ + uint32_t word; + + memcpy(&word, pdu + (quadlet * 4), sizeof(word)); + return ntohl(word); +} + +static void common_stream_header_lengths(void **state) +{ + (void)state; + + assert_int_equal(AVTPDU_CSH_LEN_V0, 24); + assert_int_equal(AVTPDU_CSH_LEN_V1, 40); + assert_int_equal(sizeof(Avtp_CommonStreamHeader_t), AVTPDU_CSH_LEN_V1); +} + +static void common_stream_header_v0_layout(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_CSH_LEN_V0]; + Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_0); + + assert_int_equal(Avtp_CommonStreamHeader_GetVersion(csh), AVTP_VERSION_0); + assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen(csh), AVTPDU_CSH_LEN_V0); + assert_int_equal(Avtp_CommonStreamHeader_GetFormatOffset(csh), 0); + + Avtp_CommonStreamHeader_SetSv(csh, true); + Avtp_CommonStreamHeader_SetMr(csh, true); + Avtp_CommonStreamHeader_SetFsd(csh, 0x3); + Avtp_CommonStreamHeader_SetTv(csh, true); + Avtp_CommonStreamHeader_SetTu(csh, true); + + assert_true(Avtp_CommonStreamHeader_IsSv(csh)); + assert_true(Avtp_CommonStreamHeader_IsMr(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetFsd(csh), 0x3); + assert_true(Avtp_CommonStreamHeader_IsTv(csh)); + assert_true(Avtp_CommonStreamHeader_IsTu(csh)); + assert_int_equal(read_quadlet(pdu, 0), 0x008F0001); + + Avtp_CommonStreamHeader_SetFormatSpecificData1(csh, 0x5A); + assert_int_equal(Avtp_CommonStreamHeader_GetFormatSpecificData1(csh), 0x5A); + assert_int_equal(read_quadlet(pdu, 0), 0x008F00B5); + + Avtp_CommonStreamHeader_SetSequenceNum(csh, 0xAB); + assert_int_equal(Avtp_CommonStreamHeader_GetSequenceNum(csh), 0xAB); + assert_int_equal(read_quadlet(pdu, 0), 0x008FABB5); + + Avtp_CommonStreamHeader_SetStreamId(csh, 0xAABBCCDDEEFF0011ULL); + assert_int_equal(Avtp_CommonStreamHeader_GetStreamId(csh), 0xAABBCCDDEEFF0011ULL); + assert_int_equal(read_quadlet(pdu, 1), 0xAABBCCDD); + assert_int_equal(read_quadlet(pdu, 2), 0xEEFF0011); + + Avtp_CommonStreamHeader_SetAvtpTimestamp(csh, 0x80C0FFEE); + assert_int_equal(Avtp_CommonStreamHeader_GetAvtpTimestamp(csh), 0x80C0FFEE); + assert_int_equal(read_quadlet(pdu, 3), 0x80C0FFEE); + + Avtp_CommonStreamHeader_SetStreamDataLength(csh, 0x1234); + assert_int_equal(Avtp_CommonStreamHeader_GetStreamDataLength(csh), 0x1234); + assert_int_equal(read_quadlet(pdu, 5), 0x12340000); +} + +static void common_stream_header_v1_layout(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_CSH_LEN_V1]; + Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_1); + + assert_int_equal(Avtp_CommonStreamHeader_GetVersion(csh), AVTP_VERSION_1); + assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen(csh), AVTPDU_CSH_LEN_V1); + assert_int_equal(Avtp_CommonStreamHeader_GetFormatOffset(csh), 16); + + Avtp_CommonStreamHeader_SetSv(csh, true); + Avtp_CommonStreamHeader_SetMr(csh, true); + Avtp_CommonStreamHeader_SetFsd(csh, 0x1); + Avtp_CommonStreamHeader_SetTv(csh, true); + Avtp_CommonStreamHeader_SetFormatSpecificData0(csh, 0x42); + Avtp_CommonStreamHeader_SetFormatSpecificData1(csh, 0x5A); + Avtp_CommonStreamHeader_SetTu(csh, true); + + assert_true(Avtp_CommonStreamHeader_IsSv(csh)); + assert_true(Avtp_CommonStreamHeader_IsMr(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetFsd(csh), 0x1); + assert_true(Avtp_CommonStreamHeader_IsTv(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetFormatSpecificData0(csh), 0x42); + assert_int_equal(Avtp_CommonStreamHeader_GetFormatSpecificData1(csh), 0x5A); + assert_true(Avtp_CommonStreamHeader_IsTu(csh)); + assert_int_equal(read_quadlet(pdu, 0), 0x9B42B5); + + Avtp_CommonStreamHeader_SetSequenceNum(csh, 0x12345678); + assert_int_equal(Avtp_CommonStreamHeader_GetSequenceNum(csh), 0x12345678); + assert_int_equal(read_quadlet(pdu, 3), 0x12345678); + + Avtp_CommonStreamHeader_SetStreamId(csh, 0x0102030405060708ULL); + assert_int_equal(Avtp_CommonStreamHeader_GetStreamId(csh), 0x0102030405060708ULL); + assert_int_equal(read_quadlet(pdu, 1), 0x01020304); + assert_int_equal(read_quadlet(pdu, 2), 0x05060708); + + Avtp_CommonStreamHeader_SetAvtpTimestamp(csh, 0x1122334455667788ULL); + assert_int_equal(Avtp_CommonStreamHeader_GetAvtpTimestamp(csh), 0x1122334455667788ULL); + assert_int_equal(read_quadlet(pdu, 4), 0x11223344); + assert_int_equal(read_quadlet(pdu, 5), 0x55667788); + + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity(csh, 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity(csh), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(read_quadlet(pdu, 6), 0x99AABBCC); + assert_int_equal(read_quadlet(pdu, 7), 0xDDEEFF00); + + Avtp_CommonStreamHeader_SetStreamDataLength(csh, 0x0ABC); + assert_int_equal(Avtp_CommonStreamHeader_GetStreamDataLength(csh), 0x0ABC); + assert_int_equal(read_quadlet(pdu, 9), 0x0ABC0000); +} + +static void common_stream_header_absent_fields(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_CSH_LEN_V0]; + uint8_t snapshot[AVTPDU_CSH_LEN_V0]; + Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_0); + + /* format_specific_data_0 and ptp_grandmaster_identity do not exist in v0. */ + assert_int_equal(Avtp_CommonStreamHeader_GetFormatSpecificData0(csh), 0); + assert_int_equal(Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity(csh), 0); + + memcpy(snapshot, pdu, sizeof(snapshot)); + Avtp_CommonStreamHeader_SetFormatSpecificData0(csh, 0x42); + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity(csh, 0xFFFFFFFFFFFFFFFFULL); + assert_memory_equal(snapshot, pdu, sizeof(snapshot)); +} + +static void common_stream_header_no_overlap(void **state) +{ + (void)state; + + for (uint8_t version = 0; version <= 1; version++) { + uint8_t coverage[AVTPDU_CSH_LEN_V1 * 8] = {0}; + const Avtp_FieldDescriptor_t *desc = + version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + + for (uint8_t i = 0; i < AVTPDU_CSH_FIELD_MAX; i++) { + uint8_t quadlet = desc[i].quadlet; + uint8_t offset = desc[i].offset; + uint8_t bits = desc[i].bits; + + for (uint8_t b = 0; b < bits; b++) { + size_t bit = ((size_t)quadlet * 32) + offset + b; + + assert_true(bit < sizeof(coverage)); + assert_int_equal(coverage[bit], 0); + coverage[bit] = 1; + } + } + } +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(common_stream_header_lengths), + cmocka_unit_test(common_stream_header_v0_layout), + cmocka_unit_test(common_stream_header_v1_layout), + cmocka_unit_test(common_stream_header_absent_fields), + cmocka_unit_test(common_stream_header_no_overlap), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} From fd88436de9ea1a48000e51aed16d1e57d22567b6 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Fri, 18 Sep 2026 23:37:19 +0200 Subject: [PATCH 03/16] Add TSCF V1 support Signed-off-by: Sebastian Schildt --- docs/api-design.md | 89 ++++++++-- examples/acf-can/acf-can-common.c | 2 +- examples/acf-vss/acf-vss-talker.c | 8 +- include/avtp/acf/Tscf.h | 283 ++++++++++++++++++++---------- unit/test-tscf.c | 220 ++++++++++++++++++++--- 5 files changed, 465 insertions(+), 137 deletions(-) diff --git a/docs/api-design.md b/docs/api-design.md index 10cd6e8c..a2b3e188 100644 --- a/docs/api-design.md +++ b/docs/api-design.md @@ -10,17 +10,20 @@ surface lives and where the conventions matter most. The ACF format modules all follow one shared template. `ACF CAN` (`include/avtp/acf/Can.h`) is the reference implementation of that template; when in doubt, follow it. -The AAF, CVF, CRF and RVF stream format modules (`include/avtp/aaf/`, -`include/avtp/cvf/`, `include/avtp/Crf.h` and `include/avtp/Rvf.h`) follow the -same template - header-only inline accessors, a field descriptor table covering -every header bit, `Init`, `IsValid` and payload helpers. They differ only in the -header they describe: the common stream header instead of the ACF header, except -for CRF, which uses the alternative header (version 0). The CVF format-specific -headers (MJPEG, H.264, JPEG 2000) and the RVF raw header are fragments of the -stream data rather than standalone PDUs: they are validated through the -enclosing PDU (`Avtp_Cvf_IsValid`/`Avtp_Rvf_IsValid`, plus a matching -`format_subtype` for CVF) and provide a shallow `IsValid` of their own that -checks the fragment header fits into the given buffer. +The stream format modules (`include/avtp/aaf/`, `include/avtp/cvf/`, +`include/avtp/Crf.h`, `include/avtp/Rvf.h` and `include/avtp/acf/Tscf.h`) +follow the same template - header-only inline accessors, a field descriptor +table covering the format's own bits, `Init`, `IsValid` and payload helpers. +They differ only in the header they describe: the common stream header, except +for CRF/NTSCF, which use the alternative header. Both header styles are +versioned (0 and 1); the common stream header fields are described once in +[`CommonStreamHeader.h`](../include/avtp/CommonStreamHeader.h) and formats add +only their own fields in version 0 coordinates (TSCF is the reference). The CVF +format-specific headers (MJPEG, H.264, JPEG 2000) and the RVF raw header are +fragments of the stream data rather than standalone PDUs: they are validated +through the enclosing PDU (`Avtp_Cvf_IsValid`/`Avtp_Rvf_IsValid`, plus a +matching `format_subtype` for CVF) and provide a shallow `IsValid` of their own +that checks the fragment header fits into the given buffer. The document is split along two audiences: @@ -553,10 +556,16 @@ functions**. They are accessed through `Avtp_CommonHeader_Get/SetSubtype` and - `IsValid` checks it with `Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu)`. -Each format still declares `AVTP__FIELD_SUBTYPE` and -`AVTP__FIELD_VERSION` in its field enum and descriptor table, so the -generic `Avtp__Get/SetField` path and the "every bit described exactly -once" rule continue to hold; only the convenience accessors are omitted. +Version numbers are available as `AVTP_VERSION_0` / `AVTP_VERSION_1`. Each +format declares the versions it accepts (for example +`AVTP_TSCF_SUPPORTED_VERSIONS`) and `IsValid` checks them with +`Avtp_Version_IsSupported(mask, version)`, rejecting reserved version values. + +The common header fields are not repeated in format field enums: `subtype`, `h` +and `version` are owned by `Avtp_CommonHeaderFieldDesc`. Formats that have been +migrated to the common stream header module (see below) no longer declare +`AVTP__FIELD_SUBTYPE`/`_VERSION`; the remaining stream formats still +carry their own copies until they are migrated. ### h (header specific) @@ -572,6 +581,56 @@ defines the bit - all stream formats (AAF/CVF/CRF/RVF/TSCF/NTSCF) provide `Avtp_CommonHeader_GetH`/`SetH` remains the generic accessor for the raw bit, for formats that redefine it or reserve it. +## The AVTP common stream header + +The common stream header (4.7.4) is shared by all stream formats and exists in +two versions, selected by the common header's `version` field: + +| Version | Length | sequence_num | avtp_timestamp | Additional fields | +|---------|--------|--------------|----------------|----------------------------------------------| +| 0 | 24 B | 8 bit | 32 bit | - | +| 1 | 40 B | 32 bit | 64 bit | `ptp_grandmaster_identity`, `format_specific_data_0` | + +[`CommonStreamHeader.h`](../include/avtp/CommonStreamHeader.h) describes the +header once for both versions: + +- `Avtp_CommonStreamHeader_t` - a view type sized for the largest version. +- `AVTPDU_CSH_LEN_V0` / `AVTPDU_CSH_LEN_V1` - the version-dependent lengths. +- `AVTPDU_CSH_FIELD_*` - the field enum, mapped by `Avtp_CshFieldDescV0` and + `Avtp_CshFieldDescV1`, one descriptor table per version. +- `Avtp_CommonStreamHeader_*` - version-dispatched accessors for `sv`, `mr`, + `f_s_d`, `tv`, `sequence_num`, `format_specific_data_0/1`, `tu`, `stream_id`, + `avtp_timestamp`, `ptp_grandmaster_identity` and `stream_data_length`. + `GetSequenceNum` returns `uint32_t` and `GetAvtpTimestamp` returns `uint64_t` + in both versions; fields absent from a version return 0 and their setters are + no-ops. + +A migrated format (TSCF is the reference) declares only its own fields, in +version 0 coordinates, and adds the format offset in its GET/SET macros: + +```c +#define GET_TSCF_FIELD(field) \ + (Avtp_GetField(Avtp_TscfFieldDesc, AVTP_TSCF_FIELD_MAX, \ + (const uint8_t *)pdu + \ + Avtp_CommonStreamHeader_GetFormatOffset( \ + (const Avtp_CommonStreamHeader_t *)pdu), \ + field)) +``` + +`GetFormatOffset` is 0 for version 0 and 16 for version 1: version 1 inserts 16 +octets before the format-specific data area, so every format field shifts by +that amount. A new header version therefore means one new table in the style +module, not one new table per format. `GetHeaderLen` is used by the payload +helpers so `Avtp__Get/SetPayload` work for both versions. + +The version 1 PDU struct (for example `Avtp_TscfV1_t`) is sized for the larger +header and is used for allocation and embedding. Accessors keep taking the +version 0 struct pointer; version 1 callers cast once. + +The "every bit described exactly once" rule becomes a cross-module test: for +each version, the common header, the common stream header and the format's own +table (shifted by the format offset) must cover the whole header exactly once. + ## ACF layering & the common header ACF formats share a *common header* whose two fields - `acf_msg_type` and diff --git a/examples/acf-can/acf-can-common.c b/examples/acf-can/acf-can-common.c index 1e6ab6c6..db8e38ca 100644 --- a/examples/acf-can/acf-can-common.c +++ b/examples/acf-can/acf-can-common.c @@ -268,7 +268,7 @@ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uin proc_bytes += AVTP_TSCF_HEADER_LEN; msg_length += Avtp_Tscf_GetStreamDataLength((Avtp_Tscf_t *)cf_pdu) + AVTP_TSCF_HEADER_LEN; s_id = Avtp_Tscf_GetStreamId((Avtp_Tscf_t *)cf_pdu); - seq_num = Avtp_Tscf_GetSequenceNum((Avtp_Tscf_t *)cf_pdu); + seq_num = (uint8_t)Avtp_Tscf_GetSequenceNum((Avtp_Tscf_t *)cf_pdu); } else if (subtype == AVTP_SUBTYPE_NTSCF) { proc_bytes += AVTP_NTSCF_HEADER_LEN; msg_length += Avtp_Ntscf_GetNtscfDataLength((Avtp_Ntscf_t *)cf_pdu) + AVTP_NTSCF_HEADER_LEN; diff --git a/examples/acf-vss/acf-vss-talker.c b/examples/acf-vss/acf-vss-talker.c index 87e8182e..d02406c0 100644 --- a/examples/acf-vss/acf-vss-talker.c +++ b/examples/acf-vss/acf-vss-talker.c @@ -144,9 +144,9 @@ static int init_cf_pdu(uint8_t *pdu) Avtp_Tscf_t *tscf_pdu = (Avtp_Tscf_t *)pdu; memset(tscf_pdu, 0, AVTP_TSCF_HEADER_LEN); Avtp_Tscf_Init(tscf_pdu); - Avtp_Tscf_SetField(tscf_pdu, AVTP_TSCF_FIELD_TU, 0U); - Avtp_Tscf_SetField(tscf_pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM, seq_num++); - Avtp_Tscf_SetField(tscf_pdu, AVTP_TSCF_FIELD_STREAM_ID, STREAM_ID); + Avtp_Tscf_SetTu(tscf_pdu, false); + Avtp_Tscf_SetSequenceNum(tscf_pdu, seq_num++); + Avtp_Tscf_SetStreamId(tscf_pdu, STREAM_ID); res = AVTP_TSCF_HEADER_LEN; } else { Avtp_Ntscf_t *ntscf_pdu = (Avtp_Ntscf_t *)pdu; @@ -163,7 +163,7 @@ static int update_cf_length(uint8_t *cf_pdu, uint64_t length) { if (use_tscf) { uint64_t payloadLen = length - AVTP_TSCF_HEADER_LEN; - Avtp_Tscf_SetField((Avtp_Tscf_t *)cf_pdu, AVTP_TSCF_FIELD_STREAM_DATA_LENGTH, payloadLen); + Avtp_Tscf_SetStreamDataLength((Avtp_Tscf_t *)cf_pdu, (uint16_t)payloadLen); } else { uint64_t payloadLen = length - AVTP_NTSCF_HEADER_LEN; Avtp_Ntscf_SetField((Avtp_Ntscf_t *)cf_pdu, AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH, payloadLen); diff --git a/include/avtp/acf/Tscf.h b/include/avtp/acf/Tscf.h index c194ee8e..8c91c58e 100644 --- a/include/avtp/acf/Tscf.h +++ b/include/avtp/acf/Tscf.h @@ -31,6 +31,11 @@ * @file * This file contains the fields descriptions of the IEEE 1722 TSCF PDUs and * functions to invoke corresponding parser and deparser. + * + * TSCF uses the AVTPDU common stream header (4.7.4), so all common fields are + * accessed through Avtp_CommonStreamHeader_*. The fields in this module are + * described in version 0 coordinates; the GET/SET macros add the common stream + * header's format offset to reach the version 1 positions. */ #pragma once @@ -46,41 +51,45 @@ #include "avtp/Defines.h" #include "avtp/Utils.h" #include "avtp/CommonHeader.h" +#include "avtp/CommonStreamHeader.h" #ifdef __cplusplus extern "C" { #endif -#define AVTP_TSCF_HEADER_LEN (6 * AVTP_QUADLET_SIZE) +#define AVTP_TSCF_HEADER_LEN_V0 AVTPDU_CSH_LEN_V0 /* 24 */ +#define AVTP_TSCF_HEADER_LEN_V1 AVTPDU_CSH_LEN_V1 /* 40 */ +/* Kept for compatibility: the version 0 header length. */ +#define AVTP_TSCF_HEADER_LEN AVTP_TSCF_HEADER_LEN_V0 + +/* TSCF supports both versions of the common stream header (Table 7). */ +#define AVTP_TSCF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) #define GET_TSCF_FIELD(field) \ - (Avtp_GetField(Avtp_TscfFieldDesc, AVTP_TSCF_FIELD_MAX, (const uint8_t *)pdu, field)) + (Avtp_GetField(Avtp_TscfFieldDesc, AVTP_TSCF_FIELD_MAX, \ + (const uint8_t *)pdu + Avtp_CommonStreamHeader_GetFormatOffset( \ + (const Avtp_CommonStreamHeader_t *)pdu), \ + field)) #define SET_TSCF_FIELD(field, value) \ - (Avtp_SetField(Avtp_TscfFieldDesc, AVTP_TSCF_FIELD_MAX, (uint8_t *)pdu, field, value)) + (Avtp_SetField(Avtp_TscfFieldDesc, AVTP_TSCF_FIELD_MAX, \ + (uint8_t *)pdu + Avtp_CommonStreamHeader_GetFormatOffset( \ + (const Avtp_CommonStreamHeader_t *)pdu), \ + field, value)) typedef struct { - uint8_t header[AVTP_TSCF_HEADER_LEN]; + uint8_t header[AVTP_TSCF_HEADER_LEN_V0]; uint8_t payload[0]; } __attribute__((packed)) Avtp_Tscf_t; +typedef struct { + uint8_t header[AVTP_TSCF_HEADER_LEN_V1]; + uint8_t payload[0]; +} __attribute__((packed)) Avtp_TscfV1_t; + typedef enum { - /* Common AVTP header */ - AVTP_TSCF_FIELD_SUBTYPE, - AVTP_TSCF_FIELD_SV, - AVTP_TSCF_FIELD_VERSION, - - /* TSCF header fields */ - AVTP_TSCF_FIELD_MR, - AVTP_TSCF_FIELD_RSV, - AVTP_TSCF_FIELD_TV, - AVTP_TSCF_FIELD_SEQUENCE_NUM, - AVTP_TSCF_FIELD_RESERVED1, - AVTP_TSCF_FIELD_TU, - AVTP_TSCF_FIELD_STREAM_ID, - AVTP_TSCF_FIELD_AVTP_TIMESTAMP, + /* TSCF-specific fields (format_specific_data_2 and _3) */ AVTP_TSCF_FIELD_RESERVED2, - AVTP_TSCF_FIELD_STREAM_DATA_LENGTH, AVTP_TSCF_FIELD_RESERVED3, /* Count number of fields for bound checks */ @@ -88,116 +97,136 @@ typedef enum { } Avtp_TscfFields_t; /** - * This table maps all IEEE 1722 TSCF-specific header fields to a descriptor. + * This table maps all TSCF-specific header fields to a descriptor. It is + * written in version 0 coordinates; the accessors add the common stream + * header's format offset for version 1. */ static const Avtp_FieldDescriptor_t Avtp_TscfFieldDesc[AVTP_TSCF_FIELD_MAX] = { - /* Common AVTP header */ - [AVTP_TSCF_FIELD_SUBTYPE] = {.quadlet = 0, .offset = 0, .bits = 8}, - [AVTP_TSCF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, - [AVTP_TSCF_FIELD_VERSION] = {.quadlet = 0, .offset = 9, .bits = 3}, - /* TSCF header*/ - [AVTP_TSCF_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, - [AVTP_TSCF_FIELD_RSV] = {.quadlet = 0, .offset = 13, .bits = 2}, - [AVTP_TSCF_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, - [AVTP_TSCF_FIELD_SEQUENCE_NUM] = {.quadlet = 0, .offset = 16, .bits = 8}, - [AVTP_TSCF_FIELD_RESERVED1] = {.quadlet = 0, .offset = 24, .bits = 7}, - [AVTP_TSCF_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, - [AVTP_TSCF_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, - [AVTP_TSCF_FIELD_AVTP_TIMESTAMP] = {.quadlet = 3, .offset = 0, .bits = 32}, [AVTP_TSCF_FIELD_RESERVED2] = {.quadlet = 4, .offset = 0, .bits = 32}, - [AVTP_TSCF_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 5, .offset = 0, .bits = 16}, [AVTP_TSCF_FIELD_RESERVED3] = {.quadlet = 5, .offset = 16, .bits = 16}, }; /** - * Return the value of an an TSCF PDU SV field as specified in the IEEE 1722 Specification. + * Return the value of the TSCF SV field as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. - * @returns Value of the TSCF PDU SV field. + * @returns Value of the TSCF SV field. */ OPEN1722_INLINE bool Avtp_Tscf_IsSv(const Avtp_Tscf_t *const pdu) { - return (bool)GET_TSCF_FIELD(AVTP_TSCF_FIELD_SV); + return Avtp_CommonStreamHeader_IsSv((const Avtp_CommonStreamHeader_t *)pdu); } /** - * Return the value of an an TSCF PDU MR field as specified in the IEEE 1722 Specification. + * Return the value of the TSCF MR field as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. - * @returns Value of the TSCF PDU MR field. + * @returns Value of the TSCF MR field. */ OPEN1722_INLINE bool Avtp_Tscf_IsMr(const Avtp_Tscf_t *const pdu) { - return (bool)GET_TSCF_FIELD(AVTP_TSCF_FIELD_MR); + return Avtp_CommonStreamHeader_IsMr((const Avtp_CommonStreamHeader_t *)pdu); } /** - * Return the value of an an TSCF PDU TV field as specified in the IEEE 1722 Specification. + * Return the value of the TSCF TV field as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. - * @returns Value of the TSCF PDU TV field. + * @returns Value of the TSCF TV field. */ OPEN1722_INLINE bool Avtp_Tscf_IsTv(const Avtp_Tscf_t *const pdu) { - return (bool)GET_TSCF_FIELD(AVTP_TSCF_FIELD_TV); + return Avtp_CommonStreamHeader_IsTv((const Avtp_CommonStreamHeader_t *)pdu); } /** - * Return the value of an an TSCF PDU Sequence Number field as specified in the IEEE 1722 - * Specification. + * Return the value of the TSCF TU field as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. - * @returns Value of the TSCF PDU Sequence Number field. + * @returns Value of the TSCF TU field. */ -OPEN1722_INLINE uint8_t Avtp_Tscf_GetSequenceNum(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE bool Avtp_Tscf_IsTu(const Avtp_Tscf_t *const pdu) { - return (uint8_t)GET_TSCF_FIELD(AVTP_TSCF_FIELD_SEQUENCE_NUM); + return Avtp_CommonStreamHeader_IsTu((const Avtp_CommonStreamHeader_t *)pdu); } /** - * Return the value of an an TSCF PDU TU field as specified in the IEEE 1722 Specification. + * Return the value of the TSCF Sequence Number field as specified in the IEEE 1722 + * Specification. The field is 8 bits in version 0 and 32 bits in version 1. * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. - * @returns Value of the TSCF PDU TU field. + * @returns Value of the TSCF Sequence Number field. */ -OPEN1722_INLINE bool Avtp_Tscf_IsTu(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Tscf_GetSequenceNum(const Avtp_Tscf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetSequenceNum((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Return the value of the TSCF sequence_num_lsb field. In version 0 this is the + * 8-bit sequence_num field; in version 1 it is the copy of the eight least + * significant bits of the 32-bit sequence_num field, stored in + * format_specific_data_0 (TSCF-4). + * + * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. + * @returns Value of the TSCF sequence_num_lsb field. + */ +OPEN1722_INLINE uint8_t Avtp_Tscf_GetSequenceNumLsb(const Avtp_Tscf_t *const pdu) { - return (bool)GET_TSCF_FIELD(AVTP_TSCF_FIELD_TU); + if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1) { + return Avtp_CommonStreamHeader_GetFormatSpecificData0( + (const Avtp_CommonStreamHeader_t *)pdu); + } + return (uint8_t)Avtp_CommonStreamHeader_GetSequenceNum((const Avtp_CommonStreamHeader_t *)pdu); } /** - * Return the value of an an TSCF PDU Stream ID field as specified in the IEEE 1722 Specification. + * Return the value of the TSCF Stream ID field as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. - * @returns Value of the TSCF PDU Stream ID field. + * @returns Value of the TSCF Stream ID field. */ OPEN1722_INLINE uint64_t Avtp_Tscf_GetStreamId(const Avtp_Tscf_t *const pdu) { - return (uint64_t)GET_TSCF_FIELD(AVTP_TSCF_FIELD_STREAM_ID); + return Avtp_CommonStreamHeader_GetStreamId((const Avtp_CommonStreamHeader_t *)pdu); } /** - * Return the value of an an TSCF PDU AVTP Timestamp field as specified in the IEEE 1722 - * Specification. + * Return the value of the TSCF AVTP Timestamp field as specified in the IEEE 1722 + * Specification. The field is 32 bits in version 0 and 64 bits in version 1. + * + * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. + * @returns Value of the TSCF AVTP Timestamp field. + */ +OPEN1722_INLINE uint64_t Avtp_Tscf_GetAvtpTimestamp(const Avtp_Tscf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetAvtpTimestamp((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Return the value of the TSCF ptp_grandmaster_identity field. The field only + * exists in version 1; version 0 returns 0. * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. - * @returns Value of the TSCF PDU AVTP Timestamp field. + * @returns Value of the TSCF ptp_grandmaster_identity field. */ -OPEN1722_INLINE uint32_t Avtp_Tscf_GetAvtpTimestamp(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Tscf_GetPtpGrandmasterIdentity(const Avtp_Tscf_t *const pdu) { - return (uint32_t)GET_TSCF_FIELD(AVTP_TSCF_FIELD_AVTP_TIMESTAMP); + return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity( + (const Avtp_CommonStreamHeader_t *)pdu); } /** - * Return the value of an an TSCF PDU Stream Data Length field as specified in the IEEE 1722 + * Return the value of the TSCF Stream Data Length field as specified in the IEEE 1722 * Specification. * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. - * @returns Value of the TSCF PDU Stream Data Length field. + * @returns Value of the TSCF Stream Data Length field. */ OPEN1722_INLINE uint16_t Avtp_Tscf_GetStreamDataLength(const Avtp_Tscf_t *const pdu) { - return (uint16_t)GET_TSCF_FIELD(AVTP_TSCF_FIELD_STREAM_DATA_LENGTH); + return Avtp_CommonStreamHeader_GetStreamDataLength((const Avtp_CommonStreamHeader_t *)pdu); } /** @@ -208,7 +237,7 @@ OPEN1722_INLINE uint16_t Avtp_Tscf_GetStreamDataLength(const Avtp_Tscf_t *const */ OPEN1722_INLINE void Avtp_Tscf_SetSv(Avtp_Tscf_t *pdu, bool sv) { - SET_TSCF_FIELD(AVTP_TSCF_FIELD_SV, sv); + Avtp_CommonStreamHeader_SetSv((Avtp_CommonStreamHeader_t *)pdu, sv); } /** @@ -219,7 +248,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetSv(Avtp_Tscf_t *pdu, bool sv) */ OPEN1722_INLINE void Avtp_Tscf_SetMr(Avtp_Tscf_t *pdu, bool mr) { - SET_TSCF_FIELD(AVTP_TSCF_FIELD_MR, mr); + Avtp_CommonStreamHeader_SetMr((Avtp_CommonStreamHeader_t *)pdu, mr); } /** @@ -230,56 +259,74 @@ OPEN1722_INLINE void Avtp_Tscf_SetMr(Avtp_Tscf_t *pdu, bool mr) */ OPEN1722_INLINE void Avtp_Tscf_SetTv(Avtp_Tscf_t *pdu, bool tv) { - SET_TSCF_FIELD(AVTP_TSCF_FIELD_TV, tv); + Avtp_CommonStreamHeader_SetTv((Avtp_CommonStreamHeader_t *)pdu, tv); } /** - * Set the value of an an TSCF PDU Sequence Number field as specified in the IEEE 1722 - * Specification. + * Set the TU bit in an ACF Tscf frame as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. - * @param value Value to set the TSCF PDU Sequence Number field to. + * @param tu Value to set the TSCF PDU TU field to. */ -OPEN1722_INLINE void Avtp_Tscf_SetSequenceNum(Avtp_Tscf_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Tscf_SetTu(Avtp_Tscf_t *pdu, bool tu) { - SET_TSCF_FIELD(AVTP_TSCF_FIELD_SEQUENCE_NUM, value); + Avtp_CommonStreamHeader_SetTu((Avtp_CommonStreamHeader_t *)pdu, tu); } /** - * Set the TU bit in an ACF Tscf frame as specified in the IEEE 1722 Specification. + * Set the value of the TSCF Sequence Number field as specified in the IEEE 1722 + * Specification. In version 1 the eight least significant bits are also written + * to the sequence_num_lsb copy in format_specific_data_0 (TSCF-4). * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. - * @param tu Value to set the TSCF PDU TU field to. + * @param value Value to set the TSCF PDU Sequence Number field to. */ -OPEN1722_INLINE void Avtp_Tscf_SetTu(Avtp_Tscf_t *pdu, bool tu) +OPEN1722_INLINE void Avtp_Tscf_SetSequenceNum(Avtp_Tscf_t *pdu, uint32_t value) { - SET_TSCF_FIELD(AVTP_TSCF_FIELD_TU, tu); + Avtp_CommonStreamHeader_SetSequenceNum((Avtp_CommonStreamHeader_t *)pdu, value); + if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_CommonStreamHeader_SetFormatSpecificData0((Avtp_CommonStreamHeader_t *)pdu, + (uint8_t)(value & 0xFFU)); + } } /** - * Set the value of an an TSCF PDU Stream ID field as specified in the IEEE 1722 Specification. + * Set the value of the TSCF Stream ID field as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. * @param value Value to set the TSCF PDU Stream ID field to. */ OPEN1722_INLINE void Avtp_Tscf_SetStreamId(Avtp_Tscf_t *pdu, uint64_t value) { - SET_TSCF_FIELD(AVTP_TSCF_FIELD_STREAM_ID, value); + Avtp_CommonStreamHeader_SetStreamId((Avtp_CommonStreamHeader_t *)pdu, value); } /** - * Set the value of an an TSCF PDU AVTP Timestamp field as specified in the IEEE 1722 Specification. + * Set the value of the TSCF AVTP Timestamp field as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. * @param value Value to set the TSCF PDU AVTP Timestamp field to. */ -OPEN1722_INLINE void Avtp_Tscf_SetAvtpTimestamp(Avtp_Tscf_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Tscf_SetAvtpTimestamp(Avtp_Tscf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetAvtpTimestamp((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Set the value of the TSCF ptp_grandmaster_identity field. The field only + * exists in version 1; on version 0 this is a no-op. + * + * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. + * @param value Value to set the TSCF PDU ptp_grandmaster_identity field to. + */ +OPEN1722_INLINE void Avtp_Tscf_SetPtpGrandmasterIdentity(Avtp_Tscf_t *pdu, uint64_t value) { - SET_TSCF_FIELD(AVTP_TSCF_FIELD_AVTP_TIMESTAMP, value); + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity((Avtp_CommonStreamHeader_t *)pdu, value); } /** - * Set the value of an an TSCF PDU Stream Data Length field as specified in the IEEE 1722 + * Set the value of the TSCF Stream Data Length field as specified in the IEEE 1722 * Specification. * * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. @@ -287,13 +334,43 @@ OPEN1722_INLINE void Avtp_Tscf_SetAvtpTimestamp(Avtp_Tscf_t *pdu, uint32_t value */ OPEN1722_INLINE void Avtp_Tscf_SetStreamDataLength(Avtp_Tscf_t *pdu, uint16_t value) { - SET_TSCF_FIELD(AVTP_TSCF_FIELD_STREAM_DATA_LENGTH, value); + Avtp_CommonStreamHeader_SetStreamDataLength((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Returns a pointer to the payload of a TSCF frame. The payload starts after + * the version-dependent common stream header. + * + * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. + * @return Pointer to the TSCF frame payload. + */ +OPEN1722_INLINE const uint8_t *Avtp_Tscf_GetPayload(const Avtp_Tscf_t *const pdu) +{ + return (const uint8_t *)pdu + + Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Sets the TSCF payload. + * + * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. + * @param payload Pointer to the payload byte array. + * @param payload_length Length of the payload. + */ +OPEN1722_INLINE void Avtp_Tscf_SetPayload(Avtp_Tscf_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + + Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu), + payload, payload_length); } /** * Checks if the ACF Tscf frame is valid by checking: - * 1) if the length field of AVTP/ACF messages contains a value larger than the actual size of - * the buffer that contains the AVTP message. 2) if other format specific invariants are not upheld + * 1) that the subtype is TSCF and the version is supported, + * 2) that the version-dependent header fits into the buffer, + * 3) that the declared stream_data_length fits into the buffer. + * * @param pdu Pointer to the first bit of an 1722 ACF Tscf PDU. * @param bufferSize Size of the buffer containing the ACF Tscf frame. * @return true if the ACF Tscf frame is valid, false otherwise. @@ -304,16 +381,22 @@ OPEN1722_INLINE bool Avtp_Tscf_IsValid(const Avtp_Tscf_t *const pdu, size_t buff return false; } - if (bufferSize < AVTP_TSCF_HEADER_LEN) { + if (Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu) != AVTP_SUBTYPE_TSCF) { return false; } - if (Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu) != AVTP_SUBTYPE_TSCF) { + uint8_t version = Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu); + if (!Avtp_Version_IsSupported(AVTP_TSCF_SUPPORTED_VERSIONS, version)) { + return false; + } + + size_t headerLen = Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); + if (bufferSize < headerLen) { return false; } // Avtp_Tscf_GetStreamDataLength returns the stream data length in octets. - if (Avtp_Tscf_GetStreamDataLength(pdu) > bufferSize) { + if ((size_t)Avtp_Tscf_GetStreamDataLength(pdu) > bufferSize - headerLen) { return false; } @@ -321,7 +404,7 @@ OPEN1722_INLINE bool Avtp_Tscf_IsValid(const Avtp_Tscf_t *const pdu, size_t buff } /** - * Initializes a TSCF PDU as specified in the IEEE 1722-2016 Specification. + * Initializes a version 0 TSCF PDU as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- * or an ACF header. @@ -336,11 +419,27 @@ OPEN1722_INLINE void Avtp_Tscf_Init(Avtp_Tscf_t *pdu) } /** - * Returns the value of an an AVTP TSCF field as specified in the IEEE 1722 Specification. + * Initializes a version 1 TSCF PDU. The caller must provide a buffer of at + * least AVTP_TSCF_HEADER_LEN_V1 octets. + * + * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- + * or an ACF header. + */ +OPEN1722_INLINE void Avtp_Tscf_InitV1(Avtp_TscfV1_t *pdu) +{ + if (pdu != NULL) { + memset(pdu, 0, sizeof(Avtp_TscfV1_t)); + Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_TSCF); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_Tscf_SetSv((Avtp_Tscf_t *)pdu, true); + } +} + +/** + * Returns the value of an AVTP TSCF field as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 AVTP TSCF PDU. * @param field Specifies the position of the data field to be read - * @param value Pointer to location to store the value. * @returns This function returns the value of the field. */ OPEN1722_INLINE uint64_t Avtp_Tscf_GetField(const Avtp_Tscf_t *const pdu, Avtp_TscfFields_t field) @@ -349,11 +448,11 @@ OPEN1722_INLINE uint64_t Avtp_Tscf_GetField(const Avtp_Tscf_t *const pdu, Avtp_T } /** - * Sets the value of an an AVTP TSCF field as specified in the IEEE 1722 Specification. + * Sets the value of an AVTP TSCF field as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 AVTP TSCF PDU. * @param field Specifies the position of the data field to be read - * @param value Pointer to location to store the value. + * @param value The value to set. */ OPEN1722_INLINE void Avtp_Tscf_SetField(Avtp_Tscf_t *pdu, Avtp_TscfFields_t field, uint64_t value) { diff --git a/unit/test-tscf.c b/unit/test-tscf.c index 57f70cd1..7711fb8b 100644 --- a/unit/test-tscf.c +++ b/unit/test-tscf.c @@ -38,65 +38,235 @@ extern "C" { #include #endif #include -#include #include -#include -#include #include "avtp/acf/Tscf.h" #include "avtp/CommonHeader.h" +#include "avtp/CommonStreamHeader.h" #define MAX_PDU_SIZE 1500 -static void tscf_init(void **state) +static uint32_t read_quadlet(const uint8_t *pdu, size_t quadlet) { + uint32_t word; + + memcpy(&word, pdu + (quadlet * 4), sizeof(word)); + return ntohl(word); +} +static void tscf_init(void **state) +{ + (void)state; uint8_t pdu[MAX_PDU_SIZE]; - uint8_t init_pdu[AVTP_TSCF_HEADER_LEN]; + uint8_t init_pdu[AVTP_TSCF_HEADER_LEN_V0]; - // Check the lengths - assert_int_equal(sizeof(Avtp_Tscf_t), AVTP_TSCF_HEADER_LEN); + assert_int_equal(sizeof(Avtp_Tscf_t), AVTP_TSCF_HEADER_LEN_V0); + assert_int_equal(sizeof(Avtp_TscfV1_t), AVTP_TSCF_HEADER_LEN_V1); - // Check init function while passing in a null pointer + /* Passing a NULL pointer must be a no-op. */ Avtp_Tscf_Init(NULL); - // Check if the function is initializing properly Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); - memset(init_pdu, 0, AVTP_TSCF_HEADER_LEN); - init_pdu[0] = AVTP_SUBTYPE_TSCF; // Setting AVTP Subtype as TSCF - init_pdu[1] = 0x80; // Setting Stream as valid - assert_memory_equal(init_pdu, pdu, AVTP_TSCF_HEADER_LEN); + memset(init_pdu, 0, AVTP_TSCF_HEADER_LEN_V0); + init_pdu[0] = AVTP_SUBTYPE_TSCF; /* subtype = TSCF */ + init_pdu[1] = 0x80; /* sv = 1, version = 0 */ + assert_memory_equal(init_pdu, pdu, AVTP_TSCF_HEADER_LEN_V0); } -static void tscf_is_valid(void **state) +static void tscf_init_v1(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t init_pdu[AVTP_TSCF_HEADER_LEN_V1]; + + /* Passing a NULL pointer must be a no-op. */ + Avtp_Tscf_InitV1(NULL); + + Avtp_Tscf_InitV1((Avtp_TscfV1_t *)pdu); + memset(init_pdu, 0, AVTP_TSCF_HEADER_LEN_V1); + init_pdu[0] = AVTP_SUBTYPE_TSCF; /* subtype = TSCF */ + init_pdu[1] = 0x90; /* sv = 1, version = 1 */ + assert_memory_equal(init_pdu, pdu, AVTP_TSCF_HEADER_LEN_V1); + + assert_int_equal(Avtp_CommonStreamHeader_GetVersion((Avtp_CommonStreamHeader_t *)pdu), + AVTP_VERSION_1); + assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen((Avtp_CommonStreamHeader_t *)pdu), + AVTP_TSCF_HEADER_LEN_V1); +} + +static void tscf_v0_layout(void **state) { + (void)state; + uint8_t pdu[AVTP_TSCF_HEADER_LEN_V0]; + uint8_t snapshot[AVTP_TSCF_HEADER_LEN_V0]; + Avtp_Tscf_t *tscf = (Avtp_Tscf_t *)pdu; - uint8_t pdu[MAX_PDU_SIZE], result; + Avtp_Tscf_Init(tscf); + + Avtp_Tscf_SetSequenceNum(tscf, 0xAB); + assert_int_equal(Avtp_Tscf_GetSequenceNum(tscf), 0xAB); + assert_int_equal(Avtp_Tscf_GetSequenceNumLsb(tscf), 0xAB); + assert_int_equal(read_quadlet(pdu, 0), 0x0580AB00); + + Avtp_Tscf_SetAvtpTimestamp(tscf, 0x80C0FFEE); + assert_int_equal(Avtp_Tscf_GetAvtpTimestamp(tscf), 0x80C0FFEE); + assert_int_equal(read_quadlet(pdu, 3), 0x80C0FFEE); + + /* ptp_grandmaster_identity does not exist in version 0: the setter is a + * no-op and the getter returns 0. */ + assert_int_equal(Avtp_Tscf_GetPtpGrandmasterIdentity(tscf), 0); + memcpy(snapshot, pdu, sizeof(snapshot)); + Avtp_Tscf_SetPtpGrandmasterIdentity(tscf, 0xFFFFFFFFFFFFFFFFULL); + assert_memory_equal(snapshot, pdu, sizeof(snapshot)); +} + +static void tscf_v1_layout(void **state) +{ + (void)state; + uint8_t pdu[AVTP_TSCF_HEADER_LEN_V1]; + Avtp_Tscf_t *tscf = (Avtp_Tscf_t *)pdu; + + Avtp_Tscf_InitV1((Avtp_TscfV1_t *)pdu); + + Avtp_Tscf_SetStreamId(tscf, 0x0102030405060708ULL); + assert_int_equal(Avtp_Tscf_GetStreamId(tscf), 0x0102030405060708ULL); + assert_int_equal(read_quadlet(pdu, 1), 0x01020304); + assert_int_equal(read_quadlet(pdu, 2), 0x05060708); + + Avtp_Tscf_SetSequenceNum(tscf, 0x12345678); + assert_int_equal(Avtp_Tscf_GetSequenceNum(tscf), 0x12345678); + assert_int_equal(read_quadlet(pdu, 3), 0x12345678); + /* sequence_num_lsb copy in format_specific_data_0 (byte 2 of quadlet 0). */ + assert_int_equal(pdu[2], 0x78); + assert_int_equal(Avtp_Tscf_GetSequenceNumLsb(tscf), 0x78); + + Avtp_Tscf_SetAvtpTimestamp(tscf, 0x1122334455667788ULL); + assert_int_equal(Avtp_Tscf_GetAvtpTimestamp(tscf), 0x1122334455667788ULL); + assert_int_equal(read_quadlet(pdu, 4), 0x11223344); + assert_int_equal(read_quadlet(pdu, 5), 0x55667788); + + Avtp_Tscf_SetPtpGrandmasterIdentity(tscf, 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Tscf_GetPtpGrandmasterIdentity(tscf), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(read_quadlet(pdu, 6), 0x99AABBCC); + assert_int_equal(read_quadlet(pdu, 7), 0xDDEEFF00); + + Avtp_Tscf_SetStreamDataLength(tscf, 0x0ABC); + assert_int_equal(Avtp_Tscf_GetStreamDataLength(tscf), 0x0ABC); + assert_int_equal(read_quadlet(pdu, 9), 0x0ABC0000); +} - // Valid IEEE 1722 TSCF Frame +static void tscf_is_valid(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + + /* Valid version 0 frame with no payload. */ Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); - assert_int_equal(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, MAX_PDU_SIZE), 1); + assert_true(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, AVTP_TSCF_HEADER_LEN_V0)); - // Not a IEEE 1722 TSCF Frame + /* Not a TSCF frame. */ memset(pdu, 0, MAX_PDU_SIZE); - assert_int_equal(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, MAX_PDU_SIZE), 0); + assert_false(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, MAX_PDU_SIZE)); - // Valid IEEE 1722 TSCF Frame (Length 28, Buffer 30) + /* Buffer smaller than the version 0 header. */ Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); - Avtp_Tscf_SetStreamDataLength((Avtp_Tscf_t *)pdu, 28); - assert_int_equal(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, 30), 1); + assert_false(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, AVTP_TSCF_HEADER_LEN_V0 - 1)); + + /* stream_data_length must fit after the header. */ + Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); + Avtp_Tscf_SetStreamDataLength((Avtp_Tscf_t *)pdu, 10); + assert_false(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, AVTP_TSCF_HEADER_LEN_V0 + 9)); + assert_true(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, AVTP_TSCF_HEADER_LEN_V0 + 10)); + + /* Valid version 1 frame with no payload. */ + Avtp_Tscf_InitV1((Avtp_TscfV1_t *)pdu); + assert_true(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, AVTP_TSCF_HEADER_LEN_V1)); + assert_false(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, AVTP_TSCF_HEADER_LEN_V1 - 1)); + + /* Unsupported version is rejected. */ + Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, 2); + assert_false(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, MAX_PDU_SIZE)); +} + +static void tscf_payload(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t payload[4] = {0xDE, 0xAD, 0xBE, 0xEF}; - // Invalid IEEE 1722 TSCF Frame (Length 24 but buffer only 9!) Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); - Avtp_Tscf_SetStreamDataLength((Avtp_Tscf_t *)pdu, 24); - assert_int_equal(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, 9), 0); + assert_ptr_equal(Avtp_Tscf_GetPayload((Avtp_Tscf_t *)pdu), pdu + AVTP_TSCF_HEADER_LEN_V0); + Avtp_Tscf_SetPayload((Avtp_Tscf_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_TSCF_HEADER_LEN_V0, payload, sizeof(payload)); + + Avtp_Tscf_InitV1((Avtp_TscfV1_t *)pdu); + assert_ptr_equal(Avtp_Tscf_GetPayload((Avtp_Tscf_t *)pdu), pdu + AVTP_TSCF_HEADER_LEN_V1); + Avtp_Tscf_SetPayload((Avtp_Tscf_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_TSCF_HEADER_LEN_V1, payload, sizeof(payload)); +} + +static void mark_descriptors(uint8_t *coverage, size_t coverageBits, + const Avtp_FieldDescriptor_t *desc, uint8_t numFields, + uint8_t quadletOffset) +{ + for (uint8_t i = 0; i < numFields; i++) { + uint8_t bits = desc[i].bits; + uint8_t offset = desc[i].offset; + uint8_t quadlet = (uint8_t)(desc[i].quadlet + quadletOffset); + + for (uint8_t b = 0; b < bits; b++) { + size_t bit = ((size_t)quadlet * 32) + offset + b; + + assert_true(bit < coverageBits); + assert_int_equal(coverage[bit], 0); + coverage[bit] = 1; + } + } +} + +static void tscf_header_coverage(void **state) +{ + (void)state; + + for (uint8_t version = 0; version <= 1; version++) { + uint8_t coverage[AVTP_TSCF_HEADER_LEN_V1 * 8] = {0}; + size_t coverageBits = sizeof(coverage); + const Avtp_FieldDescriptor_t *cshDesc = + version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + uint8_t formatOffsetQuadlets = version == AVTP_VERSION_1 ? 4 : 0; + size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_TSCF_HEADER_LEN_V1 + : (size_t)AVTP_TSCF_HEADER_LEN_V0) * + 8; + + /* subtype and version are owned by the common header; h/sv is owned by + * the style header and covered below. */ + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_SUBTYPE], 1, 0); + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_VERSION], 1, 0); + /* Common stream header fields. */ + mark_descriptors(coverage, coverageBits, cshDesc, AVTPDU_CSH_FIELD_MAX, 0); + /* TSCF-specific fields, shifted to the version's format area. */ + mark_descriptors(coverage, coverageBits, Avtp_TscfFieldDesc, AVTP_TSCF_FIELD_MAX, + formatOffsetQuadlets); + + for (size_t bit = 0; bit < coverageBits; bit++) { + assert_int_equal(coverage[bit], bit < headerBits ? 1 : 0); + } + } } int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(tscf_init), + cmocka_unit_test(tscf_init_v1), + cmocka_unit_test(tscf_v0_layout), + cmocka_unit_test(tscf_v1_layout), cmocka_unit_test(tscf_is_valid), + cmocka_unit_test(tscf_payload), + cmocka_unit_test(tscf_header_coverage), }; return cmocka_run_group_tests(tests, NULL, NULL); From c7147a9c65767c61b79377c3012934debd67f76b Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Fri, 18 Sep 2026 23:57:57 +0200 Subject: [PATCH 04/16] TSCFv1 support in linu CAN examples Signed-off-by: Sebastian Schildt --- examples/acf-can/acf-can-common.c | 78 ++++++++++++++--------- examples/acf-can/acf-can-common.h | 18 ++++-- examples/acf-can/linux/README.md | 8 ++- examples/acf-can/linux/acf-can-bridge.c | 32 +++++++--- examples/acf-can/linux/acf-can-listener.c | 2 +- examples/acf-can/linux/acf-can-talker.c | 30 +++++++-- examples/acf-can/zephyr/Kconfig | 4 ++ examples/acf-can/zephyr/acf-can-bridge.c | 24 +++++-- 8 files changed, 137 insertions(+), 59 deletions(-) diff --git a/examples/acf-can/acf-can-common.c b/examples/acf-can/acf-can-common.c index db8e38ca..f5a918a2 100644 --- a/examples/acf-can/acf-can-common.c +++ b/examples/acf-can/acf-can-common.c @@ -50,6 +50,7 @@ LOG_MODULE_REGISTER(acf_can_common, LOG_LEVEL_DBG); #include #include #include +#include #include "avtp/Udp.h" #include "avtp/CommonHeader.h" @@ -115,36 +116,41 @@ int setup_can_socket(const char *can_ifname, bool can_fd) } #endif -static int init_cf_pdu(uint8_t *pdu, uint64_t stream_id, int use_tscf, int seq_num) +static int init_cf_pdu(uint8_t *pdu, uint64_t stream_id, acf_can_cf_t cf, uint32_t seq_num) { int res; - if (use_tscf) { - Avtp_Tscf_t *tscf_pdu = (Avtp_Tscf_t *)pdu; - memset(tscf_pdu, 0, AVTP_TSCF_HEADER_LEN); - Avtp_Tscf_Init(tscf_pdu); - Avtp_Tscf_SetTu(tscf_pdu, false); - Avtp_Tscf_SetSequenceNum(tscf_pdu, seq_num); - Avtp_Tscf_SetStreamId(tscf_pdu, stream_id); - res = AVTP_TSCF_HEADER_LEN; - } else { + + if (cf == ACF_CAN_CF_NTSCF) { Avtp_Ntscf_t *ntscf_pdu = (Avtp_Ntscf_t *)pdu; - memset(ntscf_pdu, 0, AVTP_NTSCF_HEADER_LEN); Avtp_Ntscf_Init(ntscf_pdu); - Avtp_Ntscf_SetSequenceNum(ntscf_pdu, seq_num); + Avtp_Ntscf_SetSequenceNum(ntscf_pdu, (uint8_t)seq_num); Avtp_Ntscf_SetStreamId(ntscf_pdu, stream_id); - res = AVTP_NTSCF_HEADER_LEN; + return AVTP_NTSCF_HEADER_LEN; + } + + if (cf == ACF_CAN_CF_TSCF_V1) { + Avtp_Tscf_InitV1((Avtp_TscfV1_t *)pdu); + } else { + Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); } + Avtp_Tscf_SetTu((Avtp_Tscf_t *)pdu, false); + Avtp_Tscf_SetSequenceNum((Avtp_Tscf_t *)pdu, seq_num); + Avtp_Tscf_SetStreamId((Avtp_Tscf_t *)pdu, stream_id); + + res = (int)Avtp_CommonStreamHeader_GetHeaderLen((Avtp_CommonStreamHeader_t *)pdu); return res; } -static int update_cf_length(uint8_t *cf_pdu, uint64_t length, int use_tscf) +static int update_cf_length(uint8_t *cf_pdu, uint64_t length, acf_can_cf_t cf) { - if (use_tscf) { - uint64_t payloadLen = length - AVTP_TSCF_HEADER_LEN; - Avtp_Tscf_SetStreamDataLength((Avtp_Tscf_t *)cf_pdu, payloadLen); - } else { + if (cf == ACF_CAN_CF_NTSCF) { uint64_t payloadLen = length - AVTP_NTSCF_HEADER_LEN; - Avtp_Ntscf_SetNtscfDataLength((Avtp_Ntscf_t *)cf_pdu, payloadLen); + Avtp_Ntscf_SetNtscfDataLength((Avtp_Ntscf_t *)cf_pdu, (uint16_t)payloadLen); + } else { + size_t headerLen = + Avtp_CommonStreamHeader_GetHeaderLen((Avtp_CommonStreamHeader_t *)cf_pdu); + uint64_t payloadLen = length - headerLen; + Avtp_Tscf_SetStreamDataLength((Avtp_Tscf_t *)cf_pdu, (uint16_t)payloadLen); } return 0; } @@ -200,8 +206,8 @@ static int prepare_acf_packet(uint8_t *acf_pdu, frame_t *frame, bool can_fd) return Avtp_AcfCommon_GetAcfMsgLengthInBytes((Avtp_AcfCommon_t *)pdu); } -int can_to_avtp(frame_t *can_frames, bool can_fd, uint8_t *pdu, int use_udp, int use_tscf, - uint64_t stream_id, uint8_t num_acf_msgs, uint8_t cf_seq_num, uint32_t udp_seq_num) +int can_to_avtp(frame_t *can_frames, bool can_fd, uint8_t *pdu, int use_udp, acf_can_cf_t cf, + uint64_t stream_id, uint8_t num_acf_msgs, uint32_t cf_seq_num, uint32_t udp_seq_num) { // Pack into control formats @@ -218,7 +224,7 @@ int can_to_avtp(frame_t *can_frames, bool can_fd, uint8_t *pdu, int use_udp, int // Prepare the control format: TSCF/NTSCF cf_pdu = pdu + pdu_length; - res = init_cf_pdu(cf_pdu, stream_id, use_tscf, cf_seq_num++); + res = init_cf_pdu(cf_pdu, stream_id, cf, cf_seq_num); pdu_length += res; cf_length += res; @@ -232,16 +238,17 @@ int can_to_avtp(frame_t *can_frames, bool can_fd, uint8_t *pdu, int use_udp, int } // Update the length of the PDU - update_cf_length(cf_pdu, cf_length, use_tscf); + update_cf_length(cf_pdu, cf_length, cf); return pdu_length; } int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uint64_t stream_id, - uint8_t *exp_cf_seqnum, uint32_t *exp_udp_seqnum) + uint32_t *exp_cf_seqnum, uint32_t *exp_udp_seqnum) { - uint8_t *cf_pdu, *acf_pdu, *udp_pdu, seq_num, i = 0; + uint8_t *cf_pdu, *acf_pdu, *udp_pdu, i = 0; + uint32_t seq_num; uint32_t udp_seq_num; uint16_t proc_bytes = 0, msg_length = 0; uint64_t s_id; @@ -254,8 +261,8 @@ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uin proc_bytes += AVTP_UDP_HEADER_LEN; msg_length += AVTP_UDP_HEADER_LEN; if (udp_seq_num != *exp_udp_seqnum) { - LOG_ERR("Incorrect UDP sequence num. Expected: %d Recd.: %d\n", *exp_udp_seqnum, - udp_seq_num); + LOG_ERR("Incorrect UDP sequence num. Expected: %" PRIu32 " Recd.: %" PRIu32 "\n", + *exp_udp_seqnum, udp_seq_num); *exp_udp_seqnum = udp_seq_num; } } else { @@ -265,10 +272,18 @@ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uin // Only NTSCF and TSCF formats allowed uint8_t subtype = Avtp_CommonHeader_GetSubtype((Avtp_CommonHeader_t *)cf_pdu); if (subtype == AVTP_SUBTYPE_TSCF) { - proc_bytes += AVTP_TSCF_HEADER_LEN; - msg_length += Avtp_Tscf_GetStreamDataLength((Avtp_Tscf_t *)cf_pdu) + AVTP_TSCF_HEADER_LEN; + uint8_t version = + Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)cf_pdu); + if (!Avtp_Version_IsSupported(AVTP_TSCF_SUPPORTED_VERSIONS, version)) { + LOG_ERR("Unsupported TSCF version %u, ignoring frame.\n", version); + return -1; + } + size_t headerLen = + Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)cf_pdu); + proc_bytes += (uint16_t)headerLen; + msg_length += (uint16_t)(Avtp_Tscf_GetStreamDataLength((Avtp_Tscf_t *)cf_pdu) + headerLen); s_id = Avtp_Tscf_GetStreamId((Avtp_Tscf_t *)cf_pdu); - seq_num = (uint8_t)Avtp_Tscf_GetSequenceNum((Avtp_Tscf_t *)cf_pdu); + seq_num = Avtp_Tscf_GetSequenceNum((Avtp_Tscf_t *)cf_pdu); } else if (subtype == AVTP_SUBTYPE_NTSCF) { proc_bytes += AVTP_NTSCF_HEADER_LEN; msg_length += Avtp_Ntscf_GetNtscfDataLength((Avtp_Ntscf_t *)cf_pdu) + AVTP_NTSCF_HEADER_LEN; @@ -285,7 +300,8 @@ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uin // Check sequence numbers. if (seq_num != *exp_cf_seqnum) { - LOG_ERR("Incorrect sequence num. Expected: %d Recd.: %d\n", *exp_cf_seqnum, seq_num); + LOG_ERR("Incorrect sequence num. Expected: %" PRIu32 " Recd.: %" PRIu32 "\n", + *exp_cf_seqnum, seq_num); *exp_cf_seqnum = seq_num; } diff --git a/examples/acf-can/acf-can-common.h b/examples/acf-can/acf-can-common.h index c216b03a..7c78a6a4 100644 --- a/examples/acf-can/acf-can-common.h +++ b/examples/acf-can/acf-can-common.h @@ -86,6 +86,15 @@ typedef union { canfd_frame_t fd; } frame_t; +/** + * Control format used to encapsulate ACF CAN messages. + */ +typedef enum { + ACF_CAN_CF_NTSCF = 0, /* NTSCF version 0 */ + ACF_CAN_CF_TSCF_V0, /* TSCF version 0 */ + ACF_CAN_CF_TSCF_V1, /* TSCF version 1 */ +} acf_can_cf_t; + #ifdef __linux__ /** * Creates a CAN socket. @@ -110,7 +119,7 @@ int setup_can_socket(const char *can_ifname, bool can_fd); * @return Number of CAN messages received */ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uint64_t stream_id, - uint8_t *exp_cf_seqnum, uint32_t *exp_udp_seqnum); + uint32_t *exp_cf_seqnum, uint32_t *exp_udp_seqnum); /** * Function that converts AVTP Frames to CAN @@ -119,12 +128,13 @@ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uin * @param can_fd true: CAN-FD, false: Classic CAN * @param pdu: Start of AVTP Frame * @param use_udp 1: UDP encapsulation, 0: Ethernet - * @param use_tscf 1: TSCF, 0: NTSCF + * @param cf: Control format and header version used to encapsulate the CAN frames * @param stream_id: AVTP stream ID of interest * @param num_acf_msgs: No. of ACF CAN messages to aggregate * @param cf_seq_num: Control format sequence num. * @param udp_seq_num: UDP Encapsulation sequence num. * @return Length of the PDU */ -int can_to_avtp(frame_t *can_frames, bool can_fd, uint8_t *pdu, int use_udp, int use_tscf, - uint64_t stream_id, uint8_t num_acf_msgs, uint8_t cf_seq_num, uint32_t udp_seq_num); +int can_to_avtp(frame_t *can_frames, bool can_fd, uint8_t *pdu, int use_udp, acf_can_cf_t cf, + uint64_t stream_id, uint8_t num_acf_msgs, uint32_t cf_seq_num, + uint32_t udp_seq_num); diff --git a/examples/acf-can/linux/README.md b/examples/acf-can/linux/README.md index 45624f1c..5a2333e0 100644 --- a/examples/acf-can/linux/README.md +++ b/examples/acf-can/linux/README.md @@ -14,6 +14,8 @@ All these applications support IEEE 1722 over Ethernet (layer 2) as well as over The chosen format has to match between the talker and listener applications. The build system builds the applications using all available formats for the listener, talker and bridge applications. User can extend the build system to build the applications using other formats as well. +In addition to the ACF CAN message format, the TSCF transport can use version 0 (24-octet header, 8-bit sequence number) or version 1 (40-octet header, 32-bit sequence number, PTP grandmaster identity) of the AVTPDU common stream header. Select the version at runtime with `-t1`/`--tscf=1` on the talker or bridge; listeners detect the version from the received frame. + The built applications can be used along with Linux CAN utilities. On Ubuntu/Debian Linux distributions, these utilities can be installed using the package manager `apt install can-utils` ## acf-can-talker @@ -33,7 +35,8 @@ Ethernet using Open1722. -n, --dst-nw-addr=NW_ADDR Stream destination network address and port (If UDP) --stream-id=STREAM_ID Stream ID for talker stream - -t, --tscf Use TSCF v0 (Default: NTSCF v0) + -t, --tscf[=VERSION] Use TSCF; VERSION 0 or 1 selects the header + version (Default: NTSCF v0) -u, --udp Use UDP (Default: Ethernet) -?, --help Give this help list --usage Give a short usage message @@ -78,7 +81,8 @@ acf-can-bridge -- a program for bridging a CAN interface with an Ethernet interf -p, --udp-port=UDP_PORT UDP Port to listen on (if UDP) --talker-stream-id=STREAM_ID Stream ID for talker stream - -t, --tscf Use TSCF v0 (Default: NTSCF v0) + -t, --tscf[=VERSION] Use TSCF; VERSION 0 or 1 selects the header + version (Default: NTSCF v0) -u, --udp Use UDP -?, --help Give this help list --usage Give a short usage message diff --git a/examples/acf-can/linux/acf-can-bridge.c b/examples/acf-can/linux/acf-can-bridge.c index 6484e5f3..fd621497 100644 --- a/examples/acf-can/linux/acf-can-bridge.c +++ b/examples/acf-can/linux/acf-can-bridge.c @@ -56,7 +56,7 @@ static char ifname[IFNAMSIZ]; static uint8_t macaddr[ETH_ALEN]; static uint8_t ip_addr[sizeof(struct in_addr)]; static int priority = -1; -static uint8_t use_tscf = 0; +static acf_can_cf_t cf_format = ACF_CAN_CF_NTSCF; static uint8_t use_udp = 0; static uint32_t udp_listen_port = 17220; static uint32_t udp_send_port = 17220; @@ -79,7 +79,8 @@ static char doc[] = \t(Bridge eth0 with can1 using Open1722 over UDP)"; static struct argp_option options[] = { - {"tscf", 't', 0, 0, "Use TSCF v0 (Default: NTSCF v0)"}, + {"tscf", 't', "VERSION", OPTION_ARG_OPTIONAL, + "Use TSCF; VERSION 0 or 1 selects the header version (Default: NTSCF v0)"}, {"udp", 'u', 0, 0, "Use UDP"}, {"fd", ARGPARSE_CAN_FD_OPTION, 0, 0, "Use CAN-FD"}, {"count", 'c', "COUNT", 0, "Set count of CAN messages per Ethernet frame"}, @@ -99,7 +100,15 @@ static error_t parser(int key, char *arg, struct argp_state *state) switch (key) { case 't': - use_tscf = 1; + cf_format = ACF_CAN_CF_TSCF_V0; + if (arg != NULL) { + if (strcmp(arg, "1") == 0) { + cf_format = ACF_CAN_CF_TSCF_V1; + } else if (strcmp(arg, "0") != 0) { + fprintf(stderr, "Invalid TSCF version '%s' (only 0 and 1 are supported)\n", arg); + exit(EXIT_FAILURE); + } + } break; case 'p': udp_listen_port = atoi(arg); @@ -167,7 +176,7 @@ static struct argp argp = {options, parser, NULL, doc}; void *can_to_avtp_runnable(void *args) { - uint8_t cf_seq_num = 0; + uint32_t cf_seq_num = 0; uint32_t udp_seq_num = 0; uint8_t pdu[MAX_ETH_PDU_SIZE]; @@ -196,7 +205,7 @@ void *can_to_avtp_runnable(void *args) } // Pack all the read frames into an AVTP frame - pdu_length = can_to_avtp(can_frames, can_fd, pdu, use_udp, use_tscf, talker_stream_id, + pdu_length = can_to_avtp(can_frames, can_fd, pdu, use_udp, cf_format, talker_stream_id, num_acf_msgs, cf_seq_num++, udp_seq_num++); // Send the packed frame out @@ -220,7 +229,7 @@ void *avtp_to_can_runnable(void *args) uint16_t pdu_length = 0, cf_length = 0; int8_t num_can_msgs = 0; - uint8_t exp_cf_seqnum = 0; + uint32_t exp_cf_seqnum = 0; uint32_t exp_udp_seqnum = 0; uint8_t pdu[MAX_ETH_PDU_SIZE]; frame_t can_frames[MAX_CAN_FRAMES_IN_ACF]; @@ -269,10 +278,17 @@ int main(int argc, char *argv[]) // Print current configuration printf("acf-can-bridge configuration:\n"); - if (use_tscf) + switch (cf_format) { + case ACF_CAN_CF_TSCF_V0: printf("\tUsing TSCF v0\n"); - else + break; + case ACF_CAN_CF_TSCF_V1: + printf("\tUsing TSCF v1\n"); + break; + default: printf("\tUsing NTSCF v0\n"); + break; + } if (can_fd) printf("\tUsing CAN FD interface: %s\n", can_ifname); else diff --git a/examples/acf-can/linux/acf-can-listener.c b/examples/acf-can/linux/acf-can-listener.c index 2286bd74..cab590ab 100644 --- a/examples/acf-can/linux/acf-can-listener.c +++ b/examples/acf-can/linux/acf-can-listener.c @@ -123,7 +123,7 @@ int main(int argc, char *argv[]) struct ifreq ifr; uint16_t pdu_length = 0, cf_length = 0; int8_t num_can_msgs = 0; - uint8_t exp_cf_seqnum = 0; + uint32_t exp_cf_seqnum = 0; uint32_t exp_udp_seqnum = 0; uint8_t pdu[MAX_ETH_PDU_SIZE]; frame_t can_frames[MAX_CAN_FRAMES_IN_ACF]; diff --git a/examples/acf-can/linux/acf-can-talker.c b/examples/acf-can/linux/acf-can-talker.c index cb5c052d..cf4afbe8 100644 --- a/examples/acf-can/linux/acf-can-talker.c +++ b/examples/acf-can/linux/acf-can-talker.c @@ -53,7 +53,7 @@ static uint8_t macaddr[ETH_ALEN]; static uint8_t ip_addr[sizeof(struct in_addr)]; static uint32_t udp_port = 17220; static int priority = -1; -static uint8_t use_tscf = 0; +static acf_can_cf_t cf_format = ACF_CAN_CF_NTSCF; static uint8_t use_udp = 0; static bool can_fd = false; static uint8_t num_acf_msgs = 1; @@ -70,7 +70,8 @@ static char doc[] = \t(tunnel transactions from vcan1 interface using UDP)"; static struct argp_option options[] = { - {"tscf", 't', 0, 0, "Use TSCF v0 (Default: NTSCF v0)"}, + {"tscf", 't', "VERSION", OPTION_ARG_OPTIONAL, + "Use TSCF; VERSION 0 or 1 selects the header version (Default: NTSCF v0)"}, {"udp", 'u', 0, 0, "Use UDP (Default: Ethernet)"}, {"fd", ARGPARSE_CAN_FD_OPTION, 0, 0, "Use CAN-FD"}, {"count", 'c', "COUNT", 0, "Set count of CAN messages per Ethernet frame"}, @@ -87,7 +88,15 @@ static error_t parser(int key, char *arg, struct argp_state *state) switch (key) { case 't': - use_tscf = 1; + cf_format = ACF_CAN_CF_TSCF_V0; + if (arg != NULL) { + if (strcmp(arg, "1") == 0) { + cf_format = ACF_CAN_CF_TSCF_V1; + } else if (strcmp(arg, "0") != 0) { + fprintf(stderr, "Invalid TSCF version '%s' (only 0 and 1 are supported)\n", arg); + exit(EXIT_FAILURE); + } + } break; case 'u': use_udp = 1; @@ -148,7 +157,7 @@ int main(int argc, char *argv[]) struct sockaddr_ll sk_ll_addr; struct sockaddr_in sk_udp_addr; struct sockaddr *dest_addr; - uint8_t cf_seq_num = 0; + uint32_t cf_seq_num = 0; uint32_t udp_seq_num = 0; uint8_t pdu[MAX_ETH_PDU_SIZE]; @@ -157,10 +166,17 @@ int main(int argc, char *argv[]) argp_parse(&argp, argc, argv, 0, NULL, NULL); printf("acf-talker-configuration:\n"); - if (use_tscf) + switch (cf_format) { + case ACF_CAN_CF_TSCF_V0: printf("\tUsing TSCF v0\n"); - else + break; + case ACF_CAN_CF_TSCF_V1: + printf("\tUsing TSCF v1\n"); + break; + default: printf("\tUsing NTSCF v0\n"); + break; + } if (can_fd) printf("\tUsing CAN FD interface: %s\n", can_ifname); else @@ -222,7 +238,7 @@ int main(int argc, char *argv[]) } // Pack all the read frames into an AVTP frame - pdu_length = can_to_avtp(can_frames, can_fd, pdu, use_udp, use_tscf, talker_stream_id, + pdu_length = can_to_avtp(can_frames, can_fd, pdu, use_udp, cf_format, talker_stream_id, num_acf_msgs, cf_seq_num++, udp_seq_num++); // Send the packed frame out diff --git a/examples/acf-can/zephyr/Kconfig b/examples/acf-can/zephyr/Kconfig index 27b3a869..0a35c85e 100644 --- a/examples/acf-can/zephyr/Kconfig +++ b/examples/acf-can/zephyr/Kconfig @@ -8,6 +8,10 @@ config ACF_CAN_BRIDGE_USE_TSCF int "Use TSCF encapsulation" default 0 +config ACF_CAN_BRIDGE_TSCF_VERSION + int "TSCF header version (0 or 1)" + default 0 + config ACF_CAN_BRIDGE_SEND_MAC_ADDR string "MAC Address to which ACF CAN frames are sent" default "aa:bb:cc:dd:ee:ff" diff --git a/examples/acf-can/zephyr/acf-can-bridge.c b/examples/acf-can/zephyr/acf-can-bridge.c index 16a8f5aa..e38c80f9 100644 --- a/examples/acf-can/zephyr/acf-can-bridge.c +++ b/examples/acf-can/zephyr/acf-can-bridge.c @@ -62,7 +62,12 @@ LOG_MODULE_REGISTER(acf_can_bridge, LOG_LEVEL_DBG); static uint8_t macaddr[NET_ETH_ADDR_LEN]; static struct in_addr ip_addr; -static uint8_t use_tscf = CONFIG_ACF_CAN_BRIDGE_USE_TSCF; +#if CONFIG_ACF_CAN_BRIDGE_USE_TSCF +static acf_can_cf_t cf_format = + CONFIG_ACF_CAN_BRIDGE_TSCF_VERSION == 1 ? ACF_CAN_CF_TSCF_V1 : ACF_CAN_CF_TSCF_V0; +#else +static acf_can_cf_t cf_format = ACF_CAN_CF_NTSCF; +#endif static uint8_t use_udp = CONFIG_ACF_CAN_BRIDGE_USE_UDP; static uint32_t udp_listen_port = CONFIG_ACF_CAN_BRIDGE_RECV_UDP_PORT; static uint32_t udp_send_port = CONFIG_ACF_CAN_BRIDGE_SEND_UDP_PORT; @@ -203,7 +208,7 @@ static int create_listener_socket(uint8_t *macaddr, int protocol) void can_to_avtp_runnable(void *p1, void *p2, void *p3) { - uint8_t cf_seq_num = 0; + uint32_t cf_seq_num = 0; uint32_t udp_seq_num = 0; uint8_t pdu[MAX_ETH_PDU_SIZE]; @@ -254,7 +259,7 @@ void can_to_avtp_runnable(void *p1, void *p2, void *p3) } // Pack all the read frames into an AVTP frame - pdu_length = can_to_avtp(can_frames, can_fd, pdu, use_udp, use_tscf, talker_stream_id, + pdu_length = can_to_avtp(can_frames, can_fd, pdu, use_udp, cf_format, talker_stream_id, num_acf_msgs, cf_seq_num++, udp_seq_num++); // Send the packed frame out over Ethernet @@ -278,7 +283,7 @@ void avtp_to_can_runnable(void *p1, void *p2, void *p3) uint16_t pdu_length = 0; int8_t num_can_msgs = 0; - uint8_t exp_cf_seqnum = 0; + uint32_t exp_cf_seqnum = 0; uint32_t exp_udp_seqnum = 0; uint8_t pdu[MAX_ETH_PDU_SIZE]; static frame_t can_frames[MAX_CAN_FRAMES_IN_ACF]; @@ -353,10 +358,17 @@ int main(void) // Print current configuration printf("acf-can-bridge configuration:\n"); - if (use_tscf) + switch (cf_format) { + case ACF_CAN_CF_TSCF_V0: printf("\tUsing TSCF v0\n"); - else + break; + case ACF_CAN_CF_TSCF_V1: + printf("\tUsing TSCF v1\n"); + break; + default: printf("\tUsing NTSCF v0\n"); + break; + } if (can_fd) printf("\tUsing CAN FD\n"); else From 199830dfd862f91b2672e54172f7a33250e6aa85 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Sat, 19 Sep 2026 12:19:12 +0200 Subject: [PATCH 05/16] Remove offset and duplicate csh field destriptors in tscf for better readability Signed-off-by: Sebastian Schildt --- docs/api-design.md | 40 ++++--- include/avtp/CommonStreamHeader.h | 18 +-- include/avtp/acf/Tscf.h | 178 +++++++++++++++++++----------- unit/test-commonstreamheader.c | 2 - unit/test-tscf.c | 47 +++++--- 5 files changed, 170 insertions(+), 115 deletions(-) diff --git a/docs/api-design.md b/docs/api-design.md index a2b3e188..13d7a020 100644 --- a/docs/api-design.md +++ b/docs/api-design.md @@ -17,8 +17,9 @@ table covering the format's own bits, `Init`, `IsValid` and payload helpers. They differ only in the header they describe: the common stream header, except for CRF/NTSCF, which use the alternative header. Both header styles are versioned (0 and 1); the common stream header fields are described once in -[`CommonStreamHeader.h`](../include/avtp/CommonStreamHeader.h) and formats add -only their own fields in version 0 coordinates (TSCF is the reference). The CVF +[`CommonStreamHeader.h`](../include/avtp/CommonStreamHeader.h), and each format +declares a complete descriptor table per version in absolute coordinates, +reusing those positions for the common fields (TSCF is the reference). The CVF format-specific headers (MJPEG, H.264, JPEG 2000) and the RVF raw header are fragments of the stream data rather than standalone PDUs: they are validated through the enclosing PDU (`Avtp_Cvf_IsValid`/`Avtp_Rvf_IsValid`, plus a @@ -605,31 +606,36 @@ header once for both versions: in both versions; fields absent from a version return 0 and their setters are no-ops. -A migrated format (TSCF is the reference) declares only its own fields, in -version 0 coordinates, and adds the format offset in its GET/SET macros: +A migrated format (TSCF is the reference) declares a **complete descriptor +table per version**, in absolute coordinates. The common entries reuse the +positions from `Avtp_CshFieldDescV0/V1`; the format's own fields override the +format-specific data slots. The accessors select the table for the version in +use - there is no offset arithmetic: ```c -#define GET_TSCF_FIELD(field) \ - (Avtp_GetField(Avtp_TscfFieldDesc, AVTP_TSCF_FIELD_MAX, \ - (const uint8_t *)pdu + \ - Avtp_CommonStreamHeader_GetFormatOffset( \ - (const Avtp_CommonStreamHeader_t *)pdu), \ - field)) +static const Avtp_FieldDescriptor_t Avtp_TscfFieldDescV1[AVTP_TSCF_FIELD_MAX] = { + [AVTP_TSCF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, + ... /* same positions as Avtp_CshFieldDescV1 */ + [AVTP_TSCF_FIELD_RESERVED2] = {.quadlet = 8, .offset = 0, .bits = 32}, + [AVTP_TSCF_FIELD_RESERVED3] = {.quadlet = 9, .offset = 16, .bits = 16}, +}; ``` -`GetFormatOffset` is 0 for version 0 and 16 for version 1: version 1 inserts 16 -octets before the format-specific data area, so every format field shifts by -that amount. A new header version therefore means one new table in the style -module, not one new table per format. `GetHeaderLen` is used by the payload -helpers so `Avtp__Get/SetPayload` work for both versions. +This is the "subclass" model: the common stream header defines the slots and +the format table declares its interpretation of them. Because the common +entries are copied into every format table, a per-format consistency test +asserts that they equal the style module's entries for the same version. +`GetHeaderLen` is used by the payload helpers so `Avtp__Get/SetPayload` +work for both versions. The version 1 PDU struct (for example `Avtp_TscfV1_t`) is sized for the larger header and is used for allocation and embedding. Accessors keep taking the version 0 struct pointer; version 1 callers cast once. The "every bit described exactly once" rule becomes a cross-module test: for -each version, the common header, the common stream header and the format's own -table (shifted by the format offset) must cover the whole header exactly once. +each version, the common header fields (`subtype`, `version`; `h` is covered by +the format's `SV`) plus the format's complete table must cover the whole header +exactly once. ## ACF layering & the common header diff --git a/include/avtp/CommonStreamHeader.h b/include/avtp/CommonStreamHeader.h index 82c12e63..8afd0954 100644 --- a/include/avtp/CommonStreamHeader.h +++ b/include/avtp/CommonStreamHeader.h @@ -33,6 +33,10 @@ * stream header (4.7.4) for versions 0 and 1 and functions to invoke the * corresponding parser and deparser. The format-specific data slots 2 and 3 * are not covered here; their contents are defined by the individual formats. + * + * Format modules declare complete descriptor tables per version in absolute + * coordinates, reusing these positions for the common fields. A consistency + * test keeps the common entries of each format aligned with the tables here. */ #pragma once @@ -146,20 +150,6 @@ Avtp_CommonStreamHeader_GetHeaderLen(const Avtp_CommonStreamHeader_t *const pdu) : (uint8_t)AVTPDU_CSH_LEN_V0; } -/** - * Returns the byte offset of the format-specific data area relative to the - * version 0 layout: 0 for version 0 and 16 for version 1. Format field - * descriptor tables are written in version 0 coordinates and add this offset - * to the PDU pointer. - */ -OPEN1722_INLINE uint8_t -Avtp_CommonStreamHeader_GetFormatOffset(const Avtp_CommonStreamHeader_t *const pdu) -{ - return Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1 - ? (uint8_t)(AVTPDU_CSH_LEN_V1 - AVTPDU_CSH_LEN_V0) - : 0; -} - /** * Returns the value of an AVTPDU common stream header field. * diff --git a/include/avtp/acf/Tscf.h b/include/avtp/acf/Tscf.h index 8c91c58e..ad2c641a 100644 --- a/include/avtp/acf/Tscf.h +++ b/include/avtp/acf/Tscf.h @@ -32,10 +32,12 @@ * This file contains the fields descriptions of the IEEE 1722 TSCF PDUs and * functions to invoke corresponding parser and deparser. * - * TSCF uses the AVTPDU common stream header (4.7.4), so all common fields are - * accessed through Avtp_CommonStreamHeader_*. The fields in this module are - * described in version 0 coordinates; the GET/SET macros add the common stream - * header's format offset to reach the version 1 positions. + * TSCF uses the AVTPDU common stream header (4.7.4) and declares a complete + * descriptor table per version in absolute coordinates: the common fields + * reuse the positions from CommonStreamHeader.h and the format-specific data + * slots (format_specific_data_2 and _3) are overridden as reserved. A + * consistency test keeps the common entries aligned with the common stream + * header module. */ #pragma once @@ -65,17 +67,6 @@ extern "C" { /* TSCF supports both versions of the common stream header (Table 7). */ #define AVTP_TSCF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) -#define GET_TSCF_FIELD(field) \ - (Avtp_GetField(Avtp_TscfFieldDesc, AVTP_TSCF_FIELD_MAX, \ - (const uint8_t *)pdu + Avtp_CommonStreamHeader_GetFormatOffset( \ - (const Avtp_CommonStreamHeader_t *)pdu), \ - field)) -#define SET_TSCF_FIELD(field, value) \ - (Avtp_SetField(Avtp_TscfFieldDesc, AVTP_TSCF_FIELD_MAX, \ - (uint8_t *)pdu + Avtp_CommonStreamHeader_GetFormatOffset( \ - (const Avtp_CommonStreamHeader_t *)pdu), \ - field, value)) - typedef struct { uint8_t header[AVTP_TSCF_HEADER_LEN_V0]; uint8_t payload[0]; @@ -88,6 +79,20 @@ typedef struct { typedef enum { + /* Common AVTP stream header fields */ + AVTP_TSCF_FIELD_SV = 0, + AVTP_TSCF_FIELD_MR, + AVTP_TSCF_FIELD_FSD, + AVTP_TSCF_FIELD_TV, + AVTP_TSCF_FIELD_SEQUENCE_NUM, + AVTP_TSCF_FIELD_FSD0, + AVTP_TSCF_FIELD_FSD1, + AVTP_TSCF_FIELD_TU, + AVTP_TSCF_FIELD_STREAM_ID, + AVTP_TSCF_FIELD_AVTP_TIMESTAMP, + AVTP_TSCF_FIELD_PTP_GRANDMASTER_IDENTITY, + AVTP_TSCF_FIELD_STREAM_DATA_LENGTH, + /* TSCF-specific fields (format_specific_data_2 and _3) */ AVTP_TSCF_FIELD_RESERVED2, AVTP_TSCF_FIELD_RESERVED3, @@ -97,15 +102,81 @@ typedef enum { } Avtp_TscfFields_t; /** - * This table maps all TSCF-specific header fields to a descriptor. It is - * written in version 0 coordinates; the accessors add the common stream - * header's format offset for version 1. + * This table maps all IEEE 1722 TSCF header fields to a descriptor for version + * 0. It is complete and in absolute coordinates; the common stream header + * fields use the same positions as Avtp_CshFieldDescV0. */ -static const Avtp_FieldDescriptor_t Avtp_TscfFieldDesc[AVTP_TSCF_FIELD_MAX] = { +static const Avtp_FieldDescriptor_t Avtp_TscfFieldDescV0[AVTP_TSCF_FIELD_MAX] = { + [AVTP_TSCF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, + [AVTP_TSCF_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, + [AVTP_TSCF_FIELD_FSD] = {.quadlet = 0, .offset = 13, .bits = 2}, + [AVTP_TSCF_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, + [AVTP_TSCF_FIELD_SEQUENCE_NUM] = {.quadlet = 0, .offset = 16, .bits = 8}, + [AVTP_TSCF_FIELD_FSD0] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_TSCF_FIELD_FSD1] = {.quadlet = 0, .offset = 24, .bits = 7}, + [AVTP_TSCF_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, + [AVTP_TSCF_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, + [AVTP_TSCF_FIELD_AVTP_TIMESTAMP] = {.quadlet = 3, .offset = 0, .bits = 32}, + [AVTP_TSCF_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_TSCF_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 5, .offset = 0, .bits = 16}, [AVTP_TSCF_FIELD_RESERVED2] = {.quadlet = 4, .offset = 0, .bits = 32}, [AVTP_TSCF_FIELD_RESERVED3] = {.quadlet = 5, .offset = 16, .bits = 16}, }; +/** + * This table maps all IEEE 1722 TSCF header fields to a descriptor for version + * 1. It is complete and in absolute coordinates; the common stream header + * fields use the same positions as Avtp_CshFieldDescV1. + */ +static const Avtp_FieldDescriptor_t Avtp_TscfFieldDescV1[AVTP_TSCF_FIELD_MAX] = { + [AVTP_TSCF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, + [AVTP_TSCF_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, + [AVTP_TSCF_FIELD_FSD] = {.quadlet = 0, .offset = 13, .bits = 2}, + [AVTP_TSCF_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, + [AVTP_TSCF_FIELD_SEQUENCE_NUM] = {.quadlet = 3, .offset = 0, .bits = 32}, + [AVTP_TSCF_FIELD_FSD0] = {.quadlet = 0, .offset = 16, .bits = 8}, + [AVTP_TSCF_FIELD_FSD1] = {.quadlet = 0, .offset = 24, .bits = 7}, + [AVTP_TSCF_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, + [AVTP_TSCF_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, + [AVTP_TSCF_FIELD_AVTP_TIMESTAMP] = {.quadlet = 4, .offset = 0, .bits = 64}, + [AVTP_TSCF_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 6, .offset = 0, .bits = 64}, + [AVTP_TSCF_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 9, .offset = 0, .bits = 16}, + [AVTP_TSCF_FIELD_RESERVED2] = {.quadlet = 8, .offset = 0, .bits = 32}, + [AVTP_TSCF_FIELD_RESERVED3] = {.quadlet = 9, .offset = 16, .bits = 16}, +}; + +/** + * Returns the value of an AVTP TSCF field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 AVTP TSCF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + */ +OPEN1722_INLINE uint64_t Avtp_Tscf_GetField(const Avtp_Tscf_t *const pdu, Avtp_TscfFields_t field) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_TscfFieldDescV1 + : Avtp_TscfFieldDescV0; + return Avtp_GetField(desc, AVTP_TSCF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); +} + +/** + * Sets the value of an AVTP TSCF field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 AVTP TSCF PDU. + * @param field Specifies the position of the data field to be read + * @param value The value to set. + */ +OPEN1722_INLINE void Avtp_Tscf_SetField(Avtp_Tscf_t *pdu, Avtp_TscfFields_t field, uint64_t value) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_TscfFieldDescV1 + : Avtp_TscfFieldDescV0; + Avtp_SetField(desc, AVTP_TSCF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + /** * Return the value of the TSCF SV field as specified in the IEEE 1722 Specification. * @@ -114,7 +185,7 @@ static const Avtp_FieldDescriptor_t Avtp_TscfFieldDesc[AVTP_TSCF_FIELD_MAX] = { */ OPEN1722_INLINE bool Avtp_Tscf_IsSv(const Avtp_Tscf_t *const pdu) { - return Avtp_CommonStreamHeader_IsSv((const Avtp_CommonStreamHeader_t *)pdu); + return (bool)Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_SV); } /** @@ -125,7 +196,7 @@ OPEN1722_INLINE bool Avtp_Tscf_IsSv(const Avtp_Tscf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Tscf_IsMr(const Avtp_Tscf_t *const pdu) { - return Avtp_CommonStreamHeader_IsMr((const Avtp_CommonStreamHeader_t *)pdu); + return (bool)Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_MR); } /** @@ -136,7 +207,7 @@ OPEN1722_INLINE bool Avtp_Tscf_IsMr(const Avtp_Tscf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Tscf_IsTv(const Avtp_Tscf_t *const pdu) { - return Avtp_CommonStreamHeader_IsTv((const Avtp_CommonStreamHeader_t *)pdu); + return (bool)Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_TV); } /** @@ -147,7 +218,7 @@ OPEN1722_INLINE bool Avtp_Tscf_IsTv(const Avtp_Tscf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Tscf_IsTu(const Avtp_Tscf_t *const pdu) { - return Avtp_CommonStreamHeader_IsTu((const Avtp_CommonStreamHeader_t *)pdu); + return (bool)Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_TU); } /** @@ -159,7 +230,7 @@ OPEN1722_INLINE bool Avtp_Tscf_IsTu(const Avtp_Tscf_t *const pdu) */ OPEN1722_INLINE uint32_t Avtp_Tscf_GetSequenceNum(const Avtp_Tscf_t *const pdu) { - return Avtp_CommonStreamHeader_GetSequenceNum((const Avtp_CommonStreamHeader_t *)pdu); + return (uint32_t)Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM); } /** @@ -175,10 +246,9 @@ OPEN1722_INLINE uint8_t Avtp_Tscf_GetSequenceNumLsb(const Avtp_Tscf_t *const pdu { if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1) { - return Avtp_CommonStreamHeader_GetFormatSpecificData0( - (const Avtp_CommonStreamHeader_t *)pdu); + return (uint8_t)Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_FSD0); } - return (uint8_t)Avtp_CommonStreamHeader_GetSequenceNum((const Avtp_CommonStreamHeader_t *)pdu); + return (uint8_t)Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM); } /** @@ -189,7 +259,7 @@ OPEN1722_INLINE uint8_t Avtp_Tscf_GetSequenceNumLsb(const Avtp_Tscf_t *const pdu */ OPEN1722_INLINE uint64_t Avtp_Tscf_GetStreamId(const Avtp_Tscf_t *const pdu) { - return Avtp_CommonStreamHeader_GetStreamId((const Avtp_CommonStreamHeader_t *)pdu); + return Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_STREAM_ID); } /** @@ -201,7 +271,7 @@ OPEN1722_INLINE uint64_t Avtp_Tscf_GetStreamId(const Avtp_Tscf_t *const pdu) */ OPEN1722_INLINE uint64_t Avtp_Tscf_GetAvtpTimestamp(const Avtp_Tscf_t *const pdu) { - return Avtp_CommonStreamHeader_GetAvtpTimestamp((const Avtp_CommonStreamHeader_t *)pdu); + return Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_AVTP_TIMESTAMP); } /** @@ -213,8 +283,7 @@ OPEN1722_INLINE uint64_t Avtp_Tscf_GetAvtpTimestamp(const Avtp_Tscf_t *const pdu */ OPEN1722_INLINE uint64_t Avtp_Tscf_GetPtpGrandmasterIdentity(const Avtp_Tscf_t *const pdu) { - return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity( - (const Avtp_CommonStreamHeader_t *)pdu); + return Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_PTP_GRANDMASTER_IDENTITY); } /** @@ -226,7 +295,7 @@ OPEN1722_INLINE uint64_t Avtp_Tscf_GetPtpGrandmasterIdentity(const Avtp_Tscf_t * */ OPEN1722_INLINE uint16_t Avtp_Tscf_GetStreamDataLength(const Avtp_Tscf_t *const pdu) { - return Avtp_CommonStreamHeader_GetStreamDataLength((const Avtp_CommonStreamHeader_t *)pdu); + return (uint16_t)Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_STREAM_DATA_LENGTH); } /** @@ -237,7 +306,7 @@ OPEN1722_INLINE uint16_t Avtp_Tscf_GetStreamDataLength(const Avtp_Tscf_t *const */ OPEN1722_INLINE void Avtp_Tscf_SetSv(Avtp_Tscf_t *pdu, bool sv) { - Avtp_CommonStreamHeader_SetSv((Avtp_CommonStreamHeader_t *)pdu, sv); + Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_SV, sv); } /** @@ -248,7 +317,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetSv(Avtp_Tscf_t *pdu, bool sv) */ OPEN1722_INLINE void Avtp_Tscf_SetMr(Avtp_Tscf_t *pdu, bool mr) { - Avtp_CommonStreamHeader_SetMr((Avtp_CommonStreamHeader_t *)pdu, mr); + Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_MR, mr); } /** @@ -259,7 +328,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetMr(Avtp_Tscf_t *pdu, bool mr) */ OPEN1722_INLINE void Avtp_Tscf_SetTv(Avtp_Tscf_t *pdu, bool tv) { - Avtp_CommonStreamHeader_SetTv((Avtp_CommonStreamHeader_t *)pdu, tv); + Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_TV, tv); } /** @@ -270,7 +339,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetTv(Avtp_Tscf_t *pdu, bool tv) */ OPEN1722_INLINE void Avtp_Tscf_SetTu(Avtp_Tscf_t *pdu, bool tu) { - Avtp_CommonStreamHeader_SetTu((Avtp_CommonStreamHeader_t *)pdu, tu); + Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_TU, tu); } /** @@ -283,11 +352,10 @@ OPEN1722_INLINE void Avtp_Tscf_SetTu(Avtp_Tscf_t *pdu, bool tu) */ OPEN1722_INLINE void Avtp_Tscf_SetSequenceNum(Avtp_Tscf_t *pdu, uint32_t value) { - Avtp_CommonStreamHeader_SetSequenceNum((Avtp_CommonStreamHeader_t *)pdu, value); + Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM, value); if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1) { - Avtp_CommonStreamHeader_SetFormatSpecificData0((Avtp_CommonStreamHeader_t *)pdu, - (uint8_t)(value & 0xFFU)); + Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_FSD0, (uint8_t)(value & 0xFFU)); } } @@ -299,7 +367,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetSequenceNum(Avtp_Tscf_t *pdu, uint32_t value) */ OPEN1722_INLINE void Avtp_Tscf_SetStreamId(Avtp_Tscf_t *pdu, uint64_t value) { - Avtp_CommonStreamHeader_SetStreamId((Avtp_CommonStreamHeader_t *)pdu, value); + Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_STREAM_ID, value); } /** @@ -310,7 +378,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetStreamId(Avtp_Tscf_t *pdu, uint64_t value) */ OPEN1722_INLINE void Avtp_Tscf_SetAvtpTimestamp(Avtp_Tscf_t *pdu, uint64_t value) { - Avtp_CommonStreamHeader_SetAvtpTimestamp((Avtp_CommonStreamHeader_t *)pdu, value); + Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_AVTP_TIMESTAMP, value); } /** @@ -322,7 +390,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetAvtpTimestamp(Avtp_Tscf_t *pdu, uint64_t value */ OPEN1722_INLINE void Avtp_Tscf_SetPtpGrandmasterIdentity(Avtp_Tscf_t *pdu, uint64_t value) { - Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity((Avtp_CommonStreamHeader_t *)pdu, value); + Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_PTP_GRANDMASTER_IDENTITY, value); } /** @@ -334,7 +402,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetPtpGrandmasterIdentity(Avtp_Tscf_t *pdu, uint6 */ OPEN1722_INLINE void Avtp_Tscf_SetStreamDataLength(Avtp_Tscf_t *pdu, uint16_t value) { - Avtp_CommonStreamHeader_SetStreamDataLength((Avtp_CommonStreamHeader_t *)pdu, value); + Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_STREAM_DATA_LENGTH, value); } /** @@ -435,30 +503,6 @@ OPEN1722_INLINE void Avtp_Tscf_InitV1(Avtp_TscfV1_t *pdu) } } -/** - * Returns the value of an AVTP TSCF field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 AVTP TSCF PDU. - * @param field Specifies the position of the data field to be read - * @returns This function returns the value of the field. - */ -OPEN1722_INLINE uint64_t Avtp_Tscf_GetField(const Avtp_Tscf_t *const pdu, Avtp_TscfFields_t field) -{ - return (uint64_t)GET_TSCF_FIELD(field); -} - -/** - * Sets the value of an AVTP TSCF field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 AVTP TSCF PDU. - * @param field Specifies the position of the data field to be read - * @param value The value to set. - */ -OPEN1722_INLINE void Avtp_Tscf_SetField(Avtp_Tscf_t *pdu, Avtp_TscfFields_t field, uint64_t value) -{ - SET_TSCF_FIELD(field, value); -} - #ifdef __cplusplus } #endif diff --git a/unit/test-commonstreamheader.c b/unit/test-commonstreamheader.c index 5ef3ad04..e9c5cc6f 100644 --- a/unit/test-commonstreamheader.c +++ b/unit/test-commonstreamheader.c @@ -70,7 +70,6 @@ static void common_stream_header_v0_layout(void **state) assert_int_equal(Avtp_CommonStreamHeader_GetVersion(csh), AVTP_VERSION_0); assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen(csh), AVTPDU_CSH_LEN_V0); - assert_int_equal(Avtp_CommonStreamHeader_GetFormatOffset(csh), 0); Avtp_CommonStreamHeader_SetSv(csh, true); Avtp_CommonStreamHeader_SetMr(csh, true); @@ -118,7 +117,6 @@ static void common_stream_header_v1_layout(void **state) assert_int_equal(Avtp_CommonStreamHeader_GetVersion(csh), AVTP_VERSION_1); assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen(csh), AVTPDU_CSH_LEN_V1); - assert_int_equal(Avtp_CommonStreamHeader_GetFormatOffset(csh), 16); Avtp_CommonStreamHeader_SetSv(csh, true); Avtp_CommonStreamHeader_SetMr(csh, true); diff --git a/unit/test-tscf.c b/unit/test-tscf.c index 7711fb8b..173bff6a 100644 --- a/unit/test-tscf.c +++ b/unit/test-tscf.c @@ -207,13 +207,12 @@ static void tscf_payload(void **state) } static void mark_descriptors(uint8_t *coverage, size_t coverageBits, - const Avtp_FieldDescriptor_t *desc, uint8_t numFields, - uint8_t quadletOffset) + const Avtp_FieldDescriptor_t *desc, uint8_t numFields) { for (uint8_t i = 0; i < numFields; i++) { uint8_t bits = desc[i].bits; uint8_t offset = desc[i].offset; - uint8_t quadlet = (uint8_t)(desc[i].quadlet + quadletOffset); + uint8_t quadlet = desc[i].quadlet; for (uint8_t b = 0; b < bits; b++) { size_t bit = ((size_t)quadlet * 32) + offset + b; @@ -232,24 +231,19 @@ static void tscf_header_coverage(void **state) for (uint8_t version = 0; version <= 1; version++) { uint8_t coverage[AVTP_TSCF_HEADER_LEN_V1 * 8] = {0}; size_t coverageBits = sizeof(coverage); - const Avtp_FieldDescriptor_t *cshDesc = - version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; - uint8_t formatOffsetQuadlets = version == AVTP_VERSION_1 ? 4 : 0; + const Avtp_FieldDescriptor_t *tscfDesc = + version == AVTP_VERSION_1 ? Avtp_TscfFieldDescV1 : Avtp_TscfFieldDescV0; size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_TSCF_HEADER_LEN_V1 : (size_t)AVTP_TSCF_HEADER_LEN_V0) * 8; - /* subtype and version are owned by the common header; h/sv is owned by - * the style header and covered below. */ + /* subtype and version are owned by the common header; h/sv is covered + * by the format table. */ mark_descriptors(coverage, coverageBits, - &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_SUBTYPE], 1, 0); + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_SUBTYPE], 1); mark_descriptors(coverage, coverageBits, - &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_VERSION], 1, 0); - /* Common stream header fields. */ - mark_descriptors(coverage, coverageBits, cshDesc, AVTPDU_CSH_FIELD_MAX, 0); - /* TSCF-specific fields, shifted to the version's format area. */ - mark_descriptors(coverage, coverageBits, Avtp_TscfFieldDesc, AVTP_TSCF_FIELD_MAX, - formatOffsetQuadlets); + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_VERSION], 1); + mark_descriptors(coverage, coverageBits, tscfDesc, AVTP_TSCF_FIELD_MAX); for (size_t bit = 0; bit < coverageBits; bit++) { assert_int_equal(coverage[bit], bit < headerBits ? 1 : 0); @@ -257,6 +251,28 @@ static void tscf_header_coverage(void **state) } } +static void tscf_common_field_consistency(void **state) +{ + (void)state; + + /* The common fields must be declared in the same order as in the common + * stream header module, so the tables can be compared index by index. */ + assert_int_equal(AVTP_TSCF_FIELD_STREAM_DATA_LENGTH, AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH); + + for (uint8_t version = 0; version <= 1; version++) { + const Avtp_FieldDescriptor_t *tscfDesc = + version == AVTP_VERSION_1 ? Avtp_TscfFieldDescV1 : Avtp_TscfFieldDescV0; + const Avtp_FieldDescriptor_t *cshDesc = + version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + + for (uint8_t i = 0; i < AVTPDU_CSH_FIELD_MAX; i++) { + assert_int_equal(tscfDesc[i].quadlet, cshDesc[i].quadlet); + assert_int_equal(tscfDesc[i].offset, cshDesc[i].offset); + assert_int_equal(tscfDesc[i].bits, cshDesc[i].bits); + } + } +} + int main(void) { const struct CMUnitTest tests[] = { @@ -267,6 +283,7 @@ int main(void) cmocka_unit_test(tscf_is_valid), cmocka_unit_test(tscf_payload), cmocka_unit_test(tscf_header_coverage), + cmocka_unit_test(tscf_common_field_consistency), }; return cmocka_run_group_tests(tests, NULL, NULL); From ad9c84ea169c28fa2f4f248ce875c40d49ca9a93 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Sat, 19 Sep 2026 13:15:55 +0200 Subject: [PATCH 06/16] Added V1 for Alternative Header including NTSCF and CRF Signed-off-by: Sebastian Schildt --- docs/api-design.md | 31 +++ examples/acf-vss/acf-vss-talker.c | 6 +- include/avtp/AlternativeHeader.h | 194 +++++++++++++++++++ include/avtp/Crf.h | 295 ++++++++++++++++++++-------- include/avtp/acf/Ntscf.h | 309 ++++++++++++++++++++++-------- src/avtp/export/InlineExports.c | 1 + unit/test-crf.c | 181 ++++++++++++++--- unit/test-ntscf.c | 254 +++++++++++++++++++++--- 8 files changed, 1055 insertions(+), 216 deletions(-) create mode 100644 include/avtp/AlternativeHeader.h diff --git a/docs/api-design.md b/docs/api-design.md index 13d7a020..3e718215 100644 --- a/docs/api-design.md +++ b/docs/api-design.md @@ -637,6 +637,37 @@ each version, the common header fields (`subtype`, `version`; `h` is covered by the format's `SV`) plus the format's complete table must cover the whole header exactly once. +## The AVTP alternative header + +The alternative header (4.7.6) is used by formats that do not fit the common +stream or control headers - CRF and NTSCF in this library. It exists in two +versions: + +| Version | Length | Additional fields | +|---------|--------|--------------------------------------------------------------------------| +| 0 | 4 B | - | +| 1 | 16 B | `reserved[20]`, `sequence_num[32]`, `ptp_grandmaster_identity[64]`, then `reserved[12]` at the head of the format area | + +[`AlternativeHeader.h`](../include/avtp/AlternativeHeader.h) describes the +byte-aligned v1 prefix (`AVTPDU_AH_LEN_V1` = 16): + +- `Avtp_AlternativeHeader_t` - a view type sized for the v1 prefix. +- `AVTPDU_AH_FIELD_RESERVED1`, `_SEQUENCE_NUM`, `_PTP_GRANDMASTER_IDENTITY`, + mapped by `Avtp_AhFieldDescV0` (all zero) and `Avtp_AhFieldDescV1`. +- `Avtp_AlternativeHeader_*` accessors; `GetSequenceNum` returns `uint32_t` and + `GetPtpGrandmasterIdentity` `uint64_t`, both 0 on version 0. + +The trailing `reserved[12]` is the head of the format-specific data area +(format fields begin at bit 140), so it is owned by the format tables +(`AVTP_CRF_FIELD_RESERVED`, `AVTP_NTSCF_FIELD_RESERVED`). CRF and NTSCF follow +the same pattern as the stream formats: complete per-version tables in absolute +coordinates, alternative header fields first, and a consistency test that +compares those entries against `Avtp_AhFieldDescV0/V1`. Their header lengths +are format-defined (`Avtp_Crf_GetHeaderLen` 20/36, `Avtp_Ntscf_GetHeaderLen` +12/28), and `sequence_num_lsb` remains a semantic wrapper: on version 1 it is a +copy of the low byte of the alternative header's 32-bit `sequence_num` +(CRF-25 / NTSCF-6). + ## ACF layering & the common header ACF formats share a *common header* whose two fields - `acf_msg_type` and diff --git a/examples/acf-vss/acf-vss-talker.c b/examples/acf-vss/acf-vss-talker.c index d02406c0..69e44804 100644 --- a/examples/acf-vss/acf-vss-talker.c +++ b/examples/acf-vss/acf-vss-talker.c @@ -152,8 +152,8 @@ static int init_cf_pdu(uint8_t *pdu) Avtp_Ntscf_t *ntscf_pdu = (Avtp_Ntscf_t *)pdu; memset(ntscf_pdu, 0, AVTP_NTSCF_HEADER_LEN); Avtp_Ntscf_Init(ntscf_pdu); - Avtp_Ntscf_SetField(ntscf_pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM, seq_num++); - Avtp_Ntscf_SetField(ntscf_pdu, AVTP_NTSCF_FIELD_STREAM_ID, STREAM_ID); + Avtp_Ntscf_SetSequenceNum(ntscf_pdu, seq_num++); + Avtp_Ntscf_SetStreamId(ntscf_pdu, STREAM_ID); res = AVTP_NTSCF_HEADER_LEN; } return res; @@ -166,7 +166,7 @@ static int update_cf_length(uint8_t *cf_pdu, uint64_t length) Avtp_Tscf_SetStreamDataLength((Avtp_Tscf_t *)cf_pdu, (uint16_t)payloadLen); } else { uint64_t payloadLen = length - AVTP_NTSCF_HEADER_LEN; - Avtp_Ntscf_SetField((Avtp_Ntscf_t *)cf_pdu, AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH, payloadLen); + Avtp_Ntscf_SetNtscfDataLength((Avtp_Ntscf_t *)cf_pdu, (uint16_t)payloadLen); } return 0; } diff --git a/include/avtp/AlternativeHeader.h b/include/avtp/AlternativeHeader.h new file mode 100644 index 00000000..7d500c1a --- /dev/null +++ b/include/avtp/AlternativeHeader.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2026, COVESA + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of COVESA nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * This file contains the field descriptions of the IEEE 1722 AVTPDU + * alternative header (4.7.6) for versions 0 and 1 and functions to invoke the + * corresponding parser and deparser. + * + * The version 1 alternative header is modelled as the byte-aligned prefix + * through ptp_grandmaster_identity (16 octets). The trailing reserved field + * (12 bits at the head of the following quadlet) and the format fields that + * follow it are described by the individual format tables. Format modules + * declare complete descriptor tables per version in absolute coordinates, + * reusing these positions for the alternative header fields. A consistency + * test keeps the common entries of each format aligned with the tables here. + */ + +#pragma once +#include "avtp/Inline.h" + +#ifdef LINUX_KERNEL1722 +#include +#else +#include +#include +#endif + +#include "avtp/Defines.h" +#include "avtp/Utils.h" +#include "avtp/CommonHeader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* AVTPDU alternative header prefix length in octets (IEEE 1722-2025, 4.7.6). */ +#define AVTPDU_AH_LEN_V0 (1 * AVTP_QUADLET_SIZE) /* 4 */ +#define AVTPDU_AH_LEN_V1 (4 * AVTP_QUADLET_SIZE) /* 16 */ + +/** + * View type for the AVTPDU alternative header prefix. The prefix is 4 octets + * for version 0 (the common header) and 16 octets for version 1. Every accessor + * dispatches on the version field of the common header. + */ +typedef struct { + uint8_t header[AVTPDU_AH_LEN_V1]; + uint8_t payload[0]; +} Avtp_AlternativeHeader_t; + +/** + * Enumeration over all IEEE 1722 AVTPDU alternative header fields. The naming + * convention used is AVTPDU_
_FIELD_. The trailing 12-bit + * reserved field of version 1 is not listed here; it belongs to the + * format-specific data area and is described by the format tables. + */ +typedef enum { + AVTPDU_AH_FIELD_RESERVED1 = 0, + AVTPDU_AH_FIELD_SEQUENCE_NUM, + AVTPDU_AH_FIELD_PTP_GRANDMASTER_IDENTITY, + + /* Count number of fields for bound checks */ + AVTPDU_AH_FIELD_MAX +} Avtp_AlternativeHeaderField_t; + +/** + * These tables map all IEEE 1722 AVTPDU alternative header fields to a + * descriptor, one table per version. The version 0 alternative header has no + * fields beyond the common header, so all descriptors are zero. + */ +static const Avtp_FieldDescriptor_t Avtp_AhFieldDescV0[AVTPDU_AH_FIELD_MAX] = { + [AVTPDU_AH_FIELD_RESERVED1] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTPDU_AH_FIELD_SEQUENCE_NUM] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTPDU_AH_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 0, .offset = 0, .bits = 0}, +}; + +static const Avtp_FieldDescriptor_t Avtp_AhFieldDescV1[AVTPDU_AH_FIELD_MAX] = { + [AVTPDU_AH_FIELD_RESERVED1] = {.quadlet = 0, .offset = 12, .bits = 20}, + [AVTPDU_AH_FIELD_SEQUENCE_NUM] = {.quadlet = 1, .offset = 0, .bits = 32}, + [AVTPDU_AH_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 2, .offset = 0, .bits = 64}, +}; + +/** + * Returns the raw version field of the AVTPDU common header. Values other than + * 0 or 1 are reserved; the accessors treat anything other than 1 as version 0. + */ +OPEN1722_INLINE uint8_t Avtp_AlternativeHeader_GetVersion(const Avtp_AlternativeHeader_t *const pdu) +{ + return Avtp_CommonHeader_GetVersion((const Avtp_CommonHeader_t *)pdu); +} + +/** + * Returns the value of an AVTPDU alternative header field. + * + * @param pdu Pointer to the first bit of an 1722 AVTP PDU. + * @param field Specifies the position of the data field to be read. + * @returns The value of the specified field. + */ +OPEN1722_INLINE uint64_t Avtp_AlternativeHeader_GetField(const Avtp_AlternativeHeader_t *const pdu, + Avtp_AlternativeHeaderField_t field) +{ + const Avtp_FieldDescriptor_t *desc = Avtp_AlternativeHeader_GetVersion(pdu) == AVTP_VERSION_1 + ? Avtp_AhFieldDescV1 + : Avtp_AhFieldDescV0; + return Avtp_GetField(desc, AVTPDU_AH_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); +} + +/** + * Sets the value of an AVTPDU alternative header field. Fields absent from the + * version in use are left untouched. + * + * @param pdu Pointer to the first bit of an 1722 AVTP PDU. + * @param field Specifies the position of the data field to be written. + * @param value The value to set. + */ +OPEN1722_INLINE void Avtp_AlternativeHeader_SetField(Avtp_AlternativeHeader_t *pdu, + Avtp_AlternativeHeaderField_t field, + uint64_t value) +{ + const Avtp_FieldDescriptor_t *desc = Avtp_AlternativeHeader_GetVersion(pdu) == AVTP_VERSION_1 + ? Avtp_AhFieldDescV1 + : Avtp_AhFieldDescV0; + Avtp_SetField(desc, AVTPDU_AH_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Returns the sequence_num field of the AVTPDU alternative header. The field + * only exists in version 1; version 0 returns 0. + */ +OPEN1722_INLINE uint32_t +Avtp_AlternativeHeader_GetSequenceNum(const Avtp_AlternativeHeader_t *const pdu) +{ + return (uint32_t)Avtp_AlternativeHeader_GetField(pdu, AVTPDU_AH_FIELD_SEQUENCE_NUM); +} + +/** + * Sets the sequence_num field of the AVTPDU alternative header. The field only + * exists in version 1; on version 0 this is a no-op. + */ +OPEN1722_INLINE void Avtp_AlternativeHeader_SetSequenceNum(Avtp_AlternativeHeader_t *pdu, + uint32_t value) +{ + Avtp_AlternativeHeader_SetField(pdu, AVTPDU_AH_FIELD_SEQUENCE_NUM, value); +} + +/** + * Returns the ptp_grandmaster_identity field of the AVTPDU alternative header. + * The field only exists in version 1; version 0 returns 0. + */ +OPEN1722_INLINE uint64_t +Avtp_AlternativeHeader_GetPtpGrandmasterIdentity(const Avtp_AlternativeHeader_t *const pdu) +{ + return Avtp_AlternativeHeader_GetField(pdu, AVTPDU_AH_FIELD_PTP_GRANDMASTER_IDENTITY); +} + +/** + * Sets the ptp_grandmaster_identity field of the AVTPDU alternative header. + * The field only exists in version 1; on version 0 this is a no-op. + */ +OPEN1722_INLINE void Avtp_AlternativeHeader_SetPtpGrandmasterIdentity(Avtp_AlternativeHeader_t *pdu, + uint64_t value) +{ + Avtp_AlternativeHeader_SetField(pdu, AVTPDU_AH_FIELD_PTP_GRANDMASTER_IDENTITY, value); +} + +#ifdef __cplusplus +} +#endif diff --git a/include/avtp/Crf.h b/include/avtp/Crf.h index e43aa2d7..3ba0f513 100644 --- a/include/avtp/Crf.h +++ b/include/avtp/Crf.h @@ -1,6 +1,5 @@ /* * Copyright (c) 2024, COVESA - * Copyright (c) 2018, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -10,9 +9,9 @@ * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * * Neither the name of Intel Corporation, COVESA nor the names of their - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * * Neither the name of COVESA nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -32,6 +31,13 @@ * @file * This file contains the fields descriptions of the IEEE 1722 CRF PDUs and * functions to invoke corresponding parser and deparser. + * + * CRF uses the AVTPDU alternative header (4.7.6) and declares a complete + * descriptor table per version in absolute coordinates: the alternative header + * fields reuse the positions from AlternativeHeader.h, the trailing 12-bit + * reserved field and the CRF-specific fields are added by this module. A + * consistency test keeps the alternative header entries aligned with the + * alternative header module. */ #pragma once @@ -47,23 +53,30 @@ #include "avtp/Utils.h" #include "avtp/Defines.h" #include "avtp/CommonHeader.h" +#include "avtp/AlternativeHeader.h" #ifdef __cplusplus extern "C" { #endif -#define AVTP_CRF_HEADER_LEN (5 * AVTP_QUADLET_SIZE) +#define AVTP_CRF_HEADER_LEN_V0 (5 * AVTP_QUADLET_SIZE) /* 20 */ +#define AVTP_CRF_HEADER_LEN_V1 (9 * AVTP_QUADLET_SIZE) /* 36 */ +/* Kept for compatibility: the version 0 header length. */ +#define AVTP_CRF_HEADER_LEN AVTP_CRF_HEADER_LEN_V0 -#define GET_CRF_FIELD(field) \ - (Avtp_GetField(Avtp_CrfFieldDesc, AVTP_CRF_FIELD_MAX, (const uint8_t *)pdu, field)) -#define SET_CRF_FIELD(field, value) \ - (Avtp_SetField(Avtp_CrfFieldDesc, AVTP_CRF_FIELD_MAX, (uint8_t *)pdu, field, value)) +/* CRF supports both versions of the alternative header (Table 7). */ +#define AVTP_CRF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) typedef struct { - uint8_t header[AVTP_CRF_HEADER_LEN]; + uint8_t header[AVTP_CRF_HEADER_LEN_V0]; uint8_t payload[0]; } __attribute__((packed)) Avtp_Crf_t; +typedef struct { + uint8_t header[AVTP_CRF_HEADER_LEN_V1]; + uint8_t payload[0]; +} __attribute__((packed)) Avtp_CrfV1_t; + /** * CRF 'type' field values (IEEE 1722-2025, Table 31). Values 0x05-0xFF are * reserved. @@ -92,16 +105,18 @@ typedef enum { typedef enum { /* Common AVTP alternative header fields */ - AVTP_CRF_FIELD_SUBTYPE, + AVTP_CRF_FIELD_RESERVED1 = 0, + AVTP_CRF_FIELD_SEQUENCE_NUM, + AVTP_CRF_FIELD_PTP_GRANDMASTER_IDENTITY, + + /* CRF header fields */ AVTP_CRF_FIELD_SV, - AVTP_CRF_FIELD_VERSION, + AVTP_CRF_FIELD_RESERVED, AVTP_CRF_FIELD_MR, AVTP_CRF_FIELD_R, AVTP_CRF_FIELD_FS, AVTP_CRF_FIELD_TU, - AVTP_CRF_FIELD_SEQUENCE_NUM, - - /* CRF header fields */ + AVTP_CRF_FIELD_SEQUENCE_NUM_LSB, AVTP_CRF_FIELD_TYPE, AVTP_CRF_FIELD_STREAM_ID, AVTP_CRF_FIELD_PULL, @@ -114,19 +129,21 @@ typedef enum { } Avtp_CrfFields_t; /** - * This table maps all IEEE 1722 CRF header fields to a descriptor. + * This table maps all IEEE 1722 CRF header fields to a descriptor for version + * 0. It is complete and in absolute coordinates; the alternative header fields + * are absent in version 0. */ -static const Avtp_FieldDescriptor_t Avtp_CrfFieldDesc[AVTP_CRF_FIELD_MAX] = { - /* Common AVTP alternative header fields */ - [AVTP_CRF_FIELD_SUBTYPE] = {.quadlet = 0, .offset = 0, .bits = 8}, +static const Avtp_FieldDescriptor_t Avtp_CrfFieldDescV0[AVTP_CRF_FIELD_MAX] = { + [AVTP_CRF_FIELD_RESERVED1] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_CRF_FIELD_SEQUENCE_NUM] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_CRF_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 0, .offset = 0, .bits = 0}, [AVTP_CRF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, - [AVTP_CRF_FIELD_VERSION] = {.quadlet = 0, .offset = 9, .bits = 3}, + [AVTP_CRF_FIELD_RESERVED] = {.quadlet = 0, .offset = 0, .bits = 0}, [AVTP_CRF_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, [AVTP_CRF_FIELD_R] = {.quadlet = 0, .offset = 13, .bits = 1}, [AVTP_CRF_FIELD_FS] = {.quadlet = 0, .offset = 14, .bits = 1}, [AVTP_CRF_FIELD_TU] = {.quadlet = 0, .offset = 15, .bits = 1}, - [AVTP_CRF_FIELD_SEQUENCE_NUM] = {.quadlet = 0, .offset = 16, .bits = 8}, - /* CRF header fields */ + [AVTP_CRF_FIELD_SEQUENCE_NUM_LSB] = {.quadlet = 0, .offset = 16, .bits = 8}, [AVTP_CRF_FIELD_TYPE] = {.quadlet = 0, .offset = 24, .bits = 8}, [AVTP_CRF_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, [AVTP_CRF_FIELD_PULL] = {.quadlet = 3, .offset = 0, .bits = 3}, @@ -135,6 +152,73 @@ static const Avtp_FieldDescriptor_t Avtp_CrfFieldDesc[AVTP_CRF_FIELD_MAX] = { [AVTP_CRF_FIELD_TIMESTAMP_INTERVAL] = {.quadlet = 4, .offset = 16, .bits = 16}, }; +/** + * This table maps all IEEE 1722 CRF header fields to a descriptor for version + * 1. It is complete and in absolute coordinates; the alternative header fields + * use the same positions as Avtp_AhFieldDescV1. + */ +static const Avtp_FieldDescriptor_t Avtp_CrfFieldDescV1[AVTP_CRF_FIELD_MAX] = { + [AVTP_CRF_FIELD_RESERVED1] = {.quadlet = 0, .offset = 12, .bits = 20}, + [AVTP_CRF_FIELD_SEQUENCE_NUM] = {.quadlet = 1, .offset = 0, .bits = 32}, + [AVTP_CRF_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 2, .offset = 0, .bits = 64}, + [AVTP_CRF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, + [AVTP_CRF_FIELD_RESERVED] = {.quadlet = 4, .offset = 0, .bits = 12}, + [AVTP_CRF_FIELD_MR] = {.quadlet = 4, .offset = 12, .bits = 1}, + [AVTP_CRF_FIELD_R] = {.quadlet = 4, .offset = 13, .bits = 1}, + [AVTP_CRF_FIELD_FS] = {.quadlet = 4, .offset = 14, .bits = 1}, + [AVTP_CRF_FIELD_TU] = {.quadlet = 4, .offset = 15, .bits = 1}, + [AVTP_CRF_FIELD_SEQUENCE_NUM_LSB] = {.quadlet = 4, .offset = 16, .bits = 8}, + [AVTP_CRF_FIELD_TYPE] = {.quadlet = 4, .offset = 24, .bits = 8}, + [AVTP_CRF_FIELD_STREAM_ID] = {.quadlet = 5, .offset = 0, .bits = 64}, + [AVTP_CRF_FIELD_PULL] = {.quadlet = 7, .offset = 0, .bits = 3}, + [AVTP_CRF_FIELD_BASE_FREQUENCY] = {.quadlet = 7, .offset = 3, .bits = 29}, + [AVTP_CRF_FIELD_CRF_DATA_LENGTH] = {.quadlet = 8, .offset = 0, .bits = 16}, + [AVTP_CRF_FIELD_TIMESTAMP_INTERVAL] = {.quadlet = 8, .offset = 16, .bits = 16}, +}; + +/** + * Returns the value of an AVTP CRF field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + */ +OPEN1722_INLINE uint64_t Avtp_Crf_GetField(const Avtp_Crf_t *const pdu, Avtp_CrfFields_t field) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_CrfFieldDescV1 + : Avtp_CrfFieldDescV0; + return Avtp_GetField(desc, AVTP_CRF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); +} + +/** + * Sets the value of an AVTP CRF field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + */ +OPEN1722_INLINE void Avtp_Crf_SetField(Avtp_Crf_t *pdu, Avtp_CrfFields_t field, uint64_t value) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_CrfFieldDescV1 + : Avtp_CrfFieldDescV0; + Avtp_SetField(desc, AVTP_CRF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Returns the length of the CRF header in octets (20 or 36). + */ +OPEN1722_INLINE uint8_t Avtp_Crf_GetHeaderLen(const Avtp_Crf_t *const pdu) +{ + return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1 + ? (uint8_t)AVTP_CRF_HEADER_LEN_V1 + : (uint8_t)AVTP_CRF_HEADER_LEN_V0; +} + /** * Return the value of the CRF SV field as specified in the IEEE 1722 Specification. * @@ -143,7 +227,7 @@ static const Avtp_FieldDescriptor_t Avtp_CrfFieldDesc[AVTP_CRF_FIELD_MAX] = { */ OPEN1722_INLINE bool Avtp_Crf_IsSv(const Avtp_Crf_t *const pdu) { - return (bool)GET_CRF_FIELD(AVTP_CRF_FIELD_SV); + return (bool)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_SV); } /** @@ -154,7 +238,7 @@ OPEN1722_INLINE bool Avtp_Crf_IsSv(const Avtp_Crf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Crf_IsMr(const Avtp_Crf_t *const pdu) { - return (bool)GET_CRF_FIELD(AVTP_CRF_FIELD_MR); + return (bool)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_MR); } /** @@ -165,7 +249,7 @@ OPEN1722_INLINE bool Avtp_Crf_IsMr(const Avtp_Crf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Crf_IsFs(const Avtp_Crf_t *const pdu) { - return (bool)GET_CRF_FIELD(AVTP_CRF_FIELD_FS); + return (bool)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_FS); } /** @@ -176,18 +260,49 @@ OPEN1722_INLINE bool Avtp_Crf_IsFs(const Avtp_Crf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Crf_IsTu(const Avtp_Crf_t *const pdu) { - return (bool)GET_CRF_FIELD(AVTP_CRF_FIELD_TU); + return (bool)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_TU); } /** - * Return the value of the CRF Sequence Number field as specified in the IEEE 1722 Specification. + * Return the effective CRF Sequence Number field as specified in the IEEE 1722 + * Specification. The field is the 8-bit sequence_num_lsb in version 0 and the + * 32-bit sequence_num in version 1. * * @param pdu Pointer to the first bit of an 1722 CRF PDU. * @returns Value of the CRF Sequence Number field. */ -OPEN1722_INLINE uint8_t Avtp_Crf_GetSequenceNum(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Crf_GetSequenceNum(const Avtp_Crf_t *const pdu) +{ + if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1) { + return (uint32_t)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM); + } + return (uint8_t)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB); +} + +/** + * Return the value of the CRF sequence_num_lsb field. In version 1 it contains + * a copy of the eight least significant bits of the sequence_num field in the + * alternative header (CRF-25). + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @returns Value of the CRF sequence_num_lsb field. + */ +OPEN1722_INLINE uint8_t Avtp_Crf_GetSequenceNumLsb(const Avtp_Crf_t *const pdu) { - return (uint8_t)GET_CRF_FIELD(AVTP_CRF_FIELD_SEQUENCE_NUM); + return (uint8_t)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB); +} + +/** + * Return the value of the CRF ptp_grandmaster_identity field. The field only + * exists in version 1; version 0 returns 0. + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @returns Value of the CRF ptp_grandmaster_identity field. + */ +OPEN1722_INLINE uint64_t Avtp_Crf_GetPtpGrandmasterIdentity(const Avtp_Crf_t *const pdu) +{ + return Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_PTP_GRANDMASTER_IDENTITY); } /** @@ -198,7 +313,7 @@ OPEN1722_INLINE uint8_t Avtp_Crf_GetSequenceNum(const Avtp_Crf_t *const pdu) */ OPEN1722_INLINE Avtp_CrfType_t Avtp_Crf_GetType(const Avtp_Crf_t *const pdu) { - return (Avtp_CrfType_t)GET_CRF_FIELD(AVTP_CRF_FIELD_TYPE); + return (Avtp_CrfType_t)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_TYPE); } /** @@ -209,7 +324,7 @@ OPEN1722_INLINE Avtp_CrfType_t Avtp_Crf_GetType(const Avtp_Crf_t *const pdu) */ OPEN1722_INLINE uint64_t Avtp_Crf_GetStreamId(const Avtp_Crf_t *const pdu) { - return (uint64_t)GET_CRF_FIELD(AVTP_CRF_FIELD_STREAM_ID); + return Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_STREAM_ID); } /** @@ -220,7 +335,7 @@ OPEN1722_INLINE uint64_t Avtp_Crf_GetStreamId(const Avtp_Crf_t *const pdu) */ OPEN1722_INLINE Avtp_CrfPull_t Avtp_Crf_GetPull(const Avtp_Crf_t *const pdu) { - return (Avtp_CrfPull_t)GET_CRF_FIELD(AVTP_CRF_FIELD_PULL); + return (Avtp_CrfPull_t)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_PULL); } /** @@ -231,7 +346,7 @@ OPEN1722_INLINE Avtp_CrfPull_t Avtp_Crf_GetPull(const Avtp_Crf_t *const pdu) */ OPEN1722_INLINE uint32_t Avtp_Crf_GetBaseFrequency(const Avtp_Crf_t *const pdu) { - return (uint32_t)GET_CRF_FIELD(AVTP_CRF_FIELD_BASE_FREQUENCY); + return (uint32_t)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_BASE_FREQUENCY); } /** @@ -242,7 +357,7 @@ OPEN1722_INLINE uint32_t Avtp_Crf_GetBaseFrequency(const Avtp_Crf_t *const pdu) */ OPEN1722_INLINE uint16_t Avtp_Crf_GetCrfDataLength(const Avtp_Crf_t *const pdu) { - return (uint16_t)GET_CRF_FIELD(AVTP_CRF_FIELD_CRF_DATA_LENGTH); + return (uint16_t)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_CRF_DATA_LENGTH); } /** @@ -253,7 +368,7 @@ OPEN1722_INLINE uint16_t Avtp_Crf_GetCrfDataLength(const Avtp_Crf_t *const pdu) */ OPEN1722_INLINE uint16_t Avtp_Crf_GetTimestampInterval(const Avtp_Crf_t *const pdu) { - return (uint16_t)GET_CRF_FIELD(AVTP_CRF_FIELD_TIMESTAMP_INTERVAL); + return (uint16_t)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_TIMESTAMP_INTERVAL); } /** @@ -264,7 +379,7 @@ OPEN1722_INLINE uint16_t Avtp_Crf_GetTimestampInterval(const Avtp_Crf_t *const p */ OPEN1722_INLINE void Avtp_Crf_SetSv(Avtp_Crf_t *pdu, bool sv) { - SET_CRF_FIELD(AVTP_CRF_FIELD_SV, sv); + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_SV, sv); } /** @@ -275,7 +390,7 @@ OPEN1722_INLINE void Avtp_Crf_SetSv(Avtp_Crf_t *pdu, bool sv) */ OPEN1722_INLINE void Avtp_Crf_SetMr(Avtp_Crf_t *pdu, bool mr) { - SET_CRF_FIELD(AVTP_CRF_FIELD_MR, mr); + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_MR, mr); } /** @@ -286,7 +401,7 @@ OPEN1722_INLINE void Avtp_Crf_SetMr(Avtp_Crf_t *pdu, bool mr) */ OPEN1722_INLINE void Avtp_Crf_SetFs(Avtp_Crf_t *pdu, bool fs) { - SET_CRF_FIELD(AVTP_CRF_FIELD_FS, fs); + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_FS, fs); } /** @@ -297,18 +412,35 @@ OPEN1722_INLINE void Avtp_Crf_SetFs(Avtp_Crf_t *pdu, bool fs) */ OPEN1722_INLINE void Avtp_Crf_SetTu(Avtp_Crf_t *pdu, bool tu) { - SET_CRF_FIELD(AVTP_CRF_FIELD_TU, tu); + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_TU, tu); } /** - * Set the value of the CRF Sequence Number field as specified in the IEEE 1722 Specification. + * Set the effective CRF Sequence Number field as specified in the IEEE 1722 + * Specification. In version 1 the eight least significant bits are also written + * to the sequence_num_lsb copy (CRF-25); in version 0 they are the sequence + * number itself. * * @param pdu Pointer to the first bit of an 1722 CRF PDU. * @param value Value to set the CRF Sequence Number field to. */ -OPEN1722_INLINE void Avtp_Crf_SetSequenceNum(Avtp_Crf_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Crf_SetSequenceNum(Avtp_Crf_t *pdu, uint32_t value) +{ + /* No-op on version 0: the field only exists in the alternative header v1. */ + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM, value); + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); +} + +/** + * Set the value of the CRF ptp_grandmaster_identity field. The field only + * exists in version 1; on version 0 this is a no-op. + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @param value Value to set the CRF ptp_grandmaster_identity field to. + */ +OPEN1722_INLINE void Avtp_Crf_SetPtpGrandmasterIdentity(Avtp_Crf_t *pdu, uint64_t value) { - SET_CRF_FIELD(AVTP_CRF_FIELD_SEQUENCE_NUM, value); + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_PTP_GRANDMASTER_IDENTITY, value); } /** @@ -319,7 +451,7 @@ OPEN1722_INLINE void Avtp_Crf_SetSequenceNum(Avtp_Crf_t *pdu, uint8_t value) */ OPEN1722_INLINE void Avtp_Crf_SetType(Avtp_Crf_t *pdu, Avtp_CrfType_t value) { - SET_CRF_FIELD(AVTP_CRF_FIELD_TYPE, (uint64_t)value); + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_TYPE, (uint64_t)value); } /** @@ -330,7 +462,7 @@ OPEN1722_INLINE void Avtp_Crf_SetType(Avtp_Crf_t *pdu, Avtp_CrfType_t value) */ OPEN1722_INLINE void Avtp_Crf_SetStreamId(Avtp_Crf_t *pdu, uint64_t value) { - SET_CRF_FIELD(AVTP_CRF_FIELD_STREAM_ID, value); + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_STREAM_ID, value); } /** @@ -341,7 +473,7 @@ OPEN1722_INLINE void Avtp_Crf_SetStreamId(Avtp_Crf_t *pdu, uint64_t value) */ OPEN1722_INLINE void Avtp_Crf_SetPull(Avtp_Crf_t *pdu, Avtp_CrfPull_t value) { - SET_CRF_FIELD(AVTP_CRF_FIELD_PULL, (uint64_t)value); + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_PULL, (uint64_t)value); } /** @@ -352,7 +484,7 @@ OPEN1722_INLINE void Avtp_Crf_SetPull(Avtp_Crf_t *pdu, Avtp_CrfPull_t value) */ OPEN1722_INLINE void Avtp_Crf_SetBaseFrequency(Avtp_Crf_t *pdu, uint32_t value) { - SET_CRF_FIELD(AVTP_CRF_FIELD_BASE_FREQUENCY, value); + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_BASE_FREQUENCY, value); } /** @@ -363,7 +495,7 @@ OPEN1722_INLINE void Avtp_Crf_SetBaseFrequency(Avtp_Crf_t *pdu, uint32_t value) */ OPEN1722_INLINE void Avtp_Crf_SetCrfDataLength(Avtp_Crf_t *pdu, uint16_t value) { - SET_CRF_FIELD(AVTP_CRF_FIELD_CRF_DATA_LENGTH, value); + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_CRF_DATA_LENGTH, value); } /** @@ -374,11 +506,12 @@ OPEN1722_INLINE void Avtp_Crf_SetCrfDataLength(Avtp_Crf_t *pdu, uint16_t value) */ OPEN1722_INLINE void Avtp_Crf_SetTimestampInterval(Avtp_Crf_t *pdu, uint16_t value) { - SET_CRF_FIELD(AVTP_CRF_FIELD_TIMESTAMP_INTERVAL, value); + Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_TIMESTAMP_INTERVAL, value); } /** - * Returns pointer to the CRF data of a CRF frame. + * Returns pointer to the CRF data of a CRF frame. The CRF data starts after the + * version-dependent CRF header. * * The CRF data contains the timestamps of the stream. Each timestamp is * 8 octets long. @@ -388,7 +521,7 @@ OPEN1722_INLINE void Avtp_Crf_SetTimestampInterval(Avtp_Crf_t *pdu, uint16_t val */ OPEN1722_INLINE const uint8_t *Avtp_Crf_GetPayload(const Avtp_Crf_t *const pdu) { - return pdu->payload; + return (const uint8_t *)pdu + Avtp_Crf_GetHeaderLen(pdu); } /** @@ -400,11 +533,11 @@ OPEN1722_INLINE const uint8_t *Avtp_Crf_GetPayload(const Avtp_Crf_t *const pdu) */ OPEN1722_INLINE void Avtp_Crf_SetPayload(Avtp_Crf_t *pdu, uint8_t *payload, uint16_t payload_length) { - memcpy(pdu->payload, payload, payload_length); + memcpy((uint8_t *)pdu + Avtp_Crf_GetHeaderLen(pdu), payload, payload_length); } /** - * Initializes a CRF PDU as specified in the IEEE 1722 Specification. + * Initializes a version 0 CRF PDU as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of a 1722 CRF PDU. */ @@ -417,10 +550,28 @@ OPEN1722_INLINE void Avtp_Crf_Init(Avtp_Crf_t *pdu) } } +/** + * Initializes a version 1 CRF PDU. The caller must provide a buffer of at least + * AVTP_CRF_HEADER_LEN_V1 octets. + * + * @param pdu Pointer to the first bit of a 1722 CRF PDU. + */ +OPEN1722_INLINE void Avtp_Crf_InitV1(Avtp_CrfV1_t *pdu) +{ + if (pdu != NULL) { + memset(pdu, 0, sizeof(Avtp_CrfV1_t)); + Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_CRF); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_Crf_SetSv((Avtp_Crf_t *)pdu, true); + } +} + /** * Checks if the CRF frame is valid by checking: - * 1) if the crf_data_length field contains a value larger than the actual size of the buffer - * that contains the AVTP message. 2) if other format specific invariants are not upheld. + * 1) that the subtype is CRF and the version is supported, + * 2) that the version-dependent header fits into the buffer, + * 3) that crf_data_length is a non-zero multiple of 8 and fits into the + * buffer. * * The crf_data_length field contains the length (in octets) of the crf_data * field (IEEE 1722-2025, 10.4.11), so the whole AVTPDU must fit into bufferSize. @@ -437,11 +588,17 @@ OPEN1722_INLINE bool Avtp_Crf_IsValid(const Avtp_Crf_t *const pdu, size_t buffer return false; } - if (bufferSize < AVTP_CRF_HEADER_LEN) { + if (Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu) != AVTP_SUBTYPE_CRF) { return false; } - if (Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu) != AVTP_SUBTYPE_CRF) { + uint8_t version = Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu); + if (!Avtp_Version_IsSupported(AVTP_CRF_SUPPORTED_VERSIONS, version)) { + return false; + } + + size_t headerLen = Avtp_Crf_GetHeaderLen(pdu); + if (bufferSize < headerLen) { return false; } @@ -451,37 +608,13 @@ OPEN1722_INLINE bool Avtp_Crf_IsValid(const Avtp_Crf_t *const pdu, size_t buffer return false; } - if ((size_t)AVTP_CRF_HEADER_LEN + (size_t)crf_data_length > bufferSize) { + if (headerLen + (size_t)crf_data_length > bufferSize) { return false; } return true; } -/** - * Returns the value of an AVTP CRF field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 CRF PDU. - * @param field Specifies the position of the data field to be read - * @returns This function returns the value of the field. - */ -OPEN1722_INLINE uint64_t Avtp_Crf_GetField(const Avtp_Crf_t *const pdu, Avtp_CrfFields_t field) -{ - return (uint64_t)GET_CRF_FIELD(field); -} - -/** - * Sets the value of an AVTP CRF field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 CRF PDU. - * @param field Specifies the position of the data field to be written - * @param value The value to set. - */ -OPEN1722_INLINE void Avtp_Crf_SetField(Avtp_Crf_t *pdu, Avtp_CrfFields_t field, uint64_t value) -{ - SET_CRF_FIELD(field, value); -} - #ifdef __cplusplus } #endif diff --git a/include/avtp/acf/Ntscf.h b/include/avtp/acf/Ntscf.h index 52eab1ac..388d0970 100644 --- a/include/avtp/acf/Ntscf.h +++ b/include/avtp/acf/Ntscf.h @@ -31,6 +31,13 @@ * @file * This file contains the fields descriptions of the IEEE 1722 NTSCF PDUs and * functions to invoke corresponding parser and deparser. + * + * NTSCF uses the AVTPDU alternative header (4.7.6) and declares a complete + * descriptor table per version in absolute coordinates: the alternative header + * fields reuse the positions from AlternativeHeader.h, the trailing 12-bit + * reserved field and the NTSCF-specific fields are added by this module. A + * consistency test keeps the alternative header entries aligned with the + * alternative header module. */ #pragma once @@ -46,150 +53,300 @@ #include "avtp/Utils.h" #include "avtp/Defines.h" #include "avtp/CommonHeader.h" +#include "avtp/AlternativeHeader.h" #ifdef __cplusplus extern "C" { #endif -#define AVTP_NTSCF_HEADER_LEN (3 * AVTP_QUADLET_SIZE) +#define AVTP_NTSCF_HEADER_LEN_V0 (3 * AVTP_QUADLET_SIZE) /* 12 */ +#define AVTP_NTSCF_HEADER_LEN_V1 (7 * AVTP_QUADLET_SIZE) /* 28 */ +/* Kept for compatibility: the version 0 header length. */ +#define AVTP_NTSCF_HEADER_LEN AVTP_NTSCF_HEADER_LEN_V0 -#define GET_NTSCF_FIELD(field) \ - (Avtp_GetField(Avtp_NtscfFieldDesc, AVTP_NTSCF_FIELD_MAX, (const uint8_t *)pdu, field)) -#define SET_NTSCF_FIELD(field, value) \ - (Avtp_SetField(Avtp_NtscfFieldDesc, AVTP_NTSCF_FIELD_MAX, (uint8_t *)pdu, field, value)) +/* NTSCF supports both versions of the alternative header (Table 7). */ +#define AVTP_NTSCF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) typedef struct { - uint8_t header[AVTP_NTSCF_HEADER_LEN]; + uint8_t header[AVTP_NTSCF_HEADER_LEN_V0]; uint8_t payload[0]; } __attribute__((packed)) Avtp_Ntscf_t; +typedef struct { + uint8_t header[AVTP_NTSCF_HEADER_LEN_V1]; + uint8_t payload[0]; +} __attribute__((packed)) Avtp_NtscfV1_t; + typedef enum { - AVTP_NTSCF_FIELD_SUBTYPE, + + /* Common AVTP alternative header fields */ + AVTP_NTSCF_FIELD_RESERVED1 = 0, + AVTP_NTSCF_FIELD_SEQUENCE_NUM, + AVTP_NTSCF_FIELD_PTP_GRANDMASTER_IDENTITY, + + /* NTSCF header fields */ AVTP_NTSCF_FIELD_SV, - AVTP_NTSCF_FIELD_VERSION, + AVTP_NTSCF_FIELD_RESERVED, AVTP_NTSCF_FIELD_R, - /* NTSCF header fields */ AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH, - AVTP_NTSCF_FIELD_SEQUENCE_NUM, + AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB, AVTP_NTSCF_FIELD_STREAM_ID, + /* Count number of fields for bound checks */ AVTP_NTSCF_FIELD_MAX } Avtp_NtscfFields_t; /** - * This table maps all IEEE 1722 NTSCF-specific header fields to a descriptor. + * This table maps all IEEE 1722 NTSCF header fields to a descriptor for version + * 0. It is complete and in absolute coordinates; the alternative header fields + * are absent in version 0. */ -static const Avtp_FieldDescriptor_t Avtp_NtscfFieldDesc[AVTP_NTSCF_FIELD_MAX] = { - /* Common AVTP header */ - [AVTP_NTSCF_FIELD_SUBTYPE] = {.quadlet = 0, .offset = 0, .bits = 8}, +static const Avtp_FieldDescriptor_t Avtp_NtscfFieldDescV0[AVTP_NTSCF_FIELD_MAX] = { + [AVTP_NTSCF_FIELD_RESERVED1] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_NTSCF_FIELD_SEQUENCE_NUM] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_NTSCF_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 0, .offset = 0, .bits = 0}, [AVTP_NTSCF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, - [AVTP_NTSCF_FIELD_VERSION] = {.quadlet = 0, .offset = 9, .bits = 3}, + [AVTP_NTSCF_FIELD_RESERVED] = {.quadlet = 0, .offset = 0, .bits = 0}, [AVTP_NTSCF_FIELD_R] = {.quadlet = 0, .offset = 12, .bits = 1}, - /* NTSCF header */ [AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH] = {.quadlet = 0, .offset = 13, .bits = 11}, - [AVTP_NTSCF_FIELD_SEQUENCE_NUM] = {.quadlet = 0, .offset = 24, .bits = 8}, + [AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB] = {.quadlet = 0, .offset = 24, .bits = 8}, [AVTP_NTSCF_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, }; /** - * Return the value of an an NTSCF PDU SV field as specified in the IEEE 1722 Specification. + * This table maps all IEEE 1722 NTSCF header fields to a descriptor for version + * 1. It is complete and in absolute coordinates; the alternative header fields + * use the same positions as Avtp_AhFieldDescV1. + */ +static const Avtp_FieldDescriptor_t Avtp_NtscfFieldDescV1[AVTP_NTSCF_FIELD_MAX] = { + [AVTP_NTSCF_FIELD_RESERVED1] = {.quadlet = 0, .offset = 12, .bits = 20}, + [AVTP_NTSCF_FIELD_SEQUENCE_NUM] = {.quadlet = 1, .offset = 0, .bits = 32}, + [AVTP_NTSCF_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 2, .offset = 0, .bits = 64}, + [AVTP_NTSCF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, + [AVTP_NTSCF_FIELD_RESERVED] = {.quadlet = 4, .offset = 0, .bits = 12}, + [AVTP_NTSCF_FIELD_R] = {.quadlet = 4, .offset = 12, .bits = 1}, + [AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH] = {.quadlet = 4, .offset = 13, .bits = 11}, + [AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB] = {.quadlet = 4, .offset = 24, .bits = 8}, + [AVTP_NTSCF_FIELD_STREAM_ID] = {.quadlet = 5, .offset = 0, .bits = 64}, +}; + +/** + * Returns the value of an AVTP NTSCF field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 AVTP NTSCF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + */ +OPEN1722_INLINE uint64_t Avtp_Ntscf_GetField(const Avtp_Ntscf_t *const pdu, + Avtp_NtscfFields_t field) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_NtscfFieldDescV1 + : Avtp_NtscfFieldDescV0; + return Avtp_GetField(desc, AVTP_NTSCF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); +} + +/** + * Sets the value of an AVTP NTSCF field as specified in the IEEE 1722 Specification. * - * @param pdu Pointer to the first bit of an 1722 ACF Ntscf PDU. - * @returns Value of the NTSCF PDU SV field. + * @param pdu Pointer to the first bit of an 1722 AVTP NTSCF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + */ +OPEN1722_INLINE void Avtp_Ntscf_SetField(Avtp_Ntscf_t *pdu, Avtp_NtscfFields_t field, + uint64_t value) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_NtscfFieldDescV1 + : Avtp_NtscfFieldDescV0; + Avtp_SetField(desc, AVTP_NTSCF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Returns the length of the NTSCF header in octets (12 or 28). + */ +OPEN1722_INLINE uint8_t Avtp_Ntscf_GetHeaderLen(const Avtp_Ntscf_t *const pdu) +{ + return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1 + ? (uint8_t)AVTP_NTSCF_HEADER_LEN_V1 + : (uint8_t)AVTP_NTSCF_HEADER_LEN_V0; +} + +/** + * Return the value of the NTSCF SV field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @returns Value of the NTSCF SV field. */ OPEN1722_INLINE bool Avtp_Ntscf_IsSv(const Avtp_Ntscf_t *const pdu) { - return (bool)GET_NTSCF_FIELD(AVTP_NTSCF_FIELD_SV); + return (bool)Avtp_Ntscf_GetField(pdu, AVTP_NTSCF_FIELD_SV); } /** - * Return the value of an an NTSCF PDU Ntscf Data Length field as specified in the IEEE 1722 + * Return the value of the NTSCF Ntscf Data Length field as specified in the IEEE 1722 * Specification. * - * @param pdu Pointer to the first bit of an 1722 ACF Ntscf PDU. - * @returns Value of the NTSCF PDU Ntscf Data Length field. + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @returns Value of the NTSCF Ntscf Data Length field. */ OPEN1722_INLINE uint16_t Avtp_Ntscf_GetNtscfDataLength(const Avtp_Ntscf_t *const pdu) { - return (uint16_t)GET_NTSCF_FIELD(AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH); + return (uint16_t)Avtp_Ntscf_GetField(pdu, AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH); } /** - * Return the value of an an NTSCF PDU Sequence Number field as specified in the IEEE 1722 - * Specification. + * Return the effective NTSCF Sequence Number field as specified in the IEEE 1722 + * Specification. The field is the 8-bit sequence_num_lsb in version 0 and the + * 32-bit sequence_num in version 1. + * + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @returns Value of the NTSCF Sequence Number field. + */ +OPEN1722_INLINE uint32_t Avtp_Ntscf_GetSequenceNum(const Avtp_Ntscf_t *const pdu) +{ + if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1) { + return (uint32_t)Avtp_Ntscf_GetField(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM); + } + return (uint8_t)Avtp_Ntscf_GetField(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB); +} + +/** + * Return the value of the NTSCF sequence_num_lsb field. In version 1 it + * contains a copy of the eight least significant bits of the sequence_num + * field in the alternative header (NTSCF-6). + * + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @returns Value of the NTSCF sequence_num_lsb field. + */ +OPEN1722_INLINE uint8_t Avtp_Ntscf_GetSequenceNumLsb(const Avtp_Ntscf_t *const pdu) +{ + return (uint8_t)Avtp_Ntscf_GetField(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB); +} + +/** + * Return the value of the NTSCF ptp_grandmaster_identity field. The field only + * exists in version 1; version 0 returns 0. * - * @param pdu Pointer to the first bit of an 1722 ACF Ntscf PDU. - * @returns Value of the NTSCF PDU Sequence Number field. + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @returns Value of the NTSCF ptp_grandmaster_identity field. */ -OPEN1722_INLINE uint8_t Avtp_Ntscf_GetSequenceNum(const Avtp_Ntscf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Ntscf_GetPtpGrandmasterIdentity(const Avtp_Ntscf_t *const pdu) { - return (uint8_t)GET_NTSCF_FIELD(AVTP_NTSCF_FIELD_SEQUENCE_NUM); + return Avtp_Ntscf_GetField(pdu, AVTP_NTSCF_FIELD_PTP_GRANDMASTER_IDENTITY); } /** - * Return the value of an an NTSCF PDU Stream ID field as specified in the IEEE 1722 Specification. + * Return the value of the NTSCF Stream ID field as specified in the IEEE 1722 Specification. * - * @param pdu Pointer to the first bit of an 1722 ACF Ntscf PDU. - * @returns Value of the NTSCF PDU Stream ID field. + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @returns Value of the NTSCF Stream ID field. */ OPEN1722_INLINE uint64_t Avtp_Ntscf_GetStreamId(const Avtp_Ntscf_t *const pdu) { - return (uint64_t)GET_NTSCF_FIELD(AVTP_NTSCF_FIELD_STREAM_ID); + return Avtp_Ntscf_GetField(pdu, AVTP_NTSCF_FIELD_STREAM_ID); } /** * Set the SV bit in an ACF Ntscf frame as specified in the IEEE 1722 Specification. * - * @param pdu Pointer to the first bit of an 1722 ACF Ntscf PDU. + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. * @param sv Value to set the NTSCF PDU SV field to. */ OPEN1722_INLINE void Avtp_Ntscf_SetSv(Avtp_Ntscf_t *pdu, bool sv) { - SET_NTSCF_FIELD(AVTP_NTSCF_FIELD_SV, sv); + Avtp_Ntscf_SetField(pdu, AVTP_NTSCF_FIELD_SV, sv); } /** - * Set the value of an an NTSCF PDU Ntscf Data Length field as specified in the IEEE 1722 + * Set the value of the NTSCF Ntscf Data Length field as specified in the IEEE 1722 * Specification. * - * @param pdu Pointer to the first bit of an 1722 ACF Ntscf PDU. + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. * @param value Value to set the NTSCF PDU Ntscf Data Length field to. */ OPEN1722_INLINE void Avtp_Ntscf_SetNtscfDataLength(Avtp_Ntscf_t *pdu, uint16_t value) { - SET_NTSCF_FIELD(AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH, value); + Avtp_Ntscf_SetField(pdu, AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH, value); } /** - * Set the value of an an NTSCF PDU Sequence Number field as specified in the IEEE 1722 - * Specification. + * Set the effective NTSCF Sequence Number field as specified in the IEEE 1722 + * Specification. In version 1 the eight least significant bits are also written + * to the sequence_num_lsb copy (NTSCF-6); in version 0 they are the sequence + * number itself. * - * @param pdu Pointer to the first bit of an 1722 ACF Ntscf PDU. + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. * @param value Value to set the NTSCF PDU Sequence Number field to. */ -OPEN1722_INLINE void Avtp_Ntscf_SetSequenceNum(Avtp_Ntscf_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Ntscf_SetSequenceNum(Avtp_Ntscf_t *pdu, uint32_t value) { - SET_NTSCF_FIELD(AVTP_NTSCF_FIELD_SEQUENCE_NUM, value); + /* No-op on version 0: the field only exists in the alternative header v1. */ + Avtp_Ntscf_SetField(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM, value); + Avtp_Ntscf_SetField(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); } /** - * Set the value of an an NTSCF PDU Stream ID field as specified in the IEEE 1722 Specification. + * Set the value of the NTSCF ptp_grandmaster_identity field. The field only + * exists in version 1; on version 0 this is a no-op. * - * @param pdu Pointer to the first bit of an 1722 ACF Ntscf PDU. + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @param value Value to set the NTSCF PDU ptp_grandmaster_identity field to. + */ +OPEN1722_INLINE void Avtp_Ntscf_SetPtpGrandmasterIdentity(Avtp_Ntscf_t *pdu, uint64_t value) +{ + Avtp_Ntscf_SetField(pdu, AVTP_NTSCF_FIELD_PTP_GRANDMASTER_IDENTITY, value); +} + +/** + * Set the value of the NTSCF Stream ID field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. * @param value Value to set the NTSCF PDU Stream ID field to. */ OPEN1722_INLINE void Avtp_Ntscf_SetStreamId(Avtp_Ntscf_t *pdu, uint64_t value) { - SET_NTSCF_FIELD(AVTP_NTSCF_FIELD_STREAM_ID, value); + Avtp_Ntscf_SetField(pdu, AVTP_NTSCF_FIELD_STREAM_ID, value); +} + +/** + * Returns pointer to the payload of an NTSCF frame. The payload starts after + * the version-dependent NTSCF header. + * + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @return Pointer to the NTSCF frame payload. + */ +OPEN1722_INLINE const uint8_t *Avtp_Ntscf_GetPayload(const Avtp_Ntscf_t *const pdu) +{ + return (const uint8_t *)pdu + Avtp_Ntscf_GetHeaderLen(pdu); +} + +/** + * Sets the NTSCF payload. + * + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @param payload Pointer to the payload byte array. + * @param payload_length Length of the payload. + */ +OPEN1722_INLINE void Avtp_Ntscf_SetPayload(Avtp_Ntscf_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + Avtp_Ntscf_GetHeaderLen(pdu), payload, payload_length); } /** * Checks if the ACF Ntscf frame is valid by checking: - * 1) if the length field of AVTP/ACF messages contains a value larger than the actual size of - * the buffer that contains the AVTP message. 2) if other format specific invariants are not upheld - * @param pdu Pointer to the first bit of an 1722 ACF Ntscf PDU. - * @param bufferSize Size of the buffer containing the ACF Ntscf frame. - * @return true if the ACF Ntscf frame is valid, false otherwise. + * 1) that the subtype is NTSCF and the version is supported, + * 2) that the version-dependent header fits into the buffer, + * 3) that the declared ntscf_data_length fits into the buffer. + * + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @param bufferSize Size of the buffer containing the ACF NTSCF frame. + * @return true if the ACF NTSCF frame is valid, false otherwise. */ OPEN1722_INLINE bool Avtp_Ntscf_IsValid(const Avtp_Ntscf_t *const pdu, size_t bufferSize) { @@ -197,16 +354,22 @@ OPEN1722_INLINE bool Avtp_Ntscf_IsValid(const Avtp_Ntscf_t *const pdu, size_t bu return false; } - if (bufferSize < AVTP_NTSCF_HEADER_LEN) { + if (Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu) != AVTP_SUBTYPE_NTSCF) { return false; } - if (Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu) != AVTP_SUBTYPE_NTSCF) { + uint8_t version = Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu); + if (!Avtp_Version_IsSupported(AVTP_NTSCF_SUPPORTED_VERSIONS, version)) { + return false; + } + + size_t headerLen = Avtp_Ntscf_GetHeaderLen(pdu); + if (bufferSize < headerLen) { return false; } // Avtp_Ntscf_GetNtscfDataLength returns the payload length in octets. - if (Avtp_Ntscf_GetNtscfDataLength(pdu) > bufferSize) { + if ((size_t)Avtp_Ntscf_GetNtscfDataLength(pdu) > bufferSize - headerLen) { return false; } @@ -214,7 +377,7 @@ OPEN1722_INLINE bool Avtp_Ntscf_IsValid(const Avtp_Ntscf_t *const pdu, size_t bu } /** - * Initializes a NTSCF PDU as specified in the IEEE 1722-2016 Specification. + * Initializes a version 0 NTSCF PDU as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- * or an ACF header. @@ -229,30 +392,20 @@ OPEN1722_INLINE void Avtp_Ntscf_Init(Avtp_Ntscf_t *pdu) } /** - * Returns the value of an an AVTP NTSCF field as specified in the IEEE 1722 Specification. + * Initializes a version 1 NTSCF PDU. The caller must provide a buffer of at + * least AVTP_NTSCF_HEADER_LEN_V1 octets. * - * @param pdu Pointer to the first bit of an 1722 AVTP NTSCF PDU. - * @param field Specifies the position of the data field to be read - * @param value Pointer to location to store the value. - * @returns This function returns the value of the field. - */ -OPEN1722_INLINE uint64_t Avtp_Ntscf_GetField(const Avtp_Ntscf_t *const pdu, - Avtp_NtscfFields_t field) -{ - return (uint64_t)GET_NTSCF_FIELD(field); -} - -/** - * Sets the value of an an AVTP NTSCF field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 AVTP NTSCF PDU. - * @param field Specifies the position of the data field to be read - * @param value Pointer to location to store the value. + * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- + * or an ACF header. */ -OPEN1722_INLINE void Avtp_Ntscf_SetField(Avtp_Ntscf_t *pdu, Avtp_NtscfFields_t field, - uint64_t value) +OPEN1722_INLINE void Avtp_Ntscf_InitV1(Avtp_NtscfV1_t *pdu) { - SET_NTSCF_FIELD(field, value); + if (pdu != NULL) { + memset(pdu, 0, sizeof(Avtp_NtscfV1_t)); + Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_NTSCF); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_Ntscf_SetSv((Avtp_Ntscf_t *)pdu, true); + } } #ifdef __cplusplus diff --git a/src/avtp/export/InlineExports.c b/src/avtp/export/InlineExports.c index 4f903c79..672219d0 100644 --- a/src/avtp/export/InlineExports.c +++ b/src/avtp/export/InlineExports.c @@ -54,6 +54,7 @@ #include "avtp/CommonHeader.h" #include "avtp/CommonStreamHeader.h" +#include "avtp/AlternativeHeader.h" #include "avtp/Udp.h" #include "avtp/Crf.h" diff --git a/unit/test-crf.c b/unit/test-crf.c index 1c4a518b..e22df76a 100644 --- a/unit/test-crf.c +++ b/unit/test-crf.c @@ -42,6 +42,7 @@ extern "C" { #include #include "avtp/CommonHeader.h" +#include "avtp/AlternativeHeader.h" #include "avtp/Crf.h" #define MAX_PDU_SIZE 1500 @@ -66,18 +67,38 @@ static void crf_init(void **state) { (void)state; uint8_t pdu[MAX_PDU_SIZE]; - uint8_t init_pdu[AVTP_CRF_HEADER_LEN]; + uint8_t init_pdu[AVTP_CRF_HEADER_LEN_V0]; - assert_int_equal(sizeof(Avtp_Crf_t), AVTP_CRF_HEADER_LEN); + assert_int_equal(sizeof(Avtp_Crf_t), AVTP_CRF_HEADER_LEN_V0); /* Passing a NULL pointer must be a no-op. */ Avtp_Crf_Init(NULL); Avtp_Crf_Init((Avtp_Crf_t *)pdu); - memset(init_pdu, 0, AVTP_CRF_HEADER_LEN); + memset(init_pdu, 0, AVTP_CRF_HEADER_LEN_V0); init_pdu[0] = AVTP_SUBTYPE_CRF; /* subtype = CRF */ - init_pdu[1] = 0x80; /* sv = 1 */ - assert_memory_equal(init_pdu, pdu, AVTP_CRF_HEADER_LEN); + init_pdu[1] = 0x80; /* sv = 1, version = 0 */ + assert_memory_equal(init_pdu, pdu, AVTP_CRF_HEADER_LEN_V0); +} + +static void crf_init_v1(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t init_pdu[AVTP_CRF_HEADER_LEN_V1]; + + assert_int_equal(sizeof(Avtp_CrfV1_t), AVTP_CRF_HEADER_LEN_V1); + + /* Passing a NULL pointer must be a no-op. */ + Avtp_Crf_InitV1(NULL); + + Avtp_Crf_InitV1((Avtp_CrfV1_t *)pdu); + memset(init_pdu, 0, AVTP_CRF_HEADER_LEN_V1); + init_pdu[0] = AVTP_SUBTYPE_CRF; /* subtype = CRF */ + init_pdu[1] = 0x90; /* sv = 1, version = 1 */ + assert_memory_equal(init_pdu, pdu, AVTP_CRF_HEADER_LEN_V1); + + assert_int_equal(Avtp_Crf_GetHeaderLen((Avtp_Crf_t *)pdu), AVTP_CRF_HEADER_LEN_V1); } static void crf_is_valid(void **state) @@ -87,7 +108,7 @@ static void crf_is_valid(void **state) Avtp_Crf_t *crf = (Avtp_Crf_t *)pdu; init_valid_crf(crf); - assert_true(Avtp_Crf_IsValid(crf, AVTP_CRF_HEADER_LEN + 8)); + assert_true(Avtp_Crf_IsValid(crf, AVTP_CRF_HEADER_LEN_V0 + 8)); /* NULL pdu. */ assert_false(Avtp_Crf_IsValid(NULL, MAX_PDU_SIZE)); @@ -98,44 +119,99 @@ static void crf_is_valid(void **state) /* Buffer smaller than the CRF header. */ init_valid_crf(crf); - assert_false(Avtp_Crf_IsValid(crf, AVTP_CRF_HEADER_LEN - 1)); + assert_false(Avtp_Crf_IsValid(crf, AVTP_CRF_HEADER_LEN_V0 - 1)); /* crf_data_length shall be a non-zero multiple of 8. */ init_valid_crf(crf); Avtp_Crf_SetCrfDataLength(crf, 0); - assert_false(Avtp_Crf_IsValid(crf, AVTP_CRF_HEADER_LEN)); + assert_false(Avtp_Crf_IsValid(crf, AVTP_CRF_HEADER_LEN_V0)); Avtp_Crf_SetCrfDataLength(crf, 7); - assert_false(Avtp_Crf_IsValid(crf, AVTP_CRF_HEADER_LEN + 8)); + assert_false(Avtp_Crf_IsValid(crf, AVTP_CRF_HEADER_LEN_V0 + 8)); /* crf_data_length does not fit into the buffer. */ init_valid_crf(crf); Avtp_Crf_SetCrfDataLength(crf, 16); - assert_false(Avtp_Crf_IsValid(crf, AVTP_CRF_HEADER_LEN + 15)); - assert_true(Avtp_Crf_IsValid(crf, AVTP_CRF_HEADER_LEN + 16)); + assert_false(Avtp_Crf_IsValid(crf, AVTP_CRF_HEADER_LEN_V0 + 15)); + assert_true(Avtp_Crf_IsValid(crf, AVTP_CRF_HEADER_LEN_V0 + 16)); + + /* Valid version 1 frame. */ + Avtp_Crf_InitV1((Avtp_CrfV1_t *)pdu); + Avtp_Crf_SetCrfDataLength((Avtp_Crf_t *)pdu, 8); + assert_true(Avtp_Crf_IsValid((Avtp_Crf_t *)pdu, AVTP_CRF_HEADER_LEN_V1 + 8)); + assert_false(Avtp_Crf_IsValid((Avtp_Crf_t *)pdu, AVTP_CRF_HEADER_LEN_V1 + 7)); + assert_false(Avtp_Crf_IsValid((Avtp_Crf_t *)pdu, AVTP_CRF_HEADER_LEN_V1 - 1)); + + /* Unsupported version is rejected. */ + init_valid_crf(crf); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, 2); + assert_false(Avtp_Crf_IsValid(crf, MAX_PDU_SIZE)); } -static void crf_field_descriptors_cover_header(void **state) +static void mark_descriptors(uint8_t *coverage, size_t coverageBits, + const Avtp_FieldDescriptor_t *desc, uint8_t numFields) { - (void)state; - uint8_t coverage[AVTP_CRF_HEADER_LEN * 8] = {0}; - - /* Every bit of the header must be described exactly once. */ - for (uint8_t i = 0; i < AVTP_CRF_FIELD_MAX; i++) { - uint8_t quadlet = Avtp_CrfFieldDesc[i].quadlet; - uint8_t offset = Avtp_CrfFieldDesc[i].offset; - uint8_t bits = Avtp_CrfFieldDesc[i].bits; + for (uint8_t i = 0; i < numFields; i++) { + uint8_t bits = desc[i].bits; + uint8_t offset = desc[i].offset; + uint8_t quadlet = desc[i].quadlet; for (uint8_t b = 0; b < bits; b++) { size_t bit = ((size_t)quadlet * 32) + offset + b; - assert_true(bit < sizeof(coverage)); + assert_true(bit < coverageBits); assert_int_equal(coverage[bit], 0); coverage[bit] = 1; } } +} + +static void crf_field_descriptors_cover_header(void **state) +{ + (void)state; + + for (uint8_t version = 0; version <= 1; version++) { + uint8_t coverage[AVTP_CRF_HEADER_LEN_V1 * 8] = {0}; + size_t coverageBits = sizeof(coverage); + const Avtp_FieldDescriptor_t *crfDesc = + version == AVTP_VERSION_1 ? Avtp_CrfFieldDescV1 : Avtp_CrfFieldDescV0; + size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_CRF_HEADER_LEN_V1 + : (size_t)AVTP_CRF_HEADER_LEN_V0) * + 8; + + /* subtype and version are owned by the common header; h/sv is covered + * by the format table. */ + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_SUBTYPE], 1); + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_VERSION], 1); + mark_descriptors(coverage, coverageBits, crfDesc, AVTP_CRF_FIELD_MAX); + + for (size_t bit = 0; bit < coverageBits; bit++) { + assert_int_equal(coverage[bit], bit < headerBits ? 1 : 0); + } + } +} + +static void crf_ah_field_consistency(void **state) +{ + (void)state; - for (size_t bit = 0; bit < sizeof(coverage); bit++) { - assert_int_equal(coverage[bit], 1); + /* The alternative header fields must be declared first and in the same + * order as in the alternative header module. */ + assert_int_equal(AVTP_CRF_FIELD_PTP_GRANDMASTER_IDENTITY, + AVTPDU_AH_FIELD_PTP_GRANDMASTER_IDENTITY); + + for (uint8_t version = 0; version <= 1; version++) { + const Avtp_FieldDescriptor_t *crfDesc = + version == AVTP_VERSION_1 ? Avtp_CrfFieldDescV1 : Avtp_CrfFieldDescV0; + const Avtp_FieldDescriptor_t *ahDesc = + version == AVTP_VERSION_1 ? Avtp_AhFieldDescV1 : Avtp_AhFieldDescV0; + + for (uint8_t i = 0; i < AVTPDU_AH_FIELD_MAX; i++) { + assert_int_equal(crfDesc[i].quadlet, ahDesc[i].quadlet); + assert_int_equal(crfDesc[i].offset, ahDesc[i].offset); + assert_int_equal(crfDesc[i].bits, ahDesc[i].bits); + } } } @@ -177,6 +253,7 @@ static void crf_field_layout(void **state) Avtp_Crf_SetSequenceNum(crf, 0xBB); assert_int_equal(Avtp_Crf_GetSequenceNum(crf), 0xBB); + assert_int_equal(Avtp_Crf_GetSequenceNumLsb(crf), 0xBB); assert_int_equal(read_quadlet(pdu, 0), 0x0000BB00); Avtp_Crf_SetType(crf, AVTP_CRF_TYPE_VIDEO_LINE); @@ -207,6 +284,46 @@ static void crf_field_layout(void **state) Avtp_Crf_SetTimestampInterval(crf, 0x1234); assert_int_equal(Avtp_Crf_GetTimestampInterval(crf), 0x1234); assert_int_equal(read_quadlet(pdu, 4), 0xABCD1234); + + /* ptp_grandmaster_identity does not exist in version 0. */ + assert_int_equal(Avtp_Crf_GetPtpGrandmasterIdentity(crf), 0); +} + +static void crf_v1_layout(void **state) +{ + (void)state; + uint8_t pdu[AVTP_CRF_HEADER_LEN_V1]; + Avtp_Crf_t *crf = (Avtp_Crf_t *)pdu; + + Avtp_Crf_InitV1((Avtp_CrfV1_t *)pdu); + + Avtp_Crf_SetSequenceNum(crf, 0x12345678); + assert_int_equal(Avtp_Crf_GetSequenceNum(crf), 0x12345678); + assert_int_equal(Avtp_Crf_GetSequenceNumLsb(crf), 0x78); + assert_int_equal(read_quadlet(pdu, 1), 0x12345678); + assert_int_equal(pdu[18], 0x78); /* sequence_num_lsb at q4@16 */ + + Avtp_Crf_SetPtpGrandmasterIdentity(crf, 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Crf_GetPtpGrandmasterIdentity(crf), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(read_quadlet(pdu, 2), 0x99AABBCC); + assert_int_equal(read_quadlet(pdu, 3), 0xDDEEFF00); + + Avtp_Crf_SetType(crf, AVTP_CRF_TYPE_VIDEO_LINE); + assert_int_equal(Avtp_Crf_GetType(crf), AVTP_CRF_TYPE_VIDEO_LINE); + assert_int_equal(read_quadlet(pdu, 4), 0x00007803); /* type plus seq_lsb copy */ + + Avtp_Crf_SetStreamId(crf, 0x0102030405060708ULL); + assert_int_equal(Avtp_Crf_GetStreamId(crf), 0x0102030405060708ULL); + assert_int_equal(read_quadlet(pdu, 5), 0x01020304); + assert_int_equal(read_quadlet(pdu, 6), 0x05060708); + + Avtp_Crf_SetPull(crf, AVTP_CRF_PULL_MULT_BY_1_001); + Avtp_Crf_SetBaseFrequency(crf, 0x1FFFFFFF); + assert_int_equal(read_quadlet(pdu, 7), 0x5FFFFFFF); + + Avtp_Crf_SetCrfDataLength(crf, 0xABCD); + Avtp_Crf_SetTimestampInterval(crf, 0x1234); + assert_int_equal(read_quadlet(pdu, 8), 0xABCD1234); } static void crf_payload(void **state) @@ -220,11 +337,18 @@ static void crf_payload(void **state) Avtp_Crf_Init(crf); Avtp_Crf_SetPayload(crf, payload, sizeof(payload)); - assert_memory_equal(Avtp_Crf_GetPayload(crf), payload, sizeof(payload)); - assert_memory_equal(crf->payload, payload, sizeof(payload)); + assert_ptr_equal(Avtp_Crf_GetPayload(crf), pdu + AVTP_CRF_HEADER_LEN_V0); + assert_memory_equal(pdu + AVTP_CRF_HEADER_LEN_V0, payload, sizeof(payload)); memcpy(payload_out, Avtp_Crf_GetPayload(crf), sizeof(payload_out)); assert_memory_equal(payload_out, payload, sizeof(payload_out)); + + /* Version 1 payload starts after the 36-octet header. */ + Avtp_Crf_InitV1((Avtp_CrfV1_t *)pdu); + Avtp_Crf_SetPayload((Avtp_Crf_t *)pdu, payload, sizeof(payload)); + + assert_ptr_equal(Avtp_Crf_GetPayload((Avtp_Crf_t *)pdu), pdu + AVTP_CRF_HEADER_LEN_V1); + assert_memory_equal(pdu + AVTP_CRF_HEADER_LEN_V1, payload, sizeof(payload)); } static void crf_get_set_field(void **state) @@ -235,8 +359,8 @@ static void crf_get_set_field(void **state) memset(pdu, 0, MAX_PDU_SIZE); - Avtp_Crf_SetField(crf, AVTP_CRF_FIELD_SEQUENCE_NUM, 0xAA); - assert_int_equal(Avtp_Crf_GetField(crf, AVTP_CRF_FIELD_SEQUENCE_NUM), 0xAA); + Avtp_Crf_SetField(crf, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB, 0xAA); + assert_int_equal(Avtp_Crf_GetField(crf, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB), 0xAA); /* Reserved fields are reachable through the generic access engine. */ Avtp_Crf_SetField(crf, AVTP_CRF_FIELD_R, 0x1); @@ -247,10 +371,13 @@ int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(crf_init), + cmocka_unit_test(crf_init_v1), cmocka_unit_test(crf_is_valid), cmocka_unit_test(crf_field_descriptors_cover_header), + cmocka_unit_test(crf_ah_field_consistency), cmocka_unit_test(crf_flag_fields), cmocka_unit_test(crf_field_layout), + cmocka_unit_test(crf_v1_layout), cmocka_unit_test(crf_payload), cmocka_unit_test(crf_get_set_field), }; diff --git a/unit/test-ntscf.c b/unit/test-ntscf.c index b340a770..81a180db 100644 --- a/unit/test-ntscf.c +++ b/unit/test-ntscf.c @@ -38,64 +38,264 @@ extern "C" { #include #endif #include -#include #include -#include -#include -#include "avtp/acf/Ntscf.h" #include "avtp/CommonHeader.h" +#include "avtp/AlternativeHeader.h" +#include "avtp/acf/Ntscf.h" #define MAX_PDU_SIZE 1500 -static void ntscf_init(void **state) +static uint32_t read_quadlet(const uint8_t *pdu, size_t quadlet) { + uint32_t word; + + memcpy(&word, pdu + (quadlet * 4), sizeof(word)); + return ntohl(word); +} +static void ntscf_init(void **state) +{ + (void)state; uint8_t pdu[MAX_PDU_SIZE]; - uint8_t init_pdu[AVTP_NTSCF_HEADER_LEN]; + uint8_t init_pdu[AVTP_NTSCF_HEADER_LEN_V0]; - // Check the lengths - assert_int_equal(sizeof(Avtp_Ntscf_t), AVTP_NTSCF_HEADER_LEN); + assert_int_equal(sizeof(Avtp_Ntscf_t), AVTP_NTSCF_HEADER_LEN_V0); - // Check init function while passing in a null pointer + /* Passing a NULL pointer must be a no-op. */ Avtp_Ntscf_Init(NULL); - // Check if the function is initializing properly Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); - memset(init_pdu, 0, AVTP_NTSCF_HEADER_LEN); - init_pdu[0] = AVTP_SUBTYPE_NTSCF; // Setting AVTP Subtype as NTSCF - init_pdu[1] = 0x80; // Setting Stream as valid - assert_memory_equal(init_pdu, pdu, AVTP_NTSCF_HEADER_LEN); + memset(init_pdu, 0, AVTP_NTSCF_HEADER_LEN_V0); + init_pdu[0] = AVTP_SUBTYPE_NTSCF; /* subtype = NTSCF */ + init_pdu[1] = 0x80; /* sv = 1, version = 0 */ + assert_memory_equal(init_pdu, pdu, AVTP_NTSCF_HEADER_LEN_V0); } -static void ntscf_is_valid(void **state) +static void ntscf_init_v1(void **state) { + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t init_pdu[AVTP_NTSCF_HEADER_LEN_V1]; - uint8_t pdu[MAX_PDU_SIZE], result; + assert_int_equal(sizeof(Avtp_NtscfV1_t), AVTP_NTSCF_HEADER_LEN_V1); - // Valid IEEE 1722 NTSCF Frame + /* Passing a NULL pointer must be a no-op. */ + Avtp_Ntscf_InitV1(NULL); + + Avtp_Ntscf_InitV1((Avtp_NtscfV1_t *)pdu); + memset(init_pdu, 0, AVTP_NTSCF_HEADER_LEN_V1); + init_pdu[0] = AVTP_SUBTYPE_NTSCF; /* subtype = NTSCF */ + init_pdu[1] = 0x90; /* sv = 1, version = 1 */ + assert_memory_equal(init_pdu, pdu, AVTP_NTSCF_HEADER_LEN_V1); + + assert_int_equal(Avtp_Ntscf_GetHeaderLen((Avtp_Ntscf_t *)pdu), AVTP_NTSCF_HEADER_LEN_V1); +} + +static void ntscf_is_valid(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + + /* Valid version 0 frame with no payload. */ Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); - assert_int_equal(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, MAX_PDU_SIZE), 1); + assert_true(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, AVTP_NTSCF_HEADER_LEN_V0)); - // Not a IEEE 1722 NTSCF Frame + /* Not an NTSCF frame. */ memset(pdu, 0, MAX_PDU_SIZE); - assert_int_equal(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, MAX_PDU_SIZE), 0); + assert_false(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, MAX_PDU_SIZE)); - // Valid IEEE 1722 NTSCF Frame (Length 28, Buffer 30) + /* Buffer smaller than the version 0 header. */ + Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); + assert_false(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, AVTP_NTSCF_HEADER_LEN_V0 - 1)); + + /* ntscf_data_length must fit after the header. */ Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); Avtp_Ntscf_SetNtscfDataLength((Avtp_Ntscf_t *)pdu, 28); - assert_int_equal(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, 30), 1); + assert_false(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, AVTP_NTSCF_HEADER_LEN_V0 + 27)); + assert_true(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, AVTP_NTSCF_HEADER_LEN_V0 + 28)); + + /* Valid version 1 frame. */ + Avtp_Ntscf_InitV1((Avtp_NtscfV1_t *)pdu); + assert_true(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, AVTP_NTSCF_HEADER_LEN_V1)); + assert_false(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, AVTP_NTSCF_HEADER_LEN_V1 - 1)); + + /* Unsupported version is rejected. */ + Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, 2); + assert_false(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, MAX_PDU_SIZE)); +} + +static void mark_descriptors(uint8_t *coverage, size_t coverageBits, + const Avtp_FieldDescriptor_t *desc, uint8_t numFields) +{ + for (uint8_t i = 0; i < numFields; i++) { + uint8_t bits = desc[i].bits; + uint8_t offset = desc[i].offset; + uint8_t quadlet = desc[i].quadlet; + + for (uint8_t b = 0; b < bits; b++) { + size_t bit = ((size_t)quadlet * 32) + offset + b; + + assert_true(bit < coverageBits); + assert_int_equal(coverage[bit], 0); + coverage[bit] = 1; + } + } +} + +static void ntscf_field_descriptors_cover_header(void **state) +{ + (void)state; + + for (uint8_t version = 0; version <= 1; version++) { + uint8_t coverage[AVTP_NTSCF_HEADER_LEN_V1 * 8] = {0}; + size_t coverageBits = sizeof(coverage); + const Avtp_FieldDescriptor_t *ntscfDesc = + version == AVTP_VERSION_1 ? Avtp_NtscfFieldDescV1 : Avtp_NtscfFieldDescV0; + size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_NTSCF_HEADER_LEN_V1 + : (size_t)AVTP_NTSCF_HEADER_LEN_V0) * + 8; + + /* subtype and version are owned by the common header; h/sv is covered + * by the format table. */ + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_SUBTYPE], 1); + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_VERSION], 1); + mark_descriptors(coverage, coverageBits, ntscfDesc, AVTP_NTSCF_FIELD_MAX); + + for (size_t bit = 0; bit < coverageBits; bit++) { + assert_int_equal(coverage[bit], bit < headerBits ? 1 : 0); + } + } +} + +static void ntscf_ah_field_consistency(void **state) +{ + (void)state; + + /* The alternative header fields must be declared first and in the same + * order as in the alternative header module. */ + assert_int_equal(AVTP_NTSCF_FIELD_PTP_GRANDMASTER_IDENTITY, + AVTPDU_AH_FIELD_PTP_GRANDMASTER_IDENTITY); + + for (uint8_t version = 0; version <= 1; version++) { + const Avtp_FieldDescriptor_t *ntscfDesc = + version == AVTP_VERSION_1 ? Avtp_NtscfFieldDescV1 : Avtp_NtscfFieldDescV0; + const Avtp_FieldDescriptor_t *ahDesc = + version == AVTP_VERSION_1 ? Avtp_AhFieldDescV1 : Avtp_AhFieldDescV0; + + for (uint8_t i = 0; i < AVTPDU_AH_FIELD_MAX; i++) { + assert_int_equal(ntscfDesc[i].quadlet, ahDesc[i].quadlet); + assert_int_equal(ntscfDesc[i].offset, ahDesc[i].offset); + assert_int_equal(ntscfDesc[i].bits, ahDesc[i].bits); + } + } +} + +static void ntscf_field_layout(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + Avtp_Ntscf_t *ntscf = (Avtp_Ntscf_t *)pdu; + + memset(pdu, 0, MAX_PDU_SIZE); + Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)ntscf, AVTP_SUBTYPE_NTSCF); + + Avtp_Ntscf_SetSequenceNum(ntscf, 0xAB); + assert_int_equal(Avtp_Ntscf_GetSequenceNum(ntscf), 0xAB); + assert_int_equal(Avtp_Ntscf_GetSequenceNumLsb(ntscf), 0xAB); + assert_int_equal(read_quadlet(pdu, 0), 0x820000AB); + + Avtp_Ntscf_SetNtscfDataLength(ntscf, 0x123); + assert_int_equal(Avtp_Ntscf_GetNtscfDataLength(ntscf), 0x123); + assert_int_equal(read_quadlet(pdu, 0), 0x820123AB); + + Avtp_Ntscf_SetStreamId(ntscf, 0xAABBCCDDEEFF0001ULL); + assert_int_equal(Avtp_Ntscf_GetStreamId(ntscf), 0xAABBCCDDEEFF0001ULL); + assert_int_equal(read_quadlet(pdu, 1), 0xAABBCCDD); + assert_int_equal(read_quadlet(pdu, 2), 0xEEFF0001); + + /* ptp_grandmaster_identity does not exist in version 0. */ + assert_int_equal(Avtp_Ntscf_GetPtpGrandmasterIdentity(ntscf), 0); +} + +static void ntscf_v1_layout(void **state) +{ + (void)state; + uint8_t pdu[AVTP_NTSCF_HEADER_LEN_V1]; + Avtp_Ntscf_t *ntscf = (Avtp_Ntscf_t *)pdu; + + Avtp_Ntscf_InitV1((Avtp_NtscfV1_t *)pdu); + + Avtp_Ntscf_SetSequenceNum(ntscf, 0x12345678); + assert_int_equal(Avtp_Ntscf_GetSequenceNum(ntscf), 0x12345678); + assert_int_equal(Avtp_Ntscf_GetSequenceNumLsb(ntscf), 0x78); + assert_int_equal(read_quadlet(pdu, 1), 0x12345678); + assert_int_equal(pdu[19], 0x78); /* sequence_num_lsb at q4@24 */ + + Avtp_Ntscf_SetPtpGrandmasterIdentity(ntscf, 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Ntscf_GetPtpGrandmasterIdentity(ntscf), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(read_quadlet(pdu, 2), 0x99AABBCC); + assert_int_equal(read_quadlet(pdu, 3), 0xDDEEFF00); + + Avtp_Ntscf_SetNtscfDataLength(ntscf, 0x123); + assert_int_equal(Avtp_Ntscf_GetNtscfDataLength(ntscf), 0x123); + assert_int_equal(read_quadlet(pdu, 4), 0x00012378); + + Avtp_Ntscf_SetStreamId(ntscf, 0x0102030405060708ULL); + assert_int_equal(Avtp_Ntscf_GetStreamId(ntscf), 0x0102030405060708ULL); + assert_int_equal(read_quadlet(pdu, 5), 0x01020304); + assert_int_equal(read_quadlet(pdu, 6), 0x05060708); +} + +static void ntscf_payload(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t payload[4] = {0xDE, 0xAD, 0xBE, 0xEF}; - // Invalid IEEE 1722 NTSCF Frame (Length 24 but buffer only 9!) Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); - Avtp_Ntscf_SetNtscfDataLength((Avtp_Ntscf_t *)pdu, 24); - assert_int_equal(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, 9), 0); + assert_ptr_equal(Avtp_Ntscf_GetPayload((Avtp_Ntscf_t *)pdu), pdu + AVTP_NTSCF_HEADER_LEN_V0); + Avtp_Ntscf_SetPayload((Avtp_Ntscf_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_NTSCF_HEADER_LEN_V0, payload, sizeof(payload)); + + Avtp_Ntscf_InitV1((Avtp_NtscfV1_t *)pdu); + assert_ptr_equal(Avtp_Ntscf_GetPayload((Avtp_Ntscf_t *)pdu), pdu + AVTP_NTSCF_HEADER_LEN_V1); + Avtp_Ntscf_SetPayload((Avtp_Ntscf_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_NTSCF_HEADER_LEN_V1, payload, sizeof(payload)); +} + +static void ntscf_get_set_field(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + Avtp_Ntscf_t *ntscf = (Avtp_Ntscf_t *)pdu; + + memset(pdu, 0, MAX_PDU_SIZE); + + Avtp_Ntscf_SetField(ntscf, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB, 0xAA); + assert_int_equal(Avtp_Ntscf_GetField(ntscf, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB), 0xAA); + + /* Reserved fields are reachable through the generic access engine. */ + Avtp_Ntscf_SetField(ntscf, AVTP_NTSCF_FIELD_R, 0x1); + assert_int_equal(Avtp_Ntscf_GetField(ntscf, AVTP_NTSCF_FIELD_R), 0x1); } int main(void) { - const struct CMUnitTest tests[] = {cmocka_unit_test(ntscf_init), - cmocka_unit_test(ntscf_is_valid)}; + const struct CMUnitTest tests[] = { + cmocka_unit_test(ntscf_init), + cmocka_unit_test(ntscf_init_v1), + cmocka_unit_test(ntscf_is_valid), + cmocka_unit_test(ntscf_field_descriptors_cover_header), + cmocka_unit_test(ntscf_ah_field_consistency), + cmocka_unit_test(ntscf_field_layout), + cmocka_unit_test(ntscf_v1_layout), + cmocka_unit_test(ntscf_payload), + cmocka_unit_test(ntscf_get_set_field), + }; return cmocka_run_group_tests(tests, NULL, NULL); } From 1c7d6fb9c5a57ef2ca8dde72f71b71120652e5fc Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Sat, 19 Sep 2026 13:39:59 +0200 Subject: [PATCH 07/16] Add NTSCFv1 support to can bridge and talker Signed-off-by: Sebastian Schildt --- examples/acf-can/acf-can-common.c | 31 ++++++++++++++++-------- examples/acf-can/acf-can-common.h | 7 +++--- examples/acf-can/linux/README.md | 14 +++++++---- examples/acf-can/linux/acf-can-bridge.c | 24 +++++++++++++++--- examples/acf-can/linux/acf-can-talker.c | 24 +++++++++++++++--- examples/acf-can/zephyr/Kconfig | 4 +++ examples/acf-can/zephyr/acf-can-bridge.c | 7 +++++- 7 files changed, 86 insertions(+), 25 deletions(-) diff --git a/examples/acf-can/acf-can-common.c b/examples/acf-can/acf-can-common.c index f5a918a2..cd0ab0f0 100644 --- a/examples/acf-can/acf-can-common.c +++ b/examples/acf-can/acf-can-common.c @@ -120,12 +120,15 @@ static int init_cf_pdu(uint8_t *pdu, uint64_t stream_id, acf_can_cf_t cf, uint32 { int res; - if (cf == ACF_CAN_CF_NTSCF) { - Avtp_Ntscf_t *ntscf_pdu = (Avtp_Ntscf_t *)pdu; - Avtp_Ntscf_Init(ntscf_pdu); - Avtp_Ntscf_SetSequenceNum(ntscf_pdu, (uint8_t)seq_num); - Avtp_Ntscf_SetStreamId(ntscf_pdu, stream_id); - return AVTP_NTSCF_HEADER_LEN; + if (cf == ACF_CAN_CF_NTSCF_V0 || cf == ACF_CAN_CF_NTSCF_V1) { + if (cf == ACF_CAN_CF_NTSCF_V1) { + Avtp_Ntscf_InitV1((Avtp_NtscfV1_t *)pdu); + } else { + Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); + } + Avtp_Ntscf_SetSequenceNum((Avtp_Ntscf_t *)pdu, seq_num); + Avtp_Ntscf_SetStreamId((Avtp_Ntscf_t *)pdu, stream_id); + return (int)Avtp_Ntscf_GetHeaderLen((Avtp_Ntscf_t *)pdu); } if (cf == ACF_CAN_CF_TSCF_V1) { @@ -143,8 +146,9 @@ static int init_cf_pdu(uint8_t *pdu, uint64_t stream_id, acf_can_cf_t cf, uint32 static int update_cf_length(uint8_t *cf_pdu, uint64_t length, acf_can_cf_t cf) { - if (cf == ACF_CAN_CF_NTSCF) { - uint64_t payloadLen = length - AVTP_NTSCF_HEADER_LEN; + if (cf == ACF_CAN_CF_NTSCF_V0 || cf == ACF_CAN_CF_NTSCF_V1) { + size_t headerLen = Avtp_Ntscf_GetHeaderLen((Avtp_Ntscf_t *)cf_pdu); + uint64_t payloadLen = length - headerLen; Avtp_Ntscf_SetNtscfDataLength((Avtp_Ntscf_t *)cf_pdu, (uint16_t)payloadLen); } else { size_t headerLen = @@ -285,8 +289,15 @@ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uin s_id = Avtp_Tscf_GetStreamId((Avtp_Tscf_t *)cf_pdu); seq_num = Avtp_Tscf_GetSequenceNum((Avtp_Tscf_t *)cf_pdu); } else if (subtype == AVTP_SUBTYPE_NTSCF) { - proc_bytes += AVTP_NTSCF_HEADER_LEN; - msg_length += Avtp_Ntscf_GetNtscfDataLength((Avtp_Ntscf_t *)cf_pdu) + AVTP_NTSCF_HEADER_LEN; + uint8_t version = + Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)cf_pdu); + if (!Avtp_Version_IsSupported(AVTP_NTSCF_SUPPORTED_VERSIONS, version)) { + LOG_ERR("Unsupported NTSCF version %u, ignoring frame.\n", version); + return -1; + } + size_t headerLen = Avtp_Ntscf_GetHeaderLen((const Avtp_Ntscf_t *)cf_pdu); + proc_bytes += (uint16_t)headerLen; + msg_length += (uint16_t)(Avtp_Ntscf_GetNtscfDataLength((Avtp_Ntscf_t *)cf_pdu) + headerLen); s_id = Avtp_Ntscf_GetStreamId((Avtp_Ntscf_t *)cf_pdu); seq_num = Avtp_Ntscf_GetSequenceNum((Avtp_Ntscf_t *)cf_pdu); } else { diff --git a/examples/acf-can/acf-can-common.h b/examples/acf-can/acf-can-common.h index 7c78a6a4..fda30d55 100644 --- a/examples/acf-can/acf-can-common.h +++ b/examples/acf-can/acf-can-common.h @@ -90,9 +90,10 @@ typedef union { * Control format used to encapsulate ACF CAN messages. */ typedef enum { - ACF_CAN_CF_NTSCF = 0, /* NTSCF version 0 */ - ACF_CAN_CF_TSCF_V0, /* TSCF version 0 */ - ACF_CAN_CF_TSCF_V1, /* TSCF version 1 */ + ACF_CAN_CF_NTSCF_V0 = 0, /* NTSCF version 0 */ + ACF_CAN_CF_NTSCF_V1, /* NTSCF version 1 */ + ACF_CAN_CF_TSCF_V0, /* TSCF version 0 */ + ACF_CAN_CF_TSCF_V1, /* TSCF version 1 */ } acf_can_cf_t; #ifdef __linux__ diff --git a/examples/acf-can/linux/README.md b/examples/acf-can/linux/README.md index 5a2333e0..c9f203bc 100644 --- a/examples/acf-can/linux/README.md +++ b/examples/acf-can/linux/README.md @@ -14,7 +14,7 @@ All these applications support IEEE 1722 over Ethernet (layer 2) as well as over The chosen format has to match between the talker and listener applications. The build system builds the applications using all available formats for the listener, talker and bridge applications. User can extend the build system to build the applications using other formats as well. -In addition to the ACF CAN message format, the TSCF transport can use version 0 (24-octet header, 8-bit sequence number) or version 1 (40-octet header, 32-bit sequence number, PTP grandmaster identity) of the AVTPDU common stream header. Select the version at runtime with `-t1`/`--tscf=1` on the talker or bridge; listeners detect the version from the received frame. +In addition to the ACF CAN message format, the NTSCF transport can use version 0 (12-octet header, 8-bit sequence number) or version 1 (28-octet header, 32-bit sequence number, PTP grandmaster identity) of the AVTPDU alternative header, and the TSCF transport can use version 0 (24-octet header, 8-bit sequence number) or version 1 (40-octet header, 32-bit sequence number, PTP grandmaster identity) of the AVTPDU common stream header. Select the version at runtime with `-n1`/`--ntscf=1` or `-t1`/`--tscf=1` on the talker or bridge; listeners detect the version from the received frame. The built applications can be used along with Linux CAN utilities. On Ubuntu/Debian Linux distributions, these utilities can be installed using the package manager `apt install can-utils` @@ -29,11 +29,13 @@ Ethernet using Open1722. --canif=CAN_IF CAN interface -c, --count=COUNT Set count of CAN messages per Ethernet frame + --dst-nw-addr=NW_ADDR Stream destination network address and port (If + UDP) -d, --dst-addr=MACADDR Stream destination MAC address (If Ethernet) --fd Use CAN-FD -i, --ifname=IFNAME Network interface (If Ethernet) - -n, --dst-nw-addr=NW_ADDR Stream destination network address and port (If - UDP) + -n, --ntscf[=VERSION] Use NTSCF; VERSION 0 or 1 selects the header + version (Default: NTSCF v0) --stream-id=STREAM_ID Stream ID for talker stream -t, --tscf[=VERSION] Use TSCF; VERSION 0 or 1 selects the header version (Default: NTSCF v0) @@ -71,13 +73,15 @@ acf-can-bridge -- a program for bridging a CAN interface with an Ethernet interf --canif=CAN_IF CAN interface -c, --count=COUNT Set count of CAN messages per Ethernet frame + --dst-nw-addr=NW_ADDR Stream destination network address and port (If + UDP) -d, --dst-addr=MACADDR Stream destination MAC address (If Ethernet) --fd Use CAN-FD -i, --ifname=IFNAME Network interface (If Ethernet) --listener-stream-id=STREAM_ID Stream ID for listener stream - -n, --dst-nw-addr=NW_ADDR Stream destination network address and port (If - UDP) + -n, --ntscf[=VERSION] Use NTSCF; VERSION 0 or 1 selects the header + version (Default: NTSCF v0) -p, --udp-port=UDP_PORT UDP Port to listen on (if UDP) --talker-stream-id=STREAM_ID Stream ID for talker stream diff --git a/examples/acf-can/linux/acf-can-bridge.c b/examples/acf-can/linux/acf-can-bridge.c index fd621497..e50ab82a 100644 --- a/examples/acf-can/linux/acf-can-bridge.c +++ b/examples/acf-can/linux/acf-can-bridge.c @@ -49,6 +49,7 @@ #define ARGPARSE_CAN_IF_OPTION 501 #define ARGPARSE_TALKER_ID_OPTION 502 #define ARGPARSE_LISTENER_ID_OPTION 503 +#define ARGPARSE_DST_NW_ADDR_OPTION 504 #define TALKER_STREAM_ID 0xAABBCCDDEEFF0001 #define LISTENER_STREAM_ID 0xAABBCCDDEEFF0001 @@ -56,7 +57,7 @@ static char ifname[IFNAMSIZ]; static uint8_t macaddr[ETH_ALEN]; static uint8_t ip_addr[sizeof(struct in_addr)]; static int priority = -1; -static acf_can_cf_t cf_format = ACF_CAN_CF_NTSCF; +static acf_can_cf_t cf_format = ACF_CAN_CF_NTSCF_V0; static uint8_t use_udp = 0; static uint32_t udp_listen_port = 17220; static uint32_t udp_send_port = 17220; @@ -81,13 +82,16 @@ static char doc[] = static struct argp_option options[] = { {"tscf", 't', "VERSION", OPTION_ARG_OPTIONAL, "Use TSCF; VERSION 0 or 1 selects the header version (Default: NTSCF v0)"}, + {"ntscf", 'n', "VERSION", OPTION_ARG_OPTIONAL, + "Use NTSCF; VERSION 0 or 1 selects the header version (Default: NTSCF v0)"}, {"udp", 'u', 0, 0, "Use UDP"}, {"fd", ARGPARSE_CAN_FD_OPTION, 0, 0, "Use CAN-FD"}, {"count", 'c', "COUNT", 0, "Set count of CAN messages per Ethernet frame"}, {"canif", ARGPARSE_CAN_IF_OPTION, "CAN_IF", 0, "CAN interface"}, {"ifname", 'i', "IFNAME", 0, "Network interface (If Ethernet)"}, {"dst-addr", 'd', "MACADDR", 0, "Stream destination MAC address (If Ethernet)"}, - {"dst-nw-addr", 'n', "NW_ADDR", 0, "Stream destination network address and port (If UDP)"}, + {"dst-nw-addr", ARGPARSE_DST_NW_ADDR_OPTION, "NW_ADDR", 0, + "Stream destination network address and port (If UDP)"}, {"udp-port", 'p', "UDP_PORT", 0, "UDP Port to listen on (if UDP)"}, {"listener-stream-id", ARGPARSE_LISTENER_ID_OPTION, "STREAM_ID", 0, "Stream ID for listener stream"}, @@ -110,6 +114,17 @@ static error_t parser(int key, char *arg, struct argp_state *state) } } break; + case 'n': + cf_format = ACF_CAN_CF_NTSCF_V0; + if (arg != NULL) { + if (strcmp(arg, "1") == 0) { + cf_format = ACF_CAN_CF_NTSCF_V1; + } else if (strcmp(arg, "0") != 0) { + fprintf(stderr, "Invalid NTSCF version '%s' (only 0 and 1 are supported)\n", arg); + exit(EXIT_FAILURE); + } + } + break; case 'p': udp_listen_port = atoi(arg); break; @@ -140,7 +155,7 @@ static error_t parser(int key, char *arg, struct argp_state *state) exit(EXIT_FAILURE); } break; - case 'n': + case ARGPARSE_DST_NW_ADDR_OPTION: res = sscanf(arg, "%[^:]:%d", ip_addr_str, &udp_send_port); if (!res) { fprintf(stderr, "Invalid IP address or port\n"); @@ -285,6 +300,9 @@ int main(int argc, char *argv[]) case ACF_CAN_CF_TSCF_V1: printf("\tUsing TSCF v1\n"); break; + case ACF_CAN_CF_NTSCF_V1: + printf("\tUsing NTSCF v1\n"); + break; default: printf("\tUsing NTSCF v0\n"); break; diff --git a/examples/acf-can/linux/acf-can-talker.c b/examples/acf-can/linux/acf-can-talker.c index cf4afbe8..dd7aa7ed 100644 --- a/examples/acf-can/linux/acf-can-talker.c +++ b/examples/acf-can/linux/acf-can-talker.c @@ -47,13 +47,14 @@ #define ARGPARSE_CAN_FD_OPTION 500 #define ARGPARSE_CAN_IF_OPTION 501 #define ARGPARSE_TALKER_ID_OPTION 502 +#define ARGPARSE_DST_NW_ADDR_OPTION 504 static char ifname[IFNAMSIZ]; static uint8_t macaddr[ETH_ALEN]; static uint8_t ip_addr[sizeof(struct in_addr)]; static uint32_t udp_port = 17220; static int priority = -1; -static acf_can_cf_t cf_format = ACF_CAN_CF_NTSCF; +static acf_can_cf_t cf_format = ACF_CAN_CF_NTSCF_V0; static uint8_t use_udp = 0; static bool can_fd = false; static uint8_t num_acf_msgs = 1; @@ -72,13 +73,16 @@ static char doc[] = static struct argp_option options[] = { {"tscf", 't', "VERSION", OPTION_ARG_OPTIONAL, "Use TSCF; VERSION 0 or 1 selects the header version (Default: NTSCF v0)"}, + {"ntscf", 'n', "VERSION", OPTION_ARG_OPTIONAL, + "Use NTSCF; VERSION 0 or 1 selects the header version (Default: NTSCF v0)"}, {"udp", 'u', 0, 0, "Use UDP (Default: Ethernet)"}, {"fd", ARGPARSE_CAN_FD_OPTION, 0, 0, "Use CAN-FD"}, {"count", 'c', "COUNT", 0, "Set count of CAN messages per Ethernet frame"}, {"canif", ARGPARSE_CAN_IF_OPTION, "CAN_IF", 0, "CAN interface"}, {"ifname", 'i', "IFNAME", 0, "Network interface (If Ethernet)"}, {"dst-addr", 'd', "MACADDR", 0, "Stream destination MAC address (If Ethernet)"}, - {"dst-nw-addr", 'n', "NW_ADDR", 0, "Stream destination network address and port (If UDP)"}, + {"dst-nw-addr", ARGPARSE_DST_NW_ADDR_OPTION, "NW_ADDR", 0, + "Stream destination network address and port (If UDP)"}, {"stream-id", ARGPARSE_TALKER_ID_OPTION, "STREAM_ID", 0, "Stream ID for talker stream"}, {0}}; @@ -98,6 +102,17 @@ static error_t parser(int key, char *arg, struct argp_state *state) } } break; + case 'n': + cf_format = ACF_CAN_CF_NTSCF_V0; + if (arg != NULL) { + if (strcmp(arg, "1") == 0) { + cf_format = ACF_CAN_CF_NTSCF_V1; + } else if (strcmp(arg, "0") != 0) { + fprintf(stderr, "Invalid NTSCF version '%s' (only 0 and 1 are supported)\n", arg); + exit(EXIT_FAILURE); + } + } + break; case 'u': use_udp = 1; break; @@ -125,7 +140,7 @@ static error_t parser(int key, char *arg, struct argp_state *state) exit(EXIT_FAILURE); } break; - case 'n': + case ARGPARSE_DST_NW_ADDR_OPTION: res = sscanf(arg, "%[^:]:%d", ip_addr_str, &udp_port); if (!res) { fprintf(stderr, "Invalid IP address or port\n"); @@ -173,6 +188,9 @@ int main(int argc, char *argv[]) case ACF_CAN_CF_TSCF_V1: printf("\tUsing TSCF v1\n"); break; + case ACF_CAN_CF_NTSCF_V1: + printf("\tUsing NTSCF v1\n"); + break; default: printf("\tUsing NTSCF v0\n"); break; diff --git a/examples/acf-can/zephyr/Kconfig b/examples/acf-can/zephyr/Kconfig index 0a35c85e..b9685c17 100644 --- a/examples/acf-can/zephyr/Kconfig +++ b/examples/acf-can/zephyr/Kconfig @@ -12,6 +12,10 @@ config ACF_CAN_BRIDGE_TSCF_VERSION int "TSCF header version (0 or 1)" default 0 +config ACF_CAN_BRIDGE_NTSCF_VERSION + int "NTSCF header version (0 or 1)" + default 0 + config ACF_CAN_BRIDGE_SEND_MAC_ADDR string "MAC Address to which ACF CAN frames are sent" default "aa:bb:cc:dd:ee:ff" diff --git a/examples/acf-can/zephyr/acf-can-bridge.c b/examples/acf-can/zephyr/acf-can-bridge.c index e38c80f9..fe4af245 100644 --- a/examples/acf-can/zephyr/acf-can-bridge.c +++ b/examples/acf-can/zephyr/acf-can-bridge.c @@ -65,8 +65,10 @@ static struct in_addr ip_addr; #if CONFIG_ACF_CAN_BRIDGE_USE_TSCF static acf_can_cf_t cf_format = CONFIG_ACF_CAN_BRIDGE_TSCF_VERSION == 1 ? ACF_CAN_CF_TSCF_V1 : ACF_CAN_CF_TSCF_V0; +#elif CONFIG_ACF_CAN_BRIDGE_NTSCF_VERSION == 1 +static acf_can_cf_t cf_format = ACF_CAN_CF_NTSCF_V1; #else -static acf_can_cf_t cf_format = ACF_CAN_CF_NTSCF; +static acf_can_cf_t cf_format = ACF_CAN_CF_NTSCF_V0; #endif static uint8_t use_udp = CONFIG_ACF_CAN_BRIDGE_USE_UDP; static uint32_t udp_listen_port = CONFIG_ACF_CAN_BRIDGE_RECV_UDP_PORT; @@ -365,6 +367,9 @@ int main(void) case ACF_CAN_CF_TSCF_V1: printf("\tUsing TSCF v1\n"); break; + case ACF_CAN_CF_NTSCF_V1: + printf("\tUsing NTSCF v1\n"); + break; default: printf("\tUsing NTSCF v0\n"); break; From dac6a5e8bb0d09ee0540a6b06cfd9d9fa0dbc75d Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Sat, 19 Sep 2026 22:28:34 +0200 Subject: [PATCH 08/16] V1 support for Rvf, Aaf+PCM, CVF Signed-off-by: Sebastian Schildt --- docs/api-design.md | 8 +- include/avtp/Rvf.h | 346 +++++++++++++++++++++++++++------------- include/avtp/aaf/Aaf.h | 285 +++++++++++++++++++++++---------- include/avtp/aaf/Pcm.h | 284 ++++++++++++++++++++++----------- include/avtp/acf/Tscf.h | 8 + include/avtp/cvf/Cvf.h | 318 ++++++++++++++++++++++++------------ unit/test-aaf.c | 184 +++++++++++++++++---- unit/test-cvf.c | 171 ++++++++++++++++---- unit/test-pcm.c | 223 +++++++++++++++++++++----- unit/test-rvf.c | 175 ++++++++++++++++---- 10 files changed, 1477 insertions(+), 525 deletions(-) diff --git a/docs/api-design.md b/docs/api-design.md index 3e718215..7b71dc34 100644 --- a/docs/api-design.md +++ b/docs/api-design.md @@ -17,9 +17,11 @@ table covering the format's own bits, `Init`, `IsValid` and payload helpers. They differ only in the header they describe: the common stream header, except for CRF/NTSCF, which use the alternative header. Both header styles are versioned (0 and 1); the common stream header fields are described once in -[`CommonStreamHeader.h`](../include/avtp/CommonStreamHeader.h), and each format -declares a complete descriptor table per version in absolute coordinates, -reusing those positions for the common fields (TSCF is the reference). The CVF +[`CommonStreamHeader.h`](../include/avtp/CommonStreamHeader.h), and each stream +format (AAF, PCM, CVF, RVF, TSCF) declares a complete descriptor table per +version in absolute coordinates, reusing those positions for the common fields. +A per-format consistency test keeps those common entries aligned with the style +module. The CVF format-specific headers (MJPEG, H.264, JPEG 2000) and the RVF raw header are fragments of the stream data rather than standalone PDUs: they are validated through the enclosing PDU (`Avtp_Cvf_IsValid`/`Avtp_Rvf_IsValid`, plus a diff --git a/include/avtp/Rvf.h b/include/avtp/Rvf.h index 075929bf..ee451d35 100644 --- a/include/avtp/Rvf.h +++ b/include/avtp/Rvf.h @@ -33,6 +33,12 @@ * @file * This file contains the fields descriptions of the IEEE 1722 RVF PDUs and * functions to invoke corresponding parser and deparser. + * + * RVF uses the AVTPDU common stream header (4.7.4) and declares a complete + * descriptor table per version in absolute coordinates: the common stream + * header fields reuse the positions from CommonStreamHeader.h and the + * RVF-specific fields are added by this module. A consistency test keeps the + * common entries aligned with the common stream header module. */ #pragma once @@ -48,24 +54,31 @@ #include "avtp/Utils.h" #include "avtp/Defines.h" #include "avtp/CommonHeader.h" +#include "avtp/CommonStreamHeader.h" #ifdef __cplusplus extern "C" { #endif -#define AVTP_RVF_HEADER_LEN (6 * AVTP_QUADLET_SIZE) +#define AVTP_RVF_HEADER_LEN_V0 AVTPDU_CSH_LEN_V0 /* 24 */ +#define AVTP_RVF_HEADER_LEN_V1 AVTPDU_CSH_LEN_V1 /* 40 */ +/* Kept for compatibility: the version 0 header length. */ +#define AVTP_RVF_HEADER_LEN AVTP_RVF_HEADER_LEN_V0 #define AVTP_RVF_RAW_HEADER_LEN (2 * AVTP_QUADLET_SIZE) -#define GET_RVF_FIELD(field) \ - (Avtp_GetField(Avtp_RvfFieldDesc, AVTP_RVF_FIELD_MAX, (const uint8_t *)pdu, field)) -#define SET_RVF_FIELD(field, value) \ - (Avtp_SetField(Avtp_RvfFieldDesc, AVTP_RVF_FIELD_MAX, (uint8_t *)pdu, field, value)) +/* RVF supports both versions of the common stream header (Table 7). */ +#define AVTP_RVF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) typedef struct { - uint8_t header[AVTP_RVF_HEADER_LEN]; + uint8_t header[AVTP_RVF_HEADER_LEN_V0]; uint8_t payload[0]; } __attribute__((packed)) Avtp_Rvf_t; +typedef struct { + uint8_t header[AVTP_RVF_HEADER_LEN_V1]; + uint8_t payload[0]; +} __attribute__((packed)) Avtp_RvfV1_t; + typedef enum Avtp_RvfPixelDepth { AVTP_RVF_PIXEL_DEPTH_8 = 0x01, AVTP_RVF_PIXEL_DEPTH_10 = 0x02, @@ -130,22 +143,22 @@ typedef enum Avtp_RvfColorspace { typedef enum { /* Common AVTP stream header fields */ - AVTP_RVF_FIELD_SUBTYPE, - AVTP_RVF_FIELD_SV, - AVTP_RVF_FIELD_VERSION, + AVTP_RVF_FIELD_SV = 0, AVTP_RVF_FIELD_MR, - AVTP_RVF_FIELD_RSV, + AVTP_RVF_FIELD_FSD, AVTP_RVF_FIELD_TV, AVTP_RVF_FIELD_SEQUENCE_NUM, - AVTP_RVF_FIELD_RESERVED1, + AVTP_RVF_FIELD_FSD0, + AVTP_RVF_FIELD_FSD1, AVTP_RVF_FIELD_TU, - - /* RVF header fields */ AVTP_RVF_FIELD_STREAM_ID, AVTP_RVF_FIELD_AVTP_TIMESTAMP, + AVTP_RVF_FIELD_PTP_GRANDMASTER_IDENTITY, + AVTP_RVF_FIELD_STREAM_DATA_LENGTH, + + /* RVF format-specific fields */ AVTP_RVF_FIELD_ACTIVE_PIXELS, AVTP_RVF_FIELD_TOTAL_LINES, - AVTP_RVF_FIELD_STREAM_DATA_LENGTH, AVTP_RVF_FIELD_AP, AVTP_RVF_FIELD_R, AVTP_RVF_FIELD_F, @@ -160,25 +173,25 @@ typedef enum { } Avtp_RvfFields_t; /** - * This table maps all IEEE 1722 RVF header fields to a descriptor. + * This table maps all IEEE 1722 RVF header fields to a descriptor for version 0. + * It is complete and in absolute coordinates; the common stream header fields + * use the same positions as Avtp_CshFieldDescV0. */ -static const Avtp_FieldDescriptor_t Avtp_RvfFieldDesc[AVTP_RVF_FIELD_MAX] = { - /* Common AVTP stream header fields */ - [AVTP_RVF_FIELD_SUBTYPE] = {.quadlet = 0, .offset = 0, .bits = 8}, +static const Avtp_FieldDescriptor_t Avtp_RvfFieldDescV0[AVTP_RVF_FIELD_MAX] = { [AVTP_RVF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, - [AVTP_RVF_FIELD_VERSION] = {.quadlet = 0, .offset = 9, .bits = 3}, [AVTP_RVF_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, - [AVTP_RVF_FIELD_RSV] = {.quadlet = 0, .offset = 13, .bits = 2}, + [AVTP_RVF_FIELD_FSD] = {.quadlet = 0, .offset = 13, .bits = 2}, [AVTP_RVF_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, [AVTP_RVF_FIELD_SEQUENCE_NUM] = {.quadlet = 0, .offset = 16, .bits = 8}, - [AVTP_RVF_FIELD_RESERVED1] = {.quadlet = 0, .offset = 24, .bits = 7}, + [AVTP_RVF_FIELD_FSD0] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_RVF_FIELD_FSD1] = {.quadlet = 0, .offset = 24, .bits = 7}, [AVTP_RVF_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, - /* RVF header fields */ [AVTP_RVF_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, [AVTP_RVF_FIELD_AVTP_TIMESTAMP] = {.quadlet = 3, .offset = 0, .bits = 32}, + [AVTP_RVF_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_RVF_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 5, .offset = 0, .bits = 16}, [AVTP_RVF_FIELD_ACTIVE_PIXELS] = {.quadlet = 4, .offset = 0, .bits = 16}, [AVTP_RVF_FIELD_TOTAL_LINES] = {.quadlet = 4, .offset = 16, .bits = 16}, - [AVTP_RVF_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 5, .offset = 0, .bits = 16}, [AVTP_RVF_FIELD_AP] = {.quadlet = 5, .offset = 16, .bits = 1}, [AVTP_RVF_FIELD_R] = {.quadlet = 5, .offset = 17, .bits = 1}, [AVTP_RVF_FIELD_F] = {.quadlet = 5, .offset = 18, .bits = 1}, @@ -189,6 +202,76 @@ static const Avtp_FieldDescriptor_t Avtp_RvfFieldDesc[AVTP_RVF_FIELD_MAX] = { [AVTP_RVF_FIELD_RESERVED2] = {.quadlet = 5, .offset = 26, .bits = 6}, }; +/** + * This table maps all IEEE 1722 RVF header fields to a descriptor for version 1. + * It is complete and in absolute coordinates; the common stream header fields + * use the same positions as Avtp_CshFieldDescV1. + */ +static const Avtp_FieldDescriptor_t Avtp_RvfFieldDescV1[AVTP_RVF_FIELD_MAX] = { + [AVTP_RVF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, + [AVTP_RVF_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, + [AVTP_RVF_FIELD_FSD] = {.quadlet = 0, .offset = 13, .bits = 2}, + [AVTP_RVF_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, + [AVTP_RVF_FIELD_SEQUENCE_NUM] = {.quadlet = 3, .offset = 0, .bits = 32}, + [AVTP_RVF_FIELD_FSD0] = {.quadlet = 0, .offset = 16, .bits = 8}, + [AVTP_RVF_FIELD_FSD1] = {.quadlet = 0, .offset = 24, .bits = 7}, + [AVTP_RVF_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, + [AVTP_RVF_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, + [AVTP_RVF_FIELD_AVTP_TIMESTAMP] = {.quadlet = 4, .offset = 0, .bits = 64}, + [AVTP_RVF_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 6, .offset = 0, .bits = 64}, + [AVTP_RVF_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 9, .offset = 0, .bits = 16}, + [AVTP_RVF_FIELD_ACTIVE_PIXELS] = {.quadlet = 8, .offset = 0, .bits = 16}, + [AVTP_RVF_FIELD_TOTAL_LINES] = {.quadlet = 8, .offset = 16, .bits = 16}, + [AVTP_RVF_FIELD_AP] = {.quadlet = 9, .offset = 16, .bits = 1}, + [AVTP_RVF_FIELD_R] = {.quadlet = 9, .offset = 17, .bits = 1}, + [AVTP_RVF_FIELD_F] = {.quadlet = 9, .offset = 18, .bits = 1}, + [AVTP_RVF_FIELD_EF] = {.quadlet = 9, .offset = 19, .bits = 1}, + [AVTP_RVF_FIELD_EVT] = {.quadlet = 9, .offset = 20, .bits = 4}, + [AVTP_RVF_FIELD_PD] = {.quadlet = 9, .offset = 24, .bits = 1}, + [AVTP_RVF_FIELD_I] = {.quadlet = 9, .offset = 25, .bits = 1}, + [AVTP_RVF_FIELD_RESERVED2] = {.quadlet = 9, .offset = 26, .bits = 6}, +}; + +/** + * Returns the value of an AVTP RVF field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 RVF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + */ +OPEN1722_INLINE uint64_t Avtp_Rvf_GetField(const Avtp_Rvf_t *const pdu, Avtp_RvfFields_t field) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_RvfFieldDescV1 + : Avtp_RvfFieldDescV0; + return Avtp_GetField(desc, AVTP_RVF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); +} + +/** + * Sets the value of an AVTP RVF field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 RVF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + */ +OPEN1722_INLINE void Avtp_Rvf_SetField(Avtp_Rvf_t *pdu, Avtp_RvfFields_t field, uint64_t value) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_RvfFieldDescV1 + : Avtp_RvfFieldDescV0; + Avtp_SetField(desc, AVTP_RVF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Returns the length of the RVF header in octets (24 or 40). + */ +OPEN1722_INLINE uint8_t Avtp_Rvf_GetHeaderLen(const Avtp_Rvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); +} + /** * Return the value of the RVF SV field as specified in the IEEE 1722 Specification. * @@ -197,7 +280,7 @@ static const Avtp_FieldDescriptor_t Avtp_RvfFieldDesc[AVTP_RVF_FIELD_MAX] = { */ OPEN1722_INLINE bool Avtp_Rvf_IsSv(const Avtp_Rvf_t *const pdu) { - return (bool)GET_RVF_FIELD(AVTP_RVF_FIELD_SV); + return (bool)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_SV); } /** @@ -208,7 +291,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsSv(const Avtp_Rvf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Rvf_IsMr(const Avtp_Rvf_t *const pdu) { - return (bool)GET_RVF_FIELD(AVTP_RVF_FIELD_MR); + return (bool)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_MR); } /** @@ -219,18 +302,19 @@ OPEN1722_INLINE bool Avtp_Rvf_IsMr(const Avtp_Rvf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Rvf_IsTv(const Avtp_Rvf_t *const pdu) { - return (bool)GET_RVF_FIELD(AVTP_RVF_FIELD_TV); + return (bool)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_TV); } /** - * Return the value of the RVF Sequence Number field as specified in the IEEE 1722 Specification. + * Return the value of the RVF Sequence Number field as specified in the IEEE 1722 + * Specification. The field is 8 bits in version 0 and 32 bits in version 1. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @returns Value of the RVF Sequence Number field. */ -OPEN1722_INLINE uint8_t Avtp_Rvf_GetSequenceNum(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Rvf_GetSequenceNum(const Avtp_Rvf_t *const pdu) { - return (uint8_t)GET_RVF_FIELD(AVTP_RVF_FIELD_SEQUENCE_NUM); + return (uint32_t)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_SEQUENCE_NUM); } /** @@ -241,7 +325,7 @@ OPEN1722_INLINE uint8_t Avtp_Rvf_GetSequenceNum(const Avtp_Rvf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Rvf_IsTu(const Avtp_Rvf_t *const pdu) { - return (bool)GET_RVF_FIELD(AVTP_RVF_FIELD_TU); + return (bool)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_TU); } /** @@ -252,55 +336,67 @@ OPEN1722_INLINE bool Avtp_Rvf_IsTu(const Avtp_Rvf_t *const pdu) */ OPEN1722_INLINE uint64_t Avtp_Rvf_GetStreamId(const Avtp_Rvf_t *const pdu) { - return (uint64_t)GET_RVF_FIELD(AVTP_RVF_FIELD_STREAM_ID); + return Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_STREAM_ID); } /** - * Return the value of the RVF AVTP Timestamp field as specified in the IEEE 1722 Specification. + * Return the value of the RVF AVTP Timestamp field as specified in the IEEE 1722 + * Specification. The field is 32 bits in version 0 and 64 bits in version 1. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @returns Value of the RVF AVTP Timestamp field. */ -OPEN1722_INLINE uint32_t Avtp_Rvf_GetAvtpTimestamp(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Rvf_GetAvtpTimestamp(const Avtp_Rvf_t *const pdu) +{ + return Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_AVTP_TIMESTAMP); +} + +/** + * Return the value of the RVF ptp_grandmaster_identity field. The field only + * exists in version 1; version 0 returns 0. + * + * @param pdu Pointer to the first bit of an 1722 RVF PDU. + * @returns Value of the RVF ptp_grandmaster_identity field. + */ +OPEN1722_INLINE uint64_t Avtp_Rvf_GetPtpGrandmasterIdentity(const Avtp_Rvf_t *const pdu) { - return (uint32_t)GET_RVF_FIELD(AVTP_RVF_FIELD_AVTP_TIMESTAMP); + return Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_PTP_GRANDMASTER_IDENTITY); } /** - * Return the value of the RVF Active Pixels field as specified in the IEEE 1722 Specification. + * Return the value of the RVF Active Pixels field as specified in the IEEE 1722 + * Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @returns Value of the RVF Active Pixels field. */ OPEN1722_INLINE uint16_t Avtp_Rvf_GetActivePixels(const Avtp_Rvf_t *const pdu) { - return (uint16_t)GET_RVF_FIELD(AVTP_RVF_FIELD_ACTIVE_PIXELS); + return (uint16_t)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_ACTIVE_PIXELS); } /** - * Return the value of the RVF Total Lines field as specified in the IEEE 1722 Specification. + * Return the value of the RVF Total Lines field as specified in the IEEE 1722 + * Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @returns Value of the RVF Total Lines field. */ OPEN1722_INLINE uint16_t Avtp_Rvf_GetTotalLines(const Avtp_Rvf_t *const pdu) { - return (uint16_t)GET_RVF_FIELD(AVTP_RVF_FIELD_TOTAL_LINES); + return (uint16_t)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_TOTAL_LINES); } /** - * Return the value of the RVF Stream Data Length field as specified in the IEEE 1722 Specification. - * - * The stream_data_length field contains the length (in octets) of the - * stream_data_payload field, which for RVF consists of the raw header and the - * video data payload. + * Return the value of the RVF Stream Data Length field as specified in the IEEE 1722 + * Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @returns Value of the RVF Stream Data Length field. */ OPEN1722_INLINE uint16_t Avtp_Rvf_GetStreamDataLength(const Avtp_Rvf_t *const pdu) { - return (uint16_t)GET_RVF_FIELD(AVTP_RVF_FIELD_STREAM_DATA_LENGTH); + return (uint16_t)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_STREAM_DATA_LENGTH); } /** @@ -311,7 +407,7 @@ OPEN1722_INLINE uint16_t Avtp_Rvf_GetStreamDataLength(const Avtp_Rvf_t *const pd */ OPEN1722_INLINE bool Avtp_Rvf_IsAp(const Avtp_Rvf_t *const pdu) { - return (bool)GET_RVF_FIELD(AVTP_RVF_FIELD_AP); + return (bool)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_AP); } /** @@ -322,7 +418,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsAp(const Avtp_Rvf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Rvf_IsF(const Avtp_Rvf_t *const pdu) { - return (bool)GET_RVF_FIELD(AVTP_RVF_FIELD_F); + return (bool)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_F); } /** @@ -333,7 +429,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsF(const Avtp_Rvf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Rvf_IsEf(const Avtp_Rvf_t *const pdu) { - return (bool)GET_RVF_FIELD(AVTP_RVF_FIELD_EF); + return (bool)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_EF); } /** @@ -344,7 +440,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsEf(const Avtp_Rvf_t *const pdu) */ OPEN1722_INLINE uint8_t Avtp_Rvf_GetEvt(const Avtp_Rvf_t *const pdu) { - return (uint8_t)GET_RVF_FIELD(AVTP_RVF_FIELD_EVT); + return (uint8_t)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_EVT); } /** @@ -355,7 +451,7 @@ OPEN1722_INLINE uint8_t Avtp_Rvf_GetEvt(const Avtp_Rvf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Rvf_IsPd(const Avtp_Rvf_t *const pdu) { - return (bool)GET_RVF_FIELD(AVTP_RVF_FIELD_PD); + return (bool)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_PD); } /** @@ -366,62 +462,64 @@ OPEN1722_INLINE bool Avtp_Rvf_IsPd(const Avtp_Rvf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Rvf_IsI(const Avtp_Rvf_t *const pdu) { - return (bool)GET_RVF_FIELD(AVTP_RVF_FIELD_I); + return (bool)Avtp_Rvf_GetField(pdu, AVTP_RVF_FIELD_I); } /** - * Set the SV bit in a RVF frame as specified in the IEEE 1722 Specification. + * Set the SV bit in an RVF frame as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param sv Value to set the RVF SV field to. */ OPEN1722_INLINE void Avtp_Rvf_SetSv(Avtp_Rvf_t *pdu, bool sv) { - SET_RVF_FIELD(AVTP_RVF_FIELD_SV, sv); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_SV, sv); } /** - * Set the MR bit in a RVF frame as specified in the IEEE 1722 Specification. + * Set the MR bit in an RVF frame as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param mr Value to set the RVF MR field to. */ OPEN1722_INLINE void Avtp_Rvf_SetMr(Avtp_Rvf_t *pdu, bool mr) { - SET_RVF_FIELD(AVTP_RVF_FIELD_MR, mr); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_MR, mr); } /** - * Set the TV bit in a RVF frame as specified in the IEEE 1722 Specification. + * Set the TV bit in an RVF frame as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param tv Value to set the RVF TV field to. */ OPEN1722_INLINE void Avtp_Rvf_SetTv(Avtp_Rvf_t *pdu, bool tv) { - SET_RVF_FIELD(AVTP_RVF_FIELD_TV, tv); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_TV, tv); } /** - * Set the value of the RVF Sequence Number field as specified in the IEEE 1722 Specification. + * Set the value of the RVF Sequence Number field as specified in the IEEE 1722 + * Specification. The field is 8 bits in version 0 and 32 bits in version 1; values are + * truncated to the width of the version in use. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param value Value to set the RVF Sequence Number field to. */ -OPEN1722_INLINE void Avtp_Rvf_SetSequenceNum(Avtp_Rvf_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Rvf_SetSequenceNum(Avtp_Rvf_t *pdu, uint32_t value) { - SET_RVF_FIELD(AVTP_RVF_FIELD_SEQUENCE_NUM, value); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_SEQUENCE_NUM, value); } /** - * Set the TU bit in a RVF frame as specified in the IEEE 1722 Specification. + * Set the TU bit in an RVF frame as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param tu Value to set the RVF TU field to. */ OPEN1722_INLINE void Avtp_Rvf_SetTu(Avtp_Rvf_t *pdu, bool tu) { - SET_RVF_FIELD(AVTP_RVF_FIELD_TU, tu); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_TU, tu); } /** @@ -432,84 +530,101 @@ OPEN1722_INLINE void Avtp_Rvf_SetTu(Avtp_Rvf_t *pdu, bool tu) */ OPEN1722_INLINE void Avtp_Rvf_SetStreamId(Avtp_Rvf_t *pdu, uint64_t value) { - SET_RVF_FIELD(AVTP_RVF_FIELD_STREAM_ID, value); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_STREAM_ID, value); } /** - * Set the value of the RVF AVTP Timestamp field as specified in the IEEE 1722 Specification. + * Set the value of the RVF AVTP Timestamp field as specified in the IEEE 1722 + * Specification. The field is 32 bits in version 0 and 64 bits in version 1; values are + * truncated to the width of the version in use. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param value Value to set the RVF AVTP Timestamp field to. */ -OPEN1722_INLINE void Avtp_Rvf_SetAvtpTimestamp(Avtp_Rvf_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Rvf_SetAvtpTimestamp(Avtp_Rvf_t *pdu, uint64_t value) +{ + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_AVTP_TIMESTAMP, value); +} + +/** + * Set the value of the RVF ptp_grandmaster_identity field. The field only + * exists in version 1; on version 0 this is a no-op. + * + * @param pdu Pointer to the first bit of an 1722 RVF PDU. + * @param value Value to set the RVF ptp_grandmaster_identity field to. + */ +OPEN1722_INLINE void Avtp_Rvf_SetPtpGrandmasterIdentity(Avtp_Rvf_t *pdu, uint64_t value) { - SET_RVF_FIELD(AVTP_RVF_FIELD_AVTP_TIMESTAMP, value); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_PTP_GRANDMASTER_IDENTITY, value); } /** - * Set the value of the RVF Active Pixels field as specified in the IEEE 1722 Specification. + * Set the value of the RVF Active Pixels field as specified in the IEEE 1722 + * Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param value Value to set the RVF Active Pixels field to. */ OPEN1722_INLINE void Avtp_Rvf_SetActivePixels(Avtp_Rvf_t *pdu, uint16_t value) { - SET_RVF_FIELD(AVTP_RVF_FIELD_ACTIVE_PIXELS, value); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_ACTIVE_PIXELS, value); } /** - * Set the value of the RVF Total Lines field as specified in the IEEE 1722 Specification. + * Set the value of the RVF Total Lines field as specified in the IEEE 1722 + * Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param value Value to set the RVF Total Lines field to. */ OPEN1722_INLINE void Avtp_Rvf_SetTotalLines(Avtp_Rvf_t *pdu, uint16_t value) { - SET_RVF_FIELD(AVTP_RVF_FIELD_TOTAL_LINES, value); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_TOTAL_LINES, value); } /** - * Set the value of the RVF Stream Data Length field as specified in the IEEE 1722 Specification. + * Set the value of the RVF Stream Data Length field as specified in the IEEE 1722 + * Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param value Value to set the RVF Stream Data Length field to. */ OPEN1722_INLINE void Avtp_Rvf_SetStreamDataLength(Avtp_Rvf_t *pdu, uint16_t value) { - SET_RVF_FIELD(AVTP_RVF_FIELD_STREAM_DATA_LENGTH, value); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_STREAM_DATA_LENGTH, value); } /** - * Set the AP bit in a RVF frame as specified in the IEEE 1722 Specification. + * Set the AP bit in an RVF frame as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param ap Value to set the RVF AP field to. */ OPEN1722_INLINE void Avtp_Rvf_SetAp(Avtp_Rvf_t *pdu, bool ap) { - SET_RVF_FIELD(AVTP_RVF_FIELD_AP, ap); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_AP, ap); } /** - * Set the F bit in a RVF frame as specified in the IEEE 1722 Specification. + * Set the F bit in an RVF frame as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param f Value to set the RVF F field to. */ OPEN1722_INLINE void Avtp_Rvf_SetF(Avtp_Rvf_t *pdu, bool f) { - SET_RVF_FIELD(AVTP_RVF_FIELD_F, f); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_F, f); } /** - * Set the EF bit in a RVF frame as specified in the IEEE 1722 Specification. + * Set the EF bit in an RVF frame as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param ef Value to set the RVF EF field to. */ OPEN1722_INLINE void Avtp_Rvf_SetEf(Avtp_Rvf_t *pdu, bool ef) { - SET_RVF_FIELD(AVTP_RVF_FIELD_EF, ef); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_EF, ef); } /** @@ -520,33 +635,34 @@ OPEN1722_INLINE void Avtp_Rvf_SetEf(Avtp_Rvf_t *pdu, bool ef) */ OPEN1722_INLINE void Avtp_Rvf_SetEvt(Avtp_Rvf_t *pdu, uint8_t value) { - SET_RVF_FIELD(AVTP_RVF_FIELD_EVT, value); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_EVT, value); } /** - * Set the PD bit in a RVF frame as specified in the IEEE 1722 Specification. + * Set the PD bit in an RVF frame as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param pd Value to set the RVF PD field to. */ OPEN1722_INLINE void Avtp_Rvf_SetPd(Avtp_Rvf_t *pdu, bool pd) { - SET_RVF_FIELD(AVTP_RVF_FIELD_PD, pd); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_PD, pd); } /** - * Set the I bit in a RVF frame as specified in the IEEE 1722 Specification. + * Set the I bit in an RVF frame as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param i Value to set the RVF I field to. */ OPEN1722_INLINE void Avtp_Rvf_SetI(Avtp_Rvf_t *pdu, bool i) { - SET_RVF_FIELD(AVTP_RVF_FIELD_I, i); + Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_I, i); } /** - * Returns pointer to the stream data of an RVF frame. + * Returns pointer to the RVF stream data. The stream data starts after the + * version-dependent common stream header. * * The stream data contains the raw header (an Avtp_RvfRawHeader_t) followed by * the video data payload. Its length is given by the stream_data_length field. @@ -556,7 +672,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetI(Avtp_Rvf_t *pdu, bool i) */ OPEN1722_INLINE const uint8_t *Avtp_Rvf_GetPayload(const Avtp_Rvf_t *const pdu) { - return pdu->payload; + return (const uint8_t *)pdu + Avtp_Rvf_GetHeaderLen(pdu); } /** @@ -568,11 +684,11 @@ OPEN1722_INLINE const uint8_t *Avtp_Rvf_GetPayload(const Avtp_Rvf_t *const pdu) */ OPEN1722_INLINE void Avtp_Rvf_SetPayload(Avtp_Rvf_t *pdu, uint8_t *payload, uint16_t payload_length) { - memcpy(pdu->payload, payload, payload_length); + memcpy((uint8_t *)pdu + Avtp_Rvf_GetHeaderLen(pdu), payload, payload_length); } /** - * Initializes an RVF PDU as specified in the IEEE 1722 Specification. + * Initializes a version 0 RVF PDU as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of a 1722 RVF PDU. */ @@ -585,10 +701,28 @@ OPEN1722_INLINE void Avtp_Rvf_Init(Avtp_Rvf_t *pdu) } } +/** + * Initializes a version 1 RVF PDU. The caller must provide a buffer of at least + * AVTP_RVF_HEADER_LEN_V1 octets. + * + * @param pdu Pointer to the first bit of a 1722 RVF PDU. + */ +OPEN1722_INLINE void Avtp_Rvf_InitV1(Avtp_RvfV1_t *pdu) +{ + if (pdu != NULL) { + memset(pdu, 0, sizeof(Avtp_RvfV1_t)); + Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_RVF); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_Rvf_SetSv((Avtp_Rvf_t *)pdu, true); + } +} + /** * Checks if the RVF frame is valid by checking: - * 1) if the stream_data_length field contains a value larger than the actual size of the - * buffer that contains the AVTP message. 2) if other format specific invariants are not upheld. + * 1) that the subtype is RVF and the version is supported, + * 2) that the version-dependent header fits into the buffer, + * 3) that stream_data_length contains at least the raw header and fits into + * the buffer. * * The stream_data_length field contains the length (in octets) of the * stream_data_payload field (IEEE 1722-2025, 4.7.4.12), which for RVF consists @@ -605,11 +739,17 @@ OPEN1722_INLINE bool Avtp_Rvf_IsValid(const Avtp_Rvf_t *const pdu, size_t buffer return false; } - if (bufferSize < AVTP_RVF_HEADER_LEN) { + if (Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu) != AVTP_SUBTYPE_RVF) { return false; } - if (Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu) != AVTP_SUBTYPE_RVF) { + uint8_t version = Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu); + if (!Avtp_Version_IsSupported(AVTP_RVF_SUPPORTED_VERSIONS, version)) { + return false; + } + + size_t headerLen = Avtp_Rvf_GetHeaderLen(pdu); + if (bufferSize < headerLen) { return false; } @@ -620,37 +760,13 @@ OPEN1722_INLINE bool Avtp_Rvf_IsValid(const Avtp_Rvf_t *const pdu, size_t buffer return false; } - if ((size_t)AVTP_RVF_HEADER_LEN + (size_t)stream_data_length > bufferSize) { + if ((size_t)stream_data_length > bufferSize - headerLen) { return false; } return true; } -/** - * Returns the value of an AVTP RVF field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 RVF PDU. - * @param field Specifies the position of the data field to be read - * @returns This function returns the value of the field. - */ -OPEN1722_INLINE uint64_t Avtp_Rvf_GetField(const Avtp_Rvf_t *const pdu, Avtp_RvfFields_t field) -{ - return (uint64_t)GET_RVF_FIELD(field); -} - -/** - * Sets the value of an AVTP RVF field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 RVF PDU. - * @param field Specifies the position of the data field to be written - * @param value The value to set. - */ -OPEN1722_INLINE void Avtp_Rvf_SetField(Avtp_Rvf_t *pdu, Avtp_RvfFields_t field, uint64_t value) -{ - SET_RVF_FIELD(field, value); -} - /****************************************************************************** * RVF raw header * diff --git a/include/avtp/aaf/Aaf.h b/include/avtp/aaf/Aaf.h index 0e864240..00f15ca2 100644 --- a/include/avtp/aaf/Aaf.h +++ b/include/avtp/aaf/Aaf.h @@ -31,6 +31,12 @@ * @file * This file contains the fields descriptions of the IEEE 1722 AAF common stream PDUs and * functions to invoke corresponding parser and deparser. + * + * AAF uses the AVTPDU common stream header (4.7.4) and declares a complete + * descriptor table per version in absolute coordinates: the common stream + * header fields reuse the positions from CommonStreamHeader.h and the + * AAF-specific fields are added by this module. A consistency test keeps the + * common entries aligned with the common stream header module. */ #pragma once @@ -46,23 +52,30 @@ #include "avtp/Utils.h" #include "avtp/Defines.h" #include "avtp/CommonHeader.h" +#include "avtp/CommonStreamHeader.h" #ifdef __cplusplus extern "C" { #endif -#define AVTP_AAF_HEADER_LEN (6 * AVTP_QUADLET_SIZE) +#define AVTP_AAF_HEADER_LEN_V0 AVTPDU_CSH_LEN_V0 /* 24 */ +#define AVTP_AAF_HEADER_LEN_V1 AVTPDU_CSH_LEN_V1 /* 40 */ +/* Kept for compatibility: the version 0 header length. */ +#define AVTP_AAF_HEADER_LEN AVTP_AAF_HEADER_LEN_V0 -#define GET_AAF_FIELD(field) \ - (Avtp_GetField(Avtp_AafFieldDesc, AVTP_AAF_FIELD_MAX, (const uint8_t *)pdu, field)) -#define SET_AAF_FIELD(field, value) \ - (Avtp_SetField(Avtp_AafFieldDesc, AVTP_AAF_FIELD_MAX, (uint8_t *)pdu, field, value)) +/* AAF supports both versions of the common stream header (Table 7). */ +#define AVTP_AAF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) typedef struct { - uint8_t header[AVTP_AAF_HEADER_LEN]; + uint8_t header[AVTP_AAF_HEADER_LEN_V0]; uint8_t payload[0]; } __attribute__((packed)) Avtp_Aaf_t; +typedef struct { + uint8_t header[AVTP_AAF_HEADER_LEN_V1]; + uint8_t payload[0]; +} __attribute__((packed)) Avtp_AafV1_t; + /** * AAF 'format' field values (IEEE 1722-2025, Table 10). Values 0x06-0xFF are * reserved. @@ -87,22 +100,22 @@ typedef enum { typedef enum { /* Common AVTP stream header fields */ - AVTP_AAF_FIELD_SUBTYPE, - AVTP_AAF_FIELD_SV, - AVTP_AAF_FIELD_VERSION, + AVTP_AAF_FIELD_SV = 0, AVTP_AAF_FIELD_MR, - AVTP_AAF_FIELD_RSV, + AVTP_AAF_FIELD_FSD, AVTP_AAF_FIELD_TV, AVTP_AAF_FIELD_SEQUENCE_NUM, - AVTP_AAF_FIELD_RESERVED, + AVTP_AAF_FIELD_FSD0, + AVTP_AAF_FIELD_FSD1, AVTP_AAF_FIELD_TU, - - /* AAF common stream header fields */ AVTP_AAF_FIELD_STREAM_ID, AVTP_AAF_FIELD_AVTP_TIMESTAMP, + AVTP_AAF_FIELD_PTP_GRANDMASTER_IDENTITY, + AVTP_AAF_FIELD_STREAM_DATA_LENGTH, + + /* AAF format-specific fields */ AVTP_AAF_FIELD_FORMAT, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1, - AVTP_AAF_FIELD_STREAM_DATA_LENGTH, AVTP_AAF_FIELD_AFSD, AVTP_AAF_FIELD_SP, AVTP_AAF_FIELD_EVT, @@ -113,31 +126,97 @@ typedef enum { } Avtp_AafFields_t; /** - * This table maps all IEEE 1722 AAF common stream header fields to a descriptor. + * This table maps all IEEE 1722 AAF header fields to a descriptor for version 0. + * It is complete and in absolute coordinates; the common stream header fields + * use the same positions as Avtp_CshFieldDescV0. */ -static const Avtp_FieldDescriptor_t Avtp_AafFieldDesc[AVTP_AAF_FIELD_MAX] = { - /* Common AVTP stream header fields */ - [AVTP_AAF_FIELD_SUBTYPE] = {.quadlet = 0, .offset = 0, .bits = 8}, +static const Avtp_FieldDescriptor_t Avtp_AafFieldDescV0[AVTP_AAF_FIELD_MAX] = { [AVTP_AAF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, - [AVTP_AAF_FIELD_VERSION] = {.quadlet = 0, .offset = 9, .bits = 3}, [AVTP_AAF_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, - [AVTP_AAF_FIELD_RSV] = {.quadlet = 0, .offset = 13, .bits = 2}, + [AVTP_AAF_FIELD_FSD] = {.quadlet = 0, .offset = 13, .bits = 2}, [AVTP_AAF_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, [AVTP_AAF_FIELD_SEQUENCE_NUM] = {.quadlet = 0, .offset = 16, .bits = 8}, - [AVTP_AAF_FIELD_RESERVED] = {.quadlet = 0, .offset = 24, .bits = 7}, + [AVTP_AAF_FIELD_FSD0] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_AAF_FIELD_FSD1] = {.quadlet = 0, .offset = 24, .bits = 7}, [AVTP_AAF_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, - /* AAF common stream header fields */ [AVTP_AAF_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, [AVTP_AAF_FIELD_AVTP_TIMESTAMP] = {.quadlet = 3, .offset = 0, .bits = 32}, + [AVTP_AAF_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_AAF_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 5, .offset = 0, .bits = 16}, [AVTP_AAF_FIELD_FORMAT] = {.quadlet = 4, .offset = 0, .bits = 8}, [AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1] = {.quadlet = 4, .offset = 8, .bits = 24}, - [AVTP_AAF_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 5, .offset = 0, .bits = 16}, [AVTP_AAF_FIELD_AFSD] = {.quadlet = 5, .offset = 16, .bits = 3}, [AVTP_AAF_FIELD_SP] = {.quadlet = 5, .offset = 19, .bits = 1}, [AVTP_AAF_FIELD_EVT] = {.quadlet = 5, .offset = 20, .bits = 4}, [AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2] = {.quadlet = 5, .offset = 24, .bits = 8}, }; +/** + * This table maps all IEEE 1722 AAF header fields to a descriptor for version 1. + * It is complete and in absolute coordinates; the common stream header fields + * use the same positions as Avtp_CshFieldDescV1. + */ +static const Avtp_FieldDescriptor_t Avtp_AafFieldDescV1[AVTP_AAF_FIELD_MAX] = { + [AVTP_AAF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, + [AVTP_AAF_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, + [AVTP_AAF_FIELD_FSD] = {.quadlet = 0, .offset = 13, .bits = 2}, + [AVTP_AAF_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, + [AVTP_AAF_FIELD_SEQUENCE_NUM] = {.quadlet = 3, .offset = 0, .bits = 32}, + [AVTP_AAF_FIELD_FSD0] = {.quadlet = 0, .offset = 16, .bits = 8}, + [AVTP_AAF_FIELD_FSD1] = {.quadlet = 0, .offset = 24, .bits = 7}, + [AVTP_AAF_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, + [AVTP_AAF_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, + [AVTP_AAF_FIELD_AVTP_TIMESTAMP] = {.quadlet = 4, .offset = 0, .bits = 64}, + [AVTP_AAF_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 6, .offset = 0, .bits = 64}, + [AVTP_AAF_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 9, .offset = 0, .bits = 16}, + [AVTP_AAF_FIELD_FORMAT] = {.quadlet = 8, .offset = 0, .bits = 8}, + [AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1] = {.quadlet = 8, .offset = 8, .bits = 24}, + [AVTP_AAF_FIELD_AFSD] = {.quadlet = 9, .offset = 16, .bits = 3}, + [AVTP_AAF_FIELD_SP] = {.quadlet = 9, .offset = 19, .bits = 1}, + [AVTP_AAF_FIELD_EVT] = {.quadlet = 9, .offset = 20, .bits = 4}, + [AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2] = {.quadlet = 9, .offset = 24, .bits = 8}, +}; + +/** + * Returns the value of an AVTP AAF field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 AAF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + */ +OPEN1722_INLINE uint64_t Avtp_Aaf_GetField(const Avtp_Aaf_t *const pdu, Avtp_AafFields_t field) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_AafFieldDescV1 + : Avtp_AafFieldDescV0; + return Avtp_GetField(desc, AVTP_AAF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); +} + +/** + * Sets the value of an AVTP AAF field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 AAF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + */ +OPEN1722_INLINE void Avtp_Aaf_SetField(Avtp_Aaf_t *pdu, Avtp_AafFields_t field, uint64_t value) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_AafFieldDescV1 + : Avtp_AafFieldDescV0; + Avtp_SetField(desc, AVTP_AAF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Returns the length of the AAF header in octets (24 or 40). + */ +OPEN1722_INLINE uint8_t Avtp_Aaf_GetHeaderLen(const Avtp_Aaf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); +} + /** * Return the value of the AAF SV field as specified in the IEEE 1722 Specification. * @@ -146,7 +225,7 @@ static const Avtp_FieldDescriptor_t Avtp_AafFieldDesc[AVTP_AAF_FIELD_MAX] = { */ OPEN1722_INLINE bool Avtp_Aaf_IsSv(const Avtp_Aaf_t *const pdu) { - return (bool)GET_AAF_FIELD(AVTP_AAF_FIELD_SV); + return (bool)Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_SV); } /** @@ -157,7 +236,7 @@ OPEN1722_INLINE bool Avtp_Aaf_IsSv(const Avtp_Aaf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Aaf_IsMr(const Avtp_Aaf_t *const pdu) { - return (bool)GET_AAF_FIELD(AVTP_AAF_FIELD_MR); + return (bool)Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_MR); } /** @@ -168,18 +247,19 @@ OPEN1722_INLINE bool Avtp_Aaf_IsMr(const Avtp_Aaf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Aaf_IsTv(const Avtp_Aaf_t *const pdu) { - return (bool)GET_AAF_FIELD(AVTP_AAF_FIELD_TV); + return (bool)Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_TV); } /** * Return the value of the AAF Sequence Number field as specified in the IEEE 1722 Specification. + * The field is 8 bits in version 0 and 32 bits in version 1. * * @param pdu Pointer to the first bit of an 1722 AAF PDU. * @returns Value of the AAF Sequence Number field. */ -OPEN1722_INLINE uint8_t Avtp_Aaf_GetSequenceNum(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Aaf_GetSequenceNum(const Avtp_Aaf_t *const pdu) { - return (uint8_t)GET_AAF_FIELD(AVTP_AAF_FIELD_SEQUENCE_NUM); + return (uint32_t)Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_SEQUENCE_NUM); } /** @@ -190,7 +270,7 @@ OPEN1722_INLINE uint8_t Avtp_Aaf_GetSequenceNum(const Avtp_Aaf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Aaf_IsTu(const Avtp_Aaf_t *const pdu) { - return (bool)GET_AAF_FIELD(AVTP_AAF_FIELD_TU); + return (bool)Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_TU); } /** @@ -201,18 +281,31 @@ OPEN1722_INLINE bool Avtp_Aaf_IsTu(const Avtp_Aaf_t *const pdu) */ OPEN1722_INLINE uint64_t Avtp_Aaf_GetStreamId(const Avtp_Aaf_t *const pdu) { - return (uint64_t)GET_AAF_FIELD(AVTP_AAF_FIELD_STREAM_ID); + return Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_STREAM_ID); } /** * Return the value of the AAF AVTP Timestamp field as specified in the IEEE 1722 Specification. + * The field is 32 bits in version 0 and 64 bits in version 1. * * @param pdu Pointer to the first bit of an 1722 AAF PDU. * @returns Value of the AAF AVTP Timestamp field. */ -OPEN1722_INLINE uint32_t Avtp_Aaf_GetAvtpTimestamp(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Aaf_GetAvtpTimestamp(const Avtp_Aaf_t *const pdu) +{ + return Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_AVTP_TIMESTAMP); +} + +/** + * Return the value of the AAF ptp_grandmaster_identity field. The field only + * exists in version 1; version 0 returns 0. + * + * @param pdu Pointer to the first bit of an 1722 AAF PDU. + * @returns Value of the AAF ptp_grandmaster_identity field. + */ +OPEN1722_INLINE uint64_t Avtp_Aaf_GetPtpGrandmasterIdentity(const Avtp_Aaf_t *const pdu) { - return (uint32_t)GET_AAF_FIELD(AVTP_AAF_FIELD_AVTP_TIMESTAMP); + return Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_PTP_GRANDMASTER_IDENTITY); } /** @@ -223,7 +316,7 @@ OPEN1722_INLINE uint32_t Avtp_Aaf_GetAvtpTimestamp(const Avtp_Aaf_t *const pdu) */ OPEN1722_INLINE Avtp_AafFormat_t Avtp_Aaf_GetFormat(const Avtp_Aaf_t *const pdu) { - return (Avtp_AafFormat_t)GET_AAF_FIELD(AVTP_AAF_FIELD_FORMAT); + return (Avtp_AafFormat_t)Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_FORMAT); } /** @@ -235,7 +328,7 @@ OPEN1722_INLINE Avtp_AafFormat_t Avtp_Aaf_GetFormat(const Avtp_Aaf_t *const pdu) */ OPEN1722_INLINE uint32_t Avtp_Aaf_GetAafFormatSpecificData1(const Avtp_Aaf_t *const pdu) { - return (uint32_t)GET_AAF_FIELD(AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1); + return (uint32_t)Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1); } /** @@ -247,7 +340,7 @@ OPEN1722_INLINE uint32_t Avtp_Aaf_GetAafFormatSpecificData1(const Avtp_Aaf_t *co */ OPEN1722_INLINE uint16_t Avtp_Aaf_GetStreamDataLength(const Avtp_Aaf_t *const pdu) { - return (uint16_t)GET_AAF_FIELD(AVTP_AAF_FIELD_STREAM_DATA_LENGTH); + return (uint16_t)Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_STREAM_DATA_LENGTH); } /** @@ -258,7 +351,7 @@ OPEN1722_INLINE uint16_t Avtp_Aaf_GetStreamDataLength(const Avtp_Aaf_t *const pd */ OPEN1722_INLINE uint8_t Avtp_Aaf_GetAfsd(const Avtp_Aaf_t *const pdu) { - return (uint8_t)GET_AAF_FIELD(AVTP_AAF_FIELD_AFSD); + return (uint8_t)Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_AFSD); } /** @@ -269,7 +362,7 @@ OPEN1722_INLINE uint8_t Avtp_Aaf_GetAfsd(const Avtp_Aaf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Aaf_IsSp(const Avtp_Aaf_t *const pdu) { - return (bool)GET_AAF_FIELD(AVTP_AAF_FIELD_SP); + return (bool)Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_SP); } /** @@ -280,7 +373,7 @@ OPEN1722_INLINE bool Avtp_Aaf_IsSp(const Avtp_Aaf_t *const pdu) */ OPEN1722_INLINE uint8_t Avtp_Aaf_GetEvt(const Avtp_Aaf_t *const pdu) { - return (uint8_t)GET_AAF_FIELD(AVTP_AAF_FIELD_EVT); + return (uint8_t)Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_EVT); } /** @@ -292,7 +385,7 @@ OPEN1722_INLINE uint8_t Avtp_Aaf_GetEvt(const Avtp_Aaf_t *const pdu) */ OPEN1722_INLINE uint8_t Avtp_Aaf_GetAafFormatSpecificData2(const Avtp_Aaf_t *const pdu) { - return (uint8_t)GET_AAF_FIELD(AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2); + return (uint8_t)Avtp_Aaf_GetField(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2); } /** @@ -303,7 +396,7 @@ OPEN1722_INLINE uint8_t Avtp_Aaf_GetAafFormatSpecificData2(const Avtp_Aaf_t *con */ OPEN1722_INLINE void Avtp_Aaf_SetSv(Avtp_Aaf_t *pdu, bool sv) { - SET_AAF_FIELD(AVTP_AAF_FIELD_SV, sv); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_SV, sv); } /** @@ -314,7 +407,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetSv(Avtp_Aaf_t *pdu, bool sv) */ OPEN1722_INLINE void Avtp_Aaf_SetMr(Avtp_Aaf_t *pdu, bool mr) { - SET_AAF_FIELD(AVTP_AAF_FIELD_MR, mr); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_MR, mr); } /** @@ -325,18 +418,20 @@ OPEN1722_INLINE void Avtp_Aaf_SetMr(Avtp_Aaf_t *pdu, bool mr) */ OPEN1722_INLINE void Avtp_Aaf_SetTv(Avtp_Aaf_t *pdu, bool tv) { - SET_AAF_FIELD(AVTP_AAF_FIELD_TV, tv); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_TV, tv); } /** * Set the value of the AAF Sequence Number field as specified in the IEEE 1722 Specification. + * The field is 8 bits in version 0 and 32 bits in version 1; values are truncated to the + * width of the version in use. * * @param pdu Pointer to the first bit of an 1722 AAF PDU. * @param value Value to set the AAF Sequence Number field to. */ -OPEN1722_INLINE void Avtp_Aaf_SetSequenceNum(Avtp_Aaf_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Aaf_SetSequenceNum(Avtp_Aaf_t *pdu, uint32_t value) { - SET_AAF_FIELD(AVTP_AAF_FIELD_SEQUENCE_NUM, value); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_SEQUENCE_NUM, value); } /** @@ -347,7 +442,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetSequenceNum(Avtp_Aaf_t *pdu, uint8_t value) */ OPEN1722_INLINE void Avtp_Aaf_SetTu(Avtp_Aaf_t *pdu, bool tu) { - SET_AAF_FIELD(AVTP_AAF_FIELD_TU, tu); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_TU, tu); } /** @@ -358,18 +453,32 @@ OPEN1722_INLINE void Avtp_Aaf_SetTu(Avtp_Aaf_t *pdu, bool tu) */ OPEN1722_INLINE void Avtp_Aaf_SetStreamId(Avtp_Aaf_t *pdu, uint64_t value) { - SET_AAF_FIELD(AVTP_AAF_FIELD_STREAM_ID, value); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_STREAM_ID, value); } /** * Set the value of the AAF AVTP Timestamp field as specified in the IEEE 1722 Specification. + * The field is 32 bits in version 0 and 64 bits in version 1; values are truncated to the + * width of the version in use. * * @param pdu Pointer to the first bit of an 1722 AAF PDU. * @param value Value to set the AAF AVTP Timestamp field to. */ -OPEN1722_INLINE void Avtp_Aaf_SetAvtpTimestamp(Avtp_Aaf_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Aaf_SetAvtpTimestamp(Avtp_Aaf_t *pdu, uint64_t value) { - SET_AAF_FIELD(AVTP_AAF_FIELD_AVTP_TIMESTAMP, value); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_AVTP_TIMESTAMP, value); +} + +/** + * Set the value of the AAF ptp_grandmaster_identity field. The field only + * exists in version 1; on version 0 this is a no-op. + * + * @param pdu Pointer to the first bit of an 1722 AAF PDU. + * @param value Value to set the AAF ptp_grandmaster_identity field to. + */ +OPEN1722_INLINE void Avtp_Aaf_SetPtpGrandmasterIdentity(Avtp_Aaf_t *pdu, uint64_t value) +{ + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_PTP_GRANDMASTER_IDENTITY, value); } /** @@ -380,7 +489,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetAvtpTimestamp(Avtp_Aaf_t *pdu, uint32_t value) */ OPEN1722_INLINE void Avtp_Aaf_SetFormat(Avtp_Aaf_t *pdu, Avtp_AafFormat_t value) { - SET_AAF_FIELD(AVTP_AAF_FIELD_FORMAT, (uint64_t)value); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_FORMAT, (uint64_t)value); } /** @@ -392,7 +501,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetFormat(Avtp_Aaf_t *pdu, Avtp_AafFormat_t value) */ OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData1(Avtp_Aaf_t *pdu, uint32_t value) { - SET_AAF_FIELD(AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1, value); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1, value); } /** @@ -404,7 +513,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData1(Avtp_Aaf_t *pdu, uint32_ */ OPEN1722_INLINE void Avtp_Aaf_SetStreamDataLength(Avtp_Aaf_t *pdu, uint16_t value) { - SET_AAF_FIELD(AVTP_AAF_FIELD_STREAM_DATA_LENGTH, value); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_STREAM_DATA_LENGTH, value); } /** @@ -415,7 +524,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetStreamDataLength(Avtp_Aaf_t *pdu, uint16_t valu */ OPEN1722_INLINE void Avtp_Aaf_SetAfsd(Avtp_Aaf_t *pdu, uint8_t value) { - SET_AAF_FIELD(AVTP_AAF_FIELD_AFSD, value); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_AFSD, value); } /** @@ -426,7 +535,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetAfsd(Avtp_Aaf_t *pdu, uint8_t value) */ OPEN1722_INLINE void Avtp_Aaf_SetSp(Avtp_Aaf_t *pdu, bool sp) { - SET_AAF_FIELD(AVTP_AAF_FIELD_SP, sp); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_SP, sp); } /** @@ -437,7 +546,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetSp(Avtp_Aaf_t *pdu, bool sp) */ OPEN1722_INLINE void Avtp_Aaf_SetEvt(Avtp_Aaf_t *pdu, uint8_t value) { - SET_AAF_FIELD(AVTP_AAF_FIELD_EVT, value); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_EVT, value); } /** @@ -449,18 +558,19 @@ OPEN1722_INLINE void Avtp_Aaf_SetEvt(Avtp_Aaf_t *pdu, uint8_t value) */ OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData2(Avtp_Aaf_t *pdu, uint8_t value) { - SET_AAF_FIELD(AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2, value); + Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2, value); } /** - * Returns pointer to payload of an AAF frame. + * Returns pointer to payload of an AAF frame. The payload starts after the + * version-dependent common stream header. * * @param pdu Pointer to the first bit of an 1722 AAF PDU. * @return Pointer to AAF frame payload */ OPEN1722_INLINE const uint8_t *Avtp_Aaf_GetPayload(const Avtp_Aaf_t *const pdu) { - return pdu->payload; + return (const uint8_t *)pdu + Avtp_Aaf_GetHeaderLen(pdu); } /** @@ -472,11 +582,11 @@ OPEN1722_INLINE const uint8_t *Avtp_Aaf_GetPayload(const Avtp_Aaf_t *const pdu) */ OPEN1722_INLINE void Avtp_Aaf_SetPayload(Avtp_Aaf_t *pdu, uint8_t *payload, uint16_t payload_length) { - memcpy(pdu->payload, payload, payload_length); + memcpy((uint8_t *)pdu + Avtp_Aaf_GetHeaderLen(pdu), payload, payload_length); } /** - * Initializes an AAF PDU as specified in the IEEE 1722 Specification. + * Initializes a version 0 AAF PDU as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of a 1722 AAF PDU. */ @@ -489,10 +599,27 @@ OPEN1722_INLINE void Avtp_Aaf_Init(Avtp_Aaf_t *pdu) } } +/** + * Initializes a version 1 AAF PDU. The caller must provide a buffer of at least + * AVTP_AAF_HEADER_LEN_V1 octets. + * + * @param pdu Pointer to the first bit of a 1722 AAF PDU. + */ +OPEN1722_INLINE void Avtp_Aaf_InitV1(Avtp_AafV1_t *pdu) +{ + if (pdu != NULL) { + memset(pdu, 0, sizeof(Avtp_AafV1_t)); + Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_AAF); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_Aaf_SetSv((Avtp_Aaf_t *)pdu, true); + } +} + /** * Checks if the AAF frame is valid by checking: - * 1) if the length field of the AAF stream data contains a value larger than the actual size of - * the buffer that contains the AVTP message. 2) if other format specific invariants are not upheld. + * 1) that the subtype is AAF and the version is supported, + * 2) that the version-dependent header fits into the buffer, + * 3) that the declared stream_data_length fits into the buffer. * * The stream_data_length field contains the length (in octets) of the * stream_data_payload field (IEEE 1722-2025, 4.7.4.12), so the whole AVTPDU @@ -508,43 +635,25 @@ OPEN1722_INLINE bool Avtp_Aaf_IsValid(const Avtp_Aaf_t *const pdu, size_t buffer return false; } - if (bufferSize < AVTP_AAF_HEADER_LEN) { + if (Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu) != AVTP_SUBTYPE_AAF) { return false; } - if (Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu) != AVTP_SUBTYPE_AAF) { + uint8_t version = Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu); + if (!Avtp_Version_IsSupported(AVTP_AAF_SUPPORTED_VERSIONS, version)) { return false; } - if ((size_t)AVTP_AAF_HEADER_LEN + (size_t)Avtp_Aaf_GetStreamDataLength(pdu) > bufferSize) { + size_t headerLen = Avtp_Aaf_GetHeaderLen(pdu); + if (bufferSize < headerLen) { return false; } - return true; -} - -/** - * Returns the value of an AVTP AAF field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 AAF PDU. - * @param field Specifies the position of the data field to be read - * @returns This function returns the value of the field. - */ -OPEN1722_INLINE uint64_t Avtp_Aaf_GetField(const Avtp_Aaf_t *const pdu, Avtp_AafFields_t field) -{ - return (uint64_t)GET_AAF_FIELD(field); -} + if ((size_t)Avtp_Aaf_GetStreamDataLength(pdu) > bufferSize - headerLen) { + return false; + } -/** - * Sets the value of an AVTP AAF field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 AAF PDU. - * @param field Specifies the position of the data field to be written - * @param value The value to set. - */ -OPEN1722_INLINE void Avtp_Aaf_SetField(Avtp_Aaf_t *pdu, Avtp_AafFields_t field, uint64_t value) -{ - SET_AAF_FIELD(field, value); + return true; } #ifdef __cplusplus diff --git a/include/avtp/aaf/Pcm.h b/include/avtp/aaf/Pcm.h index ad859771..798f36ee 100644 --- a/include/avtp/aaf/Pcm.h +++ b/include/avtp/aaf/Pcm.h @@ -30,8 +30,15 @@ /** * @file - * This file contains the fields descriptions of the IEEE 1722 AAF PCM stream PDUs and + * This file contains the fields descriptions of the IEEE 1722 AAF PCM PDUs and * functions to invoke corresponding parser and deparser. + * + * PCM is an AAF subformat (subtype AAF, format field selects PCM). It declares + * a complete descriptor table per version in absolute coordinates: the common + * stream header fields reuse the positions from CommonStreamHeader.h and the + * PCM-specific fields are added by this module. A consistency test keeps the + * common entries aligned with the common stream header module and the fields + * shared with AAF aligned with the AAF module. */ #pragma once @@ -47,23 +54,30 @@ #include "avtp/Utils.h" #include "avtp/Defines.h" #include "avtp/aaf/Aaf.h" +#include "avtp/CommonStreamHeader.h" #ifdef __cplusplus extern "C" { #endif -#define AVTP_PCM_HEADER_LEN (6 * AVTP_QUADLET_SIZE) +#define AVTP_PCM_HEADER_LEN_V0 AVTPDU_CSH_LEN_V0 /* 24 */ +#define AVTP_PCM_HEADER_LEN_V1 AVTPDU_CSH_LEN_V1 /* 40 */ +/* Kept for compatibility: the version 0 header length. */ +#define AVTP_PCM_HEADER_LEN AVTP_PCM_HEADER_LEN_V0 -#define GET_PCM_FIELD(field) \ - (Avtp_GetField(Avtp_PcmFieldDesc, AVTP_PCM_FIELD_MAX, (const uint8_t *)pdu, field)) -#define SET_PCM_FIELD(field, value) \ - (Avtp_SetField(Avtp_PcmFieldDesc, AVTP_PCM_FIELD_MAX, (uint8_t *)pdu, field, value)) +/* PCM (AAF) supports both versions of the common stream header (Table 7). */ +#define AVTP_PCM_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) typedef struct { - uint8_t header[AVTP_PCM_HEADER_LEN]; + uint8_t header[AVTP_PCM_HEADER_LEN_V0]; uint8_t payload[0]; } __attribute__((packed)) Avtp_Pcm_t; +typedef struct { + uint8_t header[AVTP_PCM_HEADER_LEN_V1]; + uint8_t payload[0]; +} __attribute__((packed)) Avtp_PcmV1_t; + /** * AAF PCM 'nsr' (nominal sample rate) field values (IEEE 1722-2025, Table 12). * Values 0x0B-0x0F are reserved. @@ -85,25 +99,25 @@ typedef enum { typedef enum { /* Common AVTP stream header fields */ - AVTP_PCM_FIELD_SUBTYPE, - AVTP_PCM_FIELD_SV, - AVTP_PCM_FIELD_VERSION, + AVTP_PCM_FIELD_SV = 0, AVTP_PCM_FIELD_MR, - AVTP_PCM_FIELD_RSV1, + AVTP_PCM_FIELD_FSD, AVTP_PCM_FIELD_TV, AVTP_PCM_FIELD_SEQUENCE_NUM, - AVTP_PCM_FIELD_RESERVED1, + AVTP_PCM_FIELD_FSD0, + AVTP_PCM_FIELD_FSD1, AVTP_PCM_FIELD_TU, - - /* AAF PCM stream header fields */ AVTP_PCM_FIELD_STREAM_ID, AVTP_PCM_FIELD_AVTP_TIMESTAMP, + AVTP_PCM_FIELD_PTP_GRANDMASTER_IDENTITY, + AVTP_PCM_FIELD_STREAM_DATA_LENGTH, + + /* AAF PCM format-specific fields */ AVTP_PCM_FIELD_FORMAT, AVTP_PCM_FIELD_NSR, AVTP_PCM_FIELD_RSV2, AVTP_PCM_FIELD_CHANNELS_PER_FRAME, AVTP_PCM_FIELD_BIT_DEPTH, - AVTP_PCM_FIELD_STREAM_DATA_LENGTH, AVTP_PCM_FIELD_RSV3, AVTP_PCM_FIELD_SP, AVTP_PCM_FIELD_EVT, @@ -114,34 +128,103 @@ typedef enum { } Avtp_PcmFields_t; /** - * This table maps all IEEE 1722 AAF PCM stream header fields to a descriptor. + * This table maps all IEEE 1722 AAF PCM header fields to a descriptor for + * version 0. It is complete and in absolute coordinates; the common stream + * header fields use the same positions as Avtp_CshFieldDescV0. */ -static const Avtp_FieldDescriptor_t Avtp_PcmFieldDesc[AVTP_PCM_FIELD_MAX] = { - /* Common AVTP stream header fields */ - [AVTP_PCM_FIELD_SUBTYPE] = {.quadlet = 0, .offset = 0, .bits = 8}, +static const Avtp_FieldDescriptor_t Avtp_PcmFieldDescV0[AVTP_PCM_FIELD_MAX] = { [AVTP_PCM_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, - [AVTP_PCM_FIELD_VERSION] = {.quadlet = 0, .offset = 9, .bits = 3}, [AVTP_PCM_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, - [AVTP_PCM_FIELD_RSV1] = {.quadlet = 0, .offset = 13, .bits = 2}, + [AVTP_PCM_FIELD_FSD] = {.quadlet = 0, .offset = 13, .bits = 2}, [AVTP_PCM_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, [AVTP_PCM_FIELD_SEQUENCE_NUM] = {.quadlet = 0, .offset = 16, .bits = 8}, - [AVTP_PCM_FIELD_RESERVED1] = {.quadlet = 0, .offset = 24, .bits = 7}, + [AVTP_PCM_FIELD_FSD0] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_PCM_FIELD_FSD1] = {.quadlet = 0, .offset = 24, .bits = 7}, [AVTP_PCM_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, - /* AAF PCM stream header fields */ [AVTP_PCM_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, [AVTP_PCM_FIELD_AVTP_TIMESTAMP] = {.quadlet = 3, .offset = 0, .bits = 32}, + [AVTP_PCM_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_PCM_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 5, .offset = 0, .bits = 16}, [AVTP_PCM_FIELD_FORMAT] = {.quadlet = 4, .offset = 0, .bits = 8}, [AVTP_PCM_FIELD_NSR] = {.quadlet = 4, .offset = 8, .bits = 4}, [AVTP_PCM_FIELD_RSV2] = {.quadlet = 4, .offset = 12, .bits = 2}, [AVTP_PCM_FIELD_CHANNELS_PER_FRAME] = {.quadlet = 4, .offset = 14, .bits = 10}, [AVTP_PCM_FIELD_BIT_DEPTH] = {.quadlet = 4, .offset = 24, .bits = 8}, - [AVTP_PCM_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 5, .offset = 0, .bits = 16}, [AVTP_PCM_FIELD_RSV3] = {.quadlet = 5, .offset = 16, .bits = 3}, [AVTP_PCM_FIELD_SP] = {.quadlet = 5, .offset = 19, .bits = 1}, [AVTP_PCM_FIELD_EVT] = {.quadlet = 5, .offset = 20, .bits = 4}, [AVTP_PCM_FIELD_RESERVED2] = {.quadlet = 5, .offset = 24, .bits = 8}, }; +/** + * This table maps all IEEE 1722 AAF PCM header fields to a descriptor for + * version 1. It is complete and in absolute coordinates; the common stream + * header fields use the same positions as Avtp_CshFieldDescV1. + */ +static const Avtp_FieldDescriptor_t Avtp_PcmFieldDescV1[AVTP_PCM_FIELD_MAX] = { + [AVTP_PCM_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, + [AVTP_PCM_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, + [AVTP_PCM_FIELD_FSD] = {.quadlet = 0, .offset = 13, .bits = 2}, + [AVTP_PCM_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, + [AVTP_PCM_FIELD_SEQUENCE_NUM] = {.quadlet = 3, .offset = 0, .bits = 32}, + [AVTP_PCM_FIELD_FSD0] = {.quadlet = 0, .offset = 16, .bits = 8}, + [AVTP_PCM_FIELD_FSD1] = {.quadlet = 0, .offset = 24, .bits = 7}, + [AVTP_PCM_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, + [AVTP_PCM_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, + [AVTP_PCM_FIELD_AVTP_TIMESTAMP] = {.quadlet = 4, .offset = 0, .bits = 64}, + [AVTP_PCM_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 6, .offset = 0, .bits = 64}, + [AVTP_PCM_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 9, .offset = 0, .bits = 16}, + [AVTP_PCM_FIELD_FORMAT] = {.quadlet = 8, .offset = 0, .bits = 8}, + [AVTP_PCM_FIELD_NSR] = {.quadlet = 8, .offset = 8, .bits = 4}, + [AVTP_PCM_FIELD_RSV2] = {.quadlet = 8, .offset = 12, .bits = 2}, + [AVTP_PCM_FIELD_CHANNELS_PER_FRAME] = {.quadlet = 8, .offset = 14, .bits = 10}, + [AVTP_PCM_FIELD_BIT_DEPTH] = {.quadlet = 8, .offset = 24, .bits = 8}, + [AVTP_PCM_FIELD_RSV3] = {.quadlet = 9, .offset = 16, .bits = 3}, + [AVTP_PCM_FIELD_SP] = {.quadlet = 9, .offset = 19, .bits = 1}, + [AVTP_PCM_FIELD_EVT] = {.quadlet = 9, .offset = 20, .bits = 4}, + [AVTP_PCM_FIELD_RESERVED2] = {.quadlet = 9, .offset = 24, .bits = 8}, +}; + +/** + * Returns the value of an AVTP AAF PCM field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + */ +OPEN1722_INLINE uint64_t Avtp_Pcm_GetField(const Avtp_Pcm_t *const pdu, Avtp_PcmFields_t field) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_PcmFieldDescV1 + : Avtp_PcmFieldDescV0; + return Avtp_GetField(desc, AVTP_PCM_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); +} + +/** + * Sets the value of an AVTP AAF PCM field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + */ +OPEN1722_INLINE void Avtp_Pcm_SetField(Avtp_Pcm_t *pdu, Avtp_PcmFields_t field, uint64_t value) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_PcmFieldDescV1 + : Avtp_PcmFieldDescV0; + Avtp_SetField(desc, AVTP_PCM_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Returns the length of the AAF PCM header in octets (24 or 40). + */ +OPEN1722_INLINE uint8_t Avtp_Pcm_GetHeaderLen(const Avtp_Pcm_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); +} + /** * Return the value of the AAF PCM SV field as specified in the IEEE 1722 Specification. * @@ -150,7 +233,7 @@ static const Avtp_FieldDescriptor_t Avtp_PcmFieldDesc[AVTP_PCM_FIELD_MAX] = { */ OPEN1722_INLINE bool Avtp_Pcm_IsSv(const Avtp_Pcm_t *const pdu) { - return (bool)GET_PCM_FIELD(AVTP_PCM_FIELD_SV); + return (bool)Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_SV); } /** @@ -161,7 +244,7 @@ OPEN1722_INLINE bool Avtp_Pcm_IsSv(const Avtp_Pcm_t *const pdu) */ OPEN1722_INLINE bool Avtp_Pcm_IsMr(const Avtp_Pcm_t *const pdu) { - return (bool)GET_PCM_FIELD(AVTP_PCM_FIELD_MR); + return (bool)Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_MR); } /** @@ -172,19 +255,19 @@ OPEN1722_INLINE bool Avtp_Pcm_IsMr(const Avtp_Pcm_t *const pdu) */ OPEN1722_INLINE bool Avtp_Pcm_IsTv(const Avtp_Pcm_t *const pdu) { - return (bool)GET_PCM_FIELD(AVTP_PCM_FIELD_TV); + return (bool)Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_TV); } /** * Return the value of the AAF PCM Sequence Number field as specified in the IEEE 1722 - * Specification. + * Specification. The field is 8 bits in version 0 and 32 bits in version 1. * * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. * @returns Value of the AAF PCM Sequence Number field. */ -OPEN1722_INLINE uint8_t Avtp_Pcm_GetSequenceNum(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Pcm_GetSequenceNum(const Avtp_Pcm_t *const pdu) { - return (uint8_t)GET_PCM_FIELD(AVTP_PCM_FIELD_SEQUENCE_NUM); + return (uint32_t)Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_SEQUENCE_NUM); } /** @@ -195,7 +278,7 @@ OPEN1722_INLINE uint8_t Avtp_Pcm_GetSequenceNum(const Avtp_Pcm_t *const pdu) */ OPEN1722_INLINE bool Avtp_Pcm_IsTu(const Avtp_Pcm_t *const pdu) { - return (bool)GET_PCM_FIELD(AVTP_PCM_FIELD_TU); + return (bool)Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_TU); } /** @@ -206,19 +289,31 @@ OPEN1722_INLINE bool Avtp_Pcm_IsTu(const Avtp_Pcm_t *const pdu) */ OPEN1722_INLINE uint64_t Avtp_Pcm_GetStreamId(const Avtp_Pcm_t *const pdu) { - return (uint64_t)GET_PCM_FIELD(AVTP_PCM_FIELD_STREAM_ID); + return Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_STREAM_ID); } /** * Return the value of the AAF PCM AVTP Timestamp field as specified in the IEEE 1722 - * Specification. + * Specification. The field is 32 bits in version 0 and 64 bits in version 1. * * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. * @returns Value of the AAF PCM AVTP Timestamp field. */ -OPEN1722_INLINE uint32_t Avtp_Pcm_GetAvtpTimestamp(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Pcm_GetAvtpTimestamp(const Avtp_Pcm_t *const pdu) { - return (uint32_t)GET_PCM_FIELD(AVTP_PCM_FIELD_AVTP_TIMESTAMP); + return Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_AVTP_TIMESTAMP); +} + +/** + * Return the value of the AAF PCM ptp_grandmaster_identity field. The field only + * exists in version 1; version 0 returns 0. + * + * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. + * @returns Value of the AAF PCM ptp_grandmaster_identity field. + */ +OPEN1722_INLINE uint64_t Avtp_Pcm_GetPtpGrandmasterIdentity(const Avtp_Pcm_t *const pdu) +{ + return Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_PTP_GRANDMASTER_IDENTITY); } /** @@ -229,7 +324,7 @@ OPEN1722_INLINE uint32_t Avtp_Pcm_GetAvtpTimestamp(const Avtp_Pcm_t *const pdu) */ OPEN1722_INLINE Avtp_AafFormat_t Avtp_Pcm_GetFormat(const Avtp_Pcm_t *const pdu) { - return (Avtp_AafFormat_t)GET_PCM_FIELD(AVTP_PCM_FIELD_FORMAT); + return (Avtp_AafFormat_t)Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_FORMAT); } /** @@ -240,7 +335,7 @@ OPEN1722_INLINE Avtp_AafFormat_t Avtp_Pcm_GetFormat(const Avtp_Pcm_t *const pdu) */ OPEN1722_INLINE Avtp_PcmNsr_t Avtp_Pcm_GetNsr(const Avtp_Pcm_t *const pdu) { - return (Avtp_PcmNsr_t)GET_PCM_FIELD(AVTP_PCM_FIELD_NSR); + return (Avtp_PcmNsr_t)Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_NSR); } /** @@ -252,7 +347,7 @@ OPEN1722_INLINE Avtp_PcmNsr_t Avtp_Pcm_GetNsr(const Avtp_Pcm_t *const pdu) */ OPEN1722_INLINE uint16_t Avtp_Pcm_GetChannelsPerFrame(const Avtp_Pcm_t *const pdu) { - return (uint16_t)GET_PCM_FIELD(AVTP_PCM_FIELD_CHANNELS_PER_FRAME); + return (uint16_t)Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_CHANNELS_PER_FRAME); } /** @@ -263,7 +358,7 @@ OPEN1722_INLINE uint16_t Avtp_Pcm_GetChannelsPerFrame(const Avtp_Pcm_t *const pd */ OPEN1722_INLINE uint8_t Avtp_Pcm_GetBitDepth(const Avtp_Pcm_t *const pdu) { - return (uint8_t)GET_PCM_FIELD(AVTP_PCM_FIELD_BIT_DEPTH); + return (uint8_t)Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_BIT_DEPTH); } /** @@ -275,7 +370,7 @@ OPEN1722_INLINE uint8_t Avtp_Pcm_GetBitDepth(const Avtp_Pcm_t *const pdu) */ OPEN1722_INLINE uint16_t Avtp_Pcm_GetStreamDataLength(const Avtp_Pcm_t *const pdu) { - return (uint16_t)GET_PCM_FIELD(AVTP_PCM_FIELD_STREAM_DATA_LENGTH); + return (uint16_t)Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_STREAM_DATA_LENGTH); } /** @@ -286,7 +381,7 @@ OPEN1722_INLINE uint16_t Avtp_Pcm_GetStreamDataLength(const Avtp_Pcm_t *const pd */ OPEN1722_INLINE bool Avtp_Pcm_IsSp(const Avtp_Pcm_t *const pdu) { - return (bool)GET_PCM_FIELD(AVTP_PCM_FIELD_SP); + return (bool)Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_SP); } /** @@ -297,7 +392,7 @@ OPEN1722_INLINE bool Avtp_Pcm_IsSp(const Avtp_Pcm_t *const pdu) */ OPEN1722_INLINE uint8_t Avtp_Pcm_GetEvt(const Avtp_Pcm_t *const pdu) { - return (uint8_t)GET_PCM_FIELD(AVTP_PCM_FIELD_EVT); + return (uint8_t)Avtp_Pcm_GetField(pdu, AVTP_PCM_FIELD_EVT); } /** @@ -308,7 +403,7 @@ OPEN1722_INLINE uint8_t Avtp_Pcm_GetEvt(const Avtp_Pcm_t *const pdu) */ OPEN1722_INLINE void Avtp_Pcm_SetSv(Avtp_Pcm_t *pdu, bool sv) { - SET_PCM_FIELD(AVTP_PCM_FIELD_SV, sv); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_SV, sv); } /** @@ -319,7 +414,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetSv(Avtp_Pcm_t *pdu, bool sv) */ OPEN1722_INLINE void Avtp_Pcm_SetMr(Avtp_Pcm_t *pdu, bool mr) { - SET_PCM_FIELD(AVTP_PCM_FIELD_MR, mr); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_MR, mr); } /** @@ -330,19 +425,20 @@ OPEN1722_INLINE void Avtp_Pcm_SetMr(Avtp_Pcm_t *pdu, bool mr) */ OPEN1722_INLINE void Avtp_Pcm_SetTv(Avtp_Pcm_t *pdu, bool tv) { - SET_PCM_FIELD(AVTP_PCM_FIELD_TV, tv); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_TV, tv); } /** * Set the value of the AAF PCM Sequence Number field as specified in the IEEE 1722 - * Specification. + * Specification. The field is 8 bits in version 0 and 32 bits in version 1; values are + * truncated to the width of the version in use. * * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. * @param value Value to set the AAF PCM Sequence Number field to. */ -OPEN1722_INLINE void Avtp_Pcm_SetSequenceNum(Avtp_Pcm_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Pcm_SetSequenceNum(Avtp_Pcm_t *pdu, uint32_t value) { - SET_PCM_FIELD(AVTP_PCM_FIELD_SEQUENCE_NUM, value); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_SEQUENCE_NUM, value); } /** @@ -353,7 +449,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetSequenceNum(Avtp_Pcm_t *pdu, uint8_t value) */ OPEN1722_INLINE void Avtp_Pcm_SetTu(Avtp_Pcm_t *pdu, bool tu) { - SET_PCM_FIELD(AVTP_PCM_FIELD_TU, tu); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_TU, tu); } /** @@ -364,19 +460,32 @@ OPEN1722_INLINE void Avtp_Pcm_SetTu(Avtp_Pcm_t *pdu, bool tu) */ OPEN1722_INLINE void Avtp_Pcm_SetStreamId(Avtp_Pcm_t *pdu, uint64_t value) { - SET_PCM_FIELD(AVTP_PCM_FIELD_STREAM_ID, value); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_STREAM_ID, value); } /** * Set the value of the AAF PCM AVTP Timestamp field as specified in the IEEE 1722 - * Specification. + * Specification. The field is 32 bits in version 0 and 64 bits in version 1; values are + * truncated to the width of the version in use. * * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. * @param value Value to set the AAF PCM AVTP Timestamp field to. */ -OPEN1722_INLINE void Avtp_Pcm_SetAvtpTimestamp(Avtp_Pcm_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Pcm_SetAvtpTimestamp(Avtp_Pcm_t *pdu, uint64_t value) +{ + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_AVTP_TIMESTAMP, value); +} + +/** + * Set the value of the AAF PCM ptp_grandmaster_identity field. The field only + * exists in version 1; on version 0 this is a no-op. + * + * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. + * @param value Value to set the AAF PCM ptp_grandmaster_identity field to. + */ +OPEN1722_INLINE void Avtp_Pcm_SetPtpGrandmasterIdentity(Avtp_Pcm_t *pdu, uint64_t value) { - SET_PCM_FIELD(AVTP_PCM_FIELD_AVTP_TIMESTAMP, value); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_PTP_GRANDMASTER_IDENTITY, value); } /** @@ -387,7 +496,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetAvtpTimestamp(Avtp_Pcm_t *pdu, uint32_t value) */ OPEN1722_INLINE void Avtp_Pcm_SetFormat(Avtp_Pcm_t *pdu, Avtp_AafFormat_t value) { - SET_PCM_FIELD(AVTP_PCM_FIELD_FORMAT, (uint64_t)value); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_FORMAT, (uint64_t)value); } /** @@ -398,7 +507,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetFormat(Avtp_Pcm_t *pdu, Avtp_AafFormat_t value) */ OPEN1722_INLINE void Avtp_Pcm_SetNsr(Avtp_Pcm_t *pdu, Avtp_PcmNsr_t value) { - SET_PCM_FIELD(AVTP_PCM_FIELD_NSR, (uint64_t)value); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_NSR, (uint64_t)value); } /** @@ -410,7 +519,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetNsr(Avtp_Pcm_t *pdu, Avtp_PcmNsr_t value) */ OPEN1722_INLINE void Avtp_Pcm_SetChannelsPerFrame(Avtp_Pcm_t *pdu, uint16_t value) { - SET_PCM_FIELD(AVTP_PCM_FIELD_CHANNELS_PER_FRAME, value); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_CHANNELS_PER_FRAME, value); } /** @@ -421,7 +530,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetChannelsPerFrame(Avtp_Pcm_t *pdu, uint16_t valu */ OPEN1722_INLINE void Avtp_Pcm_SetBitDepth(Avtp_Pcm_t *pdu, uint8_t value) { - SET_PCM_FIELD(AVTP_PCM_FIELD_BIT_DEPTH, value); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_BIT_DEPTH, value); } /** @@ -433,7 +542,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetBitDepth(Avtp_Pcm_t *pdu, uint8_t value) */ OPEN1722_INLINE void Avtp_Pcm_SetStreamDataLength(Avtp_Pcm_t *pdu, uint16_t value) { - SET_PCM_FIELD(AVTP_PCM_FIELD_STREAM_DATA_LENGTH, value); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_STREAM_DATA_LENGTH, value); } /** @@ -444,7 +553,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetStreamDataLength(Avtp_Pcm_t *pdu, uint16_t valu */ OPEN1722_INLINE void Avtp_Pcm_SetSp(Avtp_Pcm_t *pdu, bool sp) { - SET_PCM_FIELD(AVTP_PCM_FIELD_SP, sp); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_SP, sp); } /** @@ -455,18 +564,19 @@ OPEN1722_INLINE void Avtp_Pcm_SetSp(Avtp_Pcm_t *pdu, bool sp) */ OPEN1722_INLINE void Avtp_Pcm_SetEvt(Avtp_Pcm_t *pdu, uint8_t value) { - SET_PCM_FIELD(AVTP_PCM_FIELD_EVT, value); + Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_EVT, value); } /** - * Returns pointer to payload of an AAF PCM frame. + * Returns pointer to payload of an AAF PCM frame. The payload starts after the + * version-dependent common stream header. * * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. * @return Pointer to AAF PCM frame payload */ OPEN1722_INLINE const uint8_t *Avtp_Pcm_GetPayload(const Avtp_Pcm_t *const pdu) { - return pdu->payload; + return (const uint8_t *)pdu + Avtp_Pcm_GetHeaderLen(pdu); } /** @@ -478,11 +588,11 @@ OPEN1722_INLINE const uint8_t *Avtp_Pcm_GetPayload(const Avtp_Pcm_t *const pdu) */ OPEN1722_INLINE void Avtp_Pcm_SetPayload(Avtp_Pcm_t *pdu, uint8_t *payload, uint16_t payload_length) { - memcpy(pdu->payload, payload, payload_length); + memcpy((uint8_t *)pdu + Avtp_Pcm_GetHeaderLen(pdu), payload, payload_length); } /** - * Initializes an AAF PCM PDU as specified in the IEEE 1722 Specification. + * Initializes a version 0 AAF PCM PDU as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of a 1722 AAF PCM PDU. */ @@ -495,10 +605,28 @@ OPEN1722_INLINE void Avtp_Pcm_Init(Avtp_Pcm_t *pdu) } } +/** + * Initializes a version 1 AAF PCM PDU. The caller must provide a buffer of at + * least AVTP_PCM_HEADER_LEN_V1 octets. + * + * @param pdu Pointer to the first bit of a 1722 AAF PCM PDU. + */ +OPEN1722_INLINE void Avtp_Pcm_InitV1(Avtp_PcmV1_t *pdu) +{ + if (pdu != NULL) { + memset(pdu, 0, sizeof(Avtp_PcmV1_t)); + Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_AAF); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_Pcm_SetSv((Avtp_Pcm_t *)pdu, true); + } +} + /** * Checks if the AAF PCM frame is valid by checking: - * 1) if the stream_data_length field contains a value larger than the actual size of the - * buffer that contains the AVTP message. 2) if other format specific invariants are not upheld. + * 1) that the subtype is AAF and the version is supported, + * 2) that the version-dependent header and the stream_data_length fit into + * the buffer (via Avtp_Aaf_IsValid), and + * 3) the PCM-specific invariants. * * The PCM specific invariants are defined in IEEE 1722-2025, 7.3: * - only the PCM formats (Table 10, values 0x00-0x04) use this encapsulation, @@ -569,30 +697,6 @@ OPEN1722_INLINE bool Avtp_Pcm_IsValid(const Avtp_Pcm_t *const pdu, size_t buffer return true; } -/** - * Returns the value of an AVTP AAF PCM field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. - * @param field Specifies the position of the data field to be read - * @returns This function returns the value of the field. - */ -OPEN1722_INLINE uint64_t Avtp_Pcm_GetField(const Avtp_Pcm_t *const pdu, Avtp_PcmFields_t field) -{ - return (uint64_t)GET_PCM_FIELD(field); -} - -/** - * Sets the value of an AVTP AAF PCM field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. - * @param field Specifies the position of the data field to be written - * @param value The value to set. - */ -OPEN1722_INLINE void Avtp_Pcm_SetField(Avtp_Pcm_t *pdu, Avtp_PcmFields_t field, uint64_t value) -{ - SET_PCM_FIELD(field, value); -} - #ifdef __cplusplus } #endif diff --git a/include/avtp/acf/Tscf.h b/include/avtp/acf/Tscf.h index ad2c641a..0e5f54d9 100644 --- a/include/avtp/acf/Tscf.h +++ b/include/avtp/acf/Tscf.h @@ -177,6 +177,14 @@ OPEN1722_INLINE void Avtp_Tscf_SetField(Avtp_Tscf_t *pdu, Avtp_TscfFields_t fiel Avtp_SetField(desc, AVTP_TSCF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); } +/** + * Returns the length of the TSCF header in octets (24 or 40). + */ +OPEN1722_INLINE uint8_t Avtp_Tscf_GetHeaderLen(const Avtp_Tscf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); +} + /** * Return the value of the TSCF SV field as specified in the IEEE 1722 Specification. * diff --git a/include/avtp/cvf/Cvf.h b/include/avtp/cvf/Cvf.h index 8e4aa6d0..2a5f7dfb 100644 --- a/include/avtp/cvf/Cvf.h +++ b/include/avtp/cvf/Cvf.h @@ -31,6 +31,12 @@ * @file * This file contains the fields descriptions of the IEEE 1722 CVF PDUs and * functions to invoke corresponding parser and deparser. + * + * CVF uses the AVTPDU common stream header (4.7.4) and declares a complete + * descriptor table per version in absolute coordinates: the common stream + * header fields reuse the positions from CommonStreamHeader.h and the + * CVF-specific fields are added by this module. A consistency test keeps the + * common entries aligned with the common stream header module. */ #pragma once @@ -46,23 +52,30 @@ #include "avtp/Utils.h" #include "avtp/Defines.h" #include "avtp/CommonHeader.h" +#include "avtp/CommonStreamHeader.h" #ifdef __cplusplus extern "C" { #endif -#define AVTP_CVF_HEADER_LEN (6 * AVTP_QUADLET_SIZE) +#define AVTP_CVF_HEADER_LEN_V0 AVTPDU_CSH_LEN_V0 /* 24 */ +#define AVTP_CVF_HEADER_LEN_V1 AVTPDU_CSH_LEN_V1 /* 40 */ +/* Kept for compatibility: the version 0 header length. */ +#define AVTP_CVF_HEADER_LEN AVTP_CVF_HEADER_LEN_V0 -#define GET_CVF_FIELD(field) \ - (Avtp_GetField(Avtp_CvfFieldDesc, AVTP_CVF_FIELD_MAX, (const uint8_t *)pdu, field)) -#define SET_CVF_FIELD(field, value) \ - (Avtp_SetField(Avtp_CvfFieldDesc, AVTP_CVF_FIELD_MAX, (uint8_t *)pdu, field, value)) +/* CVF supports both versions of the common stream header (Table 7). */ +#define AVTP_CVF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) typedef struct { - uint8_t header[AVTP_CVF_HEADER_LEN]; + uint8_t header[AVTP_CVF_HEADER_LEN_V0]; uint8_t payload[0]; } __attribute__((packed)) Avtp_Cvf_t; +typedef struct { + uint8_t header[AVTP_CVF_HEADER_LEN_V1]; + uint8_t payload[0]; +} __attribute__((packed)) Avtp_CvfV1_t; + /** * CVF 'format' field values (IEEE 1722-2025, Table 20). Values 0x00-0x01 and * 0x03-0xFF are reserved. @@ -85,23 +98,23 @@ typedef enum { typedef enum { /* Common AVTP stream header fields */ - AVTP_CVF_FIELD_SUBTYPE, - AVTP_CVF_FIELD_SV, - AVTP_CVF_FIELD_VERSION, + AVTP_CVF_FIELD_SV = 0, AVTP_CVF_FIELD_MR, - AVTP_CVF_FIELD_RSV1, + AVTP_CVF_FIELD_FSD, AVTP_CVF_FIELD_TV, AVTP_CVF_FIELD_SEQUENCE_NUM, - AVTP_CVF_FIELD_RESERVED1, + AVTP_CVF_FIELD_FSD0, + AVTP_CVF_FIELD_FSD1, AVTP_CVF_FIELD_TU, - - /* CVF header fields */ AVTP_CVF_FIELD_STREAM_ID, AVTP_CVF_FIELD_AVTP_TIMESTAMP, + AVTP_CVF_FIELD_PTP_GRANDMASTER_IDENTITY, + AVTP_CVF_FIELD_STREAM_DATA_LENGTH, + + /* CVF format-specific fields */ AVTP_CVF_FIELD_FORMAT, AVTP_CVF_FIELD_FORMAT_SUBTYPE, AVTP_CVF_FIELD_RESERVED2, - AVTP_CVF_FIELD_STREAM_DATA_LENGTH, AVTP_CVF_FIELD_RSV2, AVTP_CVF_FIELD_PTV, /* ptv for H.264/H.265, reserved for the other subtypes */ AVTP_CVF_FIELD_M, @@ -113,33 +126,101 @@ typedef enum { } Avtp_CvfFields_t; /** - * This table maps all IEEE 1722 CVF header fields to a descriptor. + * This table maps all IEEE 1722 CVF header fields to a descriptor for version 0. + * It is complete and in absolute coordinates; the common stream header fields + * use the same positions as Avtp_CshFieldDescV0. */ -static const Avtp_FieldDescriptor_t Avtp_CvfFieldDesc[AVTP_CVF_FIELD_MAX] = { - /* Common AVTP stream header fields */ - [AVTP_CVF_FIELD_SUBTYPE] = {.quadlet = 0, .offset = 0, .bits = 8}, +static const Avtp_FieldDescriptor_t Avtp_CvfFieldDescV0[AVTP_CVF_FIELD_MAX] = { [AVTP_CVF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, - [AVTP_CVF_FIELD_VERSION] = {.quadlet = 0, .offset = 9, .bits = 3}, [AVTP_CVF_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, - [AVTP_CVF_FIELD_RSV1] = {.quadlet = 0, .offset = 13, .bits = 2}, + [AVTP_CVF_FIELD_FSD] = {.quadlet = 0, .offset = 13, .bits = 2}, [AVTP_CVF_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, [AVTP_CVF_FIELD_SEQUENCE_NUM] = {.quadlet = 0, .offset = 16, .bits = 8}, - [AVTP_CVF_FIELD_RESERVED1] = {.quadlet = 0, .offset = 24, .bits = 7}, + [AVTP_CVF_FIELD_FSD0] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_CVF_FIELD_FSD1] = {.quadlet = 0, .offset = 24, .bits = 7}, [AVTP_CVF_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, - /* CVF header fields */ [AVTP_CVF_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, [AVTP_CVF_FIELD_AVTP_TIMESTAMP] = {.quadlet = 3, .offset = 0, .bits = 32}, + [AVTP_CVF_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 0, .offset = 0, .bits = 0}, + [AVTP_CVF_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 5, .offset = 0, .bits = 16}, [AVTP_CVF_FIELD_FORMAT] = {.quadlet = 4, .offset = 0, .bits = 8}, [AVTP_CVF_FIELD_FORMAT_SUBTYPE] = {.quadlet = 4, .offset = 8, .bits = 8}, [AVTP_CVF_FIELD_RESERVED2] = {.quadlet = 4, .offset = 16, .bits = 16}, - [AVTP_CVF_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 5, .offset = 0, .bits = 16}, [AVTP_CVF_FIELD_RSV2] = {.quadlet = 5, .offset = 16, .bits = 2}, - [AVTP_CVF_FIELD_PTV] = {.quadlet = 5, .offset = 18, .bits = 1}, /* H.264/H.265 only */ + [AVTP_CVF_FIELD_PTV] = {.quadlet = 5, .offset = 18, .bits = 1}, [AVTP_CVF_FIELD_M] = {.quadlet = 5, .offset = 19, .bits = 1}, [AVTP_CVF_FIELD_EVT] = {.quadlet = 5, .offset = 20, .bits = 4}, [AVTP_CVF_FIELD_RESERVED3] = {.quadlet = 5, .offset = 24, .bits = 8}, }; +/** + * This table maps all IEEE 1722 CVF header fields to a descriptor for version 1. + * It is complete and in absolute coordinates; the common stream header fields + * use the same positions as Avtp_CshFieldDescV1. + */ +static const Avtp_FieldDescriptor_t Avtp_CvfFieldDescV1[AVTP_CVF_FIELD_MAX] = { + [AVTP_CVF_FIELD_SV] = {.quadlet = 0, .offset = 8, .bits = 1}, + [AVTP_CVF_FIELD_MR] = {.quadlet = 0, .offset = 12, .bits = 1}, + [AVTP_CVF_FIELD_FSD] = {.quadlet = 0, .offset = 13, .bits = 2}, + [AVTP_CVF_FIELD_TV] = {.quadlet = 0, .offset = 15, .bits = 1}, + [AVTP_CVF_FIELD_SEQUENCE_NUM] = {.quadlet = 3, .offset = 0, .bits = 32}, + [AVTP_CVF_FIELD_FSD0] = {.quadlet = 0, .offset = 16, .bits = 8}, + [AVTP_CVF_FIELD_FSD1] = {.quadlet = 0, .offset = 24, .bits = 7}, + [AVTP_CVF_FIELD_TU] = {.quadlet = 0, .offset = 31, .bits = 1}, + [AVTP_CVF_FIELD_STREAM_ID] = {.quadlet = 1, .offset = 0, .bits = 64}, + [AVTP_CVF_FIELD_AVTP_TIMESTAMP] = {.quadlet = 4, .offset = 0, .bits = 64}, + [AVTP_CVF_FIELD_PTP_GRANDMASTER_IDENTITY] = {.quadlet = 6, .offset = 0, .bits = 64}, + [AVTP_CVF_FIELD_STREAM_DATA_LENGTH] = {.quadlet = 9, .offset = 0, .bits = 16}, + [AVTP_CVF_FIELD_FORMAT] = {.quadlet = 8, .offset = 0, .bits = 8}, + [AVTP_CVF_FIELD_FORMAT_SUBTYPE] = {.quadlet = 8, .offset = 8, .bits = 8}, + [AVTP_CVF_FIELD_RESERVED2] = {.quadlet = 8, .offset = 16, .bits = 16}, + [AVTP_CVF_FIELD_RSV2] = {.quadlet = 9, .offset = 16, .bits = 2}, + [AVTP_CVF_FIELD_PTV] = {.quadlet = 9, .offset = 18, .bits = 1}, + [AVTP_CVF_FIELD_M] = {.quadlet = 9, .offset = 19, .bits = 1}, + [AVTP_CVF_FIELD_EVT] = {.quadlet = 9, .offset = 20, .bits = 4}, + [AVTP_CVF_FIELD_RESERVED3] = {.quadlet = 9, .offset = 24, .bits = 8}, +}; + +/** + * Returns the value of an AVTP CVF field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 CVF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + */ +OPEN1722_INLINE uint64_t Avtp_Cvf_GetField(const Avtp_Cvf_t *const pdu, Avtp_CvfFields_t field) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_CvfFieldDescV1 + : Avtp_CvfFieldDescV0; + return Avtp_GetField(desc, AVTP_CVF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); +} + +/** + * Sets the value of an AVTP CVF field as specified in the IEEE 1722 Specification. + * + * @param pdu Pointer to the first bit of an 1722 CVF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + */ +OPEN1722_INLINE void Avtp_Cvf_SetField(Avtp_Cvf_t *pdu, Avtp_CvfFields_t field, uint64_t value) +{ + const Avtp_FieldDescriptor_t *desc = + Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 + ? Avtp_CvfFieldDescV1 + : Avtp_CvfFieldDescV0; + Avtp_SetField(desc, AVTP_CVF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Returns the length of the CVF header in octets (24 or 40). + */ +OPEN1722_INLINE uint8_t Avtp_Cvf_GetHeaderLen(const Avtp_Cvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); +} + /** * Return the value of the CVF SV field as specified in the IEEE 1722 Specification. * @@ -148,7 +229,7 @@ static const Avtp_FieldDescriptor_t Avtp_CvfFieldDesc[AVTP_CVF_FIELD_MAX] = { */ OPEN1722_INLINE bool Avtp_Cvf_IsSv(const Avtp_Cvf_t *const pdu) { - return (bool)GET_CVF_FIELD(AVTP_CVF_FIELD_SV); + return (bool)Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_SV); } /** @@ -159,7 +240,7 @@ OPEN1722_INLINE bool Avtp_Cvf_IsSv(const Avtp_Cvf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Cvf_IsMr(const Avtp_Cvf_t *const pdu) { - return (bool)GET_CVF_FIELD(AVTP_CVF_FIELD_MR); + return (bool)Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_MR); } /** @@ -170,18 +251,19 @@ OPEN1722_INLINE bool Avtp_Cvf_IsMr(const Avtp_Cvf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Cvf_IsTv(const Avtp_Cvf_t *const pdu) { - return (bool)GET_CVF_FIELD(AVTP_CVF_FIELD_TV); + return (bool)Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_TV); } /** - * Return the value of the CVF Sequence Number field as specified in the IEEE 1722 Specification. + * Return the value of the CVF Sequence Number field as specified in the IEEE 1722 + * Specification. The field is 8 bits in version 0 and 32 bits in version 1. * * @param pdu Pointer to the first bit of an 1722 CVF PDU. * @returns Value of the CVF Sequence Number field. */ -OPEN1722_INLINE uint8_t Avtp_Cvf_GetSequenceNum(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Cvf_GetSequenceNum(const Avtp_Cvf_t *const pdu) { - return (uint8_t)GET_CVF_FIELD(AVTP_CVF_FIELD_SEQUENCE_NUM); + return (uint32_t)Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_SEQUENCE_NUM); } /** @@ -192,7 +274,7 @@ OPEN1722_INLINE uint8_t Avtp_Cvf_GetSequenceNum(const Avtp_Cvf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Cvf_IsTu(const Avtp_Cvf_t *const pdu) { - return (bool)GET_CVF_FIELD(AVTP_CVF_FIELD_TU); + return (bool)Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_TU); } /** @@ -203,18 +285,31 @@ OPEN1722_INLINE bool Avtp_Cvf_IsTu(const Avtp_Cvf_t *const pdu) */ OPEN1722_INLINE uint64_t Avtp_Cvf_GetStreamId(const Avtp_Cvf_t *const pdu) { - return (uint64_t)GET_CVF_FIELD(AVTP_CVF_FIELD_STREAM_ID); + return Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_STREAM_ID); } /** - * Return the value of the CVF AVTP Timestamp field as specified in the IEEE 1722 Specification. + * Return the value of the CVF AVTP Timestamp field as specified in the IEEE 1722 + * Specification. The field is 32 bits in version 0 and 64 bits in version 1. * * @param pdu Pointer to the first bit of an 1722 CVF PDU. * @returns Value of the CVF AVTP Timestamp field. */ -OPEN1722_INLINE uint32_t Avtp_Cvf_GetAvtpTimestamp(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Cvf_GetAvtpTimestamp(const Avtp_Cvf_t *const pdu) +{ + return Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_AVTP_TIMESTAMP); +} + +/** + * Return the value of the CVF ptp_grandmaster_identity field. The field only + * exists in version 1; version 0 returns 0. + * + * @param pdu Pointer to the first bit of an 1722 CVF PDU. + * @returns Value of the CVF ptp_grandmaster_identity field. + */ +OPEN1722_INLINE uint64_t Avtp_Cvf_GetPtpGrandmasterIdentity(const Avtp_Cvf_t *const pdu) { - return (uint32_t)GET_CVF_FIELD(AVTP_CVF_FIELD_AVTP_TIMESTAMP); + return Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_PTP_GRANDMASTER_IDENTITY); } /** @@ -225,46 +320,43 @@ OPEN1722_INLINE uint32_t Avtp_Cvf_GetAvtpTimestamp(const Avtp_Cvf_t *const pdu) */ OPEN1722_INLINE Avtp_CvfFormat_t Avtp_Cvf_GetFormat(const Avtp_Cvf_t *const pdu) { - return (Avtp_CvfFormat_t)GET_CVF_FIELD(AVTP_CVF_FIELD_FORMAT); + return (Avtp_CvfFormat_t)Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_FORMAT); } /** - * Return the value of the CVF Format Subtype field as specified in the IEEE 1722 Specification. + * Return the value of the CVF Format Subtype field as specified in the IEEE 1722 + * Specification. * * @param pdu Pointer to the first bit of an 1722 CVF PDU. * @returns Value of the CVF Format Subtype field. */ OPEN1722_INLINE Avtp_CvfFormatSubtype_t Avtp_Cvf_GetFormatSubtype(const Avtp_Cvf_t *const pdu) { - return (Avtp_CvfFormatSubtype_t)GET_CVF_FIELD(AVTP_CVF_FIELD_FORMAT_SUBTYPE); + return (Avtp_CvfFormatSubtype_t)Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_FORMAT_SUBTYPE); } /** - * Return the value of the CVF Stream Data Length field as specified in the IEEE 1722 Specification. + * Return the value of the CVF Stream Data Length field as specified in the IEEE 1722 + * Specification. * * @param pdu Pointer to the first bit of an 1722 CVF PDU. * @returns Value of the CVF Stream Data Length field. */ OPEN1722_INLINE uint16_t Avtp_Cvf_GetStreamDataLength(const Avtp_Cvf_t *const pdu) { - return (uint16_t)GET_CVF_FIELD(AVTP_CVF_FIELD_STREAM_DATA_LENGTH); + return (uint16_t)Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_STREAM_DATA_LENGTH); } /** * Return the value of the CVF PTV field as specified in the IEEE 1722 Specification. - * - * The ptv (payload timestamp valid) bit is defined by the H.264 (IEEE 1722-2025, - * 8.5.2.3) and H.265 (8.7.2.3) encapsulations, where it indicates the validity - * of the format-specific timestamp. For the other format subtypes (MJPEG, - * JPEG 2000) the bit belongs to the generic CVF rsv field (8.3.1.1, Figure 39) - * and shall be zero. + * The field is defined for the H.264/H.265 format subtypes. * * @param pdu Pointer to the first bit of an 1722 CVF PDU. * @returns Value of the CVF PTV field. */ OPEN1722_INLINE bool Avtp_Cvf_IsPtv(const Avtp_Cvf_t *const pdu) { - return (bool)GET_CVF_FIELD(AVTP_CVF_FIELD_PTV); + return (bool)Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_PTV); } /** @@ -275,7 +367,7 @@ OPEN1722_INLINE bool Avtp_Cvf_IsPtv(const Avtp_Cvf_t *const pdu) */ OPEN1722_INLINE bool Avtp_Cvf_IsM(const Avtp_Cvf_t *const pdu) { - return (bool)GET_CVF_FIELD(AVTP_CVF_FIELD_M); + return (bool)Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_M); } /** @@ -286,7 +378,7 @@ OPEN1722_INLINE bool Avtp_Cvf_IsM(const Avtp_Cvf_t *const pdu) */ OPEN1722_INLINE uint8_t Avtp_Cvf_GetEvt(const Avtp_Cvf_t *const pdu) { - return (uint8_t)GET_CVF_FIELD(AVTP_CVF_FIELD_EVT); + return (uint8_t)Avtp_Cvf_GetField(pdu, AVTP_CVF_FIELD_EVT); } /** @@ -297,7 +389,7 @@ OPEN1722_INLINE uint8_t Avtp_Cvf_GetEvt(const Avtp_Cvf_t *const pdu) */ OPEN1722_INLINE void Avtp_Cvf_SetSv(Avtp_Cvf_t *pdu, bool sv) { - SET_CVF_FIELD(AVTP_CVF_FIELD_SV, sv); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_SV, sv); } /** @@ -308,7 +400,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetSv(Avtp_Cvf_t *pdu, bool sv) */ OPEN1722_INLINE void Avtp_Cvf_SetMr(Avtp_Cvf_t *pdu, bool mr) { - SET_CVF_FIELD(AVTP_CVF_FIELD_MR, mr); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_MR, mr); } /** @@ -319,18 +411,20 @@ OPEN1722_INLINE void Avtp_Cvf_SetMr(Avtp_Cvf_t *pdu, bool mr) */ OPEN1722_INLINE void Avtp_Cvf_SetTv(Avtp_Cvf_t *pdu, bool tv) { - SET_CVF_FIELD(AVTP_CVF_FIELD_TV, tv); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_TV, tv); } /** - * Set the value of the CVF Sequence Number field as specified in the IEEE 1722 Specification. + * Set the value of the CVF Sequence Number field as specified in the IEEE 1722 + * Specification. The field is 8 bits in version 0 and 32 bits in version 1; values are + * truncated to the width of the version in use. * * @param pdu Pointer to the first bit of an 1722 CVF PDU. * @param value Value to set the CVF Sequence Number field to. */ -OPEN1722_INLINE void Avtp_Cvf_SetSequenceNum(Avtp_Cvf_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Cvf_SetSequenceNum(Avtp_Cvf_t *pdu, uint32_t value) { - SET_CVF_FIELD(AVTP_CVF_FIELD_SEQUENCE_NUM, value); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_SEQUENCE_NUM, value); } /** @@ -341,7 +435,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetSequenceNum(Avtp_Cvf_t *pdu, uint8_t value) */ OPEN1722_INLINE void Avtp_Cvf_SetTu(Avtp_Cvf_t *pdu, bool tu) { - SET_CVF_FIELD(AVTP_CVF_FIELD_TU, tu); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_TU, tu); } /** @@ -352,18 +446,32 @@ OPEN1722_INLINE void Avtp_Cvf_SetTu(Avtp_Cvf_t *pdu, bool tu) */ OPEN1722_INLINE void Avtp_Cvf_SetStreamId(Avtp_Cvf_t *pdu, uint64_t value) { - SET_CVF_FIELD(AVTP_CVF_FIELD_STREAM_ID, value); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_STREAM_ID, value); } /** - * Set the value of the CVF AVTP Timestamp field as specified in the IEEE 1722 Specification. + * Set the value of the CVF AVTP Timestamp field as specified in the IEEE 1722 + * Specification. The field is 32 bits in version 0 and 64 bits in version 1; values are + * truncated to the width of the version in use. * * @param pdu Pointer to the first bit of an 1722 CVF PDU. * @param value Value to set the CVF AVTP Timestamp field to. */ -OPEN1722_INLINE void Avtp_Cvf_SetAvtpTimestamp(Avtp_Cvf_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Cvf_SetAvtpTimestamp(Avtp_Cvf_t *pdu, uint64_t value) { - SET_CVF_FIELD(AVTP_CVF_FIELD_AVTP_TIMESTAMP, value); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_AVTP_TIMESTAMP, value); +} + +/** + * Set the value of the CVF ptp_grandmaster_identity field. The field only + * exists in version 1; on version 0 this is a no-op. + * + * @param pdu Pointer to the first bit of an 1722 CVF PDU. + * @param value Value to set the CVF ptp_grandmaster_identity field to. + */ +OPEN1722_INLINE void Avtp_Cvf_SetPtpGrandmasterIdentity(Avtp_Cvf_t *pdu, uint64_t value) +{ + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_PTP_GRANDMASTER_IDENTITY, value); } /** @@ -374,45 +482,42 @@ OPEN1722_INLINE void Avtp_Cvf_SetAvtpTimestamp(Avtp_Cvf_t *pdu, uint32_t value) */ OPEN1722_INLINE void Avtp_Cvf_SetFormat(Avtp_Cvf_t *pdu, Avtp_CvfFormat_t value) { - SET_CVF_FIELD(AVTP_CVF_FIELD_FORMAT, (uint64_t)value); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_FORMAT, (uint64_t)value); } /** - * Set the value of the CVF Format Subtype field as specified in the IEEE 1722 Specification. + * Set the value of the CVF Format Subtype field as specified in the IEEE 1722 + * Specification. * * @param pdu Pointer to the first bit of an 1722 CVF PDU. * @param value Value to set the CVF Format Subtype field to. */ OPEN1722_INLINE void Avtp_Cvf_SetFormatSubtype(Avtp_Cvf_t *pdu, Avtp_CvfFormatSubtype_t value) { - SET_CVF_FIELD(AVTP_CVF_FIELD_FORMAT_SUBTYPE, (uint64_t)value); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_FORMAT_SUBTYPE, (uint64_t)value); } /** - * Set the value of the CVF Stream Data Length field as specified in the IEEE 1722 Specification. + * Set the value of the CVF Stream Data Length field as specified in the IEEE 1722 + * Specification. * * @param pdu Pointer to the first bit of an 1722 CVF PDU. * @param value Value to set the CVF Stream Data Length field to. */ OPEN1722_INLINE void Avtp_Cvf_SetStreamDataLength(Avtp_Cvf_t *pdu, uint16_t value) { - SET_CVF_FIELD(AVTP_CVF_FIELD_STREAM_DATA_LENGTH, value); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_STREAM_DATA_LENGTH, value); } /** * Set the PTV bit in a CVF frame as specified in the IEEE 1722 Specification. * - * The ptv (payload timestamp valid) bit is defined by the H.264 (IEEE 1722-2025, - * 8.5.2.3) and H.265 (8.7.2.3) encapsulations. For the other format subtypes - * (MJPEG, JPEG 2000) the bit belongs to the generic CVF rsv field (8.3.1.1, - * Figure 39) and shall be set to zero. - * * @param pdu Pointer to the first bit of an 1722 CVF PDU. * @param ptv Value to set the CVF PTV field to. */ OPEN1722_INLINE void Avtp_Cvf_SetPtv(Avtp_Cvf_t *pdu, bool ptv) { - SET_CVF_FIELD(AVTP_CVF_FIELD_PTV, ptv); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_PTV, ptv); } /** @@ -423,7 +528,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetPtv(Avtp_Cvf_t *pdu, bool ptv) */ OPEN1722_INLINE void Avtp_Cvf_SetM(Avtp_Cvf_t *pdu, bool m) { - SET_CVF_FIELD(AVTP_CVF_FIELD_M, m); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_M, m); } /** @@ -434,11 +539,12 @@ OPEN1722_INLINE void Avtp_Cvf_SetM(Avtp_Cvf_t *pdu, bool m) */ OPEN1722_INLINE void Avtp_Cvf_SetEvt(Avtp_Cvf_t *pdu, uint8_t value) { - SET_CVF_FIELD(AVTP_CVF_FIELD_EVT, value); + Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_EVT, value); } /** - * Returns pointer to the stream data of a CVF frame. + * Returns pointer to the CVF stream data. The stream data starts after the + * version-dependent common stream header. * * The stream data contains the format-specific header (e.g. the MJPEG or * H.264 header) followed by the video payload. @@ -448,7 +554,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetEvt(Avtp_Cvf_t *pdu, uint8_t value) */ OPEN1722_INLINE const uint8_t *Avtp_Cvf_GetPayload(const Avtp_Cvf_t *const pdu) { - return pdu->payload; + return (const uint8_t *)pdu + Avtp_Cvf_GetHeaderLen(pdu); } /** @@ -460,11 +566,11 @@ OPEN1722_INLINE const uint8_t *Avtp_Cvf_GetPayload(const Avtp_Cvf_t *const pdu) */ OPEN1722_INLINE void Avtp_Cvf_SetPayload(Avtp_Cvf_t *pdu, uint8_t *payload, uint16_t payload_length) { - memcpy(pdu->payload, payload, payload_length); + memcpy((uint8_t *)pdu + Avtp_Cvf_GetHeaderLen(pdu), payload, payload_length); } /** - * Initializes a CVF PDU as specified in the IEEE 1722 Specification. + * Initializes a version 0 CVF PDU as specified in the IEEE 1722 Specification. * * @param pdu Pointer to the first bit of a 1722 CVF PDU. */ @@ -478,10 +584,28 @@ OPEN1722_INLINE void Avtp_Cvf_Init(Avtp_Cvf_t *pdu) } } +/** + * Initializes a version 1 CVF PDU. The caller must provide a buffer of at least + * AVTP_CVF_HEADER_LEN_V1 octets. + * + * @param pdu Pointer to the first bit of a 1722 CVF PDU. + */ +OPEN1722_INLINE void Avtp_Cvf_InitV1(Avtp_CvfV1_t *pdu) +{ + if (pdu != NULL) { + memset(pdu, 0, sizeof(Avtp_CvfV1_t)); + Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_CVF); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_Cvf_SetFormat((Avtp_Cvf_t *)pdu, AVTP_CVF_FORMAT_RFC); + Avtp_Cvf_SetSv((Avtp_Cvf_t *)pdu, true); + } +} + /** * Checks if the CVF frame is valid by checking: - * 1) if the length field of the CVF stream data contains a value larger than the actual size of - * the buffer that contains the AVTP message. 2) if other format specific invariants are not upheld. + * 1) that the subtype is CVF and the version is supported, + * 2) that the version-dependent header fits into the buffer, + * 3) that the declared stream_data_length fits into the buffer. * * The stream_data_length field contains the length (in octets) of the * video_data_payload field (IEEE 1722-2025, 4.7.4.12), which includes the @@ -497,43 +621,25 @@ OPEN1722_INLINE bool Avtp_Cvf_IsValid(const Avtp_Cvf_t *const pdu, size_t buffer return false; } - if (bufferSize < AVTP_CVF_HEADER_LEN) { + if (Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu) != AVTP_SUBTYPE_CVF) { return false; } - if (Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu) != AVTP_SUBTYPE_CVF) { + uint8_t version = Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu); + if (!Avtp_Version_IsSupported(AVTP_CVF_SUPPORTED_VERSIONS, version)) { return false; } - if ((size_t)AVTP_CVF_HEADER_LEN + (size_t)Avtp_Cvf_GetStreamDataLength(pdu) > bufferSize) { + size_t headerLen = Avtp_Cvf_GetHeaderLen(pdu); + if (bufferSize < headerLen) { return false; } - return true; -} - -/** - * Returns the value of an AVTP CVF field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 CVF PDU. - * @param field Specifies the position of the data field to be read - * @returns This function returns the value of the field. - */ -OPEN1722_INLINE uint64_t Avtp_Cvf_GetField(const Avtp_Cvf_t *const pdu, Avtp_CvfFields_t field) -{ - return (uint64_t)GET_CVF_FIELD(field); -} + if ((size_t)Avtp_Cvf_GetStreamDataLength(pdu) > bufferSize - headerLen) { + return false; + } -/** - * Sets the value of an AVTP CVF field as specified in the IEEE 1722 Specification. - * - * @param pdu Pointer to the first bit of an 1722 CVF PDU. - * @param field Specifies the position of the data field to be written - * @param value The value to set. - */ -OPEN1722_INLINE void Avtp_Cvf_SetField(Avtp_Cvf_t *pdu, Avtp_CvfFields_t field, uint64_t value) -{ - SET_CVF_FIELD(field, value); + return true; } #ifdef __cplusplus diff --git a/unit/test-aaf.c b/unit/test-aaf.c index 83559a67..c9706cfa 100644 --- a/unit/test-aaf.c +++ b/unit/test-aaf.c @@ -41,6 +41,7 @@ extern "C" { #include #include "avtp/CommonHeader.h" +#include "avtp/CommonStreamHeader.h" #include "avtp/aaf/Aaf.h" #define MAX_PDU_SIZE 1500 @@ -57,68 +58,143 @@ static void aaf_init(void **state) { (void)state; uint8_t pdu[MAX_PDU_SIZE]; - uint8_t init_pdu[AVTP_AAF_HEADER_LEN]; + uint8_t init_pdu[AVTP_AAF_HEADER_LEN_V0]; - assert_int_equal(sizeof(Avtp_Aaf_t), AVTP_AAF_HEADER_LEN); + assert_int_equal(sizeof(Avtp_Aaf_t), AVTP_AAF_HEADER_LEN_V0); /* Passing a NULL pointer must be a no-op. */ Avtp_Aaf_Init(NULL); Avtp_Aaf_Init((Avtp_Aaf_t *)pdu); - memset(init_pdu, 0, AVTP_AAF_HEADER_LEN); + memset(init_pdu, 0, AVTP_AAF_HEADER_LEN_V0); init_pdu[0] = AVTP_SUBTYPE_AAF; /* subtype = AAF */ - init_pdu[1] = 0x80; /* sv = 1 */ - assert_memory_equal(init_pdu, pdu, AVTP_AAF_HEADER_LEN); + init_pdu[1] = 0x80; /* sv = 1, version = 0 */ + assert_memory_equal(init_pdu, pdu, AVTP_AAF_HEADER_LEN_V0); +} + +static void aaf_init_v1(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t init_pdu[AVTP_AAF_HEADER_LEN_V1]; + + assert_int_equal(sizeof(Avtp_AafV1_t), AVTP_AAF_HEADER_LEN_V1); + + /* Passing a NULL pointer must be a no-op. */ + Avtp_Aaf_InitV1(NULL); + + Avtp_Aaf_InitV1((Avtp_AafV1_t *)pdu); + memset(init_pdu, 0, AVTP_AAF_HEADER_LEN_V1); + init_pdu[0] = AVTP_SUBTYPE_AAF; /* subtype = AAF */ + init_pdu[1] = 0x90; /* sv = 1, version = 1 */ + assert_memory_equal(init_pdu, pdu, AVTP_AAF_HEADER_LEN_V1); + + assert_int_equal(Avtp_Aaf_GetHeaderLen((Avtp_Aaf_t *)pdu), AVTP_AAF_HEADER_LEN_V1); } static void aaf_is_valid(void **state) { (void)state; uint8_t pdu[MAX_PDU_SIZE]; + Avtp_Aaf_t *aaf = (Avtp_Aaf_t *)pdu; - Avtp_Aaf_Init((Avtp_Aaf_t *)pdu); - assert_true(Avtp_Aaf_IsValid((Avtp_Aaf_t *)pdu, AVTP_AAF_HEADER_LEN)); + Avtp_Aaf_Init(aaf); + assert_true(Avtp_Aaf_IsValid(aaf, AVTP_AAF_HEADER_LEN_V0)); /* NULL pdu. */ assert_false(Avtp_Aaf_IsValid(NULL, MAX_PDU_SIZE)); /* Not an AAF frame. */ memset(pdu, 0, MAX_PDU_SIZE); - assert_false(Avtp_Aaf_IsValid((Avtp_Aaf_t *)pdu, MAX_PDU_SIZE)); + assert_false(Avtp_Aaf_IsValid(aaf, MAX_PDU_SIZE)); /* Buffer smaller than the AAF header. */ - Avtp_Aaf_Init((Avtp_Aaf_t *)pdu); - assert_false(Avtp_Aaf_IsValid((Avtp_Aaf_t *)pdu, AVTP_AAF_HEADER_LEN - 1)); + Avtp_Aaf_Init(aaf); + assert_false(Avtp_Aaf_IsValid(aaf, AVTP_AAF_HEADER_LEN_V0 - 1)); /* stream_data_length does not fit into the buffer. */ - Avtp_Aaf_Init((Avtp_Aaf_t *)pdu); + Avtp_Aaf_Init(aaf); + Avtp_Aaf_SetStreamDataLength(aaf, 10); + assert_false(Avtp_Aaf_IsValid(aaf, AVTP_AAF_HEADER_LEN_V0 + 9)); + assert_true(Avtp_Aaf_IsValid(aaf, AVTP_AAF_HEADER_LEN_V0 + 10)); + + /* Valid version 1 frame. */ + Avtp_Aaf_InitV1((Avtp_AafV1_t *)pdu); Avtp_Aaf_SetStreamDataLength((Avtp_Aaf_t *)pdu, 10); - assert_false(Avtp_Aaf_IsValid((Avtp_Aaf_t *)pdu, AVTP_AAF_HEADER_LEN + 9)); - assert_true(Avtp_Aaf_IsValid((Avtp_Aaf_t *)pdu, AVTP_AAF_HEADER_LEN + 10)); + assert_true(Avtp_Aaf_IsValid((Avtp_Aaf_t *)pdu, AVTP_AAF_HEADER_LEN_V1 + 10)); + assert_false(Avtp_Aaf_IsValid((Avtp_Aaf_t *)pdu, AVTP_AAF_HEADER_LEN_V1 + 9)); + assert_false(Avtp_Aaf_IsValid((Avtp_Aaf_t *)pdu, AVTP_AAF_HEADER_LEN_V1 - 1)); + + /* Unsupported version is rejected. */ + Avtp_Aaf_Init(aaf); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, 2); + assert_false(Avtp_Aaf_IsValid(aaf, MAX_PDU_SIZE)); } -static void aaf_field_descriptors_cover_header(void **state) +static void mark_descriptors(uint8_t *coverage, size_t coverageBits, + const Avtp_FieldDescriptor_t *desc, uint8_t numFields) { - (void)state; - uint8_t coverage[AVTP_AAF_HEADER_LEN * 8] = {0}; - - /* Every bit of the header must be described exactly once. */ - for (uint8_t i = 0; i < AVTP_AAF_FIELD_MAX; i++) { - uint8_t quadlet = Avtp_AafFieldDesc[i].quadlet; - uint8_t offset = Avtp_AafFieldDesc[i].offset; - uint8_t bits = Avtp_AafFieldDesc[i].bits; + for (uint8_t i = 0; i < numFields; i++) { + uint8_t bits = desc[i].bits; + uint8_t offset = desc[i].offset; + uint8_t quadlet = desc[i].quadlet; for (uint8_t b = 0; b < bits; b++) { size_t bit = ((size_t)quadlet * 32) + offset + b; - assert_true(bit < sizeof(coverage)); + assert_true(bit < coverageBits); assert_int_equal(coverage[bit], 0); coverage[bit] = 1; } } +} - for (size_t bit = 0; bit < sizeof(coverage); bit++) { - assert_int_equal(coverage[bit], 1); +static void aaf_field_descriptors_cover_header(void **state) +{ + (void)state; + + for (uint8_t version = 0; version <= 1; version++) { + uint8_t coverage[AVTP_AAF_HEADER_LEN_V1 * 8] = {0}; + size_t coverageBits = sizeof(coverage); + const Avtp_FieldDescriptor_t *aafDesc = + version == AVTP_VERSION_1 ? Avtp_AafFieldDescV1 : Avtp_AafFieldDescV0; + size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_AAF_HEADER_LEN_V1 + : (size_t)AVTP_AAF_HEADER_LEN_V0) * + 8; + + /* subtype and version are owned by the common header; h/sv is covered + * by the format table. */ + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_SUBTYPE], 1); + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_VERSION], 1); + mark_descriptors(coverage, coverageBits, aafDesc, AVTP_AAF_FIELD_MAX); + + for (size_t bit = 0; bit < coverageBits; bit++) { + assert_int_equal(coverage[bit], bit < headerBits ? 1 : 0); + } + } +} + +static void aaf_common_field_consistency(void **state) +{ + (void)state; + + /* The common fields must be declared in the same order as in the common + * stream header module, so the tables can be compared index by index. */ + assert_int_equal(AVTP_AAF_FIELD_STREAM_DATA_LENGTH, AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH); + + for (uint8_t version = 0; version <= 1; version++) { + const Avtp_FieldDescriptor_t *aafDesc = + version == AVTP_VERSION_1 ? Avtp_AafFieldDescV1 : Avtp_AafFieldDescV0; + const Avtp_FieldDescriptor_t *cshDesc = + version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + + for (uint8_t i = 0; i < AVTPDU_CSH_FIELD_MAX; i++) { + assert_int_equal(aafDesc[i].quadlet, cshDesc[i].quadlet); + assert_int_equal(aafDesc[i].offset, cshDesc[i].offset); + assert_int_equal(aafDesc[i].bits, cshDesc[i].bits); + } } } @@ -211,6 +287,43 @@ static void aaf_field_layout(void **state) Avtp_Aaf_SetAafFormatSpecificData2(aaf, 0xAB); assert_int_equal(Avtp_Aaf_GetAafFormatSpecificData2(aaf), 0xAB); assert_int_equal(read_quadlet(pdu, 5), 0xAAAABAAB); + + /* ptp_grandmaster_identity does not exist in version 0. */ + assert_int_equal(Avtp_Aaf_GetPtpGrandmasterIdentity(aaf), 0); +} + +static void aaf_v1_layout(void **state) +{ + (void)state; + uint8_t pdu[AVTP_AAF_HEADER_LEN_V1]; + Avtp_Aaf_t *aaf = (Avtp_Aaf_t *)pdu; + + Avtp_Aaf_InitV1((Avtp_AafV1_t *)pdu); + + Avtp_Aaf_SetSequenceNum(aaf, 0x12345678); + assert_int_equal(Avtp_Aaf_GetSequenceNum(aaf), 0x12345678); + assert_int_equal(read_quadlet(pdu, 3), 0x12345678); + + Avtp_Aaf_SetAvtpTimestamp(aaf, 0x1122334455667788ULL); + assert_int_equal(Avtp_Aaf_GetAvtpTimestamp(aaf), 0x1122334455667788ULL); + assert_int_equal(read_quadlet(pdu, 4), 0x11223344); + assert_int_equal(read_quadlet(pdu, 5), 0x55667788); + + Avtp_Aaf_SetPtpGrandmasterIdentity(aaf, 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Aaf_GetPtpGrandmasterIdentity(aaf), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(read_quadlet(pdu, 6), 0x99AABBCC); + assert_int_equal(read_quadlet(pdu, 7), 0xDDEEFF00); + + Avtp_Aaf_SetFormat(aaf, AVTP_AAF_FORMAT_INT_16BIT); + Avtp_Aaf_SetAafFormatSpecificData1(aaf, 0x123456); + assert_int_equal(read_quadlet(pdu, 8), 0x04123456); + + Avtp_Aaf_SetStreamDataLength(aaf, 0xAAAA); + Avtp_Aaf_SetAfsd(aaf, 0x5); + Avtp_Aaf_SetSp(aaf, true); + Avtp_Aaf_SetEvt(aaf, 0xA); + Avtp_Aaf_SetAafFormatSpecificData2(aaf, 0xAB); + assert_int_equal(read_quadlet(pdu, 9), 0xAAAABAAB); } static void aaf_payload(void **state) @@ -224,11 +337,17 @@ static void aaf_payload(void **state) Avtp_Aaf_Init(aaf); Avtp_Aaf_SetPayload(aaf, payload, sizeof(payload)); - assert_memory_equal(Avtp_Aaf_GetPayload(aaf), payload, sizeof(payload)); - assert_memory_equal(aaf->payload, payload, sizeof(payload)); + assert_ptr_equal(Avtp_Aaf_GetPayload(aaf), pdu + AVTP_AAF_HEADER_LEN_V0); + assert_memory_equal(pdu + AVTP_AAF_HEADER_LEN_V0, payload, sizeof(payload)); memcpy(payload_out, Avtp_Aaf_GetPayload(aaf), sizeof(payload_out)); assert_memory_equal(payload_out, payload, sizeof(payload_out)); + + /* Version 1 payload starts after the 40-octet header. */ + Avtp_Aaf_InitV1((Avtp_AafV1_t *)pdu); + Avtp_Aaf_SetPayload((Avtp_Aaf_t *)pdu, payload, sizeof(payload)); + assert_ptr_equal(Avtp_Aaf_GetPayload((Avtp_Aaf_t *)pdu), pdu + AVTP_AAF_HEADER_LEN_V1); + assert_memory_equal(pdu + AVTP_AAF_HEADER_LEN_V1, payload, sizeof(payload)); } static void aaf_get_set_field(void **state) @@ -243,21 +362,24 @@ static void aaf_get_set_field(void **state) assert_int_equal(Avtp_Aaf_GetField(aaf, AVTP_AAF_FIELD_EVT), 0xA); /* Reserved fields are reachable through the generic access engine. */ - Avtp_Aaf_SetField(aaf, AVTP_AAF_FIELD_RSV, 0x3); - assert_int_equal(Avtp_Aaf_GetField(aaf, AVTP_AAF_FIELD_RSV), 0x3); + Avtp_Aaf_SetField(aaf, AVTP_AAF_FIELD_FSD, 0x3); + assert_int_equal(Avtp_Aaf_GetField(aaf, AVTP_AAF_FIELD_FSD), 0x3); - Avtp_Aaf_SetField(aaf, AVTP_AAF_FIELD_RESERVED, 0x7F); - assert_int_equal(Avtp_Aaf_GetField(aaf, AVTP_AAF_FIELD_RESERVED), 0x7F); + Avtp_Aaf_SetField(aaf, AVTP_AAF_FIELD_FSD1, 0x7F); + assert_int_equal(Avtp_Aaf_GetField(aaf, AVTP_AAF_FIELD_FSD1), 0x7F); } int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(aaf_init), + cmocka_unit_test(aaf_init_v1), cmocka_unit_test(aaf_is_valid), cmocka_unit_test(aaf_field_descriptors_cover_header), + cmocka_unit_test(aaf_common_field_consistency), cmocka_unit_test(aaf_flag_fields), cmocka_unit_test(aaf_field_layout), + cmocka_unit_test(aaf_v1_layout), cmocka_unit_test(aaf_payload), cmocka_unit_test(aaf_get_set_field), }; diff --git a/unit/test-cvf.c b/unit/test-cvf.c index 0744df8d..1b2af508 100644 --- a/unit/test-cvf.c +++ b/unit/test-cvf.c @@ -42,6 +42,7 @@ extern "C" { #include #include "avtp/CommonHeader.h" +#include "avtp/CommonStreamHeader.h" #include "avtp/cvf/Cvf.h" #include "avtp/cvf/H264.h" #include "avtp/cvf/Jpeg2000.h" @@ -65,19 +66,40 @@ static void cvf_init(void **state) { (void)state; uint8_t pdu[MAX_PDU_SIZE]; - uint8_t init_pdu[AVTP_CVF_HEADER_LEN]; + uint8_t init_pdu[AVTP_CVF_HEADER_LEN_V0]; - assert_int_equal(sizeof(Avtp_Cvf_t), AVTP_CVF_HEADER_LEN); + assert_int_equal(sizeof(Avtp_Cvf_t), AVTP_CVF_HEADER_LEN_V0); /* Passing a NULL pointer must be a no-op. */ Avtp_Cvf_Init(NULL); Avtp_Cvf_Init((Avtp_Cvf_t *)pdu); - memset(init_pdu, 0, AVTP_CVF_HEADER_LEN); + memset(init_pdu, 0, AVTP_CVF_HEADER_LEN_V0); init_pdu[0] = AVTP_SUBTYPE_CVF; /* subtype = CVF */ - init_pdu[1] = 0x80; /* sv = 1 */ + init_pdu[1] = 0x80; /* sv = 1, version = 0 */ init_pdu[16] = AVTP_CVF_FORMAT_RFC; /* format = RFC */ - assert_memory_equal(init_pdu, pdu, AVTP_CVF_HEADER_LEN); + assert_memory_equal(init_pdu, pdu, AVTP_CVF_HEADER_LEN_V0); +} + +static void cvf_init_v1(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t init_pdu[AVTP_CVF_HEADER_LEN_V1]; + + assert_int_equal(sizeof(Avtp_CvfV1_t), AVTP_CVF_HEADER_LEN_V1); + + /* Passing a NULL pointer must be a no-op. */ + Avtp_Cvf_InitV1(NULL); + + Avtp_Cvf_InitV1((Avtp_CvfV1_t *)pdu); + memset(init_pdu, 0, AVTP_CVF_HEADER_LEN_V1); + init_pdu[0] = AVTP_SUBTYPE_CVF; /* subtype = CVF */ + init_pdu[1] = 0x90; /* sv = 1, version = 1 */ + init_pdu[32] = AVTP_CVF_FORMAT_RFC; /* format = RFC at q8@0 */ + assert_memory_equal(init_pdu, pdu, AVTP_CVF_HEADER_LEN_V1); + + assert_int_equal(Avtp_Cvf_GetHeaderLen((Avtp_Cvf_t *)pdu), AVTP_CVF_HEADER_LEN_V1); } static void cvf_is_valid(void **state) @@ -86,7 +108,7 @@ static void cvf_is_valid(void **state) uint8_t pdu[MAX_PDU_SIZE]; Avtp_Cvf_Init((Avtp_Cvf_t *)pdu); - assert_true(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN)); + assert_true(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN_V0)); /* NULL pdu. */ assert_false(Avtp_Cvf_IsValid(NULL, MAX_PDU_SIZE)); @@ -97,37 +119,87 @@ static void cvf_is_valid(void **state) /* Buffer smaller than the CVF header. */ Avtp_Cvf_Init((Avtp_Cvf_t *)pdu); - assert_false(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN - 1)); + assert_false(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN_V0 - 1)); /* stream_data_length does not fit into the buffer. */ Avtp_Cvf_Init((Avtp_Cvf_t *)pdu); Avtp_Cvf_SetStreamDataLength((Avtp_Cvf_t *)pdu, 10); - assert_false(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN + 9)); - assert_true(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN + 10)); + assert_false(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN_V0 + 9)); + assert_true(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN_V0 + 10)); + + /* Valid version 1 frame. */ + Avtp_Cvf_InitV1((Avtp_CvfV1_t *)pdu); + Avtp_Cvf_SetStreamDataLength((Avtp_Cvf_t *)pdu, 10); + assert_true(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN_V1 + 10)); + assert_false(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN_V1 + 9)); + assert_false(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN_V1 - 1)); + + /* Unsupported version is rejected. */ + Avtp_Cvf_Init((Avtp_Cvf_t *)pdu); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, 2); + assert_false(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, MAX_PDU_SIZE)); } -static void cvf_field_descriptors_cover_header(void **state) +static void mark_descriptors(uint8_t *coverage, size_t coverageBits, + const Avtp_FieldDescriptor_t *desc, uint8_t numFields) { - (void)state; - uint8_t coverage[AVTP_CVF_HEADER_LEN * 8] = {0}; - - /* Every bit of the header must be described exactly once. */ - for (uint8_t i = 0; i < AVTP_CVF_FIELD_MAX; i++) { - uint8_t quadlet = Avtp_CvfFieldDesc[i].quadlet; - uint8_t offset = Avtp_CvfFieldDesc[i].offset; - uint8_t bits = Avtp_CvfFieldDesc[i].bits; + for (uint8_t i = 0; i < numFields; i++) { + uint8_t bits = desc[i].bits; + uint8_t offset = desc[i].offset; + uint8_t quadlet = desc[i].quadlet; for (uint8_t b = 0; b < bits; b++) { size_t bit = ((size_t)quadlet * 32) + offset + b; - assert_true(bit < sizeof(coverage)); + assert_true(bit < coverageBits); assert_int_equal(coverage[bit], 0); coverage[bit] = 1; } } +} - for (size_t bit = 0; bit < sizeof(coverage); bit++) { - assert_int_equal(coverage[bit], 1); +static void cvf_field_descriptors_cover_header(void **state) +{ + (void)state; + + for (uint8_t version = 0; version <= 1; version++) { + uint8_t coverage[AVTP_CVF_HEADER_LEN_V1 * 8] = {0}; + size_t coverageBits = sizeof(coverage); + const Avtp_FieldDescriptor_t *cvfDesc = + version == AVTP_VERSION_1 ? Avtp_CvfFieldDescV1 : Avtp_CvfFieldDescV0; + size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_CVF_HEADER_LEN_V1 + : (size_t)AVTP_CVF_HEADER_LEN_V0) * + 8; + + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_SUBTYPE], 1); + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_VERSION], 1); + mark_descriptors(coverage, coverageBits, cvfDesc, AVTP_CVF_FIELD_MAX); + + for (size_t bit = 0; bit < coverageBits; bit++) { + assert_int_equal(coverage[bit], bit < headerBits ? 1 : 0); + } + } +} + +static void cvf_common_field_consistency(void **state) +{ + (void)state; + + assert_int_equal(AVTP_CVF_FIELD_STREAM_DATA_LENGTH, AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH); + + for (uint8_t version = 0; version <= 1; version++) { + const Avtp_FieldDescriptor_t *cvfDesc = + version == AVTP_VERSION_1 ? Avtp_CvfFieldDescV1 : Avtp_CvfFieldDescV0; + const Avtp_FieldDescriptor_t *cshDesc = + version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + + for (uint8_t i = 0; i < AVTPDU_CSH_FIELD_MAX; i++) { + assert_int_equal(cvfDesc[i].quadlet, cshDesc[i].quadlet); + assert_int_equal(cvfDesc[i].offset, cshDesc[i].offset); + assert_int_equal(cvfDesc[i].bits, cshDesc[i].bits); + } } } @@ -221,6 +293,42 @@ static void cvf_field_layout(void **state) Avtp_Cvf_SetEvt(cvf, 0xA); assert_int_equal(Avtp_Cvf_GetEvt(cvf), 0xA); assert_int_equal(read_quadlet(pdu, 5), 0xAAAA3A00); + + /* ptp_grandmaster_identity does not exist in version 0. */ + assert_int_equal(Avtp_Cvf_GetPtpGrandmasterIdentity(cvf), 0); +} + +static void cvf_v1_layout(void **state) +{ + (void)state; + uint8_t pdu[AVTP_CVF_HEADER_LEN_V1]; + Avtp_Cvf_t *cvf = (Avtp_Cvf_t *)pdu; + + Avtp_Cvf_InitV1((Avtp_CvfV1_t *)pdu); + + Avtp_Cvf_SetSequenceNum(cvf, 0x12345678); + assert_int_equal(Avtp_Cvf_GetSequenceNum(cvf), 0x12345678); + assert_int_equal(read_quadlet(pdu, 3), 0x12345678); + + Avtp_Cvf_SetAvtpTimestamp(cvf, 0x1122334455667788ULL); + assert_int_equal(Avtp_Cvf_GetAvtpTimestamp(cvf), 0x1122334455667788ULL); + assert_int_equal(read_quadlet(pdu, 4), 0x11223344); + assert_int_equal(read_quadlet(pdu, 5), 0x55667788); + + Avtp_Cvf_SetPtpGrandmasterIdentity(cvf, 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Cvf_GetPtpGrandmasterIdentity(cvf), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(read_quadlet(pdu, 6), 0x99AABBCC); + assert_int_equal(read_quadlet(pdu, 7), 0xDDEEFF00); + + Avtp_Cvf_SetFormat(cvf, AVTP_CVF_FORMAT_RFC); + Avtp_Cvf_SetFormatSubtype(cvf, AVTP_CVF_FORMAT_SUBTYPE_H264); + assert_int_equal(read_quadlet(pdu, 8), 0x02010000); + + Avtp_Cvf_SetStreamDataLength(cvf, 0xAAAA); + Avtp_Cvf_SetPtv(cvf, true); + Avtp_Cvf_SetM(cvf, true); + Avtp_Cvf_SetEvt(cvf, 0xA); + assert_int_equal(read_quadlet(pdu, 9), 0xAAAA3A00); } static void cvf_payload(void **state) @@ -234,11 +342,17 @@ static void cvf_payload(void **state) Avtp_Cvf_Init(cvf); Avtp_Cvf_SetPayload(cvf, payload, sizeof(payload)); - assert_memory_equal(Avtp_Cvf_GetPayload(cvf), payload, sizeof(payload)); - assert_memory_equal(cvf->payload, payload, sizeof(payload)); + assert_ptr_equal(Avtp_Cvf_GetPayload(cvf), pdu + AVTP_CVF_HEADER_LEN_V0); + assert_memory_equal(pdu + AVTP_CVF_HEADER_LEN_V0, payload, sizeof(payload)); memcpy(payload_out, Avtp_Cvf_GetPayload(cvf), sizeof(payload_out)); assert_memory_equal(payload_out, payload, sizeof(payload_out)); + + /* Version 1 payload starts after the 40-octet header. */ + Avtp_Cvf_InitV1((Avtp_CvfV1_t *)pdu); + Avtp_Cvf_SetPayload((Avtp_Cvf_t *)pdu, payload, sizeof(payload)); + assert_ptr_equal(Avtp_Cvf_GetPayload((Avtp_Cvf_t *)pdu), pdu + AVTP_CVF_HEADER_LEN_V1); + assert_memory_equal(pdu + AVTP_CVF_HEADER_LEN_V1, payload, sizeof(payload)); } static void cvf_get_set_field(void **state) @@ -253,11 +367,11 @@ static void cvf_get_set_field(void **state) assert_int_equal(Avtp_Cvf_GetField(cvf, AVTP_CVF_FIELD_EVT), 0xA); /* Reserved fields are reachable through the generic access engine. */ - Avtp_Cvf_SetField(cvf, AVTP_CVF_FIELD_RSV1, 0x3); - assert_int_equal(Avtp_Cvf_GetField(cvf, AVTP_CVF_FIELD_RSV1), 0x3); + Avtp_Cvf_SetField(cvf, AVTP_CVF_FIELD_FSD, 0x3); + assert_int_equal(Avtp_Cvf_GetField(cvf, AVTP_CVF_FIELD_FSD), 0x3); - Avtp_Cvf_SetField(cvf, AVTP_CVF_FIELD_RESERVED1, 0x7F); - assert_int_equal(Avtp_Cvf_GetField(cvf, AVTP_CVF_FIELD_RESERVED1), 0x7F); + Avtp_Cvf_SetField(cvf, AVTP_CVF_FIELD_FSD1, 0x7F); + assert_int_equal(Avtp_Cvf_GetField(cvf, AVTP_CVF_FIELD_FSD1), 0x7F); } /****************************************************************************** @@ -567,10 +681,13 @@ int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(cvf_init), + cmocka_unit_test(cvf_init_v1), cmocka_unit_test(cvf_is_valid), cmocka_unit_test(cvf_field_descriptors_cover_header), + cmocka_unit_test(cvf_common_field_consistency), cmocka_unit_test(cvf_flag_fields), cmocka_unit_test(cvf_field_layout), + cmocka_unit_test(cvf_v1_layout), cmocka_unit_test(cvf_payload), cmocka_unit_test(cvf_get_set_field), cmocka_unit_test(mjpeg_init), diff --git a/unit/test-pcm.c b/unit/test-pcm.c index d0c531b7..4a656904 100644 --- a/unit/test-pcm.c +++ b/unit/test-pcm.c @@ -41,6 +41,8 @@ extern "C" { #include #include "avtp/CommonHeader.h" +#include "avtp/CommonStreamHeader.h" +#include "avtp/aaf/Aaf.h" #include "avtp/aaf/Pcm.h" #define MAX_PDU_SIZE 1500 @@ -65,18 +67,38 @@ static void pcm_init(void **state) { (void)state; uint8_t pdu[MAX_PDU_SIZE]; - uint8_t init_pdu[AVTP_PCM_HEADER_LEN]; + uint8_t init_pdu[AVTP_PCM_HEADER_LEN_V0]; - assert_int_equal(sizeof(Avtp_Pcm_t), AVTP_PCM_HEADER_LEN); + assert_int_equal(sizeof(Avtp_Pcm_t), AVTP_PCM_HEADER_LEN_V0); /* Passing a NULL pointer must be a no-op. */ Avtp_Pcm_Init(NULL); Avtp_Pcm_Init((Avtp_Pcm_t *)pdu); - memset(init_pdu, 0, AVTP_PCM_HEADER_LEN); + memset(init_pdu, 0, AVTP_PCM_HEADER_LEN_V0); init_pdu[0] = AVTP_SUBTYPE_AAF; /* subtype = AAF */ - init_pdu[1] = 0x80; /* sv = 1 */ - assert_memory_equal(init_pdu, pdu, AVTP_PCM_HEADER_LEN); + init_pdu[1] = 0x80; /* sv = 1, version = 0 */ + assert_memory_equal(init_pdu, pdu, AVTP_PCM_HEADER_LEN_V0); +} + +static void pcm_init_v1(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t init_pdu[AVTP_PCM_HEADER_LEN_V1]; + + assert_int_equal(sizeof(Avtp_PcmV1_t), AVTP_PCM_HEADER_LEN_V1); + + /* Passing a NULL pointer must be a no-op. */ + Avtp_Pcm_InitV1(NULL); + + Avtp_Pcm_InitV1((Avtp_PcmV1_t *)pdu); + memset(init_pdu, 0, AVTP_PCM_HEADER_LEN_V1); + init_pdu[0] = AVTP_SUBTYPE_AAF; /* subtype = AAF */ + init_pdu[1] = 0x90; /* sv = 1, version = 1 */ + assert_memory_equal(init_pdu, pdu, AVTP_PCM_HEADER_LEN_V1); + + assert_int_equal(Avtp_Pcm_GetHeaderLen((Avtp_Pcm_t *)pdu), AVTP_PCM_HEADER_LEN_V1); } static void pcm_is_valid(void **state) @@ -86,7 +108,7 @@ static void pcm_is_valid(void **state) Avtp_Pcm_t *pcm = (Avtp_Pcm_t *)pdu; init_valid_pcm(pcm); - assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); /* NULL pdu. */ assert_false(Avtp_Pcm_IsValid(NULL, MAX_PDU_SIZE)); @@ -97,88 +119,162 @@ static void pcm_is_valid(void **state) /* Buffer smaller than the AAF header. */ init_valid_pcm(pcm); - assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN - 1)); + assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0 - 1)); /* stream_data_length does not fit into the buffer. */ init_valid_pcm(pcm); Avtp_Pcm_SetStreamDataLength(pcm, 10); - assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN + 9)); - assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN + 10)); + assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0 + 9)); + assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0 + 10)); /* AES3 (0x05) and reserved format values (0x06) are not PCM. */ init_valid_pcm(pcm); Avtp_Pcm_SetFormat(pcm, AVTP_AAF_FORMAT_AES3_32BIT); - assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); Avtp_Pcm_SetFormat(pcm, (Avtp_AafFormat_t)0x06); - assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); /* channels_per_frame shall be a positive integer. */ init_valid_pcm(pcm); Avtp_Pcm_SetChannelsPerFrame(pcm, 0); - assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); /* bit_depth shall not be zero. */ init_valid_pcm(pcm); Avtp_Pcm_SetBitDepth(pcm, 0); - assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); /* bit_depth shall not exceed the sample container size. */ init_valid_pcm(pcm); Avtp_Pcm_SetFormat(pcm, AVTP_AAF_FORMAT_INT_16BIT); Avtp_Pcm_SetBitDepth(pcm, 24); - assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); Avtp_Pcm_SetBitDepth(pcm, 16); - assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); init_valid_pcm(pcm); Avtp_Pcm_SetFormat(pcm, AVTP_AAF_FORMAT_INT_24BIT); Avtp_Pcm_SetBitDepth(pcm, 24); - assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); Avtp_Pcm_SetBitDepth(pcm, 32); - assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); init_valid_pcm(pcm); Avtp_Pcm_SetFormat(pcm, AVTP_AAF_FORMAT_INT_32BIT); Avtp_Pcm_SetBitDepth(pcm, 32); - assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); /* FLOAT_32BIT requires bit_depth to be exactly 32. */ init_valid_pcm(pcm); Avtp_Pcm_SetFormat(pcm, AVTP_AAF_FORMAT_FLOAT_32BIT); Avtp_Pcm_SetBitDepth(pcm, 24); - assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_false(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); Avtp_Pcm_SetBitDepth(pcm, 32); - assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); /* The sample size of a user format is not constrained. */ init_valid_pcm(pcm); Avtp_Pcm_SetFormat(pcm, AVTP_AAF_FORMAT_USER); Avtp_Pcm_SetBitDepth(pcm, 20); - assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN)); + assert_true(Avtp_Pcm_IsValid(pcm, AVTP_PCM_HEADER_LEN_V0)); + + /* Valid version 1 frame. */ + Avtp_Pcm_InitV1((Avtp_PcmV1_t *)pdu); + Avtp_Pcm_SetChannelsPerFrame((Avtp_Pcm_t *)pdu, 2); + Avtp_Pcm_SetBitDepth((Avtp_Pcm_t *)pdu, 16); + assert_true(Avtp_Pcm_IsValid((Avtp_Pcm_t *)pdu, AVTP_PCM_HEADER_LEN_V1)); + assert_false(Avtp_Pcm_IsValid((Avtp_Pcm_t *)pdu, AVTP_PCM_HEADER_LEN_V1 - 1)); + + /* Unsupported version is rejected. */ + init_valid_pcm(pcm); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, 2); + assert_false(Avtp_Pcm_IsValid(pcm, MAX_PDU_SIZE)); } -static void pcm_field_descriptors_cover_header(void **state) +static void mark_descriptors(uint8_t *coverage, size_t coverageBits, + const Avtp_FieldDescriptor_t *desc, uint8_t numFields) { - (void)state; - uint8_t coverage[AVTP_PCM_HEADER_LEN * 8] = {0}; - - /* Every bit of the header must be described exactly once. */ - for (uint8_t i = 0; i < AVTP_PCM_FIELD_MAX; i++) { - uint8_t quadlet = Avtp_PcmFieldDesc[i].quadlet; - uint8_t offset = Avtp_PcmFieldDesc[i].offset; - uint8_t bits = Avtp_PcmFieldDesc[i].bits; + for (uint8_t i = 0; i < numFields; i++) { + uint8_t bits = desc[i].bits; + uint8_t offset = desc[i].offset; + uint8_t quadlet = desc[i].quadlet; for (uint8_t b = 0; b < bits; b++) { size_t bit = ((size_t)quadlet * 32) + offset + b; - assert_true(bit < sizeof(coverage)); + assert_true(bit < coverageBits); assert_int_equal(coverage[bit], 0); coverage[bit] = 1; } } +} + +static void pcm_field_descriptors_cover_header(void **state) +{ + (void)state; + + for (uint8_t version = 0; version <= 1; version++) { + uint8_t coverage[AVTP_PCM_HEADER_LEN_V1 * 8] = {0}; + size_t coverageBits = sizeof(coverage); + const Avtp_FieldDescriptor_t *pcmDesc = + version == AVTP_VERSION_1 ? Avtp_PcmFieldDescV1 : Avtp_PcmFieldDescV0; + size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_PCM_HEADER_LEN_V1 + : (size_t)AVTP_PCM_HEADER_LEN_V0) * + 8; + + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_SUBTYPE], 1); + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_VERSION], 1); + mark_descriptors(coverage, coverageBits, pcmDesc, AVTP_PCM_FIELD_MAX); + + for (size_t bit = 0; bit < coverageBits; bit++) { + assert_int_equal(coverage[bit], bit < headerBits ? 1 : 0); + } + } +} + +static void pcm_common_field_consistency(void **state) +{ + (void)state; + + assert_int_equal(AVTP_PCM_FIELD_STREAM_DATA_LENGTH, AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH); + + for (uint8_t version = 0; version <= 1; version++) { + const Avtp_FieldDescriptor_t *pcmDesc = + version == AVTP_VERSION_1 ? Avtp_PcmFieldDescV1 : Avtp_PcmFieldDescV0; + const Avtp_FieldDescriptor_t *cshDesc = + version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + + for (uint8_t i = 0; i < AVTPDU_CSH_FIELD_MAX; i++) { + assert_int_equal(pcmDesc[i].quadlet, cshDesc[i].quadlet); + assert_int_equal(pcmDesc[i].offset, cshDesc[i].offset); + assert_int_equal(pcmDesc[i].bits, cshDesc[i].bits); + } + } +} + +static void pcm_aaf_shared_field_consistency(void **state) +{ + (void)state; - for (size_t bit = 0; bit < sizeof(coverage); bit++) { - assert_int_equal(coverage[bit], 1); + for (uint8_t version = 0; version <= 1; version++) { + const Avtp_FieldDescriptor_t *pcmDesc = + version == AVTP_VERSION_1 ? Avtp_PcmFieldDescV1 : Avtp_PcmFieldDescV0; + const Avtp_FieldDescriptor_t *aafDesc = + version == AVTP_VERSION_1 ? Avtp_AafFieldDescV1 : Avtp_AafFieldDescV0; + + /* PCM and AAF interpret the same format-specific data slots, so the + * shared fields must have identical positions. */ + assert_memory_equal(&pcmDesc[AVTP_PCM_FIELD_FORMAT], &aafDesc[AVTP_AAF_FIELD_FORMAT], + sizeof(Avtp_FieldDescriptor_t)); + assert_memory_equal(&pcmDesc[AVTP_PCM_FIELD_SP], &aafDesc[AVTP_AAF_FIELD_SP], + sizeof(Avtp_FieldDescriptor_t)); + assert_memory_equal(&pcmDesc[AVTP_PCM_FIELD_EVT], &aafDesc[AVTP_AAF_FIELD_EVT], + sizeof(Avtp_FieldDescriptor_t)); + assert_memory_equal(&pcmDesc[AVTP_PCM_FIELD_STREAM_DATA_LENGTH], + &aafDesc[AVTP_AAF_FIELD_STREAM_DATA_LENGTH], + sizeof(Avtp_FieldDescriptor_t)); } } @@ -273,6 +369,49 @@ static void pcm_field_layout(void **state) Avtp_Pcm_SetEvt(pcm, 0xA); assert_int_equal(Avtp_Pcm_GetEvt(pcm), 0xA); assert_int_equal(read_quadlet(pdu, 5), 0xAAAA1A00); + + /* ptp_grandmaster_identity does not exist in version 0. */ + assert_int_equal(Avtp_Pcm_GetPtpGrandmasterIdentity(pcm), 0); +} + +static void pcm_v1_layout(void **state) +{ + (void)state; + uint8_t pdu[AVTP_PCM_HEADER_LEN_V1]; + Avtp_Pcm_t *pcm = (Avtp_Pcm_t *)pdu; + + Avtp_Pcm_InitV1((Avtp_PcmV1_t *)pdu); + + Avtp_Pcm_SetSequenceNum(pcm, 0x12345678); + assert_int_equal(Avtp_Pcm_GetSequenceNum(pcm), 0x12345678); + assert_int_equal(read_quadlet(pdu, 3), 0x12345678); + + Avtp_Pcm_SetAvtpTimestamp(pcm, 0x1122334455667788ULL); + assert_int_equal(Avtp_Pcm_GetAvtpTimestamp(pcm), 0x1122334455667788ULL); + assert_int_equal(read_quadlet(pdu, 4), 0x11223344); + assert_int_equal(read_quadlet(pdu, 5), 0x55667788); + + Avtp_Pcm_SetPtpGrandmasterIdentity(pcm, 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Pcm_GetPtpGrandmasterIdentity(pcm), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(read_quadlet(pdu, 6), 0x99AABBCC); + assert_int_equal(read_quadlet(pdu, 7), 0xDDEEFF00); + + Avtp_Pcm_SetFormat(pcm, AVTP_AAF_FORMAT_INT_16BIT); + assert_int_equal(read_quadlet(pdu, 8), 0x04000000); + + Avtp_Pcm_SetNsr(pcm, AVTP_PCM_NSR_48KHZ); + assert_int_equal(read_quadlet(pdu, 8), 0x04500000); + + Avtp_Pcm_SetChannelsPerFrame(pcm, 0x2AA); + assert_int_equal(read_quadlet(pdu, 8), 0x0452AA00); + + Avtp_Pcm_SetBitDepth(pcm, 0xA5); + assert_int_equal(read_quadlet(pdu, 8), 0x0452AAA5); + + Avtp_Pcm_SetStreamDataLength(pcm, 0xAAAA); + Avtp_Pcm_SetSp(pcm, true); + Avtp_Pcm_SetEvt(pcm, 0xA); + assert_int_equal(read_quadlet(pdu, 9), 0xAAAA1A00); } static void pcm_payload(void **state) @@ -286,11 +425,17 @@ static void pcm_payload(void **state) Avtp_Pcm_Init(pcm); Avtp_Pcm_SetPayload(pcm, payload, sizeof(payload)); - assert_memory_equal(Avtp_Pcm_GetPayload(pcm), payload, sizeof(payload)); - assert_memory_equal(pcm->payload, payload, sizeof(payload)); + assert_ptr_equal(Avtp_Pcm_GetPayload(pcm), pdu + AVTP_PCM_HEADER_LEN_V0); + assert_memory_equal(pdu + AVTP_PCM_HEADER_LEN_V0, payload, sizeof(payload)); memcpy(payload_out, Avtp_Pcm_GetPayload(pcm), sizeof(payload_out)); assert_memory_equal(payload_out, payload, sizeof(payload_out)); + + /* Version 1 payload starts after the 40-octet header. */ + Avtp_Pcm_InitV1((Avtp_PcmV1_t *)pdu); + Avtp_Pcm_SetPayload((Avtp_Pcm_t *)pdu, payload, sizeof(payload)); + assert_ptr_equal(Avtp_Pcm_GetPayload((Avtp_Pcm_t *)pdu), pdu + AVTP_PCM_HEADER_LEN_V1); + assert_memory_equal(pdu + AVTP_PCM_HEADER_LEN_V1, payload, sizeof(payload)); } static void pcm_get_set_field(void **state) @@ -305,8 +450,8 @@ static void pcm_get_set_field(void **state) assert_int_equal(Avtp_Pcm_GetField(pcm, AVTP_PCM_FIELD_EVT), 0xA); /* Reserved fields are reachable through the generic access engine. */ - Avtp_Pcm_SetField(pcm, AVTP_PCM_FIELD_RSV2, 0x3); - assert_int_equal(Avtp_Pcm_GetField(pcm, AVTP_PCM_FIELD_RSV2), 0x3); + Avtp_Pcm_SetField(pcm, AVTP_PCM_FIELD_FSD, 0x3); + assert_int_equal(Avtp_Pcm_GetField(pcm, AVTP_PCM_FIELD_FSD), 0x3); Avtp_Pcm_SetField(pcm, AVTP_PCM_FIELD_RESERVED2, 0xAB); assert_int_equal(Avtp_Pcm_GetField(pcm, AVTP_PCM_FIELD_RESERVED2), 0xAB); @@ -316,10 +461,14 @@ int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(pcm_init), + cmocka_unit_test(pcm_init_v1), cmocka_unit_test(pcm_is_valid), cmocka_unit_test(pcm_field_descriptors_cover_header), + cmocka_unit_test(pcm_common_field_consistency), + cmocka_unit_test(pcm_aaf_shared_field_consistency), cmocka_unit_test(pcm_flag_fields), cmocka_unit_test(pcm_field_layout), + cmocka_unit_test(pcm_v1_layout), cmocka_unit_test(pcm_payload), cmocka_unit_test(pcm_get_set_field), }; diff --git a/unit/test-rvf.c b/unit/test-rvf.c index 5729ace6..ce7b6adc 100644 --- a/unit/test-rvf.c +++ b/unit/test-rvf.c @@ -44,6 +44,7 @@ extern "C" { #include #include "avtp/CommonHeader.h" +#include "avtp/CommonStreamHeader.h" #include "avtp/Rvf.h" #define MAX_PDU_SIZE 1500 @@ -67,18 +68,38 @@ static void rvf_init(void **state) { (void)state; uint8_t pdu[MAX_PDU_SIZE]; - uint8_t init_pdu[AVTP_RVF_HEADER_LEN]; + uint8_t init_pdu[AVTP_RVF_HEADER_LEN_V0]; - assert_int_equal(sizeof(Avtp_Rvf_t), AVTP_RVF_HEADER_LEN); + assert_int_equal(sizeof(Avtp_Rvf_t), AVTP_RVF_HEADER_LEN_V0); /* Passing a NULL pointer must be a no-op. */ Avtp_Rvf_Init(NULL); Avtp_Rvf_Init((Avtp_Rvf_t *)pdu); - memset(init_pdu, 0, AVTP_RVF_HEADER_LEN); + memset(init_pdu, 0, AVTP_RVF_HEADER_LEN_V0); init_pdu[0] = AVTP_SUBTYPE_RVF; /* subtype = RVF */ - init_pdu[1] = 0x80; /* sv = 1 */ - assert_memory_equal(init_pdu, pdu, AVTP_RVF_HEADER_LEN); + init_pdu[1] = 0x80; /* sv = 1, version = 0 */ + assert_memory_equal(init_pdu, pdu, AVTP_RVF_HEADER_LEN_V0); +} + +static void rvf_init_v1(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t init_pdu[AVTP_RVF_HEADER_LEN_V1]; + + assert_int_equal(sizeof(Avtp_RvfV1_t), AVTP_RVF_HEADER_LEN_V1); + + /* Passing a NULL pointer must be a no-op. */ + Avtp_Rvf_InitV1(NULL); + + Avtp_Rvf_InitV1((Avtp_RvfV1_t *)pdu); + memset(init_pdu, 0, AVTP_RVF_HEADER_LEN_V1); + init_pdu[0] = AVTP_SUBTYPE_RVF; /* subtype = RVF */ + init_pdu[1] = 0x90; /* sv = 1, version = 1 */ + assert_memory_equal(init_pdu, pdu, AVTP_RVF_HEADER_LEN_V1); + + assert_int_equal(Avtp_Rvf_GetHeaderLen((Avtp_Rvf_t *)pdu), AVTP_RVF_HEADER_LEN_V1); } static void rvf_is_valid(void **state) @@ -88,7 +109,7 @@ static void rvf_is_valid(void **state) Avtp_Rvf_t *rvf = (Avtp_Rvf_t *)pdu; init_valid_rvf(rvf); - assert_true(Avtp_Rvf_IsValid(rvf, AVTP_RVF_HEADER_LEN + AVTP_RVF_RAW_HEADER_LEN)); + assert_true(Avtp_Rvf_IsValid(rvf, AVTP_RVF_HEADER_LEN_V0 + AVTP_RVF_RAW_HEADER_LEN)); /* NULL pdu. */ assert_false(Avtp_Rvf_IsValid(NULL, MAX_PDU_SIZE)); @@ -99,7 +120,7 @@ static void rvf_is_valid(void **state) /* Buffer smaller than the RVF header. */ init_valid_rvf(rvf); - assert_false(Avtp_Rvf_IsValid(rvf, AVTP_RVF_HEADER_LEN - 1)); + assert_false(Avtp_Rvf_IsValid(rvf, AVTP_RVF_HEADER_LEN_V0 - 1)); /* The stream data always contains at least the raw header. */ init_valid_rvf(rvf); @@ -109,32 +130,82 @@ static void rvf_is_valid(void **state) /* stream_data_length does not fit into the buffer. */ init_valid_rvf(rvf); Avtp_Rvf_SetStreamDataLength(rvf, 16); - assert_false(Avtp_Rvf_IsValid(rvf, AVTP_RVF_HEADER_LEN + 15)); - assert_true(Avtp_Rvf_IsValid(rvf, AVTP_RVF_HEADER_LEN + 16)); + assert_false(Avtp_Rvf_IsValid(rvf, AVTP_RVF_HEADER_LEN_V0 + 15)); + assert_true(Avtp_Rvf_IsValid(rvf, AVTP_RVF_HEADER_LEN_V0 + 16)); + + /* Valid version 1 frame. */ + Avtp_Rvf_InitV1((Avtp_RvfV1_t *)pdu); + Avtp_Rvf_SetStreamDataLength((Avtp_Rvf_t *)pdu, AVTP_RVF_RAW_HEADER_LEN); + assert_true( + Avtp_Rvf_IsValid((Avtp_Rvf_t *)pdu, AVTP_RVF_HEADER_LEN_V1 + AVTP_RVF_RAW_HEADER_LEN)); + assert_false(Avtp_Rvf_IsValid((Avtp_Rvf_t *)pdu, AVTP_RVF_HEADER_LEN_V1 - 1)); + + /* Unsupported version is rejected. */ + init_valid_rvf(rvf); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, 2); + assert_false(Avtp_Rvf_IsValid(rvf, MAX_PDU_SIZE)); } -static void rvf_field_descriptors_cover_header(void **state) +static void mark_descriptors(uint8_t *coverage, size_t coverageBits, + const Avtp_FieldDescriptor_t *desc, uint8_t numFields) { - (void)state; - uint8_t coverage[AVTP_RVF_HEADER_LEN * 8] = {0}; - - /* Every bit of the header must be described exactly once. */ - for (uint8_t i = 0; i < AVTP_RVF_FIELD_MAX; i++) { - uint8_t quadlet = Avtp_RvfFieldDesc[i].quadlet; - uint8_t offset = Avtp_RvfFieldDesc[i].offset; - uint8_t bits = Avtp_RvfFieldDesc[i].bits; + for (uint8_t i = 0; i < numFields; i++) { + uint8_t bits = desc[i].bits; + uint8_t offset = desc[i].offset; + uint8_t quadlet = desc[i].quadlet; for (uint8_t b = 0; b < bits; b++) { size_t bit = ((size_t)quadlet * 32) + offset + b; - assert_true(bit < sizeof(coverage)); + assert_true(bit < coverageBits); assert_int_equal(coverage[bit], 0); coverage[bit] = 1; } } +} - for (size_t bit = 0; bit < sizeof(coverage); bit++) { - assert_int_equal(coverage[bit], 1); +static void rvf_field_descriptors_cover_header(void **state) +{ + (void)state; + + for (uint8_t version = 0; version <= 1; version++) { + uint8_t coverage[AVTP_RVF_HEADER_LEN_V1 * 8] = {0}; + size_t coverageBits = sizeof(coverage); + const Avtp_FieldDescriptor_t *rvfDesc = + version == AVTP_VERSION_1 ? Avtp_RvfFieldDescV1 : Avtp_RvfFieldDescV0; + size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_RVF_HEADER_LEN_V1 + : (size_t)AVTP_RVF_HEADER_LEN_V0) * + 8; + + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_SUBTYPE], 1); + mark_descriptors(coverage, coverageBits, + &Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIELD_VERSION], 1); + mark_descriptors(coverage, coverageBits, rvfDesc, AVTP_RVF_FIELD_MAX); + + for (size_t bit = 0; bit < coverageBits; bit++) { + assert_int_equal(coverage[bit], bit < headerBits ? 1 : 0); + } + } +} + +static void rvf_common_field_consistency(void **state) +{ + (void)state; + + assert_int_equal(AVTP_RVF_FIELD_STREAM_DATA_LENGTH, AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH); + + for (uint8_t version = 0; version <= 1; version++) { + const Avtp_FieldDescriptor_t *rvfDesc = + version == AVTP_VERSION_1 ? Avtp_RvfFieldDescV1 : Avtp_RvfFieldDescV0; + const Avtp_FieldDescriptor_t *cshDesc = + version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + + for (uint8_t i = 0; i < AVTPDU_CSH_FIELD_MAX; i++) { + assert_int_equal(rvfDesc[i].quadlet, cshDesc[i].quadlet); + assert_int_equal(rvfDesc[i].offset, cshDesc[i].offset); + assert_int_equal(rvfDesc[i].bits, cshDesc[i].bits); + } } } @@ -251,6 +322,45 @@ static void rvf_field_layout(void **state) Avtp_Rvf_SetI(rvf, true); assert_true(Avtp_Rvf_IsI(rvf)); assert_int_equal(read_quadlet(pdu, 5), 0xAAAABAC0); + + /* ptp_grandmaster_identity does not exist in version 0. */ + assert_int_equal(Avtp_Rvf_GetPtpGrandmasterIdentity(rvf), 0); +} + +static void rvf_v1_layout(void **state) +{ + (void)state; + uint8_t pdu[AVTP_RVF_HEADER_LEN_V1]; + Avtp_Rvf_t *rvf = (Avtp_Rvf_t *)pdu; + + Avtp_Rvf_InitV1((Avtp_RvfV1_t *)pdu); + + Avtp_Rvf_SetSequenceNum(rvf, 0x12345678); + assert_int_equal(Avtp_Rvf_GetSequenceNum(rvf), 0x12345678); + assert_int_equal(read_quadlet(pdu, 3), 0x12345678); + + Avtp_Rvf_SetAvtpTimestamp(rvf, 0x1122334455667788ULL); + assert_int_equal(Avtp_Rvf_GetAvtpTimestamp(rvf), 0x1122334455667788ULL); + assert_int_equal(read_quadlet(pdu, 4), 0x11223344); + assert_int_equal(read_quadlet(pdu, 5), 0x55667788); + + Avtp_Rvf_SetPtpGrandmasterIdentity(rvf, 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Rvf_GetPtpGrandmasterIdentity(rvf), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(read_quadlet(pdu, 6), 0x99AABBCC); + assert_int_equal(read_quadlet(pdu, 7), 0xDDEEFF00); + + Avtp_Rvf_SetActivePixels(rvf, 0x20); + Avtp_Rvf_SetTotalLines(rvf, 0x3C); + assert_int_equal(read_quadlet(pdu, 8), 0x0020003C); + + Avtp_Rvf_SetStreamDataLength(rvf, 0xAAAA); + Avtp_Rvf_SetAp(rvf, true); + Avtp_Rvf_SetF(rvf, true); + Avtp_Rvf_SetEf(rvf, true); + Avtp_Rvf_SetEvt(rvf, 0xA); + Avtp_Rvf_SetPd(rvf, true); + Avtp_Rvf_SetI(rvf, true); + assert_int_equal(read_quadlet(pdu, 9), 0xAAAABAC0); } static void rvf_payload(void **state) @@ -264,11 +374,17 @@ static void rvf_payload(void **state) Avtp_Rvf_Init(rvf); Avtp_Rvf_SetPayload(rvf, payload, sizeof(payload)); - assert_memory_equal(Avtp_Rvf_GetPayload(rvf), payload, sizeof(payload)); - assert_memory_equal(rvf->payload, payload, sizeof(payload)); + assert_ptr_equal(Avtp_Rvf_GetPayload(rvf), pdu + AVTP_RVF_HEADER_LEN_V0); + assert_memory_equal(pdu + AVTP_RVF_HEADER_LEN_V0, payload, sizeof(payload)); memcpy(payload_out, Avtp_Rvf_GetPayload(rvf), sizeof(payload_out)); assert_memory_equal(payload_out, payload, sizeof(payload_out)); + + /* Version 1 payload starts after the 40-octet header. */ + Avtp_Rvf_InitV1((Avtp_RvfV1_t *)pdu); + Avtp_Rvf_SetPayload((Avtp_Rvf_t *)pdu, payload, sizeof(payload)); + assert_ptr_equal(Avtp_Rvf_GetPayload((Avtp_Rvf_t *)pdu), pdu + AVTP_RVF_HEADER_LEN_V1); + assert_memory_equal(pdu + AVTP_RVF_HEADER_LEN_V1, payload, sizeof(payload)); } static void rvf_get_set_field(void **state) @@ -283,11 +399,11 @@ static void rvf_get_set_field(void **state) assert_int_equal(Avtp_Rvf_GetField(rvf, AVTP_RVF_FIELD_SEQUENCE_NUM), 0xAA); /* Reserved fields are reachable through the generic access engine. */ - Avtp_Rvf_SetField(rvf, AVTP_RVF_FIELD_RSV, 0x3); - assert_int_equal(Avtp_Rvf_GetField(rvf, AVTP_RVF_FIELD_RSV), 0x3); + Avtp_Rvf_SetField(rvf, AVTP_RVF_FIELD_FSD, 0x3); + assert_int_equal(Avtp_Rvf_GetField(rvf, AVTP_RVF_FIELD_FSD), 0x3); - Avtp_Rvf_SetField(rvf, AVTP_RVF_FIELD_RESERVED1, 0x5A); - assert_int_equal(Avtp_Rvf_GetField(rvf, AVTP_RVF_FIELD_RESERVED1), 0x5A); + Avtp_Rvf_SetField(rvf, AVTP_RVF_FIELD_FSD1, 0x5A); + assert_int_equal(Avtp_Rvf_GetField(rvf, AVTP_RVF_FIELD_FSD1), 0x5A); } static void rvf_raw_header_init(void **state) @@ -437,17 +553,20 @@ static void rvf_raw_header_overlay(void **state) Avtp_RvfRawHeader_SetPixelDepth(raw, AVTP_RVF_PIXEL_DEPTH_8); assert_int_equal(Avtp_RvfRawHeader_GetPixelDepth(raw), AVTP_RVF_PIXEL_DEPTH_8); - assert_true(Avtp_Rvf_IsValid(rvf, AVTP_RVF_HEADER_LEN + AVTP_RVF_RAW_HEADER_LEN)); + assert_true(Avtp_Rvf_IsValid(rvf, AVTP_RVF_HEADER_LEN_V0 + AVTP_RVF_RAW_HEADER_LEN)); } int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(rvf_init), + cmocka_unit_test(rvf_init_v1), cmocka_unit_test(rvf_is_valid), cmocka_unit_test(rvf_field_descriptors_cover_header), + cmocka_unit_test(rvf_common_field_consistency), cmocka_unit_test(rvf_flag_fields), cmocka_unit_test(rvf_field_layout), + cmocka_unit_test(rvf_v1_layout), cmocka_unit_test(rvf_payload), cmocka_unit_test(rvf_get_set_field), cmocka_unit_test(rvf_raw_header_init), From 16b574fdfb20e552567045e9f4e31e2af7033bd2 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Sun, 20 Sep 2026 22:29:28 +0200 Subject: [PATCH 09/16] Provide explicit v0 and v1 acessors for all fields for performance reasons Signed-off-by: Sebastian Schildt --- include/avtp/AlternativeHeader.h | 181 ++++++- include/avtp/CommonStreamHeader.h | 597 +++++++++++++++++++++- include/avtp/Crf.h | 664 +++++++++++++++++++++++- include/avtp/Rvf.h | 804 +++++++++++++++++++++++++++++- include/avtp/aaf/Aaf.h | 732 ++++++++++++++++++++++++++- include/avtp/aaf/Pcm.h | 732 ++++++++++++++++++++++++++- include/avtp/acf/Ntscf.h | 418 +++++++++++++++- include/avtp/acf/Tscf.h | 563 ++++++++++++++++++++- include/avtp/cvf/Cvf.h | 696 +++++++++++++++++++++++++- unit/CMakeLists.txt | 1 + unit/test-aaf.c | 164 ++++++ unit/test-alternativeheader.c | 163 ++++++ unit/test-commonstreamheader.c | 192 +++++++ unit/test-crf.c | 157 ++++++ unit/test-cvf.c | 155 ++++++ unit/test-ntscf.c | 130 +++++ unit/test-pcm.c | 163 ++++++ unit/test-rvf.c | 167 +++++++ unit/test-tscf.c | 137 +++++ 19 files changed, 6650 insertions(+), 166 deletions(-) create mode 100644 unit/test-alternativeheader.c diff --git a/include/avtp/AlternativeHeader.h b/include/avtp/AlternativeHeader.h index 7d500c1a..60f34427 100644 --- a/include/avtp/AlternativeHeader.h +++ b/include/avtp/AlternativeHeader.h @@ -116,7 +116,40 @@ OPEN1722_INLINE uint8_t Avtp_AlternativeHeader_GetVersion(const Avtp_Alternative } /** - * Returns the value of an AVTPDU alternative header field. + * Returns the value of an AVTPDU alternative header field as laid out by + * version 0. No version dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AVTP PDU. + * @param field Specifies the position of the data field to be read. + * @returns The value of the specified field. + * @see Avtp_AlternativeHeader_GetField + */ +OPEN1722_INLINE uint64_t Avtp_AlternativeHeader_GetField_V0( + const Avtp_AlternativeHeader_t *const pdu, Avtp_AlternativeHeaderField_t field) +{ + return Avtp_GetField(Avtp_AhFieldDescV0, AVTPDU_AH_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTPDU alternative header field as laid out by + * version 1. No version dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AVTP PDU. + * @param field Specifies the position of the data field to be read. + * @returns The value of the specified field. + * @see Avtp_AlternativeHeader_GetField + */ +OPEN1722_INLINE uint64_t Avtp_AlternativeHeader_GetField_V1( + const Avtp_AlternativeHeader_t *const pdu, Avtp_AlternativeHeaderField_t field) +{ + return Avtp_GetField(Avtp_AhFieldDescV1, AVTPDU_AH_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTPDU alternative header field, dispatching on the + * version field of the PDU. * * @param pdu Pointer to the first bit of an 1722 AVTP PDU. * @param field Specifies the position of the data field to be read. @@ -125,15 +158,49 @@ OPEN1722_INLINE uint8_t Avtp_AlternativeHeader_GetVersion(const Avtp_Alternative OPEN1722_INLINE uint64_t Avtp_AlternativeHeader_GetField(const Avtp_AlternativeHeader_t *const pdu, Avtp_AlternativeHeaderField_t field) { - const Avtp_FieldDescriptor_t *desc = Avtp_AlternativeHeader_GetVersion(pdu) == AVTP_VERSION_1 - ? Avtp_AhFieldDescV1 - : Avtp_AhFieldDescV0; - return Avtp_GetField(desc, AVTPDU_AH_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); + return Avtp_AlternativeHeader_GetVersion(pdu) == AVTP_VERSION_1 + ? Avtp_AlternativeHeader_GetField_V1(pdu, field) + : Avtp_AlternativeHeader_GetField_V0(pdu, field); +} + +/** + * Sets the value of an AVTPDU alternative header field as laid out by version + * 0. No version dispatch is performed; fields absent from version 0 are left + * untouched. + * + * @param pdu Pointer to the first bit of an 1722 AVTP PDU. + * @param field Specifies the position of the data field to be written. + * @param value The value to set. + * @see Avtp_AlternativeHeader_SetField + */ +OPEN1722_INLINE void Avtp_AlternativeHeader_SetField_V0(Avtp_AlternativeHeader_t *pdu, + Avtp_AlternativeHeaderField_t field, + uint64_t value) +{ + Avtp_SetField(Avtp_AhFieldDescV0, AVTPDU_AH_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); } /** - * Sets the value of an AVTPDU alternative header field. Fields absent from the - * version in use are left untouched. + * Sets the value of an AVTPDU alternative header field as laid out by version + * 1. No version dispatch is performed; fields absent from version 1 are left + * untouched. + * + * @param pdu Pointer to the first bit of an 1722 AVTP PDU. + * @param field Specifies the position of the data field to be written. + * @param value The value to set. + * @see Avtp_AlternativeHeader_SetField + */ +OPEN1722_INLINE void Avtp_AlternativeHeader_SetField_V1(Avtp_AlternativeHeader_t *pdu, + Avtp_AlternativeHeaderField_t field, + uint64_t value) +{ + Avtp_SetField(Avtp_AhFieldDescV1, AVTPDU_AH_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Sets the value of an AVTPDU alternative header field, dispatching on the + * version field of the PDU. Fields absent from the version in use are left + * untouched. * * @param pdu Pointer to the first bit of an 1722 AVTP PDU. * @param field Specifies the position of the data field to be written. @@ -143,10 +210,11 @@ OPEN1722_INLINE void Avtp_AlternativeHeader_SetField(Avtp_AlternativeHeader_t *p Avtp_AlternativeHeaderField_t field, uint64_t value) { - const Avtp_FieldDescriptor_t *desc = Avtp_AlternativeHeader_GetVersion(pdu) == AVTP_VERSION_1 - ? Avtp_AhFieldDescV1 - : Avtp_AhFieldDescV0; - Avtp_SetField(desc, AVTPDU_AH_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); + if (Avtp_AlternativeHeader_GetVersion(pdu) == AVTP_VERSION_1) { + Avtp_AlternativeHeader_SetField_V1(pdu, field, value); + } else { + Avtp_AlternativeHeader_SetField_V0(pdu, field, value); + } } /** @@ -189,6 +257,97 @@ OPEN1722_INLINE void Avtp_AlternativeHeader_SetPtpGrandmasterIdentity(Avtp_Alter Avtp_AlternativeHeader_SetField(pdu, AVTPDU_AH_FIELD_PTP_GRANDMASTER_IDENTITY, value); } +/* + * Version-typed named accessors. These select the field layout for one + * explicit version and never read the version field; the version-dispatched + * accessors above delegate to them. See each version-dispatched accessor for + * the full field documentation. + */ + +/** + * Version 0 variant of Avtp_AlternativeHeader_GetSequenceNum(). The field is + * absent from version 0, so this always returns 0. + * @see Avtp_AlternativeHeader_GetSequenceNum + */ +OPEN1722_INLINE uint32_t +Avtp_AlternativeHeader_GetSequenceNum_V0(const Avtp_AlternativeHeader_t *const pdu) +{ + return (uint32_t)Avtp_AlternativeHeader_GetField_V0(pdu, AVTPDU_AH_FIELD_SEQUENCE_NUM); +} + +/** + * Version 1 variant of Avtp_AlternativeHeader_GetSequenceNum(). + * @see Avtp_AlternativeHeader_GetSequenceNum + */ +OPEN1722_INLINE uint32_t +Avtp_AlternativeHeader_GetSequenceNum_V1(const Avtp_AlternativeHeader_t *const pdu) +{ + return (uint32_t)Avtp_AlternativeHeader_GetField_V1(pdu, AVTPDU_AH_FIELD_SEQUENCE_NUM); +} + +/** + * Version 0 variant of Avtp_AlternativeHeader_GetPtpGrandmasterIdentity(). + * The field is absent from version 0, so this always returns 0. + * @see Avtp_AlternativeHeader_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t +Avtp_AlternativeHeader_GetPtpGrandmasterIdentity_V0(const Avtp_AlternativeHeader_t *const pdu) +{ + return Avtp_AlternativeHeader_GetField_V0(pdu, AVTPDU_AH_FIELD_PTP_GRANDMASTER_IDENTITY); +} + +/** + * Version 1 variant of Avtp_AlternativeHeader_GetPtpGrandmasterIdentity(). + * @see Avtp_AlternativeHeader_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t +Avtp_AlternativeHeader_GetPtpGrandmasterIdentity_V1(const Avtp_AlternativeHeader_t *const pdu) +{ + return Avtp_AlternativeHeader_GetField_V1(pdu, AVTPDU_AH_FIELD_PTP_GRANDMASTER_IDENTITY); +} + +/** + * Version 0 variant of Avtp_AlternativeHeader_SetSequenceNum(). The field is + * absent from version 0, so this is a no-op. + * @see Avtp_AlternativeHeader_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_AlternativeHeader_SetSequenceNum_V0(Avtp_AlternativeHeader_t *pdu, + uint32_t value) +{ + Avtp_AlternativeHeader_SetField_V0(pdu, AVTPDU_AH_FIELD_SEQUENCE_NUM, value); +} + +/** + * Version 1 variant of Avtp_AlternativeHeader_SetSequenceNum(). + * @see Avtp_AlternativeHeader_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_AlternativeHeader_SetSequenceNum_V1(Avtp_AlternativeHeader_t *pdu, + uint32_t value) +{ + Avtp_AlternativeHeader_SetField_V1(pdu, AVTPDU_AH_FIELD_SEQUENCE_NUM, value); +} + +/** + * Version 0 variant of Avtp_AlternativeHeader_SetPtpGrandmasterIdentity(). + * The field is absent from version 0, so this is a no-op. + * @see Avtp_AlternativeHeader_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void +Avtp_AlternativeHeader_SetPtpGrandmasterIdentity_V0(Avtp_AlternativeHeader_t *pdu, uint64_t value) +{ + Avtp_AlternativeHeader_SetField_V0(pdu, AVTPDU_AH_FIELD_PTP_GRANDMASTER_IDENTITY, value); +} + +/** + * Version 1 variant of Avtp_AlternativeHeader_SetPtpGrandmasterIdentity(). + * @see Avtp_AlternativeHeader_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void +Avtp_AlternativeHeader_SetPtpGrandmasterIdentity_V1(Avtp_AlternativeHeader_t *pdu, uint64_t value) +{ + Avtp_AlternativeHeader_SetField_V1(pdu, AVTPDU_AH_FIELD_PTP_GRANDMASTER_IDENTITY, value); +} + #ifdef __cplusplus } #endif diff --git a/include/avtp/CommonStreamHeader.h b/include/avtp/CommonStreamHeader.h index 8afd0954..f53e8c36 100644 --- a/include/avtp/CommonStreamHeader.h +++ b/include/avtp/CommonStreamHeader.h @@ -141,17 +141,76 @@ Avtp_CommonStreamHeader_GetVersion(const Avtp_CommonStreamHeader_t *const pdu) } /** - * Returns the length of the common stream header in octets (24 or 40). + * Returns the length of the version 0 common stream header in octets (24). + * The PDU pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetHeaderLen_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTPDU_CSH_LEN_V0; +} + +/** + * Returns the length of the version 1 common stream header in octets (40). + * The PDU pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetHeaderLen_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTPDU_CSH_LEN_V1; +} + +/** + * Returns the length of the common stream header in octets (24 or 40), + * dispatching on the version field of the PDU. */ OPEN1722_INLINE uint8_t Avtp_CommonStreamHeader_GetHeaderLen(const Avtp_CommonStreamHeader_t *const pdu) { - return Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1 ? (uint8_t)AVTPDU_CSH_LEN_V1 - : (uint8_t)AVTPDU_CSH_LEN_V0; + return Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1 + ? Avtp_CommonStreamHeader_GetHeaderLen_V1(pdu) + : Avtp_CommonStreamHeader_GetHeaderLen_V0(pdu); +} + +/** + * Returns the value of an AVTPDU common stream header field as laid out by + * version 0. No version dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AVTP PDU. + * @param field Specifies the position of the data field to be read. + * @returns The value of the specified field. + * @see Avtp_CommonStreamHeader_GetField + */ +OPEN1722_INLINE uint64_t Avtp_CommonStreamHeader_GetField_V0( + const Avtp_CommonStreamHeader_t *const pdu, Avtp_CommonStreamHeaderField_t field) +{ + return Avtp_GetField(Avtp_CshFieldDescV0, AVTPDU_CSH_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTPDU common stream header field as laid out by + * version 1. No version dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AVTP PDU. + * @param field Specifies the position of the data field to be read. + * @returns The value of the specified field. + * @see Avtp_CommonStreamHeader_GetField + */ +OPEN1722_INLINE uint64_t Avtp_CommonStreamHeader_GetField_V1( + const Avtp_CommonStreamHeader_t *const pdu, Avtp_CommonStreamHeaderField_t field) +{ + return Avtp_GetField(Avtp_CshFieldDescV1, AVTPDU_CSH_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); } /** - * Returns the value of an AVTPDU common stream header field. + * Returns the value of an AVTPDU common stream header field, dispatching on + * the version field of the PDU. * * @param pdu Pointer to the first bit of an 1722 AVTP PDU. * @param field Specifies the position of the data field to be read. @@ -160,15 +219,49 @@ Avtp_CommonStreamHeader_GetHeaderLen(const Avtp_CommonStreamHeader_t *const pdu) OPEN1722_INLINE uint64_t Avtp_CommonStreamHeader_GetField( const Avtp_CommonStreamHeader_t *const pdu, Avtp_CommonStreamHeaderField_t field) { - const Avtp_FieldDescriptor_t *desc = Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1 - ? Avtp_CshFieldDescV1 - : Avtp_CshFieldDescV0; - return Avtp_GetField(desc, AVTPDU_CSH_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); + return Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1 + ? Avtp_CommonStreamHeader_GetField_V1(pdu, field) + : Avtp_CommonStreamHeader_GetField_V0(pdu, field); +} + +/** + * Sets the value of an AVTPDU common stream header field as laid out by + * version 0. No version dispatch is performed; fields absent from version 0 + * are left untouched. + * + * @param pdu Pointer to the first bit of an 1722 AVTP PDU. + * @param field Specifies the position of the data field to be written. + * @param value The value to set. + * @see Avtp_CommonStreamHeader_SetField + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetField_V0(Avtp_CommonStreamHeader_t *pdu, + Avtp_CommonStreamHeaderField_t field, + uint64_t value) +{ + Avtp_SetField(Avtp_CshFieldDescV0, AVTPDU_CSH_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Sets the value of an AVTPDU common stream header field as laid out by + * version 1. No version dispatch is performed; fields absent from version 1 + * are left untouched. + * + * @param pdu Pointer to the first bit of an 1722 AVTP PDU. + * @param field Specifies the position of the data field to be written. + * @param value The value to set. + * @see Avtp_CommonStreamHeader_SetField + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetField_V1(Avtp_CommonStreamHeader_t *pdu, + Avtp_CommonStreamHeaderField_t field, + uint64_t value) +{ + Avtp_SetField(Avtp_CshFieldDescV1, AVTPDU_CSH_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); } /** - * Sets the value of an AVTPDU common stream header field. Fields absent from - * the version in use are left untouched. + * Sets the value of an AVTPDU common stream header field, dispatching on the + * version field of the PDU. Fields absent from the version in use are left + * untouched. * * @param pdu Pointer to the first bit of an 1722 AVTP PDU. * @param field Specifies the position of the data field to be written. @@ -178,10 +271,11 @@ OPEN1722_INLINE void Avtp_CommonStreamHeader_SetField(Avtp_CommonStreamHeader_t Avtp_CommonStreamHeaderField_t field, uint64_t value) { - const Avtp_FieldDescriptor_t *desc = Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1 - ? Avtp_CshFieldDescV1 - : Avtp_CshFieldDescV0; - Avtp_SetField(desc, AVTPDU_CSH_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); + if (Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1) { + Avtp_CommonStreamHeader_SetField_V1(pdu, field, value); + } else { + Avtp_CommonStreamHeader_SetField_V0(pdu, field, value); + } } /** @@ -406,6 +500,481 @@ OPEN1722_INLINE void Avtp_CommonStreamHeader_SetStreamDataLength(Avtp_CommonStre Avtp_CommonStreamHeader_SetField(pdu, AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH, value); } +/* + * Version-typed named accessors. These select the field layout for one + * explicit version and never read the version field; the version-dispatched + * accessors above delegate to them. See each version-dispatched accessor for + * the full field documentation. + */ + +/** + * Version 0 variant of Avtp_CommonStreamHeader_IsSv(). + * @see Avtp_CommonStreamHeader_IsSv + */ +OPEN1722_INLINE bool Avtp_CommonStreamHeader_IsSv_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (bool)Avtp_CommonStreamHeader_GetField_V0(pdu, AVTPDU_CSH_FIELD_SV); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_IsSv(). + * @see Avtp_CommonStreamHeader_IsSv + */ +OPEN1722_INLINE bool Avtp_CommonStreamHeader_IsSv_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (bool)Avtp_CommonStreamHeader_GetField_V1(pdu, AVTPDU_CSH_FIELD_SV); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_IsMr(). + * @see Avtp_CommonStreamHeader_IsMr + */ +OPEN1722_INLINE bool Avtp_CommonStreamHeader_IsMr_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (bool)Avtp_CommonStreamHeader_GetField_V0(pdu, AVTPDU_CSH_FIELD_MR); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_IsMr(). + * @see Avtp_CommonStreamHeader_IsMr + */ +OPEN1722_INLINE bool Avtp_CommonStreamHeader_IsMr_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (bool)Avtp_CommonStreamHeader_GetField_V1(pdu, AVTPDU_CSH_FIELD_MR); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_IsTv(). + * @see Avtp_CommonStreamHeader_IsTv + */ +OPEN1722_INLINE bool Avtp_CommonStreamHeader_IsTv_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (bool)Avtp_CommonStreamHeader_GetField_V0(pdu, AVTPDU_CSH_FIELD_TV); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_IsTv(). + * @see Avtp_CommonStreamHeader_IsTv + */ +OPEN1722_INLINE bool Avtp_CommonStreamHeader_IsTv_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (bool)Avtp_CommonStreamHeader_GetField_V1(pdu, AVTPDU_CSH_FIELD_TV); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_IsTu(). + * @see Avtp_CommonStreamHeader_IsTu + */ +OPEN1722_INLINE bool Avtp_CommonStreamHeader_IsTu_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (bool)Avtp_CommonStreamHeader_GetField_V0(pdu, AVTPDU_CSH_FIELD_TU); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_IsTu(). + * @see Avtp_CommonStreamHeader_IsTu + */ +OPEN1722_INLINE bool Avtp_CommonStreamHeader_IsTu_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (bool)Avtp_CommonStreamHeader_GetField_V1(pdu, AVTPDU_CSH_FIELD_TU); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_GetFsd(). + * @see Avtp_CommonStreamHeader_GetFsd + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetFsd_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint8_t)Avtp_CommonStreamHeader_GetField_V0(pdu, AVTPDU_CSH_FIELD_FSD); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_GetFsd(). + * @see Avtp_CommonStreamHeader_GetFsd + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetFsd_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint8_t)Avtp_CommonStreamHeader_GetField_V1(pdu, AVTPDU_CSH_FIELD_FSD); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_GetFormatSpecificData0(). The + * field is absent from version 0, so this always returns 0. + * @see Avtp_CommonStreamHeader_GetFormatSpecificData0 + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetFormatSpecificData0_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint8_t)Avtp_CommonStreamHeader_GetField_V0(pdu, AVTPDU_CSH_FIELD_FSD0); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_GetFormatSpecificData0(). + * @see Avtp_CommonStreamHeader_GetFormatSpecificData0 + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetFormatSpecificData0_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint8_t)Avtp_CommonStreamHeader_GetField_V1(pdu, AVTPDU_CSH_FIELD_FSD0); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_GetFormatSpecificData1(). + * @see Avtp_CommonStreamHeader_GetFormatSpecificData1 + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetFormatSpecificData1_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint8_t)Avtp_CommonStreamHeader_GetField_V0(pdu, AVTPDU_CSH_FIELD_FSD1); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_GetFormatSpecificData1(). + * @see Avtp_CommonStreamHeader_GetFormatSpecificData1 + */ +OPEN1722_INLINE uint8_t +Avtp_CommonStreamHeader_GetFormatSpecificData1_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint8_t)Avtp_CommonStreamHeader_GetField_V1(pdu, AVTPDU_CSH_FIELD_FSD1); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_GetSequenceNum(). + * @see Avtp_CommonStreamHeader_GetSequenceNum + */ +OPEN1722_INLINE uint32_t +Avtp_CommonStreamHeader_GetSequenceNum_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint32_t)Avtp_CommonStreamHeader_GetField_V0(pdu, AVTPDU_CSH_FIELD_SEQUENCE_NUM); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_GetSequenceNum(). + * @see Avtp_CommonStreamHeader_GetSequenceNum + */ +OPEN1722_INLINE uint32_t +Avtp_CommonStreamHeader_GetSequenceNum_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint32_t)Avtp_CommonStreamHeader_GetField_V1(pdu, AVTPDU_CSH_FIELD_SEQUENCE_NUM); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_GetStreamId(). + * @see Avtp_CommonStreamHeader_GetStreamId + */ +OPEN1722_INLINE uint64_t +Avtp_CommonStreamHeader_GetStreamId_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetField_V0(pdu, AVTPDU_CSH_FIELD_STREAM_ID); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_GetStreamId(). + * @see Avtp_CommonStreamHeader_GetStreamId + */ +OPEN1722_INLINE uint64_t +Avtp_CommonStreamHeader_GetStreamId_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetField_V1(pdu, AVTPDU_CSH_FIELD_STREAM_ID); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_GetAvtpTimestamp(). + * @see Avtp_CommonStreamHeader_GetAvtpTimestamp + */ +OPEN1722_INLINE uint64_t +Avtp_CommonStreamHeader_GetAvtpTimestamp_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetField_V0(pdu, AVTPDU_CSH_FIELD_AVTP_TIMESTAMP); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_GetAvtpTimestamp(). + * @see Avtp_CommonStreamHeader_GetAvtpTimestamp + */ +OPEN1722_INLINE uint64_t +Avtp_CommonStreamHeader_GetAvtpTimestamp_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetField_V1(pdu, AVTPDU_CSH_FIELD_AVTP_TIMESTAMP); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity(). + * The field is absent from version 0, so this always returns 0. + * @see Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t +Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetField_V0(pdu, AVTPDU_CSH_FIELD_PTP_GRANDMASTER_IDENTITY); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity(). + * @see Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t +Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetField_V1(pdu, AVTPDU_CSH_FIELD_PTP_GRANDMASTER_IDENTITY); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_GetStreamDataLength(). + * @see Avtp_CommonStreamHeader_GetStreamDataLength + */ +OPEN1722_INLINE uint16_t +Avtp_CommonStreamHeader_GetStreamDataLength_V0(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint16_t)Avtp_CommonStreamHeader_GetField_V0(pdu, AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_GetStreamDataLength(). + * @see Avtp_CommonStreamHeader_GetStreamDataLength + */ +OPEN1722_INLINE uint16_t +Avtp_CommonStreamHeader_GetStreamDataLength_V1(const Avtp_CommonStreamHeader_t *const pdu) +{ + return (uint16_t)Avtp_CommonStreamHeader_GetField_V1(pdu, AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_SetSv(). + * @see Avtp_CommonStreamHeader_SetSv + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetSv_V0(Avtp_CommonStreamHeader_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetField_V0(pdu, AVTPDU_CSH_FIELD_SV, sv); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_SetSv(). + * @see Avtp_CommonStreamHeader_SetSv + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetSv_V1(Avtp_CommonStreamHeader_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetField_V1(pdu, AVTPDU_CSH_FIELD_SV, sv); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_SetMr(). + * @see Avtp_CommonStreamHeader_SetMr + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetMr_V0(Avtp_CommonStreamHeader_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetField_V0(pdu, AVTPDU_CSH_FIELD_MR, mr); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_SetMr(). + * @see Avtp_CommonStreamHeader_SetMr + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetMr_V1(Avtp_CommonStreamHeader_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetField_V1(pdu, AVTPDU_CSH_FIELD_MR, mr); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_SetTv(). + * @see Avtp_CommonStreamHeader_SetTv + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetTv_V0(Avtp_CommonStreamHeader_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetField_V0(pdu, AVTPDU_CSH_FIELD_TV, tv); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_SetTv(). + * @see Avtp_CommonStreamHeader_SetTv + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetTv_V1(Avtp_CommonStreamHeader_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetField_V1(pdu, AVTPDU_CSH_FIELD_TV, tv); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_SetTu(). + * @see Avtp_CommonStreamHeader_SetTu + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetTu_V0(Avtp_CommonStreamHeader_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetField_V0(pdu, AVTPDU_CSH_FIELD_TU, tu); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_SetTu(). + * @see Avtp_CommonStreamHeader_SetTu + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetTu_V1(Avtp_CommonStreamHeader_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetField_V1(pdu, AVTPDU_CSH_FIELD_TU, tu); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_SetFsd(). + * @see Avtp_CommonStreamHeader_SetFsd + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetFsd_V0(Avtp_CommonStreamHeader_t *pdu, uint8_t fsd) +{ + Avtp_CommonStreamHeader_SetField_V0(pdu, AVTPDU_CSH_FIELD_FSD, fsd); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_SetFsd(). + * @see Avtp_CommonStreamHeader_SetFsd + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetFsd_V1(Avtp_CommonStreamHeader_t *pdu, uint8_t fsd) +{ + Avtp_CommonStreamHeader_SetField_V1(pdu, AVTPDU_CSH_FIELD_FSD, fsd); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_SetFormatSpecificData0(). + * The field is absent from version 0, so this is a no-op. + * @see Avtp_CommonStreamHeader_SetFormatSpecificData0 + */ +OPEN1722_INLINE void +Avtp_CommonStreamHeader_SetFormatSpecificData0_V0(Avtp_CommonStreamHeader_t *pdu, uint8_t value) +{ + Avtp_CommonStreamHeader_SetField_V0(pdu, AVTPDU_CSH_FIELD_FSD0, value); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_SetFormatSpecificData0(). + * @see Avtp_CommonStreamHeader_SetFormatSpecificData0 + */ +OPEN1722_INLINE void +Avtp_CommonStreamHeader_SetFormatSpecificData0_V1(Avtp_CommonStreamHeader_t *pdu, uint8_t value) +{ + Avtp_CommonStreamHeader_SetField_V1(pdu, AVTPDU_CSH_FIELD_FSD0, value); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_SetFormatSpecificData1(). + * @see Avtp_CommonStreamHeader_SetFormatSpecificData1 + */ +OPEN1722_INLINE void +Avtp_CommonStreamHeader_SetFormatSpecificData1_V0(Avtp_CommonStreamHeader_t *pdu, uint8_t value) +{ + Avtp_CommonStreamHeader_SetField_V0(pdu, AVTPDU_CSH_FIELD_FSD1, value); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_SetFormatSpecificData1(). + * @see Avtp_CommonStreamHeader_SetFormatSpecificData1 + */ +OPEN1722_INLINE void +Avtp_CommonStreamHeader_SetFormatSpecificData1_V1(Avtp_CommonStreamHeader_t *pdu, uint8_t value) +{ + Avtp_CommonStreamHeader_SetField_V1(pdu, AVTPDU_CSH_FIELD_FSD1, value); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_SetSequenceNum(). Values are + * truncated to the 8-bit version 0 field width. + * @see Avtp_CommonStreamHeader_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetSequenceNum_V0(Avtp_CommonStreamHeader_t *pdu, + uint32_t value) +{ + Avtp_CommonStreamHeader_SetField_V0(pdu, AVTPDU_CSH_FIELD_SEQUENCE_NUM, value); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_SetSequenceNum(). + * @see Avtp_CommonStreamHeader_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetSequenceNum_V1(Avtp_CommonStreamHeader_t *pdu, + uint32_t value) +{ + Avtp_CommonStreamHeader_SetField_V1(pdu, AVTPDU_CSH_FIELD_SEQUENCE_NUM, value); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_SetStreamId(). + * @see Avtp_CommonStreamHeader_SetStreamId + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetStreamId_V0(Avtp_CommonStreamHeader_t *pdu, + uint64_t value) +{ + Avtp_CommonStreamHeader_SetField_V0(pdu, AVTPDU_CSH_FIELD_STREAM_ID, value); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_SetStreamId(). + * @see Avtp_CommonStreamHeader_SetStreamId + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetStreamId_V1(Avtp_CommonStreamHeader_t *pdu, + uint64_t value) +{ + Avtp_CommonStreamHeader_SetField_V1(pdu, AVTPDU_CSH_FIELD_STREAM_ID, value); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_SetAvtpTimestamp(). Values are + * truncated to the 32-bit version 0 field width. + * @see Avtp_CommonStreamHeader_SetAvtpTimestamp + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetAvtpTimestamp_V0(Avtp_CommonStreamHeader_t *pdu, + uint64_t value) +{ + Avtp_CommonStreamHeader_SetField_V0(pdu, AVTPDU_CSH_FIELD_AVTP_TIMESTAMP, value); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_SetAvtpTimestamp(). + * @see Avtp_CommonStreamHeader_SetAvtpTimestamp + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetAvtpTimestamp_V1(Avtp_CommonStreamHeader_t *pdu, + uint64_t value) +{ + Avtp_CommonStreamHeader_SetField_V1(pdu, AVTPDU_CSH_FIELD_AVTP_TIMESTAMP, value); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity(). + * The field is absent from version 0, so this is a no-op. + * @see Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void +Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V0(Avtp_CommonStreamHeader_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetField_V0(pdu, AVTPDU_CSH_FIELD_PTP_GRANDMASTER_IDENTITY, value); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity(). + * @see Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void +Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V1(Avtp_CommonStreamHeader_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetField_V1(pdu, AVTPDU_CSH_FIELD_PTP_GRANDMASTER_IDENTITY, value); +} + +/** + * Version 0 variant of Avtp_CommonStreamHeader_SetStreamDataLength(). + * @see Avtp_CommonStreamHeader_SetStreamDataLength + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetStreamDataLength_V0(Avtp_CommonStreamHeader_t *pdu, + uint16_t value) +{ + Avtp_CommonStreamHeader_SetField_V0(pdu, AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH, value); +} + +/** + * Version 1 variant of Avtp_CommonStreamHeader_SetStreamDataLength(). + * @see Avtp_CommonStreamHeader_SetStreamDataLength + */ +OPEN1722_INLINE void Avtp_CommonStreamHeader_SetStreamDataLength_V1(Avtp_CommonStreamHeader_t *pdu, + uint16_t value) +{ + Avtp_CommonStreamHeader_SetField_V1(pdu, AVTPDU_CSH_FIELD_STREAM_DATA_LENGTH, value); +} + #ifdef __cplusplus } #endif diff --git a/include/avtp/Crf.h b/include/avtp/Crf.h index 3ba0f513..ba984ea0 100644 --- a/include/avtp/Crf.h +++ b/include/avtp/Crf.h @@ -177,7 +177,38 @@ static const Avtp_FieldDescriptor_t Avtp_CrfFieldDescV1[AVTP_CRF_FIELD_MAX] = { }; /** - * Returns the value of an AVTP CRF field as specified in the IEEE 1722 Specification. + * Returns the value of an AVTP CRF field as laid out by version 0. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Crf_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Crf_GetField_V0(const Avtp_Crf_t *const pdu, Avtp_CrfFields_t field) +{ + return Avtp_GetField(Avtp_CrfFieldDescV0, AVTP_CRF_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP CRF field as laid out by version 1. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Crf_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Crf_GetField_V1(const Avtp_CrfV1_t *const pdu, Avtp_CrfFields_t field) +{ + return Avtp_GetField(Avtp_CrfFieldDescV1, AVTP_CRF_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP CRF field, dispatching on the version field of + * the PDU. * * @param pdu Pointer to the first bit of an 1722 CRF PDU. * @param field Specifies the position of the data field to be read @@ -185,15 +216,43 @@ static const Avtp_FieldDescriptor_t Avtp_CrfFieldDescV1[AVTP_CRF_FIELD_MAX] = { */ OPEN1722_INLINE uint64_t Avtp_Crf_GetField(const Avtp_Crf_t *const pdu, Avtp_CrfFields_t field) { - const Avtp_FieldDescriptor_t *desc = - Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_CrfFieldDescV1 - : Avtp_CrfFieldDescV0; - return Avtp_GetField(desc, AVTP_CRF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); + return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Crf_GetField_V1((const Avtp_CrfV1_t *)pdu, field) + : Avtp_Crf_GetField_V0(pdu, field); +} + +/** + * Sets the value of an AVTP CRF field as laid out by version 0. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Crf_SetField + */ +OPEN1722_INLINE void Avtp_Crf_SetField_V0(Avtp_Crf_t *pdu, Avtp_CrfFields_t field, uint64_t value) +{ + Avtp_SetField(Avtp_CrfFieldDescV0, AVTP_CRF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Sets the value of an AVTP CRF field as laid out by version 1. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Crf_SetField + */ +OPEN1722_INLINE void Avtp_Crf_SetField_V1(Avtp_CrfV1_t *pdu, Avtp_CrfFields_t field, uint64_t value) +{ + Avtp_SetField(Avtp_CrfFieldDescV1, AVTP_CRF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); } /** - * Sets the value of an AVTP CRF field as specified in the IEEE 1722 Specification. + * Sets the value of an AVTP CRF field, dispatching on the version field of the + * PDU. * * @param pdu Pointer to the first bit of an 1722 CRF PDU. * @param field Specifies the position of the data field to be written @@ -201,22 +260,46 @@ OPEN1722_INLINE uint64_t Avtp_Crf_GetField(const Avtp_Crf_t *const pdu, Avtp_Crf */ OPEN1722_INLINE void Avtp_Crf_SetField(Avtp_Crf_t *pdu, Avtp_CrfFields_t field, uint64_t value) { - const Avtp_FieldDescriptor_t *desc = - Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_CrfFieldDescV1 - : Avtp_CrfFieldDescV0; - Avtp_SetField(desc, AVTP_CRF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); + if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Crf_SetField_V1((Avtp_CrfV1_t *)pdu, field, value); + } else { + Avtp_Crf_SetField_V0(pdu, field, value); + } +} + +/** + * Returns the length of the version 0 CRF header in octets (20). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Crf_GetHeaderLen_V0(const Avtp_Crf_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_CRF_HEADER_LEN_V0; } /** - * Returns the length of the CRF header in octets (20 or 36). + * Returns the length of the version 1 CRF header in octets (36). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Crf_GetHeaderLen_V1(const Avtp_CrfV1_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_CRF_HEADER_LEN_V1; +} + +/** + * Returns the length of the CRF header in octets (20 or 36), dispatching on the + * version field of the PDU. */ OPEN1722_INLINE uint8_t Avtp_Crf_GetHeaderLen(const Avtp_Crf_t *const pdu) { return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == AVTP_VERSION_1 - ? (uint8_t)AVTP_CRF_HEADER_LEN_V1 - : (uint8_t)AVTP_CRF_HEADER_LEN_V0; + ? Avtp_Crf_GetHeaderLen_V1((const Avtp_CrfV1_t *)pdu) + : Avtp_Crf_GetHeaderLen_V0(pdu); } /** @@ -273,11 +356,11 @@ OPEN1722_INLINE bool Avtp_Crf_IsTu(const Avtp_Crf_t *const pdu) */ OPEN1722_INLINE uint32_t Avtp_Crf_GetSequenceNum(const Avtp_Crf_t *const pdu) { - if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1) { - return (uint32_t)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM); - } - return (uint8_t)Avtp_Crf_GetField(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB); + return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1 + ? (uint32_t)Avtp_Crf_GetField_V1((const Avtp_CrfV1_t *)pdu, + AVTP_CRF_FIELD_SEQUENCE_NUM) + : (uint8_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB); } /** @@ -426,9 +509,14 @@ OPEN1722_INLINE void Avtp_Crf_SetTu(Avtp_Crf_t *pdu, bool tu) */ OPEN1722_INLINE void Avtp_Crf_SetSequenceNum(Avtp_Crf_t *pdu, uint32_t value) { - /* No-op on version 0: the field only exists in the alternative header v1. */ - Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM, value); - Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); + if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Crf_SetField_V1((Avtp_CrfV1_t *)pdu, AVTP_CRF_FIELD_SEQUENCE_NUM, value); + Avtp_Crf_SetField_V1((Avtp_CrfV1_t *)pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB, + (uint8_t)(value & 0xFFU)); + } else { + Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); + } } /** @@ -509,6 +597,30 @@ OPEN1722_INLINE void Avtp_Crf_SetTimestampInterval(Avtp_Crf_t *pdu, uint16_t val Avtp_Crf_SetField(pdu, AVTP_CRF_FIELD_TIMESTAMP_INTERVAL, value); } +/** + * Returns a pointer to the CRF data of a version 0 CRF frame. + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @return Pointer to CRF data + * @see Avtp_Crf_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Crf_GetPayload_V0(const Avtp_Crf_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_CRF_HEADER_LEN_V0; +} + +/** + * Returns a pointer to the CRF data of a version 1 CRF frame. + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @return Pointer to CRF data + * @see Avtp_Crf_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Crf_GetPayload_V1(const Avtp_CrfV1_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_CRF_HEADER_LEN_V1; +} + /** * Returns pointer to the CRF data of a CRF frame. The CRF data starts after the * version-dependent CRF header. @@ -521,7 +633,38 @@ OPEN1722_INLINE void Avtp_Crf_SetTimestampInterval(Avtp_Crf_t *pdu, uint16_t val */ OPEN1722_INLINE const uint8_t *Avtp_Crf_GetPayload(const Avtp_Crf_t *const pdu) { - return (const uint8_t *)pdu + Avtp_Crf_GetHeaderLen(pdu); + return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Crf_GetPayload_V1((const Avtp_CrfV1_t *)pdu) + : Avtp_Crf_GetPayload_V0(pdu); +} + +/** + * Sets the CRF data of a version 0 CRF frame. + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @param payload Pointer to the payload byte array + * @param payload_length Length of the payload + * @see Avtp_Crf_SetPayload + */ +OPEN1722_INLINE void Avtp_Crf_SetPayload_V0(Avtp_Crf_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_CRF_HEADER_LEN_V0, payload, payload_length); +} + +/** + * Sets the CRF data of a version 1 CRF frame. + * + * @param pdu Pointer to the first bit of an 1722 CRF PDU. + * @param payload Pointer to the payload byte array + * @param payload_length Length of the payload + * @see Avtp_Crf_SetPayload + */ +OPEN1722_INLINE void Avtp_Crf_SetPayload_V1(Avtp_CrfV1_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_CRF_HEADER_LEN_V1, payload, payload_length); } /** @@ -533,7 +676,12 @@ OPEN1722_INLINE const uint8_t *Avtp_Crf_GetPayload(const Avtp_Crf_t *const pdu) */ OPEN1722_INLINE void Avtp_Crf_SetPayload(Avtp_Crf_t *pdu, uint8_t *payload, uint16_t payload_length) { - memcpy((uint8_t *)pdu + Avtp_Crf_GetHeaderLen(pdu), payload, payload_length); + if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Crf_SetPayload_V1((Avtp_CrfV1_t *)pdu, payload, payload_length); + } else { + Avtp_Crf_SetPayload_V0(pdu, payload, payload_length); + } } /** @@ -615,6 +763,472 @@ OPEN1722_INLINE bool Avtp_Crf_IsValid(const Avtp_Crf_t *const pdu, size_t buffer return true; } +/* + * Version-typed named accessors. These select the field layout for one + * explicit version and never read the version field; the version-dispatched + * accessors above delegate to them. Alternative header fields delegate to the + * shared Avtp_AlternativeHeader_* variants. See each version-dispatched + * accessor for the full field documentation. + */ + +/** + * Version 0 variant of Avtp_Crf_IsSv(). + * @see Avtp_Crf_IsSv + */ +OPEN1722_INLINE bool Avtp_Crf_IsSv_V0(const Avtp_Crf_t *const pdu) +{ + return (bool)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_SV); +} + +/** + * Version 1 variant of Avtp_Crf_IsSv(). + * @see Avtp_Crf_IsSv + */ +OPEN1722_INLINE bool Avtp_Crf_IsSv_V1(const Avtp_CrfV1_t *const pdu) +{ + return (bool)Avtp_Crf_GetField_V1(pdu, AVTP_CRF_FIELD_SV); +} + +/** + * Version 0 variant of Avtp_Crf_IsMr(). + * @see Avtp_Crf_IsMr + */ +OPEN1722_INLINE bool Avtp_Crf_IsMr_V0(const Avtp_Crf_t *const pdu) +{ + return (bool)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_MR); +} + +/** + * Version 1 variant of Avtp_Crf_IsMr(). + * @see Avtp_Crf_IsMr + */ +OPEN1722_INLINE bool Avtp_Crf_IsMr_V1(const Avtp_CrfV1_t *const pdu) +{ + return (bool)Avtp_Crf_GetField_V1(pdu, AVTP_CRF_FIELD_MR); +} + +/** + * Version 0 variant of Avtp_Crf_IsFs(). + * @see Avtp_Crf_IsFs + */ +OPEN1722_INLINE bool Avtp_Crf_IsFs_V0(const Avtp_Crf_t *const pdu) +{ + return (bool)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_FS); +} + +/** + * Version 1 variant of Avtp_Crf_IsFs(). + * @see Avtp_Crf_IsFs + */ +OPEN1722_INLINE bool Avtp_Crf_IsFs_V1(const Avtp_CrfV1_t *const pdu) +{ + return (bool)Avtp_Crf_GetField_V1(pdu, AVTP_CRF_FIELD_FS); +} + +/** + * Version 0 variant of Avtp_Crf_IsTu(). + * @see Avtp_Crf_IsTu + */ +OPEN1722_INLINE bool Avtp_Crf_IsTu_V0(const Avtp_Crf_t *const pdu) +{ + return (bool)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_TU); +} + +/** + * Version 1 variant of Avtp_Crf_IsTu(). + * @see Avtp_Crf_IsTu + */ +OPEN1722_INLINE bool Avtp_Crf_IsTu_V1(const Avtp_CrfV1_t *const pdu) +{ + return (bool)Avtp_Crf_GetField_V1(pdu, AVTP_CRF_FIELD_TU); +} + +/** + * Version 0 variant of Avtp_Crf_GetSequenceNum(). In version 0 the sequence + * number is the 8-bit sequence_num_lsb field. + * @see Avtp_Crf_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Crf_GetSequenceNum_V0(const Avtp_Crf_t *const pdu) +{ + return (uint32_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB); +} + +/** + * Version 1 variant of Avtp_Crf_GetSequenceNum(). + * @see Avtp_Crf_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Crf_GetSequenceNum_V1(const Avtp_CrfV1_t *const pdu) +{ + return (uint32_t)Avtp_Crf_GetField_V1(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM); +} + +/** + * Version 0 variant of Avtp_Crf_GetSequenceNumLsb(). + * @see Avtp_Crf_GetSequenceNumLsb + */ +OPEN1722_INLINE uint8_t Avtp_Crf_GetSequenceNumLsb_V0(const Avtp_Crf_t *const pdu) +{ + return (uint8_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB); +} + +/** + * Version 1 variant of Avtp_Crf_GetSequenceNumLsb(). + * @see Avtp_Crf_GetSequenceNumLsb + */ +OPEN1722_INLINE uint8_t Avtp_Crf_GetSequenceNumLsb_V1(const Avtp_CrfV1_t *const pdu) +{ + return (uint8_t)Avtp_Crf_GetField_V1(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB); +} + +/** + * Version 0 variant of Avtp_Crf_GetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this always returns 0. + * @see Avtp_Crf_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Crf_GetPtpGrandmasterIdentity_V0(const Avtp_Crf_t *const pdu) +{ + return Avtp_AlternativeHeader_GetPtpGrandmasterIdentity_V0( + (const Avtp_AlternativeHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Crf_GetPtpGrandmasterIdentity(). + * @see Avtp_Crf_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Crf_GetPtpGrandmasterIdentity_V1(const Avtp_CrfV1_t *const pdu) +{ + return Avtp_AlternativeHeader_GetPtpGrandmasterIdentity_V1( + (const Avtp_AlternativeHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Crf_GetType(). + * @see Avtp_Crf_GetType + */ +OPEN1722_INLINE Avtp_CrfType_t Avtp_Crf_GetType_V0(const Avtp_Crf_t *const pdu) +{ + return (Avtp_CrfType_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_TYPE); +} + +/** + * Version 1 variant of Avtp_Crf_GetType(). + * @see Avtp_Crf_GetType + */ +OPEN1722_INLINE Avtp_CrfType_t Avtp_Crf_GetType_V1(const Avtp_CrfV1_t *const pdu) +{ + return (Avtp_CrfType_t)Avtp_Crf_GetField_V1(pdu, AVTP_CRF_FIELD_TYPE); +} + +/** + * Version 0 variant of Avtp_Crf_GetStreamId(). + * @see Avtp_Crf_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Crf_GetStreamId_V0(const Avtp_Crf_t *const pdu) +{ + return Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_STREAM_ID); +} + +/** + * Version 1 variant of Avtp_Crf_GetStreamId(). + * @see Avtp_Crf_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Crf_GetStreamId_V1(const Avtp_CrfV1_t *const pdu) +{ + return Avtp_Crf_GetField_V1(pdu, AVTP_CRF_FIELD_STREAM_ID); +} + +/** + * Version 0 variant of Avtp_Crf_GetPull(). + * @see Avtp_Crf_GetPull + */ +OPEN1722_INLINE Avtp_CrfPull_t Avtp_Crf_GetPull_V0(const Avtp_Crf_t *const pdu) +{ + return (Avtp_CrfPull_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_PULL); +} + +/** + * Version 1 variant of Avtp_Crf_GetPull(). + * @see Avtp_Crf_GetPull + */ +OPEN1722_INLINE Avtp_CrfPull_t Avtp_Crf_GetPull_V1(const Avtp_CrfV1_t *const pdu) +{ + return (Avtp_CrfPull_t)Avtp_Crf_GetField_V1(pdu, AVTP_CRF_FIELD_PULL); +} + +/** + * Version 0 variant of Avtp_Crf_GetBaseFrequency(). + * @see Avtp_Crf_GetBaseFrequency + */ +OPEN1722_INLINE uint32_t Avtp_Crf_GetBaseFrequency_V0(const Avtp_Crf_t *const pdu) +{ + return (uint32_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_BASE_FREQUENCY); +} + +/** + * Version 1 variant of Avtp_Crf_GetBaseFrequency(). + * @see Avtp_Crf_GetBaseFrequency + */ +OPEN1722_INLINE uint32_t Avtp_Crf_GetBaseFrequency_V1(const Avtp_CrfV1_t *const pdu) +{ + return (uint32_t)Avtp_Crf_GetField_V1(pdu, AVTP_CRF_FIELD_BASE_FREQUENCY); +} + +/** + * Version 0 variant of Avtp_Crf_GetCrfDataLength(). + * @see Avtp_Crf_GetCrfDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Crf_GetCrfDataLength_V0(const Avtp_Crf_t *const pdu) +{ + return (uint16_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_CRF_DATA_LENGTH); +} + +/** + * Version 1 variant of Avtp_Crf_GetCrfDataLength(). + * @see Avtp_Crf_GetCrfDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Crf_GetCrfDataLength_V1(const Avtp_CrfV1_t *const pdu) +{ + return (uint16_t)Avtp_Crf_GetField_V1(pdu, AVTP_CRF_FIELD_CRF_DATA_LENGTH); +} + +/** + * Version 0 variant of Avtp_Crf_GetTimestampInterval(). + * @see Avtp_Crf_GetTimestampInterval + */ +OPEN1722_INLINE uint16_t Avtp_Crf_GetTimestampInterval_V0(const Avtp_Crf_t *const pdu) +{ + return (uint16_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_TIMESTAMP_INTERVAL); +} + +/** + * Version 1 variant of Avtp_Crf_GetTimestampInterval(). + * @see Avtp_Crf_GetTimestampInterval + */ +OPEN1722_INLINE uint16_t Avtp_Crf_GetTimestampInterval_V1(const Avtp_CrfV1_t *const pdu) +{ + return (uint16_t)Avtp_Crf_GetField_V1(pdu, AVTP_CRF_FIELD_TIMESTAMP_INTERVAL); +} + +/** + * Version 0 variant of Avtp_Crf_SetSv(). + * @see Avtp_Crf_SetSv + */ +OPEN1722_INLINE void Avtp_Crf_SetSv_V0(Avtp_Crf_t *pdu, bool sv) +{ + Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_SV, sv); +} + +/** + * Version 1 variant of Avtp_Crf_SetSv(). + * @see Avtp_Crf_SetSv + */ +OPEN1722_INLINE void Avtp_Crf_SetSv_V1(Avtp_CrfV1_t *pdu, bool sv) +{ + Avtp_Crf_SetField_V1(pdu, AVTP_CRF_FIELD_SV, sv); +} + +/** + * Version 0 variant of Avtp_Crf_SetMr(). + * @see Avtp_Crf_SetMr + */ +OPEN1722_INLINE void Avtp_Crf_SetMr_V0(Avtp_Crf_t *pdu, bool mr) +{ + Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_MR, mr); +} + +/** + * Version 1 variant of Avtp_Crf_SetMr(). + * @see Avtp_Crf_SetMr + */ +OPEN1722_INLINE void Avtp_Crf_SetMr_V1(Avtp_CrfV1_t *pdu, bool mr) +{ + Avtp_Crf_SetField_V1(pdu, AVTP_CRF_FIELD_MR, mr); +} + +/** + * Version 0 variant of Avtp_Crf_SetFs(). + * @see Avtp_Crf_SetFs + */ +OPEN1722_INLINE void Avtp_Crf_SetFs_V0(Avtp_Crf_t *pdu, bool fs) +{ + Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_FS, fs); +} + +/** + * Version 1 variant of Avtp_Crf_SetFs(). + * @see Avtp_Crf_SetFs + */ +OPEN1722_INLINE void Avtp_Crf_SetFs_V1(Avtp_CrfV1_t *pdu, bool fs) +{ + Avtp_Crf_SetField_V1(pdu, AVTP_CRF_FIELD_FS, fs); +} + +/** + * Version 0 variant of Avtp_Crf_SetTu(). + * @see Avtp_Crf_SetTu + */ +OPEN1722_INLINE void Avtp_Crf_SetTu_V0(Avtp_Crf_t *pdu, bool tu) +{ + Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_TU, tu); +} + +/** + * Version 1 variant of Avtp_Crf_SetTu(). + * @see Avtp_Crf_SetTu + */ +OPEN1722_INLINE void Avtp_Crf_SetTu_V1(Avtp_CrfV1_t *pdu, bool tu) +{ + Avtp_Crf_SetField_V1(pdu, AVTP_CRF_FIELD_TU, tu); +} + +/** + * Version 0 variant of Avtp_Crf_SetSequenceNum(). The value is truncated to the + * 8-bit version 0 sequence_num_lsb field. + * @see Avtp_Crf_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Crf_SetSequenceNum_V0(Avtp_Crf_t *pdu, uint32_t value) +{ + Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); +} + +/** + * Version 1 variant of Avtp_Crf_SetSequenceNum(). The eight least significant + * bits are also written to the sequence_num_lsb copy (CRF-25). + * @see Avtp_Crf_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Crf_SetSequenceNum_V1(Avtp_CrfV1_t *pdu, uint32_t value) +{ + Avtp_Crf_SetField_V1(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM, value); + Avtp_Crf_SetField_V1(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); +} + +/** + * Version 0 variant of Avtp_Crf_SetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this is a no-op. + * @see Avtp_Crf_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Crf_SetPtpGrandmasterIdentity_V0(Avtp_Crf_t *pdu, uint64_t value) +{ + Avtp_AlternativeHeader_SetPtpGrandmasterIdentity_V0((Avtp_AlternativeHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Crf_SetPtpGrandmasterIdentity(). + * @see Avtp_Crf_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Crf_SetPtpGrandmasterIdentity_V1(Avtp_CrfV1_t *pdu, uint64_t value) +{ + Avtp_AlternativeHeader_SetPtpGrandmasterIdentity_V1((Avtp_AlternativeHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Crf_SetType(). + * @see Avtp_Crf_SetType + */ +OPEN1722_INLINE void Avtp_Crf_SetType_V0(Avtp_Crf_t *pdu, Avtp_CrfType_t value) +{ + Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_TYPE, (uint64_t)value); +} + +/** + * Version 1 variant of Avtp_Crf_SetType(). + * @see Avtp_Crf_SetType + */ +OPEN1722_INLINE void Avtp_Crf_SetType_V1(Avtp_CrfV1_t *pdu, Avtp_CrfType_t value) +{ + Avtp_Crf_SetField_V1(pdu, AVTP_CRF_FIELD_TYPE, (uint64_t)value); +} + +/** + * Version 0 variant of Avtp_Crf_SetStreamId(). + * @see Avtp_Crf_SetStreamId + */ +OPEN1722_INLINE void Avtp_Crf_SetStreamId_V0(Avtp_Crf_t *pdu, uint64_t value) +{ + Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_STREAM_ID, value); +} + +/** + * Version 1 variant of Avtp_Crf_SetStreamId(). + * @see Avtp_Crf_SetStreamId + */ +OPEN1722_INLINE void Avtp_Crf_SetStreamId_V1(Avtp_CrfV1_t *pdu, uint64_t value) +{ + Avtp_Crf_SetField_V1(pdu, AVTP_CRF_FIELD_STREAM_ID, value); +} + +/** + * Version 0 variant of Avtp_Crf_SetPull(). + * @see Avtp_Crf_SetPull + */ +OPEN1722_INLINE void Avtp_Crf_SetPull_V0(Avtp_Crf_t *pdu, Avtp_CrfPull_t value) +{ + Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_PULL, (uint64_t)value); +} + +/** + * Version 1 variant of Avtp_Crf_SetPull(). + * @see Avtp_Crf_SetPull + */ +OPEN1722_INLINE void Avtp_Crf_SetPull_V1(Avtp_CrfV1_t *pdu, Avtp_CrfPull_t value) +{ + Avtp_Crf_SetField_V1(pdu, AVTP_CRF_FIELD_PULL, (uint64_t)value); +} + +/** + * Version 0 variant of Avtp_Crf_SetBaseFrequency(). + * @see Avtp_Crf_SetBaseFrequency + */ +OPEN1722_INLINE void Avtp_Crf_SetBaseFrequency_V0(Avtp_Crf_t *pdu, uint32_t value) +{ + Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_BASE_FREQUENCY, value); +} + +/** + * Version 1 variant of Avtp_Crf_SetBaseFrequency(). + * @see Avtp_Crf_SetBaseFrequency + */ +OPEN1722_INLINE void Avtp_Crf_SetBaseFrequency_V1(Avtp_CrfV1_t *pdu, uint32_t value) +{ + Avtp_Crf_SetField_V1(pdu, AVTP_CRF_FIELD_BASE_FREQUENCY, value); +} + +/** + * Version 0 variant of Avtp_Crf_SetCrfDataLength(). + * @see Avtp_Crf_SetCrfDataLength + */ +OPEN1722_INLINE void Avtp_Crf_SetCrfDataLength_V0(Avtp_Crf_t *pdu, uint16_t value) +{ + Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_CRF_DATA_LENGTH, value); +} + +/** + * Version 1 variant of Avtp_Crf_SetCrfDataLength(). + * @see Avtp_Crf_SetCrfDataLength + */ +OPEN1722_INLINE void Avtp_Crf_SetCrfDataLength_V1(Avtp_CrfV1_t *pdu, uint16_t value) +{ + Avtp_Crf_SetField_V1(pdu, AVTP_CRF_FIELD_CRF_DATA_LENGTH, value); +} + +/** + * Version 0 variant of Avtp_Crf_SetTimestampInterval(). + * @see Avtp_Crf_SetTimestampInterval + */ +OPEN1722_INLINE void Avtp_Crf_SetTimestampInterval_V0(Avtp_Crf_t *pdu, uint16_t value) +{ + Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_TIMESTAMP_INTERVAL, value); +} + +/** + * Version 1 variant of Avtp_Crf_SetTimestampInterval(). + * @see Avtp_Crf_SetTimestampInterval + */ +OPEN1722_INLINE void Avtp_Crf_SetTimestampInterval_V1(Avtp_CrfV1_t *pdu, uint16_t value) +{ + Avtp_Crf_SetField_V1(pdu, AVTP_CRF_FIELD_TIMESTAMP_INTERVAL, value); +} + #ifdef __cplusplus } #endif diff --git a/include/avtp/Rvf.h b/include/avtp/Rvf.h index ee451d35..7c7770c5 100644 --- a/include/avtp/Rvf.h +++ b/include/avtp/Rvf.h @@ -233,7 +233,38 @@ static const Avtp_FieldDescriptor_t Avtp_RvfFieldDescV1[AVTP_RVF_FIELD_MAX] = { }; /** - * Returns the value of an AVTP RVF field as specified in the IEEE 1722 Specification. + * Returns the value of an AVTP RVF field as laid out by version 0. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 RVF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Rvf_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Rvf_GetField_V0(const Avtp_Rvf_t *const pdu, Avtp_RvfFields_t field) +{ + return Avtp_GetField(Avtp_RvfFieldDescV0, AVTP_RVF_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP RVF field as laid out by version 1. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 RVF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Rvf_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Rvf_GetField_V1(const Avtp_RvfV1_t *const pdu, Avtp_RvfFields_t field) +{ + return Avtp_GetField(Avtp_RvfFieldDescV1, AVTP_RVF_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP RVF field, dispatching on the version field of + * the PDU. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param field Specifies the position of the data field to be read @@ -241,15 +272,43 @@ static const Avtp_FieldDescriptor_t Avtp_RvfFieldDescV1[AVTP_RVF_FIELD_MAX] = { */ OPEN1722_INLINE uint64_t Avtp_Rvf_GetField(const Avtp_Rvf_t *const pdu, Avtp_RvfFields_t field) { - const Avtp_FieldDescriptor_t *desc = - Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_RvfFieldDescV1 - : Avtp_RvfFieldDescV0; - return Avtp_GetField(desc, AVTP_RVF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Rvf_GetField_V1((const Avtp_RvfV1_t *)pdu, field) + : Avtp_Rvf_GetField_V0(pdu, field); +} + +/** + * Sets the value of an AVTP RVF field as laid out by version 0. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 RVF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Rvf_SetField + */ +OPEN1722_INLINE void Avtp_Rvf_SetField_V0(Avtp_Rvf_t *pdu, Avtp_RvfFields_t field, uint64_t value) +{ + Avtp_SetField(Avtp_RvfFieldDescV0, AVTP_RVF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); } /** - * Sets the value of an AVTP RVF field as specified in the IEEE 1722 Specification. + * Sets the value of an AVTP RVF field as laid out by version 1. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 RVF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Rvf_SetField + */ +OPEN1722_INLINE void Avtp_Rvf_SetField_V1(Avtp_RvfV1_t *pdu, Avtp_RvfFields_t field, uint64_t value) +{ + Avtp_SetField(Avtp_RvfFieldDescV1, AVTP_RVF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Sets the value of an AVTP RVF field, dispatching on the version field of the + * PDU. * * @param pdu Pointer to the first bit of an 1722 RVF PDU. * @param field Specifies the position of the data field to be written @@ -257,19 +316,46 @@ OPEN1722_INLINE uint64_t Avtp_Rvf_GetField(const Avtp_Rvf_t *const pdu, Avtp_Rvf */ OPEN1722_INLINE void Avtp_Rvf_SetField(Avtp_Rvf_t *pdu, Avtp_RvfFields_t field, uint64_t value) { - const Avtp_FieldDescriptor_t *desc = - Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_RvfFieldDescV1 - : Avtp_RvfFieldDescV0; - Avtp_SetField(desc, AVTP_RVF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); + if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Rvf_SetField_V1((Avtp_RvfV1_t *)pdu, field, value); + } else { + Avtp_Rvf_SetField_V0(pdu, field, value); + } } /** - * Returns the length of the RVF header in octets (24 or 40). + * Returns the length of the version 0 RVF header in octets (24). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Rvf_GetHeaderLen_V0(const Avtp_Rvf_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_RVF_HEADER_LEN_V0; +} + +/** + * Returns the length of the version 1 RVF header in octets (40). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Rvf_GetHeaderLen_V1(const Avtp_RvfV1_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_RVF_HEADER_LEN_V1; +} + +/** + * Returns the length of the RVF header in octets (24 or 40), dispatching on the + * version field of the PDU. */ OPEN1722_INLINE uint8_t Avtp_Rvf_GetHeaderLen(const Avtp_Rvf_t *const pdu) { - return Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Rvf_GetHeaderLen_V1((const Avtp_RvfV1_t *)pdu) + : Avtp_Rvf_GetHeaderLen_V0(pdu); } /** @@ -660,6 +746,30 @@ OPEN1722_INLINE void Avtp_Rvf_SetI(Avtp_Rvf_t *pdu, bool i) Avtp_Rvf_SetField(pdu, AVTP_RVF_FIELD_I, i); } +/** + * Returns a pointer to the stream data of a version 0 RVF frame. + * + * @param pdu Pointer to the first bit of an 1722 RVF PDU. + * @return Pointer to RVF stream data + * @see Avtp_Rvf_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Rvf_GetPayload_V0(const Avtp_Rvf_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_RVF_HEADER_LEN_V0; +} + +/** + * Returns a pointer to the stream data of a version 1 RVF frame. + * + * @param pdu Pointer to the first bit of an 1722 RVF PDU. + * @return Pointer to RVF stream data + * @see Avtp_Rvf_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Rvf_GetPayload_V1(const Avtp_RvfV1_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_RVF_HEADER_LEN_V1; +} + /** * Returns pointer to the RVF stream data. The stream data starts after the * version-dependent common stream header. @@ -672,7 +782,38 @@ OPEN1722_INLINE void Avtp_Rvf_SetI(Avtp_Rvf_t *pdu, bool i) */ OPEN1722_INLINE const uint8_t *Avtp_Rvf_GetPayload(const Avtp_Rvf_t *const pdu) { - return (const uint8_t *)pdu + Avtp_Rvf_GetHeaderLen(pdu); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Rvf_GetPayload_V1((const Avtp_RvfV1_t *)pdu) + : Avtp_Rvf_GetPayload_V0(pdu); +} + +/** + * Sets the stream data of a version 0 RVF frame. + * + * @param pdu Pointer to the first bit of an 1722 RVF PDU. + * @param payload Pointer to the payload byte array + * @param payload_length Length of the payload + * @see Avtp_Rvf_SetPayload + */ +OPEN1722_INLINE void Avtp_Rvf_SetPayload_V0(Avtp_Rvf_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_RVF_HEADER_LEN_V0, payload, payload_length); +} + +/** + * Sets the stream data of a version 1 RVF frame. + * + * @param pdu Pointer to the first bit of an 1722 RVF PDU. + * @param payload Pointer to the payload byte array + * @param payload_length Length of the payload + * @see Avtp_Rvf_SetPayload + */ +OPEN1722_INLINE void Avtp_Rvf_SetPayload_V1(Avtp_RvfV1_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_RVF_HEADER_LEN_V1, payload, payload_length); } /** @@ -684,7 +825,12 @@ OPEN1722_INLINE const uint8_t *Avtp_Rvf_GetPayload(const Avtp_Rvf_t *const pdu) */ OPEN1722_INLINE void Avtp_Rvf_SetPayload(Avtp_Rvf_t *pdu, uint8_t *payload, uint16_t payload_length) { - memcpy((uint8_t *)pdu + Avtp_Rvf_GetHeaderLen(pdu), payload, payload_length); + if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Rvf_SetPayload_V1((Avtp_RvfV1_t *)pdu, payload, payload_length); + } else { + Avtp_Rvf_SetPayload_V0(pdu, payload, payload_length); + } } /** @@ -1082,6 +1228,632 @@ OPEN1722_INLINE void Avtp_RvfRawHeader_SetField(Avtp_RvfRawHeader_t *pdu, SET_RVF_RAW_HEADER_FIELD(field, value); } +/* + * Version-typed named accessors. These select the field layout for one + * explicit version and never read the version field; the version-dispatched + * accessors above delegate to them. Common stream header fields delegate to + * the shared Avtp_CommonStreamHeader_* variants. See each version-dispatched + * accessor for the full field documentation. + */ + +/** + * Version 0 variant of Avtp_Rvf_IsSv(). + * @see Avtp_Rvf_IsSv + */ +OPEN1722_INLINE bool Avtp_Rvf_IsSv_V0(const Avtp_Rvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsSv_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Rvf_IsSv(). + * @see Avtp_Rvf_IsSv + */ +OPEN1722_INLINE bool Avtp_Rvf_IsSv_V1(const Avtp_RvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsSv_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Rvf_IsMr(). + * @see Avtp_Rvf_IsMr + */ +OPEN1722_INLINE bool Avtp_Rvf_IsMr_V0(const Avtp_Rvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsMr_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Rvf_IsMr(). + * @see Avtp_Rvf_IsMr + */ +OPEN1722_INLINE bool Avtp_Rvf_IsMr_V1(const Avtp_RvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsMr_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Rvf_IsTv(). + * @see Avtp_Rvf_IsTv + */ +OPEN1722_INLINE bool Avtp_Rvf_IsTv_V0(const Avtp_Rvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTv_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Rvf_IsTv(). + * @see Avtp_Rvf_IsTv + */ +OPEN1722_INLINE bool Avtp_Rvf_IsTv_V1(const Avtp_RvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTv_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Rvf_IsTu(). + * @see Avtp_Rvf_IsTu + */ +OPEN1722_INLINE bool Avtp_Rvf_IsTu_V0(const Avtp_Rvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTu_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Rvf_IsTu(). + * @see Avtp_Rvf_IsTu + */ +OPEN1722_INLINE bool Avtp_Rvf_IsTu_V1(const Avtp_RvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTu_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Rvf_GetSequenceNum(). Values are truncated to the + * 8-bit version 0 field width. + * @see Avtp_Rvf_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Rvf_GetSequenceNum_V0(const Avtp_Rvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetSequenceNum_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Rvf_GetSequenceNum(). + * @see Avtp_Rvf_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Rvf_GetSequenceNum_V1(const Avtp_RvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetSequenceNum_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Rvf_GetStreamId(). + * @see Avtp_Rvf_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Rvf_GetStreamId_V0(const Avtp_Rvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamId_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Rvf_GetStreamId(). + * @see Avtp_Rvf_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Rvf_GetStreamId_V1(const Avtp_RvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamId_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Rvf_GetAvtpTimestamp(). + * @see Avtp_Rvf_GetAvtpTimestamp + */ +OPEN1722_INLINE uint64_t Avtp_Rvf_GetAvtpTimestamp_V0(const Avtp_Rvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetAvtpTimestamp_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Rvf_GetAvtpTimestamp(). + * @see Avtp_Rvf_GetAvtpTimestamp + */ +OPEN1722_INLINE uint64_t Avtp_Rvf_GetAvtpTimestamp_V1(const Avtp_RvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetAvtpTimestamp_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Rvf_GetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this always returns 0. + * @see Avtp_Rvf_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Rvf_GetPtpGrandmasterIdentity_V0(const Avtp_Rvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V0( + (const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Rvf_GetPtpGrandmasterIdentity(). + * @see Avtp_Rvf_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Rvf_GetPtpGrandmasterIdentity_V1(const Avtp_RvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V1( + (const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Rvf_GetStreamDataLength(). + * @see Avtp_Rvf_GetStreamDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Rvf_GetStreamDataLength_V0(const Avtp_Rvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamDataLength_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Rvf_GetStreamDataLength(). + * @see Avtp_Rvf_GetStreamDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Rvf_GetStreamDataLength_V1(const Avtp_RvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamDataLength_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Rvf_GetActivePixels(). + * @see Avtp_Rvf_GetActivePixels + */ +OPEN1722_INLINE uint16_t Avtp_Rvf_GetActivePixels_V0(const Avtp_Rvf_t *const pdu) +{ + return (uint16_t)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_ACTIVE_PIXELS); +} + +/** + * Version 1 variant of Avtp_Rvf_GetActivePixels(). + * @see Avtp_Rvf_GetActivePixels + */ +OPEN1722_INLINE uint16_t Avtp_Rvf_GetActivePixels_V1(const Avtp_RvfV1_t *const pdu) +{ + return (uint16_t)Avtp_Rvf_GetField_V1(pdu, AVTP_RVF_FIELD_ACTIVE_PIXELS); +} + +/** + * Version 0 variant of Avtp_Rvf_GetTotalLines(). + * @see Avtp_Rvf_GetTotalLines + */ +OPEN1722_INLINE uint16_t Avtp_Rvf_GetTotalLines_V0(const Avtp_Rvf_t *const pdu) +{ + return (uint16_t)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_TOTAL_LINES); +} + +/** + * Version 1 variant of Avtp_Rvf_GetTotalLines(). + * @see Avtp_Rvf_GetTotalLines + */ +OPEN1722_INLINE uint16_t Avtp_Rvf_GetTotalLines_V1(const Avtp_RvfV1_t *const pdu) +{ + return (uint16_t)Avtp_Rvf_GetField_V1(pdu, AVTP_RVF_FIELD_TOTAL_LINES); +} + +/** + * Version 0 variant of Avtp_Rvf_IsAp(). + * @see Avtp_Rvf_IsAp + */ +OPEN1722_INLINE bool Avtp_Rvf_IsAp_V0(const Avtp_Rvf_t *const pdu) +{ + return (bool)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_AP); +} + +/** + * Version 1 variant of Avtp_Rvf_IsAp(). + * @see Avtp_Rvf_IsAp + */ +OPEN1722_INLINE bool Avtp_Rvf_IsAp_V1(const Avtp_RvfV1_t *const pdu) +{ + return (bool)Avtp_Rvf_GetField_V1(pdu, AVTP_RVF_FIELD_AP); +} + +/** + * Version 0 variant of Avtp_Rvf_IsF(). + * @see Avtp_Rvf_IsF + */ +OPEN1722_INLINE bool Avtp_Rvf_IsF_V0(const Avtp_Rvf_t *const pdu) +{ + return (bool)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_F); +} + +/** + * Version 1 variant of Avtp_Rvf_IsF(). + * @see Avtp_Rvf_IsF + */ +OPEN1722_INLINE bool Avtp_Rvf_IsF_V1(const Avtp_RvfV1_t *const pdu) +{ + return (bool)Avtp_Rvf_GetField_V1(pdu, AVTP_RVF_FIELD_F); +} + +/** + * Version 0 variant of Avtp_Rvf_IsEf(). + * @see Avtp_Rvf_IsEf + */ +OPEN1722_INLINE bool Avtp_Rvf_IsEf_V0(const Avtp_Rvf_t *const pdu) +{ + return (bool)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_EF); +} + +/** + * Version 1 variant of Avtp_Rvf_IsEf(). + * @see Avtp_Rvf_IsEf + */ +OPEN1722_INLINE bool Avtp_Rvf_IsEf_V1(const Avtp_RvfV1_t *const pdu) +{ + return (bool)Avtp_Rvf_GetField_V1(pdu, AVTP_RVF_FIELD_EF); +} + +/** + * Version 0 variant of Avtp_Rvf_GetEvt(). + * @see Avtp_Rvf_GetEvt + */ +OPEN1722_INLINE uint8_t Avtp_Rvf_GetEvt_V0(const Avtp_Rvf_t *const pdu) +{ + return (uint8_t)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_EVT); +} + +/** + * Version 1 variant of Avtp_Rvf_GetEvt(). + * @see Avtp_Rvf_GetEvt + */ +OPEN1722_INLINE uint8_t Avtp_Rvf_GetEvt_V1(const Avtp_RvfV1_t *const pdu) +{ + return (uint8_t)Avtp_Rvf_GetField_V1(pdu, AVTP_RVF_FIELD_EVT); +} + +/** + * Version 0 variant of Avtp_Rvf_IsPd(). + * @see Avtp_Rvf_IsPd + */ +OPEN1722_INLINE bool Avtp_Rvf_IsPd_V0(const Avtp_Rvf_t *const pdu) +{ + return (bool)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_PD); +} + +/** + * Version 1 variant of Avtp_Rvf_IsPd(). + * @see Avtp_Rvf_IsPd + */ +OPEN1722_INLINE bool Avtp_Rvf_IsPd_V1(const Avtp_RvfV1_t *const pdu) +{ + return (bool)Avtp_Rvf_GetField_V1(pdu, AVTP_RVF_FIELD_PD); +} + +/** + * Version 0 variant of Avtp_Rvf_IsI(). + * @see Avtp_Rvf_IsI + */ +OPEN1722_INLINE bool Avtp_Rvf_IsI_V0(const Avtp_Rvf_t *const pdu) +{ + return (bool)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_I); +} + +/** + * Version 1 variant of Avtp_Rvf_IsI(). + * @see Avtp_Rvf_IsI + */ +OPEN1722_INLINE bool Avtp_Rvf_IsI_V1(const Avtp_RvfV1_t *const pdu) +{ + return (bool)Avtp_Rvf_GetField_V1(pdu, AVTP_RVF_FIELD_I); +} + +/** + * Version 0 variant of Avtp_Rvf_SetSv(). + * @see Avtp_Rvf_SetSv + */ +OPEN1722_INLINE void Avtp_Rvf_SetSv_V0(Avtp_Rvf_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetSv_V0((Avtp_CommonStreamHeader_t *)pdu, sv); +} + +/** + * Version 1 variant of Avtp_Rvf_SetSv(). + * @see Avtp_Rvf_SetSv + */ +OPEN1722_INLINE void Avtp_Rvf_SetSv_V1(Avtp_RvfV1_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetSv_V1((Avtp_CommonStreamHeader_t *)pdu, sv); +} + +/** + * Version 0 variant of Avtp_Rvf_SetMr(). + * @see Avtp_Rvf_SetMr + */ +OPEN1722_INLINE void Avtp_Rvf_SetMr_V0(Avtp_Rvf_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetMr_V0((Avtp_CommonStreamHeader_t *)pdu, mr); +} + +/** + * Version 1 variant of Avtp_Rvf_SetMr(). + * @see Avtp_Rvf_SetMr + */ +OPEN1722_INLINE void Avtp_Rvf_SetMr_V1(Avtp_RvfV1_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetMr_V1((Avtp_CommonStreamHeader_t *)pdu, mr); +} + +/** + * Version 0 variant of Avtp_Rvf_SetTv(). + * @see Avtp_Rvf_SetTv + */ +OPEN1722_INLINE void Avtp_Rvf_SetTv_V0(Avtp_Rvf_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetTv_V0((Avtp_CommonStreamHeader_t *)pdu, tv); +} + +/** + * Version 1 variant of Avtp_Rvf_SetTv(). + * @see Avtp_Rvf_SetTv + */ +OPEN1722_INLINE void Avtp_Rvf_SetTv_V1(Avtp_RvfV1_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetTv_V1((Avtp_CommonStreamHeader_t *)pdu, tv); +} + +/** + * Version 0 variant of Avtp_Rvf_SetTu(). + * @see Avtp_Rvf_SetTu + */ +OPEN1722_INLINE void Avtp_Rvf_SetTu_V0(Avtp_Rvf_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetTu_V0((Avtp_CommonStreamHeader_t *)pdu, tu); +} + +/** + * Version 1 variant of Avtp_Rvf_SetTu(). + * @see Avtp_Rvf_SetTu + */ +OPEN1722_INLINE void Avtp_Rvf_SetTu_V1(Avtp_RvfV1_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetTu_V1((Avtp_CommonStreamHeader_t *)pdu, tu); +} + +/** + * Version 0 variant of Avtp_Rvf_SetSequenceNum(). Values are truncated to the + * 8-bit version 0 field width. + * @see Avtp_Rvf_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Rvf_SetSequenceNum_V0(Avtp_Rvf_t *pdu, uint32_t value) +{ + Avtp_CommonStreamHeader_SetSequenceNum_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Rvf_SetSequenceNum(). + * @see Avtp_Rvf_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Rvf_SetSequenceNum_V1(Avtp_RvfV1_t *pdu, uint32_t value) +{ + Avtp_CommonStreamHeader_SetSequenceNum_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Rvf_SetStreamId(). + * @see Avtp_Rvf_SetStreamId + */ +OPEN1722_INLINE void Avtp_Rvf_SetStreamId_V0(Avtp_Rvf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetStreamId_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Rvf_SetStreamId(). + * @see Avtp_Rvf_SetStreamId + */ +OPEN1722_INLINE void Avtp_Rvf_SetStreamId_V1(Avtp_RvfV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetStreamId_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Rvf_SetAvtpTimestamp(). + * @see Avtp_Rvf_SetAvtpTimestamp + */ +OPEN1722_INLINE void Avtp_Rvf_SetAvtpTimestamp_V0(Avtp_Rvf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetAvtpTimestamp_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Rvf_SetAvtpTimestamp(). + * @see Avtp_Rvf_SetAvtpTimestamp + */ +OPEN1722_INLINE void Avtp_Rvf_SetAvtpTimestamp_V1(Avtp_RvfV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetAvtpTimestamp_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Rvf_SetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this is a no-op. + * @see Avtp_Rvf_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Rvf_SetPtpGrandmasterIdentity_V0(Avtp_Rvf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Rvf_SetPtpGrandmasterIdentity(). + * @see Avtp_Rvf_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Rvf_SetPtpGrandmasterIdentity_V1(Avtp_RvfV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Rvf_SetStreamDataLength(). + * @see Avtp_Rvf_SetStreamDataLength + */ +OPEN1722_INLINE void Avtp_Rvf_SetStreamDataLength_V0(Avtp_Rvf_t *pdu, uint16_t value) +{ + Avtp_CommonStreamHeader_SetStreamDataLength_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Rvf_SetStreamDataLength(). + * @see Avtp_Rvf_SetStreamDataLength + */ +OPEN1722_INLINE void Avtp_Rvf_SetStreamDataLength_V1(Avtp_RvfV1_t *pdu, uint16_t value) +{ + Avtp_CommonStreamHeader_SetStreamDataLength_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Rvf_SetActivePixels(). + * @see Avtp_Rvf_SetActivePixels + */ +OPEN1722_INLINE void Avtp_Rvf_SetActivePixels_V0(Avtp_Rvf_t *pdu, uint16_t value) +{ + Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_ACTIVE_PIXELS, value); +} + +/** + * Version 1 variant of Avtp_Rvf_SetActivePixels(). + * @see Avtp_Rvf_SetActivePixels + */ +OPEN1722_INLINE void Avtp_Rvf_SetActivePixels_V1(Avtp_RvfV1_t *pdu, uint16_t value) +{ + Avtp_Rvf_SetField_V1(pdu, AVTP_RVF_FIELD_ACTIVE_PIXELS, value); +} + +/** + * Version 0 variant of Avtp_Rvf_SetTotalLines(). + * @see Avtp_Rvf_SetTotalLines + */ +OPEN1722_INLINE void Avtp_Rvf_SetTotalLines_V0(Avtp_Rvf_t *pdu, uint16_t value) +{ + Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_TOTAL_LINES, value); +} + +/** + * Version 1 variant of Avtp_Rvf_SetTotalLines(). + * @see Avtp_Rvf_SetTotalLines + */ +OPEN1722_INLINE void Avtp_Rvf_SetTotalLines_V1(Avtp_RvfV1_t *pdu, uint16_t value) +{ + Avtp_Rvf_SetField_V1(pdu, AVTP_RVF_FIELD_TOTAL_LINES, value); +} + +/** + * Version 0 variant of Avtp_Rvf_SetAp(). + * @see Avtp_Rvf_SetAp + */ +OPEN1722_INLINE void Avtp_Rvf_SetAp_V0(Avtp_Rvf_t *pdu, bool ap) +{ + Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_AP, ap); +} + +/** + * Version 1 variant of Avtp_Rvf_SetAp(). + * @see Avtp_Rvf_SetAp + */ +OPEN1722_INLINE void Avtp_Rvf_SetAp_V1(Avtp_RvfV1_t *pdu, bool ap) +{ + Avtp_Rvf_SetField_V1(pdu, AVTP_RVF_FIELD_AP, ap); +} + +/** + * Version 0 variant of Avtp_Rvf_SetF(). + * @see Avtp_Rvf_SetF + */ +OPEN1722_INLINE void Avtp_Rvf_SetF_V0(Avtp_Rvf_t *pdu, bool f) +{ + Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_F, f); +} + +/** + * Version 1 variant of Avtp_Rvf_SetF(). + * @see Avtp_Rvf_SetF + */ +OPEN1722_INLINE void Avtp_Rvf_SetF_V1(Avtp_RvfV1_t *pdu, bool f) +{ + Avtp_Rvf_SetField_V1(pdu, AVTP_RVF_FIELD_F, f); +} + +/** + * Version 0 variant of Avtp_Rvf_SetEf(). + * @see Avtp_Rvf_SetEf + */ +OPEN1722_INLINE void Avtp_Rvf_SetEf_V0(Avtp_Rvf_t *pdu, bool ef) +{ + Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_EF, ef); +} + +/** + * Version 1 variant of Avtp_Rvf_SetEf(). + * @see Avtp_Rvf_SetEf + */ +OPEN1722_INLINE void Avtp_Rvf_SetEf_V1(Avtp_RvfV1_t *pdu, bool ef) +{ + Avtp_Rvf_SetField_V1(pdu, AVTP_RVF_FIELD_EF, ef); +} + +/** + * Version 0 variant of Avtp_Rvf_SetEvt(). + * @see Avtp_Rvf_SetEvt + */ +OPEN1722_INLINE void Avtp_Rvf_SetEvt_V0(Avtp_Rvf_t *pdu, uint8_t value) +{ + Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_EVT, value); +} + +/** + * Version 1 variant of Avtp_Rvf_SetEvt(). + * @see Avtp_Rvf_SetEvt + */ +OPEN1722_INLINE void Avtp_Rvf_SetEvt_V1(Avtp_RvfV1_t *pdu, uint8_t value) +{ + Avtp_Rvf_SetField_V1(pdu, AVTP_RVF_FIELD_EVT, value); +} + +/** + * Version 0 variant of Avtp_Rvf_SetPd(). + * @see Avtp_Rvf_SetPd + */ +OPEN1722_INLINE void Avtp_Rvf_SetPd_V0(Avtp_Rvf_t *pdu, bool pd) +{ + Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_PD, pd); +} + +/** + * Version 1 variant of Avtp_Rvf_SetPd(). + * @see Avtp_Rvf_SetPd + */ +OPEN1722_INLINE void Avtp_Rvf_SetPd_V1(Avtp_RvfV1_t *pdu, bool pd) +{ + Avtp_Rvf_SetField_V1(pdu, AVTP_RVF_FIELD_PD, pd); +} + +/** + * Version 0 variant of Avtp_Rvf_SetI(). + * @see Avtp_Rvf_SetI + */ +OPEN1722_INLINE void Avtp_Rvf_SetI_V0(Avtp_Rvf_t *pdu, bool i) +{ + Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_I, i); +} + +/** + * Version 1 variant of Avtp_Rvf_SetI(). + * @see Avtp_Rvf_SetI + */ +OPEN1722_INLINE void Avtp_Rvf_SetI_V1(Avtp_RvfV1_t *pdu, bool i) +{ + Avtp_Rvf_SetField_V1(pdu, AVTP_RVF_FIELD_I, i); +} + #ifdef __cplusplus } #endif diff --git a/include/avtp/aaf/Aaf.h b/include/avtp/aaf/Aaf.h index 00f15ca2..f11fe19b 100644 --- a/include/avtp/aaf/Aaf.h +++ b/include/avtp/aaf/Aaf.h @@ -178,7 +178,38 @@ static const Avtp_FieldDescriptor_t Avtp_AafFieldDescV1[AVTP_AAF_FIELD_MAX] = { }; /** - * Returns the value of an AVTP AAF field as specified in the IEEE 1722 Specification. + * Returns the value of an AVTP AAF field as laid out by version 0. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AAF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Aaf_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Aaf_GetField_V0(const Avtp_Aaf_t *const pdu, Avtp_AafFields_t field) +{ + return Avtp_GetField(Avtp_AafFieldDescV0, AVTP_AAF_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP AAF field as laid out by version 1. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AAF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Aaf_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Aaf_GetField_V1(const Avtp_AafV1_t *const pdu, Avtp_AafFields_t field) +{ + return Avtp_GetField(Avtp_AafFieldDescV1, AVTP_AAF_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP AAF field, dispatching on the version field of + * the PDU. * * @param pdu Pointer to the first bit of an 1722 AAF PDU. * @param field Specifies the position of the data field to be read @@ -186,15 +217,43 @@ static const Avtp_FieldDescriptor_t Avtp_AafFieldDescV1[AVTP_AAF_FIELD_MAX] = { */ OPEN1722_INLINE uint64_t Avtp_Aaf_GetField(const Avtp_Aaf_t *const pdu, Avtp_AafFields_t field) { - const Avtp_FieldDescriptor_t *desc = - Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_AafFieldDescV1 - : Avtp_AafFieldDescV0; - return Avtp_GetField(desc, AVTP_AAF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Aaf_GetField_V1((const Avtp_AafV1_t *)pdu, field) + : Avtp_Aaf_GetField_V0(pdu, field); } /** - * Sets the value of an AVTP AAF field as specified in the IEEE 1722 Specification. + * Sets the value of an AVTP AAF field as laid out by version 0. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AAF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Aaf_SetField + */ +OPEN1722_INLINE void Avtp_Aaf_SetField_V0(Avtp_Aaf_t *pdu, Avtp_AafFields_t field, uint64_t value) +{ + Avtp_SetField(Avtp_AafFieldDescV0, AVTP_AAF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Sets the value of an AVTP AAF field as laid out by version 1. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AAF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Aaf_SetField + */ +OPEN1722_INLINE void Avtp_Aaf_SetField_V1(Avtp_AafV1_t *pdu, Avtp_AafFields_t field, uint64_t value) +{ + Avtp_SetField(Avtp_AafFieldDescV1, AVTP_AAF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Sets the value of an AVTP AAF field, dispatching on the version field of the + * PDU. * * @param pdu Pointer to the first bit of an 1722 AAF PDU. * @param field Specifies the position of the data field to be written @@ -202,19 +261,46 @@ OPEN1722_INLINE uint64_t Avtp_Aaf_GetField(const Avtp_Aaf_t *const pdu, Avtp_Aaf */ OPEN1722_INLINE void Avtp_Aaf_SetField(Avtp_Aaf_t *pdu, Avtp_AafFields_t field, uint64_t value) { - const Avtp_FieldDescriptor_t *desc = - Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_AafFieldDescV1 - : Avtp_AafFieldDescV0; - Avtp_SetField(desc, AVTP_AAF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); + if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Aaf_SetField_V1((Avtp_AafV1_t *)pdu, field, value); + } else { + Avtp_Aaf_SetField_V0(pdu, field, value); + } +} + +/** + * Returns the length of the version 0 AAF header in octets (24). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Aaf_GetHeaderLen_V0(const Avtp_Aaf_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_AAF_HEADER_LEN_V0; +} + +/** + * Returns the length of the version 1 AAF header in octets (40). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Aaf_GetHeaderLen_V1(const Avtp_AafV1_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_AAF_HEADER_LEN_V1; } /** - * Returns the length of the AAF header in octets (24 or 40). + * Returns the length of the AAF header in octets (24 or 40), dispatching on the + * version field of the PDU. */ OPEN1722_INLINE uint8_t Avtp_Aaf_GetHeaderLen(const Avtp_Aaf_t *const pdu) { - return Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Aaf_GetHeaderLen_V1((const Avtp_AafV1_t *)pdu) + : Avtp_Aaf_GetHeaderLen_V0(pdu); } /** @@ -561,6 +647,30 @@ OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData2(Avtp_Aaf_t *pdu, uint8_t Avtp_Aaf_SetField(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2, value); } +/** + * Returns a pointer to the payload of a version 0 AAF frame. + * + * @param pdu Pointer to the first bit of an 1722 AAF PDU. + * @return Pointer to AAF frame payload + * @see Avtp_Aaf_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Aaf_GetPayload_V0(const Avtp_Aaf_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_AAF_HEADER_LEN_V0; +} + +/** + * Returns a pointer to the payload of a version 1 AAF frame. + * + * @param pdu Pointer to the first bit of an 1722 AAF PDU. + * @return Pointer to AAF frame payload + * @see Avtp_Aaf_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Aaf_GetPayload_V1(const Avtp_AafV1_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_AAF_HEADER_LEN_V1; +} + /** * Returns pointer to payload of an AAF frame. The payload starts after the * version-dependent common stream header. @@ -570,7 +680,38 @@ OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData2(Avtp_Aaf_t *pdu, uint8_t */ OPEN1722_INLINE const uint8_t *Avtp_Aaf_GetPayload(const Avtp_Aaf_t *const pdu) { - return (const uint8_t *)pdu + Avtp_Aaf_GetHeaderLen(pdu); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Aaf_GetPayload_V1((const Avtp_AafV1_t *)pdu) + : Avtp_Aaf_GetPayload_V0(pdu); +} + +/** + * Sets the payload of a version 0 AAF frame. + * + * @param pdu Pointer to the first bit of an 1722 AAF PDU. + * @param payload Pointer to the payload byte array + * @param payload_length Length of the payload + * @see Avtp_Aaf_SetPayload + */ +OPEN1722_INLINE void Avtp_Aaf_SetPayload_V0(Avtp_Aaf_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_AAF_HEADER_LEN_V0, payload, payload_length); +} + +/** + * Sets the payload of a version 1 AAF frame. + * + * @param pdu Pointer to the first bit of an 1722 AAF PDU. + * @param payload Pointer to the payload byte array + * @param payload_length Length of the payload + * @see Avtp_Aaf_SetPayload + */ +OPEN1722_INLINE void Avtp_Aaf_SetPayload_V1(Avtp_AafV1_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_AAF_HEADER_LEN_V1, payload, payload_length); } /** @@ -582,7 +723,12 @@ OPEN1722_INLINE const uint8_t *Avtp_Aaf_GetPayload(const Avtp_Aaf_t *const pdu) */ OPEN1722_INLINE void Avtp_Aaf_SetPayload(Avtp_Aaf_t *pdu, uint8_t *payload, uint16_t payload_length) { - memcpy((uint8_t *)pdu + Avtp_Aaf_GetHeaderLen(pdu), payload, payload_length); + if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Aaf_SetPayload_V1((Avtp_AafV1_t *)pdu, payload, payload_length); + } else { + Avtp_Aaf_SetPayload_V0(pdu, payload, payload_length); + } } /** @@ -656,6 +802,560 @@ OPEN1722_INLINE bool Avtp_Aaf_IsValid(const Avtp_Aaf_t *const pdu, size_t buffer return true; } +/* + * Version-typed named accessors. These select the field layout for one + * explicit version and never read the version field; the version-dispatched + * accessors above delegate to them. Common stream header fields delegate to + * the shared Avtp_CommonStreamHeader_* variants. See each version-dispatched + * accessor for the full field documentation. + */ + +/** + * Version 0 variant of Avtp_Aaf_IsSv(). + * @see Avtp_Aaf_IsSv + */ +OPEN1722_INLINE bool Avtp_Aaf_IsSv_V0(const Avtp_Aaf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsSv_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Aaf_IsSv(). + * @see Avtp_Aaf_IsSv + */ +OPEN1722_INLINE bool Avtp_Aaf_IsSv_V1(const Avtp_AafV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsSv_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Aaf_IsMr(). + * @see Avtp_Aaf_IsMr + */ +OPEN1722_INLINE bool Avtp_Aaf_IsMr_V0(const Avtp_Aaf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsMr_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Aaf_IsMr(). + * @see Avtp_Aaf_IsMr + */ +OPEN1722_INLINE bool Avtp_Aaf_IsMr_V1(const Avtp_AafV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsMr_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Aaf_IsTv(). + * @see Avtp_Aaf_IsTv + */ +OPEN1722_INLINE bool Avtp_Aaf_IsTv_V0(const Avtp_Aaf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTv_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Aaf_IsTv(). + * @see Avtp_Aaf_IsTv + */ +OPEN1722_INLINE bool Avtp_Aaf_IsTv_V1(const Avtp_AafV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTv_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Aaf_IsTu(). + * @see Avtp_Aaf_IsTu + */ +OPEN1722_INLINE bool Avtp_Aaf_IsTu_V0(const Avtp_Aaf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTu_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Aaf_IsTu(). + * @see Avtp_Aaf_IsTu + */ +OPEN1722_INLINE bool Avtp_Aaf_IsTu_V1(const Avtp_AafV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTu_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Aaf_GetSequenceNum(). Values are truncated to the + * 8-bit version 0 field width. + * @see Avtp_Aaf_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Aaf_GetSequenceNum_V0(const Avtp_Aaf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetSequenceNum_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Aaf_GetSequenceNum(). + * @see Avtp_Aaf_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Aaf_GetSequenceNum_V1(const Avtp_AafV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetSequenceNum_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Aaf_GetStreamId(). + * @see Avtp_Aaf_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Aaf_GetStreamId_V0(const Avtp_Aaf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamId_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Aaf_GetStreamId(). + * @see Avtp_Aaf_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Aaf_GetStreamId_V1(const Avtp_AafV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamId_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Aaf_GetAvtpTimestamp(). + * @see Avtp_Aaf_GetAvtpTimestamp + */ +OPEN1722_INLINE uint64_t Avtp_Aaf_GetAvtpTimestamp_V0(const Avtp_Aaf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetAvtpTimestamp_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Aaf_GetAvtpTimestamp(). + * @see Avtp_Aaf_GetAvtpTimestamp + */ +OPEN1722_INLINE uint64_t Avtp_Aaf_GetAvtpTimestamp_V1(const Avtp_AafV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetAvtpTimestamp_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Aaf_GetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this always returns 0. + * @see Avtp_Aaf_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Aaf_GetPtpGrandmasterIdentity_V0(const Avtp_Aaf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V0( + (const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Aaf_GetPtpGrandmasterIdentity(). + * @see Avtp_Aaf_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Aaf_GetPtpGrandmasterIdentity_V1(const Avtp_AafV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V1( + (const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Aaf_GetFormat(). + * @see Avtp_Aaf_GetFormat + */ +OPEN1722_INLINE Avtp_AafFormat_t Avtp_Aaf_GetFormat_V0(const Avtp_Aaf_t *const pdu) +{ + return (Avtp_AafFormat_t)Avtp_Aaf_GetField_V0(pdu, AVTP_AAF_FIELD_FORMAT); +} + +/** + * Version 1 variant of Avtp_Aaf_GetFormat(). + * @see Avtp_Aaf_GetFormat + */ +OPEN1722_INLINE Avtp_AafFormat_t Avtp_Aaf_GetFormat_V1(const Avtp_AafV1_t *const pdu) +{ + return (Avtp_AafFormat_t)Avtp_Aaf_GetField_V1(pdu, AVTP_AAF_FIELD_FORMAT); +} + +/** + * Version 0 variant of Avtp_Aaf_GetAafFormatSpecificData1(). + * @see Avtp_Aaf_GetAafFormatSpecificData1 + */ +OPEN1722_INLINE uint32_t Avtp_Aaf_GetAafFormatSpecificData1_V0(const Avtp_Aaf_t *const pdu) +{ + return (uint32_t)Avtp_Aaf_GetField_V0(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1); +} + +/** + * Version 1 variant of Avtp_Aaf_GetAafFormatSpecificData1(). + * @see Avtp_Aaf_GetAafFormatSpecificData1 + */ +OPEN1722_INLINE uint32_t Avtp_Aaf_GetAafFormatSpecificData1_V1(const Avtp_AafV1_t *const pdu) +{ + return (uint32_t)Avtp_Aaf_GetField_V1(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1); +} + +/** + * Version 0 variant of Avtp_Aaf_GetStreamDataLength(). + * @see Avtp_Aaf_GetStreamDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Aaf_GetStreamDataLength_V0(const Avtp_Aaf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamDataLength_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Aaf_GetStreamDataLength(). + * @see Avtp_Aaf_GetStreamDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Aaf_GetStreamDataLength_V1(const Avtp_AafV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamDataLength_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Aaf_GetAfsd(). + * @see Avtp_Aaf_GetAfsd + */ +OPEN1722_INLINE uint8_t Avtp_Aaf_GetAfsd_V0(const Avtp_Aaf_t *const pdu) +{ + return (uint8_t)Avtp_Aaf_GetField_V0(pdu, AVTP_AAF_FIELD_AFSD); +} + +/** + * Version 1 variant of Avtp_Aaf_GetAfsd(). + * @see Avtp_Aaf_GetAfsd + */ +OPEN1722_INLINE uint8_t Avtp_Aaf_GetAfsd_V1(const Avtp_AafV1_t *const pdu) +{ + return (uint8_t)Avtp_Aaf_GetField_V1(pdu, AVTP_AAF_FIELD_AFSD); +} + +/** + * Version 0 variant of Avtp_Aaf_IsSp(). + * @see Avtp_Aaf_IsSp + */ +OPEN1722_INLINE bool Avtp_Aaf_IsSp_V0(const Avtp_Aaf_t *const pdu) +{ + return (bool)Avtp_Aaf_GetField_V0(pdu, AVTP_AAF_FIELD_SP); +} + +/** + * Version 1 variant of Avtp_Aaf_IsSp(). + * @see Avtp_Aaf_IsSp + */ +OPEN1722_INLINE bool Avtp_Aaf_IsSp_V1(const Avtp_AafV1_t *const pdu) +{ + return (bool)Avtp_Aaf_GetField_V1(pdu, AVTP_AAF_FIELD_SP); +} + +/** + * Version 0 variant of Avtp_Aaf_GetEvt(). + * @see Avtp_Aaf_GetEvt + */ +OPEN1722_INLINE uint8_t Avtp_Aaf_GetEvt_V0(const Avtp_Aaf_t *const pdu) +{ + return (uint8_t)Avtp_Aaf_GetField_V0(pdu, AVTP_AAF_FIELD_EVT); +} + +/** + * Version 1 variant of Avtp_Aaf_GetEvt(). + * @see Avtp_Aaf_GetEvt + */ +OPEN1722_INLINE uint8_t Avtp_Aaf_GetEvt_V1(const Avtp_AafV1_t *const pdu) +{ + return (uint8_t)Avtp_Aaf_GetField_V1(pdu, AVTP_AAF_FIELD_EVT); +} + +/** + * Version 0 variant of Avtp_Aaf_GetAafFormatSpecificData2(). + * @see Avtp_Aaf_GetAafFormatSpecificData2 + */ +OPEN1722_INLINE uint8_t Avtp_Aaf_GetAafFormatSpecificData2_V0(const Avtp_Aaf_t *const pdu) +{ + return (uint8_t)Avtp_Aaf_GetField_V0(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2); +} + +/** + * Version 1 variant of Avtp_Aaf_GetAafFormatSpecificData2(). + * @see Avtp_Aaf_GetAafFormatSpecificData2 + */ +OPEN1722_INLINE uint8_t Avtp_Aaf_GetAafFormatSpecificData2_V1(const Avtp_AafV1_t *const pdu) +{ + return (uint8_t)Avtp_Aaf_GetField_V1(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2); +} + +/** + * Version 0 variant of Avtp_Aaf_SetSv(). + * @see Avtp_Aaf_SetSv + */ +OPEN1722_INLINE void Avtp_Aaf_SetSv_V0(Avtp_Aaf_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetSv_V0((Avtp_CommonStreamHeader_t *)pdu, sv); +} + +/** + * Version 1 variant of Avtp_Aaf_SetSv(). + * @see Avtp_Aaf_SetSv + */ +OPEN1722_INLINE void Avtp_Aaf_SetSv_V1(Avtp_AafV1_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetSv_V1((Avtp_CommonStreamHeader_t *)pdu, sv); +} + +/** + * Version 0 variant of Avtp_Aaf_SetMr(). + * @see Avtp_Aaf_SetMr + */ +OPEN1722_INLINE void Avtp_Aaf_SetMr_V0(Avtp_Aaf_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetMr_V0((Avtp_CommonStreamHeader_t *)pdu, mr); +} + +/** + * Version 1 variant of Avtp_Aaf_SetMr(). + * @see Avtp_Aaf_SetMr + */ +OPEN1722_INLINE void Avtp_Aaf_SetMr_V1(Avtp_AafV1_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetMr_V1((Avtp_CommonStreamHeader_t *)pdu, mr); +} + +/** + * Version 0 variant of Avtp_Aaf_SetTv(). + * @see Avtp_Aaf_SetTv + */ +OPEN1722_INLINE void Avtp_Aaf_SetTv_V0(Avtp_Aaf_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetTv_V0((Avtp_CommonStreamHeader_t *)pdu, tv); +} + +/** + * Version 1 variant of Avtp_Aaf_SetTv(). + * @see Avtp_Aaf_SetTv + */ +OPEN1722_INLINE void Avtp_Aaf_SetTv_V1(Avtp_AafV1_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetTv_V1((Avtp_CommonStreamHeader_t *)pdu, tv); +} + +/** + * Version 0 variant of Avtp_Aaf_SetTu(). + * @see Avtp_Aaf_SetTu + */ +OPEN1722_INLINE void Avtp_Aaf_SetTu_V0(Avtp_Aaf_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetTu_V0((Avtp_CommonStreamHeader_t *)pdu, tu); +} + +/** + * Version 1 variant of Avtp_Aaf_SetTu(). + * @see Avtp_Aaf_SetTu + */ +OPEN1722_INLINE void Avtp_Aaf_SetTu_V1(Avtp_AafV1_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetTu_V1((Avtp_CommonStreamHeader_t *)pdu, tu); +} + +/** + * Version 0 variant of Avtp_Aaf_SetSequenceNum(). Values are truncated to the + * 8-bit version 0 field width. + * @see Avtp_Aaf_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Aaf_SetSequenceNum_V0(Avtp_Aaf_t *pdu, uint32_t value) +{ + Avtp_CommonStreamHeader_SetSequenceNum_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Aaf_SetSequenceNum(). + * @see Avtp_Aaf_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Aaf_SetSequenceNum_V1(Avtp_AafV1_t *pdu, uint32_t value) +{ + Avtp_CommonStreamHeader_SetSequenceNum_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Aaf_SetStreamId(). + * @see Avtp_Aaf_SetStreamId + */ +OPEN1722_INLINE void Avtp_Aaf_SetStreamId_V0(Avtp_Aaf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetStreamId_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Aaf_SetStreamId(). + * @see Avtp_Aaf_SetStreamId + */ +OPEN1722_INLINE void Avtp_Aaf_SetStreamId_V1(Avtp_AafV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetStreamId_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Aaf_SetAvtpTimestamp(). + * @see Avtp_Aaf_SetAvtpTimestamp + */ +OPEN1722_INLINE void Avtp_Aaf_SetAvtpTimestamp_V0(Avtp_Aaf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetAvtpTimestamp_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Aaf_SetAvtpTimestamp(). + * @see Avtp_Aaf_SetAvtpTimestamp + */ +OPEN1722_INLINE void Avtp_Aaf_SetAvtpTimestamp_V1(Avtp_AafV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetAvtpTimestamp_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Aaf_SetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this is a no-op. + * @see Avtp_Aaf_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Aaf_SetPtpGrandmasterIdentity_V0(Avtp_Aaf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Aaf_SetPtpGrandmasterIdentity(). + * @see Avtp_Aaf_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Aaf_SetPtpGrandmasterIdentity_V1(Avtp_AafV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Aaf_SetFormat(). + * @see Avtp_Aaf_SetFormat + */ +OPEN1722_INLINE void Avtp_Aaf_SetFormat_V0(Avtp_Aaf_t *pdu, Avtp_AafFormat_t value) +{ + Avtp_Aaf_SetField_V0(pdu, AVTP_AAF_FIELD_FORMAT, (uint64_t)value); +} + +/** + * Version 1 variant of Avtp_Aaf_SetFormat(). + * @see Avtp_Aaf_SetFormat + */ +OPEN1722_INLINE void Avtp_Aaf_SetFormat_V1(Avtp_AafV1_t *pdu, Avtp_AafFormat_t value) +{ + Avtp_Aaf_SetField_V1(pdu, AVTP_AAF_FIELD_FORMAT, (uint64_t)value); +} + +/** + * Version 0 variant of Avtp_Aaf_SetAafFormatSpecificData1(). + * @see Avtp_Aaf_SetAafFormatSpecificData1 + */ +OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData1_V0(Avtp_Aaf_t *pdu, uint32_t value) +{ + Avtp_Aaf_SetField_V0(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1, value); +} + +/** + * Version 1 variant of Avtp_Aaf_SetAafFormatSpecificData1(). + * @see Avtp_Aaf_SetAafFormatSpecificData1 + */ +OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData1_V1(Avtp_AafV1_t *pdu, uint32_t value) +{ + Avtp_Aaf_SetField_V1(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1, value); +} + +/** + * Version 0 variant of Avtp_Aaf_SetStreamDataLength(). + * @see Avtp_Aaf_SetStreamDataLength + */ +OPEN1722_INLINE void Avtp_Aaf_SetStreamDataLength_V0(Avtp_Aaf_t *pdu, uint16_t value) +{ + Avtp_CommonStreamHeader_SetStreamDataLength_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Aaf_SetStreamDataLength(). + * @see Avtp_Aaf_SetStreamDataLength + */ +OPEN1722_INLINE void Avtp_Aaf_SetStreamDataLength_V1(Avtp_AafV1_t *pdu, uint16_t value) +{ + Avtp_CommonStreamHeader_SetStreamDataLength_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Aaf_SetAfsd(). + * @see Avtp_Aaf_SetAfsd + */ +OPEN1722_INLINE void Avtp_Aaf_SetAfsd_V0(Avtp_Aaf_t *pdu, uint8_t value) +{ + Avtp_Aaf_SetField_V0(pdu, AVTP_AAF_FIELD_AFSD, value); +} + +/** + * Version 1 variant of Avtp_Aaf_SetAfsd(). + * @see Avtp_Aaf_SetAfsd + */ +OPEN1722_INLINE void Avtp_Aaf_SetAfsd_V1(Avtp_AafV1_t *pdu, uint8_t value) +{ + Avtp_Aaf_SetField_V1(pdu, AVTP_AAF_FIELD_AFSD, value); +} + +/** + * Version 0 variant of Avtp_Aaf_SetSp(). + * @see Avtp_Aaf_SetSp + */ +OPEN1722_INLINE void Avtp_Aaf_SetSp_V0(Avtp_Aaf_t *pdu, bool sp) +{ + Avtp_Aaf_SetField_V0(pdu, AVTP_AAF_FIELD_SP, sp); +} + +/** + * Version 1 variant of Avtp_Aaf_SetSp(). + * @see Avtp_Aaf_SetSp + */ +OPEN1722_INLINE void Avtp_Aaf_SetSp_V1(Avtp_AafV1_t *pdu, bool sp) +{ + Avtp_Aaf_SetField_V1(pdu, AVTP_AAF_FIELD_SP, sp); +} + +/** + * Version 0 variant of Avtp_Aaf_SetEvt(). + * @see Avtp_Aaf_SetEvt + */ +OPEN1722_INLINE void Avtp_Aaf_SetEvt_V0(Avtp_Aaf_t *pdu, uint8_t value) +{ + Avtp_Aaf_SetField_V0(pdu, AVTP_AAF_FIELD_EVT, value); +} + +/** + * Version 1 variant of Avtp_Aaf_SetEvt(). + * @see Avtp_Aaf_SetEvt + */ +OPEN1722_INLINE void Avtp_Aaf_SetEvt_V1(Avtp_AafV1_t *pdu, uint8_t value) +{ + Avtp_Aaf_SetField_V1(pdu, AVTP_AAF_FIELD_EVT, value); +} + +/** + * Version 0 variant of Avtp_Aaf_SetAafFormatSpecificData2(). + * @see Avtp_Aaf_SetAafFormatSpecificData2 + */ +OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData2_V0(Avtp_Aaf_t *pdu, uint8_t value) +{ + Avtp_Aaf_SetField_V0(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2, value); +} + +/** + * Version 1 variant of Avtp_Aaf_SetAafFormatSpecificData2(). + * @see Avtp_Aaf_SetAafFormatSpecificData2 + */ +OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData2_V1(Avtp_AafV1_t *pdu, uint8_t value) +{ + Avtp_Aaf_SetField_V1(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2, value); +} + #ifdef __cplusplus } #endif diff --git a/include/avtp/aaf/Pcm.h b/include/avtp/aaf/Pcm.h index 798f36ee..1a2d25a7 100644 --- a/include/avtp/aaf/Pcm.h +++ b/include/avtp/aaf/Pcm.h @@ -186,7 +186,38 @@ static const Avtp_FieldDescriptor_t Avtp_PcmFieldDescV1[AVTP_PCM_FIELD_MAX] = { }; /** - * Returns the value of an AVTP AAF PCM field as specified in the IEEE 1722 Specification. + * Returns the value of an AVTP AAF PCM field as laid out by version 0. No + * version dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Pcm_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Pcm_GetField_V0(const Avtp_Pcm_t *const pdu, Avtp_PcmFields_t field) +{ + return Avtp_GetField(Avtp_PcmFieldDescV0, AVTP_PCM_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP AAF PCM field as laid out by version 1. No + * version dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Pcm_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Pcm_GetField_V1(const Avtp_PcmV1_t *const pdu, Avtp_PcmFields_t field) +{ + return Avtp_GetField(Avtp_PcmFieldDescV1, AVTP_PCM_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP AAF PCM field, dispatching on the version field + * of the PDU. * * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. * @param field Specifies the position of the data field to be read @@ -194,15 +225,43 @@ static const Avtp_FieldDescriptor_t Avtp_PcmFieldDescV1[AVTP_PCM_FIELD_MAX] = { */ OPEN1722_INLINE uint64_t Avtp_Pcm_GetField(const Avtp_Pcm_t *const pdu, Avtp_PcmFields_t field) { - const Avtp_FieldDescriptor_t *desc = - Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_PcmFieldDescV1 - : Avtp_PcmFieldDescV0; - return Avtp_GetField(desc, AVTP_PCM_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Pcm_GetField_V1((const Avtp_PcmV1_t *)pdu, field) + : Avtp_Pcm_GetField_V0(pdu, field); } /** - * Sets the value of an AVTP AAF PCM field as specified in the IEEE 1722 Specification. + * Sets the value of an AVTP AAF PCM field as laid out by version 0. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Pcm_SetField + */ +OPEN1722_INLINE void Avtp_Pcm_SetField_V0(Avtp_Pcm_t *pdu, Avtp_PcmFields_t field, uint64_t value) +{ + Avtp_SetField(Avtp_PcmFieldDescV0, AVTP_PCM_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Sets the value of an AVTP AAF PCM field as laid out by version 1. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Pcm_SetField + */ +OPEN1722_INLINE void Avtp_Pcm_SetField_V1(Avtp_PcmV1_t *pdu, Avtp_PcmFields_t field, uint64_t value) +{ + Avtp_SetField(Avtp_PcmFieldDescV1, AVTP_PCM_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Sets the value of an AVTP AAF PCM field, dispatching on the version field of + * the PDU. * * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. * @param field Specifies the position of the data field to be written @@ -210,19 +269,46 @@ OPEN1722_INLINE uint64_t Avtp_Pcm_GetField(const Avtp_Pcm_t *const pdu, Avtp_Pcm */ OPEN1722_INLINE void Avtp_Pcm_SetField(Avtp_Pcm_t *pdu, Avtp_PcmFields_t field, uint64_t value) { - const Avtp_FieldDescriptor_t *desc = - Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_PcmFieldDescV1 - : Avtp_PcmFieldDescV0; - Avtp_SetField(desc, AVTP_PCM_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); + if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Pcm_SetField_V1((Avtp_PcmV1_t *)pdu, field, value); + } else { + Avtp_Pcm_SetField_V0(pdu, field, value); + } +} + +/** + * Returns the length of the version 0 AAF PCM header in octets (24). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Pcm_GetHeaderLen_V0(const Avtp_Pcm_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_PCM_HEADER_LEN_V0; +} + +/** + * Returns the length of the version 1 AAF PCM header in octets (40). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Pcm_GetHeaderLen_V1(const Avtp_PcmV1_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_PCM_HEADER_LEN_V1; } /** - * Returns the length of the AAF PCM header in octets (24 or 40). + * Returns the length of the AAF PCM header in octets (24 or 40), dispatching + * on the version field of the PDU. */ OPEN1722_INLINE uint8_t Avtp_Pcm_GetHeaderLen(const Avtp_Pcm_t *const pdu) { - return Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Pcm_GetHeaderLen_V1((const Avtp_PcmV1_t *)pdu) + : Avtp_Pcm_GetHeaderLen_V0(pdu); } /** @@ -567,6 +653,30 @@ OPEN1722_INLINE void Avtp_Pcm_SetEvt(Avtp_Pcm_t *pdu, uint8_t value) Avtp_Pcm_SetField(pdu, AVTP_PCM_FIELD_EVT, value); } +/** + * Returns a pointer to the payload of a version 0 AAF PCM frame. + * + * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. + * @return Pointer to AAF PCM frame payload + * @see Avtp_Pcm_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Pcm_GetPayload_V0(const Avtp_Pcm_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_PCM_HEADER_LEN_V0; +} + +/** + * Returns a pointer to the payload of a version 1 AAF PCM frame. + * + * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. + * @return Pointer to AAF PCM frame payload + * @see Avtp_Pcm_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Pcm_GetPayload_V1(const Avtp_PcmV1_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_PCM_HEADER_LEN_V1; +} + /** * Returns pointer to payload of an AAF PCM frame. The payload starts after the * version-dependent common stream header. @@ -576,7 +686,38 @@ OPEN1722_INLINE void Avtp_Pcm_SetEvt(Avtp_Pcm_t *pdu, uint8_t value) */ OPEN1722_INLINE const uint8_t *Avtp_Pcm_GetPayload(const Avtp_Pcm_t *const pdu) { - return (const uint8_t *)pdu + Avtp_Pcm_GetHeaderLen(pdu); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Pcm_GetPayload_V1((const Avtp_PcmV1_t *)pdu) + : Avtp_Pcm_GetPayload_V0(pdu); +} + +/** + * Sets the payload of a version 0 AAF PCM frame. + * + * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. + * @param payload Pointer to the payload byte array + * @param payload_length Length of the payload + * @see Avtp_Pcm_SetPayload + */ +OPEN1722_INLINE void Avtp_Pcm_SetPayload_V0(Avtp_Pcm_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_PCM_HEADER_LEN_V0, payload, payload_length); +} + +/** + * Sets the payload of a version 1 AAF PCM frame. + * + * @param pdu Pointer to the first bit of an 1722 AAF PCM PDU. + * @param payload Pointer to the payload byte array + * @param payload_length Length of the payload + * @see Avtp_Pcm_SetPayload + */ +OPEN1722_INLINE void Avtp_Pcm_SetPayload_V1(Avtp_PcmV1_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_PCM_HEADER_LEN_V1, payload, payload_length); } /** @@ -588,7 +729,12 @@ OPEN1722_INLINE const uint8_t *Avtp_Pcm_GetPayload(const Avtp_Pcm_t *const pdu) */ OPEN1722_INLINE void Avtp_Pcm_SetPayload(Avtp_Pcm_t *pdu, uint8_t *payload, uint16_t payload_length) { - memcpy((uint8_t *)pdu + Avtp_Pcm_GetHeaderLen(pdu), payload, payload_length); + if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Pcm_SetPayload_V1((Avtp_PcmV1_t *)pdu, payload, payload_length); + } else { + Avtp_Pcm_SetPayload_V0(pdu, payload, payload_length); + } } /** @@ -697,6 +843,560 @@ OPEN1722_INLINE bool Avtp_Pcm_IsValid(const Avtp_Pcm_t *const pdu, size_t buffer return true; } +/* + * Version-typed named accessors. These select the field layout for one + * explicit version and never read the version field; the version-dispatched + * accessors above delegate to them. Common stream header fields delegate to + * the shared Avtp_CommonStreamHeader_* variants. See each version-dispatched + * accessor for the full field documentation. + */ + +/** + * Version 0 variant of Avtp_Pcm_IsSv(). + * @see Avtp_Pcm_IsSv + */ +OPEN1722_INLINE bool Avtp_Pcm_IsSv_V0(const Avtp_Pcm_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsSv_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Pcm_IsSv(). + * @see Avtp_Pcm_IsSv + */ +OPEN1722_INLINE bool Avtp_Pcm_IsSv_V1(const Avtp_PcmV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsSv_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Pcm_IsMr(). + * @see Avtp_Pcm_IsMr + */ +OPEN1722_INLINE bool Avtp_Pcm_IsMr_V0(const Avtp_Pcm_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsMr_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Pcm_IsMr(). + * @see Avtp_Pcm_IsMr + */ +OPEN1722_INLINE bool Avtp_Pcm_IsMr_V1(const Avtp_PcmV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsMr_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Pcm_IsTv(). + * @see Avtp_Pcm_IsTv + */ +OPEN1722_INLINE bool Avtp_Pcm_IsTv_V0(const Avtp_Pcm_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTv_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Pcm_IsTv(). + * @see Avtp_Pcm_IsTv + */ +OPEN1722_INLINE bool Avtp_Pcm_IsTv_V1(const Avtp_PcmV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTv_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Pcm_IsTu(). + * @see Avtp_Pcm_IsTu + */ +OPEN1722_INLINE bool Avtp_Pcm_IsTu_V0(const Avtp_Pcm_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTu_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Pcm_IsTu(). + * @see Avtp_Pcm_IsTu + */ +OPEN1722_INLINE bool Avtp_Pcm_IsTu_V1(const Avtp_PcmV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTu_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Pcm_GetSequenceNum(). Values are truncated to the + * 8-bit version 0 field width. + * @see Avtp_Pcm_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Pcm_GetSequenceNum_V0(const Avtp_Pcm_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetSequenceNum_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Pcm_GetSequenceNum(). + * @see Avtp_Pcm_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Pcm_GetSequenceNum_V1(const Avtp_PcmV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetSequenceNum_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Pcm_GetStreamId(). + * @see Avtp_Pcm_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Pcm_GetStreamId_V0(const Avtp_Pcm_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamId_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Pcm_GetStreamId(). + * @see Avtp_Pcm_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Pcm_GetStreamId_V1(const Avtp_PcmV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamId_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Pcm_GetAvtpTimestamp(). + * @see Avtp_Pcm_GetAvtpTimestamp + */ +OPEN1722_INLINE uint64_t Avtp_Pcm_GetAvtpTimestamp_V0(const Avtp_Pcm_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetAvtpTimestamp_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Pcm_GetAvtpTimestamp(). + * @see Avtp_Pcm_GetAvtpTimestamp + */ +OPEN1722_INLINE uint64_t Avtp_Pcm_GetAvtpTimestamp_V1(const Avtp_PcmV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetAvtpTimestamp_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Pcm_GetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this always returns 0. + * @see Avtp_Pcm_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Pcm_GetPtpGrandmasterIdentity_V0(const Avtp_Pcm_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V0( + (const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Pcm_GetPtpGrandmasterIdentity(). + * @see Avtp_Pcm_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Pcm_GetPtpGrandmasterIdentity_V1(const Avtp_PcmV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V1( + (const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Pcm_GetFormat(). + * @see Avtp_Pcm_GetFormat + */ +OPEN1722_INLINE Avtp_AafFormat_t Avtp_Pcm_GetFormat_V0(const Avtp_Pcm_t *const pdu) +{ + return (Avtp_AafFormat_t)Avtp_Pcm_GetField_V0(pdu, AVTP_PCM_FIELD_FORMAT); +} + +/** + * Version 1 variant of Avtp_Pcm_GetFormat(). + * @see Avtp_Pcm_GetFormat + */ +OPEN1722_INLINE Avtp_AafFormat_t Avtp_Pcm_GetFormat_V1(const Avtp_PcmV1_t *const pdu) +{ + return (Avtp_AafFormat_t)Avtp_Pcm_GetField_V1(pdu, AVTP_PCM_FIELD_FORMAT); +} + +/** + * Version 0 variant of Avtp_Pcm_GetNsr(). + * @see Avtp_Pcm_GetNsr + */ +OPEN1722_INLINE Avtp_PcmNsr_t Avtp_Pcm_GetNsr_V0(const Avtp_Pcm_t *const pdu) +{ + return (Avtp_PcmNsr_t)Avtp_Pcm_GetField_V0(pdu, AVTP_PCM_FIELD_NSR); +} + +/** + * Version 1 variant of Avtp_Pcm_GetNsr(). + * @see Avtp_Pcm_GetNsr + */ +OPEN1722_INLINE Avtp_PcmNsr_t Avtp_Pcm_GetNsr_V1(const Avtp_PcmV1_t *const pdu) +{ + return (Avtp_PcmNsr_t)Avtp_Pcm_GetField_V1(pdu, AVTP_PCM_FIELD_NSR); +} + +/** + * Version 0 variant of Avtp_Pcm_GetChannelsPerFrame(). + * @see Avtp_Pcm_GetChannelsPerFrame + */ +OPEN1722_INLINE uint16_t Avtp_Pcm_GetChannelsPerFrame_V0(const Avtp_Pcm_t *const pdu) +{ + return (uint16_t)Avtp_Pcm_GetField_V0(pdu, AVTP_PCM_FIELD_CHANNELS_PER_FRAME); +} + +/** + * Version 1 variant of Avtp_Pcm_GetChannelsPerFrame(). + * @see Avtp_Pcm_GetChannelsPerFrame + */ +OPEN1722_INLINE uint16_t Avtp_Pcm_GetChannelsPerFrame_V1(const Avtp_PcmV1_t *const pdu) +{ + return (uint16_t)Avtp_Pcm_GetField_V1(pdu, AVTP_PCM_FIELD_CHANNELS_PER_FRAME); +} + +/** + * Version 0 variant of Avtp_Pcm_GetBitDepth(). + * @see Avtp_Pcm_GetBitDepth + */ +OPEN1722_INLINE uint8_t Avtp_Pcm_GetBitDepth_V0(const Avtp_Pcm_t *const pdu) +{ + return (uint8_t)Avtp_Pcm_GetField_V0(pdu, AVTP_PCM_FIELD_BIT_DEPTH); +} + +/** + * Version 1 variant of Avtp_Pcm_GetBitDepth(). + * @see Avtp_Pcm_GetBitDepth + */ +OPEN1722_INLINE uint8_t Avtp_Pcm_GetBitDepth_V1(const Avtp_PcmV1_t *const pdu) +{ + return (uint8_t)Avtp_Pcm_GetField_V1(pdu, AVTP_PCM_FIELD_BIT_DEPTH); +} + +/** + * Version 0 variant of Avtp_Pcm_GetStreamDataLength(). + * @see Avtp_Pcm_GetStreamDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Pcm_GetStreamDataLength_V0(const Avtp_Pcm_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamDataLength_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Pcm_GetStreamDataLength(). + * @see Avtp_Pcm_GetStreamDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Pcm_GetStreamDataLength_V1(const Avtp_PcmV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamDataLength_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Pcm_IsSp(). + * @see Avtp_Pcm_IsSp + */ +OPEN1722_INLINE bool Avtp_Pcm_IsSp_V0(const Avtp_Pcm_t *const pdu) +{ + return (bool)Avtp_Pcm_GetField_V0(pdu, AVTP_PCM_FIELD_SP); +} + +/** + * Version 1 variant of Avtp_Pcm_IsSp(). + * @see Avtp_Pcm_IsSp + */ +OPEN1722_INLINE bool Avtp_Pcm_IsSp_V1(const Avtp_PcmV1_t *const pdu) +{ + return (bool)Avtp_Pcm_GetField_V1(pdu, AVTP_PCM_FIELD_SP); +} + +/** + * Version 0 variant of Avtp_Pcm_GetEvt(). + * @see Avtp_Pcm_GetEvt + */ +OPEN1722_INLINE uint8_t Avtp_Pcm_GetEvt_V0(const Avtp_Pcm_t *const pdu) +{ + return (uint8_t)Avtp_Pcm_GetField_V0(pdu, AVTP_PCM_FIELD_EVT); +} + +/** + * Version 1 variant of Avtp_Pcm_GetEvt(). + * @see Avtp_Pcm_GetEvt + */ +OPEN1722_INLINE uint8_t Avtp_Pcm_GetEvt_V1(const Avtp_PcmV1_t *const pdu) +{ + return (uint8_t)Avtp_Pcm_GetField_V1(pdu, AVTP_PCM_FIELD_EVT); +} + +/** + * Version 0 variant of Avtp_Pcm_SetSv(). + * @see Avtp_Pcm_SetSv + */ +OPEN1722_INLINE void Avtp_Pcm_SetSv_V0(Avtp_Pcm_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetSv_V0((Avtp_CommonStreamHeader_t *)pdu, sv); +} + +/** + * Version 1 variant of Avtp_Pcm_SetSv(). + * @see Avtp_Pcm_SetSv + */ +OPEN1722_INLINE void Avtp_Pcm_SetSv_V1(Avtp_PcmV1_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetSv_V1((Avtp_CommonStreamHeader_t *)pdu, sv); +} + +/** + * Version 0 variant of Avtp_Pcm_SetMr(). + * @see Avtp_Pcm_SetMr + */ +OPEN1722_INLINE void Avtp_Pcm_SetMr_V0(Avtp_Pcm_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetMr_V0((Avtp_CommonStreamHeader_t *)pdu, mr); +} + +/** + * Version 1 variant of Avtp_Pcm_SetMr(). + * @see Avtp_Pcm_SetMr + */ +OPEN1722_INLINE void Avtp_Pcm_SetMr_V1(Avtp_PcmV1_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetMr_V1((Avtp_CommonStreamHeader_t *)pdu, mr); +} + +/** + * Version 0 variant of Avtp_Pcm_SetTv(). + * @see Avtp_Pcm_SetTv + */ +OPEN1722_INLINE void Avtp_Pcm_SetTv_V0(Avtp_Pcm_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetTv_V0((Avtp_CommonStreamHeader_t *)pdu, tv); +} + +/** + * Version 1 variant of Avtp_Pcm_SetTv(). + * @see Avtp_Pcm_SetTv + */ +OPEN1722_INLINE void Avtp_Pcm_SetTv_V1(Avtp_PcmV1_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetTv_V1((Avtp_CommonStreamHeader_t *)pdu, tv); +} + +/** + * Version 0 variant of Avtp_Pcm_SetTu(). + * @see Avtp_Pcm_SetTu + */ +OPEN1722_INLINE void Avtp_Pcm_SetTu_V0(Avtp_Pcm_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetTu_V0((Avtp_CommonStreamHeader_t *)pdu, tu); +} + +/** + * Version 1 variant of Avtp_Pcm_SetTu(). + * @see Avtp_Pcm_SetTu + */ +OPEN1722_INLINE void Avtp_Pcm_SetTu_V1(Avtp_PcmV1_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetTu_V1((Avtp_CommonStreamHeader_t *)pdu, tu); +} + +/** + * Version 0 variant of Avtp_Pcm_SetSequenceNum(). Values are truncated to the + * 8-bit version 0 field width. + * @see Avtp_Pcm_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Pcm_SetSequenceNum_V0(Avtp_Pcm_t *pdu, uint32_t value) +{ + Avtp_CommonStreamHeader_SetSequenceNum_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Pcm_SetSequenceNum(). + * @see Avtp_Pcm_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Pcm_SetSequenceNum_V1(Avtp_PcmV1_t *pdu, uint32_t value) +{ + Avtp_CommonStreamHeader_SetSequenceNum_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Pcm_SetStreamId(). + * @see Avtp_Pcm_SetStreamId + */ +OPEN1722_INLINE void Avtp_Pcm_SetStreamId_V0(Avtp_Pcm_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetStreamId_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Pcm_SetStreamId(). + * @see Avtp_Pcm_SetStreamId + */ +OPEN1722_INLINE void Avtp_Pcm_SetStreamId_V1(Avtp_PcmV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetStreamId_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Pcm_SetAvtpTimestamp(). + * @see Avtp_Pcm_SetAvtpTimestamp + */ +OPEN1722_INLINE void Avtp_Pcm_SetAvtpTimestamp_V0(Avtp_Pcm_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetAvtpTimestamp_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Pcm_SetAvtpTimestamp(). + * @see Avtp_Pcm_SetAvtpTimestamp + */ +OPEN1722_INLINE void Avtp_Pcm_SetAvtpTimestamp_V1(Avtp_PcmV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetAvtpTimestamp_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Pcm_SetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this is a no-op. + * @see Avtp_Pcm_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Pcm_SetPtpGrandmasterIdentity_V0(Avtp_Pcm_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Pcm_SetPtpGrandmasterIdentity(). + * @see Avtp_Pcm_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Pcm_SetPtpGrandmasterIdentity_V1(Avtp_PcmV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Pcm_SetFormat(). + * @see Avtp_Pcm_SetFormat + */ +OPEN1722_INLINE void Avtp_Pcm_SetFormat_V0(Avtp_Pcm_t *pdu, Avtp_AafFormat_t value) +{ + Avtp_Pcm_SetField_V0(pdu, AVTP_PCM_FIELD_FORMAT, (uint64_t)value); +} + +/** + * Version 1 variant of Avtp_Pcm_SetFormat(). + * @see Avtp_Pcm_SetFormat + */ +OPEN1722_INLINE void Avtp_Pcm_SetFormat_V1(Avtp_PcmV1_t *pdu, Avtp_AafFormat_t value) +{ + Avtp_Pcm_SetField_V1(pdu, AVTP_PCM_FIELD_FORMAT, (uint64_t)value); +} + +/** + * Version 0 variant of Avtp_Pcm_SetNsr(). + * @see Avtp_Pcm_SetNsr + */ +OPEN1722_INLINE void Avtp_Pcm_SetNsr_V0(Avtp_Pcm_t *pdu, Avtp_PcmNsr_t value) +{ + Avtp_Pcm_SetField_V0(pdu, AVTP_PCM_FIELD_NSR, (uint64_t)value); +} + +/** + * Version 1 variant of Avtp_Pcm_SetNsr(). + * @see Avtp_Pcm_SetNsr + */ +OPEN1722_INLINE void Avtp_Pcm_SetNsr_V1(Avtp_PcmV1_t *pdu, Avtp_PcmNsr_t value) +{ + Avtp_Pcm_SetField_V1(pdu, AVTP_PCM_FIELD_NSR, (uint64_t)value); +} + +/** + * Version 0 variant of Avtp_Pcm_SetChannelsPerFrame(). + * @see Avtp_Pcm_SetChannelsPerFrame + */ +OPEN1722_INLINE void Avtp_Pcm_SetChannelsPerFrame_V0(Avtp_Pcm_t *pdu, uint16_t value) +{ + Avtp_Pcm_SetField_V0(pdu, AVTP_PCM_FIELD_CHANNELS_PER_FRAME, value); +} + +/** + * Version 1 variant of Avtp_Pcm_SetChannelsPerFrame(). + * @see Avtp_Pcm_SetChannelsPerFrame + */ +OPEN1722_INLINE void Avtp_Pcm_SetChannelsPerFrame_V1(Avtp_PcmV1_t *pdu, uint16_t value) +{ + Avtp_Pcm_SetField_V1(pdu, AVTP_PCM_FIELD_CHANNELS_PER_FRAME, value); +} + +/** + * Version 0 variant of Avtp_Pcm_SetBitDepth(). + * @see Avtp_Pcm_SetBitDepth + */ +OPEN1722_INLINE void Avtp_Pcm_SetBitDepth_V0(Avtp_Pcm_t *pdu, uint8_t value) +{ + Avtp_Pcm_SetField_V0(pdu, AVTP_PCM_FIELD_BIT_DEPTH, value); +} + +/** + * Version 1 variant of Avtp_Pcm_SetBitDepth(). + * @see Avtp_Pcm_SetBitDepth + */ +OPEN1722_INLINE void Avtp_Pcm_SetBitDepth_V1(Avtp_PcmV1_t *pdu, uint8_t value) +{ + Avtp_Pcm_SetField_V1(pdu, AVTP_PCM_FIELD_BIT_DEPTH, value); +} + +/** + * Version 0 variant of Avtp_Pcm_SetStreamDataLength(). + * @see Avtp_Pcm_SetStreamDataLength + */ +OPEN1722_INLINE void Avtp_Pcm_SetStreamDataLength_V0(Avtp_Pcm_t *pdu, uint16_t value) +{ + Avtp_CommonStreamHeader_SetStreamDataLength_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Pcm_SetStreamDataLength(). + * @see Avtp_Pcm_SetStreamDataLength + */ +OPEN1722_INLINE void Avtp_Pcm_SetStreamDataLength_V1(Avtp_PcmV1_t *pdu, uint16_t value) +{ + Avtp_CommonStreamHeader_SetStreamDataLength_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Pcm_SetSp(). + * @see Avtp_Pcm_SetSp + */ +OPEN1722_INLINE void Avtp_Pcm_SetSp_V0(Avtp_Pcm_t *pdu, bool sp) +{ + Avtp_Pcm_SetField_V0(pdu, AVTP_PCM_FIELD_SP, sp); +} + +/** + * Version 1 variant of Avtp_Pcm_SetSp(). + * @see Avtp_Pcm_SetSp + */ +OPEN1722_INLINE void Avtp_Pcm_SetSp_V1(Avtp_PcmV1_t *pdu, bool sp) +{ + Avtp_Pcm_SetField_V1(pdu, AVTP_PCM_FIELD_SP, sp); +} + +/** + * Version 0 variant of Avtp_Pcm_SetEvt(). + * @see Avtp_Pcm_SetEvt + */ +OPEN1722_INLINE void Avtp_Pcm_SetEvt_V0(Avtp_Pcm_t *pdu, uint8_t value) +{ + Avtp_Pcm_SetField_V0(pdu, AVTP_PCM_FIELD_EVT, value); +} + +/** + * Version 1 variant of Avtp_Pcm_SetEvt(). + * @see Avtp_Pcm_SetEvt + */ +OPEN1722_INLINE void Avtp_Pcm_SetEvt_V1(Avtp_PcmV1_t *pdu, uint8_t value) +{ + Avtp_Pcm_SetField_V1(pdu, AVTP_PCM_FIELD_EVT, value); +} + #ifdef __cplusplus } #endif diff --git a/include/avtp/acf/Ntscf.h b/include/avtp/acf/Ntscf.h index 388d0970..c9f17153 100644 --- a/include/avtp/acf/Ntscf.h +++ b/include/avtp/acf/Ntscf.h @@ -131,7 +131,40 @@ static const Avtp_FieldDescriptor_t Avtp_NtscfFieldDescV1[AVTP_NTSCF_FIELD_MAX] }; /** - * Returns the value of an AVTP NTSCF field as specified in the IEEE 1722 Specification. + * Returns the value of an AVTP NTSCF field as laid out by version 0. No + * version dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AVTP NTSCF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Ntscf_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Ntscf_GetField_V0(const Avtp_Ntscf_t *const pdu, + Avtp_NtscfFields_t field) +{ + return Avtp_GetField(Avtp_NtscfFieldDescV0, AVTP_NTSCF_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP NTSCF field as laid out by version 1. No + * version dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AVTP NTSCF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Ntscf_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Ntscf_GetField_V1(const Avtp_NtscfV1_t *const pdu, + Avtp_NtscfFields_t field) +{ + return Avtp_GetField(Avtp_NtscfFieldDescV1, AVTP_NTSCF_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP NTSCF field, dispatching on the version field of + * the PDU. * * @param pdu Pointer to the first bit of an 1722 AVTP NTSCF PDU. * @param field Specifies the position of the data field to be read @@ -140,15 +173,47 @@ static const Avtp_FieldDescriptor_t Avtp_NtscfFieldDescV1[AVTP_NTSCF_FIELD_MAX] OPEN1722_INLINE uint64_t Avtp_Ntscf_GetField(const Avtp_Ntscf_t *const pdu, Avtp_NtscfFields_t field) { - const Avtp_FieldDescriptor_t *desc = - Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_NtscfFieldDescV1 - : Avtp_NtscfFieldDescV0; - return Avtp_GetField(desc, AVTP_NTSCF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); + return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Ntscf_GetField_V1((const Avtp_NtscfV1_t *)pdu, field) + : Avtp_Ntscf_GetField_V0(pdu, field); } /** - * Sets the value of an AVTP NTSCF field as specified in the IEEE 1722 Specification. + * Sets the value of an AVTP NTSCF field as laid out by version 0. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AVTP NTSCF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Ntscf_SetField + */ +OPEN1722_INLINE void Avtp_Ntscf_SetField_V0(Avtp_Ntscf_t *pdu, Avtp_NtscfFields_t field, + uint64_t value) +{ + Avtp_SetField(Avtp_NtscfFieldDescV0, AVTP_NTSCF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, + value); +} + +/** + * Sets the value of an AVTP NTSCF field as laid out by version 1. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AVTP NTSCF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Ntscf_SetField + */ +OPEN1722_INLINE void Avtp_Ntscf_SetField_V1(Avtp_NtscfV1_t *pdu, Avtp_NtscfFields_t field, + uint64_t value) +{ + Avtp_SetField(Avtp_NtscfFieldDescV1, AVTP_NTSCF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, + value); +} + +/** + * Sets the value of an AVTP NTSCF field, dispatching on the version field of + * the PDU. * * @param pdu Pointer to the first bit of an 1722 AVTP NTSCF PDU. * @param field Specifies the position of the data field to be written @@ -157,22 +222,46 @@ OPEN1722_INLINE uint64_t Avtp_Ntscf_GetField(const Avtp_Ntscf_t *const pdu, OPEN1722_INLINE void Avtp_Ntscf_SetField(Avtp_Ntscf_t *pdu, Avtp_NtscfFields_t field, uint64_t value) { - const Avtp_FieldDescriptor_t *desc = - Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_NtscfFieldDescV1 - : Avtp_NtscfFieldDescV0; - Avtp_SetField(desc, AVTP_NTSCF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); + if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Ntscf_SetField_V1((Avtp_NtscfV1_t *)pdu, field, value); + } else { + Avtp_Ntscf_SetField_V0(pdu, field, value); + } +} + +/** + * Returns the length of the version 0 NTSCF header in octets (12). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Ntscf_GetHeaderLen_V0(const Avtp_Ntscf_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_NTSCF_HEADER_LEN_V0; } /** - * Returns the length of the NTSCF header in octets (12 or 28). + * Returns the length of the version 1 NTSCF header in octets (28). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Ntscf_GetHeaderLen_V1(const Avtp_NtscfV1_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_NTSCF_HEADER_LEN_V1; +} + +/** + * Returns the length of the NTSCF header in octets (12 or 28), dispatching on + * the version field of the PDU. */ OPEN1722_INLINE uint8_t Avtp_Ntscf_GetHeaderLen(const Avtp_Ntscf_t *const pdu) { return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == AVTP_VERSION_1 - ? (uint8_t)AVTP_NTSCF_HEADER_LEN_V1 - : (uint8_t)AVTP_NTSCF_HEADER_LEN_V0; + ? Avtp_Ntscf_GetHeaderLen_V1((const Avtp_NtscfV1_t *)pdu) + : Avtp_Ntscf_GetHeaderLen_V0(pdu); } /** @@ -208,11 +297,11 @@ OPEN1722_INLINE uint16_t Avtp_Ntscf_GetNtscfDataLength(const Avtp_Ntscf_t *const */ OPEN1722_INLINE uint32_t Avtp_Ntscf_GetSequenceNum(const Avtp_Ntscf_t *const pdu) { - if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1) { - return (uint32_t)Avtp_Ntscf_GetField(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM); - } - return (uint8_t)Avtp_Ntscf_GetField(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB); + return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1 + ? (uint32_t)Avtp_Ntscf_GetField_V1((const Avtp_NtscfV1_t *)pdu, + AVTP_NTSCF_FIELD_SEQUENCE_NUM) + : (uint8_t)Avtp_Ntscf_GetField_V0(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB); } /** @@ -285,9 +374,14 @@ OPEN1722_INLINE void Avtp_Ntscf_SetNtscfDataLength(Avtp_Ntscf_t *pdu, uint16_t v */ OPEN1722_INLINE void Avtp_Ntscf_SetSequenceNum(Avtp_Ntscf_t *pdu, uint32_t value) { - /* No-op on version 0: the field only exists in the alternative header v1. */ - Avtp_Ntscf_SetField(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM, value); - Avtp_Ntscf_SetField(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); + if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Ntscf_SetField_V1((Avtp_NtscfV1_t *)pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM, value); + Avtp_Ntscf_SetField_V1((Avtp_NtscfV1_t *)pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB, + (uint8_t)(value & 0xFFU)); + } else { + Avtp_Ntscf_SetField_V0(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); + } } /** @@ -313,6 +407,30 @@ OPEN1722_INLINE void Avtp_Ntscf_SetStreamId(Avtp_Ntscf_t *pdu, uint64_t value) Avtp_Ntscf_SetField(pdu, AVTP_NTSCF_FIELD_STREAM_ID, value); } +/** + * Returns a pointer to the payload of a version 0 NTSCF frame. + * + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @return Pointer to the NTSCF frame payload. + * @see Avtp_Ntscf_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Ntscf_GetPayload_V0(const Avtp_Ntscf_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_NTSCF_HEADER_LEN_V0; +} + +/** + * Returns a pointer to the payload of a version 1 NTSCF frame. + * + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @return Pointer to the NTSCF frame payload. + * @see Avtp_Ntscf_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Ntscf_GetPayload_V1(const Avtp_NtscfV1_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_NTSCF_HEADER_LEN_V1; +} + /** * Returns pointer to the payload of an NTSCF frame. The payload starts after * the version-dependent NTSCF header. @@ -322,7 +440,38 @@ OPEN1722_INLINE void Avtp_Ntscf_SetStreamId(Avtp_Ntscf_t *pdu, uint64_t value) */ OPEN1722_INLINE const uint8_t *Avtp_Ntscf_GetPayload(const Avtp_Ntscf_t *const pdu) { - return (const uint8_t *)pdu + Avtp_Ntscf_GetHeaderLen(pdu); + return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Ntscf_GetPayload_V1((const Avtp_NtscfV1_t *)pdu) + : Avtp_Ntscf_GetPayload_V0(pdu); +} + +/** + * Sets the payload of a version 0 NTSCF frame. + * + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @param payload Pointer to the payload byte array. + * @param payload_length Length of the payload. + * @see Avtp_Ntscf_SetPayload + */ +OPEN1722_INLINE void Avtp_Ntscf_SetPayload_V0(Avtp_Ntscf_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_NTSCF_HEADER_LEN_V0, payload, payload_length); +} + +/** + * Sets the payload of a version 1 NTSCF frame. + * + * @param pdu Pointer to the first bit of an 1722 ACF NTSCF PDU. + * @param payload Pointer to the payload byte array. + * @param payload_length Length of the payload. + * @see Avtp_Ntscf_SetPayload + */ +OPEN1722_INLINE void Avtp_Ntscf_SetPayload_V1(Avtp_NtscfV1_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_NTSCF_HEADER_LEN_V1, payload, payload_length); } /** @@ -335,7 +484,12 @@ OPEN1722_INLINE const uint8_t *Avtp_Ntscf_GetPayload(const Avtp_Ntscf_t *const p OPEN1722_INLINE void Avtp_Ntscf_SetPayload(Avtp_Ntscf_t *pdu, uint8_t *payload, uint16_t payload_length) { - memcpy((uint8_t *)pdu + Avtp_Ntscf_GetHeaderLen(pdu), payload, payload_length); + if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Ntscf_SetPayload_V1((Avtp_NtscfV1_t *)pdu, payload, payload_length); + } else { + Avtp_Ntscf_SetPayload_V0(pdu, payload, payload_length); + } } /** @@ -408,6 +562,220 @@ OPEN1722_INLINE void Avtp_Ntscf_InitV1(Avtp_NtscfV1_t *pdu) } } +/* + * Version-typed named accessors. These select the field layout for one + * explicit version and never read the version field; the version-dispatched + * accessors above delegate to them. Alternative header fields delegate to the + * shared Avtp_AlternativeHeader_* variants. See each version-dispatched + * accessor for the full field documentation. + */ + +/** + * Version 0 variant of Avtp_Ntscf_IsSv(). + * @see Avtp_Ntscf_IsSv + */ +OPEN1722_INLINE bool Avtp_Ntscf_IsSv_V0(const Avtp_Ntscf_t *const pdu) +{ + return (bool)Avtp_Ntscf_GetField_V0(pdu, AVTP_NTSCF_FIELD_SV); +} + +/** + * Version 1 variant of Avtp_Ntscf_IsSv(). + * @see Avtp_Ntscf_IsSv + */ +OPEN1722_INLINE bool Avtp_Ntscf_IsSv_V1(const Avtp_NtscfV1_t *const pdu) +{ + return (bool)Avtp_Ntscf_GetField_V1(pdu, AVTP_NTSCF_FIELD_SV); +} + +/** + * Version 0 variant of Avtp_Ntscf_GetNtscfDataLength(). + * @see Avtp_Ntscf_GetNtscfDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Ntscf_GetNtscfDataLength_V0(const Avtp_Ntscf_t *const pdu) +{ + return (uint16_t)Avtp_Ntscf_GetField_V0(pdu, AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH); +} + +/** + * Version 1 variant of Avtp_Ntscf_GetNtscfDataLength(). + * @see Avtp_Ntscf_GetNtscfDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Ntscf_GetNtscfDataLength_V1(const Avtp_NtscfV1_t *const pdu) +{ + return (uint16_t)Avtp_Ntscf_GetField_V1(pdu, AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH); +} + +/** + * Version 0 variant of Avtp_Ntscf_GetSequenceNum(). In version 0 the sequence + * number is the 8-bit sequence_num_lsb field. + * @see Avtp_Ntscf_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Ntscf_GetSequenceNum_V0(const Avtp_Ntscf_t *const pdu) +{ + return (uint32_t)Avtp_Ntscf_GetField_V0(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB); +} + +/** + * Version 1 variant of Avtp_Ntscf_GetSequenceNum(). + * @see Avtp_Ntscf_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Ntscf_GetSequenceNum_V1(const Avtp_NtscfV1_t *const pdu) +{ + return (uint32_t)Avtp_Ntscf_GetField_V1(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM); +} + +/** + * Version 0 variant of Avtp_Ntscf_GetSequenceNumLsb(). + * @see Avtp_Ntscf_GetSequenceNumLsb + */ +OPEN1722_INLINE uint8_t Avtp_Ntscf_GetSequenceNumLsb_V0(const Avtp_Ntscf_t *const pdu) +{ + return (uint8_t)Avtp_Ntscf_GetField_V0(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB); +} + +/** + * Version 1 variant of Avtp_Ntscf_GetSequenceNumLsb(). + * @see Avtp_Ntscf_GetSequenceNumLsb + */ +OPEN1722_INLINE uint8_t Avtp_Ntscf_GetSequenceNumLsb_V1(const Avtp_NtscfV1_t *const pdu) +{ + return (uint8_t)Avtp_Ntscf_GetField_V1(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB); +} + +/** + * Version 0 variant of Avtp_Ntscf_GetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this always returns 0. + * @see Avtp_Ntscf_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Ntscf_GetPtpGrandmasterIdentity_V0(const Avtp_Ntscf_t *const pdu) +{ + return Avtp_AlternativeHeader_GetPtpGrandmasterIdentity_V0( + (const Avtp_AlternativeHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Ntscf_GetPtpGrandmasterIdentity(). + * @see Avtp_Ntscf_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Ntscf_GetPtpGrandmasterIdentity_V1(const Avtp_NtscfV1_t *const pdu) +{ + return Avtp_AlternativeHeader_GetPtpGrandmasterIdentity_V1( + (const Avtp_AlternativeHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Ntscf_GetStreamId(). + * @see Avtp_Ntscf_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Ntscf_GetStreamId_V0(const Avtp_Ntscf_t *const pdu) +{ + return Avtp_Ntscf_GetField_V0(pdu, AVTP_NTSCF_FIELD_STREAM_ID); +} + +/** + * Version 1 variant of Avtp_Ntscf_GetStreamId(). + * @see Avtp_Ntscf_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Ntscf_GetStreamId_V1(const Avtp_NtscfV1_t *const pdu) +{ + return Avtp_Ntscf_GetField_V1(pdu, AVTP_NTSCF_FIELD_STREAM_ID); +} + +/** + * Version 0 variant of Avtp_Ntscf_SetSv(). + * @see Avtp_Ntscf_SetSv + */ +OPEN1722_INLINE void Avtp_Ntscf_SetSv_V0(Avtp_Ntscf_t *pdu, bool sv) +{ + Avtp_Ntscf_SetField_V0(pdu, AVTP_NTSCF_FIELD_SV, sv); +} + +/** + * Version 1 variant of Avtp_Ntscf_SetSv(). + * @see Avtp_Ntscf_SetSv + */ +OPEN1722_INLINE void Avtp_Ntscf_SetSv_V1(Avtp_NtscfV1_t *pdu, bool sv) +{ + Avtp_Ntscf_SetField_V1(pdu, AVTP_NTSCF_FIELD_SV, sv); +} + +/** + * Version 0 variant of Avtp_Ntscf_SetNtscfDataLength(). + * @see Avtp_Ntscf_SetNtscfDataLength + */ +OPEN1722_INLINE void Avtp_Ntscf_SetNtscfDataLength_V0(Avtp_Ntscf_t *pdu, uint16_t value) +{ + Avtp_Ntscf_SetField_V0(pdu, AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH, value); +} + +/** + * Version 1 variant of Avtp_Ntscf_SetNtscfDataLength(). + * @see Avtp_Ntscf_SetNtscfDataLength + */ +OPEN1722_INLINE void Avtp_Ntscf_SetNtscfDataLength_V1(Avtp_NtscfV1_t *pdu, uint16_t value) +{ + Avtp_Ntscf_SetField_V1(pdu, AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH, value); +} + +/** + * Version 0 variant of Avtp_Ntscf_SetSequenceNum(). The value is truncated to + * the 8-bit version 0 sequence_num_lsb field. + * @see Avtp_Ntscf_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Ntscf_SetSequenceNum_V0(Avtp_Ntscf_t *pdu, uint32_t value) +{ + Avtp_Ntscf_SetField_V0(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); +} + +/** + * Version 1 variant of Avtp_Ntscf_SetSequenceNum(). The eight least significant + * bits are also written to the sequence_num_lsb copy (NTSCF-6). + * @see Avtp_Ntscf_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Ntscf_SetSequenceNum_V1(Avtp_NtscfV1_t *pdu, uint32_t value) +{ + Avtp_Ntscf_SetField_V1(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM, value); + Avtp_Ntscf_SetField_V1(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); +} + +/** + * Version 0 variant of Avtp_Ntscf_SetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this is a no-op. + * @see Avtp_Ntscf_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Ntscf_SetPtpGrandmasterIdentity_V0(Avtp_Ntscf_t *pdu, uint64_t value) +{ + Avtp_AlternativeHeader_SetPtpGrandmasterIdentity_V0((Avtp_AlternativeHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Ntscf_SetPtpGrandmasterIdentity(). + * @see Avtp_Ntscf_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Ntscf_SetPtpGrandmasterIdentity_V1(Avtp_NtscfV1_t *pdu, uint64_t value) +{ + Avtp_AlternativeHeader_SetPtpGrandmasterIdentity_V1((Avtp_AlternativeHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Ntscf_SetStreamId(). + * @see Avtp_Ntscf_SetStreamId + */ +OPEN1722_INLINE void Avtp_Ntscf_SetStreamId_V0(Avtp_Ntscf_t *pdu, uint64_t value) +{ + Avtp_Ntscf_SetField_V0(pdu, AVTP_NTSCF_FIELD_STREAM_ID, value); +} + +/** + * Version 1 variant of Avtp_Ntscf_SetStreamId(). + * @see Avtp_Ntscf_SetStreamId + */ +OPEN1722_INLINE void Avtp_Ntscf_SetStreamId_V1(Avtp_NtscfV1_t *pdu, uint64_t value) +{ + Avtp_Ntscf_SetField_V1(pdu, AVTP_NTSCF_FIELD_STREAM_ID, value); +} + #ifdef __cplusplus } #endif diff --git a/include/avtp/acf/Tscf.h b/include/avtp/acf/Tscf.h index 0e5f54d9..8c686944 100644 --- a/include/avtp/acf/Tscf.h +++ b/include/avtp/acf/Tscf.h @@ -146,43 +146,133 @@ static const Avtp_FieldDescriptor_t Avtp_TscfFieldDescV1[AVTP_TSCF_FIELD_MAX] = }; /** - * Returns the value of an AVTP TSCF field as specified in the IEEE 1722 Specification. + * Returns the value of an AVTP TSCF field as laid out by version 0. No version + * dispatch is performed. * * @param pdu Pointer to the first bit of an 1722 AVTP TSCF PDU. * @param field Specifies the position of the data field to be read * @returns This function returns the value of the field. + * @see Avtp_Tscf_GetField */ -OPEN1722_INLINE uint64_t Avtp_Tscf_GetField(const Avtp_Tscf_t *const pdu, Avtp_TscfFields_t field) +OPEN1722_INLINE uint64_t Avtp_Tscf_GetField_V0(const Avtp_Tscf_t *const pdu, + Avtp_TscfFields_t field) +{ + return Avtp_GetField(Avtp_TscfFieldDescV0, AVTP_TSCF_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP TSCF field as laid out by version 1. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AVTP TSCF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Tscf_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Tscf_GetField_V1(const Avtp_TscfV1_t *const pdu, + Avtp_TscfFields_t field) { - const Avtp_FieldDescriptor_t *desc = - Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_TscfFieldDescV1 - : Avtp_TscfFieldDescV0; - return Avtp_GetField(desc, AVTP_TSCF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); + return Avtp_GetField(Avtp_TscfFieldDescV1, AVTP_TSCF_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); } /** - * Sets the value of an AVTP TSCF field as specified in the IEEE 1722 Specification. + * Returns the value of an AVTP TSCF field, dispatching on the version field of + * the PDU. * * @param pdu Pointer to the first bit of an 1722 AVTP TSCF PDU. * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + */ +OPEN1722_INLINE uint64_t Avtp_Tscf_GetField(const Avtp_Tscf_t *const pdu, Avtp_TscfFields_t field) +{ + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Tscf_GetField_V1((const Avtp_TscfV1_t *)pdu, field) + : Avtp_Tscf_GetField_V0(pdu, field); +} + +/** + * Sets the value of an AVTP TSCF field as laid out by version 0. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AVTP TSCF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Tscf_SetField + */ +OPEN1722_INLINE void Avtp_Tscf_SetField_V0(Avtp_Tscf_t *pdu, Avtp_TscfFields_t field, + uint64_t value) +{ + Avtp_SetField(Avtp_TscfFieldDescV0, AVTP_TSCF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Sets the value of an AVTP TSCF field as laid out by version 1. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 AVTP TSCF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Tscf_SetField + */ +OPEN1722_INLINE void Avtp_Tscf_SetField_V1(Avtp_TscfV1_t *pdu, Avtp_TscfFields_t field, + uint64_t value) +{ + Avtp_SetField(Avtp_TscfFieldDescV1, AVTP_TSCF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Sets the value of an AVTP TSCF field, dispatching on the version field of the + * PDU. + * + * @param pdu Pointer to the first bit of an 1722 AVTP TSCF PDU. + * @param field Specifies the position of the data field to be written * @param value The value to set. */ OPEN1722_INLINE void Avtp_Tscf_SetField(Avtp_Tscf_t *pdu, Avtp_TscfFields_t field, uint64_t value) { - const Avtp_FieldDescriptor_t *desc = - Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_TscfFieldDescV1 - : Avtp_TscfFieldDescV0; - Avtp_SetField(desc, AVTP_TSCF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); + if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Tscf_SetField_V1((Avtp_TscfV1_t *)pdu, field, value); + } else { + Avtp_Tscf_SetField_V0(pdu, field, value); + } +} + +/** + * Returns the length of the version 0 TSCF header in octets (24). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Tscf_GetHeaderLen_V0(const Avtp_Tscf_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_TSCF_HEADER_LEN_V0; +} + +/** + * Returns the length of the version 1 TSCF header in octets (40). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Tscf_GetHeaderLen_V1(const Avtp_TscfV1_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_TSCF_HEADER_LEN_V1; } /** - * Returns the length of the TSCF header in octets (24 or 40). + * Returns the length of the TSCF header in octets (24 or 40), dispatching on + * the version field of the PDU. */ OPEN1722_INLINE uint8_t Avtp_Tscf_GetHeaderLen(const Avtp_Tscf_t *const pdu) { - return Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Tscf_GetHeaderLen_V1((const Avtp_TscfV1_t *)pdu) + : Avtp_Tscf_GetHeaderLen_V0(pdu); } /** @@ -252,11 +342,10 @@ OPEN1722_INLINE uint32_t Avtp_Tscf_GetSequenceNum(const Avtp_Tscf_t *const pdu) */ OPEN1722_INLINE uint8_t Avtp_Tscf_GetSequenceNumLsb(const Avtp_Tscf_t *const pdu) { - if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1) { - return (uint8_t)Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_FSD0); - } - return (uint8_t)Avtp_Tscf_GetField(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? (uint8_t)Avtp_Tscf_GetField_V1((const Avtp_TscfV1_t *)pdu, AVTP_TSCF_FIELD_FSD0) + : (uint8_t)Avtp_Tscf_GetField_V0(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM); } /** @@ -360,10 +449,12 @@ OPEN1722_INLINE void Avtp_Tscf_SetTu(Avtp_Tscf_t *pdu, bool tu) */ OPEN1722_INLINE void Avtp_Tscf_SetSequenceNum(Avtp_Tscf_t *pdu, uint32_t value) { - Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM, value); if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1) { - Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_FSD0, (uint8_t)(value & 0xFFU)); + Avtp_Tscf_SetField_V1((Avtp_TscfV1_t *)pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM, value); + Avtp_Tscf_SetField_V1((Avtp_TscfV1_t *)pdu, AVTP_TSCF_FIELD_FSD0, (uint8_t)(value & 0xFFU)); + } else { + Avtp_Tscf_SetField_V0(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM, value); } } @@ -413,6 +504,30 @@ OPEN1722_INLINE void Avtp_Tscf_SetStreamDataLength(Avtp_Tscf_t *pdu, uint16_t va Avtp_Tscf_SetField(pdu, AVTP_TSCF_FIELD_STREAM_DATA_LENGTH, value); } +/** + * Returns a pointer to the payload of a version 0 TSCF frame. + * + * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. + * @return Pointer to the TSCF frame payload. + * @see Avtp_Tscf_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Tscf_GetPayload_V0(const Avtp_Tscf_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_TSCF_HEADER_LEN_V0; +} + +/** + * Returns a pointer to the payload of a version 1 TSCF frame. + * + * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. + * @return Pointer to the TSCF frame payload. + * @see Avtp_Tscf_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Tscf_GetPayload_V1(const Avtp_TscfV1_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_TSCF_HEADER_LEN_V1; +} + /** * Returns a pointer to the payload of a TSCF frame. The payload starts after * the version-dependent common stream header. @@ -422,8 +537,38 @@ OPEN1722_INLINE void Avtp_Tscf_SetStreamDataLength(Avtp_Tscf_t *pdu, uint16_t va */ OPEN1722_INLINE const uint8_t *Avtp_Tscf_GetPayload(const Avtp_Tscf_t *const pdu) { - return (const uint8_t *)pdu + - Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Tscf_GetPayload_V1((const Avtp_TscfV1_t *)pdu) + : Avtp_Tscf_GetPayload_V0(pdu); +} + +/** + * Sets the payload of a version 0 TSCF frame. + * + * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. + * @param payload Pointer to the payload byte array. + * @param payload_length Length of the payload. + * @see Avtp_Tscf_SetPayload + */ +OPEN1722_INLINE void Avtp_Tscf_SetPayload_V0(Avtp_Tscf_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_TSCF_HEADER_LEN_V0, payload, payload_length); +} + +/** + * Sets the payload of a version 1 TSCF frame. + * + * @param pdu Pointer to the first bit of an 1722 ACF TSCF PDU. + * @param payload Pointer to the payload byte array. + * @param payload_length Length of the payload. + * @see Avtp_Tscf_SetPayload + */ +OPEN1722_INLINE void Avtp_Tscf_SetPayload_V1(Avtp_TscfV1_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_TSCF_HEADER_LEN_V1, payload, payload_length); } /** @@ -436,9 +581,12 @@ OPEN1722_INLINE const uint8_t *Avtp_Tscf_GetPayload(const Avtp_Tscf_t *const pdu OPEN1722_INLINE void Avtp_Tscf_SetPayload(Avtp_Tscf_t *pdu, uint8_t *payload, uint16_t payload_length) { - memcpy((uint8_t *)pdu + - Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu), - payload, payload_length); + if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Tscf_SetPayload_V1((Avtp_TscfV1_t *)pdu, payload, payload_length); + } else { + Avtp_Tscf_SetPayload_V0(pdu, payload, payload_length); + } } /** @@ -511,6 +659,367 @@ OPEN1722_INLINE void Avtp_Tscf_InitV1(Avtp_TscfV1_t *pdu) } } +/* + * Version-typed named accessors. These select the field layout for one + * explicit version and never read the version field; the version-dispatched + * accessors above delegate to them. Common stream header fields delegate to + * the shared Avtp_CommonStreamHeader_* variants. See each version-dispatched + * accessor for the full field documentation. + */ + +/** + * Version 0 variant of Avtp_Tscf_IsSv(). + * @see Avtp_Tscf_IsSv + */ +OPEN1722_INLINE bool Avtp_Tscf_IsSv_V0(const Avtp_Tscf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsSv_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Tscf_IsSv(). + * @see Avtp_Tscf_IsSv + */ +OPEN1722_INLINE bool Avtp_Tscf_IsSv_V1(const Avtp_TscfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsSv_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Tscf_IsMr(). + * @see Avtp_Tscf_IsMr + */ +OPEN1722_INLINE bool Avtp_Tscf_IsMr_V0(const Avtp_Tscf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsMr_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Tscf_IsMr(). + * @see Avtp_Tscf_IsMr + */ +OPEN1722_INLINE bool Avtp_Tscf_IsMr_V1(const Avtp_TscfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsMr_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Tscf_IsTv(). + * @see Avtp_Tscf_IsTv + */ +OPEN1722_INLINE bool Avtp_Tscf_IsTv_V0(const Avtp_Tscf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTv_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Tscf_IsTv(). + * @see Avtp_Tscf_IsTv + */ +OPEN1722_INLINE bool Avtp_Tscf_IsTv_V1(const Avtp_TscfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTv_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Tscf_IsTu(). + * @see Avtp_Tscf_IsTu + */ +OPEN1722_INLINE bool Avtp_Tscf_IsTu_V0(const Avtp_Tscf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTu_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Tscf_IsTu(). + * @see Avtp_Tscf_IsTu + */ +OPEN1722_INLINE bool Avtp_Tscf_IsTu_V1(const Avtp_TscfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTu_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Tscf_GetSequenceNum(). + * @see Avtp_Tscf_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Tscf_GetSequenceNum_V0(const Avtp_Tscf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetSequenceNum_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Tscf_GetSequenceNum(). + * @see Avtp_Tscf_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Tscf_GetSequenceNum_V1(const Avtp_TscfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetSequenceNum_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Tscf_GetSequenceNumLsb(). In version 0 this is the + * 8-bit sequence_num field. + * @see Avtp_Tscf_GetSequenceNumLsb + */ +OPEN1722_INLINE uint8_t Avtp_Tscf_GetSequenceNumLsb_V0(const Avtp_Tscf_t *const pdu) +{ + return (uint8_t)Avtp_Tscf_GetField_V0(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM); +} + +/** + * Version 1 variant of Avtp_Tscf_GetSequenceNumLsb(). In version 1 this is the + * copy of the eight least significant bits of sequence_num stored in + * format_specific_data_0 (TSCF-4). + * @see Avtp_Tscf_GetSequenceNumLsb + */ +OPEN1722_INLINE uint8_t Avtp_Tscf_GetSequenceNumLsb_V1(const Avtp_TscfV1_t *const pdu) +{ + return (uint8_t)Avtp_Tscf_GetField_V1(pdu, AVTP_TSCF_FIELD_FSD0); +} + +/** + * Version 0 variant of Avtp_Tscf_GetStreamId(). + * @see Avtp_Tscf_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Tscf_GetStreamId_V0(const Avtp_Tscf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamId_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Tscf_GetStreamId(). + * @see Avtp_Tscf_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Tscf_GetStreamId_V1(const Avtp_TscfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamId_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Tscf_GetAvtpTimestamp(). + * @see Avtp_Tscf_GetAvtpTimestamp + */ +OPEN1722_INLINE uint64_t Avtp_Tscf_GetAvtpTimestamp_V0(const Avtp_Tscf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetAvtpTimestamp_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Tscf_GetAvtpTimestamp(). + * @see Avtp_Tscf_GetAvtpTimestamp + */ +OPEN1722_INLINE uint64_t Avtp_Tscf_GetAvtpTimestamp_V1(const Avtp_TscfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetAvtpTimestamp_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Tscf_GetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this always returns 0. + * @see Avtp_Tscf_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Tscf_GetPtpGrandmasterIdentity_V0(const Avtp_Tscf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V0( + (const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Tscf_GetPtpGrandmasterIdentity(). + * @see Avtp_Tscf_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Tscf_GetPtpGrandmasterIdentity_V1(const Avtp_TscfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V1( + (const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Tscf_GetStreamDataLength(). + * @see Avtp_Tscf_GetStreamDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Tscf_GetStreamDataLength_V0(const Avtp_Tscf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamDataLength_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Tscf_GetStreamDataLength(). + * @see Avtp_Tscf_GetStreamDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Tscf_GetStreamDataLength_V1(const Avtp_TscfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamDataLength_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Tscf_SetSv(). + * @see Avtp_Tscf_SetSv + */ +OPEN1722_INLINE void Avtp_Tscf_SetSv_V0(Avtp_Tscf_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetSv_V0((Avtp_CommonStreamHeader_t *)pdu, sv); +} + +/** + * Version 1 variant of Avtp_Tscf_SetSv(). + * @see Avtp_Tscf_SetSv + */ +OPEN1722_INLINE void Avtp_Tscf_SetSv_V1(Avtp_TscfV1_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetSv_V1((Avtp_CommonStreamHeader_t *)pdu, sv); +} + +/** + * Version 0 variant of Avtp_Tscf_SetMr(). + * @see Avtp_Tscf_SetMr + */ +OPEN1722_INLINE void Avtp_Tscf_SetMr_V0(Avtp_Tscf_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetMr_V0((Avtp_CommonStreamHeader_t *)pdu, mr); +} + +/** + * Version 1 variant of Avtp_Tscf_SetMr(). + * @see Avtp_Tscf_SetMr + */ +OPEN1722_INLINE void Avtp_Tscf_SetMr_V1(Avtp_TscfV1_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetMr_V1((Avtp_CommonStreamHeader_t *)pdu, mr); +} + +/** + * Version 0 variant of Avtp_Tscf_SetTv(). + * @see Avtp_Tscf_SetTv + */ +OPEN1722_INLINE void Avtp_Tscf_SetTv_V0(Avtp_Tscf_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetTv_V0((Avtp_CommonStreamHeader_t *)pdu, tv); +} + +/** + * Version 1 variant of Avtp_Tscf_SetTv(). + * @see Avtp_Tscf_SetTv + */ +OPEN1722_INLINE void Avtp_Tscf_SetTv_V1(Avtp_TscfV1_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetTv_V1((Avtp_CommonStreamHeader_t *)pdu, tv); +} + +/** + * Version 0 variant of Avtp_Tscf_SetTu(). + * @see Avtp_Tscf_SetTu + */ +OPEN1722_INLINE void Avtp_Tscf_SetTu_V0(Avtp_Tscf_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetTu_V0((Avtp_CommonStreamHeader_t *)pdu, tu); +} + +/** + * Version 1 variant of Avtp_Tscf_SetTu(). + * @see Avtp_Tscf_SetTu + */ +OPEN1722_INLINE void Avtp_Tscf_SetTu_V1(Avtp_TscfV1_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetTu_V1((Avtp_CommonStreamHeader_t *)pdu, tu); +} + +/** + * Version 0 variant of Avtp_Tscf_SetSequenceNum(). Values are truncated to the + * 8-bit version 0 sequence_num field. + * @see Avtp_Tscf_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Tscf_SetSequenceNum_V0(Avtp_Tscf_t *pdu, uint32_t value) +{ + Avtp_Tscf_SetField_V0(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM, value); +} + +/** + * Version 1 variant of Avtp_Tscf_SetSequenceNum(). The eight least significant + * bits are also written to the sequence_num_lsb copy in format_specific_data_0 + * (TSCF-4). + * @see Avtp_Tscf_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Tscf_SetSequenceNum_V1(Avtp_TscfV1_t *pdu, uint32_t value) +{ + Avtp_Tscf_SetField_V1(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM, value); + Avtp_Tscf_SetField_V1(pdu, AVTP_TSCF_FIELD_FSD0, (uint8_t)(value & 0xFFU)); +} + +/** + * Version 0 variant of Avtp_Tscf_SetStreamId(). + * @see Avtp_Tscf_SetStreamId + */ +OPEN1722_INLINE void Avtp_Tscf_SetStreamId_V0(Avtp_Tscf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetStreamId_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Tscf_SetStreamId(). + * @see Avtp_Tscf_SetStreamId + */ +OPEN1722_INLINE void Avtp_Tscf_SetStreamId_V1(Avtp_TscfV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetStreamId_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Tscf_SetAvtpTimestamp(). + * @see Avtp_Tscf_SetAvtpTimestamp + */ +OPEN1722_INLINE void Avtp_Tscf_SetAvtpTimestamp_V0(Avtp_Tscf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetAvtpTimestamp_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Tscf_SetAvtpTimestamp(). + * @see Avtp_Tscf_SetAvtpTimestamp + */ +OPEN1722_INLINE void Avtp_Tscf_SetAvtpTimestamp_V1(Avtp_TscfV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetAvtpTimestamp_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Tscf_SetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this is a no-op. + * @see Avtp_Tscf_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Tscf_SetPtpGrandmasterIdentity_V0(Avtp_Tscf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Tscf_SetPtpGrandmasterIdentity(). + * @see Avtp_Tscf_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Tscf_SetPtpGrandmasterIdentity_V1(Avtp_TscfV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Tscf_SetStreamDataLength(). + * @see Avtp_Tscf_SetStreamDataLength + */ +OPEN1722_INLINE void Avtp_Tscf_SetStreamDataLength_V0(Avtp_Tscf_t *pdu, uint16_t value) +{ + Avtp_CommonStreamHeader_SetStreamDataLength_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Tscf_SetStreamDataLength(). + * @see Avtp_Tscf_SetStreamDataLength + */ +OPEN1722_INLINE void Avtp_Tscf_SetStreamDataLength_V1(Avtp_TscfV1_t *pdu, uint16_t value) +{ + Avtp_CommonStreamHeader_SetStreamDataLength_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + #ifdef __cplusplus } #endif diff --git a/include/avtp/cvf/Cvf.h b/include/avtp/cvf/Cvf.h index 2a5f7dfb..ddea512b 100644 --- a/include/avtp/cvf/Cvf.h +++ b/include/avtp/cvf/Cvf.h @@ -182,7 +182,38 @@ static const Avtp_FieldDescriptor_t Avtp_CvfFieldDescV1[AVTP_CVF_FIELD_MAX] = { }; /** - * Returns the value of an AVTP CVF field as specified in the IEEE 1722 Specification. + * Returns the value of an AVTP CVF field as laid out by version 0. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 CVF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Cvf_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Cvf_GetField_V0(const Avtp_Cvf_t *const pdu, Avtp_CvfFields_t field) +{ + return Avtp_GetField(Avtp_CvfFieldDescV0, AVTP_CVF_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP CVF field as laid out by version 1. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 CVF PDU. + * @param field Specifies the position of the data field to be read + * @returns This function returns the value of the field. + * @see Avtp_Cvf_GetField + */ +OPEN1722_INLINE uint64_t Avtp_Cvf_GetField_V1(const Avtp_CvfV1_t *const pdu, Avtp_CvfFields_t field) +{ + return Avtp_GetField(Avtp_CvfFieldDescV1, AVTP_CVF_FIELD_MAX, (const uint8_t *)pdu, + (uint8_t)field); +} + +/** + * Returns the value of an AVTP CVF field, dispatching on the version field of + * the PDU. * * @param pdu Pointer to the first bit of an 1722 CVF PDU. * @param field Specifies the position of the data field to be read @@ -190,15 +221,43 @@ static const Avtp_FieldDescriptor_t Avtp_CvfFieldDescV1[AVTP_CVF_FIELD_MAX] = { */ OPEN1722_INLINE uint64_t Avtp_Cvf_GetField(const Avtp_Cvf_t *const pdu, Avtp_CvfFields_t field) { - const Avtp_FieldDescriptor_t *desc = - Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_CvfFieldDescV1 - : Avtp_CvfFieldDescV0; - return Avtp_GetField(desc, AVTP_CVF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Cvf_GetField_V1((const Avtp_CvfV1_t *)pdu, field) + : Avtp_Cvf_GetField_V0(pdu, field); +} + +/** + * Sets the value of an AVTP CVF field as laid out by version 0. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 CVF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Cvf_SetField + */ +OPEN1722_INLINE void Avtp_Cvf_SetField_V0(Avtp_Cvf_t *pdu, Avtp_CvfFields_t field, uint64_t value) +{ + Avtp_SetField(Avtp_CvfFieldDescV0, AVTP_CVF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); } /** - * Sets the value of an AVTP CVF field as specified in the IEEE 1722 Specification. + * Sets the value of an AVTP CVF field as laid out by version 1. No version + * dispatch is performed. + * + * @param pdu Pointer to the first bit of an 1722 CVF PDU. + * @param field Specifies the position of the data field to be written + * @param value The value to set. + * @see Avtp_Cvf_SetField + */ +OPEN1722_INLINE void Avtp_Cvf_SetField_V1(Avtp_CvfV1_t *pdu, Avtp_CvfFields_t field, uint64_t value) +{ + Avtp_SetField(Avtp_CvfFieldDescV1, AVTP_CVF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); +} + +/** + * Sets the value of an AVTP CVF field, dispatching on the version field of the + * PDU. * * @param pdu Pointer to the first bit of an 1722 CVF PDU. * @param field Specifies the position of the data field to be written @@ -206,19 +265,46 @@ OPEN1722_INLINE uint64_t Avtp_Cvf_GetField(const Avtp_Cvf_t *const pdu, Avtp_Cvf */ OPEN1722_INLINE void Avtp_Cvf_SetField(Avtp_Cvf_t *pdu, Avtp_CvfFields_t field, uint64_t value) { - const Avtp_FieldDescriptor_t *desc = - Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == AVTP_VERSION_1 - ? Avtp_CvfFieldDescV1 - : Avtp_CvfFieldDescV0; - Avtp_SetField(desc, AVTP_CVF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); + if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Cvf_SetField_V1((Avtp_CvfV1_t *)pdu, field, value); + } else { + Avtp_Cvf_SetField_V0(pdu, field, value); + } +} + +/** + * Returns the length of the version 0 CVF header in octets (24). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Cvf_GetHeaderLen_V0(const Avtp_Cvf_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_CVF_HEADER_LEN_V0; +} + +/** + * Returns the length of the version 1 CVF header in octets (40). The PDU + * pointer is not read; it keeps the signature aligned with the + * version-dispatched accessors. + */ +OPEN1722_INLINE uint8_t Avtp_Cvf_GetHeaderLen_V1(const Avtp_CvfV1_t *const pdu) +{ + (void)pdu; + return (uint8_t)AVTP_CVF_HEADER_LEN_V1; } /** - * Returns the length of the CVF header in octets (24 or 40). + * Returns the length of the CVF header in octets (24 or 40), dispatching on the + * version field of the PDU. */ OPEN1722_INLINE uint8_t Avtp_Cvf_GetHeaderLen(const Avtp_Cvf_t *const pdu) { - return Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)pdu); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Cvf_GetHeaderLen_V1((const Avtp_CvfV1_t *)pdu) + : Avtp_Cvf_GetHeaderLen_V0(pdu); } /** @@ -542,6 +628,30 @@ OPEN1722_INLINE void Avtp_Cvf_SetEvt(Avtp_Cvf_t *pdu, uint8_t value) Avtp_Cvf_SetField(pdu, AVTP_CVF_FIELD_EVT, value); } +/** + * Returns a pointer to the stream data of a version 0 CVF frame. + * + * @param pdu Pointer to the first bit of an 1722 CVF PDU. + * @return Pointer to CVF stream data + * @see Avtp_Cvf_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Cvf_GetPayload_V0(const Avtp_Cvf_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_CVF_HEADER_LEN_V0; +} + +/** + * Returns a pointer to the stream data of a version 1 CVF frame. + * + * @param pdu Pointer to the first bit of an 1722 CVF PDU. + * @return Pointer to CVF stream data + * @see Avtp_Cvf_GetPayload + */ +OPEN1722_INLINE const uint8_t *Avtp_Cvf_GetPayload_V1(const Avtp_CvfV1_t *const pdu) +{ + return (const uint8_t *)pdu + AVTP_CVF_HEADER_LEN_V1; +} + /** * Returns pointer to the CVF stream data. The stream data starts after the * version-dependent common stream header. @@ -554,7 +664,38 @@ OPEN1722_INLINE void Avtp_Cvf_SetEvt(Avtp_Cvf_t *pdu, uint8_t value) */ OPEN1722_INLINE const uint8_t *Avtp_Cvf_GetPayload(const Avtp_Cvf_t *const pdu) { - return (const uint8_t *)pdu + Avtp_Cvf_GetHeaderLen(pdu); + return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1 + ? Avtp_Cvf_GetPayload_V1((const Avtp_CvfV1_t *)pdu) + : Avtp_Cvf_GetPayload_V0(pdu); +} + +/** + * Sets the stream data of a version 0 CVF frame. + * + * @param pdu Pointer to the first bit of an 1722 CVF PDU. + * @param payload Pointer to the payload byte array + * @param payload_length Length of the payload + * @see Avtp_Cvf_SetPayload + */ +OPEN1722_INLINE void Avtp_Cvf_SetPayload_V0(Avtp_Cvf_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_CVF_HEADER_LEN_V0, payload, payload_length); +} + +/** + * Sets the stream data of a version 1 CVF frame. + * + * @param pdu Pointer to the first bit of an 1722 CVF PDU. + * @param payload Pointer to the payload byte array + * @param payload_length Length of the payload + * @see Avtp_Cvf_SetPayload + */ +OPEN1722_INLINE void Avtp_Cvf_SetPayload_V1(Avtp_CvfV1_t *pdu, uint8_t *payload, + uint16_t payload_length) +{ + memcpy((uint8_t *)pdu + AVTP_CVF_HEADER_LEN_V1, payload, payload_length); } /** @@ -566,7 +707,12 @@ OPEN1722_INLINE const uint8_t *Avtp_Cvf_GetPayload(const Avtp_Cvf_t *const pdu) */ OPEN1722_INLINE void Avtp_Cvf_SetPayload(Avtp_Cvf_t *pdu, uint8_t *payload, uint16_t payload_length) { - memcpy((uint8_t *)pdu + Avtp_Cvf_GetHeaderLen(pdu), payload, payload_length); + if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == + AVTP_VERSION_1) { + Avtp_Cvf_SetPayload_V1((Avtp_CvfV1_t *)pdu, payload, payload_length); + } else { + Avtp_Cvf_SetPayload_V0(pdu, payload, payload_length); + } } /** @@ -642,6 +788,524 @@ OPEN1722_INLINE bool Avtp_Cvf_IsValid(const Avtp_Cvf_t *const pdu, size_t buffer return true; } +/* + * Version-typed named accessors. These select the field layout for one + * explicit version and never read the version field; the version-dispatched + * accessors above delegate to them. Common stream header fields delegate to + * the shared Avtp_CommonStreamHeader_* variants. See each version-dispatched + * accessor for the full field documentation. + */ + +/** + * Version 0 variant of Avtp_Cvf_IsSv(). + * @see Avtp_Cvf_IsSv + */ +OPEN1722_INLINE bool Avtp_Cvf_IsSv_V0(const Avtp_Cvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsSv_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Cvf_IsSv(). + * @see Avtp_Cvf_IsSv + */ +OPEN1722_INLINE bool Avtp_Cvf_IsSv_V1(const Avtp_CvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsSv_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Cvf_IsMr(). + * @see Avtp_Cvf_IsMr + */ +OPEN1722_INLINE bool Avtp_Cvf_IsMr_V0(const Avtp_Cvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsMr_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Cvf_IsMr(). + * @see Avtp_Cvf_IsMr + */ +OPEN1722_INLINE bool Avtp_Cvf_IsMr_V1(const Avtp_CvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsMr_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Cvf_IsTv(). + * @see Avtp_Cvf_IsTv + */ +OPEN1722_INLINE bool Avtp_Cvf_IsTv_V0(const Avtp_Cvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTv_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Cvf_IsTv(). + * @see Avtp_Cvf_IsTv + */ +OPEN1722_INLINE bool Avtp_Cvf_IsTv_V1(const Avtp_CvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTv_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Cvf_IsTu(). + * @see Avtp_Cvf_IsTu + */ +OPEN1722_INLINE bool Avtp_Cvf_IsTu_V0(const Avtp_Cvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTu_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Cvf_IsTu(). + * @see Avtp_Cvf_IsTu + */ +OPEN1722_INLINE bool Avtp_Cvf_IsTu_V1(const Avtp_CvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_IsTu_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Cvf_GetSequenceNum(). Values are truncated to the + * 8-bit version 0 field width. + * @see Avtp_Cvf_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Cvf_GetSequenceNum_V0(const Avtp_Cvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetSequenceNum_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Cvf_GetSequenceNum(). + * @see Avtp_Cvf_GetSequenceNum + */ +OPEN1722_INLINE uint32_t Avtp_Cvf_GetSequenceNum_V1(const Avtp_CvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetSequenceNum_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Cvf_GetStreamId(). + * @see Avtp_Cvf_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Cvf_GetStreamId_V0(const Avtp_Cvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamId_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Cvf_GetStreamId(). + * @see Avtp_Cvf_GetStreamId + */ +OPEN1722_INLINE uint64_t Avtp_Cvf_GetStreamId_V1(const Avtp_CvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamId_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Cvf_GetAvtpTimestamp(). + * @see Avtp_Cvf_GetAvtpTimestamp + */ +OPEN1722_INLINE uint64_t Avtp_Cvf_GetAvtpTimestamp_V0(const Avtp_Cvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetAvtpTimestamp_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Cvf_GetAvtpTimestamp(). + * @see Avtp_Cvf_GetAvtpTimestamp + */ +OPEN1722_INLINE uint64_t Avtp_Cvf_GetAvtpTimestamp_V1(const Avtp_CvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetAvtpTimestamp_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Cvf_GetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this always returns 0. + * @see Avtp_Cvf_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Cvf_GetPtpGrandmasterIdentity_V0(const Avtp_Cvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V0( + (const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Cvf_GetPtpGrandmasterIdentity(). + * @see Avtp_Cvf_GetPtpGrandmasterIdentity + */ +OPEN1722_INLINE uint64_t Avtp_Cvf_GetPtpGrandmasterIdentity_V1(const Avtp_CvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V1( + (const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Cvf_GetFormat(). + * @see Avtp_Cvf_GetFormat + */ +OPEN1722_INLINE Avtp_CvfFormat_t Avtp_Cvf_GetFormat_V0(const Avtp_Cvf_t *const pdu) +{ + return (Avtp_CvfFormat_t)Avtp_Cvf_GetField_V0(pdu, AVTP_CVF_FIELD_FORMAT); +} + +/** + * Version 1 variant of Avtp_Cvf_GetFormat(). + * @see Avtp_Cvf_GetFormat + */ +OPEN1722_INLINE Avtp_CvfFormat_t Avtp_Cvf_GetFormat_V1(const Avtp_CvfV1_t *const pdu) +{ + return (Avtp_CvfFormat_t)Avtp_Cvf_GetField_V1(pdu, AVTP_CVF_FIELD_FORMAT); +} + +/** + * Version 0 variant of Avtp_Cvf_GetFormatSubtype(). + * @see Avtp_Cvf_GetFormatSubtype + */ +OPEN1722_INLINE Avtp_CvfFormatSubtype_t Avtp_Cvf_GetFormatSubtype_V0(const Avtp_Cvf_t *const pdu) +{ + return (Avtp_CvfFormatSubtype_t)Avtp_Cvf_GetField_V0(pdu, AVTP_CVF_FIELD_FORMAT_SUBTYPE); +} + +/** + * Version 1 variant of Avtp_Cvf_GetFormatSubtype(). + * @see Avtp_Cvf_GetFormatSubtype + */ +OPEN1722_INLINE Avtp_CvfFormatSubtype_t Avtp_Cvf_GetFormatSubtype_V1(const Avtp_CvfV1_t *const pdu) +{ + return (Avtp_CvfFormatSubtype_t)Avtp_Cvf_GetField_V1(pdu, AVTP_CVF_FIELD_FORMAT_SUBTYPE); +} + +/** + * Version 0 variant of Avtp_Cvf_GetStreamDataLength(). + * @see Avtp_Cvf_GetStreamDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Cvf_GetStreamDataLength_V0(const Avtp_Cvf_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamDataLength_V0((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 1 variant of Avtp_Cvf_GetStreamDataLength(). + * @see Avtp_Cvf_GetStreamDataLength + */ +OPEN1722_INLINE uint16_t Avtp_Cvf_GetStreamDataLength_V1(const Avtp_CvfV1_t *const pdu) +{ + return Avtp_CommonStreamHeader_GetStreamDataLength_V1((const Avtp_CommonStreamHeader_t *)pdu); +} + +/** + * Version 0 variant of Avtp_Cvf_IsPtv(). + * @see Avtp_Cvf_IsPtv + */ +OPEN1722_INLINE bool Avtp_Cvf_IsPtv_V0(const Avtp_Cvf_t *const pdu) +{ + return (bool)Avtp_Cvf_GetField_V0(pdu, AVTP_CVF_FIELD_PTV); +} + +/** + * Version 1 variant of Avtp_Cvf_IsPtv(). + * @see Avtp_Cvf_IsPtv + */ +OPEN1722_INLINE bool Avtp_Cvf_IsPtv_V1(const Avtp_CvfV1_t *const pdu) +{ + return (bool)Avtp_Cvf_GetField_V1(pdu, AVTP_CVF_FIELD_PTV); +} + +/** + * Version 0 variant of Avtp_Cvf_IsM(). + * @see Avtp_Cvf_IsM + */ +OPEN1722_INLINE bool Avtp_Cvf_IsM_V0(const Avtp_Cvf_t *const pdu) +{ + return (bool)Avtp_Cvf_GetField_V0(pdu, AVTP_CVF_FIELD_M); +} + +/** + * Version 1 variant of Avtp_Cvf_IsM(). + * @see Avtp_Cvf_IsM + */ +OPEN1722_INLINE bool Avtp_Cvf_IsM_V1(const Avtp_CvfV1_t *const pdu) +{ + return (bool)Avtp_Cvf_GetField_V1(pdu, AVTP_CVF_FIELD_M); +} + +/** + * Version 0 variant of Avtp_Cvf_GetEvt(). + * @see Avtp_Cvf_GetEvt + */ +OPEN1722_INLINE uint8_t Avtp_Cvf_GetEvt_V0(const Avtp_Cvf_t *const pdu) +{ + return (uint8_t)Avtp_Cvf_GetField_V0(pdu, AVTP_CVF_FIELD_EVT); +} + +/** + * Version 1 variant of Avtp_Cvf_GetEvt(). + * @see Avtp_Cvf_GetEvt + */ +OPEN1722_INLINE uint8_t Avtp_Cvf_GetEvt_V1(const Avtp_CvfV1_t *const pdu) +{ + return (uint8_t)Avtp_Cvf_GetField_V1(pdu, AVTP_CVF_FIELD_EVT); +} + +/** + * Version 0 variant of Avtp_Cvf_SetSv(). + * @see Avtp_Cvf_SetSv + */ +OPEN1722_INLINE void Avtp_Cvf_SetSv_V0(Avtp_Cvf_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetSv_V0((Avtp_CommonStreamHeader_t *)pdu, sv); +} + +/** + * Version 1 variant of Avtp_Cvf_SetSv(). + * @see Avtp_Cvf_SetSv + */ +OPEN1722_INLINE void Avtp_Cvf_SetSv_V1(Avtp_CvfV1_t *pdu, bool sv) +{ + Avtp_CommonStreamHeader_SetSv_V1((Avtp_CommonStreamHeader_t *)pdu, sv); +} + +/** + * Version 0 variant of Avtp_Cvf_SetMr(). + * @see Avtp_Cvf_SetMr + */ +OPEN1722_INLINE void Avtp_Cvf_SetMr_V0(Avtp_Cvf_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetMr_V0((Avtp_CommonStreamHeader_t *)pdu, mr); +} + +/** + * Version 1 variant of Avtp_Cvf_SetMr(). + * @see Avtp_Cvf_SetMr + */ +OPEN1722_INLINE void Avtp_Cvf_SetMr_V1(Avtp_CvfV1_t *pdu, bool mr) +{ + Avtp_CommonStreamHeader_SetMr_V1((Avtp_CommonStreamHeader_t *)pdu, mr); +} + +/** + * Version 0 variant of Avtp_Cvf_SetTv(). + * @see Avtp_Cvf_SetTv + */ +OPEN1722_INLINE void Avtp_Cvf_SetTv_V0(Avtp_Cvf_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetTv_V0((Avtp_CommonStreamHeader_t *)pdu, tv); +} + +/** + * Version 1 variant of Avtp_Cvf_SetTv(). + * @see Avtp_Cvf_SetTv + */ +OPEN1722_INLINE void Avtp_Cvf_SetTv_V1(Avtp_CvfV1_t *pdu, bool tv) +{ + Avtp_CommonStreamHeader_SetTv_V1((Avtp_CommonStreamHeader_t *)pdu, tv); +} + +/** + * Version 0 variant of Avtp_Cvf_SetTu(). + * @see Avtp_Cvf_SetTu + */ +OPEN1722_INLINE void Avtp_Cvf_SetTu_V0(Avtp_Cvf_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetTu_V0((Avtp_CommonStreamHeader_t *)pdu, tu); +} + +/** + * Version 1 variant of Avtp_Cvf_SetTu(). + * @see Avtp_Cvf_SetTu + */ +OPEN1722_INLINE void Avtp_Cvf_SetTu_V1(Avtp_CvfV1_t *pdu, bool tu) +{ + Avtp_CommonStreamHeader_SetTu_V1((Avtp_CommonStreamHeader_t *)pdu, tu); +} + +/** + * Version 0 variant of Avtp_Cvf_SetSequenceNum(). Values are truncated to the + * 8-bit version 0 field width. + * @see Avtp_Cvf_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Cvf_SetSequenceNum_V0(Avtp_Cvf_t *pdu, uint32_t value) +{ + Avtp_CommonStreamHeader_SetSequenceNum_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Cvf_SetSequenceNum(). + * @see Avtp_Cvf_SetSequenceNum + */ +OPEN1722_INLINE void Avtp_Cvf_SetSequenceNum_V1(Avtp_CvfV1_t *pdu, uint32_t value) +{ + Avtp_CommonStreamHeader_SetSequenceNum_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Cvf_SetStreamId(). + * @see Avtp_Cvf_SetStreamId + */ +OPEN1722_INLINE void Avtp_Cvf_SetStreamId_V0(Avtp_Cvf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetStreamId_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Cvf_SetStreamId(). + * @see Avtp_Cvf_SetStreamId + */ +OPEN1722_INLINE void Avtp_Cvf_SetStreamId_V1(Avtp_CvfV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetStreamId_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Cvf_SetAvtpTimestamp(). + * @see Avtp_Cvf_SetAvtpTimestamp + */ +OPEN1722_INLINE void Avtp_Cvf_SetAvtpTimestamp_V0(Avtp_Cvf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetAvtpTimestamp_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Cvf_SetAvtpTimestamp(). + * @see Avtp_Cvf_SetAvtpTimestamp + */ +OPEN1722_INLINE void Avtp_Cvf_SetAvtpTimestamp_V1(Avtp_CvfV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetAvtpTimestamp_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Cvf_SetPtpGrandmasterIdentity(). The field is + * absent from version 0, so this is a no-op. + * @see Avtp_Cvf_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Cvf_SetPtpGrandmasterIdentity_V0(Avtp_Cvf_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Cvf_SetPtpGrandmasterIdentity(). + * @see Avtp_Cvf_SetPtpGrandmasterIdentity + */ +OPEN1722_INLINE void Avtp_Cvf_SetPtpGrandmasterIdentity_V1(Avtp_CvfV1_t *pdu, uint64_t value) +{ + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Cvf_SetFormat(). + * @see Avtp_Cvf_SetFormat + */ +OPEN1722_INLINE void Avtp_Cvf_SetFormat_V0(Avtp_Cvf_t *pdu, Avtp_CvfFormat_t value) +{ + Avtp_Cvf_SetField_V0(pdu, AVTP_CVF_FIELD_FORMAT, (uint64_t)value); +} + +/** + * Version 1 variant of Avtp_Cvf_SetFormat(). + * @see Avtp_Cvf_SetFormat + */ +OPEN1722_INLINE void Avtp_Cvf_SetFormat_V1(Avtp_CvfV1_t *pdu, Avtp_CvfFormat_t value) +{ + Avtp_Cvf_SetField_V1(pdu, AVTP_CVF_FIELD_FORMAT, (uint64_t)value); +} + +/** + * Version 0 variant of Avtp_Cvf_SetFormatSubtype(). + * @see Avtp_Cvf_SetFormatSubtype + */ +OPEN1722_INLINE void Avtp_Cvf_SetFormatSubtype_V0(Avtp_Cvf_t *pdu, Avtp_CvfFormatSubtype_t value) +{ + Avtp_Cvf_SetField_V0(pdu, AVTP_CVF_FIELD_FORMAT_SUBTYPE, (uint64_t)value); +} + +/** + * Version 1 variant of Avtp_Cvf_SetFormatSubtype(). + * @see Avtp_Cvf_SetFormatSubtype + */ +OPEN1722_INLINE void Avtp_Cvf_SetFormatSubtype_V1(Avtp_CvfV1_t *pdu, Avtp_CvfFormatSubtype_t value) +{ + Avtp_Cvf_SetField_V1(pdu, AVTP_CVF_FIELD_FORMAT_SUBTYPE, (uint64_t)value); +} + +/** + * Version 0 variant of Avtp_Cvf_SetStreamDataLength(). + * @see Avtp_Cvf_SetStreamDataLength + */ +OPEN1722_INLINE void Avtp_Cvf_SetStreamDataLength_V0(Avtp_Cvf_t *pdu, uint16_t value) +{ + Avtp_CommonStreamHeader_SetStreamDataLength_V0((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 1 variant of Avtp_Cvf_SetStreamDataLength(). + * @see Avtp_Cvf_SetStreamDataLength + */ +OPEN1722_INLINE void Avtp_Cvf_SetStreamDataLength_V1(Avtp_CvfV1_t *pdu, uint16_t value) +{ + Avtp_CommonStreamHeader_SetStreamDataLength_V1((Avtp_CommonStreamHeader_t *)pdu, value); +} + +/** + * Version 0 variant of Avtp_Cvf_SetPtv(). + * @see Avtp_Cvf_SetPtv + */ +OPEN1722_INLINE void Avtp_Cvf_SetPtv_V0(Avtp_Cvf_t *pdu, bool ptv) +{ + Avtp_Cvf_SetField_V0(pdu, AVTP_CVF_FIELD_PTV, ptv); +} + +/** + * Version 1 variant of Avtp_Cvf_SetPtv(). + * @see Avtp_Cvf_SetPtv + */ +OPEN1722_INLINE void Avtp_Cvf_SetPtv_V1(Avtp_CvfV1_t *pdu, bool ptv) +{ + Avtp_Cvf_SetField_V1(pdu, AVTP_CVF_FIELD_PTV, ptv); +} + +/** + * Version 0 variant of Avtp_Cvf_SetM(). + * @see Avtp_Cvf_SetM + */ +OPEN1722_INLINE void Avtp_Cvf_SetM_V0(Avtp_Cvf_t *pdu, bool m) +{ + Avtp_Cvf_SetField_V0(pdu, AVTP_CVF_FIELD_M, m); +} + +/** + * Version 1 variant of Avtp_Cvf_SetM(). + * @see Avtp_Cvf_SetM + */ +OPEN1722_INLINE void Avtp_Cvf_SetM_V1(Avtp_CvfV1_t *pdu, bool m) +{ + Avtp_Cvf_SetField_V1(pdu, AVTP_CVF_FIELD_M, m); +} + +/** + * Version 0 variant of Avtp_Cvf_SetEvt(). + * @see Avtp_Cvf_SetEvt + */ +OPEN1722_INLINE void Avtp_Cvf_SetEvt_V0(Avtp_Cvf_t *pdu, uint8_t value) +{ + Avtp_Cvf_SetField_V0(pdu, AVTP_CVF_FIELD_EVT, value); +} + +/** + * Version 1 variant of Avtp_Cvf_SetEvt(). + * @see Avtp_Cvf_SetEvt + */ +OPEN1722_INLINE void Avtp_Cvf_SetEvt_V1(Avtp_CvfV1_t *pdu, uint8_t value) +{ + Avtp_Cvf_SetField_V1(pdu, AVTP_CVF_FIELD_EVT, value); +} + #ifdef __cplusplus } #endif diff --git a/unit/CMakeLists.txt b/unit/CMakeLists.txt index 88c02cc8..45f95bfe 100644 --- a/unit/CMakeLists.txt +++ b/unit/CMakeLists.txt @@ -85,6 +85,7 @@ add_dual_test(test-sensor test-sensor.c) add_dual_test(test-udp test-udp.c) add_dual_test(test-commonheader test-commonheader.c) add_dual_test(test-commonstreamheader test-commonstreamheader.c) +add_dual_test(test-alternativeheader test-alternativeheader.c) add_dual_test(test-gisf test-gisf.c) add_dual_test(test-abb test-abb.c) add_dual_test(test-gbb test-gbb.c) diff --git a/unit/test-aaf.c b/unit/test-aaf.c index c9706cfa..bac4d27d 100644 --- a/unit/test-aaf.c +++ b/unit/test-aaf.c @@ -54,6 +54,17 @@ static uint32_t read_quadlet(const uint8_t *pdu, size_t quadlet) return ntohl(word); } +static uint64_t mask_field_value(uint8_t bits, uint64_t value) +{ + if (bits == 0) { + return 0; + } + if (bits >= 64) { + return value; + } + return value & ((((uint64_t)1) << bits) - 1); +} + static void aaf_init(void **state) { (void)state; @@ -369,6 +380,155 @@ static void aaf_get_set_field(void **state) assert_int_equal(Avtp_Aaf_GetField(aaf, AVTP_AAF_FIELD_FSD1), 0x7F); } +static void aaf_typed_fields_v0(void **state) +{ + (void)state; + uint8_t pdu[AVTP_AAF_HEADER_LEN_V1]; + Avtp_Aaf_t *aaf = (Avtp_Aaf_t *)pdu; + + Avtp_Aaf_Init(aaf); + + for (uint8_t f = 0; f < AVTP_AAF_FIELD_MAX; f++) { + uint8_t bits = Avtp_AafFieldDescV0[f].bits; + uint64_t value = 0xA5A5A5A5A5A5A5A5ULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_AafFields_t field = (Avtp_AafFields_t)f; + + Avtp_Aaf_SetField_V0(aaf, field, value); + assert_int_equal(Avtp_Aaf_GetField_V0(aaf, field), expected); + assert_int_equal(Avtp_Aaf_GetField(aaf, field), expected); + assert_int_equal(Avtp_GetField(Avtp_AafFieldDescV0, AVTP_AAF_FIELD_MAX, pdu, f), expected); + } +} + +static void aaf_typed_fields_v1(void **state) +{ + (void)state; + uint8_t pdu[AVTP_AAF_HEADER_LEN_V1]; + Avtp_AafV1_t *aaf = (Avtp_AafV1_t *)pdu; + + Avtp_Aaf_InitV1(aaf); + + for (uint8_t f = 0; f < AVTP_AAF_FIELD_MAX; f++) { + uint8_t bits = Avtp_AafFieldDescV1[f].bits; + uint64_t value = 0x5A5A5A5A5A5A5A5AULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_AafFields_t field = (Avtp_AafFields_t)f; + + Avtp_Aaf_SetField_V1(aaf, field, value); + assert_int_equal(Avtp_Aaf_GetField_V1(aaf, field), expected); + assert_int_equal(Avtp_Aaf_GetField((Avtp_Aaf_t *)aaf, field), expected); + assert_int_equal(Avtp_GetField(Avtp_AafFieldDescV1, AVTP_AAF_FIELD_MAX, pdu, f), expected); + } +} + +static void aaf_typed_named(void **state) +{ + (void)state; + uint8_t pdu[AVTP_AAF_HEADER_LEN_V1]; + Avtp_Aaf_t *v0 = (Avtp_Aaf_t *)pdu; + Avtp_AafV1_t *v1 = (Avtp_AafV1_t *)pdu; + + /* Version 0. */ + Avtp_Aaf_Init(v0); + Avtp_Aaf_SetSv_V0(v0, true); + Avtp_Aaf_SetMr_V0(v0, true); + Avtp_Aaf_SetTv_V0(v0, true); + Avtp_Aaf_SetTu_V0(v0, true); + Avtp_Aaf_SetSequenceNum_V0(v0, 0x55); + Avtp_Aaf_SetStreamId_V0(v0, 0xAABBCCDDEEFF0001ULL); + Avtp_Aaf_SetAvtpTimestamp_V0(v0, 0x80C0FFEE); + Avtp_Aaf_SetFormat_V0(v0, AVTP_AAF_FORMAT_INT_16BIT); + Avtp_Aaf_SetAafFormatSpecificData1_V0(v0, 0x123456); + Avtp_Aaf_SetStreamDataLength_V0(v0, 0xAAAA); + Avtp_Aaf_SetAfsd_V0(v0, 0x5); + Avtp_Aaf_SetSp_V0(v0, true); + Avtp_Aaf_SetEvt_V0(v0, 0xA); + Avtp_Aaf_SetAafFormatSpecificData2_V0(v0, 0xAB); + + assert_true(Avtp_Aaf_IsSv_V0(v0)); + assert_true(Avtp_Aaf_IsMr_V0(v0)); + assert_true(Avtp_Aaf_IsTv_V0(v0)); + assert_true(Avtp_Aaf_IsTu_V0(v0)); + assert_int_equal(Avtp_Aaf_GetSequenceNum_V0(v0), 0x55); + assert_int_equal(Avtp_Aaf_GetStreamId_V0(v0), 0xAABBCCDDEEFF0001ULL); + assert_int_equal(Avtp_Aaf_GetAvtpTimestamp_V0(v0), 0x80C0FFEE); + assert_int_equal(Avtp_Aaf_GetFormat_V0(v0), AVTP_AAF_FORMAT_INT_16BIT); + assert_int_equal(Avtp_Aaf_GetAafFormatSpecificData1_V0(v0), 0x123456); + assert_int_equal(Avtp_Aaf_GetStreamDataLength_V0(v0), 0xAAAA); + assert_int_equal(Avtp_Aaf_GetAfsd_V0(v0), 0x5); + assert_true(Avtp_Aaf_IsSp_V0(v0)); + assert_int_equal(Avtp_Aaf_GetEvt_V0(v0), 0xA); + assert_int_equal(Avtp_Aaf_GetAafFormatSpecificData2_V0(v0), 0xAB); + assert_int_equal(Avtp_Aaf_GetPtpGrandmasterIdentity_V0(v0), 0); + + /* The version-dispatched accessors agree with the version 0 variants. */ + assert_int_equal(Avtp_Aaf_GetSequenceNum(v0), Avtp_Aaf_GetSequenceNum_V0(v0)); + assert_int_equal(Avtp_Aaf_GetStreamId(v0), Avtp_Aaf_GetStreamId_V0(v0)); + assert_int_equal(Avtp_Aaf_GetAvtpTimestamp(v0), Avtp_Aaf_GetAvtpTimestamp_V0(v0)); + assert_int_equal(Avtp_Aaf_GetFormat(v0), Avtp_Aaf_GetFormat_V0(v0)); + assert_int_equal(Avtp_Aaf_GetStreamDataLength(v0), Avtp_Aaf_GetStreamDataLength_V0(v0)); + assert_int_equal(Avtp_Aaf_GetEvt(v0), Avtp_Aaf_GetEvt_V0(v0)); + + /* Version 1. */ + Avtp_Aaf_InitV1(v1); + Avtp_Aaf_SetSv_V1(v1, true); + Avtp_Aaf_SetSequenceNum_V1(v1, 0x12345678); + Avtp_Aaf_SetStreamId_V1(v1, 0x0102030405060708ULL); + Avtp_Aaf_SetAvtpTimestamp_V1(v1, 0x1122334455667788ULL); + Avtp_Aaf_SetPtpGrandmasterIdentity_V1(v1, 0x99AABBCCDDEEFF00ULL); + Avtp_Aaf_SetFormat_V1(v1, AVTP_AAF_FORMAT_FLOAT_32BIT); + Avtp_Aaf_SetAafFormatSpecificData1_V1(v1, 0x654321); + Avtp_Aaf_SetStreamDataLength_V1(v1, 0xBBBB); + Avtp_Aaf_SetAfsd_V1(v1, 0x2); + Avtp_Aaf_SetSp_V1(v1, true); + Avtp_Aaf_SetEvt_V1(v1, 0xB); + Avtp_Aaf_SetAafFormatSpecificData2_V1(v1, 0xCD); + + assert_true(Avtp_Aaf_IsSv_V1(v1)); + assert_int_equal(Avtp_Aaf_GetSequenceNum_V1(v1), 0x12345678); + assert_int_equal(Avtp_Aaf_GetStreamId_V1(v1), 0x0102030405060708ULL); + assert_int_equal(Avtp_Aaf_GetAvtpTimestamp_V1(v1), 0x1122334455667788ULL); + assert_int_equal(Avtp_Aaf_GetPtpGrandmasterIdentity_V1(v1), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Aaf_GetFormat_V1(v1), AVTP_AAF_FORMAT_FLOAT_32BIT); + assert_int_equal(Avtp_Aaf_GetAafFormatSpecificData1_V1(v1), 0x654321); + assert_int_equal(Avtp_Aaf_GetStreamDataLength_V1(v1), 0xBBBB); + assert_int_equal(Avtp_Aaf_GetAfsd_V1(v1), 0x2); + assert_true(Avtp_Aaf_IsSp_V1(v1)); + assert_int_equal(Avtp_Aaf_GetEvt_V1(v1), 0xB); + assert_int_equal(Avtp_Aaf_GetAafFormatSpecificData2_V1(v1), 0xCD); + + /* The version-dispatched accessors agree with the version 1 variants. */ + assert_int_equal(Avtp_Aaf_GetSequenceNum(v0), Avtp_Aaf_GetSequenceNum_V1(v1)); + assert_int_equal(Avtp_Aaf_GetStreamId(v0), Avtp_Aaf_GetStreamId_V1(v1)); + assert_int_equal(Avtp_Aaf_GetAvtpTimestamp(v0), Avtp_Aaf_GetAvtpTimestamp_V1(v1)); + assert_int_equal(Avtp_Aaf_GetPtpGrandmasterIdentity(v0), + Avtp_Aaf_GetPtpGrandmasterIdentity_V1(v1)); + assert_int_equal(Avtp_Aaf_GetFormat(v0), Avtp_Aaf_GetFormat_V1(v1)); + assert_int_equal(Avtp_Aaf_GetStreamDataLength(v0), Avtp_Aaf_GetStreamDataLength_V1(v1)); + assert_int_equal(Avtp_Aaf_GetAfsd(v0), Avtp_Aaf_GetAfsd_V1(v1)); + assert_int_equal(Avtp_Aaf_GetEvt(v0), Avtp_Aaf_GetEvt_V1(v1)); +} + +static void aaf_typed_helpers(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t payload[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + + Avtp_Aaf_Init((Avtp_Aaf_t *)pdu); + assert_int_equal(Avtp_Aaf_GetHeaderLen_V0((Avtp_Aaf_t *)pdu), AVTP_AAF_HEADER_LEN_V0); + assert_ptr_equal(Avtp_Aaf_GetPayload_V0((Avtp_Aaf_t *)pdu), pdu + AVTP_AAF_HEADER_LEN_V0); + Avtp_Aaf_SetPayload_V0((Avtp_Aaf_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_AAF_HEADER_LEN_V0, payload, sizeof(payload)); + + Avtp_Aaf_InitV1((Avtp_AafV1_t *)pdu); + assert_int_equal(Avtp_Aaf_GetHeaderLen_V1((Avtp_AafV1_t *)pdu), AVTP_AAF_HEADER_LEN_V1); + assert_ptr_equal(Avtp_Aaf_GetPayload_V1((Avtp_AafV1_t *)pdu), pdu + AVTP_AAF_HEADER_LEN_V1); + Avtp_Aaf_SetPayload_V1((Avtp_AafV1_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_AAF_HEADER_LEN_V1, payload, sizeof(payload)); +} + int main(void) { const struct CMUnitTest tests[] = { @@ -382,6 +542,10 @@ int main(void) cmocka_unit_test(aaf_v1_layout), cmocka_unit_test(aaf_payload), cmocka_unit_test(aaf_get_set_field), + cmocka_unit_test(aaf_typed_fields_v0), + cmocka_unit_test(aaf_typed_fields_v1), + cmocka_unit_test(aaf_typed_named), + cmocka_unit_test(aaf_typed_helpers), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/unit/test-alternativeheader.c b/unit/test-alternativeheader.c new file mode 100644 index 00000000..e114bf1e --- /dev/null +++ b/unit/test-alternativeheader.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2026, COVESA + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of COVESA nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#if defined(__cplusplus) +extern "C" { +#include +} +#else +#include +#endif +#include +#include + +#include "avtp/AlternativeHeader.h" + +static uint64_t mask_field_value(uint8_t bits, uint64_t value) +{ + if (bits == 0) { + return 0; + } + if (bits >= 64) { + return value; + } + return value & ((((uint64_t)1) << bits) - 1); +} + +static void alternative_header_lengths(void **state) +{ + (void)state; + + assert_int_equal(AVTPDU_AH_LEN_V0, 4); + assert_int_equal(AVTPDU_AH_LEN_V1, 16); + assert_int_equal(sizeof(Avtp_AlternativeHeader_t), AVTPDU_AH_LEN_V1); +} + +static void alternative_header_typed_fields_v0(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_AH_LEN_V1]; + Avtp_AlternativeHeader_t *ah = (Avtp_AlternativeHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ah, AVTP_VERSION_0); + + for (uint8_t f = 0; f < AVTPDU_AH_FIELD_MAX; f++) { + uint8_t bits = Avtp_AhFieldDescV0[f].bits; + uint64_t value = 0xA5A5A5A5A5A5A5A5ULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_AlternativeHeaderField_t field = (Avtp_AlternativeHeaderField_t)f; + + Avtp_AlternativeHeader_SetField_V0(ah, field, value); + assert_int_equal(Avtp_AlternativeHeader_GetField_V0(ah, field), expected); + assert_int_equal(Avtp_AlternativeHeader_GetField(ah, field), expected); + assert_int_equal(Avtp_GetField(Avtp_AhFieldDescV0, AVTPDU_AH_FIELD_MAX, pdu, f), expected); + } +} + +static void alternative_header_typed_fields_v1(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_AH_LEN_V1]; + Avtp_AlternativeHeader_t *ah = (Avtp_AlternativeHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ah, AVTP_VERSION_1); + + for (uint8_t f = 0; f < AVTPDU_AH_FIELD_MAX; f++) { + uint8_t bits = Avtp_AhFieldDescV1[f].bits; + uint64_t value = 0x5A5A5A5A5A5A5A5AULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_AlternativeHeaderField_t field = (Avtp_AlternativeHeaderField_t)f; + + Avtp_AlternativeHeader_SetField_V1(ah, field, value); + assert_int_equal(Avtp_AlternativeHeader_GetField_V1(ah, field), expected); + assert_int_equal(Avtp_AlternativeHeader_GetField(ah, field), expected); + assert_int_equal(Avtp_GetField(Avtp_AhFieldDescV1, AVTPDU_AH_FIELD_MAX, pdu, f), expected); + } +} + +static void alternative_header_typed_named_v1(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_AH_LEN_V1]; + Avtp_AlternativeHeader_t *ah = (Avtp_AlternativeHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ah, AVTP_VERSION_1); + + Avtp_AlternativeHeader_SetSequenceNum_V1(ah, 0x12345678); + Avtp_AlternativeHeader_SetPtpGrandmasterIdentity_V1(ah, 0x99AABBCCDDEEFF00ULL); + + assert_int_equal(Avtp_AlternativeHeader_GetSequenceNum_V1(ah), 0x12345678); + assert_int_equal(Avtp_AlternativeHeader_GetPtpGrandmasterIdentity_V1(ah), + 0x99AABBCCDDEEFF00ULL); + + /* The version-dispatched accessors agree with the version 1 variants. */ + assert_int_equal(Avtp_AlternativeHeader_GetSequenceNum(ah), + Avtp_AlternativeHeader_GetSequenceNum_V1(ah)); + assert_int_equal(Avtp_AlternativeHeader_GetPtpGrandmasterIdentity(ah), + Avtp_AlternativeHeader_GetPtpGrandmasterIdentity_V1(ah)); +} + +static void alternative_header_typed_absent_fields(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_AH_LEN_V1]; + uint8_t snapshot[AVTPDU_AH_LEN_V1]; + Avtp_AlternativeHeader_t *ah = (Avtp_AlternativeHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ah, AVTP_VERSION_0); + + /* sequence_num and ptp_grandmaster_identity do not exist in v0. */ + assert_int_equal(Avtp_AlternativeHeader_GetSequenceNum_V0(ah), 0); + assert_int_equal(Avtp_AlternativeHeader_GetPtpGrandmasterIdentity_V0(ah), 0); + + memcpy(snapshot, pdu, sizeof(snapshot)); + Avtp_AlternativeHeader_SetSequenceNum_V0(ah, 0xFFFFFFFF); + Avtp_AlternativeHeader_SetPtpGrandmasterIdentity_V0(ah, 0xFFFFFFFFFFFFFFFFULL); + assert_memory_equal(snapshot, pdu, sizeof(snapshot)); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(alternative_header_lengths), + cmocka_unit_test(alternative_header_typed_fields_v0), + cmocka_unit_test(alternative_header_typed_fields_v1), + cmocka_unit_test(alternative_header_typed_named_v1), + cmocka_unit_test(alternative_header_typed_absent_fields), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/unit/test-commonstreamheader.c b/unit/test-commonstreamheader.c index e9c5cc6f..b7c991c1 100644 --- a/unit/test-commonstreamheader.c +++ b/unit/test-commonstreamheader.c @@ -50,6 +50,17 @@ static uint32_t read_quadlet(const uint8_t *pdu, size_t quadlet) return ntohl(word); } +static uint64_t mask_field_value(uint8_t bits, uint64_t value) +{ + if (bits == 0) { + return 0; + } + if (bits >= 64) { + return value; + } + return value & ((((uint64_t)1) << bits) - 1); +} + static void common_stream_header_lengths(void **state) { (void)state; @@ -204,6 +215,181 @@ static void common_stream_header_no_overlap(void **state) } } +static void common_stream_header_typed_header_len(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_CSH_LEN_V1]; + Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + + assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen_V0(csh), AVTPDU_CSH_LEN_V0); + assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen_V1(csh), AVTPDU_CSH_LEN_V1); + + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_0); + assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen(csh), AVTPDU_CSH_LEN_V0); + + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_1); + assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen(csh), AVTPDU_CSH_LEN_V1); +} + +static void common_stream_header_typed_fields_v0(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_CSH_LEN_V1]; + Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_0); + + for (uint8_t f = 0; f < AVTPDU_CSH_FIELD_MAX; f++) { + uint8_t bits = Avtp_CshFieldDescV0[f].bits; + uint64_t value = 0xA5A5A5A5A5A5A5A5ULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_CommonStreamHeaderField_t field = (Avtp_CommonStreamHeaderField_t)f; + + Avtp_CommonStreamHeader_SetField_V0(csh, field, value); + assert_int_equal(Avtp_CommonStreamHeader_GetField_V0(csh, field), expected); + assert_int_equal(Avtp_CommonStreamHeader_GetField(csh, field), expected); + assert_int_equal(Avtp_GetField(Avtp_CshFieldDescV0, AVTPDU_CSH_FIELD_MAX, pdu, f), + expected); + } +} + +static void common_stream_header_typed_fields_v1(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_CSH_LEN_V1]; + Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_1); + + for (uint8_t f = 0; f < AVTPDU_CSH_FIELD_MAX; f++) { + uint8_t bits = Avtp_CshFieldDescV1[f].bits; + uint64_t value = 0x5A5A5A5A5A5A5A5AULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_CommonStreamHeaderField_t field = (Avtp_CommonStreamHeaderField_t)f; + + Avtp_CommonStreamHeader_SetField_V1(csh, field, value); + assert_int_equal(Avtp_CommonStreamHeader_GetField_V1(csh, field), expected); + assert_int_equal(Avtp_CommonStreamHeader_GetField(csh, field), expected); + assert_int_equal(Avtp_GetField(Avtp_CshFieldDescV1, AVTPDU_CSH_FIELD_MAX, pdu, f), + expected); + } +} + +static void common_stream_header_typed_named_v0(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_CSH_LEN_V0]; + Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_0); + + Avtp_CommonStreamHeader_SetSv_V0(csh, true); + Avtp_CommonStreamHeader_SetMr_V0(csh, true); + Avtp_CommonStreamHeader_SetFsd_V0(csh, 0x3); + Avtp_CommonStreamHeader_SetTv_V0(csh, true); + Avtp_CommonStreamHeader_SetTu_V0(csh, true); + Avtp_CommonStreamHeader_SetFormatSpecificData1_V0(csh, 0x5A); + Avtp_CommonStreamHeader_SetSequenceNum_V0(csh, 0xAB); + Avtp_CommonStreamHeader_SetStreamId_V0(csh, 0xAABBCCDDEEFF0011ULL); + Avtp_CommonStreamHeader_SetAvtpTimestamp_V0(csh, 0x80C0FFEE); + Avtp_CommonStreamHeader_SetStreamDataLength_V0(csh, 0x1234); + + assert_true(Avtp_CommonStreamHeader_IsSv_V0(csh)); + assert_true(Avtp_CommonStreamHeader_IsMr_V0(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetFsd_V0(csh), 0x3); + assert_true(Avtp_CommonStreamHeader_IsTv_V0(csh)); + assert_true(Avtp_CommonStreamHeader_IsTu_V0(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetFormatSpecificData1_V0(csh), 0x5A); + assert_int_equal(Avtp_CommonStreamHeader_GetSequenceNum_V0(csh), 0xAB); + assert_int_equal(Avtp_CommonStreamHeader_GetStreamId_V0(csh), 0xAABBCCDDEEFF0011ULL); + assert_int_equal(Avtp_CommonStreamHeader_GetAvtpTimestamp_V0(csh), 0x80C0FFEE); + assert_int_equal(Avtp_CommonStreamHeader_GetStreamDataLength_V0(csh), 0x1234); + + /* The version-dispatched accessors agree with the version 0 variants. */ + assert_int_equal(Avtp_CommonStreamHeader_GetSequenceNum(csh), + Avtp_CommonStreamHeader_GetSequenceNum_V0(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetStreamId(csh), + Avtp_CommonStreamHeader_GetStreamId_V0(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetAvtpTimestamp(csh), + Avtp_CommonStreamHeader_GetAvtpTimestamp_V0(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetStreamDataLength(csh), + Avtp_CommonStreamHeader_GetStreamDataLength_V0(csh)); +} + +static void common_stream_header_typed_named_v1(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_CSH_LEN_V1]; + Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_1); + + Avtp_CommonStreamHeader_SetSv_V1(csh, true); + Avtp_CommonStreamHeader_SetMr_V1(csh, true); + Avtp_CommonStreamHeader_SetFsd_V1(csh, 0x1); + Avtp_CommonStreamHeader_SetTv_V1(csh, true); + Avtp_CommonStreamHeader_SetFormatSpecificData0_V1(csh, 0x42); + Avtp_CommonStreamHeader_SetFormatSpecificData1_V1(csh, 0x5A); + Avtp_CommonStreamHeader_SetTu_V1(csh, true); + Avtp_CommonStreamHeader_SetSequenceNum_V1(csh, 0x12345678); + Avtp_CommonStreamHeader_SetStreamId_V1(csh, 0x0102030405060708ULL); + Avtp_CommonStreamHeader_SetAvtpTimestamp_V1(csh, 0x1122334455667788ULL); + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V1(csh, 0x99AABBCCDDEEFF00ULL); + Avtp_CommonStreamHeader_SetStreamDataLength_V1(csh, 0x0ABC); + + assert_true(Avtp_CommonStreamHeader_IsSv_V1(csh)); + assert_true(Avtp_CommonStreamHeader_IsMr_V1(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetFsd_V1(csh), 0x1); + assert_true(Avtp_CommonStreamHeader_IsTv_V1(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetFormatSpecificData0_V1(csh), 0x42); + assert_int_equal(Avtp_CommonStreamHeader_GetFormatSpecificData1_V1(csh), 0x5A); + assert_true(Avtp_CommonStreamHeader_IsTu_V1(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetSequenceNum_V1(csh), 0x12345678); + assert_int_equal(Avtp_CommonStreamHeader_GetStreamId_V1(csh), 0x0102030405060708ULL); + assert_int_equal(Avtp_CommonStreamHeader_GetAvtpTimestamp_V1(csh), 0x1122334455667788ULL); + assert_int_equal(Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V1(csh), + 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_CommonStreamHeader_GetStreamDataLength_V1(csh), 0x0ABC); + + /* The version-dispatched accessors agree with the version 1 variants. */ + assert_int_equal(Avtp_CommonStreamHeader_GetSequenceNum(csh), + Avtp_CommonStreamHeader_GetSequenceNum_V1(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetStreamId(csh), + Avtp_CommonStreamHeader_GetStreamId_V1(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetAvtpTimestamp(csh), + Avtp_CommonStreamHeader_GetAvtpTimestamp_V1(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity(csh), + Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V1(csh)); + assert_int_equal(Avtp_CommonStreamHeader_GetStreamDataLength(csh), + Avtp_CommonStreamHeader_GetStreamDataLength_V1(csh)); +} + +static void common_stream_header_typed_absent_fields(void **state) +{ + (void)state; + uint8_t pdu[AVTPDU_CSH_LEN_V0]; + uint8_t snapshot[AVTPDU_CSH_LEN_V0]; + Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; + + memset(pdu, 0, sizeof(pdu)); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_0); + + /* format_specific_data_0 and ptp_grandmaster_identity do not exist in v0. */ + assert_int_equal(Avtp_CommonStreamHeader_GetFormatSpecificData0_V0(csh), 0); + assert_int_equal(Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V0(csh), 0); + + memcpy(snapshot, pdu, sizeof(snapshot)); + Avtp_CommonStreamHeader_SetFormatSpecificData0_V0(csh, 0x42); + Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V0(csh, 0xFFFFFFFFFFFFFFFFULL); + assert_memory_equal(snapshot, pdu, sizeof(snapshot)); +} + int main(void) { const struct CMUnitTest tests[] = { @@ -212,6 +398,12 @@ int main(void) cmocka_unit_test(common_stream_header_v1_layout), cmocka_unit_test(common_stream_header_absent_fields), cmocka_unit_test(common_stream_header_no_overlap), + cmocka_unit_test(common_stream_header_typed_header_len), + cmocka_unit_test(common_stream_header_typed_fields_v0), + cmocka_unit_test(common_stream_header_typed_fields_v1), + cmocka_unit_test(common_stream_header_typed_named_v0), + cmocka_unit_test(common_stream_header_typed_named_v1), + cmocka_unit_test(common_stream_header_typed_absent_fields), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/unit/test-crf.c b/unit/test-crf.c index e22df76a..9f8a2046 100644 --- a/unit/test-crf.c +++ b/unit/test-crf.c @@ -55,6 +55,17 @@ static uint32_t read_quadlet(const uint8_t *pdu, size_t quadlet) return ntohl(word); } +static uint64_t mask_field_value(uint8_t bits, uint64_t value) +{ + if (bits == 0) { + return 0; + } + if (bits >= 64) { + return value; + } + return value & ((((uint64_t)1) << bits) - 1); +} + /* Initializes a minimal but valid CRF frame. */ static void init_valid_crf(Avtp_Crf_t *pdu) { @@ -367,6 +378,148 @@ static void crf_get_set_field(void **state) assert_int_equal(Avtp_Crf_GetField(crf, AVTP_CRF_FIELD_R), 0x1); } +static void crf_typed_fields_v0(void **state) +{ + (void)state; + uint8_t pdu[AVTP_CRF_HEADER_LEN_V1]; + Avtp_Crf_t *crf = (Avtp_Crf_t *)pdu; + + Avtp_Crf_Init(crf); + + for (uint8_t f = 0; f < AVTP_CRF_FIELD_MAX; f++) { + uint8_t bits = Avtp_CrfFieldDescV0[f].bits; + uint64_t value = 0xA5A5A5A5A5A5A5A5ULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_CrfFields_t field = (Avtp_CrfFields_t)f; + + Avtp_Crf_SetField_V0(crf, field, value); + assert_int_equal(Avtp_Crf_GetField_V0(crf, field), expected); + assert_int_equal(Avtp_Crf_GetField(crf, field), expected); + assert_int_equal(Avtp_GetField(Avtp_CrfFieldDescV0, AVTP_CRF_FIELD_MAX, pdu, f), expected); + } +} + +static void crf_typed_fields_v1(void **state) +{ + (void)state; + uint8_t pdu[AVTP_CRF_HEADER_LEN_V1]; + Avtp_CrfV1_t *crf = (Avtp_CrfV1_t *)pdu; + + Avtp_Crf_InitV1(crf); + + for (uint8_t f = 0; f < AVTP_CRF_FIELD_MAX; f++) { + uint8_t bits = Avtp_CrfFieldDescV1[f].bits; + uint64_t value = 0x5A5A5A5A5A5A5A5AULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_CrfFields_t field = (Avtp_CrfFields_t)f; + + Avtp_Crf_SetField_V1(crf, field, value); + assert_int_equal(Avtp_Crf_GetField_V1(crf, field), expected); + assert_int_equal(Avtp_Crf_GetField((Avtp_Crf_t *)crf, field), expected); + assert_int_equal(Avtp_GetField(Avtp_CrfFieldDescV1, AVTP_CRF_FIELD_MAX, pdu, f), expected); + } +} + +static void crf_typed_named(void **state) +{ + (void)state; + uint8_t pdu[AVTP_CRF_HEADER_LEN_V1]; + Avtp_Crf_t *v0 = (Avtp_Crf_t *)pdu; + Avtp_CrfV1_t *v1 = (Avtp_CrfV1_t *)pdu; + + /* Version 0. */ + Avtp_Crf_Init(v0); + Avtp_Crf_SetSv_V0(v0, true); + Avtp_Crf_SetMr_V0(v0, true); + Avtp_Crf_SetFs_V0(v0, true); + Avtp_Crf_SetTu_V0(v0, true); + Avtp_Crf_SetSequenceNum_V0(v0, 0xBB); + Avtp_Crf_SetType_V0(v0, AVTP_CRF_TYPE_VIDEO_LINE); + Avtp_Crf_SetStreamId_V0(v0, 0xAABBCCDDEEFF0002ULL); + Avtp_Crf_SetPull_V0(v0, AVTP_CRF_PULL_MULT_BY_1_001); + Avtp_Crf_SetBaseFrequency_V0(v0, 0x1FFFFFFF); + Avtp_Crf_SetCrfDataLength_V0(v0, 0xABCD); + Avtp_Crf_SetTimestampInterval_V0(v0, 0x1234); + + assert_true(Avtp_Crf_IsSv_V0(v0)); + assert_true(Avtp_Crf_IsMr_V0(v0)); + assert_true(Avtp_Crf_IsFs_V0(v0)); + assert_true(Avtp_Crf_IsTu_V0(v0)); + assert_int_equal(Avtp_Crf_GetSequenceNum_V0(v0), 0xBB); + assert_int_equal(Avtp_Crf_GetSequenceNumLsb_V0(v0), 0xBB); + assert_int_equal(Avtp_Crf_GetType_V0(v0), AVTP_CRF_TYPE_VIDEO_LINE); + assert_int_equal(Avtp_Crf_GetStreamId_V0(v0), 0xAABBCCDDEEFF0002ULL); + assert_int_equal(Avtp_Crf_GetPull_V0(v0), AVTP_CRF_PULL_MULT_BY_1_001); + assert_int_equal(Avtp_Crf_GetBaseFrequency_V0(v0), 0x1FFFFFFF); + assert_int_equal(Avtp_Crf_GetCrfDataLength_V0(v0), 0xABCD); + assert_int_equal(Avtp_Crf_GetTimestampInterval_V0(v0), 0x1234); + assert_int_equal(Avtp_Crf_GetPtpGrandmasterIdentity_V0(v0), 0); + + /* The version-dispatched accessors agree with the version 0 variants. */ + assert_int_equal(Avtp_Crf_GetSequenceNum(v0), Avtp_Crf_GetSequenceNum_V0(v0)); + assert_int_equal(Avtp_Crf_GetSequenceNumLsb(v0), Avtp_Crf_GetSequenceNumLsb_V0(v0)); + assert_int_equal(Avtp_Crf_GetType(v0), Avtp_Crf_GetType_V0(v0)); + assert_int_equal(Avtp_Crf_GetStreamId(v0), Avtp_Crf_GetStreamId_V0(v0)); + assert_int_equal(Avtp_Crf_GetPull(v0), Avtp_Crf_GetPull_V0(v0)); + assert_int_equal(Avtp_Crf_GetBaseFrequency(v0), Avtp_Crf_GetBaseFrequency_V0(v0)); + assert_int_equal(Avtp_Crf_GetCrfDataLength(v0), Avtp_Crf_GetCrfDataLength_V0(v0)); + assert_int_equal(Avtp_Crf_GetTimestampInterval(v0), Avtp_Crf_GetTimestampInterval_V0(v0)); + + /* Version 1. */ + Avtp_Crf_InitV1(v1); + Avtp_Crf_SetSv_V1(v1, true); + Avtp_Crf_SetSequenceNum_V1(v1, 0x12345678); + Avtp_Crf_SetPtpGrandmasterIdentity_V1(v1, 0x99AABBCCDDEEFF00ULL); + Avtp_Crf_SetType_V1(v1, AVTP_CRF_TYPE_VIDEO_LINE); + Avtp_Crf_SetStreamId_V1(v1, 0x0102030405060708ULL); + Avtp_Crf_SetPull_V1(v1, AVTP_CRF_PULL_MULT_BY_1_001); + Avtp_Crf_SetBaseFrequency_V1(v1, 0x1FFFFFFF); + Avtp_Crf_SetCrfDataLength_V1(v1, 0xABCD); + Avtp_Crf_SetTimestampInterval_V1(v1, 0x1234); + + assert_true(Avtp_Crf_IsSv_V1(v1)); + assert_int_equal(Avtp_Crf_GetSequenceNum_V1(v1), 0x12345678); + assert_int_equal(Avtp_Crf_GetSequenceNumLsb_V1(v1), 0x78); + assert_int_equal(Avtp_Crf_GetPtpGrandmasterIdentity_V1(v1), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Crf_GetType_V1(v1), AVTP_CRF_TYPE_VIDEO_LINE); + assert_int_equal(Avtp_Crf_GetStreamId_V1(v1), 0x0102030405060708ULL); + assert_int_equal(Avtp_Crf_GetPull_V1(v1), AVTP_CRF_PULL_MULT_BY_1_001); + assert_int_equal(Avtp_Crf_GetBaseFrequency_V1(v1), 0x1FFFFFFF); + assert_int_equal(Avtp_Crf_GetCrfDataLength_V1(v1), 0xABCD); + assert_int_equal(Avtp_Crf_GetTimestampInterval_V1(v1), 0x1234); + + /* The version-dispatched accessors agree with the version 1 variants. */ + assert_int_equal(Avtp_Crf_GetSequenceNum(v0), Avtp_Crf_GetSequenceNum_V1(v1)); + assert_int_equal(Avtp_Crf_GetSequenceNumLsb(v0), Avtp_Crf_GetSequenceNumLsb_V1(v1)); + assert_int_equal(Avtp_Crf_GetPtpGrandmasterIdentity(v0), + Avtp_Crf_GetPtpGrandmasterIdentity_V1(v1)); + assert_int_equal(Avtp_Crf_GetType(v0), Avtp_Crf_GetType_V1(v1)); + assert_int_equal(Avtp_Crf_GetStreamId(v0), Avtp_Crf_GetStreamId_V1(v1)); + assert_int_equal(Avtp_Crf_GetPull(v0), Avtp_Crf_GetPull_V1(v1)); + assert_int_equal(Avtp_Crf_GetBaseFrequency(v0), Avtp_Crf_GetBaseFrequency_V1(v1)); + assert_int_equal(Avtp_Crf_GetCrfDataLength(v0), Avtp_Crf_GetCrfDataLength_V1(v1)); + assert_int_equal(Avtp_Crf_GetTimestampInterval(v0), Avtp_Crf_GetTimestampInterval_V1(v1)); +} + +static void crf_typed_helpers(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t payload[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + + Avtp_Crf_Init((Avtp_Crf_t *)pdu); + assert_int_equal(Avtp_Crf_GetHeaderLen_V0((Avtp_Crf_t *)pdu), AVTP_CRF_HEADER_LEN_V0); + assert_ptr_equal(Avtp_Crf_GetPayload_V0((Avtp_Crf_t *)pdu), pdu + AVTP_CRF_HEADER_LEN_V0); + Avtp_Crf_SetPayload_V0((Avtp_Crf_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_CRF_HEADER_LEN_V0, payload, sizeof(payload)); + + Avtp_Crf_InitV1((Avtp_CrfV1_t *)pdu); + assert_int_equal(Avtp_Crf_GetHeaderLen_V1((Avtp_CrfV1_t *)pdu), AVTP_CRF_HEADER_LEN_V1); + assert_ptr_equal(Avtp_Crf_GetPayload_V1((Avtp_CrfV1_t *)pdu), pdu + AVTP_CRF_HEADER_LEN_V1); + Avtp_Crf_SetPayload_V1((Avtp_CrfV1_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_CRF_HEADER_LEN_V1, payload, sizeof(payload)); +} + int main(void) { const struct CMUnitTest tests[] = { @@ -380,6 +533,10 @@ int main(void) cmocka_unit_test(crf_v1_layout), cmocka_unit_test(crf_payload), cmocka_unit_test(crf_get_set_field), + cmocka_unit_test(crf_typed_fields_v0), + cmocka_unit_test(crf_typed_fields_v1), + cmocka_unit_test(crf_typed_named), + cmocka_unit_test(crf_typed_helpers), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/unit/test-cvf.c b/unit/test-cvf.c index 1b2af508..dfc65a00 100644 --- a/unit/test-cvf.c +++ b/unit/test-cvf.c @@ -58,6 +58,17 @@ static uint32_t read_quadlet(const uint8_t *pdu, size_t quadlet) return ntohl(word); } +static uint64_t mask_field_value(uint8_t bits, uint64_t value) +{ + if (bits == 0) { + return 0; + } + if (bits >= 64) { + return value; + } + return value & ((((uint64_t)1) << bits) - 1); +} + /****************************************************************************** * CVF tests *****************************************************************************/ @@ -677,6 +688,146 @@ static void jpeg2000_payload(void **state) assert_memory_equal(jpeg2000->payload, payload, sizeof(payload)); } +static void cvf_typed_fields_v0(void **state) +{ + (void)state; + uint8_t pdu[AVTP_CVF_HEADER_LEN_V1]; + Avtp_Cvf_t *cvf = (Avtp_Cvf_t *)pdu; + + Avtp_Cvf_Init(cvf); + + for (uint8_t f = 0; f < AVTP_CVF_FIELD_MAX; f++) { + uint8_t bits = Avtp_CvfFieldDescV0[f].bits; + uint64_t value = 0xA5A5A5A5A5A5A5A5ULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_CvfFields_t field = (Avtp_CvfFields_t)f; + + Avtp_Cvf_SetField_V0(cvf, field, value); + assert_int_equal(Avtp_Cvf_GetField_V0(cvf, field), expected); + assert_int_equal(Avtp_Cvf_GetField(cvf, field), expected); + assert_int_equal(Avtp_GetField(Avtp_CvfFieldDescV0, AVTP_CVF_FIELD_MAX, pdu, f), expected); + } +} + +static void cvf_typed_fields_v1(void **state) +{ + (void)state; + uint8_t pdu[AVTP_CVF_HEADER_LEN_V1]; + Avtp_CvfV1_t *cvf = (Avtp_CvfV1_t *)pdu; + + Avtp_Cvf_InitV1(cvf); + + for (uint8_t f = 0; f < AVTP_CVF_FIELD_MAX; f++) { + uint8_t bits = Avtp_CvfFieldDescV1[f].bits; + uint64_t value = 0x5A5A5A5A5A5A5A5AULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_CvfFields_t field = (Avtp_CvfFields_t)f; + + Avtp_Cvf_SetField_V1(cvf, field, value); + assert_int_equal(Avtp_Cvf_GetField_V1(cvf, field), expected); + assert_int_equal(Avtp_Cvf_GetField((Avtp_Cvf_t *)cvf, field), expected); + assert_int_equal(Avtp_GetField(Avtp_CvfFieldDescV1, AVTP_CVF_FIELD_MAX, pdu, f), expected); + } +} + +static void cvf_typed_named(void **state) +{ + (void)state; + uint8_t pdu[AVTP_CVF_HEADER_LEN_V1]; + Avtp_Cvf_t *v0 = (Avtp_Cvf_t *)pdu; + Avtp_CvfV1_t *v1 = (Avtp_CvfV1_t *)pdu; + + /* Version 0. */ + Avtp_Cvf_Init(v0); + Avtp_Cvf_SetSv_V0(v0, true); + Avtp_Cvf_SetSequenceNum_V0(v0, 0x55); + Avtp_Cvf_SetStreamId_V0(v0, 0xAABBCCDDEEFF0001ULL); + Avtp_Cvf_SetAvtpTimestamp_V0(v0, 0x80C0FFEE); + Avtp_Cvf_SetFormat_V0(v0, AVTP_CVF_FORMAT_RFC); + Avtp_Cvf_SetFormatSubtype_V0(v0, AVTP_CVF_FORMAT_SUBTYPE_MJPEG); + Avtp_Cvf_SetStreamDataLength_V0(v0, 0xAAAA); + Avtp_Cvf_SetPtv_V0(v0, true); + Avtp_Cvf_SetM_V0(v0, true); + Avtp_Cvf_SetEvt_V0(v0, 0xA); + + assert_true(Avtp_Cvf_IsSv_V0(v0)); + assert_int_equal(Avtp_Cvf_GetSequenceNum_V0(v0), 0x55); + assert_int_equal(Avtp_Cvf_GetStreamId_V0(v0), 0xAABBCCDDEEFF0001ULL); + assert_int_equal(Avtp_Cvf_GetAvtpTimestamp_V0(v0), 0x80C0FFEE); + assert_int_equal(Avtp_Cvf_GetFormat_V0(v0), AVTP_CVF_FORMAT_RFC); + assert_int_equal(Avtp_Cvf_GetFormatSubtype_V0(v0), AVTP_CVF_FORMAT_SUBTYPE_MJPEG); + assert_int_equal(Avtp_Cvf_GetStreamDataLength_V0(v0), 0xAAAA); + assert_true(Avtp_Cvf_IsPtv_V0(v0)); + assert_true(Avtp_Cvf_IsM_V0(v0)); + assert_int_equal(Avtp_Cvf_GetEvt_V0(v0), 0xA); + assert_int_equal(Avtp_Cvf_GetPtpGrandmasterIdentity_V0(v0), 0); + + /* The version-dispatched accessors agree with the version 0 variants. */ + assert_int_equal(Avtp_Cvf_GetSequenceNum(v0), Avtp_Cvf_GetSequenceNum_V0(v0)); + assert_int_equal(Avtp_Cvf_GetStreamId(v0), Avtp_Cvf_GetStreamId_V0(v0)); + assert_int_equal(Avtp_Cvf_GetAvtpTimestamp(v0), Avtp_Cvf_GetAvtpTimestamp_V0(v0)); + assert_int_equal(Avtp_Cvf_GetFormat(v0), Avtp_Cvf_GetFormat_V0(v0)); + assert_int_equal(Avtp_Cvf_GetFormatSubtype(v0), Avtp_Cvf_GetFormatSubtype_V0(v0)); + assert_int_equal(Avtp_Cvf_GetStreamDataLength(v0), Avtp_Cvf_GetStreamDataLength_V0(v0)); + assert_int_equal(Avtp_Cvf_GetEvt(v0), Avtp_Cvf_GetEvt_V0(v0)); + + /* Version 1. */ + Avtp_Cvf_InitV1(v1); + Avtp_Cvf_SetSv_V1(v1, true); + Avtp_Cvf_SetSequenceNum_V1(v1, 0x12345678); + Avtp_Cvf_SetStreamId_V1(v1, 0x0102030405060708ULL); + Avtp_Cvf_SetAvtpTimestamp_V1(v1, 0x1122334455667788ULL); + Avtp_Cvf_SetPtpGrandmasterIdentity_V1(v1, 0x99AABBCCDDEEFF00ULL); + Avtp_Cvf_SetFormat_V1(v1, AVTP_CVF_FORMAT_RFC); + Avtp_Cvf_SetFormatSubtype_V1(v1, AVTP_CVF_FORMAT_SUBTYPE_H264); + Avtp_Cvf_SetStreamDataLength_V1(v1, 0xBBBB); + Avtp_Cvf_SetPtv_V1(v1, true); + Avtp_Cvf_SetM_V1(v1, true); + Avtp_Cvf_SetEvt_V1(v1, 0xB); + + assert_true(Avtp_Cvf_IsSv_V1(v1)); + assert_int_equal(Avtp_Cvf_GetSequenceNum_V1(v1), 0x12345678); + assert_int_equal(Avtp_Cvf_GetStreamId_V1(v1), 0x0102030405060708ULL); + assert_int_equal(Avtp_Cvf_GetAvtpTimestamp_V1(v1), 0x1122334455667788ULL); + assert_int_equal(Avtp_Cvf_GetPtpGrandmasterIdentity_V1(v1), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Cvf_GetFormat_V1(v1), AVTP_CVF_FORMAT_RFC); + assert_int_equal(Avtp_Cvf_GetFormatSubtype_V1(v1), AVTP_CVF_FORMAT_SUBTYPE_H264); + assert_int_equal(Avtp_Cvf_GetStreamDataLength_V1(v1), 0xBBBB); + assert_true(Avtp_Cvf_IsPtv_V1(v1)); + assert_true(Avtp_Cvf_IsM_V1(v1)); + assert_int_equal(Avtp_Cvf_GetEvt_V1(v1), 0xB); + + /* The version-dispatched accessors agree with the version 1 variants. */ + assert_int_equal(Avtp_Cvf_GetSequenceNum(v0), Avtp_Cvf_GetSequenceNum_V1(v1)); + assert_int_equal(Avtp_Cvf_GetStreamId(v0), Avtp_Cvf_GetStreamId_V1(v1)); + assert_int_equal(Avtp_Cvf_GetAvtpTimestamp(v0), Avtp_Cvf_GetAvtpTimestamp_V1(v1)); + assert_int_equal(Avtp_Cvf_GetPtpGrandmasterIdentity(v0), + Avtp_Cvf_GetPtpGrandmasterIdentity_V1(v1)); + assert_int_equal(Avtp_Cvf_GetFormat(v0), Avtp_Cvf_GetFormat_V1(v1)); + assert_int_equal(Avtp_Cvf_GetFormatSubtype(v0), Avtp_Cvf_GetFormatSubtype_V1(v1)); + assert_int_equal(Avtp_Cvf_GetStreamDataLength(v0), Avtp_Cvf_GetStreamDataLength_V1(v1)); + assert_int_equal(Avtp_Cvf_GetEvt(v0), Avtp_Cvf_GetEvt_V1(v1)); +} + +static void cvf_typed_helpers(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t payload[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + + Avtp_Cvf_Init((Avtp_Cvf_t *)pdu); + assert_int_equal(Avtp_Cvf_GetHeaderLen_V0((Avtp_Cvf_t *)pdu), AVTP_CVF_HEADER_LEN_V0); + assert_ptr_equal(Avtp_Cvf_GetPayload_V0((Avtp_Cvf_t *)pdu), pdu + AVTP_CVF_HEADER_LEN_V0); + Avtp_Cvf_SetPayload_V0((Avtp_Cvf_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_CVF_HEADER_LEN_V0, payload, sizeof(payload)); + + Avtp_Cvf_InitV1((Avtp_CvfV1_t *)pdu); + assert_int_equal(Avtp_Cvf_GetHeaderLen_V1((Avtp_CvfV1_t *)pdu), AVTP_CVF_HEADER_LEN_V1); + assert_ptr_equal(Avtp_Cvf_GetPayload_V1((Avtp_CvfV1_t *)pdu), pdu + AVTP_CVF_HEADER_LEN_V1); + Avtp_Cvf_SetPayload_V1((Avtp_CvfV1_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_CVF_HEADER_LEN_V1, payload, sizeof(payload)); +} + int main(void) { const struct CMUnitTest tests[] = { @@ -690,6 +841,10 @@ int main(void) cmocka_unit_test(cvf_v1_layout), cmocka_unit_test(cvf_payload), cmocka_unit_test(cvf_get_set_field), + cmocka_unit_test(cvf_typed_fields_v0), + cmocka_unit_test(cvf_typed_fields_v1), + cmocka_unit_test(cvf_typed_named), + cmocka_unit_test(cvf_typed_helpers), cmocka_unit_test(mjpeg_init), cmocka_unit_test(mjpeg_is_valid), cmocka_unit_test(mjpeg_field_descriptors_cover_header), diff --git a/unit/test-ntscf.c b/unit/test-ntscf.c index 81a180db..5a176c10 100644 --- a/unit/test-ntscf.c +++ b/unit/test-ntscf.c @@ -54,6 +54,17 @@ static uint32_t read_quadlet(const uint8_t *pdu, size_t quadlet) return ntohl(word); } +static uint64_t mask_field_value(uint8_t bits, uint64_t value) +{ + if (bits == 0) { + return 0; + } + if (bits >= 64) { + return value; + } + return value & ((((uint64_t)1) << bits) - 1); +} + static void ntscf_init(void **state) { (void)state; @@ -283,6 +294,121 @@ static void ntscf_get_set_field(void **state) assert_int_equal(Avtp_Ntscf_GetField(ntscf, AVTP_NTSCF_FIELD_R), 0x1); } +static void ntscf_typed_fields_v0(void **state) +{ + (void)state; + uint8_t pdu[AVTP_NTSCF_HEADER_LEN_V1]; + Avtp_Ntscf_t *ntscf = (Avtp_Ntscf_t *)pdu; + + Avtp_Ntscf_Init(ntscf); + + for (uint8_t f = 0; f < AVTP_NTSCF_FIELD_MAX; f++) { + uint8_t bits = Avtp_NtscfFieldDescV0[f].bits; + uint64_t value = 0xA5A5A5A5A5A5A5A5ULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_NtscfFields_t field = (Avtp_NtscfFields_t)f; + + Avtp_Ntscf_SetField_V0(ntscf, field, value); + assert_int_equal(Avtp_Ntscf_GetField_V0(ntscf, field), expected); + assert_int_equal(Avtp_Ntscf_GetField(ntscf, field), expected); + assert_int_equal(Avtp_GetField(Avtp_NtscfFieldDescV0, AVTP_NTSCF_FIELD_MAX, pdu, f), + expected); + } +} + +static void ntscf_typed_fields_v1(void **state) +{ + (void)state; + uint8_t pdu[AVTP_NTSCF_HEADER_LEN_V1]; + Avtp_NtscfV1_t *ntscf = (Avtp_NtscfV1_t *)pdu; + + Avtp_Ntscf_InitV1(ntscf); + + for (uint8_t f = 0; f < AVTP_NTSCF_FIELD_MAX; f++) { + uint8_t bits = Avtp_NtscfFieldDescV1[f].bits; + uint64_t value = 0x5A5A5A5A5A5A5A5AULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_NtscfFields_t field = (Avtp_NtscfFields_t)f; + + Avtp_Ntscf_SetField_V1(ntscf, field, value); + assert_int_equal(Avtp_Ntscf_GetField_V1(ntscf, field), expected); + assert_int_equal(Avtp_Ntscf_GetField((Avtp_Ntscf_t *)ntscf, field), expected); + assert_int_equal(Avtp_GetField(Avtp_NtscfFieldDescV1, AVTP_NTSCF_FIELD_MAX, pdu, f), + expected); + } +} + +static void ntscf_typed_named(void **state) +{ + (void)state; + uint8_t pdu[AVTP_NTSCF_HEADER_LEN_V1]; + Avtp_Ntscf_t *v0 = (Avtp_Ntscf_t *)pdu; + Avtp_NtscfV1_t *v1 = (Avtp_NtscfV1_t *)pdu; + + /* Version 0. */ + Avtp_Ntscf_Init(v0); + Avtp_Ntscf_SetSv_V0(v0, true); + Avtp_Ntscf_SetSequenceNum_V0(v0, 0xAB); + Avtp_Ntscf_SetNtscfDataLength_V0(v0, 0x123); + Avtp_Ntscf_SetStreamId_V0(v0, 0xAABBCCDDEEFF0001ULL); + + assert_true(Avtp_Ntscf_IsSv_V0(v0)); + assert_int_equal(Avtp_Ntscf_GetSequenceNum_V0(v0), 0xAB); + assert_int_equal(Avtp_Ntscf_GetSequenceNumLsb_V0(v0), 0xAB); + assert_int_equal(Avtp_Ntscf_GetNtscfDataLength_V0(v0), 0x123); + assert_int_equal(Avtp_Ntscf_GetStreamId_V0(v0), 0xAABBCCDDEEFF0001ULL); + assert_int_equal(Avtp_Ntscf_GetPtpGrandmasterIdentity_V0(v0), 0); + + /* The version-dispatched accessors agree with the version 0 variants. */ + assert_int_equal(Avtp_Ntscf_GetSequenceNum(v0), Avtp_Ntscf_GetSequenceNum_V0(v0)); + assert_int_equal(Avtp_Ntscf_GetSequenceNumLsb(v0), Avtp_Ntscf_GetSequenceNumLsb_V0(v0)); + assert_int_equal(Avtp_Ntscf_GetNtscfDataLength(v0), Avtp_Ntscf_GetNtscfDataLength_V0(v0)); + assert_int_equal(Avtp_Ntscf_GetStreamId(v0), Avtp_Ntscf_GetStreamId_V0(v0)); + + /* Version 1. */ + Avtp_Ntscf_InitV1(v1); + Avtp_Ntscf_SetSv_V1(v1, true); + Avtp_Ntscf_SetSequenceNum_V1(v1, 0x12345678); + Avtp_Ntscf_SetNtscfDataLength_V1(v1, 0x456); + Avtp_Ntscf_SetPtpGrandmasterIdentity_V1(v1, 0x99AABBCCDDEEFF00ULL); + Avtp_Ntscf_SetStreamId_V1(v1, 0x0102030405060708ULL); + + assert_true(Avtp_Ntscf_IsSv_V1(v1)); + assert_int_equal(Avtp_Ntscf_GetSequenceNum_V1(v1), 0x12345678); + assert_int_equal(Avtp_Ntscf_GetSequenceNumLsb_V1(v1), 0x78); + assert_int_equal(Avtp_Ntscf_GetNtscfDataLength_V1(v1), 0x456); + assert_int_equal(Avtp_Ntscf_GetPtpGrandmasterIdentity_V1(v1), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Ntscf_GetStreamId_V1(v1), 0x0102030405060708ULL); + + /* The version-dispatched accessors agree with the version 1 variants. */ + assert_int_equal(Avtp_Ntscf_GetSequenceNum(v0), Avtp_Ntscf_GetSequenceNum_V1(v1)); + assert_int_equal(Avtp_Ntscf_GetSequenceNumLsb(v0), Avtp_Ntscf_GetSequenceNumLsb_V1(v1)); + assert_int_equal(Avtp_Ntscf_GetNtscfDataLength(v0), Avtp_Ntscf_GetNtscfDataLength_V1(v1)); + assert_int_equal(Avtp_Ntscf_GetPtpGrandmasterIdentity(v0), + Avtp_Ntscf_GetPtpGrandmasterIdentity_V1(v1)); + assert_int_equal(Avtp_Ntscf_GetStreamId(v0), Avtp_Ntscf_GetStreamId_V1(v1)); +} + +static void ntscf_typed_helpers(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t payload[4] = {0xDE, 0xAD, 0xBE, 0xEF}; + + Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); + assert_int_equal(Avtp_Ntscf_GetHeaderLen_V0((Avtp_Ntscf_t *)pdu), AVTP_NTSCF_HEADER_LEN_V0); + assert_ptr_equal(Avtp_Ntscf_GetPayload_V0((Avtp_Ntscf_t *)pdu), pdu + AVTP_NTSCF_HEADER_LEN_V0); + Avtp_Ntscf_SetPayload_V0((Avtp_Ntscf_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_NTSCF_HEADER_LEN_V0, payload, sizeof(payload)); + + Avtp_Ntscf_InitV1((Avtp_NtscfV1_t *)pdu); + assert_int_equal(Avtp_Ntscf_GetHeaderLen_V1((Avtp_NtscfV1_t *)pdu), AVTP_NTSCF_HEADER_LEN_V1); + assert_ptr_equal(Avtp_Ntscf_GetPayload_V1((Avtp_NtscfV1_t *)pdu), + pdu + AVTP_NTSCF_HEADER_LEN_V1); + Avtp_Ntscf_SetPayload_V1((Avtp_NtscfV1_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_NTSCF_HEADER_LEN_V1, payload, sizeof(payload)); +} + int main(void) { const struct CMUnitTest tests[] = { @@ -295,6 +421,10 @@ int main(void) cmocka_unit_test(ntscf_v1_layout), cmocka_unit_test(ntscf_payload), cmocka_unit_test(ntscf_get_set_field), + cmocka_unit_test(ntscf_typed_fields_v0), + cmocka_unit_test(ntscf_typed_fields_v1), + cmocka_unit_test(ntscf_typed_named), + cmocka_unit_test(ntscf_typed_helpers), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/unit/test-pcm.c b/unit/test-pcm.c index 4a656904..0e1cf442 100644 --- a/unit/test-pcm.c +++ b/unit/test-pcm.c @@ -55,6 +55,17 @@ static uint32_t read_quadlet(const uint8_t *pdu, size_t quadlet) return ntohl(word); } +static uint64_t mask_field_value(uint8_t bits, uint64_t value) +{ + if (bits == 0) { + return 0; + } + if (bits >= 64) { + return value; + } + return value & ((((uint64_t)1) << bits) - 1); +} + /* Initializes a minimal but valid AAF PCM frame. */ static void init_valid_pcm(Avtp_Pcm_t *pdu) { @@ -457,6 +468,154 @@ static void pcm_get_set_field(void **state) assert_int_equal(Avtp_Pcm_GetField(pcm, AVTP_PCM_FIELD_RESERVED2), 0xAB); } +static void pcm_typed_fields_v0(void **state) +{ + (void)state; + uint8_t pdu[AVTP_PCM_HEADER_LEN_V1]; + Avtp_Pcm_t *pcm = (Avtp_Pcm_t *)pdu; + + Avtp_Pcm_Init(pcm); + + for (uint8_t f = 0; f < AVTP_PCM_FIELD_MAX; f++) { + uint8_t bits = Avtp_PcmFieldDescV0[f].bits; + uint64_t value = 0xA5A5A5A5A5A5A5A5ULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_PcmFields_t field = (Avtp_PcmFields_t)f; + + Avtp_Pcm_SetField_V0(pcm, field, value); + assert_int_equal(Avtp_Pcm_GetField_V0(pcm, field), expected); + assert_int_equal(Avtp_Pcm_GetField(pcm, field), expected); + assert_int_equal(Avtp_GetField(Avtp_PcmFieldDescV0, AVTP_PCM_FIELD_MAX, pdu, f), expected); + } +} + +static void pcm_typed_fields_v1(void **state) +{ + (void)state; + uint8_t pdu[AVTP_PCM_HEADER_LEN_V1]; + Avtp_PcmV1_t *pcm = (Avtp_PcmV1_t *)pdu; + + Avtp_Pcm_InitV1(pcm); + + for (uint8_t f = 0; f < AVTP_PCM_FIELD_MAX; f++) { + uint8_t bits = Avtp_PcmFieldDescV1[f].bits; + uint64_t value = 0x5A5A5A5A5A5A5A5AULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_PcmFields_t field = (Avtp_PcmFields_t)f; + + Avtp_Pcm_SetField_V1(pcm, field, value); + assert_int_equal(Avtp_Pcm_GetField_V1(pcm, field), expected); + assert_int_equal(Avtp_Pcm_GetField((Avtp_Pcm_t *)pcm, field), expected); + assert_int_equal(Avtp_GetField(Avtp_PcmFieldDescV1, AVTP_PCM_FIELD_MAX, pdu, f), expected); + } +} + +static void pcm_typed_named(void **state) +{ + (void)state; + uint8_t pdu[AVTP_PCM_HEADER_LEN_V1]; + Avtp_Pcm_t *v0 = (Avtp_Pcm_t *)pdu; + Avtp_PcmV1_t *v1 = (Avtp_PcmV1_t *)pdu; + + /* Version 0. */ + Avtp_Pcm_Init(v0); + Avtp_Pcm_SetSv_V0(v0, true); + Avtp_Pcm_SetSequenceNum_V0(v0, 0x55); + Avtp_Pcm_SetStreamId_V0(v0, 0xAABBCCDDEEFF0001ULL); + Avtp_Pcm_SetAvtpTimestamp_V0(v0, 0x80C0FFEE); + Avtp_Pcm_SetFormat_V0(v0, AVTP_AAF_FORMAT_INT_16BIT); + Avtp_Pcm_SetNsr_V0(v0, AVTP_PCM_NSR_48KHZ); + Avtp_Pcm_SetChannelsPerFrame_V0(v0, 2); + Avtp_Pcm_SetBitDepth_V0(v0, 16); + Avtp_Pcm_SetStreamDataLength_V0(v0, 0xAAAA); + Avtp_Pcm_SetSp_V0(v0, true); + Avtp_Pcm_SetEvt_V0(v0, 0xA); + + assert_true(Avtp_Pcm_IsSv_V0(v0)); + assert_int_equal(Avtp_Pcm_GetSequenceNum_V0(v0), 0x55); + assert_int_equal(Avtp_Pcm_GetStreamId_V0(v0), 0xAABBCCDDEEFF0001ULL); + assert_int_equal(Avtp_Pcm_GetAvtpTimestamp_V0(v0), 0x80C0FFEE); + assert_int_equal(Avtp_Pcm_GetFormat_V0(v0), AVTP_AAF_FORMAT_INT_16BIT); + assert_int_equal(Avtp_Pcm_GetNsr_V0(v0), AVTP_PCM_NSR_48KHZ); + assert_int_equal(Avtp_Pcm_GetChannelsPerFrame_V0(v0), 2); + assert_int_equal(Avtp_Pcm_GetBitDepth_V0(v0), 16); + assert_int_equal(Avtp_Pcm_GetStreamDataLength_V0(v0), 0xAAAA); + assert_true(Avtp_Pcm_IsSp_V0(v0)); + assert_int_equal(Avtp_Pcm_GetEvt_V0(v0), 0xA); + assert_int_equal(Avtp_Pcm_GetPtpGrandmasterIdentity_V0(v0), 0); + + /* The version-dispatched accessors agree with the version 0 variants. */ + assert_int_equal(Avtp_Pcm_GetSequenceNum(v0), Avtp_Pcm_GetSequenceNum_V0(v0)); + assert_int_equal(Avtp_Pcm_GetStreamId(v0), Avtp_Pcm_GetStreamId_V0(v0)); + assert_int_equal(Avtp_Pcm_GetAvtpTimestamp(v0), Avtp_Pcm_GetAvtpTimestamp_V0(v0)); + assert_int_equal(Avtp_Pcm_GetFormat(v0), Avtp_Pcm_GetFormat_V0(v0)); + assert_int_equal(Avtp_Pcm_GetNsr(v0), Avtp_Pcm_GetNsr_V0(v0)); + assert_int_equal(Avtp_Pcm_GetChannelsPerFrame(v0), Avtp_Pcm_GetChannelsPerFrame_V0(v0)); + assert_int_equal(Avtp_Pcm_GetBitDepth(v0), Avtp_Pcm_GetBitDepth_V0(v0)); + assert_int_equal(Avtp_Pcm_GetStreamDataLength(v0), Avtp_Pcm_GetStreamDataLength_V0(v0)); + assert_int_equal(Avtp_Pcm_GetEvt(v0), Avtp_Pcm_GetEvt_V0(v0)); + + /* Version 1. */ + Avtp_Pcm_InitV1(v1); + Avtp_Pcm_SetSv_V1(v1, true); + Avtp_Pcm_SetSequenceNum_V1(v1, 0x12345678); + Avtp_Pcm_SetStreamId_V1(v1, 0x0102030405060708ULL); + Avtp_Pcm_SetAvtpTimestamp_V1(v1, 0x1122334455667788ULL); + Avtp_Pcm_SetPtpGrandmasterIdentity_V1(v1, 0x99AABBCCDDEEFF00ULL); + Avtp_Pcm_SetFormat_V1(v1, AVTP_AAF_FORMAT_FLOAT_32BIT); + Avtp_Pcm_SetNsr_V1(v1, AVTP_PCM_NSR_96KHZ); + Avtp_Pcm_SetChannelsPerFrame_V1(v1, 8); + Avtp_Pcm_SetBitDepth_V1(v1, 32); + Avtp_Pcm_SetStreamDataLength_V1(v1, 0xBBBB); + Avtp_Pcm_SetSp_V1(v1, true); + Avtp_Pcm_SetEvt_V1(v1, 0xB); + + assert_true(Avtp_Pcm_IsSv_V1(v1)); + assert_int_equal(Avtp_Pcm_GetSequenceNum_V1(v1), 0x12345678); + assert_int_equal(Avtp_Pcm_GetStreamId_V1(v1), 0x0102030405060708ULL); + assert_int_equal(Avtp_Pcm_GetAvtpTimestamp_V1(v1), 0x1122334455667788ULL); + assert_int_equal(Avtp_Pcm_GetPtpGrandmasterIdentity_V1(v1), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Pcm_GetFormat_V1(v1), AVTP_AAF_FORMAT_FLOAT_32BIT); + assert_int_equal(Avtp_Pcm_GetNsr_V1(v1), AVTP_PCM_NSR_96KHZ); + assert_int_equal(Avtp_Pcm_GetChannelsPerFrame_V1(v1), 8); + assert_int_equal(Avtp_Pcm_GetBitDepth_V1(v1), 32); + assert_int_equal(Avtp_Pcm_GetStreamDataLength_V1(v1), 0xBBBB); + assert_true(Avtp_Pcm_IsSp_V1(v1)); + assert_int_equal(Avtp_Pcm_GetEvt_V1(v1), 0xB); + + /* The version-dispatched accessors agree with the version 1 variants. */ + assert_int_equal(Avtp_Pcm_GetSequenceNum(v0), Avtp_Pcm_GetSequenceNum_V1(v1)); + assert_int_equal(Avtp_Pcm_GetStreamId(v0), Avtp_Pcm_GetStreamId_V1(v1)); + assert_int_equal(Avtp_Pcm_GetAvtpTimestamp(v0), Avtp_Pcm_GetAvtpTimestamp_V1(v1)); + assert_int_equal(Avtp_Pcm_GetPtpGrandmasterIdentity(v0), + Avtp_Pcm_GetPtpGrandmasterIdentity_V1(v1)); + assert_int_equal(Avtp_Pcm_GetFormat(v0), Avtp_Pcm_GetFormat_V1(v1)); + assert_int_equal(Avtp_Pcm_GetNsr(v0), Avtp_Pcm_GetNsr_V1(v1)); + assert_int_equal(Avtp_Pcm_GetChannelsPerFrame(v0), Avtp_Pcm_GetChannelsPerFrame_V1(v1)); + assert_int_equal(Avtp_Pcm_GetBitDepth(v0), Avtp_Pcm_GetBitDepth_V1(v1)); + assert_int_equal(Avtp_Pcm_GetStreamDataLength(v0), Avtp_Pcm_GetStreamDataLength_V1(v1)); + assert_int_equal(Avtp_Pcm_GetEvt(v0), Avtp_Pcm_GetEvt_V1(v1)); +} + +static void pcm_typed_helpers(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t payload[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + + Avtp_Pcm_Init((Avtp_Pcm_t *)pdu); + assert_int_equal(Avtp_Pcm_GetHeaderLen_V0((Avtp_Pcm_t *)pdu), AVTP_PCM_HEADER_LEN_V0); + assert_ptr_equal(Avtp_Pcm_GetPayload_V0((Avtp_Pcm_t *)pdu), pdu + AVTP_PCM_HEADER_LEN_V0); + Avtp_Pcm_SetPayload_V0((Avtp_Pcm_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_PCM_HEADER_LEN_V0, payload, sizeof(payload)); + + Avtp_Pcm_InitV1((Avtp_PcmV1_t *)pdu); + assert_int_equal(Avtp_Pcm_GetHeaderLen_V1((Avtp_PcmV1_t *)pdu), AVTP_PCM_HEADER_LEN_V1); + assert_ptr_equal(Avtp_Pcm_GetPayload_V1((Avtp_PcmV1_t *)pdu), pdu + AVTP_PCM_HEADER_LEN_V1); + Avtp_Pcm_SetPayload_V1((Avtp_PcmV1_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_PCM_HEADER_LEN_V1, payload, sizeof(payload)); +} + int main(void) { const struct CMUnitTest tests[] = { @@ -471,6 +630,10 @@ int main(void) cmocka_unit_test(pcm_v1_layout), cmocka_unit_test(pcm_payload), cmocka_unit_test(pcm_get_set_field), + cmocka_unit_test(pcm_typed_fields_v0), + cmocka_unit_test(pcm_typed_fields_v1), + cmocka_unit_test(pcm_typed_named), + cmocka_unit_test(pcm_typed_helpers), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/unit/test-rvf.c b/unit/test-rvf.c index ce7b6adc..58e0303d 100644 --- a/unit/test-rvf.c +++ b/unit/test-rvf.c @@ -57,6 +57,17 @@ static uint32_t read_quadlet(const uint8_t *pdu, size_t quadlet) return ntohl(word); } +static uint64_t mask_field_value(uint8_t bits, uint64_t value) +{ + if (bits == 0) { + return 0; + } + if (bits >= 64) { + return value; + } + return value & ((((uint64_t)1) << bits) - 1); +} + /* Initializes a minimal but valid RVF frame. */ static void init_valid_rvf(Avtp_Rvf_t *pdu) { @@ -556,6 +567,158 @@ static void rvf_raw_header_overlay(void **state) assert_true(Avtp_Rvf_IsValid(rvf, AVTP_RVF_HEADER_LEN_V0 + AVTP_RVF_RAW_HEADER_LEN)); } +static void rvf_typed_fields_v0(void **state) +{ + (void)state; + uint8_t pdu[AVTP_RVF_HEADER_LEN_V1]; + Avtp_Rvf_t *rvf = (Avtp_Rvf_t *)pdu; + + Avtp_Rvf_Init(rvf); + + for (uint8_t f = 0; f < AVTP_RVF_FIELD_MAX; f++) { + uint8_t bits = Avtp_RvfFieldDescV0[f].bits; + uint64_t value = 0xA5A5A5A5A5A5A5A5ULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_RvfFields_t field = (Avtp_RvfFields_t)f; + + Avtp_Rvf_SetField_V0(rvf, field, value); + assert_int_equal(Avtp_Rvf_GetField_V0(rvf, field), expected); + assert_int_equal(Avtp_Rvf_GetField(rvf, field), expected); + assert_int_equal(Avtp_GetField(Avtp_RvfFieldDescV0, AVTP_RVF_FIELD_MAX, pdu, f), expected); + } +} + +static void rvf_typed_fields_v1(void **state) +{ + (void)state; + uint8_t pdu[AVTP_RVF_HEADER_LEN_V1]; + Avtp_RvfV1_t *rvf = (Avtp_RvfV1_t *)pdu; + + Avtp_Rvf_InitV1(rvf); + + for (uint8_t f = 0; f < AVTP_RVF_FIELD_MAX; f++) { + uint8_t bits = Avtp_RvfFieldDescV1[f].bits; + uint64_t value = 0x5A5A5A5A5A5A5A5AULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_RvfFields_t field = (Avtp_RvfFields_t)f; + + Avtp_Rvf_SetField_V1(rvf, field, value); + assert_int_equal(Avtp_Rvf_GetField_V1(rvf, field), expected); + assert_int_equal(Avtp_Rvf_GetField((Avtp_Rvf_t *)rvf, field), expected); + assert_int_equal(Avtp_GetField(Avtp_RvfFieldDescV1, AVTP_RVF_FIELD_MAX, pdu, f), expected); + } +} + +static void rvf_typed_named(void **state) +{ + (void)state; + uint8_t pdu[AVTP_RVF_HEADER_LEN_V1]; + Avtp_Rvf_t *v0 = (Avtp_Rvf_t *)pdu; + Avtp_RvfV1_t *v1 = (Avtp_RvfV1_t *)pdu; + + /* Version 0. */ + Avtp_Rvf_Init(v0); + Avtp_Rvf_SetSv_V0(v0, true); + Avtp_Rvf_SetSequenceNum_V0(v0, 0x55); + Avtp_Rvf_SetStreamId_V0(v0, 0xAABBCCDDEEFF0001ULL); + Avtp_Rvf_SetAvtpTimestamp_V0(v0, 0x80C0FFEE); + Avtp_Rvf_SetStreamDataLength_V0(v0, 0xAAAA); + Avtp_Rvf_SetActivePixels_V0(v0, 1920); + Avtp_Rvf_SetTotalLines_V0(v0, 1080); + Avtp_Rvf_SetAp_V0(v0, true); + Avtp_Rvf_SetF_V0(v0, true); + Avtp_Rvf_SetEf_V0(v0, true); + Avtp_Rvf_SetEvt_V0(v0, 0xA); + Avtp_Rvf_SetPd_V0(v0, true); + Avtp_Rvf_SetI_V0(v0, true); + + assert_true(Avtp_Rvf_IsSv_V0(v0)); + assert_int_equal(Avtp_Rvf_GetSequenceNum_V0(v0), 0x55); + assert_int_equal(Avtp_Rvf_GetStreamId_V0(v0), 0xAABBCCDDEEFF0001ULL); + assert_int_equal(Avtp_Rvf_GetAvtpTimestamp_V0(v0), 0x80C0FFEE); + assert_int_equal(Avtp_Rvf_GetStreamDataLength_V0(v0), 0xAAAA); + assert_int_equal(Avtp_Rvf_GetActivePixels_V0(v0), 1920); + assert_int_equal(Avtp_Rvf_GetTotalLines_V0(v0), 1080); + assert_true(Avtp_Rvf_IsAp_V0(v0)); + assert_true(Avtp_Rvf_IsF_V0(v0)); + assert_true(Avtp_Rvf_IsEf_V0(v0)); + assert_int_equal(Avtp_Rvf_GetEvt_V0(v0), 0xA); + assert_true(Avtp_Rvf_IsPd_V0(v0)); + assert_true(Avtp_Rvf_IsI_V0(v0)); + assert_int_equal(Avtp_Rvf_GetPtpGrandmasterIdentity_V0(v0), 0); + + /* The version-dispatched accessors agree with the version 0 variants. */ + assert_int_equal(Avtp_Rvf_GetSequenceNum(v0), Avtp_Rvf_GetSequenceNum_V0(v0)); + assert_int_equal(Avtp_Rvf_GetStreamId(v0), Avtp_Rvf_GetStreamId_V0(v0)); + assert_int_equal(Avtp_Rvf_GetAvtpTimestamp(v0), Avtp_Rvf_GetAvtpTimestamp_V0(v0)); + assert_int_equal(Avtp_Rvf_GetStreamDataLength(v0), Avtp_Rvf_GetStreamDataLength_V0(v0)); + assert_int_equal(Avtp_Rvf_GetActivePixels(v0), Avtp_Rvf_GetActivePixels_V0(v0)); + assert_int_equal(Avtp_Rvf_GetTotalLines(v0), Avtp_Rvf_GetTotalLines_V0(v0)); + assert_int_equal(Avtp_Rvf_GetEvt(v0), Avtp_Rvf_GetEvt_V0(v0)); + + /* Version 1. */ + Avtp_Rvf_InitV1(v1); + Avtp_Rvf_SetSv_V1(v1, true); + Avtp_Rvf_SetSequenceNum_V1(v1, 0x12345678); + Avtp_Rvf_SetStreamId_V1(v1, 0x0102030405060708ULL); + Avtp_Rvf_SetAvtpTimestamp_V1(v1, 0x1122334455667788ULL); + Avtp_Rvf_SetPtpGrandmasterIdentity_V1(v1, 0x99AABBCCDDEEFF00ULL); + Avtp_Rvf_SetStreamDataLength_V1(v1, 0xBBBB); + Avtp_Rvf_SetActivePixels_V1(v1, 1280); + Avtp_Rvf_SetTotalLines_V1(v1, 720); + Avtp_Rvf_SetAp_V1(v1, true); + Avtp_Rvf_SetF_V1(v1, true); + Avtp_Rvf_SetEf_V1(v1, true); + Avtp_Rvf_SetEvt_V1(v1, 0xB); + Avtp_Rvf_SetPd_V1(v1, true); + Avtp_Rvf_SetI_V1(v1, true); + + assert_true(Avtp_Rvf_IsSv_V1(v1)); + assert_int_equal(Avtp_Rvf_GetSequenceNum_V1(v1), 0x12345678); + assert_int_equal(Avtp_Rvf_GetStreamId_V1(v1), 0x0102030405060708ULL); + assert_int_equal(Avtp_Rvf_GetAvtpTimestamp_V1(v1), 0x1122334455667788ULL); + assert_int_equal(Avtp_Rvf_GetPtpGrandmasterIdentity_V1(v1), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Rvf_GetStreamDataLength_V1(v1), 0xBBBB); + assert_int_equal(Avtp_Rvf_GetActivePixels_V1(v1), 1280); + assert_int_equal(Avtp_Rvf_GetTotalLines_V1(v1), 720); + assert_true(Avtp_Rvf_IsAp_V1(v1)); + assert_true(Avtp_Rvf_IsF_V1(v1)); + assert_true(Avtp_Rvf_IsEf_V1(v1)); + assert_int_equal(Avtp_Rvf_GetEvt_V1(v1), 0xB); + assert_true(Avtp_Rvf_IsPd_V1(v1)); + assert_true(Avtp_Rvf_IsI_V1(v1)); + + /* The version-dispatched accessors agree with the version 1 variants. */ + assert_int_equal(Avtp_Rvf_GetSequenceNum(v0), Avtp_Rvf_GetSequenceNum_V1(v1)); + assert_int_equal(Avtp_Rvf_GetStreamId(v0), Avtp_Rvf_GetStreamId_V1(v1)); + assert_int_equal(Avtp_Rvf_GetAvtpTimestamp(v0), Avtp_Rvf_GetAvtpTimestamp_V1(v1)); + assert_int_equal(Avtp_Rvf_GetPtpGrandmasterIdentity(v0), + Avtp_Rvf_GetPtpGrandmasterIdentity_V1(v1)); + assert_int_equal(Avtp_Rvf_GetStreamDataLength(v0), Avtp_Rvf_GetStreamDataLength_V1(v1)); + assert_int_equal(Avtp_Rvf_GetActivePixels(v0), Avtp_Rvf_GetActivePixels_V1(v1)); + assert_int_equal(Avtp_Rvf_GetTotalLines(v0), Avtp_Rvf_GetTotalLines_V1(v1)); + assert_int_equal(Avtp_Rvf_GetEvt(v0), Avtp_Rvf_GetEvt_V1(v1)); +} + +static void rvf_typed_helpers(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t payload[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + + Avtp_Rvf_Init((Avtp_Rvf_t *)pdu); + assert_int_equal(Avtp_Rvf_GetHeaderLen_V0((Avtp_Rvf_t *)pdu), AVTP_RVF_HEADER_LEN_V0); + assert_ptr_equal(Avtp_Rvf_GetPayload_V0((Avtp_Rvf_t *)pdu), pdu + AVTP_RVF_HEADER_LEN_V0); + Avtp_Rvf_SetPayload_V0((Avtp_Rvf_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_RVF_HEADER_LEN_V0, payload, sizeof(payload)); + + Avtp_Rvf_InitV1((Avtp_RvfV1_t *)pdu); + assert_int_equal(Avtp_Rvf_GetHeaderLen_V1((Avtp_RvfV1_t *)pdu), AVTP_RVF_HEADER_LEN_V1); + assert_ptr_equal(Avtp_Rvf_GetPayload_V1((Avtp_RvfV1_t *)pdu), pdu + AVTP_RVF_HEADER_LEN_V1); + Avtp_Rvf_SetPayload_V1((Avtp_RvfV1_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_RVF_HEADER_LEN_V1, payload, sizeof(payload)); +} + int main(void) { const struct CMUnitTest tests[] = { @@ -575,6 +738,10 @@ int main(void) cmocka_unit_test(rvf_raw_header_field_layout), cmocka_unit_test(rvf_raw_header_payload), cmocka_unit_test(rvf_raw_header_get_set_field), + cmocka_unit_test(rvf_typed_fields_v0), + cmocka_unit_test(rvf_typed_fields_v1), + cmocka_unit_test(rvf_typed_named), + cmocka_unit_test(rvf_typed_helpers), cmocka_unit_test(rvf_raw_header_overlay), }; diff --git a/unit/test-tscf.c b/unit/test-tscf.c index 173bff6a..87c1c56f 100644 --- a/unit/test-tscf.c +++ b/unit/test-tscf.c @@ -54,6 +54,17 @@ static uint32_t read_quadlet(const uint8_t *pdu, size_t quadlet) return ntohl(word); } +static uint64_t mask_field_value(uint8_t bits, uint64_t value) +{ + if (bits == 0) { + return 0; + } + if (bits >= 64) { + return value; + } + return value & ((((uint64_t)1) << bits) - 1); +} + static void tscf_init(void **state) { (void)state; @@ -273,6 +284,128 @@ static void tscf_common_field_consistency(void **state) } } +static void tscf_typed_fields_v0(void **state) +{ + (void)state; + uint8_t pdu[AVTP_TSCF_HEADER_LEN_V1]; + Avtp_Tscf_t *tscf = (Avtp_Tscf_t *)pdu; + + Avtp_Tscf_Init(tscf); + + for (uint8_t f = 0; f < AVTP_TSCF_FIELD_MAX; f++) { + uint8_t bits = Avtp_TscfFieldDescV0[f].bits; + uint64_t value = 0xA5A5A5A5A5A5A5A5ULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_TscfFields_t field = (Avtp_TscfFields_t)f; + + Avtp_Tscf_SetField_V0(tscf, field, value); + assert_int_equal(Avtp_Tscf_GetField_V0(tscf, field), expected); + assert_int_equal(Avtp_Tscf_GetField(tscf, field), expected); + assert_int_equal(Avtp_GetField(Avtp_TscfFieldDescV0, AVTP_TSCF_FIELD_MAX, pdu, f), + expected); + } +} + +static void tscf_typed_fields_v1(void **state) +{ + (void)state; + uint8_t pdu[AVTP_TSCF_HEADER_LEN_V1]; + Avtp_TscfV1_t *tscf = (Avtp_TscfV1_t *)pdu; + + Avtp_Tscf_InitV1(tscf); + + for (uint8_t f = 0; f < AVTP_TSCF_FIELD_MAX; f++) { + uint8_t bits = Avtp_TscfFieldDescV1[f].bits; + uint64_t value = 0x5A5A5A5A5A5A5A5AULL ^ (uint64_t)f; + uint64_t expected = mask_field_value(bits, value); + Avtp_TscfFields_t field = (Avtp_TscfFields_t)f; + + Avtp_Tscf_SetField_V1(tscf, field, value); + assert_int_equal(Avtp_Tscf_GetField_V1(tscf, field), expected); + assert_int_equal(Avtp_Tscf_GetField((Avtp_Tscf_t *)tscf, field), expected); + assert_int_equal(Avtp_GetField(Avtp_TscfFieldDescV1, AVTP_TSCF_FIELD_MAX, pdu, f), + expected); + } +} + +static void tscf_typed_named(void **state) +{ + (void)state; + uint8_t pdu[AVTP_TSCF_HEADER_LEN_V1]; + Avtp_Tscf_t *v0 = (Avtp_Tscf_t *)pdu; + Avtp_TscfV1_t *v1 = (Avtp_TscfV1_t *)pdu; + + /* Version 0. */ + Avtp_Tscf_Init(v0); + Avtp_Tscf_SetSv_V0(v0, true); + Avtp_Tscf_SetSequenceNum_V0(v0, 0xAB); + Avtp_Tscf_SetStreamId_V0(v0, 0x0102030405060708ULL); + Avtp_Tscf_SetAvtpTimestamp_V0(v0, 0x80C0FFEE); + Avtp_Tscf_SetStreamDataLength_V0(v0, 0x0ABC); + + assert_true(Avtp_Tscf_IsSv_V0(v0)); + assert_int_equal(Avtp_Tscf_GetSequenceNum_V0(v0), 0xAB); + assert_int_equal(Avtp_Tscf_GetSequenceNumLsb_V0(v0), 0xAB); + assert_int_equal(Avtp_Tscf_GetStreamId_V0(v0), 0x0102030405060708ULL); + assert_int_equal(Avtp_Tscf_GetAvtpTimestamp_V0(v0), 0x80C0FFEE); + assert_int_equal(Avtp_Tscf_GetStreamDataLength_V0(v0), 0x0ABC); + assert_int_equal(Avtp_Tscf_GetPtpGrandmasterIdentity_V0(v0), 0); + + /* The version-dispatched accessors agree with the version 0 variants. */ + assert_int_equal(Avtp_Tscf_GetSequenceNum(v0), Avtp_Tscf_GetSequenceNum_V0(v0)); + assert_int_equal(Avtp_Tscf_GetSequenceNumLsb(v0), Avtp_Tscf_GetSequenceNumLsb_V0(v0)); + assert_int_equal(Avtp_Tscf_GetStreamId(v0), Avtp_Tscf_GetStreamId_V0(v0)); + assert_int_equal(Avtp_Tscf_GetAvtpTimestamp(v0), Avtp_Tscf_GetAvtpTimestamp_V0(v0)); + assert_int_equal(Avtp_Tscf_GetStreamDataLength(v0), Avtp_Tscf_GetStreamDataLength_V0(v0)); + + /* Version 1. */ + Avtp_Tscf_InitV1(v1); + Avtp_Tscf_SetSv_V1(v1, true); + Avtp_Tscf_SetSequenceNum_V1(v1, 0x12345678); + Avtp_Tscf_SetStreamId_V1(v1, 0x1122334455667788ULL); + Avtp_Tscf_SetAvtpTimestamp_V1(v1, 0x99AABBCCDDEEFF00ULL); + Avtp_Tscf_SetPtpGrandmasterIdentity_V1(v1, 0x0F1E2D3C4B5A6978ULL); + Avtp_Tscf_SetStreamDataLength_V1(v1, 0x0DEF); + + assert_true(Avtp_Tscf_IsSv_V1(v1)); + assert_int_equal(Avtp_Tscf_GetSequenceNum_V1(v1), 0x12345678); + /* sequence_num_lsb copy in format_specific_data_0 (byte 2 of quadlet 0). */ + assert_int_equal(Avtp_Tscf_GetSequenceNumLsb_V1(v1), 0x78); + assert_int_equal(pdu[2], 0x78); + assert_int_equal(Avtp_Tscf_GetStreamId_V1(v1), 0x1122334455667788ULL); + assert_int_equal(Avtp_Tscf_GetAvtpTimestamp_V1(v1), 0x99AABBCCDDEEFF00ULL); + assert_int_equal(Avtp_Tscf_GetPtpGrandmasterIdentity_V1(v1), 0x0F1E2D3C4B5A6978ULL); + assert_int_equal(Avtp_Tscf_GetStreamDataLength_V1(v1), 0x0DEF); + + /* The version-dispatched accessors agree with the version 1 variants. */ + assert_int_equal(Avtp_Tscf_GetSequenceNum(v0), Avtp_Tscf_GetSequenceNum_V1(v1)); + assert_int_equal(Avtp_Tscf_GetSequenceNumLsb(v0), Avtp_Tscf_GetSequenceNumLsb_V1(v1)); + assert_int_equal(Avtp_Tscf_GetStreamId(v0), Avtp_Tscf_GetStreamId_V1(v1)); + assert_int_equal(Avtp_Tscf_GetAvtpTimestamp(v0), Avtp_Tscf_GetAvtpTimestamp_V1(v1)); + assert_int_equal(Avtp_Tscf_GetPtpGrandmasterIdentity(v0), + Avtp_Tscf_GetPtpGrandmasterIdentity_V1(v1)); + assert_int_equal(Avtp_Tscf_GetStreamDataLength(v0), Avtp_Tscf_GetStreamDataLength_V1(v1)); +} + +static void tscf_typed_helpers(void **state) +{ + (void)state; + uint8_t pdu[MAX_PDU_SIZE]; + uint8_t payload[4] = {0xDE, 0xAD, 0xBE, 0xEF}; + + Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); + assert_int_equal(Avtp_Tscf_GetHeaderLen_V0((Avtp_Tscf_t *)pdu), AVTP_TSCF_HEADER_LEN_V0); + assert_ptr_equal(Avtp_Tscf_GetPayload_V0((Avtp_Tscf_t *)pdu), pdu + AVTP_TSCF_HEADER_LEN_V0); + Avtp_Tscf_SetPayload_V0((Avtp_Tscf_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_TSCF_HEADER_LEN_V0, payload, sizeof(payload)); + + Avtp_Tscf_InitV1((Avtp_TscfV1_t *)pdu); + assert_int_equal(Avtp_Tscf_GetHeaderLen_V1((Avtp_TscfV1_t *)pdu), AVTP_TSCF_HEADER_LEN_V1); + assert_ptr_equal(Avtp_Tscf_GetPayload_V1((Avtp_TscfV1_t *)pdu), pdu + AVTP_TSCF_HEADER_LEN_V1); + Avtp_Tscf_SetPayload_V1((Avtp_TscfV1_t *)pdu, payload, sizeof(payload)); + assert_memory_equal(pdu + AVTP_TSCF_HEADER_LEN_V1, payload, sizeof(payload)); +} + int main(void) { const struct CMUnitTest tests[] = { @@ -284,6 +417,10 @@ int main(void) cmocka_unit_test(tscf_payload), cmocka_unit_test(tscf_header_coverage), cmocka_unit_test(tscf_common_field_consistency), + cmocka_unit_test(tscf_typed_fields_v0), + cmocka_unit_test(tscf_typed_fields_v1), + cmocka_unit_test(tscf_typed_named), + cmocka_unit_test(tscf_typed_helpers), }; return cmocka_run_group_tests(tests, NULL, NULL); From 612bc37a96421eda79fd084a8f89c1ed041df8f5 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Sun, 20 Sep 2026 22:50:28 +0200 Subject: [PATCH 10/16] Inline field access engine and update docs Signed-off-by: Sebastian Schildt --- docs/api-design.md | 94 ++++++++++++--- docs/inline.md | 9 +- examples/aaf/aaf-listener.c | 30 ++--- examples/aaf/aaf-talker.c | 20 ++-- examples/acf-can/acf-can-common.c | 107 +++++++++++------ .../acf-can/linux-kernel-mod/1722ethernet.c | 11 +- examples/acf-can/linux-kernel-mod/Makefile | 2 +- examples/acf-vss/acf-vss-talker.c | 14 +-- examples/crf/crf-listener.c | 74 ++++++------ examples/crf/crf-talker.c | 14 +-- examples/cvf/cvf-listener.c | 16 +-- examples/cvf/cvf-talker.c | 18 +-- examples/hello-world/hello-world-talker.c | 18 +-- include/avtp/Utils.h | 89 +++++++++++++- src/avtp/Utils.c | 110 ------------------ src/avtp/export/InlineExports.c | 18 +-- 16 files changed, 361 insertions(+), 283 deletions(-) delete mode 100644 src/avtp/Utils.c diff --git a/docs/api-design.md b/docs/api-design.md index 7b71dc34..8dcd0733 100644 --- a/docs/api-design.md +++ b/docs/api-design.md @@ -95,6 +95,16 @@ no validation. There is no guarding against malformed input in the hot path; that freedom is what lets you write truly high-performance code, e.g. forwarding high-rate CAN traffic on a small microcontroller. +Formats with more than one header version additionally offer version-typed +accessors (`..._V0` / `..._V1`, see +[Version-typed accessors](#version-typed-accessors)). They never read the +version field and select the layout at compile time. The field-access engine is +inline, so with a compile-time descriptor table and field index a version-typed +accessor folds into direct bit manipulation. The version-agnostic accessor +reads the version once and forwards to the matching typed variant: use the +typed form when the version is known and the agnostic form for mixed-version +paths. + Where validation is wanted, each format offers an `IsValid()` function you can call *once* to check a frame before accessing it (see [Accessor semantics & the safety contract](#accessor-semantics--the-safety-contract)). @@ -153,6 +163,35 @@ OPEN1722_INLINE bool Avtp_Can_IsMtv(const Avtp_Can_t *const pdu); OPEN1722_INLINE void Avtp_Can_SetMtv(Avtp_Can_t *pdu, bool mtv); ``` +### Version-typed accessors + +Formats that support more than one header version (the common stream header and +alternative header formats, see +[The AVTP common stream header](#the-avtp-common-stream-header)) provide three +layers of field accessors: + +| Layer | Pattern | Example | +|-------|---------|---------| +| Version-typed named | `Avtp___V0` / `_V1` | `Avtp_Tscf_GetSequenceNum_V1` | +| Version-typed generic | `Avtp__GetField_V0` / `_V1` | `Avtp_Tscf_GetField_V1(pdu, field)` | +| Version-agnostic | `Avtp__` | `Avtp_Tscf_GetSequenceNum` | + +The version-typed variants take the matching PDU struct (`Avtp__t` for +`_V0`, `Avtp_V1_t` for `_V1`), never read the version field and select +the field layout at compile time. The version-agnostic variant reads the version +once and forwards to the matching typed variant. Setters keep the +version-specific semantics: for example `SetSequenceNum_V1` on TSCF/NTSCF/CRF +also writes the `sequence_num_lsb` copy, while the version 0 variant writes the +8-bit `sequence_num_lsb` field that is the sequence number there. + +Use the typed variants whenever the version is known - a talker after +`Init`/`InitV1`, or a listener after checking the version once - and the +agnostic variant for mixed-version receive paths. The common stream header +fields are implemented once in +[`CommonStreamHeader.h`](../include/avtp/CommonStreamHeader.h) and delegated to +by each format, so the same field has identical typed accessors in every +format. + ### Return types Getters return the natural C type for the field width - `uint8_t`, @@ -301,7 +340,11 @@ Accessors, `Init`, `IsValid` and the convenience helpers (payload access, `SetPayloadLength`, `CreateAcfMessage`, …) are all declared `OPEN1722_INLINE` rather than `static inline`. By default this resolves to `static inline`, so embedded and bare-metal consumers get fully-inlined code with no call -overhead. +overhead. The field-access engine itself +(`Avtp_GetField`/`Avtp_SetField` in +[`Utils.h`](../include/avtp/Utils.h)) is inline as well, which is what lets a +version-typed accessor with a constant descriptor table and field index fold +into direct bit manipulation. For shared-library/FFI users (e.g. Python `ctypes`, Rust FFI), the same functions are also exported as regular symbols in `libopen1722.so`, so they can @@ -603,10 +646,11 @@ header once for both versions: `Avtp_CshFieldDescV1`, one descriptor table per version. - `Avtp_CommonStreamHeader_*` - version-dispatched accessors for `sv`, `mr`, `f_s_d`, `tv`, `sequence_num`, `format_specific_data_0/1`, `tu`, `stream_id`, - `avtp_timestamp`, `ptp_grandmaster_identity` and `stream_data_length`. - `GetSequenceNum` returns `uint32_t` and `GetAvtpTimestamp` returns `uint64_t` - in both versions; fields absent from a version return 0 and their setters are - no-ops. + `avtp_timestamp`, `ptp_grandmaster_identity` and `stream_data_length`, each + with `_V0`/`_V1` typed variants plus the generic `GetField_V0/_V1` and + `SetField_V0/_V1`. `GetSequenceNum` returns `uint32_t` and `GetAvtpTimestamp` + returns `uint64_t` in both versions; fields absent from a version return 0 and + their setters are no-ops. A migrated format (TSCF is the reference) declares a **complete descriptor table per version**, in absolute coordinates. The common entries reuse the @@ -631,8 +675,11 @@ asserts that they equal the style module's entries for the same version. work for both versions. The version 1 PDU struct (for example `Avtp_TscfV1_t`) is sized for the larger -header and is used for allocation and embedding. Accessors keep taking the -version 0 struct pointer; version 1 callers cast once. +header and is used for allocation and embedding. Version-typed accessors take +the matching struct (`Avtp__t` for `_V0`, `Avtp_V1_t` for +`_V1`), so version 1 callers keep the typed pointer. The version-agnostic +accessors still take the version 0 struct pointer and version 1 callers cast +once. The "every bit described exactly once" rule becomes a cross-module test: for each version, the common header fields (`subtype`, `version`; `h` is covered by @@ -656,8 +703,11 @@ byte-aligned v1 prefix (`AVTPDU_AH_LEN_V1` = 16): - `Avtp_AlternativeHeader_t` - a view type sized for the v1 prefix. - `AVTPDU_AH_FIELD_RESERVED1`, `_SEQUENCE_NUM`, `_PTP_GRANDMASTER_IDENTITY`, mapped by `Avtp_AhFieldDescV0` (all zero) and `Avtp_AhFieldDescV1`. -- `Avtp_AlternativeHeader_*` accessors; `GetSequenceNum` returns `uint32_t` and - `GetPtpGrandmasterIdentity` `uint64_t`, both 0 on version 0. +- `Avtp_AlternativeHeader_*` accessors with `_V0`/`_V1` typed variants and the + generic `GetField_V0/_V1` and `SetField_V0/_V1`; `GetSequenceNum` returns + `uint32_t` and `GetPtpGrandmasterIdentity` `uint64_t`, both 0 on version 0. + CRF and NTSCF delegate their alternative header fields to these shared + variants. The trailing `reserved[12]` is the head of the format-specific data area (format fields begin at bit 140), so it is owned by the format tables @@ -715,10 +765,11 @@ All getters and setters ultimately funnel through two generic functions in [`Utils.h`](../include/avtp/Utils.h): ```c -uint64_t Avtp_GetField(const Avtp_FieldDescriptor_t *fieldDescriptors, - uint8_t numFields, const uint8_t *const pdu, uint8_t field); -void Avtp_SetField(const Avtp_FieldDescriptor_t *fieldDescriptors, - uint8_t numFields, uint8_t *pdu, uint8_t field, uint64_t value); +OPEN1722_INLINE uint64_t Avtp_GetField(const Avtp_FieldDescriptor_t *fieldDescriptors, + uint8_t numFields, const uint8_t *const pdu, uint8_t field); +OPEN1722_INLINE void Avtp_SetField(const Avtp_FieldDescriptor_t *fieldDescriptors, + uint8_t numFields, uint8_t *pdu, uint8_t field, + uint64_t value); ``` They look up `field` in `fieldDescriptors` and extract/insert the described bit @@ -727,6 +778,13 @@ helpers in [`Byteorder.h`](../include/avtp/Byteorder.h). `numFields` (the `..._FIELD_MAX` terminator) is used only for a bounds check on the `field` index. +The engine is inline: when the descriptor table and the field index are +compile-time constants (as in every version-typed accessor), the compiler folds +the table lookup and the extraction loop into direct loads, shifts and masks. +The shared library still exports regular `Avtp_GetField`/`Avtp_SetField` +symbols for FFI users (see +[Inline accessors & symbol export](#inline-accessors--symbol-export)). + The descriptor type is defined in [`Defines.h`](../include/avtp/Defines.h): ```c @@ -761,7 +819,9 @@ bare-metal consumers get fully-inlined accessors with no call overhead. For shared-library/FFI users, a dedicated export translation unit (`src/avtp/export/InlineExports.c`) re-includes the headers with the macro emptied, forcing an external symbol for every inline function in -`libopen1722.so`. +`libopen1722.so`. The field-access engine in `Utils.h` and the shared ACF +common-header accessors in `AcfCommon.h` are part of that export set, so the +symbols `Avtp_GetField` and `Avtp_SetField` remain available to FFI callers. The full mechanism, and how to force non-inline use in your own code, is documented in [`inline.md`](inline.md). For the purposes of this document the @@ -833,3 +893,9 @@ this order and the template in 12. Add unit tests under `unit/` and register the test target in the build. A concrete reference for every step is `Can.h`. + +For a format that supports more than one header version, also follow +[Accessor API](header-versions.md#accessor-api) in the migration guide: declare +a complete descriptor table per version and add `_V0`/`_V1` variants for every +accessor, delegating the common fields to `CommonStreamHeader.h` (or +`AlternativeHeader.h` for the alternative header). diff --git a/docs/inline.md b/docs/inline.md index 23377454..76b695a9 100644 --- a/docs/inline.md +++ b/docs/inline.md @@ -25,15 +25,16 @@ All inline functions in the public headers use `OPEN1722_INLINE` instead of `sta The shared library build includes a single file `src/avtp/export/InlineExports.c` that overrides the macro and re-includes all inline headers: ```c -// Phase 1: include shared deps in static-inline mode +// Phase 1: leaf dependencies in static-inline mode #include "avtp/Inline.h" #include "avtp/Defines.h" #include "avtp/Byteorder.h" -// ... // Phase 2: override and include all target headers #undef OPEN1722_INLINE #define OPEN1722_INLINE +#include "avtp/Utils.h" // field-access engine +#include "avtp/acf/AcfCommon.h" // shared ACF common header #include "avtp/Udp.h" #include "avtp/acf/Ntscf.h" // ... all remaining format headers @@ -41,7 +42,7 @@ The shared library build includes a single file `src/avtp/export/InlineExports.c When `OPEN1722_INLINE` is empty, each function definition in the target headers becomes a regular external function definition, emitted as an exported symbol in `libopen1722.so`. -Phase 1 ensures that all shared dependencies (Byteorder, Utils, AcfCommon, etc.) are processed in the default static-inline mode, so they have internal linkage and do not cause duplicate-symbol errors. +Phase 1 ensures that the leaf dependencies (Byteorder, Defines, etc.) are processed in the default static-inline mode, so they have internal linkage and do not cause duplicate-symbol errors. `Utils.h` and `AcfCommon.h` must be part of phase 2 rather than phase 1: `AcfCommon.h` includes `Utils.h`, and `#pragma once` fixes a header's linkage at first parse, so both have to be processed with `OPEN1722_INLINE` empty for their functions (including `Avtp_GetField`/`Avtp_SetField`) to be exported. ## Usage @@ -98,6 +99,8 @@ This makes the function declarations plain `extern` declarations — no function ``` include/avtp/Inline.h ← defines OPEN1722_INLINE macro +include/avtp/Utils.h ← field-access engine (inline) +include/avtp/acf/AcfCommon.h ← shared ACF common header (inline) include/avtp/acf/{Ntscf,Tscf,Can,...}.h ← uses OPEN1722_INLINE src/avtp/export/ └── InlineExports.c ← single export unit (all formats) diff --git a/examples/aaf/aaf-listener.c b/examples/aaf/aaf-listener.c index a2cebd3c..57615972 100644 --- a/examples/aaf/aaf-listener.c +++ b/examples/aaf/aaf-listener.c @@ -174,25 +174,25 @@ static bool is_valid_packet(Avtp_Pcm_t *pdu) return false; } - if (!Avtp_Pcm_IsTv(pdu)) { + if (!Avtp_Pcm_IsTv_V0(pdu)) { fprintf(stderr, "tv mismatch: expected %u, got %u\n", 1, 0); return false; } - if (Avtp_Pcm_IsSp(pdu)) { + if (Avtp_Pcm_IsSp_V0(pdu)) { fprintf(stderr, "sp mismatch: expected %u, got %u\n", AVTP_AAF_SP_NORMAL, AVTP_AAF_SP_SPARSE); return false; } - val64 = Avtp_Pcm_GetStreamId(pdu); + val64 = Avtp_Pcm_GetStreamId_V0(pdu); if (val64 != STREAM_ID) { fprintf(stderr, "Stream ID mismatch: expected %" PRIu64 ", got %" PRIu64 "\n", STREAM_ID, val64); return false; } - val8 = Avtp_Pcm_GetSequenceNum(pdu); + val8 = Avtp_Pcm_GetSequenceNum_V0(pdu); if (val8 != expected_seq) { /* If we have a sequence number mismatch, we simply log the * issue and continue to process the packet. We don't want to @@ -204,32 +204,32 @@ static bool is_valid_packet(Avtp_Pcm_t *pdu) expected_seq++; - if (Avtp_Pcm_GetFormat(pdu) != AVTP_AAF_FORMAT_INT_16BIT) { + if (Avtp_Pcm_GetFormat_V0(pdu) != AVTP_AAF_FORMAT_INT_16BIT) { fprintf(stderr, "Format mismatch: expected %u, got %u\n", AVTP_AAF_FORMAT_INT_16BIT, - Avtp_Pcm_GetFormat(pdu)); + Avtp_Pcm_GetFormat_V0(pdu)); return false; } - if (Avtp_Pcm_GetNsr(pdu) != AVTP_PCM_NSR_48KHZ) { + if (Avtp_Pcm_GetNsr_V0(pdu) != AVTP_PCM_NSR_48KHZ) { fprintf(stderr, "Sample rate mismatch: expected %u, got %u\n", AVTP_PCM_NSR_48KHZ, - Avtp_Pcm_GetNsr(pdu)); + Avtp_Pcm_GetNsr_V0(pdu)); return false; } - if (Avtp_Pcm_GetChannelsPerFrame(pdu) != NUM_CHANNELS) { + if (Avtp_Pcm_GetChannelsPerFrame_V0(pdu) != NUM_CHANNELS) { fprintf(stderr, "Channels mismatch: expected %u, got %u\n", NUM_CHANNELS, - Avtp_Pcm_GetChannelsPerFrame(pdu)); + Avtp_Pcm_GetChannelsPerFrame_V0(pdu)); return false; } - if (Avtp_Pcm_GetBitDepth(pdu) != 16) { - fprintf(stderr, "Depth mismatch: expected %u, got %u\n", 16, Avtp_Pcm_GetBitDepth(pdu)); + if (Avtp_Pcm_GetBitDepth_V0(pdu) != 16) { + fprintf(stderr, "Depth mismatch: expected %u, got %u\n", 16, Avtp_Pcm_GetBitDepth_V0(pdu)); return false; } - if (Avtp_Pcm_GetStreamDataLength(pdu) != DATA_LEN) { + if (Avtp_Pcm_GetStreamDataLength_V0(pdu) != DATA_LEN) { fprintf(stderr, "Data len mismatch: expected %u, got %u\n", DATA_LEN, - Avtp_Pcm_GetStreamDataLength(pdu)); + Avtp_Pcm_GetStreamDataLength_V0(pdu)); return false; } @@ -257,7 +257,7 @@ static int new_packet(int sk_fd, int timer_fd) return 0; } - avtp_time = Avtp_Pcm_GetAvtpTimestamp(pdu); + avtp_time = Avtp_Pcm_GetAvtpTimestamp_V0(pdu); res = get_presentation_time(avtp_time, &tspec); if (res < 0) diff --git a/examples/aaf/aaf-talker.c b/examples/aaf/aaf-talker.c index 8b60a908..09d8202d 100644 --- a/examples/aaf/aaf-talker.c +++ b/examples/aaf/aaf-talker.c @@ -123,14 +123,14 @@ static struct argp argp = {options, parser}; static void init_pdu(Avtp_Pcm_t *pdu) { Avtp_Pcm_Init(pdu); - Avtp_Pcm_SetTv(pdu, true); - Avtp_Pcm_SetStreamId(pdu, STREAM_ID); - Avtp_Pcm_SetFormat(pdu, AVTP_AAF_FORMAT_INT_16BIT); - Avtp_Pcm_SetNsr(pdu, AVTP_PCM_NSR_48KHZ); - Avtp_Pcm_SetChannelsPerFrame(pdu, NUM_CHANNELS); - Avtp_Pcm_SetBitDepth(pdu, 16); - Avtp_Pcm_SetStreamDataLength(pdu, DATA_LEN); - Avtp_Pcm_SetSp(pdu, false); + Avtp_Pcm_SetTv_V0(pdu, true); + Avtp_Pcm_SetStreamId_V0(pdu, STREAM_ID); + Avtp_Pcm_SetFormat_V0(pdu, AVTP_AAF_FORMAT_INT_16BIT); + Avtp_Pcm_SetNsr_V0(pdu, AVTP_PCM_NSR_48KHZ); + Avtp_Pcm_SetChannelsPerFrame_V0(pdu, NUM_CHANNELS); + Avtp_Pcm_SetBitDepth_V0(pdu, 16); + Avtp_Pcm_SetStreamDataLength_V0(pdu, DATA_LEN); + Avtp_Pcm_SetSp_V0(pdu, false); } int main(int argc, char *argv[]) @@ -172,8 +172,8 @@ int main(int argc, char *argv[]) goto err; } - Avtp_Pcm_SetAvtpTimestamp(pdu, avtp_time); - Avtp_Pcm_SetSequenceNum(pdu, seq_num++); + Avtp_Pcm_SetAvtpTimestamp_V0(pdu, avtp_time); + Avtp_Pcm_SetSequenceNum_V0(pdu, seq_num++); n = sendto(fd, pdu, PDU_SIZE, 0, (struct sockaddr *)&sk_addr, sizeof(sk_addr)); if (n < 0) { diff --git a/examples/acf-can/acf-can-common.c b/examples/acf-can/acf-can-common.c index cd0ab0f0..3fe22b3e 100644 --- a/examples/acf-can/acf-can-common.c +++ b/examples/acf-can/acf-can-common.c @@ -118,43 +118,57 @@ int setup_can_socket(const char *can_ifname, bool can_fd) static int init_cf_pdu(uint8_t *pdu, uint64_t stream_id, acf_can_cf_t cf, uint32_t seq_num) { - int res; + if (cf == ACF_CAN_CF_NTSCF_V1) { + Avtp_NtscfV1_t *ntscf = (Avtp_NtscfV1_t *)pdu; + Avtp_Ntscf_InitV1(ntscf); + Avtp_Ntscf_SetSequenceNum_V1(ntscf, seq_num); + Avtp_Ntscf_SetStreamId_V1(ntscf, stream_id); + return (int)Avtp_Ntscf_GetHeaderLen_V1(ntscf); + } - if (cf == ACF_CAN_CF_NTSCF_V0 || cf == ACF_CAN_CF_NTSCF_V1) { - if (cf == ACF_CAN_CF_NTSCF_V1) { - Avtp_Ntscf_InitV1((Avtp_NtscfV1_t *)pdu); - } else { - Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); - } - Avtp_Ntscf_SetSequenceNum((Avtp_Ntscf_t *)pdu, seq_num); - Avtp_Ntscf_SetStreamId((Avtp_Ntscf_t *)pdu, stream_id); - return (int)Avtp_Ntscf_GetHeaderLen((Avtp_Ntscf_t *)pdu); + if (cf == ACF_CAN_CF_NTSCF_V0) { + Avtp_Ntscf_t *ntscf = (Avtp_Ntscf_t *)pdu; + Avtp_Ntscf_Init(ntscf); + Avtp_Ntscf_SetSequenceNum_V0(ntscf, seq_num); + Avtp_Ntscf_SetStreamId_V0(ntscf, stream_id); + return (int)Avtp_Ntscf_GetHeaderLen_V0(ntscf); } if (cf == ACF_CAN_CF_TSCF_V1) { - Avtp_Tscf_InitV1((Avtp_TscfV1_t *)pdu); - } else { - Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); + Avtp_TscfV1_t *tscf = (Avtp_TscfV1_t *)pdu; + Avtp_Tscf_InitV1(tscf); + Avtp_Tscf_SetTu_V1(tscf, false); + Avtp_Tscf_SetSequenceNum_V1(tscf, seq_num); + Avtp_Tscf_SetStreamId_V1(tscf, stream_id); + return (int)Avtp_Tscf_GetHeaderLen_V1(tscf); } - Avtp_Tscf_SetTu((Avtp_Tscf_t *)pdu, false); - Avtp_Tscf_SetSequenceNum((Avtp_Tscf_t *)pdu, seq_num); - Avtp_Tscf_SetStreamId((Avtp_Tscf_t *)pdu, stream_id); - res = (int)Avtp_CommonStreamHeader_GetHeaderLen((Avtp_CommonStreamHeader_t *)pdu); - return res; + Avtp_Tscf_t *tscf = (Avtp_Tscf_t *)pdu; + Avtp_Tscf_Init(tscf); + Avtp_Tscf_SetTu_V0(tscf, false); + Avtp_Tscf_SetSequenceNum_V0(tscf, seq_num); + Avtp_Tscf_SetStreamId_V0(tscf, stream_id); + return (int)Avtp_Tscf_GetHeaderLen_V0(tscf); } static int update_cf_length(uint8_t *cf_pdu, uint64_t length, acf_can_cf_t cf) { - if (cf == ACF_CAN_CF_NTSCF_V0 || cf == ACF_CAN_CF_NTSCF_V1) { - size_t headerLen = Avtp_Ntscf_GetHeaderLen((Avtp_Ntscf_t *)cf_pdu); - uint64_t payloadLen = length - headerLen; - Avtp_Ntscf_SetNtscfDataLength((Avtp_Ntscf_t *)cf_pdu, (uint16_t)payloadLen); + if (cf == ACF_CAN_CF_NTSCF_V1) { + Avtp_NtscfV1_t *ntscf = (Avtp_NtscfV1_t *)cf_pdu; + uint64_t payloadLen = length - Avtp_Ntscf_GetHeaderLen_V1(ntscf); + Avtp_Ntscf_SetNtscfDataLength_V1(ntscf, (uint16_t)payloadLen); + } else if (cf == ACF_CAN_CF_NTSCF_V0) { + Avtp_Ntscf_t *ntscf = (Avtp_Ntscf_t *)cf_pdu; + uint64_t payloadLen = length - Avtp_Ntscf_GetHeaderLen_V0(ntscf); + Avtp_Ntscf_SetNtscfDataLength_V0(ntscf, (uint16_t)payloadLen); + } else if (cf == ACF_CAN_CF_TSCF_V1) { + Avtp_TscfV1_t *tscf = (Avtp_TscfV1_t *)cf_pdu; + uint64_t payloadLen = length - Avtp_Tscf_GetHeaderLen_V1(tscf); + Avtp_Tscf_SetStreamDataLength_V1(tscf, (uint16_t)payloadLen); } else { - size_t headerLen = - Avtp_CommonStreamHeader_GetHeaderLen((Avtp_CommonStreamHeader_t *)cf_pdu); - uint64_t payloadLen = length - headerLen; - Avtp_Tscf_SetStreamDataLength((Avtp_Tscf_t *)cf_pdu, (uint16_t)payloadLen); + Avtp_Tscf_t *tscf = (Avtp_Tscf_t *)cf_pdu; + uint64_t payloadLen = length - Avtp_Tscf_GetHeaderLen_V0(tscf); + Avtp_Tscf_SetStreamDataLength_V0(tscf, (uint16_t)payloadLen); } return 0; } @@ -282,12 +296,21 @@ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uin LOG_ERR("Unsupported TSCF version %u, ignoring frame.\n", version); return -1; } - size_t headerLen = - Avtp_CommonStreamHeader_GetHeaderLen((const Avtp_CommonStreamHeader_t *)cf_pdu); - proc_bytes += (uint16_t)headerLen; - msg_length += (uint16_t)(Avtp_Tscf_GetStreamDataLength((Avtp_Tscf_t *)cf_pdu) + headerLen); - s_id = Avtp_Tscf_GetStreamId((Avtp_Tscf_t *)cf_pdu); - seq_num = Avtp_Tscf_GetSequenceNum((Avtp_Tscf_t *)cf_pdu); + if (version == AVTP_VERSION_1) { + const Avtp_TscfV1_t *tscf = (const Avtp_TscfV1_t *)cf_pdu; + size_t headerLen = Avtp_Tscf_GetHeaderLen_V1(tscf); + proc_bytes += (uint16_t)headerLen; + msg_length += (uint16_t)(Avtp_Tscf_GetStreamDataLength_V1(tscf) + headerLen); + s_id = Avtp_Tscf_GetStreamId_V1(tscf); + seq_num = Avtp_Tscf_GetSequenceNum_V1(tscf); + } else { + const Avtp_Tscf_t *tscf = (const Avtp_Tscf_t *)cf_pdu; + size_t headerLen = Avtp_Tscf_GetHeaderLen_V0(tscf); + proc_bytes += (uint16_t)headerLen; + msg_length += (uint16_t)(Avtp_Tscf_GetStreamDataLength_V0(tscf) + headerLen); + s_id = Avtp_Tscf_GetStreamId_V0(tscf); + seq_num = Avtp_Tscf_GetSequenceNum_V0(tscf); + } } else if (subtype == AVTP_SUBTYPE_NTSCF) { uint8_t version = Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)cf_pdu); @@ -295,11 +318,21 @@ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uin LOG_ERR("Unsupported NTSCF version %u, ignoring frame.\n", version); return -1; } - size_t headerLen = Avtp_Ntscf_GetHeaderLen((const Avtp_Ntscf_t *)cf_pdu); - proc_bytes += (uint16_t)headerLen; - msg_length += (uint16_t)(Avtp_Ntscf_GetNtscfDataLength((Avtp_Ntscf_t *)cf_pdu) + headerLen); - s_id = Avtp_Ntscf_GetStreamId((Avtp_Ntscf_t *)cf_pdu); - seq_num = Avtp_Ntscf_GetSequenceNum((Avtp_Ntscf_t *)cf_pdu); + if (version == AVTP_VERSION_1) { + const Avtp_NtscfV1_t *ntscf = (const Avtp_NtscfV1_t *)cf_pdu; + size_t headerLen = Avtp_Ntscf_GetHeaderLen_V1(ntscf); + proc_bytes += (uint16_t)headerLen; + msg_length += (uint16_t)(Avtp_Ntscf_GetNtscfDataLength_V1(ntscf) + headerLen); + s_id = Avtp_Ntscf_GetStreamId_V1(ntscf); + seq_num = Avtp_Ntscf_GetSequenceNum_V1(ntscf); + } else { + const Avtp_Ntscf_t *ntscf = (const Avtp_Ntscf_t *)cf_pdu; + size_t headerLen = Avtp_Ntscf_GetHeaderLen_V0(ntscf); + proc_bytes += (uint16_t)headerLen; + msg_length += (uint16_t)(Avtp_Ntscf_GetNtscfDataLength_V0(ntscf) + headerLen); + s_id = Avtp_Ntscf_GetStreamId_V0(ntscf); + seq_num = Avtp_Ntscf_GetSequenceNum_V0(ntscf); + } } else { return -1; } diff --git a/examples/acf-can/linux-kernel-mod/1722ethernet.c b/examples/acf-can/linux-kernel-mod/1722ethernet.c index 2daaaaa0..57456370 100644 --- a/examples/acf-can/linux-kernel-mod/1722ethernet.c +++ b/examples/acf-can/linux-kernel-mod/1722ethernet.c @@ -50,8 +50,9 @@ void prepare_ntscf_header(Avtp_Ntscf_t *ntscf_header, struct acfcan_cfg *cfg) { Avtp_Ntscf_Init(ntscf_header); Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ntscf_header, 0); - Avtp_Ntscf_SetSequenceNum(ntscf_header, cfg->sequenceNum++); // This can't be right. Increase? - Avtp_Ntscf_SetStreamId(ntscf_header, cfg->tx_streamid); + Avtp_Ntscf_SetSequenceNum_V0(ntscf_header, + cfg->sequenceNum++); // This can't be right. Increase? + Avtp_Ntscf_SetStreamId_V0(ntscf_header, cfg->tx_streamid); } void prepare_can_header(Avtp_Can_t *can_header, struct acfcan_cfg *cfg, const struct sk_buff *skb) @@ -112,7 +113,7 @@ void calculate_and_set_ntscf_size(ACFCANPdu_t *pdu) // 1722 is a mess. Bytes, lukicly we have padded quadlets in can already.... uint16_t canandpadinbytes = Avtp_AcfCommon_GetAcfMsgLengthInBytes((Avtp_AcfCommon_t *)&pdu->can); - Avtp_Ntscf_SetNtscfDataLength(&pdu->ntscf, canandpadinbytes); + Avtp_Ntscf_SetNtscfDataLength_V0(&pdu->ntscf, canandpadinbytes); } int forward_can_frame(struct net_device *can_dev, const struct sk_buff *skb_can) @@ -226,7 +227,7 @@ int ieee1722_packet_handdler(struct sk_buff *skb, struct net_device *dev, struct Avtp_Can_t *can = (Avtp_Can_t *)(skb->data + sizeof(Avtp_Ntscf_t)); // This is bytes, not quadlets - uint16_t msg_length = Avtp_Ntscf_GetNtscfDataLength(ntscf); + uint16_t msg_length = Avtp_Ntscf_GetNtscfDataLength_V0(ntscf); // seq_num = Avtp_Ntscf_GetSequenceNum((Avtp_Ntscf_t*)cf_pdu); if (msg_length > skb->len - sizeof(Avtp_Ntscf_t)) { @@ -242,7 +243,7 @@ int ieee1722_packet_handdler(struct sk_buff *skb, struct net_device *dev, struct return NET_RX_DROP; } - uint64_t stream_id = Avtp_Ntscf_GetStreamId(ntscf); + uint64_t stream_id = Avtp_Ntscf_GetStreamId_V0(ntscf); uint8_t busid = Avtp_Can_GetCanBusId(can); pr_debug( diff --git a/examples/acf-can/linux-kernel-mod/Makefile b/examples/acf-can/linux-kernel-mod/Makefile index 467dac48..6f80f69d 100644 --- a/examples/acf-can/linux-kernel-mod/Makefile +++ b/examples/acf-can/linux-kernel-mod/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_ACF_CAN) += acfcan.o -acfcan-objs := acfcanmain.o 1722ethernet.o ../../../src/avtp/Utils.o +acfcan-objs := acfcanmain.o 1722ethernet.o ccflags-y += -DLINUX_KERNEL1722=1 ccflags-y += -I $(src)/../../../include diff --git a/examples/acf-vss/acf-vss-talker.c b/examples/acf-vss/acf-vss-talker.c index 69e44804..7dc8a5de 100644 --- a/examples/acf-vss/acf-vss-talker.c +++ b/examples/acf-vss/acf-vss-talker.c @@ -144,16 +144,16 @@ static int init_cf_pdu(uint8_t *pdu) Avtp_Tscf_t *tscf_pdu = (Avtp_Tscf_t *)pdu; memset(tscf_pdu, 0, AVTP_TSCF_HEADER_LEN); Avtp_Tscf_Init(tscf_pdu); - Avtp_Tscf_SetTu(tscf_pdu, false); - Avtp_Tscf_SetSequenceNum(tscf_pdu, seq_num++); - Avtp_Tscf_SetStreamId(tscf_pdu, STREAM_ID); + Avtp_Tscf_SetTu_V0(tscf_pdu, false); + Avtp_Tscf_SetSequenceNum_V0(tscf_pdu, seq_num++); + Avtp_Tscf_SetStreamId_V0(tscf_pdu, STREAM_ID); res = AVTP_TSCF_HEADER_LEN; } else { Avtp_Ntscf_t *ntscf_pdu = (Avtp_Ntscf_t *)pdu; memset(ntscf_pdu, 0, AVTP_NTSCF_HEADER_LEN); Avtp_Ntscf_Init(ntscf_pdu); - Avtp_Ntscf_SetSequenceNum(ntscf_pdu, seq_num++); - Avtp_Ntscf_SetStreamId(ntscf_pdu, STREAM_ID); + Avtp_Ntscf_SetSequenceNum_V0(ntscf_pdu, seq_num++); + Avtp_Ntscf_SetStreamId_V0(ntscf_pdu, STREAM_ID); res = AVTP_NTSCF_HEADER_LEN; } return res; @@ -163,10 +163,10 @@ static int update_cf_length(uint8_t *cf_pdu, uint64_t length) { if (use_tscf) { uint64_t payloadLen = length - AVTP_TSCF_HEADER_LEN; - Avtp_Tscf_SetStreamDataLength((Avtp_Tscf_t *)cf_pdu, (uint16_t)payloadLen); + Avtp_Tscf_SetStreamDataLength_V0((Avtp_Tscf_t *)cf_pdu, (uint16_t)payloadLen); } else { uint64_t payloadLen = length - AVTP_NTSCF_HEADER_LEN; - Avtp_Ntscf_SetNtscfDataLength((Avtp_Ntscf_t *)cf_pdu, (uint16_t)payloadLen); + Avtp_Ntscf_SetNtscfDataLength_V0((Avtp_Ntscf_t *)cf_pdu, (uint16_t)payloadLen); } return 0; } diff --git a/examples/crf/crf-listener.c b/examples/crf/crf-listener.c index b77a1d74..fe356e5a 100644 --- a/examples/crf/crf-listener.c +++ b/examples/crf/crf-listener.c @@ -281,17 +281,17 @@ static bool is_valid_crf_pdu(Avtp_Crf_t *pdu) return false; } - if (!Avtp_Crf_IsSv(pdu)) { + if (!Avtp_Crf_IsSv_V0(pdu)) { fprintf(stderr, "CRF: sv mismatch: expected %u, got %u\n", 1, 0); return false; } - if (Avtp_Crf_IsFs(pdu)) { + if (Avtp_Crf_IsFs_V0(pdu)) { fprintf(stderr, "CRF: fs mismatch: expected %u, got %u\n", 0, 1); return false; } - val8 = Avtp_Crf_GetSequenceNum(pdu); + val8 = Avtp_Crf_GetSequenceNum_V0(pdu); if (val8 != crf_seq_num) { /* If we have a sequence number mismatch, we simply log the * issue and continue to process the packet. We don't want to @@ -304,34 +304,34 @@ static bool is_valid_crf_pdu(Avtp_Crf_t *pdu) crf_seq_num++; - if (Avtp_Crf_GetType(pdu) != AVTP_CRF_TYPE_AUDIO_SAMPLE) { + if (Avtp_Crf_GetType_V0(pdu) != AVTP_CRF_TYPE_AUDIO_SAMPLE) { fprintf(stderr, "CRF: Type mismatch: expected %u, got %u\n", - (unsigned)AVTP_CRF_TYPE_AUDIO_SAMPLE, (unsigned)Avtp_Crf_GetType(pdu)); + (unsigned)AVTP_CRF_TYPE_AUDIO_SAMPLE, (unsigned)Avtp_Crf_GetType_V0(pdu)); return false; } - val64 = Avtp_Crf_GetStreamId(pdu); + val64 = Avtp_Crf_GetStreamId_V0(pdu); if (val64 != CRF_STREAM_ID) { fprintf(stderr, "CRF: Stream ID mismatch: expected %" PRIu64 ", got %" PRIu64 "\n", CRF_STREAM_ID, val64); return false; } - if (Avtp_Crf_GetPull(pdu) != AVTP_CRF_PULL_MULT_BY_1) { + if (Avtp_Crf_GetPull_V0(pdu) != AVTP_CRF_PULL_MULT_BY_1) { fprintf(stderr, "CRF: Pull mismatch: expected %u, got %u\n", - (unsigned)AVTP_CRF_PULL_MULT_BY_1, (unsigned)Avtp_Crf_GetPull(pdu)); + (unsigned)AVTP_CRF_PULL_MULT_BY_1, (unsigned)Avtp_Crf_GetPull_V0(pdu)); return false; } - if (Avtp_Crf_GetBaseFrequency(pdu) != (uint32_t)CRF_SAMPLE_RATE) { + if (Avtp_Crf_GetBaseFrequency_V0(pdu) != (uint32_t)CRF_SAMPLE_RATE) { fprintf(stderr, "CRF: Base frequency mismatch: expected %u, got %u\n", CRF_SAMPLE_RATE, - Avtp_Crf_GetBaseFrequency(pdu)); + Avtp_Crf_GetBaseFrequency_V0(pdu)); return false; } - if ((size_t)Avtp_Crf_GetCrfDataLength(pdu) != CRF_DATA_LEN) { + if ((size_t)Avtp_Crf_GetCrfDataLength_V0(pdu) != CRF_DATA_LEN) { fprintf(stderr, "CRF: Data length mismatch: expected %zu, got %u\n", CRF_DATA_LEN, - Avtp_Crf_GetCrfDataLength(pdu)); + Avtp_Crf_GetCrfDataLength_V0(pdu)); return false; } @@ -354,25 +354,25 @@ static bool is_valid_aaf_pdu(Avtp_Pcm_t *pdu) return false; } - if (!Avtp_Pcm_IsTv(pdu)) { + if (!Avtp_Pcm_IsTv_V0(pdu)) { fprintf(stderr, "AAF: tv mismatch: expected %u, got %u\n", 1, 0); return false; } - if (Avtp_Pcm_IsSp(pdu)) { + if (Avtp_Pcm_IsSp_V0(pdu)) { fprintf(stderr, "AAF: sp mismatch: expected %u, got %u\n", AVTP_AAF_SP_NORMAL, AVTP_AAF_SP_SPARSE); return false; } - val64 = Avtp_Pcm_GetStreamId(pdu); + val64 = Avtp_Pcm_GetStreamId_V0(pdu); if (val64 != AAF_STREAM_ID) { fprintf(stderr, "AAF: Stream ID mismatch: expected %" PRIu64 ", got %" PRIu64 "\n", AAF_STREAM_ID, val64); return false; } - val8 = Avtp_Pcm_GetSequenceNum(pdu); + val8 = Avtp_Pcm_GetSequenceNum_V0(pdu); if (val8 != aaf_seq_num) { /* If we have a sequence number mismatch, we simply log the * issue and continue to process the packet. We don't want to @@ -385,33 +385,33 @@ static bool is_valid_aaf_pdu(Avtp_Pcm_t *pdu) aaf_seq_num++; - if (Avtp_Pcm_GetFormat(pdu) != AVTP_AAF_FORMAT_INT_16BIT) { + if (Avtp_Pcm_GetFormat_V0(pdu) != AVTP_AAF_FORMAT_INT_16BIT) { fprintf(stderr, "AAF: Format mismatch: expected %u, got %u\n", AVTP_AAF_FORMAT_INT_16BIT, - Avtp_Pcm_GetFormat(pdu)); + Avtp_Pcm_GetFormat_V0(pdu)); return false; } - if (Avtp_Pcm_GetNsr(pdu) != AVTP_PCM_NSR_48KHZ) { + if (Avtp_Pcm_GetNsr_V0(pdu) != AVTP_PCM_NSR_48KHZ) { fprintf(stderr, "AAF: Sample rate mismatch: expected %u, got %u\n", AVTP_PCM_NSR_48KHZ, - Avtp_Pcm_GetNsr(pdu)); + Avtp_Pcm_GetNsr_V0(pdu)); return false; } - if (Avtp_Pcm_GetChannelsPerFrame(pdu) != AAF_NUM_CHANNELS) { + if (Avtp_Pcm_GetChannelsPerFrame_V0(pdu) != AAF_NUM_CHANNELS) { fprintf(stderr, "AAF: Channels mismatch: expected %u, got %u\n", AAF_NUM_CHANNELS, - Avtp_Pcm_GetChannelsPerFrame(pdu)); + Avtp_Pcm_GetChannelsPerFrame_V0(pdu)); return false; } - if (Avtp_Pcm_GetBitDepth(pdu) != 16) { + if (Avtp_Pcm_GetBitDepth_V0(pdu) != 16) { fprintf(stderr, "AAF: Depth mismatch: expected %u, got %u\n", 16, - Avtp_Pcm_GetBitDepth(pdu)); + Avtp_Pcm_GetBitDepth_V0(pdu)); return false; } - if (Avtp_Pcm_GetStreamDataLength(pdu) != AAF_DATA_LEN) { + if (Avtp_Pcm_GetStreamDataLength_V0(pdu) != AAF_DATA_LEN) { fprintf(stderr, "AAF: Data len mismatch: expected %u, got %u\n", AAF_DATA_LEN, - Avtp_Pcm_GetStreamDataLength(pdu)); + Avtp_Pcm_GetStreamDataLength_V0(pdu)); return false; } @@ -421,14 +421,14 @@ static bool is_valid_aaf_pdu(Avtp_Pcm_t *pdu) static void init_aaf_pdu(Avtp_Pcm_t *pdu) { Avtp_Pcm_Init(pdu); - Avtp_Pcm_SetTv(pdu, true); - Avtp_Pcm_SetStreamId(pdu, AAF_STREAM_ID); - Avtp_Pcm_SetFormat(pdu, AVTP_AAF_FORMAT_INT_16BIT); - Avtp_Pcm_SetNsr(pdu, AVTP_PCM_NSR_48KHZ); - Avtp_Pcm_SetChannelsPerFrame(pdu, AAF_NUM_CHANNELS); - Avtp_Pcm_SetBitDepth(pdu, 16); - Avtp_Pcm_SetStreamDataLength(pdu, AAF_DATA_LEN); - Avtp_Pcm_SetSp(pdu, false); + Avtp_Pcm_SetTv_V0(pdu, true); + Avtp_Pcm_SetStreamId_V0(pdu, AAF_STREAM_ID); + Avtp_Pcm_SetFormat_V0(pdu, AVTP_AAF_FORMAT_INT_16BIT); + Avtp_Pcm_SetNsr_V0(pdu, AVTP_PCM_NSR_48KHZ); + Avtp_Pcm_SetChannelsPerFrame_V0(pdu, AAF_NUM_CHANNELS); + Avtp_Pcm_SetBitDepth_V0(pdu, 16); + Avtp_Pcm_SetStreamDataLength_V0(pdu, AAF_DATA_LEN); + Avtp_Pcm_SetSp_V0(pdu, false); } static int aaf_talker_tx_timeout(int fd_timer, int fd_sk, const struct sockaddr_ll *addr, @@ -448,8 +448,8 @@ static int aaf_talker_tx_timeout(int fd_timer, int fd_sk, const struct sockaddr_ while (expirations--) { avtp_time = get_next_mclk_timestamp(); - Avtp_Pcm_SetAvtpTimestamp(pdu, avtp_time); - Avtp_Pcm_SetSequenceNum(pdu, aaf_seq_num++); + Avtp_Pcm_SetAvtpTimestamp_V0(pdu, avtp_time); + Avtp_Pcm_SetSequenceNum_V0(pdu, aaf_seq_num++); n = sendto(fd_sk, pdu, AAF_PDU_SIZE, 0, (struct sockaddr *)addr, sizeof(*addr)); if (n < 0) { @@ -546,7 +546,7 @@ static int handle_aaf_pdu(Avtp_Pcm_t *pdu) if (!is_valid_aaf_pdu(pdu)) return 0; - avtp_time = Avtp_Pcm_GetAvtpTimestamp(pdu); + avtp_time = Avtp_Pcm_GetAvtpTimestamp_V0(pdu); if (need_mclk_lookup) { mclk_time = mclk_lookup(avtp_time); diff --git a/examples/crf/crf-talker.c b/examples/crf/crf-talker.c index 2cd353ad..54d41d38 100644 --- a/examples/crf/crf-talker.c +++ b/examples/crf/crf-talker.c @@ -153,12 +153,12 @@ static uint64_t calculate_crf_timestamp(struct timespec tspec, uint64_t rounded_ static void init_pdu(Avtp_Crf_t *pdu) { Avtp_Crf_Init(pdu); - Avtp_Crf_SetType(pdu, AVTP_CRF_TYPE_AUDIO_SAMPLE); - Avtp_Crf_SetStreamId(pdu, STREAM_ID); - Avtp_Crf_SetPull(pdu, AVTP_CRF_PULL_MULT_BY_1); - Avtp_Crf_SetBaseFrequency(pdu, SAMPLE_RATE); - Avtp_Crf_SetTimestampInterval(pdu, TIMESTAMP_INTERVAL); - Avtp_Crf_SetCrfDataLength(pdu, (uint16_t)DATA_LEN); + Avtp_Crf_SetType_V0(pdu, AVTP_CRF_TYPE_AUDIO_SAMPLE); + Avtp_Crf_SetStreamId_V0(pdu, STREAM_ID); + Avtp_Crf_SetPull_V0(pdu, AVTP_CRF_PULL_MULT_BY_1); + Avtp_Crf_SetBaseFrequency_V0(pdu, SAMPLE_RATE); + Avtp_Crf_SetTimestampInterval_V0(pdu, TIMESTAMP_INTERVAL); + Avtp_Crf_SetCrfDataLength_V0(pdu, (uint16_t)DATA_LEN); } int main(int argc, char *argv[]) @@ -201,7 +201,7 @@ int main(int argc, char *argv[]) memcpy(pdu->payload + (idx * sizeof(timestamp)), ×tamp, sizeof(timestamp)); } - Avtp_Crf_SetSequenceNum(pdu, seq_num++); + Avtp_Crf_SetSequenceNum_V0(pdu, seq_num++); n = sendto(sk_fd, pdu, PDU_SIZE, 0, (struct sockaddr *)&sk_addr, sizeof(sk_addr)); if (n < 0) { diff --git a/examples/cvf/cvf-listener.c b/examples/cvf/cvf-listener.c index e247a5f0..edbc9a32 100644 --- a/examples/cvf/cvf-listener.c +++ b/examples/cvf/cvf-listener.c @@ -180,18 +180,18 @@ static bool is_valid_packet(Avtp_Cvf_t *cvf, size_t bufferSize) return false; } - if (!Avtp_Cvf_IsTv(cvf)) { + if (!Avtp_Cvf_IsTv_V0(cvf)) { fprintf(stderr, "tv mismatch: expected %u, got %u\n", 1, 0); return false; } - uint64_t stream_id = Avtp_Cvf_GetStreamId(cvf); + uint64_t stream_id = Avtp_Cvf_GetStreamId_V0(cvf); if (stream_id != STREAM_ID) { fprintf(stderr, "Stream ID mismatch: expected %lu, got %lu\n", STREAM_ID, stream_id); return false; } - uint8_t sequence_num = Avtp_Cvf_GetSequenceNum(cvf); + uint8_t sequence_num = Avtp_Cvf_GetSequenceNum_V0(cvf); if (sequence_num != expected_seq) { fprintf(stderr, "Sequence number mismatch: expected %" PRIu8 ", " @@ -201,14 +201,14 @@ static bool is_valid_packet(Avtp_Cvf_t *cvf, size_t bufferSize) } expected_seq++; - Avtp_CvfFormat_t format = Avtp_Cvf_GetFormat(cvf); + Avtp_CvfFormat_t format = Avtp_Cvf_GetFormat_V0(cvf); if (format != AVTP_CVF_FORMAT_RFC) { fprintf(stderr, "Format mismatch: expected %u, got %u\n", AVTP_CVF_FORMAT_RFC, (unsigned)format); return false; } - Avtp_CvfFormatSubtype_t format_subtype = Avtp_Cvf_GetFormatSubtype(cvf); + Avtp_CvfFormatSubtype_t format_subtype = Avtp_Cvf_GetFormatSubtype_V0(cvf); if (format_subtype != AVTP_CVF_FORMAT_SUBTYPE_H264) { fprintf(stderr, "Format mismatch: expected %u, got %u\n", AVTP_CVF_FORMAT_SUBTYPE_H264, (unsigned)format_subtype); @@ -220,7 +220,7 @@ static bool is_valid_packet(Avtp_Cvf_t *cvf, size_t bufferSize) static uint16_t get_h264_data_len(Avtp_Cvf_t *cvf) { - uint16_t stream_data_len = Avtp_Cvf_GetStreamDataLength(cvf); + uint16_t stream_data_len = Avtp_Cvf_GetStreamDataLength_V0(cvf); return (uint16_t)(stream_data_len - AVTP_H264_HEADER_LEN); } @@ -248,12 +248,12 @@ static int new_packet(int sk_fd, int timer_fd) return 0; } - if (!Avtp_H264_IsValid(h264Header, Avtp_Cvf_GetStreamDataLength(cvf))) { + if (!Avtp_H264_IsValid(h264Header, Avtp_Cvf_GetStreamDataLength_V0(cvf))) { fprintf(stderr, "Dropping packet: H.264 header does not fit into the CVF stream data\n"); return 0; } - avtp_time = Avtp_Cvf_GetAvtpTimestamp(cvf); + avtp_time = Avtp_Cvf_GetAvtpTimestamp_V0(cvf); res = get_presentation_time(avtp_time, &tspec); if (res < 0) diff --git a/examples/cvf/cvf-talker.c b/examples/cvf/cvf-talker.c index baca9e91..b98e86c5 100644 --- a/examples/cvf/cvf-talker.c +++ b/examples/cvf/cvf-talker.c @@ -139,11 +139,11 @@ static struct argp argp = {options, parser}; static void init_pdu(Avtp_Cvf_t *cvf) { Avtp_Cvf_Init(cvf); - Avtp_Cvf_SetFormatSubtype(cvf, AVTP_CVF_FORMAT_SUBTYPE_H264); - Avtp_Cvf_SetTv(cvf, true); - Avtp_Cvf_SetStreamId(cvf, STREAM_ID); - Avtp_Cvf_SetM(cvf, true); - Avtp_Cvf_SetPtv(cvf, false); + Avtp_Cvf_SetFormatSubtype_V0(cvf, AVTP_CVF_FORMAT_SUBTYPE_H264); + Avtp_Cvf_SetTv_V0(cvf, true); + Avtp_Cvf_SetStreamId_V0(cvf, STREAM_ID); + Avtp_Cvf_SetM_V0(cvf, true); + Avtp_Cvf_SetPtv_V0(cvf, false); Avtp_H264_t *h264 = (Avtp_H264_t *)(&cvf->payload); Avtp_H264_Init(h264); @@ -197,10 +197,10 @@ static int prepare_packet(Avtp_Cvf_t *cvfHeader, char *nal_data, size_t nal_data return -1; } - Avtp_Cvf_SetAvtpTimestamp(cvfHeader, avtp_time); - Avtp_Cvf_SetSequenceNum(cvfHeader, seq_num++); - Avtp_Cvf_SetStreamDataLength(cvfHeader, - (uint16_t)(nal_data_len + (size_t)AVTP_H264_HEADER_LEN)); + Avtp_Cvf_SetAvtpTimestamp_V0(cvfHeader, avtp_time); + Avtp_Cvf_SetSequenceNum_V0(cvfHeader, seq_num++); + Avtp_Cvf_SetStreamDataLength_V0(cvfHeader, + (uint16_t)(nal_data_len + (size_t)AVTP_H264_HEADER_LEN)); memcpy(h264Payload, nal_data, nal_data_len); diff --git a/examples/hello-world/hello-world-talker.c b/examples/hello-world/hello-world-talker.c index 5c0e9ab8..4dbbad4d 100644 --- a/examples/hello-world/hello-world-talker.c +++ b/examples/hello-world/hello-world-talker.c @@ -127,16 +127,16 @@ static int init_cf_pdu(uint8_t *pdu) Avtp_Tscf_t *tscf_pdu = (Avtp_Tscf_t *)pdu; memset(tscf_pdu, 0, AVTP_TSCF_HEADER_LEN); Avtp_Tscf_Init(tscf_pdu); - Avtp_Tscf_SetTu(tscf_pdu, false); - Avtp_Tscf_SetSequenceNum(tscf_pdu, seq_num++); - Avtp_Tscf_SetStreamId(tscf_pdu, STREAM_ID); + Avtp_Tscf_SetTu_V0(tscf_pdu, false); + Avtp_Tscf_SetSequenceNum_V0(tscf_pdu, seq_num++); + Avtp_Tscf_SetStreamId_V0(tscf_pdu, STREAM_ID); res = AVTP_TSCF_HEADER_LEN; } else { Avtp_Ntscf_t *ntscf_pdu = (Avtp_Ntscf_t *)pdu; memset(ntscf_pdu, 0, AVTP_NTSCF_HEADER_LEN); Avtp_Ntscf_Init(ntscf_pdu); - Avtp_Ntscf_SetSequenceNum(ntscf_pdu, seq_num++); - Avtp_Ntscf_SetStreamId(ntscf_pdu, STREAM_ID); + Avtp_Ntscf_SetSequenceNum_V0(ntscf_pdu, seq_num++); + Avtp_Ntscf_SetStreamId_V0(ntscf_pdu, STREAM_ID); res = AVTP_NTSCF_HEADER_LEN; } return res; @@ -146,10 +146,10 @@ static int update_pdu_length(uint8_t *pdu, uint64_t length) { if (use_tscf) { uint64_t payloadLen = length - AVTP_TSCF_HEADER_LEN; - Avtp_Tscf_SetStreamDataLength((Avtp_Tscf_t *)pdu, payloadLen); + Avtp_Tscf_SetStreamDataLength_V0((Avtp_Tscf_t *)pdu, (uint16_t)payloadLen); } else { uint64_t payloadLen = length - AVTP_NTSCF_HEADER_LEN; - Avtp_Ntscf_SetNtscfDataLength((Avtp_Ntscf_t *)pdu, payloadLen); + Avtp_Ntscf_SetNtscfDataLength_V0((Avtp_Ntscf_t *)pdu, (uint16_t)payloadLen); } return 0; } @@ -180,10 +180,10 @@ static int update_cf_length(uint8_t *cf_pdu, uint64_t length) { if (use_tscf) { uint64_t payloadLen = length - AVTP_TSCF_HEADER_LEN; - Avtp_Tscf_SetStreamDataLength((Avtp_Tscf_t *)cf_pdu, payloadLen); + Avtp_Tscf_SetStreamDataLength_V0((Avtp_Tscf_t *)cf_pdu, (uint16_t)payloadLen); } else { uint64_t payloadLen = length - AVTP_NTSCF_HEADER_LEN; - Avtp_Ntscf_SetNtscfDataLength((Avtp_Ntscf_t *)cf_pdu, payloadLen); + Avtp_Ntscf_SetNtscfDataLength_V0((Avtp_Ntscf_t *)cf_pdu, (uint16_t)payloadLen); } return 0; } diff --git a/include/avtp/Utils.h b/include/avtp/Utils.h index 89516934..f95cc4ee 100644 --- a/include/avtp/Utils.h +++ b/include/avtp/Utils.h @@ -32,10 +32,16 @@ * This file contains the parser for reading and writing data fields within IEEE * 1722 Base PDUs and perform all the necessary conversion from/to host/network * byte-order. + * + * The field-access engine is defined inline so that accessors using constant + * descriptors and field indices can be folded into direct bit manipulation by + * the compiler. The shared library exports the same functions as regular + * symbols (see src/avtp/export/InlineExports.c) for FFI users. */ #pragma once +#include "avtp/Inline.h" #include "avtp/Defines.h" #include "avtp/Byteorder.h" @@ -43,29 +49,104 @@ extern "C" { #endif +/** + * Returns the smaller of two octet values. Implementation detail of the field + * access engine. + */ +static inline uint8_t Avtp_MinU8(uint8_t a, uint8_t b) +{ + return a < b ? a : b; +} + /** * Extracts a data field from a 1722 frame and handles necessary byte-order * conversions. * + * @param fieldDescriptors Pointer to the field descriptor table. + * @param numFields Number of entries in the descriptor table. * @param pdu Pointer to the first bit of an 1722 PDU. This is typically an 1722 * AVTP- or an ACF header. * @param field Specifies the position of the data field to be read * @returns This function returns the field value from the PDU. */ -uint64_t Avtp_GetField(const Avtp_FieldDescriptor_t *fieldDescriptors, uint8_t numFields, - const uint8_t *const pdu, uint8_t field); +OPEN1722_INLINE uint64_t Avtp_GetField(const Avtp_FieldDescriptor_t *fieldDescriptors, + uint8_t numFields, const uint8_t *const pdu, uint8_t field) +{ + uint64_t result = 0; + if (fieldDescriptors != NULL && pdu != NULL && field < numFields) { + const Avtp_FieldDescriptor_t *fieldDescriptor = &fieldDescriptors[field]; + uint8_t quadletOffset = 0; + uint8_t processedBits = 0; + while (processedBits < fieldDescriptor->bits) { + uint8_t quadletId = fieldDescriptor->quadlet + quadletOffset; + uint8_t quadletBits; + uint8_t quadletShift; + if (processedBits == 0) { + quadletBits = Avtp_MinU8((uint8_t)(32 - fieldDescriptor->offset), + (uint8_t)(fieldDescriptor->bits - processedBits)); + quadletShift = (uint8_t)(32 - quadletBits - fieldDescriptor->offset); + } else { + quadletBits = Avtp_MinU8(32, (uint8_t)(fieldDescriptor->bits - processedBits)); + quadletShift = (uint8_t)(32 - quadletBits); + } + uint32_t quadletMask = (uint32_t)(((1ULL << quadletBits) - 1ULL) << quadletShift); + const uint32_t *quadletPtr = (const uint32_t *)(pdu + quadletId * 4); + uint32_t quadletHostOrder = Avtp_BeToCpu32(*quadletPtr); + uint32_t partialValue = (quadletHostOrder & quadletMask) >> quadletShift; + result |= (uint64_t)(partialValue) + << (fieldDescriptor->bits - processedBits - quadletBits); + + quadletOffset += 1; + processedBits += quadletBits; + } + } + return result; +} /** * Sets a data field in a 1722 frame to a specified value and handles necessary * byte-order conversions. * + * @param fieldDescriptors Pointer to the field descriptor table. + * @param numFields Number of entries in the descriptor table. * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- * or an ACF header. * @param field Specifies the position of the data field to be written * @param value The value to set. */ -void Avtp_SetField(const Avtp_FieldDescriptor_t *fieldDescriptors, uint8_t numFields, uint8_t *pdu, - uint8_t field, uint64_t value); +OPEN1722_INLINE void Avtp_SetField(const Avtp_FieldDescriptor_t *fieldDescriptors, + uint8_t numFields, uint8_t *pdu, uint8_t field, uint64_t value) +{ + if (fieldDescriptors != NULL && pdu != NULL && field < numFields) { + const Avtp_FieldDescriptor_t *fieldDescriptor = &fieldDescriptors[field]; + uint8_t quadletOffset = 0; + uint8_t processedBits = 0; + while (processedBits < fieldDescriptor->bits) { + uint8_t quadletId = fieldDescriptor->quadlet + quadletOffset; + uint8_t quadletBits; + uint8_t quadletShift; + if (processedBits == 0) { + quadletBits = Avtp_MinU8((uint8_t)(32 - fieldDescriptor->offset), + (uint8_t)(fieldDescriptor->bits - processedBits)); + quadletShift = (uint8_t)(32 - quadletBits - fieldDescriptor->offset); + } else { + quadletBits = Avtp_MinU8(32, (uint8_t)(fieldDescriptor->bits - processedBits)); + quadletShift = (uint8_t)(32 - quadletBits); + } + uint32_t partialValue = + (uint32_t)(value >> (fieldDescriptor->bits - processedBits - quadletBits)); + uint32_t quadletMask = (uint32_t)(((1ULL << quadletBits) - 1ULL) << quadletShift); + uint32_t *quadletPtr = (uint32_t *)(pdu + quadletId * 4); + uint32_t quadletHostOrder = Avtp_BeToCpu32(*quadletPtr); + quadletHostOrder = + (quadletHostOrder & ~quadletMask) | ((partialValue << quadletShift) & quadletMask); + *quadletPtr = Avtp_CpuToBe32(quadletHostOrder); + + quadletOffset += 1; + processedBits += quadletBits; + } + } +} #ifdef __cplusplus } diff --git a/src/avtp/Utils.c b/src/avtp/Utils.c deleted file mode 100644 index d195dc77..00000000 --- a/src/avtp/Utils.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2024, COVESA - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of COVESA nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifdef LINUX_KERNEL1722 -#include -#else -#include -#include -#endif - -#include "avtp/Utils.h" -#include "avtp/Defines.h" -#include "avtp/Byteorder.h" - -#define MAX(x, y) (((x) > (y)) ? (x) : (y)) -#define MIN(x, y) (((x) < (y)) ? (x) : (y)) - -uint64_t Avtp_GetField(const Avtp_FieldDescriptor_t *fieldDescriptors, uint8_t numFields, - const uint8_t *const pdu, uint8_t field) -{ - uint64_t result = 0; - if (fieldDescriptors != NULL && pdu != NULL && field < numFields) { - const Avtp_FieldDescriptor_t *fieldDescriptor = &fieldDescriptors[field]; - uint8_t quadletOffset = 0; - uint8_t processedBits = 0; - while (processedBits < fieldDescriptor->bits) { - uint8_t quadletId = fieldDescriptor->quadlet + quadletOffset; - uint8_t quadletBits; - uint8_t quadletShift; - if (processedBits == 0) { - quadletBits = (uint8_t)MIN(32 - fieldDescriptor->offset, - fieldDescriptor->bits - processedBits); - quadletShift = (uint8_t)(32 - quadletBits - fieldDescriptor->offset); - } else { - quadletBits = (uint8_t)MIN(32, fieldDescriptor->bits - processedBits); - quadletShift = (uint8_t)(32 - quadletBits); - } - uint32_t quadletMask = (uint32_t)(((1ULL << quadletBits) - 1ULL) << quadletShift); - const uint32_t *quadletPtr = (const uint32_t *)(pdu + quadletId * 4); - uint32_t quadletHostOrder = Avtp_BeToCpu32(*quadletPtr); - uint32_t partialValue = (quadletHostOrder & quadletMask) >> quadletShift; - result |= (uint64_t)(partialValue) - << (fieldDescriptor->bits - processedBits - quadletBits); - - quadletOffset += 1; - processedBits += quadletBits; - } - } - return result; -} - -void Avtp_SetField(const Avtp_FieldDescriptor_t *fieldDescriptors, uint8_t numFields, uint8_t *pdu, - uint8_t field, uint64_t value) -{ - if (fieldDescriptors != NULL && pdu != NULL && field < numFields) { - const Avtp_FieldDescriptor_t *fieldDescriptor = &fieldDescriptors[field]; - uint8_t quadletOffset = 0; - uint8_t processedBits = 0; - while (processedBits < fieldDescriptor->bits) { - uint8_t quadletId = fieldDescriptor->quadlet + quadletOffset; - uint8_t quadletBits; - uint8_t quadletShift; - if (processedBits == 0) { - quadletBits = (uint8_t)MIN(32 - fieldDescriptor->offset, - fieldDescriptor->bits - processedBits); - quadletShift = (uint8_t)(32 - quadletBits - fieldDescriptor->offset); - } else { - quadletBits = (uint8_t)MIN(32, fieldDescriptor->bits - processedBits); - quadletShift = (uint8_t)(32 - quadletBits); - } - uint32_t partialValue = - (uint32_t)(value >> (fieldDescriptor->bits - processedBits - quadletBits)); - uint32_t quadletMask = (uint32_t)(((1ULL << quadletBits) - 1ULL) << quadletShift); - uint32_t *quadletPtr = (uint32_t *)(pdu + quadletId * 4); - uint32_t quadletHostOrder = Avtp_BeToCpu32(*quadletPtr); - quadletHostOrder = - (quadletHostOrder & ~quadletMask) | ((partialValue << quadletShift) & quadletMask); - *quadletPtr = Avtp_CpuToBe32(quadletHostOrder); - - quadletOffset += 1; - processedBits += quadletBits; - } - } -} diff --git a/src/avtp/export/InlineExports.c b/src/avtp/export/InlineExports.c index 672219d0..4219be75 100644 --- a/src/avtp/export/InlineExports.c +++ b/src/avtp/export/InlineExports.c @@ -30,12 +30,15 @@ /* * Forces external definitions of all inline functions in the public headers. * - * Phase 1 includes all transitive dependencies (Byteorder, Utils, - * AcfCommon, etc.) in the default static-inline mode so they have - * internal linkage and do not conflict between translation units. + * Phase 1 includes the leaf dependencies (Byteorder, Defines, etc.) in the + * default static-inline mode so they have internal linkage and do not conflict + * between translation units. * - * Phase 2 overrides OPEN1722_INLINE to empty and includes each target - * header, making its inline functions regular extern definitions. + * Phase 2 overrides OPEN1722_INLINE to empty and includes each target header, + * making its inline functions regular extern definitions. Utils.h comes first + * because the field-access engine it defines is used by all format headers; + * AcfCommon.h follows it (it includes Utils.h, so both must be processed in + * this mode for their functions to be exported). */ /* --- Phase 1: shared deps (static-inline mode) ----------------------- */ @@ -44,14 +47,15 @@ #include "avtp/Inline.h" #include "avtp/Defines.h" #include "avtp/Byteorder.h" -#include "avtp/Utils.h" -#include "avtp/acf/AcfCommon.h" /* --- Phase 2: target headers (extern-definition mode) ---------------- */ #undef OPEN1722_INLINE #define OPEN1722_INLINE +#include "avtp/Utils.h" +#include "avtp/acf/AcfCommon.h" + #include "avtp/CommonHeader.h" #include "avtp/CommonStreamHeader.h" #include "avtp/AlternativeHeader.h" From 2ec95174f136c967c57054db327062b6fa54cfb6 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Sun, 20 Sep 2026 23:32:08 +0200 Subject: [PATCH 11/16] Add microbenchmark for regression testing and remove unneeded coverage instrumentation Signed-off-by: Sebastian Schildt --- CMakeLists.txt | 1 + bench/CMakeLists.txt | 32 ++++++ bench/README.md | 65 ++++++++++++ bench/bench-field-access.c | 207 +++++++++++++++++++++++++++++++++++++ bench/check-folding.sh | 139 +++++++++++++++++++++++++ docs/inline.md | 16 +++ unit/CMakeLists.txt | 10 +- 7 files changed, 466 insertions(+), 4 deletions(-) create mode 100644 bench/CMakeLists.txt create mode 100644 bench/README.md create mode 100644 bench/bench-field-access.c create mode 100755 bench/check-folding.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index eab6df0b..b5a83455 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,7 @@ if (NOT (DEFINED ENV{ZEPHYR_BASE})) enable_testing() add_custom_target(unittests) add_subdirectory(unit EXCLUDE_FROM_ALL) + add_subdirectory(bench EXCLUDE_FROM_ALL) install(DIRECTORY include/ DESTINATION include) install(TARGETS open1722 EXPORT Open1722Targets DESTINATION lib) diff --git a/bench/CMakeLists.txt b/bench/CMakeLists.txt new file mode 100644 index 00000000..6e53937e --- /dev/null +++ b/bench/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# Copyright (c) 2026, COVESA +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# # Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# # Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# # Neither the name of COVESA nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +add_executable(bench-field-access bench-field-access.c) +target_link_libraries(bench-field-access open1722) +target_include_directories(bench-field-access PRIVATE ${PROJECT_SOURCE_DIR}/include) diff --git a/bench/README.md b/bench/README.md new file mode 100644 index 00000000..ebe7da34 --- /dev/null +++ b/bench/README.md @@ -0,0 +1,65 @@ +# Accessor benchmarks and folding check + +This directory contains tooling that validates the performance claim behind the +version-typed accessors (`_V0`/`_V1`): they should compile to direct bit +manipulation, close to a hand-written raw access, while the version-agnostic +accessors pay one version read and branch on top. + +## Folding check + +```sh +./bench/check-folding.sh [build-dir] +``` + +Builds `libopen1722.so` in Release mode (default build dir `build-folding`) and +checks two things: + +1. **Consumer path (the performance claim).** A small probe including the + headers is compiled at `-O2`; the generated assembly for a version-typed and + a version-agnostic accessor must contain no `call` instructions. This is the + path that embedded and normal C consumers use. +2. **Exported FFI wrappers.** The exported copies in `libopen1722.so` are + regular functions and C semantic interposition prevents the compiler from + fully folding them, so the check only asserts that representative typed + accessors (`Avtp_Tscf_GetSequenceNum_V1`, `Avtp_Tscf_SetSequenceNum_V1`, + `Avtp_CommonStreamHeader_GetStreamId_V1`, `Avtp_Rvf_GetActivePixels_V1`) + never fall back to the version-agnostic dispatcher, the generic engine or the + version readers. + +The script exits non-zero on failure. + +This check is deliberately not wired into CI: it inspects generated code and is +compiler/optimizer sensitive. Run it after changes to the field-access engine or +the accessor patterns. + +## Micro-benchmark + +```sh +cmake -S . -B build-bench -DCMAKE_BUILD_TYPE=Release +cmake --build build-bench --target bench-field-access -j"$(nproc)" +./build-bench/bench/bench-field-access +``` + +`bench-field-access` measures typed vs. agnostic vs. raw access for: + +- TSCF v1 and v0 `sequence_num` (32 bit and 8 bit), get and set +- TSCF v1 `stream_id` (64 bit, two quadlets) +- RVF v1 `active_pixels` (format-specific field) + +Each measurement runs 20 million iterations with a compiler barrier per +iteration so the loops cannot be optimized away or hoisted. Build with +`-DCMAKE_BUILD_TYPE=Release`; the library is not instrumented for coverage in +any build (see `unit/CMakeLists.txt`), so no special build flags are needed. + +Example output shape: + +``` +TSCF version 1, get sequence_num (32 bit): + typed Avtp_Tscf_GetSequenceNum_V1 0.3 ns/op + agnostic Avtp_Tscf_GetSequenceNum 1.2 ns/op + raw be32(header + 12) 0.3 ns/op +``` + +Absolute numbers depend on the machine and compiler; the typed column should be +within a few percent of the raw column, and the agnostic column is expected to +be a few cycles slower. diff --git a/bench/bench-field-access.c b/bench/bench-field-access.c new file mode 100644 index 00000000..045e2308 --- /dev/null +++ b/bench/bench-field-access.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2026, COVESA + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of COVESA nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * Micro-benchmark comparing version-typed accessors, version-agnostic + * accessors and raw bit access on the same PDUs. + * + * Build a Release build and run: + * + * cmake -S . -B build-bench -DCMAKE_BUILD_TYPE=Release + * cmake --build build-bench --target bench-field-access -j"$(nproc)" + * ./build-bench/bench/bench-field-access + * + * The absolute numbers depend on the machine; the point is the ratio between + * the typed and the raw column. A version-typed accessor should be within a + * few percent of the raw access, while the agnostic variant pays one version + * load and branch on top. See README.md and check-folding.sh. + */ + +#include +#include +#include +#include + +#include "avtp/Byteorder.h" +#include "avtp/Rvf.h" +#include "avtp/acf/Tscf.h" + +#define ITERATIONS 20000000u + +static volatile uint64_t sink; + +/* + * Keeps the compiler from hoisting loop-invariant loads or coalescing the + * stores; it is applied to every variant equally. + */ +#if defined(__GNUC__) +#define COMPILER_BARRIER() __asm__ __volatile__("" ::: "memory") +#else +#define COMPILER_BARRIER() (sink ^= 1u) +#endif + +static uint64_t now_ns(void) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + return ((uint64_t)ts.tv_sec * 1000000000ULL) + (uint64_t)ts.tv_nsec; +} + +#define BENCH(label, body) \ + do { \ + uint64_t bench_sum = 0; \ + uint64_t bench_start = now_ns(); \ + for (uint32_t bench_i = 0; bench_i < ITERATIONS; bench_i++) { \ + COMPILER_BARRIER(); \ + body; \ + } \ + uint64_t bench_elapsed = now_ns() - bench_start; \ + sink += bench_sum; \ + printf(" %-40s %8.3f ns/op\n", label, (double)bench_elapsed / (double)ITERATIONS); \ + } while (0) + +static uint32_t raw_be32(const uint8_t *p) +{ + uint32_t value; + + memcpy(&value, p, sizeof(value)); + return Avtp_BeToCpu32(value); +} + +static void bench_tscf_v1_get(void) +{ + uint8_t buf[AVTP_TSCF_HEADER_LEN_V1]; + Avtp_TscfV1_t *pdu = (Avtp_TscfV1_t *)buf; + + Avtp_Tscf_InitV1(pdu); + Avtp_Tscf_SetSequenceNum_V1(pdu, 0x12345678); + + printf("TSCF version 1, get sequence_num (32 bit):\n"); + BENCH("typed Avtp_Tscf_GetSequenceNum_V1", bench_sum += Avtp_Tscf_GetSequenceNum_V1(pdu)); + BENCH("agnostic Avtp_Tscf_GetSequenceNum", + bench_sum += Avtp_Tscf_GetSequenceNum((const Avtp_Tscf_t *)pdu)); + BENCH("raw be32(header + 12)", bench_sum += raw_be32(pdu->header + 12)); +} + +static void bench_tscf_v1_set(void) +{ + uint8_t buf[AVTP_TSCF_HEADER_LEN_V1]; + Avtp_TscfV1_t *pdu = (Avtp_TscfV1_t *)buf; + + Avtp_Tscf_InitV1(pdu); + + printf("TSCF version 1, set sequence_num (32 bit + lsb copy):\n"); + BENCH("typed Avtp_Tscf_SetSequenceNum_V1", Avtp_Tscf_SetSequenceNum_V1(pdu, bench_i); + bench_sum += pdu->header[15]); + BENCH("agnostic Avtp_Tscf_SetSequenceNum", + Avtp_Tscf_SetSequenceNum((Avtp_Tscf_t *)pdu, bench_i); + bench_sum += pdu->header[15]); + BENCH("raw two stores", uint32_t raw = Avtp_CpuToBe32(bench_i); + memcpy(pdu->header + 12, &raw, sizeof(raw)); pdu->header[2] = (uint8_t)bench_i; + bench_sum += pdu->header[15]); +} + +static void bench_tscf_v0_get(void) +{ + uint8_t buf[AVTP_TSCF_HEADER_LEN_V0]; + Avtp_Tscf_t *pdu = (Avtp_Tscf_t *)buf; + + Avtp_Tscf_Init(pdu); + Avtp_Tscf_SetSequenceNum_V0(pdu, 0xAB); + + printf("TSCF version 0, get sequence_num (8 bit):\n"); + BENCH("typed Avtp_Tscf_GetSequenceNum_V0", bench_sum += Avtp_Tscf_GetSequenceNum_V0(pdu)); + BENCH("agnostic Avtp_Tscf_GetSequenceNum", bench_sum += Avtp_Tscf_GetSequenceNum(pdu)); + BENCH("raw (be32(header) >> 8) & 0xff", bench_sum += (raw_be32(pdu->header) >> 8) & 0xFFU); +} + +static void bench_tscf_v0_set(void) +{ + uint8_t buf[AVTP_TSCF_HEADER_LEN_V0]; + Avtp_Tscf_t *pdu = (Avtp_Tscf_t *)buf; + + Avtp_Tscf_Init(pdu); + + printf("TSCF version 0, set sequence_num (8 bit):\n"); + BENCH("typed Avtp_Tscf_SetSequenceNum_V0", Avtp_Tscf_SetSequenceNum_V0(pdu, bench_i); + bench_sum += pdu->header[15]); + BENCH("agnostic Avtp_Tscf_SetSequenceNum", Avtp_Tscf_SetSequenceNum(pdu, bench_i); + bench_sum += pdu->header[15]); + BENCH("raw one store", pdu->header[2] = (uint8_t)bench_i; bench_sum += pdu->header[15]); +} + +static void bench_tscf_v1_stream_id(void) +{ + uint8_t buf[AVTP_TSCF_HEADER_LEN_V1]; + Avtp_TscfV1_t *pdu = (Avtp_TscfV1_t *)buf; + + Avtp_Tscf_InitV1(pdu); + Avtp_Tscf_SetStreamId_V1(pdu, 0x0102030405060708ULL); + + printf("TSCF version 1, get stream_id (64 bit, two quadlets):\n"); + BENCH("typed Avtp_Tscf_GetStreamId_V1", bench_sum += Avtp_Tscf_GetStreamId_V1(pdu)); + BENCH("agnostic Avtp_Tscf_GetStreamId", + bench_sum += Avtp_Tscf_GetStreamId((const Avtp_Tscf_t *)pdu)); + BENCH("raw two be32 loads", bench_sum += ((uint64_t)raw_be32(pdu->header + 4) << 32) | + (uint64_t)raw_be32(pdu->header + 8)); +} + +static void bench_rvf_v1_active_pixels(void) +{ + uint8_t buf[AVTP_RVF_HEADER_LEN_V1]; + Avtp_RvfV1_t *pdu = (Avtp_RvfV1_t *)buf; + + Avtp_Rvf_InitV1(pdu); + Avtp_Rvf_SetActivePixels_V1(pdu, 1920); + + printf("RVF version 1, get active_pixels (format-specific, 16 bit):\n"); + BENCH("typed Avtp_Rvf_GetActivePixels_V1", bench_sum += Avtp_Rvf_GetActivePixels_V1(pdu)); + BENCH("agnostic Avtp_Rvf_GetActivePixels", + bench_sum += Avtp_Rvf_GetActivePixels((const Avtp_Rvf_t *)pdu)); + BENCH("raw be32(header + 32) >> 16", bench_sum += raw_be32(pdu->header + 32) >> 16); +} + +int main(void) +{ + printf("bench-field-access: %u iterations per measurement, compiler %s\n\n", ITERATIONS, + __VERSION__); + + bench_tscf_v1_get(); + bench_tscf_v1_set(); + bench_tscf_v0_get(); + bench_tscf_v0_set(); + bench_tscf_v1_stream_id(); + bench_rvf_v1_active_pixels(); + + printf("\nsink=%" PRIu64 " (prevents the compiler from discarding the loops)\n", sink); + + return 0; +} diff --git a/bench/check-folding.sh b/bench/check-folding.sh new file mode 100755 index 00000000..6f6ab947 --- /dev/null +++ b/bench/check-folding.sh @@ -0,0 +1,139 @@ +#!/bin/sh +# +# Copyright (c) 2026, COVESA +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# # Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# # Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# # Neither the name of COVESA nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Verifies that version-typed accessors fold to direct bit manipulation: +# +# 1. The performance path is the header path: a consumer probe compiled at -O2 +# must produce call-free code for both the typed and the agnostic accessor. +# 2. The exported copies in libopen1722.so are FFI wrappers. C semantic +# interposition prevents the compiler from fully folding them, so the check +# only asserts that they never fall back to the version-agnostic dispatcher, +# the generic engine or the version readers. +# +# Usage: ./bench/check-folding.sh [build-dir] + +set -eu + +script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +root_dir=$(CDPATH= cd -- "$script_dir/.." && pwd) +build_dir=${1:-"$root_dir/build-folding"} + +if ! command -v objdump >/dev/null 2>&1; then + echo "check-folding: objdump not found" >&2 + exit 2 +fi + +echo "Configuring $build_dir (Release)..." +cmake -S "$root_dir" -B "$build_dir" -DCMAKE_BUILD_TYPE=Release >/dev/null +cmake --build "$build_dir" --target open1722 -j"$(nproc)" >/dev/null + +lib="$build_dir/src/libopen1722.so" +tmp_dir=$(mktemp -d) +trap 'rm -rf "$tmp_dir"' EXIT + +objdump -d --no-show-raw-insn "$lib" >"$tmp_dir/disasm.txt" + +failures=0 + +function_body() { + symbol=$1 + file=$2 + awk -v s="$symbol" ' + $0 ~ ("^[0-9a-f]+ <" s ">:") { found = 1; print; next } + $0 == (s ":") { found = 1; print; next } + found && /^[0-9a-f]+ )|Avtp_SetField(@plt|\.part|>)|Avtp_[A-Za-z]+_GetField(@plt|\.part|>)|Avtp_[A-Za-z]+_SetField(@plt|\.part|>)|GetVersion(@plt|\.part|>)' + +check_exported_typed() { + symbol=$1 + body=$(function_body "$symbol" "$tmp_dir/disasm.txt") + if [ -z "$body" ]; then + echo "FAIL $symbol: symbol not found in $lib" + failures=$((failures + 1)) + return + fi + if printf '%s\n' "$body" | grep -qE "$FORBIDDEN"; then + echo "FAIL $symbol: falls back to dispatch/engine/version read" + printf '%s\n' "$body" | grep -E "$FORBIDDEN" | sed 's/^/ /' + failures=$((failures + 1)) + else + echo "ok $symbol" + fi +} + +echo +echo "Exported version-typed accessors (expect no dispatch/engine fallback):" +check_exported_typed Avtp_Tscf_GetSequenceNum_V1 +check_exported_typed Avtp_Tscf_SetSequenceNum_V1 +check_exported_typed Avtp_CommonStreamHeader_GetStreamId_V1 +check_exported_typed Avtp_Rvf_GetActivePixels_V1 + +echo +echo "Consumer probe compiled at -O2 (expect call-free code):" +cat >"$tmp_dir/probe.c" <<'EOF' +#include "avtp/acf/Tscf.h" + +uint32_t probe_typed(const Avtp_TscfV1_t *pdu) +{ + return Avtp_Tscf_GetSequenceNum_V1(pdu); +} + +uint32_t probe_agnostic(const Avtp_Tscf_t *pdu) +{ + return Avtp_Tscf_GetSequenceNum(pdu); +} +EOF +cc -std=c99 -O2 -I"$root_dir/include" -S -o"$tmp_dir/probe.s" "$tmp_dir/probe.c" +for probe in probe_typed probe_agnostic; do + body=$(function_body "$probe" "$tmp_dir/probe.s") + if [ -z "$body" ]; then + echo "FAIL $probe: not found in generated assembly" + failures=$((failures + 1)) + elif printf '%s\n' "$body" | grep -qE '[[:space:]]call'; then + echo "FAIL $probe: contains a call" + printf '%s\n' "$body" | grep -E '[[:space:]]call' | sed 's/^/ /' + failures=$((failures + 1)) + else + echo "ok $probe" + fi +done + +echo +if [ "$failures" -ne 0 ]; then + echo "$failures folding check(s) failed" + exit 1 +fi +echo "All folding checks passed" diff --git a/docs/inline.md b/docs/inline.md index 76b695a9..7041c77e 100644 --- a/docs/inline.md +++ b/docs/inline.md @@ -108,6 +108,22 @@ src/avtp/export/ When a new header with inline functions is added, simply add its `#include` to `InlineExports.c` in phase 2. +## Coverage instrumentation + +The libraries are deliberately **not** instrumented for coverage. The accessors +and the field-access engine are inline in public headers, so the code that +actually executes in the tests is compiled into the test executables; those are +instrumented instead (see `add_dual_test` in `unit/CMakeLists.txt`). +`test_all.sh` filters the lcov report to the public headers +(`--include '*/include/*/*.h'`), which is where the inline code lives. +Instrumenting the libraries would add gcov counters to local and benchmark +builds without contributing to the report. + +Note that the exported copies of the accessors are regular functions, so C +semantic interposition can leave calls between them. The performance guarantee +of the version-typed accessors applies to the header path; see +[`bench/README.md`](../bench/README.md). + ## Frequently Asked Questions ### Does this affect embedded / Zephyr / bare-metal builds? diff --git a/unit/CMakeLists.txt b/unit/CMakeLists.txt index 45f95bfe..874b1a9d 100644 --- a/unit/CMakeLists.txt +++ b/unit/CMakeLists.txt @@ -35,10 +35,12 @@ if (NOT cmocka_FOUND) return() endif() -target_compile_options(open1722 PRIVATE -coverage) -target_link_options(open1722 PRIVATE -coverage) -target_compile_options(open1722custom PRIVATE -coverage) -target_link_options(open1722custom PRIVATE -coverage) +# Coverage is measured on the unit test executables only (see add_dual_test +# below), not on the libraries: the public accessors and the field-access +# engine are header-inline, so the test translation units are where that code +# is actually executed and counted. test_all.sh filters the lcov report to the +# public headers. Instrumenting the libraries would add gcov overhead to local +# and benchmark builds without contributing to the report. # Function to create dual tests (C and C++ compilation) for the same source file function(add_dual_test TEST_NAME SOURCE_FILE) From 38123464516defb08df3634c29fc88098db21ad0 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Fri, 2 Oct 2026 17:54:36 +0200 Subject: [PATCH 12/16] Check PDU length in acf-can examples before parsing Signed-off-by: Sebastian Schildt --- examples/acf-can/acf-can-common.c | 31 ++++++++++++++++++++--- examples/acf-can/acf-can-common.h | 7 +++-- examples/acf-can/linux/acf-can-bridge.c | 7 ++--- examples/acf-can/linux/acf-can-listener.c | 7 ++--- examples/acf-can/zephyr/acf-can-bridge.c | 6 ++--- 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/examples/acf-can/acf-can-common.c b/examples/acf-can/acf-can-common.c index 3fe22b3e..c0369a98 100644 --- a/examples/acf-can/acf-can-common.c +++ b/examples/acf-can/acf-can-common.c @@ -261,8 +261,8 @@ int can_to_avtp(frame_t *can_frames, bool can_fd, uint8_t *pdu, int use_udp, acf return pdu_length; } -int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uint64_t stream_id, - uint32_t *exp_cf_seqnum, uint32_t *exp_udp_seqnum) +int avtp_to_can(uint8_t *pdu, size_t pdu_length, frame_t *can_frames, bool can_fd, int use_udp, + uint64_t stream_id, uint32_t *exp_cf_seqnum, uint32_t *exp_udp_seqnum) { uint8_t *cf_pdu, *acf_pdu, *udp_pdu, i = 0; @@ -273,6 +273,10 @@ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uin // Check for UDP encapsulation if (use_udp) { + if (pdu_length < AVTP_UDP_HEADER_LEN) { + LOG_ERR("Truncated UDP encapsulated frame, ignoring frame.\n"); + return -1; + } udp_pdu = pdu; udp_seq_num = Avtp_Udp_GetEncapsulationSeqNo((Avtp_Udp_t *)udp_pdu); cf_pdu = pdu + AVTP_UDP_HEADER_LEN; @@ -287,9 +291,24 @@ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uin cf_pdu = pdu; } + /* The subtype is encoded in the first octet and the version in the + * second one. Both must have been received before the control format can + * be identified and validated below. */ + if (pdu_length - proc_bytes < 2) { + LOG_ERR("Truncated AVTP frame, ignoring frame.\n"); + return -1; + } + // Only NTSCF and TSCF formats allowed uint8_t subtype = Avtp_CommonHeader_GetSubtype((Avtp_CommonHeader_t *)cf_pdu); if (subtype == AVTP_SUBTYPE_TSCF) { + /* Validate the untrusted header against the number of bytes actually + * received: this checks the subtype and version, that the declared + * header fits, and that the declared stream data length fits. */ + if (!Avtp_Tscf_IsValid((const Avtp_Tscf_t *)cf_pdu, pdu_length - proc_bytes)) { + LOG_ERR("Invalid TSCF header, ignoring frame.\n"); + return -1; + } uint8_t version = Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)cf_pdu); if (!Avtp_Version_IsSupported(AVTP_TSCF_SUPPORTED_VERSIONS, version)) { @@ -312,6 +331,10 @@ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uin seq_num = Avtp_Tscf_GetSequenceNum_V0(tscf); } } else if (subtype == AVTP_SUBTYPE_NTSCF) { + if (!Avtp_Ntscf_IsValid((const Avtp_Ntscf_t *)cf_pdu, pdu_length - proc_bytes)) { + LOG_ERR("Invalid NTSCF header, ignoring frame.\n"); + return -1; + } uint8_t version = Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)cf_pdu); if (!Avtp_Version_IsSupported(AVTP_NTSCF_SUPPORTED_VERSIONS, version)) { @@ -358,7 +381,9 @@ int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uin * remaining buffer, and the resulting payload size must match * the CAN/CAN-FD bound encoded by the FDF bit. Without this * guard a malformed frame could feed garbage values to the - * consumers below. */ + * consumers below. The control format header was validated + * against the received byte count above, so msg_length can never + * exceed the received frame. */ if (!AVTP_CAN(IsValid)((AVTP_CAN(t) *)acf_pdu, msg_length - proc_bytes)) { LOG_ERR("Error: ACF CAN frame failed validation, ignoring frame.\n"); return -1; diff --git a/examples/acf-can/acf-can-common.h b/examples/acf-can/acf-can-common.h index fda30d55..edb80d30 100644 --- a/examples/acf-can/acf-can-common.h +++ b/examples/acf-can/acf-can-common.h @@ -27,6 +27,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include + #ifdef __linux__ #include #elif defined(__ZEPHYR__) @@ -111,6 +113,7 @@ int setup_can_socket(const char *can_ifname, bool can_fd); * Function that converts AVTP Frames to CAN * * @param pdu: Start of the AVTP Frame + * @param pdu_length: Number of received bytes in the AVTP Frame * @param can_frames: Array of CAM Frames to be recovered from AVTP Frames * @param can_fd true: CAN-FD, false: Classic CAN * @param use_udp 1: UDP encapsulation, 0: Ethernet @@ -119,8 +122,8 @@ int setup_can_socket(const char *can_ifname, bool can_fd); * @param exp_udp_seqnum: Expected UDP Encapsulation sequence num. * @return Number of CAN messages received */ -int avtp_to_can(uint8_t *pdu, frame_t *can_frames, bool can_fd, int use_udp, uint64_t stream_id, - uint32_t *exp_cf_seqnum, uint32_t *exp_udp_seqnum); +int avtp_to_can(uint8_t *pdu, size_t pdu_length, frame_t *can_frames, bool can_fd, int use_udp, + uint64_t stream_id, uint32_t *exp_cf_seqnum, uint32_t *exp_udp_seqnum); /** * Function that converts AVTP Frames to CAN diff --git a/examples/acf-can/linux/acf-can-bridge.c b/examples/acf-can/linux/acf-can-bridge.c index e50ab82a..078e6ef1 100644 --- a/examples/acf-can/linux/acf-can-bridge.c +++ b/examples/acf-can/linux/acf-can-bridge.c @@ -242,7 +242,8 @@ void *can_to_avtp_runnable(void *args) void *avtp_to_can_runnable(void *args) { - uint16_t pdu_length = 0, cf_length = 0; + ssize_t pdu_length = 0; + uint16_t cf_length = 0; int8_t num_can_msgs = 0; uint32_t exp_cf_seqnum = 0; uint32_t exp_udp_seqnum = 0; @@ -258,8 +259,8 @@ void *avtp_to_can_runnable(void *args) continue; } - num_can_msgs = avtp_to_can(pdu, can_frames, can_fd, use_udp, listener_stream_id, - &exp_cf_seqnum, &exp_udp_seqnum); + num_can_msgs = avtp_to_can(pdu, (size_t)pdu_length, can_frames, can_fd, use_udp, + listener_stream_id, &exp_cf_seqnum, &exp_udp_seqnum); if (num_can_msgs <= 0) { continue; } diff --git a/examples/acf-can/linux/acf-can-listener.c b/examples/acf-can/linux/acf-can-listener.c index cab590ab..35c6874d 100644 --- a/examples/acf-can/linux/acf-can-listener.c +++ b/examples/acf-can/linux/acf-can-listener.c @@ -121,7 +121,8 @@ int main(int argc, char *argv[]) int can_socket = 0; struct sockaddr_can can_addr; struct ifreq ifr; - uint16_t pdu_length = 0, cf_length = 0; + ssize_t pdu_length = 0; + uint16_t cf_length = 0; int8_t num_can_msgs = 0; uint32_t exp_cf_seqnum = 0; uint32_t exp_udp_seqnum = 0; @@ -168,8 +169,8 @@ int main(int argc, char *argv[]) continue; } - num_can_msgs = avtp_to_can(pdu, can_frames, can_fd, use_udp, listener_stream_id, - &exp_cf_seqnum, &exp_udp_seqnum); + num_can_msgs = avtp_to_can(pdu, (size_t)pdu_length, can_frames, can_fd, use_udp, + listener_stream_id, &exp_cf_seqnum, &exp_udp_seqnum); if (num_can_msgs < 0) { continue; } diff --git a/examples/acf-can/zephyr/acf-can-bridge.c b/examples/acf-can/zephyr/acf-can-bridge.c index fe4af245..1d6dcef7 100644 --- a/examples/acf-can/zephyr/acf-can-bridge.c +++ b/examples/acf-can/zephyr/acf-can-bridge.c @@ -283,7 +283,7 @@ void can_to_avtp_runnable(void *p1, void *p2, void *p3) void avtp_to_can_runnable(void *p1, void *p2, void *p3) { - uint16_t pdu_length = 0; + ssize_t pdu_length = 0; int8_t num_can_msgs = 0; uint32_t exp_cf_seqnum = 0; uint32_t exp_udp_seqnum = 0; @@ -325,8 +325,8 @@ void avtp_to_can_runnable(void *p1, void *p2, void *p3) continue; } - num_can_msgs = avtp_to_can(pdu, can_frames, can_fd, use_udp, listener_stream_id, - &exp_cf_seqnum, &exp_udp_seqnum); + num_can_msgs = avtp_to_can(pdu, (size_t)pdu_length, can_frames, can_fd, use_udp, + listener_stream_id, &exp_cf_seqnum, &exp_udp_seqnum); if (num_can_msgs <= 0) { continue; } From cecc610657709fa76cc50985c751018e9b1e021c Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Fri, 2 Oct 2026 18:05:04 +0200 Subject: [PATCH 13/16] Restrict allowed values for TSCF/NTSCF version in Zephyr KConfig Signed-off-by: Sebastian Schildt --- examples/acf-can/zephyr/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/acf-can/zephyr/Kconfig b/examples/acf-can/zephyr/Kconfig index b9685c17..df088424 100644 --- a/examples/acf-can/zephyr/Kconfig +++ b/examples/acf-can/zephyr/Kconfig @@ -10,10 +10,12 @@ config ACF_CAN_BRIDGE_USE_TSCF config ACF_CAN_BRIDGE_TSCF_VERSION int "TSCF header version (0 or 1)" + range 0 1 default 0 config ACF_CAN_BRIDGE_NTSCF_VERSION int "NTSCF header version (0 or 1)" + range 0 1 default 0 config ACF_CAN_BRIDGE_SEND_MAC_ADDR From 7c6323c4fdbdcaf3f3af1f7912dfb8a520938391 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Fri, 2 Oct 2026 18:16:13 +0200 Subject: [PATCH 14/16] Fix sequence number rollover behavior in acf-can examples Signed-off-by: Sebastian Schildt --- examples/acf-can/acf-can-common.c | 11 ++++++++--- examples/acf-can/acf-can-common.h | 4 +++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/examples/acf-can/acf-can-common.c b/examples/acf-can/acf-can-common.c index c0369a98..9cbf92d6 100644 --- a/examples/acf-can/acf-can-common.c +++ b/examples/acf-can/acf-can-common.c @@ -268,6 +268,7 @@ int avtp_to_can(uint8_t *pdu, size_t pdu_length, frame_t *can_frames, bool can_f uint8_t *cf_pdu, *acf_pdu, *udp_pdu, i = 0; uint32_t seq_num; uint32_t udp_seq_num; + uint32_t seq_mask = UINT32_MAX; uint16_t proc_bytes = 0, msg_length = 0; uint64_t s_id; @@ -329,6 +330,7 @@ int avtp_to_can(uint8_t *pdu, size_t pdu_length, frame_t *can_frames, bool can_f msg_length += (uint16_t)(Avtp_Tscf_GetStreamDataLength_V0(tscf) + headerLen); s_id = Avtp_Tscf_GetStreamId_V0(tscf); seq_num = Avtp_Tscf_GetSequenceNum_V0(tscf); + seq_mask = 0xFFU; } } else if (subtype == AVTP_SUBTYPE_NTSCF) { if (!Avtp_Ntscf_IsValid((const Avtp_Ntscf_t *)cf_pdu, pdu_length - proc_bytes)) { @@ -355,6 +357,7 @@ int avtp_to_can(uint8_t *pdu, size_t pdu_length, frame_t *can_frames, bool can_f msg_length += (uint16_t)(Avtp_Ntscf_GetNtscfDataLength_V0(ntscf) + headerLen); s_id = Avtp_Ntscf_GetStreamId_V0(ntscf); seq_num = Avtp_Ntscf_GetSequenceNum_V0(ntscf); + seq_mask = 0xFFU; } } else { return -1; @@ -365,10 +368,12 @@ int avtp_to_can(uint8_t *pdu, size_t pdu_length, frame_t *can_frames, bool can_f return -1; } - // Check sequence numbers. - if (seq_num != *exp_cf_seqnum) { + // Check sequence numbers. Version 0 only carries an 8-bit sequence + // number, so compare modulo 256 there; version 1 uses the full 32 bits. + uint32_t expected_seq_num = *exp_cf_seqnum & seq_mask; + if ((seq_num & seq_mask) != expected_seq_num) { LOG_ERR("Incorrect sequence num. Expected: %" PRIu32 " Recd.: %" PRIu32 "\n", - *exp_cf_seqnum, seq_num); + expected_seq_num, seq_num); *exp_cf_seqnum = seq_num; } diff --git a/examples/acf-can/acf-can-common.h b/examples/acf-can/acf-can-common.h index edb80d30..e25e50b1 100644 --- a/examples/acf-can/acf-can-common.h +++ b/examples/acf-can/acf-can-common.h @@ -118,7 +118,9 @@ int setup_can_socket(const char *can_ifname, bool can_fd); * @param can_fd true: CAN-FD, false: Classic CAN * @param use_udp 1: UDP encapsulation, 0: Ethernet * @param stream_id: AVTP stream ID of interest - * @param exp_cf_seqnum: Expected Control format sequence num. + * @param exp_cf_seqnum: Expected Control format sequence num. Version 0 + * control formats carry an 8-bit sequence number, so only the low 8 bits are + * compared for them; version 1 uses the full 32 bits. * @param exp_udp_seqnum: Expected UDP Encapsulation sequence num. * @return Number of CAN messages received */ From f2caa8b7aabb1d4a02f640f8bf12aa311f94a2c9 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Sat, 3 Oct 2026 13:08:51 +0200 Subject: [PATCH 15/16] Rename AVTP_VERSION to AVTPDU_VERSION Signed-off-by: Sebastian Schildt --- docs/api-design.md | 4 ++-- examples/acf-can/acf-can-common.c | 8 ++++---- include/avtp/AlternativeHeader.h | 4 ++-- include/avtp/CommonHeader.h | 14 +++++++------- include/avtp/CommonStreamHeader.h | 6 +++--- include/avtp/Crf.h | 20 ++++++++++---------- include/avtp/Rvf.h | 16 ++++++++-------- include/avtp/aaf/Aaf.h | 16 ++++++++-------- include/avtp/aaf/Pcm.h | 14 +++++++------- include/avtp/acf/Ntscf.h | 20 ++++++++++---------- include/avtp/acf/Tscf.h | 20 ++++++++++---------- include/avtp/cvf/Cvf.h | 16 ++++++++-------- unit/test-aaf.c | 10 +++++----- unit/test-alternativeheader.c | 8 ++++---- unit/test-commonheader.c | 23 ++++++++++++----------- unit/test-commonstreamheader.c | 26 +++++++++++++------------- unit/test-crf.c | 10 +++++----- unit/test-cvf.c | 10 +++++----- unit/test-ntscf.c | 10 +++++----- unit/test-pcm.c | 14 +++++++------- unit/test-rvf.c | 10 +++++----- unit/test-tscf.c | 12 ++++++------ 22 files changed, 146 insertions(+), 145 deletions(-) diff --git a/docs/api-design.md b/docs/api-design.md index 8dcd0733..745c74b8 100644 --- a/docs/api-design.md +++ b/docs/api-design.md @@ -602,10 +602,10 @@ functions**. They are accessed through `Avtp_CommonHeader_Get/SetSubtype` and - `IsValid` checks it with `Avtp_CommonHeader_GetSubtype((const Avtp_CommonHeader_t *)pdu)`. -Version numbers are available as `AVTP_VERSION_0` / `AVTP_VERSION_1`. Each +AVTPDU version numbers are available as `AVTPDU_VERSION_0` / `AVTPDU_VERSION_1`. Each format declares the versions it accepts (for example `AVTP_TSCF_SUPPORTED_VERSIONS`) and `IsValid` checks them with -`Avtp_Version_IsSupported(mask, version)`, rejecting reserved version values. +`Avtp_AvtpduVersion_IsSupported(mask, version)`, rejecting reserved version values. The common header fields are not repeated in format field enums: `subtype`, `h` and `version` are owned by `Avtp_CommonHeaderFieldDesc`. Formats that have been diff --git a/examples/acf-can/acf-can-common.c b/examples/acf-can/acf-can-common.c index 9cbf92d6..392c881c 100644 --- a/examples/acf-can/acf-can-common.c +++ b/examples/acf-can/acf-can-common.c @@ -312,11 +312,11 @@ int avtp_to_can(uint8_t *pdu, size_t pdu_length, frame_t *can_frames, bool can_f } uint8_t version = Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)cf_pdu); - if (!Avtp_Version_IsSupported(AVTP_TSCF_SUPPORTED_VERSIONS, version)) { + if (!Avtp_AvtpduVersion_IsSupported(AVTP_TSCF_SUPPORTED_VERSIONS, version)) { LOG_ERR("Unsupported TSCF version %u, ignoring frame.\n", version); return -1; } - if (version == AVTP_VERSION_1) { + if (version == AVTPDU_VERSION_1) { const Avtp_TscfV1_t *tscf = (const Avtp_TscfV1_t *)cf_pdu; size_t headerLen = Avtp_Tscf_GetHeaderLen_V1(tscf); proc_bytes += (uint16_t)headerLen; @@ -339,11 +339,11 @@ int avtp_to_can(uint8_t *pdu, size_t pdu_length, frame_t *can_frames, bool can_f } uint8_t version = Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)cf_pdu); - if (!Avtp_Version_IsSupported(AVTP_NTSCF_SUPPORTED_VERSIONS, version)) { + if (!Avtp_AvtpduVersion_IsSupported(AVTP_NTSCF_SUPPORTED_VERSIONS, version)) { LOG_ERR("Unsupported NTSCF version %u, ignoring frame.\n", version); return -1; } - if (version == AVTP_VERSION_1) { + if (version == AVTPDU_VERSION_1) { const Avtp_NtscfV1_t *ntscf = (const Avtp_NtscfV1_t *)cf_pdu; size_t headerLen = Avtp_Ntscf_GetHeaderLen_V1(ntscf); proc_bytes += (uint16_t)headerLen; diff --git a/include/avtp/AlternativeHeader.h b/include/avtp/AlternativeHeader.h index 60f34427..738a2e70 100644 --- a/include/avtp/AlternativeHeader.h +++ b/include/avtp/AlternativeHeader.h @@ -158,7 +158,7 @@ OPEN1722_INLINE uint64_t Avtp_AlternativeHeader_GetField_V1( OPEN1722_INLINE uint64_t Avtp_AlternativeHeader_GetField(const Avtp_AlternativeHeader_t *const pdu, Avtp_AlternativeHeaderField_t field) { - return Avtp_AlternativeHeader_GetVersion(pdu) == AVTP_VERSION_1 + return Avtp_AlternativeHeader_GetVersion(pdu) == AVTPDU_VERSION_1 ? Avtp_AlternativeHeader_GetField_V1(pdu, field) : Avtp_AlternativeHeader_GetField_V0(pdu, field); } @@ -210,7 +210,7 @@ OPEN1722_INLINE void Avtp_AlternativeHeader_SetField(Avtp_AlternativeHeader_t *p Avtp_AlternativeHeaderField_t field, uint64_t value) { - if (Avtp_AlternativeHeader_GetVersion(pdu) == AVTP_VERSION_1) { + if (Avtp_AlternativeHeader_GetVersion(pdu) == AVTPDU_VERSION_1) { Avtp_AlternativeHeader_SetField_V1(pdu, field, value); } else { Avtp_AlternativeHeader_SetField_V0(pdu, field, value); diff --git a/include/avtp/CommonHeader.h b/include/avtp/CommonHeader.h index b8998f49..11de48bb 100644 --- a/include/avtp/CommonHeader.h +++ b/include/avtp/CommonHeader.h @@ -53,9 +53,9 @@ extern "C" { #define AVTPDU_COMMON_LEN (1 * AVTP_QUADLET_SIZE) -/* Version field values (IEEE 1722-2025, 4.7.3.4). */ -#define AVTP_VERSION_0 0 -#define AVTP_VERSION_1 1 +/* AVTPDU common header version field values (IEEE 1722-2025, 4.7.3.4). */ +#define AVTPDU_VERSION_0 0 +#define AVTPDU_VERSION_1 1 typedef struct { uint8_t header[AVTPDU_COMMON_LEN]; @@ -118,13 +118,13 @@ static const Avtp_FieldDescriptor_t Avtp_CommonHeaderFieldDesc[AVTPDU_COMMON_FIE }; /** - * Returns true if the given AVTP version is present in the supported-version mask. + * Returns true if the given AVTPDU version is present in the supported-version mask. * - * @param versionMask Bit mask in which bit N marks version N as supported. - * @param version Version number to test (0 to 7). + * @param versionMask Bit mask in which bit N marks AVTPDU version N as supported. + * @param version AVTPDU version number to test (0 to 7). * @returns true if the version is supported, false otherwise. */ -OPEN1722_INLINE bool Avtp_Version_IsSupported(uint8_t versionMask, uint8_t version) +OPEN1722_INLINE bool Avtp_AvtpduVersion_IsSupported(uint8_t versionMask, uint8_t version) { if (version >= 8U) { return false; diff --git a/include/avtp/CommonStreamHeader.h b/include/avtp/CommonStreamHeader.h index f53e8c36..c4feb00c 100644 --- a/include/avtp/CommonStreamHeader.h +++ b/include/avtp/CommonStreamHeader.h @@ -171,7 +171,7 @@ Avtp_CommonStreamHeader_GetHeaderLen_V1(const Avtp_CommonStreamHeader_t *const p OPEN1722_INLINE uint8_t Avtp_CommonStreamHeader_GetHeaderLen(const Avtp_CommonStreamHeader_t *const pdu) { - return Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1 + return Avtp_CommonStreamHeader_GetVersion(pdu) == AVTPDU_VERSION_1 ? Avtp_CommonStreamHeader_GetHeaderLen_V1(pdu) : Avtp_CommonStreamHeader_GetHeaderLen_V0(pdu); } @@ -219,7 +219,7 @@ OPEN1722_INLINE uint64_t Avtp_CommonStreamHeader_GetField_V1( OPEN1722_INLINE uint64_t Avtp_CommonStreamHeader_GetField( const Avtp_CommonStreamHeader_t *const pdu, Avtp_CommonStreamHeaderField_t field) { - return Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1 + return Avtp_CommonStreamHeader_GetVersion(pdu) == AVTPDU_VERSION_1 ? Avtp_CommonStreamHeader_GetField_V1(pdu, field) : Avtp_CommonStreamHeader_GetField_V0(pdu, field); } @@ -271,7 +271,7 @@ OPEN1722_INLINE void Avtp_CommonStreamHeader_SetField(Avtp_CommonStreamHeader_t Avtp_CommonStreamHeaderField_t field, uint64_t value) { - if (Avtp_CommonStreamHeader_GetVersion(pdu) == AVTP_VERSION_1) { + if (Avtp_CommonStreamHeader_GetVersion(pdu) == AVTPDU_VERSION_1) { Avtp_CommonStreamHeader_SetField_V1(pdu, field, value); } else { Avtp_CommonStreamHeader_SetField_V0(pdu, field, value); diff --git a/include/avtp/Crf.h b/include/avtp/Crf.h index ba984ea0..bb6762bd 100644 --- a/include/avtp/Crf.h +++ b/include/avtp/Crf.h @@ -65,7 +65,7 @@ extern "C" { #define AVTP_CRF_HEADER_LEN AVTP_CRF_HEADER_LEN_V0 /* CRF supports both versions of the alternative header (Table 7). */ -#define AVTP_CRF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) +#define AVTP_CRF_SUPPORTED_VERSIONS ((1u << AVTPDU_VERSION_0) | (1u << AVTPDU_VERSION_1)) typedef struct { uint8_t header[AVTP_CRF_HEADER_LEN_V0]; @@ -217,7 +217,7 @@ OPEN1722_INLINE uint64_t Avtp_Crf_GetField_V1(const Avtp_CrfV1_t *const pdu, Avt OPEN1722_INLINE uint64_t Avtp_Crf_GetField(const Avtp_Crf_t *const pdu, Avtp_CrfFields_t field) { return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Crf_GetField_V1((const Avtp_CrfV1_t *)pdu, field) : Avtp_Crf_GetField_V0(pdu, field); } @@ -261,7 +261,7 @@ OPEN1722_INLINE void Avtp_Crf_SetField_V1(Avtp_CrfV1_t *pdu, Avtp_CrfFields_t fi OPEN1722_INLINE void Avtp_Crf_SetField(Avtp_Crf_t *pdu, Avtp_CrfFields_t field, uint64_t value) { if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Crf_SetField_V1((Avtp_CrfV1_t *)pdu, field, value); } else { Avtp_Crf_SetField_V0(pdu, field, value); @@ -297,7 +297,7 @@ OPEN1722_INLINE uint8_t Avtp_Crf_GetHeaderLen_V1(const Avtp_CrfV1_t *const pdu) OPEN1722_INLINE uint8_t Avtp_Crf_GetHeaderLen(const Avtp_Crf_t *const pdu) { return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Crf_GetHeaderLen_V1((const Avtp_CrfV1_t *)pdu) : Avtp_Crf_GetHeaderLen_V0(pdu); } @@ -357,7 +357,7 @@ OPEN1722_INLINE bool Avtp_Crf_IsTu(const Avtp_Crf_t *const pdu) OPEN1722_INLINE uint32_t Avtp_Crf_GetSequenceNum(const Avtp_Crf_t *const pdu) { return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? (uint32_t)Avtp_Crf_GetField_V1((const Avtp_CrfV1_t *)pdu, AVTP_CRF_FIELD_SEQUENCE_NUM) : (uint8_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB); @@ -510,7 +510,7 @@ OPEN1722_INLINE void Avtp_Crf_SetTu(Avtp_Crf_t *pdu, bool tu) OPEN1722_INLINE void Avtp_Crf_SetSequenceNum(Avtp_Crf_t *pdu, uint32_t value) { if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Crf_SetField_V1((Avtp_CrfV1_t *)pdu, AVTP_CRF_FIELD_SEQUENCE_NUM, value); Avtp_Crf_SetField_V1((Avtp_CrfV1_t *)pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); @@ -634,7 +634,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Crf_GetPayload_V1(const Avtp_CrfV1_t *const OPEN1722_INLINE const uint8_t *Avtp_Crf_GetPayload(const Avtp_Crf_t *const pdu) { return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Crf_GetPayload_V1((const Avtp_CrfV1_t *)pdu) : Avtp_Crf_GetPayload_V0(pdu); } @@ -677,7 +677,7 @@ OPEN1722_INLINE void Avtp_Crf_SetPayload_V1(Avtp_CrfV1_t *pdu, uint8_t *payload, OPEN1722_INLINE void Avtp_Crf_SetPayload(Avtp_Crf_t *pdu, uint8_t *payload, uint16_t payload_length) { if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Crf_SetPayload_V1((Avtp_CrfV1_t *)pdu, payload, payload_length); } else { Avtp_Crf_SetPayload_V0(pdu, payload, payload_length); @@ -709,7 +709,7 @@ OPEN1722_INLINE void Avtp_Crf_InitV1(Avtp_CrfV1_t *pdu) if (pdu != NULL) { memset(pdu, 0, sizeof(Avtp_CrfV1_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_CRF); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTPDU_VERSION_1); Avtp_Crf_SetSv((Avtp_Crf_t *)pdu, true); } } @@ -741,7 +741,7 @@ OPEN1722_INLINE bool Avtp_Crf_IsValid(const Avtp_Crf_t *const pdu, size_t buffer } uint8_t version = Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu); - if (!Avtp_Version_IsSupported(AVTP_CRF_SUPPORTED_VERSIONS, version)) { + if (!Avtp_AvtpduVersion_IsSupported(AVTP_CRF_SUPPORTED_VERSIONS, version)) { return false; } diff --git a/include/avtp/Rvf.h b/include/avtp/Rvf.h index 7c7770c5..9d324219 100644 --- a/include/avtp/Rvf.h +++ b/include/avtp/Rvf.h @@ -67,7 +67,7 @@ extern "C" { #define AVTP_RVF_RAW_HEADER_LEN (2 * AVTP_QUADLET_SIZE) /* RVF supports both versions of the common stream header (Table 7). */ -#define AVTP_RVF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) +#define AVTP_RVF_SUPPORTED_VERSIONS ((1u << AVTPDU_VERSION_0) | (1u << AVTPDU_VERSION_1)) typedef struct { uint8_t header[AVTP_RVF_HEADER_LEN_V0]; @@ -273,7 +273,7 @@ OPEN1722_INLINE uint64_t Avtp_Rvf_GetField_V1(const Avtp_RvfV1_t *const pdu, Avt OPEN1722_INLINE uint64_t Avtp_Rvf_GetField(const Avtp_Rvf_t *const pdu, Avtp_RvfFields_t field) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Rvf_GetField_V1((const Avtp_RvfV1_t *)pdu, field) : Avtp_Rvf_GetField_V0(pdu, field); } @@ -317,7 +317,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetField_V1(Avtp_RvfV1_t *pdu, Avtp_RvfFields_t fi OPEN1722_INLINE void Avtp_Rvf_SetField(Avtp_Rvf_t *pdu, Avtp_RvfFields_t field, uint64_t value) { if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Rvf_SetField_V1((Avtp_RvfV1_t *)pdu, field, value); } else { Avtp_Rvf_SetField_V0(pdu, field, value); @@ -353,7 +353,7 @@ OPEN1722_INLINE uint8_t Avtp_Rvf_GetHeaderLen_V1(const Avtp_RvfV1_t *const pdu) OPEN1722_INLINE uint8_t Avtp_Rvf_GetHeaderLen(const Avtp_Rvf_t *const pdu) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Rvf_GetHeaderLen_V1((const Avtp_RvfV1_t *)pdu) : Avtp_Rvf_GetHeaderLen_V0(pdu); } @@ -783,7 +783,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Rvf_GetPayload_V1(const Avtp_RvfV1_t *const OPEN1722_INLINE const uint8_t *Avtp_Rvf_GetPayload(const Avtp_Rvf_t *const pdu) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Rvf_GetPayload_V1((const Avtp_RvfV1_t *)pdu) : Avtp_Rvf_GetPayload_V0(pdu); } @@ -826,7 +826,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetPayload_V1(Avtp_RvfV1_t *pdu, uint8_t *payload, OPEN1722_INLINE void Avtp_Rvf_SetPayload(Avtp_Rvf_t *pdu, uint8_t *payload, uint16_t payload_length) { if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Rvf_SetPayload_V1((Avtp_RvfV1_t *)pdu, payload, payload_length); } else { Avtp_Rvf_SetPayload_V0(pdu, payload, payload_length); @@ -858,7 +858,7 @@ OPEN1722_INLINE void Avtp_Rvf_InitV1(Avtp_RvfV1_t *pdu) if (pdu != NULL) { memset(pdu, 0, sizeof(Avtp_RvfV1_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_RVF); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTPDU_VERSION_1); Avtp_Rvf_SetSv((Avtp_Rvf_t *)pdu, true); } } @@ -890,7 +890,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsValid(const Avtp_Rvf_t *const pdu, size_t buffer } uint8_t version = Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu); - if (!Avtp_Version_IsSupported(AVTP_RVF_SUPPORTED_VERSIONS, version)) { + if (!Avtp_AvtpduVersion_IsSupported(AVTP_RVF_SUPPORTED_VERSIONS, version)) { return false; } diff --git a/include/avtp/aaf/Aaf.h b/include/avtp/aaf/Aaf.h index f11fe19b..3b4bafdb 100644 --- a/include/avtp/aaf/Aaf.h +++ b/include/avtp/aaf/Aaf.h @@ -64,7 +64,7 @@ extern "C" { #define AVTP_AAF_HEADER_LEN AVTP_AAF_HEADER_LEN_V0 /* AAF supports both versions of the common stream header (Table 7). */ -#define AVTP_AAF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) +#define AVTP_AAF_SUPPORTED_VERSIONS ((1u << AVTPDU_VERSION_0) | (1u << AVTPDU_VERSION_1)) typedef struct { uint8_t header[AVTP_AAF_HEADER_LEN_V0]; @@ -218,7 +218,7 @@ OPEN1722_INLINE uint64_t Avtp_Aaf_GetField_V1(const Avtp_AafV1_t *const pdu, Avt OPEN1722_INLINE uint64_t Avtp_Aaf_GetField(const Avtp_Aaf_t *const pdu, Avtp_AafFields_t field) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Aaf_GetField_V1((const Avtp_AafV1_t *)pdu, field) : Avtp_Aaf_GetField_V0(pdu, field); } @@ -262,7 +262,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetField_V1(Avtp_AafV1_t *pdu, Avtp_AafFields_t fi OPEN1722_INLINE void Avtp_Aaf_SetField(Avtp_Aaf_t *pdu, Avtp_AafFields_t field, uint64_t value) { if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Aaf_SetField_V1((Avtp_AafV1_t *)pdu, field, value); } else { Avtp_Aaf_SetField_V0(pdu, field, value); @@ -298,7 +298,7 @@ OPEN1722_INLINE uint8_t Avtp_Aaf_GetHeaderLen_V1(const Avtp_AafV1_t *const pdu) OPEN1722_INLINE uint8_t Avtp_Aaf_GetHeaderLen(const Avtp_Aaf_t *const pdu) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Aaf_GetHeaderLen_V1((const Avtp_AafV1_t *)pdu) : Avtp_Aaf_GetHeaderLen_V0(pdu); } @@ -681,7 +681,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Aaf_GetPayload_V1(const Avtp_AafV1_t *const OPEN1722_INLINE const uint8_t *Avtp_Aaf_GetPayload(const Avtp_Aaf_t *const pdu) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Aaf_GetPayload_V1((const Avtp_AafV1_t *)pdu) : Avtp_Aaf_GetPayload_V0(pdu); } @@ -724,7 +724,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetPayload_V1(Avtp_AafV1_t *pdu, uint8_t *payload, OPEN1722_INLINE void Avtp_Aaf_SetPayload(Avtp_Aaf_t *pdu, uint8_t *payload, uint16_t payload_length) { if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Aaf_SetPayload_V1((Avtp_AafV1_t *)pdu, payload, payload_length); } else { Avtp_Aaf_SetPayload_V0(pdu, payload, payload_length); @@ -756,7 +756,7 @@ OPEN1722_INLINE void Avtp_Aaf_InitV1(Avtp_AafV1_t *pdu) if (pdu != NULL) { memset(pdu, 0, sizeof(Avtp_AafV1_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_AAF); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTPDU_VERSION_1); Avtp_Aaf_SetSv((Avtp_Aaf_t *)pdu, true); } } @@ -786,7 +786,7 @@ OPEN1722_INLINE bool Avtp_Aaf_IsValid(const Avtp_Aaf_t *const pdu, size_t buffer } uint8_t version = Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu); - if (!Avtp_Version_IsSupported(AVTP_AAF_SUPPORTED_VERSIONS, version)) { + if (!Avtp_AvtpduVersion_IsSupported(AVTP_AAF_SUPPORTED_VERSIONS, version)) { return false; } diff --git a/include/avtp/aaf/Pcm.h b/include/avtp/aaf/Pcm.h index 1a2d25a7..9d6dffed 100644 --- a/include/avtp/aaf/Pcm.h +++ b/include/avtp/aaf/Pcm.h @@ -66,7 +66,7 @@ extern "C" { #define AVTP_PCM_HEADER_LEN AVTP_PCM_HEADER_LEN_V0 /* PCM (AAF) supports both versions of the common stream header (Table 7). */ -#define AVTP_PCM_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) +#define AVTP_PCM_SUPPORTED_VERSIONS ((1u << AVTPDU_VERSION_0) | (1u << AVTPDU_VERSION_1)) typedef struct { uint8_t header[AVTP_PCM_HEADER_LEN_V0]; @@ -226,7 +226,7 @@ OPEN1722_INLINE uint64_t Avtp_Pcm_GetField_V1(const Avtp_PcmV1_t *const pdu, Avt OPEN1722_INLINE uint64_t Avtp_Pcm_GetField(const Avtp_Pcm_t *const pdu, Avtp_PcmFields_t field) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Pcm_GetField_V1((const Avtp_PcmV1_t *)pdu, field) : Avtp_Pcm_GetField_V0(pdu, field); } @@ -270,7 +270,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetField_V1(Avtp_PcmV1_t *pdu, Avtp_PcmFields_t fi OPEN1722_INLINE void Avtp_Pcm_SetField(Avtp_Pcm_t *pdu, Avtp_PcmFields_t field, uint64_t value) { if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Pcm_SetField_V1((Avtp_PcmV1_t *)pdu, field, value); } else { Avtp_Pcm_SetField_V0(pdu, field, value); @@ -306,7 +306,7 @@ OPEN1722_INLINE uint8_t Avtp_Pcm_GetHeaderLen_V1(const Avtp_PcmV1_t *const pdu) OPEN1722_INLINE uint8_t Avtp_Pcm_GetHeaderLen(const Avtp_Pcm_t *const pdu) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Pcm_GetHeaderLen_V1((const Avtp_PcmV1_t *)pdu) : Avtp_Pcm_GetHeaderLen_V0(pdu); } @@ -687,7 +687,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Pcm_GetPayload_V1(const Avtp_PcmV1_t *const OPEN1722_INLINE const uint8_t *Avtp_Pcm_GetPayload(const Avtp_Pcm_t *const pdu) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Pcm_GetPayload_V1((const Avtp_PcmV1_t *)pdu) : Avtp_Pcm_GetPayload_V0(pdu); } @@ -730,7 +730,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetPayload_V1(Avtp_PcmV1_t *pdu, uint8_t *payload, OPEN1722_INLINE void Avtp_Pcm_SetPayload(Avtp_Pcm_t *pdu, uint8_t *payload, uint16_t payload_length) { if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Pcm_SetPayload_V1((Avtp_PcmV1_t *)pdu, payload, payload_length); } else { Avtp_Pcm_SetPayload_V0(pdu, payload, payload_length); @@ -762,7 +762,7 @@ OPEN1722_INLINE void Avtp_Pcm_InitV1(Avtp_PcmV1_t *pdu) if (pdu != NULL) { memset(pdu, 0, sizeof(Avtp_PcmV1_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_AAF); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTPDU_VERSION_1); Avtp_Pcm_SetSv((Avtp_Pcm_t *)pdu, true); } } diff --git a/include/avtp/acf/Ntscf.h b/include/avtp/acf/Ntscf.h index c9f17153..5739dcd2 100644 --- a/include/avtp/acf/Ntscf.h +++ b/include/avtp/acf/Ntscf.h @@ -65,7 +65,7 @@ extern "C" { #define AVTP_NTSCF_HEADER_LEN AVTP_NTSCF_HEADER_LEN_V0 /* NTSCF supports both versions of the alternative header (Table 7). */ -#define AVTP_NTSCF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) +#define AVTP_NTSCF_SUPPORTED_VERSIONS ((1u << AVTPDU_VERSION_0) | (1u << AVTPDU_VERSION_1)) typedef struct { uint8_t header[AVTP_NTSCF_HEADER_LEN_V0]; @@ -174,7 +174,7 @@ OPEN1722_INLINE uint64_t Avtp_Ntscf_GetField(const Avtp_Ntscf_t *const pdu, Avtp_NtscfFields_t field) { return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Ntscf_GetField_V1((const Avtp_NtscfV1_t *)pdu, field) : Avtp_Ntscf_GetField_V0(pdu, field); } @@ -223,7 +223,7 @@ OPEN1722_INLINE void Avtp_Ntscf_SetField(Avtp_Ntscf_t *pdu, Avtp_NtscfFields_t f uint64_t value) { if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Ntscf_SetField_V1((Avtp_NtscfV1_t *)pdu, field, value); } else { Avtp_Ntscf_SetField_V0(pdu, field, value); @@ -259,7 +259,7 @@ OPEN1722_INLINE uint8_t Avtp_Ntscf_GetHeaderLen_V1(const Avtp_NtscfV1_t *const p OPEN1722_INLINE uint8_t Avtp_Ntscf_GetHeaderLen(const Avtp_Ntscf_t *const pdu) { return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Ntscf_GetHeaderLen_V1((const Avtp_NtscfV1_t *)pdu) : Avtp_Ntscf_GetHeaderLen_V0(pdu); } @@ -298,7 +298,7 @@ OPEN1722_INLINE uint16_t Avtp_Ntscf_GetNtscfDataLength(const Avtp_Ntscf_t *const OPEN1722_INLINE uint32_t Avtp_Ntscf_GetSequenceNum(const Avtp_Ntscf_t *const pdu) { return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? (uint32_t)Avtp_Ntscf_GetField_V1((const Avtp_NtscfV1_t *)pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM) : (uint8_t)Avtp_Ntscf_GetField_V0(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB); @@ -375,7 +375,7 @@ OPEN1722_INLINE void Avtp_Ntscf_SetNtscfDataLength(Avtp_Ntscf_t *pdu, uint16_t v OPEN1722_INLINE void Avtp_Ntscf_SetSequenceNum(Avtp_Ntscf_t *pdu, uint32_t value) { if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Ntscf_SetField_V1((Avtp_NtscfV1_t *)pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM, value); Avtp_Ntscf_SetField_V1((Avtp_NtscfV1_t *)pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); @@ -441,7 +441,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Ntscf_GetPayload_V1(const Avtp_NtscfV1_t *co OPEN1722_INLINE const uint8_t *Avtp_Ntscf_GetPayload(const Avtp_Ntscf_t *const pdu) { return Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Ntscf_GetPayload_V1((const Avtp_NtscfV1_t *)pdu) : Avtp_Ntscf_GetPayload_V0(pdu); } @@ -485,7 +485,7 @@ OPEN1722_INLINE void Avtp_Ntscf_SetPayload(Avtp_Ntscf_t *pdu, uint8_t *payload, uint16_t payload_length) { if (Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Ntscf_SetPayload_V1((Avtp_NtscfV1_t *)pdu, payload, payload_length); } else { Avtp_Ntscf_SetPayload_V0(pdu, payload, payload_length); @@ -513,7 +513,7 @@ OPEN1722_INLINE bool Avtp_Ntscf_IsValid(const Avtp_Ntscf_t *const pdu, size_t bu } uint8_t version = Avtp_AlternativeHeader_GetVersion((const Avtp_AlternativeHeader_t *)pdu); - if (!Avtp_Version_IsSupported(AVTP_NTSCF_SUPPORTED_VERSIONS, version)) { + if (!Avtp_AvtpduVersion_IsSupported(AVTP_NTSCF_SUPPORTED_VERSIONS, version)) { return false; } @@ -557,7 +557,7 @@ OPEN1722_INLINE void Avtp_Ntscf_InitV1(Avtp_NtscfV1_t *pdu) if (pdu != NULL) { memset(pdu, 0, sizeof(Avtp_NtscfV1_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_NTSCF); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTPDU_VERSION_1); Avtp_Ntscf_SetSv((Avtp_Ntscf_t *)pdu, true); } } diff --git a/include/avtp/acf/Tscf.h b/include/avtp/acf/Tscf.h index 8c686944..5a6e415d 100644 --- a/include/avtp/acf/Tscf.h +++ b/include/avtp/acf/Tscf.h @@ -65,7 +65,7 @@ extern "C" { #define AVTP_TSCF_HEADER_LEN AVTP_TSCF_HEADER_LEN_V0 /* TSCF supports both versions of the common stream header (Table 7). */ -#define AVTP_TSCF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) +#define AVTP_TSCF_SUPPORTED_VERSIONS ((1u << AVTPDU_VERSION_0) | (1u << AVTPDU_VERSION_1)) typedef struct { uint8_t header[AVTP_TSCF_HEADER_LEN_V0]; @@ -188,7 +188,7 @@ OPEN1722_INLINE uint64_t Avtp_Tscf_GetField_V1(const Avtp_TscfV1_t *const pdu, OPEN1722_INLINE uint64_t Avtp_Tscf_GetField(const Avtp_Tscf_t *const pdu, Avtp_TscfFields_t field) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Tscf_GetField_V1((const Avtp_TscfV1_t *)pdu, field) : Avtp_Tscf_GetField_V0(pdu, field); } @@ -234,7 +234,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetField_V1(Avtp_TscfV1_t *pdu, Avtp_TscfFields_t OPEN1722_INLINE void Avtp_Tscf_SetField(Avtp_Tscf_t *pdu, Avtp_TscfFields_t field, uint64_t value) { if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Tscf_SetField_V1((Avtp_TscfV1_t *)pdu, field, value); } else { Avtp_Tscf_SetField_V0(pdu, field, value); @@ -270,7 +270,7 @@ OPEN1722_INLINE uint8_t Avtp_Tscf_GetHeaderLen_V1(const Avtp_TscfV1_t *const pdu OPEN1722_INLINE uint8_t Avtp_Tscf_GetHeaderLen(const Avtp_Tscf_t *const pdu) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Tscf_GetHeaderLen_V1((const Avtp_TscfV1_t *)pdu) : Avtp_Tscf_GetHeaderLen_V0(pdu); } @@ -343,7 +343,7 @@ OPEN1722_INLINE uint32_t Avtp_Tscf_GetSequenceNum(const Avtp_Tscf_t *const pdu) OPEN1722_INLINE uint8_t Avtp_Tscf_GetSequenceNumLsb(const Avtp_Tscf_t *const pdu) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? (uint8_t)Avtp_Tscf_GetField_V1((const Avtp_TscfV1_t *)pdu, AVTP_TSCF_FIELD_FSD0) : (uint8_t)Avtp_Tscf_GetField_V0(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM); } @@ -450,7 +450,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetTu(Avtp_Tscf_t *pdu, bool tu) OPEN1722_INLINE void Avtp_Tscf_SetSequenceNum(Avtp_Tscf_t *pdu, uint32_t value) { if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Tscf_SetField_V1((Avtp_TscfV1_t *)pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM, value); Avtp_Tscf_SetField_V1((Avtp_TscfV1_t *)pdu, AVTP_TSCF_FIELD_FSD0, (uint8_t)(value & 0xFFU)); } else { @@ -538,7 +538,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Tscf_GetPayload_V1(const Avtp_TscfV1_t *cons OPEN1722_INLINE const uint8_t *Avtp_Tscf_GetPayload(const Avtp_Tscf_t *const pdu) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Tscf_GetPayload_V1((const Avtp_TscfV1_t *)pdu) : Avtp_Tscf_GetPayload_V0(pdu); } @@ -582,7 +582,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetPayload(Avtp_Tscf_t *pdu, uint8_t *payload, uint16_t payload_length) { if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Tscf_SetPayload_V1((Avtp_TscfV1_t *)pdu, payload, payload_length); } else { Avtp_Tscf_SetPayload_V0(pdu, payload, payload_length); @@ -610,7 +610,7 @@ OPEN1722_INLINE bool Avtp_Tscf_IsValid(const Avtp_Tscf_t *const pdu, size_t buff } uint8_t version = Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu); - if (!Avtp_Version_IsSupported(AVTP_TSCF_SUPPORTED_VERSIONS, version)) { + if (!Avtp_AvtpduVersion_IsSupported(AVTP_TSCF_SUPPORTED_VERSIONS, version)) { return false; } @@ -654,7 +654,7 @@ OPEN1722_INLINE void Avtp_Tscf_InitV1(Avtp_TscfV1_t *pdu) if (pdu != NULL) { memset(pdu, 0, sizeof(Avtp_TscfV1_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_TSCF); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTPDU_VERSION_1); Avtp_Tscf_SetSv((Avtp_Tscf_t *)pdu, true); } } diff --git a/include/avtp/cvf/Cvf.h b/include/avtp/cvf/Cvf.h index ddea512b..8fe439b8 100644 --- a/include/avtp/cvf/Cvf.h +++ b/include/avtp/cvf/Cvf.h @@ -64,7 +64,7 @@ extern "C" { #define AVTP_CVF_HEADER_LEN AVTP_CVF_HEADER_LEN_V0 /* CVF supports both versions of the common stream header (Table 7). */ -#define AVTP_CVF_SUPPORTED_VERSIONS ((1u << AVTP_VERSION_0) | (1u << AVTP_VERSION_1)) +#define AVTP_CVF_SUPPORTED_VERSIONS ((1u << AVTPDU_VERSION_0) | (1u << AVTPDU_VERSION_1)) typedef struct { uint8_t header[AVTP_CVF_HEADER_LEN_V0]; @@ -222,7 +222,7 @@ OPEN1722_INLINE uint64_t Avtp_Cvf_GetField_V1(const Avtp_CvfV1_t *const pdu, Avt OPEN1722_INLINE uint64_t Avtp_Cvf_GetField(const Avtp_Cvf_t *const pdu, Avtp_CvfFields_t field) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Cvf_GetField_V1((const Avtp_CvfV1_t *)pdu, field) : Avtp_Cvf_GetField_V0(pdu, field); } @@ -266,7 +266,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetField_V1(Avtp_CvfV1_t *pdu, Avtp_CvfFields_t fi OPEN1722_INLINE void Avtp_Cvf_SetField(Avtp_Cvf_t *pdu, Avtp_CvfFields_t field, uint64_t value) { if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Cvf_SetField_V1((Avtp_CvfV1_t *)pdu, field, value); } else { Avtp_Cvf_SetField_V0(pdu, field, value); @@ -302,7 +302,7 @@ OPEN1722_INLINE uint8_t Avtp_Cvf_GetHeaderLen_V1(const Avtp_CvfV1_t *const pdu) OPEN1722_INLINE uint8_t Avtp_Cvf_GetHeaderLen(const Avtp_Cvf_t *const pdu) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Cvf_GetHeaderLen_V1((const Avtp_CvfV1_t *)pdu) : Avtp_Cvf_GetHeaderLen_V0(pdu); } @@ -665,7 +665,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Cvf_GetPayload_V1(const Avtp_CvfV1_t *const OPEN1722_INLINE const uint8_t *Avtp_Cvf_GetPayload(const Avtp_Cvf_t *const pdu) { return Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1 + AVTPDU_VERSION_1 ? Avtp_Cvf_GetPayload_V1((const Avtp_CvfV1_t *)pdu) : Avtp_Cvf_GetPayload_V0(pdu); } @@ -708,7 +708,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetPayload_V1(Avtp_CvfV1_t *pdu, uint8_t *payload, OPEN1722_INLINE void Avtp_Cvf_SetPayload(Avtp_Cvf_t *pdu, uint8_t *payload, uint16_t payload_length) { if (Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu) == - AVTP_VERSION_1) { + AVTPDU_VERSION_1) { Avtp_Cvf_SetPayload_V1((Avtp_CvfV1_t *)pdu, payload, payload_length); } else { Avtp_Cvf_SetPayload_V0(pdu, payload, payload_length); @@ -741,7 +741,7 @@ OPEN1722_INLINE void Avtp_Cvf_InitV1(Avtp_CvfV1_t *pdu) if (pdu != NULL) { memset(pdu, 0, sizeof(Avtp_CvfV1_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_CVF); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, AVTPDU_VERSION_1); Avtp_Cvf_SetFormat((Avtp_Cvf_t *)pdu, AVTP_CVF_FORMAT_RFC); Avtp_Cvf_SetSv((Avtp_Cvf_t *)pdu, true); } @@ -772,7 +772,7 @@ OPEN1722_INLINE bool Avtp_Cvf_IsValid(const Avtp_Cvf_t *const pdu, size_t buffer } uint8_t version = Avtp_CommonStreamHeader_GetVersion((const Avtp_CommonStreamHeader_t *)pdu); - if (!Avtp_Version_IsSupported(AVTP_CVF_SUPPORTED_VERSIONS, version)) { + if (!Avtp_AvtpduVersion_IsSupported(AVTP_CVF_SUPPORTED_VERSIONS, version)) { return false; } diff --git a/unit/test-aaf.c b/unit/test-aaf.c index bac4d27d..123ad439 100644 --- a/unit/test-aaf.c +++ b/unit/test-aaf.c @@ -168,9 +168,9 @@ static void aaf_field_descriptors_cover_header(void **state) uint8_t coverage[AVTP_AAF_HEADER_LEN_V1 * 8] = {0}; size_t coverageBits = sizeof(coverage); const Avtp_FieldDescriptor_t *aafDesc = - version == AVTP_VERSION_1 ? Avtp_AafFieldDescV1 : Avtp_AafFieldDescV0; - size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_AAF_HEADER_LEN_V1 - : (size_t)AVTP_AAF_HEADER_LEN_V0) * + version == AVTPDU_VERSION_1 ? Avtp_AafFieldDescV1 : Avtp_AafFieldDescV0; + size_t headerBits = (version == AVTPDU_VERSION_1 ? (size_t)AVTP_AAF_HEADER_LEN_V1 + : (size_t)AVTP_AAF_HEADER_LEN_V0) * 8; /* subtype and version are owned by the common header; h/sv is covered @@ -197,9 +197,9 @@ static void aaf_common_field_consistency(void **state) for (uint8_t version = 0; version <= 1; version++) { const Avtp_FieldDescriptor_t *aafDesc = - version == AVTP_VERSION_1 ? Avtp_AafFieldDescV1 : Avtp_AafFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_AafFieldDescV1 : Avtp_AafFieldDescV0; const Avtp_FieldDescriptor_t *cshDesc = - version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; for (uint8_t i = 0; i < AVTPDU_CSH_FIELD_MAX; i++) { assert_int_equal(aafDesc[i].quadlet, cshDesc[i].quadlet); diff --git a/unit/test-alternativeheader.c b/unit/test-alternativeheader.c index e114bf1e..264d3be8 100644 --- a/unit/test-alternativeheader.c +++ b/unit/test-alternativeheader.c @@ -69,7 +69,7 @@ static void alternative_header_typed_fields_v0(void **state) Avtp_AlternativeHeader_t *ah = (Avtp_AlternativeHeader_t *)pdu; memset(pdu, 0, sizeof(pdu)); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ah, AVTP_VERSION_0); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ah, AVTPDU_VERSION_0); for (uint8_t f = 0; f < AVTPDU_AH_FIELD_MAX; f++) { uint8_t bits = Avtp_AhFieldDescV0[f].bits; @@ -91,7 +91,7 @@ static void alternative_header_typed_fields_v1(void **state) Avtp_AlternativeHeader_t *ah = (Avtp_AlternativeHeader_t *)pdu; memset(pdu, 0, sizeof(pdu)); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ah, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ah, AVTPDU_VERSION_1); for (uint8_t f = 0; f < AVTPDU_AH_FIELD_MAX; f++) { uint8_t bits = Avtp_AhFieldDescV1[f].bits; @@ -113,7 +113,7 @@ static void alternative_header_typed_named_v1(void **state) Avtp_AlternativeHeader_t *ah = (Avtp_AlternativeHeader_t *)pdu; memset(pdu, 0, sizeof(pdu)); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ah, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ah, AVTPDU_VERSION_1); Avtp_AlternativeHeader_SetSequenceNum_V1(ah, 0x12345678); Avtp_AlternativeHeader_SetPtpGrandmasterIdentity_V1(ah, 0x99AABBCCDDEEFF00ULL); @@ -137,7 +137,7 @@ static void alternative_header_typed_absent_fields(void **state) Avtp_AlternativeHeader_t *ah = (Avtp_AlternativeHeader_t *)pdu; memset(pdu, 0, sizeof(pdu)); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ah, AVTP_VERSION_0); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ah, AVTPDU_VERSION_0); /* sequence_num and ptp_grandmaster_identity do not exist in v0. */ assert_int_equal(Avtp_AlternativeHeader_GetSequenceNum_V0(ah), 0); diff --git a/unit/test-commonheader.c b/unit/test-commonheader.c index 5c363a43..182ca364 100644 --- a/unit/test-commonheader.c +++ b/unit/test-commonheader.c @@ -88,17 +88,18 @@ static void common_header_subtypes(void **state) static void common_header_version_support(void **state) { (void)state; - uint8_t both = (uint8_t)((1U << AVTP_VERSION_0) | (1U << AVTP_VERSION_1)); - - assert_int_equal(AVTP_VERSION_0, 0); - assert_int_equal(AVTP_VERSION_1, 1); - - assert_true(Avtp_Version_IsSupported(both, AVTP_VERSION_0)); - assert_true(Avtp_Version_IsSupported(both, AVTP_VERSION_1)); - assert_false(Avtp_Version_IsSupported(both, 2)); - assert_false(Avtp_Version_IsSupported((uint8_t)(1U << AVTP_VERSION_0), AVTP_VERSION_1)); - assert_false(Avtp_Version_IsSupported(0, AVTP_VERSION_0)); - assert_false(Avtp_Version_IsSupported(0xFF, 8)); + uint8_t both = (uint8_t)((1U << AVTPDU_VERSION_0) | (1U << AVTPDU_VERSION_1)); + + assert_int_equal(AVTPDU_VERSION_0, 0); + assert_int_equal(AVTPDU_VERSION_1, 1); + + assert_true(Avtp_AvtpduVersion_IsSupported(both, AVTPDU_VERSION_0)); + assert_true(Avtp_AvtpduVersion_IsSupported(both, AVTPDU_VERSION_1)); + assert_false(Avtp_AvtpduVersion_IsSupported(both, 2)); + assert_false( + Avtp_AvtpduVersion_IsSupported((uint8_t)(1U << AVTPDU_VERSION_0), AVTPDU_VERSION_1)); + assert_false(Avtp_AvtpduVersion_IsSupported(0, AVTPDU_VERSION_0)); + assert_false(Avtp_AvtpduVersion_IsSupported(0xFF, 8)); } int main(void) diff --git a/unit/test-commonstreamheader.c b/unit/test-commonstreamheader.c index b7c991c1..6b4386c1 100644 --- a/unit/test-commonstreamheader.c +++ b/unit/test-commonstreamheader.c @@ -77,9 +77,9 @@ static void common_stream_header_v0_layout(void **state) Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; memset(pdu, 0, sizeof(pdu)); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_0); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTPDU_VERSION_0); - assert_int_equal(Avtp_CommonStreamHeader_GetVersion(csh), AVTP_VERSION_0); + assert_int_equal(Avtp_CommonStreamHeader_GetVersion(csh), AVTPDU_VERSION_0); assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen(csh), AVTPDU_CSH_LEN_V0); Avtp_CommonStreamHeader_SetSv(csh, true); @@ -124,9 +124,9 @@ static void common_stream_header_v1_layout(void **state) Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; memset(pdu, 0, sizeof(pdu)); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTPDU_VERSION_1); - assert_int_equal(Avtp_CommonStreamHeader_GetVersion(csh), AVTP_VERSION_1); + assert_int_equal(Avtp_CommonStreamHeader_GetVersion(csh), AVTPDU_VERSION_1); assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen(csh), AVTPDU_CSH_LEN_V1); Avtp_CommonStreamHeader_SetSv(csh, true); @@ -178,7 +178,7 @@ static void common_stream_header_absent_fields(void **state) Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; memset(pdu, 0, sizeof(pdu)); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_0); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTPDU_VERSION_0); /* format_specific_data_0 and ptp_grandmaster_identity do not exist in v0. */ assert_int_equal(Avtp_CommonStreamHeader_GetFormatSpecificData0(csh), 0); @@ -197,7 +197,7 @@ static void common_stream_header_no_overlap(void **state) for (uint8_t version = 0; version <= 1; version++) { uint8_t coverage[AVTPDU_CSH_LEN_V1 * 8] = {0}; const Avtp_FieldDescriptor_t *desc = - version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; for (uint8_t i = 0; i < AVTPDU_CSH_FIELD_MAX; i++) { uint8_t quadlet = desc[i].quadlet; @@ -226,10 +226,10 @@ static void common_stream_header_typed_header_len(void **state) assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen_V0(csh), AVTPDU_CSH_LEN_V0); assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen_V1(csh), AVTPDU_CSH_LEN_V1); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_0); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTPDU_VERSION_0); assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen(csh), AVTPDU_CSH_LEN_V0); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTPDU_VERSION_1); assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen(csh), AVTPDU_CSH_LEN_V1); } @@ -240,7 +240,7 @@ static void common_stream_header_typed_fields_v0(void **state) Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; memset(pdu, 0, sizeof(pdu)); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_0); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTPDU_VERSION_0); for (uint8_t f = 0; f < AVTPDU_CSH_FIELD_MAX; f++) { uint8_t bits = Avtp_CshFieldDescV0[f].bits; @@ -263,7 +263,7 @@ static void common_stream_header_typed_fields_v1(void **state) Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; memset(pdu, 0, sizeof(pdu)); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTPDU_VERSION_1); for (uint8_t f = 0; f < AVTPDU_CSH_FIELD_MAX; f++) { uint8_t bits = Avtp_CshFieldDescV1[f].bits; @@ -286,7 +286,7 @@ static void common_stream_header_typed_named_v0(void **state) Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; memset(pdu, 0, sizeof(pdu)); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_0); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTPDU_VERSION_0); Avtp_CommonStreamHeader_SetSv_V0(csh, true); Avtp_CommonStreamHeader_SetMr_V0(csh, true); @@ -328,7 +328,7 @@ static void common_stream_header_typed_named_v1(void **state) Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; memset(pdu, 0, sizeof(pdu)); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_1); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTPDU_VERSION_1); Avtp_CommonStreamHeader_SetSv_V1(csh, true); Avtp_CommonStreamHeader_SetMr_V1(csh, true); @@ -378,7 +378,7 @@ static void common_stream_header_typed_absent_fields(void **state) Avtp_CommonStreamHeader_t *csh = (Avtp_CommonStreamHeader_t *)pdu; memset(pdu, 0, sizeof(pdu)); - Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTP_VERSION_0); + Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)csh, AVTPDU_VERSION_0); /* format_specific_data_0 and ptp_grandmaster_identity do not exist in v0. */ assert_int_equal(Avtp_CommonStreamHeader_GetFormatSpecificData0_V0(csh), 0); diff --git a/unit/test-crf.c b/unit/test-crf.c index 9f8a2046..9029b63b 100644 --- a/unit/test-crf.c +++ b/unit/test-crf.c @@ -184,9 +184,9 @@ static void crf_field_descriptors_cover_header(void **state) uint8_t coverage[AVTP_CRF_HEADER_LEN_V1 * 8] = {0}; size_t coverageBits = sizeof(coverage); const Avtp_FieldDescriptor_t *crfDesc = - version == AVTP_VERSION_1 ? Avtp_CrfFieldDescV1 : Avtp_CrfFieldDescV0; - size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_CRF_HEADER_LEN_V1 - : (size_t)AVTP_CRF_HEADER_LEN_V0) * + version == AVTPDU_VERSION_1 ? Avtp_CrfFieldDescV1 : Avtp_CrfFieldDescV0; + size_t headerBits = (version == AVTPDU_VERSION_1 ? (size_t)AVTP_CRF_HEADER_LEN_V1 + : (size_t)AVTP_CRF_HEADER_LEN_V0) * 8; /* subtype and version are owned by the common header; h/sv is covered @@ -214,9 +214,9 @@ static void crf_ah_field_consistency(void **state) for (uint8_t version = 0; version <= 1; version++) { const Avtp_FieldDescriptor_t *crfDesc = - version == AVTP_VERSION_1 ? Avtp_CrfFieldDescV1 : Avtp_CrfFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_CrfFieldDescV1 : Avtp_CrfFieldDescV0; const Avtp_FieldDescriptor_t *ahDesc = - version == AVTP_VERSION_1 ? Avtp_AhFieldDescV1 : Avtp_AhFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_AhFieldDescV1 : Avtp_AhFieldDescV0; for (uint8_t i = 0; i < AVTPDU_AH_FIELD_MAX; i++) { assert_int_equal(crfDesc[i].quadlet, ahDesc[i].quadlet); diff --git a/unit/test-cvf.c b/unit/test-cvf.c index dfc65a00..73d95f2f 100644 --- a/unit/test-cvf.c +++ b/unit/test-cvf.c @@ -177,9 +177,9 @@ static void cvf_field_descriptors_cover_header(void **state) uint8_t coverage[AVTP_CVF_HEADER_LEN_V1 * 8] = {0}; size_t coverageBits = sizeof(coverage); const Avtp_FieldDescriptor_t *cvfDesc = - version == AVTP_VERSION_1 ? Avtp_CvfFieldDescV1 : Avtp_CvfFieldDescV0; - size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_CVF_HEADER_LEN_V1 - : (size_t)AVTP_CVF_HEADER_LEN_V0) * + version == AVTPDU_VERSION_1 ? Avtp_CvfFieldDescV1 : Avtp_CvfFieldDescV0; + size_t headerBits = (version == AVTPDU_VERSION_1 ? (size_t)AVTP_CVF_HEADER_LEN_V1 + : (size_t)AVTP_CVF_HEADER_LEN_V0) * 8; mark_descriptors(coverage, coverageBits, @@ -202,9 +202,9 @@ static void cvf_common_field_consistency(void **state) for (uint8_t version = 0; version <= 1; version++) { const Avtp_FieldDescriptor_t *cvfDesc = - version == AVTP_VERSION_1 ? Avtp_CvfFieldDescV1 : Avtp_CvfFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_CvfFieldDescV1 : Avtp_CvfFieldDescV0; const Avtp_FieldDescriptor_t *cshDesc = - version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; for (uint8_t i = 0; i < AVTPDU_CSH_FIELD_MAX; i++) { assert_int_equal(cvfDesc[i].quadlet, cshDesc[i].quadlet); diff --git a/unit/test-ntscf.c b/unit/test-ntscf.c index 5a176c10..30d2fcab 100644 --- a/unit/test-ntscf.c +++ b/unit/test-ntscf.c @@ -163,9 +163,9 @@ static void ntscf_field_descriptors_cover_header(void **state) uint8_t coverage[AVTP_NTSCF_HEADER_LEN_V1 * 8] = {0}; size_t coverageBits = sizeof(coverage); const Avtp_FieldDescriptor_t *ntscfDesc = - version == AVTP_VERSION_1 ? Avtp_NtscfFieldDescV1 : Avtp_NtscfFieldDescV0; - size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_NTSCF_HEADER_LEN_V1 - : (size_t)AVTP_NTSCF_HEADER_LEN_V0) * + version == AVTPDU_VERSION_1 ? Avtp_NtscfFieldDescV1 : Avtp_NtscfFieldDescV0; + size_t headerBits = (version == AVTPDU_VERSION_1 ? (size_t)AVTP_NTSCF_HEADER_LEN_V1 + : (size_t)AVTP_NTSCF_HEADER_LEN_V0) * 8; /* subtype and version are owned by the common header; h/sv is covered @@ -193,9 +193,9 @@ static void ntscf_ah_field_consistency(void **state) for (uint8_t version = 0; version <= 1; version++) { const Avtp_FieldDescriptor_t *ntscfDesc = - version == AVTP_VERSION_1 ? Avtp_NtscfFieldDescV1 : Avtp_NtscfFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_NtscfFieldDescV1 : Avtp_NtscfFieldDescV0; const Avtp_FieldDescriptor_t *ahDesc = - version == AVTP_VERSION_1 ? Avtp_AhFieldDescV1 : Avtp_AhFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_AhFieldDescV1 : Avtp_AhFieldDescV0; for (uint8_t i = 0; i < AVTPDU_AH_FIELD_MAX; i++) { assert_int_equal(ntscfDesc[i].quadlet, ahDesc[i].quadlet); diff --git a/unit/test-pcm.c b/unit/test-pcm.c index 0e1cf442..3bcef976 100644 --- a/unit/test-pcm.c +++ b/unit/test-pcm.c @@ -228,9 +228,9 @@ static void pcm_field_descriptors_cover_header(void **state) uint8_t coverage[AVTP_PCM_HEADER_LEN_V1 * 8] = {0}; size_t coverageBits = sizeof(coverage); const Avtp_FieldDescriptor_t *pcmDesc = - version == AVTP_VERSION_1 ? Avtp_PcmFieldDescV1 : Avtp_PcmFieldDescV0; - size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_PCM_HEADER_LEN_V1 - : (size_t)AVTP_PCM_HEADER_LEN_V0) * + version == AVTPDU_VERSION_1 ? Avtp_PcmFieldDescV1 : Avtp_PcmFieldDescV0; + size_t headerBits = (version == AVTPDU_VERSION_1 ? (size_t)AVTP_PCM_HEADER_LEN_V1 + : (size_t)AVTP_PCM_HEADER_LEN_V0) * 8; mark_descriptors(coverage, coverageBits, @@ -253,9 +253,9 @@ static void pcm_common_field_consistency(void **state) for (uint8_t version = 0; version <= 1; version++) { const Avtp_FieldDescriptor_t *pcmDesc = - version == AVTP_VERSION_1 ? Avtp_PcmFieldDescV1 : Avtp_PcmFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_PcmFieldDescV1 : Avtp_PcmFieldDescV0; const Avtp_FieldDescriptor_t *cshDesc = - version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; for (uint8_t i = 0; i < AVTPDU_CSH_FIELD_MAX; i++) { assert_int_equal(pcmDesc[i].quadlet, cshDesc[i].quadlet); @@ -271,9 +271,9 @@ static void pcm_aaf_shared_field_consistency(void **state) for (uint8_t version = 0; version <= 1; version++) { const Avtp_FieldDescriptor_t *pcmDesc = - version == AVTP_VERSION_1 ? Avtp_PcmFieldDescV1 : Avtp_PcmFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_PcmFieldDescV1 : Avtp_PcmFieldDescV0; const Avtp_FieldDescriptor_t *aafDesc = - version == AVTP_VERSION_1 ? Avtp_AafFieldDescV1 : Avtp_AafFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_AafFieldDescV1 : Avtp_AafFieldDescV0; /* PCM and AAF interpret the same format-specific data slots, so the * shared fields must have identical positions. */ diff --git a/unit/test-rvf.c b/unit/test-rvf.c index 58e0303d..f1a795f7 100644 --- a/unit/test-rvf.c +++ b/unit/test-rvf.c @@ -183,9 +183,9 @@ static void rvf_field_descriptors_cover_header(void **state) uint8_t coverage[AVTP_RVF_HEADER_LEN_V1 * 8] = {0}; size_t coverageBits = sizeof(coverage); const Avtp_FieldDescriptor_t *rvfDesc = - version == AVTP_VERSION_1 ? Avtp_RvfFieldDescV1 : Avtp_RvfFieldDescV0; - size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_RVF_HEADER_LEN_V1 - : (size_t)AVTP_RVF_HEADER_LEN_V0) * + version == AVTPDU_VERSION_1 ? Avtp_RvfFieldDescV1 : Avtp_RvfFieldDescV0; + size_t headerBits = (version == AVTPDU_VERSION_1 ? (size_t)AVTP_RVF_HEADER_LEN_V1 + : (size_t)AVTP_RVF_HEADER_LEN_V0) * 8; mark_descriptors(coverage, coverageBits, @@ -208,9 +208,9 @@ static void rvf_common_field_consistency(void **state) for (uint8_t version = 0; version <= 1; version++) { const Avtp_FieldDescriptor_t *rvfDesc = - version == AVTP_VERSION_1 ? Avtp_RvfFieldDescV1 : Avtp_RvfFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_RvfFieldDescV1 : Avtp_RvfFieldDescV0; const Avtp_FieldDescriptor_t *cshDesc = - version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; for (uint8_t i = 0; i < AVTPDU_CSH_FIELD_MAX; i++) { assert_int_equal(rvfDesc[i].quadlet, cshDesc[i].quadlet); diff --git a/unit/test-tscf.c b/unit/test-tscf.c index 87c1c56f..7fa41206 100644 --- a/unit/test-tscf.c +++ b/unit/test-tscf.c @@ -100,7 +100,7 @@ static void tscf_init_v1(void **state) assert_memory_equal(init_pdu, pdu, AVTP_TSCF_HEADER_LEN_V1); assert_int_equal(Avtp_CommonStreamHeader_GetVersion((Avtp_CommonStreamHeader_t *)pdu), - AVTP_VERSION_1); + AVTPDU_VERSION_1); assert_int_equal(Avtp_CommonStreamHeader_GetHeaderLen((Avtp_CommonStreamHeader_t *)pdu), AVTP_TSCF_HEADER_LEN_V1); } @@ -243,9 +243,9 @@ static void tscf_header_coverage(void **state) uint8_t coverage[AVTP_TSCF_HEADER_LEN_V1 * 8] = {0}; size_t coverageBits = sizeof(coverage); const Avtp_FieldDescriptor_t *tscfDesc = - version == AVTP_VERSION_1 ? Avtp_TscfFieldDescV1 : Avtp_TscfFieldDescV0; - size_t headerBits = (version == AVTP_VERSION_1 ? (size_t)AVTP_TSCF_HEADER_LEN_V1 - : (size_t)AVTP_TSCF_HEADER_LEN_V0) * + version == AVTPDU_VERSION_1 ? Avtp_TscfFieldDescV1 : Avtp_TscfFieldDescV0; + size_t headerBits = (version == AVTPDU_VERSION_1 ? (size_t)AVTP_TSCF_HEADER_LEN_V1 + : (size_t)AVTP_TSCF_HEADER_LEN_V0) * 8; /* subtype and version are owned by the common header; h/sv is covered @@ -272,9 +272,9 @@ static void tscf_common_field_consistency(void **state) for (uint8_t version = 0; version <= 1; version++) { const Avtp_FieldDescriptor_t *tscfDesc = - version == AVTP_VERSION_1 ? Avtp_TscfFieldDescV1 : Avtp_TscfFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_TscfFieldDescV1 : Avtp_TscfFieldDescV0; const Avtp_FieldDescriptor_t *cshDesc = - version == AVTP_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; + version == AVTPDU_VERSION_1 ? Avtp_CshFieldDescV1 : Avtp_CshFieldDescV0; for (uint8_t i = 0; i < AVTPDU_CSH_FIELD_MAX; i++) { assert_int_equal(tscfDesc[i].quadlet, cshDesc[i].quadlet); From a141334a2ab725999e6221fa5a6c7b381326c6a6 Mon Sep 17 00:00:00 2001 From: Sebastian Schildt Date: Sat, 3 Oct 2026 16:39:14 +0200 Subject: [PATCH 16/16] Use consistent V0 V1 naming for versioned subprotocols, providing a generic alias that can be used for version agnostic access Signed-off-by: Sebastian Schildt --- README.md | 10 +- bench/bench-field-access.c | 4 +- docs/api-design.md | 54 ++++++--- docs/inline.md | 2 +- examples/aaf/aaf-talker.c | 2 +- examples/acf-can/acf-can-common.c | 4 +- .../acf-can/linux-kernel-mod/1722ethernet.c | 2 +- examples/acf-vss/acf-vss-talker.c | 4 +- examples/crf/crf-listener.c | 2 +- examples/crf/crf-talker.c | 2 +- examples/cvf/cvf-talker.c | 2 +- examples/hello-world/hello-world-talker.c | 4 +- include/avtp/Crf.h | 92 +++++++++------ include/avtp/Rvf.h | 110 +++++++++++------- include/avtp/aaf/Aaf.h | 102 ++++++++++------ include/avtp/aaf/Pcm.h | 102 ++++++++++------ include/avtp/acf/Ntscf.h | 64 +++++++--- include/avtp/acf/Tscf.h | 80 ++++++++----- include/avtp/cvf/Cvf.h | 98 ++++++++++------ unit/test-aaf.c | 47 ++++++-- unit/test-crf.c | 41 +++++-- unit/test-cvf.c | 47 ++++++-- unit/test-ntscf.c | 45 +++++-- unit/test-pcm.c | 41 +++++-- unit/test-rvf.c | 43 +++++-- unit/test-tscf.c | 47 ++++++-- 26 files changed, 716 insertions(+), 335 deletions(-) diff --git a/README.md b/README.md index 5fce09f0..29367e1a 100644 --- a/README.md +++ b/README.md @@ -146,8 +146,8 @@ When combining IEEE 1722 header/message structs directly in memory to form a pac typedef struct __attribute__((packed)) { // IEEE 1722 UDP encapsulation header (optional) Avtp_Udp_t udp; - // IEEE 1722 TSCF header - Avtp_Tscf_t tscf; + // IEEE 1722 TSCF header (version 0 layout; use Avtp_TscfV1_t for version 1) + Avtp_TscfV0_t tscf; // IEEE 1722 ACF message #1 Avtp_Can_t can; uint8_t canPayload[CAN_PAYLOAD_LEN]; @@ -171,8 +171,10 @@ int main() // Init UDP encapsulation header Avtp_Udp_Init(&pdu.udp); - // Init TSCF header - Avtp_Tscf_Init(&pdu.tscf); + // Init TSCF header. Use Avtp_Tscf_Init(&pdu.tscf, version) to pick the + // version at runtime; version 0 and version 1 have different layouts and + // header lengths (Avtp_TscfV0_t / Avtp_TscfV1_t). + Avtp_Tscf_InitV0(&pdu.tscf); Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)&pdu.tscf, 0); Avtp_Tscf_SetSequenceNum(&pdu.tscf, 123); Avtp_Tscf_SetStreamId(&pdu.tscf, 0xAABBCCDDEEFF); diff --git a/bench/bench-field-access.c b/bench/bench-field-access.c index 045e2308..a6806d89 100644 --- a/bench/bench-field-access.c +++ b/bench/bench-field-access.c @@ -134,7 +134,7 @@ static void bench_tscf_v0_get(void) uint8_t buf[AVTP_TSCF_HEADER_LEN_V0]; Avtp_Tscf_t *pdu = (Avtp_Tscf_t *)buf; - Avtp_Tscf_Init(pdu); + Avtp_Tscf_InitV0(pdu); Avtp_Tscf_SetSequenceNum_V0(pdu, 0xAB); printf("TSCF version 0, get sequence_num (8 bit):\n"); @@ -148,7 +148,7 @@ static void bench_tscf_v0_set(void) uint8_t buf[AVTP_TSCF_HEADER_LEN_V0]; Avtp_Tscf_t *pdu = (Avtp_Tscf_t *)buf; - Avtp_Tscf_Init(pdu); + Avtp_Tscf_InitV0(pdu); printf("TSCF version 0, set sequence_num (8 bit):\n"); BENCH("typed Avtp_Tscf_SetSequenceNum_V0", Avtp_Tscf_SetSequenceNum_V0(pdu, bench_i); diff --git a/docs/api-design.md b/docs/api-design.md index 745c74b8..8654cb10 100644 --- a/docs/api-design.md +++ b/docs/api-design.md @@ -176,16 +176,21 @@ layers of field accessors: | Version-typed generic | `Avtp__GetField_V0` / `_V1` | `Avtp_Tscf_GetField_V1(pdu, field)` | | Version-agnostic | `Avtp__` | `Avtp_Tscf_GetSequenceNum` | -The version-typed variants take the matching PDU struct (`Avtp__t` for -`_V0`, `Avtp_V1_t` for `_V1`), never read the version field and select -the field layout at compile time. The version-agnostic variant reads the version -once and forwards to the matching typed variant. Setters keep the -version-specific semantics: for example `SetSequenceNum_V1` on TSCF/NTSCF/CRF -also writes the `sequence_num_lsb` copy, while the version 0 variant writes the -8-bit `sequence_num_lsb` field that is the sequence number there. +The version-typed variants take the matching PDU struct (`Avtp_V0_t` +for `_V0`, `Avtp_V1_t` for `_V1`), never read the version field and +select the field layout at compile time. The version-agnostic variant takes the +generic `Avtp__t` handle - an alias of the version 0 struct - reads the +version once and forwards to the matching typed variant. Version-agnostic +setters dispatch on the wire version, so they must follow one of +`Avtp__Init`, `Avtp__InitV0` or `Avtp__InitV1`; the +version-agnostic init selects the layout from its `version` argument. Setters +keep the version-specific semantics: for example `SetSequenceNum_V1` on +TSCF/NTSCF/CRF also writes the `sequence_num_lsb` copy, while the version 0 +variant writes the 8-bit `sequence_num_lsb` field that is the sequence number +there. Use the typed variants whenever the version is known - a talker after -`Init`/`InitV1`, or a listener after checking the version once - and the +`InitV0`/`InitV1`, or a listener after checking the version once - and the agnostic variant for mixed-version receive paths. The common stream header fields are implemented once in [`CommonStreamHeader.h`](../include/avtp/CommonStreamHeader.h) and delegated to @@ -250,12 +255,17 @@ also be `packed` so the compiler inserts no padding between them: ```c typedef struct __attribute__((packed)) { - Avtp_Tscf_t tscf; + Avtp_TscfV0_t tscf; Avtp_Can_t can; uint8_t canPayload[8]; } My1722Pdu_t; ``` +Formats with more than one header version name their concrete wire structs +`Avtp_V0_t` and `Avtp_V1_t`; embed the struct matching the +version you are building. `Avtp__t` is an alias of the version 0 struct +and is the generic handle used by the version-agnostic accessors. + ## Accessor semantics & the safety contract Accessors are intentionally *unsafe against malformed input*. A getter assumes @@ -375,6 +385,12 @@ used): | Header length | `AVTP__HEADER_LEN` | `AVTP_CAN_HEADER_LEN` | | ACF message type | `AVTP_ACF_TYPE_` | `AVTP_ACF_TYPE_CAN` | +Formats that support more than one header version additionally define +`Avtp_V0_t` and `Avtp_V1_t` for the two wire layouts and keep +`Avtp__t` as an alias of the version 0 struct, used as the generic +handle by the version-agnostic accessors. `InitV0`/`InitV1` initialise one +version explicitly and the generic `Init(pdu, version)` selects at runtime. + Field enum values are always declared with the terminator `..._FIELD_MAX` as the last entry. This value is never a real field; it exists to give the field-count used for bounds checking in the access engine (see @@ -674,12 +690,15 @@ asserts that they equal the style module's entries for the same version. `GetHeaderLen` is used by the payload helpers so `Avtp__Get/SetPayload` work for both versions. -The version 1 PDU struct (for example `Avtp_TscfV1_t`) is sized for the larger -header and is used for allocation and embedding. Version-typed accessors take -the matching struct (`Avtp__t` for `_V0`, `Avtp_V1_t` for -`_V1`), so version 1 callers keep the typed pointer. The version-agnostic -accessors still take the version 0 struct pointer and version 1 callers cast -once. +The version 0 and version 1 PDU structs (for example `Avtp_TscfV0_t` and +`Avtp_TscfV1_t`) are used for allocation and embedding. Version-typed accessors +take the matching struct (`Avtp_V0_t` for `_V0`, `Avtp_V1_t` +for `_V1`), so version 1 callers keep the typed pointer. The version-agnostic +accessors take the generic `Avtp__t` handle (an alias of the version 0 +struct) and version 1 callers cast once. `InitV0`/`InitV1` initialise one +version explicitly; the generic `Init(pdu, version)` selects the layout at +runtime. Version-agnostic setters require one of those inits first, since they +dispatch on the wire version field. The "every bit described exactly once" rule becomes a cross-module test: for each version, the common header fields (`subtype`, `version`; `h` is covered by @@ -898,4 +917,7 @@ For a format that supports more than one header version, also follow [Accessor API](header-versions.md#accessor-api) in the migration guide: declare a complete descriptor table per version and add `_V0`/`_V1` variants for every accessor, delegating the common fields to `CommonStreamHeader.h` (or -`AlternativeHeader.h` for the alternative header). +`AlternativeHeader.h` for the alternative header). Name the concrete structs +`Avtp_V0_t`/`Avtp_V1_t`, keep `Avtp__t` as the generic +handle alias of the version 0 struct, and provide `InitV0`/`InitV1` plus the +version-parameterised `Init`. diff --git a/docs/inline.md b/docs/inline.md index 7041c77e..966711b3 100644 --- a/docs/inline.md +++ b/docs/inline.md @@ -54,7 +54,7 @@ Include the headers and call functions as usual. The compiler gets `static inlin #include "avtp/acf/Ntscf.h" void parse(uint8_t *frame) { - Avtp_Ntscf_t *pdu = (Avtp_Ntscf_t *)frame; + Avtp_Ntscf_t *pdu = (Avtp_Ntscf_t *)frame; /* version-agnostic handle */ uint16_t len = Avtp_Ntscf_GetNtscfDataLength(pdu); // ... } diff --git a/examples/aaf/aaf-talker.c b/examples/aaf/aaf-talker.c index 09d8202d..c8711e8e 100644 --- a/examples/aaf/aaf-talker.c +++ b/examples/aaf/aaf-talker.c @@ -122,7 +122,7 @@ static struct argp argp = {options, parser}; static void init_pdu(Avtp_Pcm_t *pdu) { - Avtp_Pcm_Init(pdu); + Avtp_Pcm_InitV0(pdu); Avtp_Pcm_SetTv_V0(pdu, true); Avtp_Pcm_SetStreamId_V0(pdu, STREAM_ID); Avtp_Pcm_SetFormat_V0(pdu, AVTP_AAF_FORMAT_INT_16BIT); diff --git a/examples/acf-can/acf-can-common.c b/examples/acf-can/acf-can-common.c index 392c881c..ef13fa02 100644 --- a/examples/acf-can/acf-can-common.c +++ b/examples/acf-can/acf-can-common.c @@ -128,7 +128,7 @@ static int init_cf_pdu(uint8_t *pdu, uint64_t stream_id, acf_can_cf_t cf, uint32 if (cf == ACF_CAN_CF_NTSCF_V0) { Avtp_Ntscf_t *ntscf = (Avtp_Ntscf_t *)pdu; - Avtp_Ntscf_Init(ntscf); + Avtp_Ntscf_InitV0(ntscf); Avtp_Ntscf_SetSequenceNum_V0(ntscf, seq_num); Avtp_Ntscf_SetStreamId_V0(ntscf, stream_id); return (int)Avtp_Ntscf_GetHeaderLen_V0(ntscf); @@ -144,7 +144,7 @@ static int init_cf_pdu(uint8_t *pdu, uint64_t stream_id, acf_can_cf_t cf, uint32 } Avtp_Tscf_t *tscf = (Avtp_Tscf_t *)pdu; - Avtp_Tscf_Init(tscf); + Avtp_Tscf_InitV0(tscf); Avtp_Tscf_SetTu_V0(tscf, false); Avtp_Tscf_SetSequenceNum_V0(tscf, seq_num); Avtp_Tscf_SetStreamId_V0(tscf, stream_id); diff --git a/examples/acf-can/linux-kernel-mod/1722ethernet.c b/examples/acf-can/linux-kernel-mod/1722ethernet.c index 57456370..0d08faa2 100644 --- a/examples/acf-can/linux-kernel-mod/1722ethernet.c +++ b/examples/acf-can/linux-kernel-mod/1722ethernet.c @@ -48,7 +48,7 @@ void prepare_ntscf_header(Avtp_Ntscf_t *ntscf_header, struct acfcan_cfg *cfg) { - Avtp_Ntscf_Init(ntscf_header); + Avtp_Ntscf_InitV0(ntscf_header); Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)ntscf_header, 0); Avtp_Ntscf_SetSequenceNum_V0(ntscf_header, cfg->sequenceNum++); // This can't be right. Increase? diff --git a/examples/acf-vss/acf-vss-talker.c b/examples/acf-vss/acf-vss-talker.c index 7dc8a5de..8da719b9 100644 --- a/examples/acf-vss/acf-vss-talker.c +++ b/examples/acf-vss/acf-vss-talker.c @@ -143,7 +143,7 @@ static int init_cf_pdu(uint8_t *pdu) if (use_tscf) { Avtp_Tscf_t *tscf_pdu = (Avtp_Tscf_t *)pdu; memset(tscf_pdu, 0, AVTP_TSCF_HEADER_LEN); - Avtp_Tscf_Init(tscf_pdu); + Avtp_Tscf_InitV0(tscf_pdu); Avtp_Tscf_SetTu_V0(tscf_pdu, false); Avtp_Tscf_SetSequenceNum_V0(tscf_pdu, seq_num++); Avtp_Tscf_SetStreamId_V0(tscf_pdu, STREAM_ID); @@ -151,7 +151,7 @@ static int init_cf_pdu(uint8_t *pdu) } else { Avtp_Ntscf_t *ntscf_pdu = (Avtp_Ntscf_t *)pdu; memset(ntscf_pdu, 0, AVTP_NTSCF_HEADER_LEN); - Avtp_Ntscf_Init(ntscf_pdu); + Avtp_Ntscf_InitV0(ntscf_pdu); Avtp_Ntscf_SetSequenceNum_V0(ntscf_pdu, seq_num++); Avtp_Ntscf_SetStreamId_V0(ntscf_pdu, STREAM_ID); res = AVTP_NTSCF_HEADER_LEN; diff --git a/examples/crf/crf-listener.c b/examples/crf/crf-listener.c index fe356e5a..7262aeea 100644 --- a/examples/crf/crf-listener.c +++ b/examples/crf/crf-listener.c @@ -420,7 +420,7 @@ static bool is_valid_aaf_pdu(Avtp_Pcm_t *pdu) static void init_aaf_pdu(Avtp_Pcm_t *pdu) { - Avtp_Pcm_Init(pdu); + Avtp_Pcm_InitV0(pdu); Avtp_Pcm_SetTv_V0(pdu, true); Avtp_Pcm_SetStreamId_V0(pdu, AAF_STREAM_ID); Avtp_Pcm_SetFormat_V0(pdu, AVTP_AAF_FORMAT_INT_16BIT); diff --git a/examples/crf/crf-talker.c b/examples/crf/crf-talker.c index 54d41d38..05325ca8 100644 --- a/examples/crf/crf-talker.c +++ b/examples/crf/crf-talker.c @@ -152,7 +152,7 @@ static uint64_t calculate_crf_timestamp(struct timespec tspec, uint64_t rounded_ static void init_pdu(Avtp_Crf_t *pdu) { - Avtp_Crf_Init(pdu); + Avtp_Crf_InitV0(pdu); Avtp_Crf_SetType_V0(pdu, AVTP_CRF_TYPE_AUDIO_SAMPLE); Avtp_Crf_SetStreamId_V0(pdu, STREAM_ID); Avtp_Crf_SetPull_V0(pdu, AVTP_CRF_PULL_MULT_BY_1); diff --git a/examples/cvf/cvf-talker.c b/examples/cvf/cvf-talker.c index b98e86c5..d74caa0c 100644 --- a/examples/cvf/cvf-talker.c +++ b/examples/cvf/cvf-talker.c @@ -138,7 +138,7 @@ static struct argp argp = {options, parser}; static void init_pdu(Avtp_Cvf_t *cvf) { - Avtp_Cvf_Init(cvf); + Avtp_Cvf_InitV0(cvf); Avtp_Cvf_SetFormatSubtype_V0(cvf, AVTP_CVF_FORMAT_SUBTYPE_H264); Avtp_Cvf_SetTv_V0(cvf, true); Avtp_Cvf_SetStreamId_V0(cvf, STREAM_ID); diff --git a/examples/hello-world/hello-world-talker.c b/examples/hello-world/hello-world-talker.c index 4dbbad4d..dd369f76 100644 --- a/examples/hello-world/hello-world-talker.c +++ b/examples/hello-world/hello-world-talker.c @@ -126,7 +126,7 @@ static int init_cf_pdu(uint8_t *pdu) if (use_tscf) { Avtp_Tscf_t *tscf_pdu = (Avtp_Tscf_t *)pdu; memset(tscf_pdu, 0, AVTP_TSCF_HEADER_LEN); - Avtp_Tscf_Init(tscf_pdu); + Avtp_Tscf_InitV0(tscf_pdu); Avtp_Tscf_SetTu_V0(tscf_pdu, false); Avtp_Tscf_SetSequenceNum_V0(tscf_pdu, seq_num++); Avtp_Tscf_SetStreamId_V0(tscf_pdu, STREAM_ID); @@ -134,7 +134,7 @@ static int init_cf_pdu(uint8_t *pdu) } else { Avtp_Ntscf_t *ntscf_pdu = (Avtp_Ntscf_t *)pdu; memset(ntscf_pdu, 0, AVTP_NTSCF_HEADER_LEN); - Avtp_Ntscf_Init(ntscf_pdu); + Avtp_Ntscf_InitV0(ntscf_pdu); Avtp_Ntscf_SetSequenceNum_V0(ntscf_pdu, seq_num++); Avtp_Ntscf_SetStreamId_V0(ntscf_pdu, STREAM_ID); res = AVTP_NTSCF_HEADER_LEN; diff --git a/include/avtp/Crf.h b/include/avtp/Crf.h index bb6762bd..deaaceb4 100644 --- a/include/avtp/Crf.h +++ b/include/avtp/Crf.h @@ -70,13 +70,20 @@ extern "C" { typedef struct { uint8_t header[AVTP_CRF_HEADER_LEN_V0]; uint8_t payload[0]; -} __attribute__((packed)) Avtp_Crf_t; +} __attribute__((packed)) Avtp_CrfV0_t; typedef struct { uint8_t header[AVTP_CRF_HEADER_LEN_V1]; uint8_t payload[0]; } __attribute__((packed)) Avtp_CrfV1_t; +/** + * Version-agnostic handle for CRF PDUs. It is an alias of the version 0 + * layout and is the pointer type of the version-agnostic accessors; version 1 + * PDUs use Avtp_CrfV1_t. For version 0 use Avtp_CrfV0_t. + */ +typedef Avtp_CrfV0_t Avtp_Crf_t; + /** * CRF 'type' field values (IEEE 1722-2025, Table 31). Values 0x05-0xFF are * reserved. @@ -185,7 +192,7 @@ static const Avtp_FieldDescriptor_t Avtp_CrfFieldDescV1[AVTP_CRF_FIELD_MAX] = { * @returns This function returns the value of the field. * @see Avtp_Crf_GetField */ -OPEN1722_INLINE uint64_t Avtp_Crf_GetField_V0(const Avtp_Crf_t *const pdu, Avtp_CrfFields_t field) +OPEN1722_INLINE uint64_t Avtp_Crf_GetField_V0(const Avtp_CrfV0_t *const pdu, Avtp_CrfFields_t field) { return Avtp_GetField(Avtp_CrfFieldDescV0, AVTP_CRF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); @@ -231,7 +238,7 @@ OPEN1722_INLINE uint64_t Avtp_Crf_GetField(const Avtp_Crf_t *const pdu, Avtp_Crf * @param value The value to set. * @see Avtp_Crf_SetField */ -OPEN1722_INLINE void Avtp_Crf_SetField_V0(Avtp_Crf_t *pdu, Avtp_CrfFields_t field, uint64_t value) +OPEN1722_INLINE void Avtp_Crf_SetField_V0(Avtp_CrfV0_t *pdu, Avtp_CrfFields_t field, uint64_t value) { Avtp_SetField(Avtp_CrfFieldDescV0, AVTP_CRF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); } @@ -273,7 +280,7 @@ OPEN1722_INLINE void Avtp_Crf_SetField(Avtp_Crf_t *pdu, Avtp_CrfFields_t field, * pointer is not read; it keeps the signature aligned with the * version-dispatched accessors. */ -OPEN1722_INLINE uint8_t Avtp_Crf_GetHeaderLen_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Crf_GetHeaderLen_V0(const Avtp_CrfV0_t *const pdu) { (void)pdu; return (uint8_t)AVTP_CRF_HEADER_LEN_V0; @@ -604,7 +611,7 @@ OPEN1722_INLINE void Avtp_Crf_SetTimestampInterval(Avtp_Crf_t *pdu, uint16_t val * @return Pointer to CRF data * @see Avtp_Crf_GetPayload */ -OPEN1722_INLINE const uint8_t *Avtp_Crf_GetPayload_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE const uint8_t *Avtp_Crf_GetPayload_V0(const Avtp_CrfV0_t *const pdu) { return (const uint8_t *)pdu + AVTP_CRF_HEADER_LEN_V0; } @@ -647,7 +654,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Crf_GetPayload(const Avtp_Crf_t *const pdu) * @param payload_length Length of the payload * @see Avtp_Crf_SetPayload */ -OPEN1722_INLINE void Avtp_Crf_SetPayload_V0(Avtp_Crf_t *pdu, uint8_t *payload, +OPEN1722_INLINE void Avtp_Crf_SetPayload_V0(Avtp_CrfV0_t *pdu, uint8_t *payload, uint16_t payload_length) { memcpy((uint8_t *)pdu + AVTP_CRF_HEADER_LEN_V0, payload, payload_length); @@ -689,10 +696,10 @@ OPEN1722_INLINE void Avtp_Crf_SetPayload(Avtp_Crf_t *pdu, uint8_t *payload, uint * * @param pdu Pointer to the first bit of a 1722 CRF PDU. */ -OPEN1722_INLINE void Avtp_Crf_Init(Avtp_Crf_t *pdu) +OPEN1722_INLINE void Avtp_Crf_InitV0(Avtp_CrfV0_t *pdu) { if (pdu != NULL) { - memset(pdu, 0, sizeof(Avtp_Crf_t)); + memset(pdu, 0, sizeof(Avtp_CrfV0_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_CRF); Avtp_Crf_SetSv(pdu, true); } @@ -763,6 +770,25 @@ OPEN1722_INLINE bool Avtp_Crf_IsValid(const Avtp_Crf_t *const pdu, size_t buffer return true; } +/** + * Initializes a CRF PDU of the given version. The caller must provide a + * buffer of at least AVTP_CRF_HEADER_LEN_V1 octets for version 1 (for + * example an Avtp_CrfV1_t); version 0 uses AVTP_CRF_HEADER_LEN_V0 + * octets. Any version other than AVTPDU_VERSION_1 initializes a version 0 PDU. + * + * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- + * or an ACF header. + * @param version AVTPDU header version (AVTPDU_VERSION_0 or AVTPDU_VERSION_1). + */ +OPEN1722_INLINE void Avtp_Crf_Init(Avtp_Crf_t *pdu, uint8_t version) +{ + if (version == AVTPDU_VERSION_1) { + Avtp_Crf_InitV1((Avtp_CrfV1_t *)pdu); + } else { + Avtp_Crf_InitV0(pdu); + } +} + /* * Version-typed named accessors. These select the field layout for one * explicit version and never read the version field; the version-dispatched @@ -775,7 +801,7 @@ OPEN1722_INLINE bool Avtp_Crf_IsValid(const Avtp_Crf_t *const pdu, size_t buffer * Version 0 variant of Avtp_Crf_IsSv(). * @see Avtp_Crf_IsSv */ -OPEN1722_INLINE bool Avtp_Crf_IsSv_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE bool Avtp_Crf_IsSv_V0(const Avtp_CrfV0_t *const pdu) { return (bool)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_SV); } @@ -793,7 +819,7 @@ OPEN1722_INLINE bool Avtp_Crf_IsSv_V1(const Avtp_CrfV1_t *const pdu) * Version 0 variant of Avtp_Crf_IsMr(). * @see Avtp_Crf_IsMr */ -OPEN1722_INLINE bool Avtp_Crf_IsMr_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE bool Avtp_Crf_IsMr_V0(const Avtp_CrfV0_t *const pdu) { return (bool)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_MR); } @@ -811,7 +837,7 @@ OPEN1722_INLINE bool Avtp_Crf_IsMr_V1(const Avtp_CrfV1_t *const pdu) * Version 0 variant of Avtp_Crf_IsFs(). * @see Avtp_Crf_IsFs */ -OPEN1722_INLINE bool Avtp_Crf_IsFs_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE bool Avtp_Crf_IsFs_V0(const Avtp_CrfV0_t *const pdu) { return (bool)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_FS); } @@ -829,7 +855,7 @@ OPEN1722_INLINE bool Avtp_Crf_IsFs_V1(const Avtp_CrfV1_t *const pdu) * Version 0 variant of Avtp_Crf_IsTu(). * @see Avtp_Crf_IsTu */ -OPEN1722_INLINE bool Avtp_Crf_IsTu_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE bool Avtp_Crf_IsTu_V0(const Avtp_CrfV0_t *const pdu) { return (bool)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_TU); } @@ -848,7 +874,7 @@ OPEN1722_INLINE bool Avtp_Crf_IsTu_V1(const Avtp_CrfV1_t *const pdu) * number is the 8-bit sequence_num_lsb field. * @see Avtp_Crf_GetSequenceNum */ -OPEN1722_INLINE uint32_t Avtp_Crf_GetSequenceNum_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Crf_GetSequenceNum_V0(const Avtp_CrfV0_t *const pdu) { return (uint32_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB); } @@ -866,7 +892,7 @@ OPEN1722_INLINE uint32_t Avtp_Crf_GetSequenceNum_V1(const Avtp_CrfV1_t *const pd * Version 0 variant of Avtp_Crf_GetSequenceNumLsb(). * @see Avtp_Crf_GetSequenceNumLsb */ -OPEN1722_INLINE uint8_t Avtp_Crf_GetSequenceNumLsb_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Crf_GetSequenceNumLsb_V0(const Avtp_CrfV0_t *const pdu) { return (uint8_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB); } @@ -885,7 +911,7 @@ OPEN1722_INLINE uint8_t Avtp_Crf_GetSequenceNumLsb_V1(const Avtp_CrfV1_t *const * absent from version 0, so this always returns 0. * @see Avtp_Crf_GetPtpGrandmasterIdentity */ -OPEN1722_INLINE uint64_t Avtp_Crf_GetPtpGrandmasterIdentity_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Crf_GetPtpGrandmasterIdentity_V0(const Avtp_CrfV0_t *const pdu) { return Avtp_AlternativeHeader_GetPtpGrandmasterIdentity_V0( (const Avtp_AlternativeHeader_t *)pdu); @@ -905,7 +931,7 @@ OPEN1722_INLINE uint64_t Avtp_Crf_GetPtpGrandmasterIdentity_V1(const Avtp_CrfV1_ * Version 0 variant of Avtp_Crf_GetType(). * @see Avtp_Crf_GetType */ -OPEN1722_INLINE Avtp_CrfType_t Avtp_Crf_GetType_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE Avtp_CrfType_t Avtp_Crf_GetType_V0(const Avtp_CrfV0_t *const pdu) { return (Avtp_CrfType_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_TYPE); } @@ -923,7 +949,7 @@ OPEN1722_INLINE Avtp_CrfType_t Avtp_Crf_GetType_V1(const Avtp_CrfV1_t *const pdu * Version 0 variant of Avtp_Crf_GetStreamId(). * @see Avtp_Crf_GetStreamId */ -OPEN1722_INLINE uint64_t Avtp_Crf_GetStreamId_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Crf_GetStreamId_V0(const Avtp_CrfV0_t *const pdu) { return Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_STREAM_ID); } @@ -941,7 +967,7 @@ OPEN1722_INLINE uint64_t Avtp_Crf_GetStreamId_V1(const Avtp_CrfV1_t *const pdu) * Version 0 variant of Avtp_Crf_GetPull(). * @see Avtp_Crf_GetPull */ -OPEN1722_INLINE Avtp_CrfPull_t Avtp_Crf_GetPull_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE Avtp_CrfPull_t Avtp_Crf_GetPull_V0(const Avtp_CrfV0_t *const pdu) { return (Avtp_CrfPull_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_PULL); } @@ -959,7 +985,7 @@ OPEN1722_INLINE Avtp_CrfPull_t Avtp_Crf_GetPull_V1(const Avtp_CrfV1_t *const pdu * Version 0 variant of Avtp_Crf_GetBaseFrequency(). * @see Avtp_Crf_GetBaseFrequency */ -OPEN1722_INLINE uint32_t Avtp_Crf_GetBaseFrequency_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Crf_GetBaseFrequency_V0(const Avtp_CrfV0_t *const pdu) { return (uint32_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_BASE_FREQUENCY); } @@ -977,7 +1003,7 @@ OPEN1722_INLINE uint32_t Avtp_Crf_GetBaseFrequency_V1(const Avtp_CrfV1_t *const * Version 0 variant of Avtp_Crf_GetCrfDataLength(). * @see Avtp_Crf_GetCrfDataLength */ -OPEN1722_INLINE uint16_t Avtp_Crf_GetCrfDataLength_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE uint16_t Avtp_Crf_GetCrfDataLength_V0(const Avtp_CrfV0_t *const pdu) { return (uint16_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_CRF_DATA_LENGTH); } @@ -995,7 +1021,7 @@ OPEN1722_INLINE uint16_t Avtp_Crf_GetCrfDataLength_V1(const Avtp_CrfV1_t *const * Version 0 variant of Avtp_Crf_GetTimestampInterval(). * @see Avtp_Crf_GetTimestampInterval */ -OPEN1722_INLINE uint16_t Avtp_Crf_GetTimestampInterval_V0(const Avtp_Crf_t *const pdu) +OPEN1722_INLINE uint16_t Avtp_Crf_GetTimestampInterval_V0(const Avtp_CrfV0_t *const pdu) { return (uint16_t)Avtp_Crf_GetField_V0(pdu, AVTP_CRF_FIELD_TIMESTAMP_INTERVAL); } @@ -1013,7 +1039,7 @@ OPEN1722_INLINE uint16_t Avtp_Crf_GetTimestampInterval_V1(const Avtp_CrfV1_t *co * Version 0 variant of Avtp_Crf_SetSv(). * @see Avtp_Crf_SetSv */ -OPEN1722_INLINE void Avtp_Crf_SetSv_V0(Avtp_Crf_t *pdu, bool sv) +OPEN1722_INLINE void Avtp_Crf_SetSv_V0(Avtp_CrfV0_t *pdu, bool sv) { Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_SV, sv); } @@ -1031,7 +1057,7 @@ OPEN1722_INLINE void Avtp_Crf_SetSv_V1(Avtp_CrfV1_t *pdu, bool sv) * Version 0 variant of Avtp_Crf_SetMr(). * @see Avtp_Crf_SetMr */ -OPEN1722_INLINE void Avtp_Crf_SetMr_V0(Avtp_Crf_t *pdu, bool mr) +OPEN1722_INLINE void Avtp_Crf_SetMr_V0(Avtp_CrfV0_t *pdu, bool mr) { Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_MR, mr); } @@ -1049,7 +1075,7 @@ OPEN1722_INLINE void Avtp_Crf_SetMr_V1(Avtp_CrfV1_t *pdu, bool mr) * Version 0 variant of Avtp_Crf_SetFs(). * @see Avtp_Crf_SetFs */ -OPEN1722_INLINE void Avtp_Crf_SetFs_V0(Avtp_Crf_t *pdu, bool fs) +OPEN1722_INLINE void Avtp_Crf_SetFs_V0(Avtp_CrfV0_t *pdu, bool fs) { Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_FS, fs); } @@ -1067,7 +1093,7 @@ OPEN1722_INLINE void Avtp_Crf_SetFs_V1(Avtp_CrfV1_t *pdu, bool fs) * Version 0 variant of Avtp_Crf_SetTu(). * @see Avtp_Crf_SetTu */ -OPEN1722_INLINE void Avtp_Crf_SetTu_V0(Avtp_Crf_t *pdu, bool tu) +OPEN1722_INLINE void Avtp_Crf_SetTu_V0(Avtp_CrfV0_t *pdu, bool tu) { Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_TU, tu); } @@ -1086,7 +1112,7 @@ OPEN1722_INLINE void Avtp_Crf_SetTu_V1(Avtp_CrfV1_t *pdu, bool tu) * 8-bit version 0 sequence_num_lsb field. * @see Avtp_Crf_SetSequenceNum */ -OPEN1722_INLINE void Avtp_Crf_SetSequenceNum_V0(Avtp_Crf_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Crf_SetSequenceNum_V0(Avtp_CrfV0_t *pdu, uint32_t value) { Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); } @@ -1107,7 +1133,7 @@ OPEN1722_INLINE void Avtp_Crf_SetSequenceNum_V1(Avtp_CrfV1_t *pdu, uint32_t valu * absent from version 0, so this is a no-op. * @see Avtp_Crf_SetPtpGrandmasterIdentity */ -OPEN1722_INLINE void Avtp_Crf_SetPtpGrandmasterIdentity_V0(Avtp_Crf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Crf_SetPtpGrandmasterIdentity_V0(Avtp_CrfV0_t *pdu, uint64_t value) { Avtp_AlternativeHeader_SetPtpGrandmasterIdentity_V0((Avtp_AlternativeHeader_t *)pdu, value); } @@ -1125,7 +1151,7 @@ OPEN1722_INLINE void Avtp_Crf_SetPtpGrandmasterIdentity_V1(Avtp_CrfV1_t *pdu, ui * Version 0 variant of Avtp_Crf_SetType(). * @see Avtp_Crf_SetType */ -OPEN1722_INLINE void Avtp_Crf_SetType_V0(Avtp_Crf_t *pdu, Avtp_CrfType_t value) +OPEN1722_INLINE void Avtp_Crf_SetType_V0(Avtp_CrfV0_t *pdu, Avtp_CrfType_t value) { Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_TYPE, (uint64_t)value); } @@ -1143,7 +1169,7 @@ OPEN1722_INLINE void Avtp_Crf_SetType_V1(Avtp_CrfV1_t *pdu, Avtp_CrfType_t value * Version 0 variant of Avtp_Crf_SetStreamId(). * @see Avtp_Crf_SetStreamId */ -OPEN1722_INLINE void Avtp_Crf_SetStreamId_V0(Avtp_Crf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Crf_SetStreamId_V0(Avtp_CrfV0_t *pdu, uint64_t value) { Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_STREAM_ID, value); } @@ -1161,7 +1187,7 @@ OPEN1722_INLINE void Avtp_Crf_SetStreamId_V1(Avtp_CrfV1_t *pdu, uint64_t value) * Version 0 variant of Avtp_Crf_SetPull(). * @see Avtp_Crf_SetPull */ -OPEN1722_INLINE void Avtp_Crf_SetPull_V0(Avtp_Crf_t *pdu, Avtp_CrfPull_t value) +OPEN1722_INLINE void Avtp_Crf_SetPull_V0(Avtp_CrfV0_t *pdu, Avtp_CrfPull_t value) { Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_PULL, (uint64_t)value); } @@ -1179,7 +1205,7 @@ OPEN1722_INLINE void Avtp_Crf_SetPull_V1(Avtp_CrfV1_t *pdu, Avtp_CrfPull_t value * Version 0 variant of Avtp_Crf_SetBaseFrequency(). * @see Avtp_Crf_SetBaseFrequency */ -OPEN1722_INLINE void Avtp_Crf_SetBaseFrequency_V0(Avtp_Crf_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Crf_SetBaseFrequency_V0(Avtp_CrfV0_t *pdu, uint32_t value) { Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_BASE_FREQUENCY, value); } @@ -1197,7 +1223,7 @@ OPEN1722_INLINE void Avtp_Crf_SetBaseFrequency_V1(Avtp_CrfV1_t *pdu, uint32_t va * Version 0 variant of Avtp_Crf_SetCrfDataLength(). * @see Avtp_Crf_SetCrfDataLength */ -OPEN1722_INLINE void Avtp_Crf_SetCrfDataLength_V0(Avtp_Crf_t *pdu, uint16_t value) +OPEN1722_INLINE void Avtp_Crf_SetCrfDataLength_V0(Avtp_CrfV0_t *pdu, uint16_t value) { Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_CRF_DATA_LENGTH, value); } @@ -1215,7 +1241,7 @@ OPEN1722_INLINE void Avtp_Crf_SetCrfDataLength_V1(Avtp_CrfV1_t *pdu, uint16_t va * Version 0 variant of Avtp_Crf_SetTimestampInterval(). * @see Avtp_Crf_SetTimestampInterval */ -OPEN1722_INLINE void Avtp_Crf_SetTimestampInterval_V0(Avtp_Crf_t *pdu, uint16_t value) +OPEN1722_INLINE void Avtp_Crf_SetTimestampInterval_V0(Avtp_CrfV0_t *pdu, uint16_t value) { Avtp_Crf_SetField_V0(pdu, AVTP_CRF_FIELD_TIMESTAMP_INTERVAL, value); } diff --git a/include/avtp/Rvf.h b/include/avtp/Rvf.h index 9d324219..66be322c 100644 --- a/include/avtp/Rvf.h +++ b/include/avtp/Rvf.h @@ -72,13 +72,20 @@ extern "C" { typedef struct { uint8_t header[AVTP_RVF_HEADER_LEN_V0]; uint8_t payload[0]; -} __attribute__((packed)) Avtp_Rvf_t; +} __attribute__((packed)) Avtp_RvfV0_t; typedef struct { uint8_t header[AVTP_RVF_HEADER_LEN_V1]; uint8_t payload[0]; } __attribute__((packed)) Avtp_RvfV1_t; +/** + * Version-agnostic handle for RVF PDUs. It is an alias of the version 0 + * layout and is the pointer type of the version-agnostic accessors; version 1 + * PDUs use Avtp_RvfV1_t. For version 0 use Avtp_RvfV0_t. + */ +typedef Avtp_RvfV0_t Avtp_Rvf_t; + typedef enum Avtp_RvfPixelDepth { AVTP_RVF_PIXEL_DEPTH_8 = 0x01, AVTP_RVF_PIXEL_DEPTH_10 = 0x02, @@ -241,7 +248,7 @@ static const Avtp_FieldDescriptor_t Avtp_RvfFieldDescV1[AVTP_RVF_FIELD_MAX] = { * @returns This function returns the value of the field. * @see Avtp_Rvf_GetField */ -OPEN1722_INLINE uint64_t Avtp_Rvf_GetField_V0(const Avtp_Rvf_t *const pdu, Avtp_RvfFields_t field) +OPEN1722_INLINE uint64_t Avtp_Rvf_GetField_V0(const Avtp_RvfV0_t *const pdu, Avtp_RvfFields_t field) { return Avtp_GetField(Avtp_RvfFieldDescV0, AVTP_RVF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); @@ -287,7 +294,7 @@ OPEN1722_INLINE uint64_t Avtp_Rvf_GetField(const Avtp_Rvf_t *const pdu, Avtp_Rvf * @param value The value to set. * @see Avtp_Rvf_SetField */ -OPEN1722_INLINE void Avtp_Rvf_SetField_V0(Avtp_Rvf_t *pdu, Avtp_RvfFields_t field, uint64_t value) +OPEN1722_INLINE void Avtp_Rvf_SetField_V0(Avtp_RvfV0_t *pdu, Avtp_RvfFields_t field, uint64_t value) { Avtp_SetField(Avtp_RvfFieldDescV0, AVTP_RVF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); } @@ -329,7 +336,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetField(Avtp_Rvf_t *pdu, Avtp_RvfFields_t field, * pointer is not read; it keeps the signature aligned with the * version-dispatched accessors. */ -OPEN1722_INLINE uint8_t Avtp_Rvf_GetHeaderLen_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Rvf_GetHeaderLen_V0(const Avtp_RvfV0_t *const pdu) { (void)pdu; return (uint8_t)AVTP_RVF_HEADER_LEN_V0; @@ -753,7 +760,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetI(Avtp_Rvf_t *pdu, bool i) * @return Pointer to RVF stream data * @see Avtp_Rvf_GetPayload */ -OPEN1722_INLINE const uint8_t *Avtp_Rvf_GetPayload_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE const uint8_t *Avtp_Rvf_GetPayload_V0(const Avtp_RvfV0_t *const pdu) { return (const uint8_t *)pdu + AVTP_RVF_HEADER_LEN_V0; } @@ -796,7 +803,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Rvf_GetPayload(const Avtp_Rvf_t *const pdu) * @param payload_length Length of the payload * @see Avtp_Rvf_SetPayload */ -OPEN1722_INLINE void Avtp_Rvf_SetPayload_V0(Avtp_Rvf_t *pdu, uint8_t *payload, +OPEN1722_INLINE void Avtp_Rvf_SetPayload_V0(Avtp_RvfV0_t *pdu, uint8_t *payload, uint16_t payload_length) { memcpy((uint8_t *)pdu + AVTP_RVF_HEADER_LEN_V0, payload, payload_length); @@ -838,10 +845,10 @@ OPEN1722_INLINE void Avtp_Rvf_SetPayload(Avtp_Rvf_t *pdu, uint8_t *payload, uint * * @param pdu Pointer to the first bit of a 1722 RVF PDU. */ -OPEN1722_INLINE void Avtp_Rvf_Init(Avtp_Rvf_t *pdu) +OPEN1722_INLINE void Avtp_Rvf_InitV0(Avtp_RvfV0_t *pdu) { if (pdu != NULL) { - memset(pdu, 0, sizeof(Avtp_Rvf_t)); + memset(pdu, 0, sizeof(Avtp_RvfV0_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_RVF); Avtp_Rvf_SetSv(pdu, true); } @@ -863,6 +870,25 @@ OPEN1722_INLINE void Avtp_Rvf_InitV1(Avtp_RvfV1_t *pdu) } } +/** + * Initializes an RVF PDU of the given version. The caller must provide a + * buffer of at least AVTP_RVF_HEADER_LEN_V1 octets for version 1 (for + * example an Avtp_RvfV1_t); version 0 uses AVTP_RVF_HEADER_LEN_V0 + * octets. Any version other than AVTPDU_VERSION_1 initializes a version 0 PDU. + * + * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- + * or an ACF header. + * @param version AVTPDU header version (AVTPDU_VERSION_0 or AVTPDU_VERSION_1). + */ +OPEN1722_INLINE void Avtp_Rvf_Init(Avtp_Rvf_t *pdu, uint8_t version) +{ + if (version == AVTPDU_VERSION_1) { + Avtp_Rvf_InitV1((Avtp_RvfV1_t *)pdu); + } else { + Avtp_Rvf_InitV0(pdu); + } +} + /** * Checks if the RVF frame is valid by checking: * 1) that the subtype is RVF and the version is supported, @@ -1240,7 +1266,7 @@ OPEN1722_INLINE void Avtp_RvfRawHeader_SetField(Avtp_RvfRawHeader_t *pdu, * Version 0 variant of Avtp_Rvf_IsSv(). * @see Avtp_Rvf_IsSv */ -OPEN1722_INLINE bool Avtp_Rvf_IsSv_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Rvf_IsSv_V0(const Avtp_RvfV0_t *const pdu) { return Avtp_CommonStreamHeader_IsSv_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -1258,7 +1284,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsSv_V1(const Avtp_RvfV1_t *const pdu) * Version 0 variant of Avtp_Rvf_IsMr(). * @see Avtp_Rvf_IsMr */ -OPEN1722_INLINE bool Avtp_Rvf_IsMr_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Rvf_IsMr_V0(const Avtp_RvfV0_t *const pdu) { return Avtp_CommonStreamHeader_IsMr_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -1276,7 +1302,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsMr_V1(const Avtp_RvfV1_t *const pdu) * Version 0 variant of Avtp_Rvf_IsTv(). * @see Avtp_Rvf_IsTv */ -OPEN1722_INLINE bool Avtp_Rvf_IsTv_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Rvf_IsTv_V0(const Avtp_RvfV0_t *const pdu) { return Avtp_CommonStreamHeader_IsTv_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -1294,7 +1320,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsTv_V1(const Avtp_RvfV1_t *const pdu) * Version 0 variant of Avtp_Rvf_IsTu(). * @see Avtp_Rvf_IsTu */ -OPEN1722_INLINE bool Avtp_Rvf_IsTu_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Rvf_IsTu_V0(const Avtp_RvfV0_t *const pdu) { return Avtp_CommonStreamHeader_IsTu_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -1313,7 +1339,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsTu_V1(const Avtp_RvfV1_t *const pdu) * 8-bit version 0 field width. * @see Avtp_Rvf_GetSequenceNum */ -OPEN1722_INLINE uint32_t Avtp_Rvf_GetSequenceNum_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Rvf_GetSequenceNum_V0(const Avtp_RvfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetSequenceNum_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -1331,7 +1357,7 @@ OPEN1722_INLINE uint32_t Avtp_Rvf_GetSequenceNum_V1(const Avtp_RvfV1_t *const pd * Version 0 variant of Avtp_Rvf_GetStreamId(). * @see Avtp_Rvf_GetStreamId */ -OPEN1722_INLINE uint64_t Avtp_Rvf_GetStreamId_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Rvf_GetStreamId_V0(const Avtp_RvfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetStreamId_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -1349,7 +1375,7 @@ OPEN1722_INLINE uint64_t Avtp_Rvf_GetStreamId_V1(const Avtp_RvfV1_t *const pdu) * Version 0 variant of Avtp_Rvf_GetAvtpTimestamp(). * @see Avtp_Rvf_GetAvtpTimestamp */ -OPEN1722_INLINE uint64_t Avtp_Rvf_GetAvtpTimestamp_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Rvf_GetAvtpTimestamp_V0(const Avtp_RvfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetAvtpTimestamp_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -1368,7 +1394,7 @@ OPEN1722_INLINE uint64_t Avtp_Rvf_GetAvtpTimestamp_V1(const Avtp_RvfV1_t *const * absent from version 0, so this always returns 0. * @see Avtp_Rvf_GetPtpGrandmasterIdentity */ -OPEN1722_INLINE uint64_t Avtp_Rvf_GetPtpGrandmasterIdentity_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Rvf_GetPtpGrandmasterIdentity_V0(const Avtp_RvfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V0( (const Avtp_CommonStreamHeader_t *)pdu); @@ -1388,7 +1414,7 @@ OPEN1722_INLINE uint64_t Avtp_Rvf_GetPtpGrandmasterIdentity_V1(const Avtp_RvfV1_ * Version 0 variant of Avtp_Rvf_GetStreamDataLength(). * @see Avtp_Rvf_GetStreamDataLength */ -OPEN1722_INLINE uint16_t Avtp_Rvf_GetStreamDataLength_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE uint16_t Avtp_Rvf_GetStreamDataLength_V0(const Avtp_RvfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetStreamDataLength_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -1406,7 +1432,7 @@ OPEN1722_INLINE uint16_t Avtp_Rvf_GetStreamDataLength_V1(const Avtp_RvfV1_t *con * Version 0 variant of Avtp_Rvf_GetActivePixels(). * @see Avtp_Rvf_GetActivePixels */ -OPEN1722_INLINE uint16_t Avtp_Rvf_GetActivePixels_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE uint16_t Avtp_Rvf_GetActivePixels_V0(const Avtp_RvfV0_t *const pdu) { return (uint16_t)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_ACTIVE_PIXELS); } @@ -1424,7 +1450,7 @@ OPEN1722_INLINE uint16_t Avtp_Rvf_GetActivePixels_V1(const Avtp_RvfV1_t *const p * Version 0 variant of Avtp_Rvf_GetTotalLines(). * @see Avtp_Rvf_GetTotalLines */ -OPEN1722_INLINE uint16_t Avtp_Rvf_GetTotalLines_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE uint16_t Avtp_Rvf_GetTotalLines_V0(const Avtp_RvfV0_t *const pdu) { return (uint16_t)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_TOTAL_LINES); } @@ -1442,7 +1468,7 @@ OPEN1722_INLINE uint16_t Avtp_Rvf_GetTotalLines_V1(const Avtp_RvfV1_t *const pdu * Version 0 variant of Avtp_Rvf_IsAp(). * @see Avtp_Rvf_IsAp */ -OPEN1722_INLINE bool Avtp_Rvf_IsAp_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Rvf_IsAp_V0(const Avtp_RvfV0_t *const pdu) { return (bool)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_AP); } @@ -1460,7 +1486,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsAp_V1(const Avtp_RvfV1_t *const pdu) * Version 0 variant of Avtp_Rvf_IsF(). * @see Avtp_Rvf_IsF */ -OPEN1722_INLINE bool Avtp_Rvf_IsF_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Rvf_IsF_V0(const Avtp_RvfV0_t *const pdu) { return (bool)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_F); } @@ -1478,7 +1504,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsF_V1(const Avtp_RvfV1_t *const pdu) * Version 0 variant of Avtp_Rvf_IsEf(). * @see Avtp_Rvf_IsEf */ -OPEN1722_INLINE bool Avtp_Rvf_IsEf_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Rvf_IsEf_V0(const Avtp_RvfV0_t *const pdu) { return (bool)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_EF); } @@ -1496,7 +1522,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsEf_V1(const Avtp_RvfV1_t *const pdu) * Version 0 variant of Avtp_Rvf_GetEvt(). * @see Avtp_Rvf_GetEvt */ -OPEN1722_INLINE uint8_t Avtp_Rvf_GetEvt_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Rvf_GetEvt_V0(const Avtp_RvfV0_t *const pdu) { return (uint8_t)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_EVT); } @@ -1514,7 +1540,7 @@ OPEN1722_INLINE uint8_t Avtp_Rvf_GetEvt_V1(const Avtp_RvfV1_t *const pdu) * Version 0 variant of Avtp_Rvf_IsPd(). * @see Avtp_Rvf_IsPd */ -OPEN1722_INLINE bool Avtp_Rvf_IsPd_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Rvf_IsPd_V0(const Avtp_RvfV0_t *const pdu) { return (bool)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_PD); } @@ -1532,7 +1558,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsPd_V1(const Avtp_RvfV1_t *const pdu) * Version 0 variant of Avtp_Rvf_IsI(). * @see Avtp_Rvf_IsI */ -OPEN1722_INLINE bool Avtp_Rvf_IsI_V0(const Avtp_Rvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Rvf_IsI_V0(const Avtp_RvfV0_t *const pdu) { return (bool)Avtp_Rvf_GetField_V0(pdu, AVTP_RVF_FIELD_I); } @@ -1550,7 +1576,7 @@ OPEN1722_INLINE bool Avtp_Rvf_IsI_V1(const Avtp_RvfV1_t *const pdu) * Version 0 variant of Avtp_Rvf_SetSv(). * @see Avtp_Rvf_SetSv */ -OPEN1722_INLINE void Avtp_Rvf_SetSv_V0(Avtp_Rvf_t *pdu, bool sv) +OPEN1722_INLINE void Avtp_Rvf_SetSv_V0(Avtp_RvfV0_t *pdu, bool sv) { Avtp_CommonStreamHeader_SetSv_V0((Avtp_CommonStreamHeader_t *)pdu, sv); } @@ -1568,7 +1594,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetSv_V1(Avtp_RvfV1_t *pdu, bool sv) * Version 0 variant of Avtp_Rvf_SetMr(). * @see Avtp_Rvf_SetMr */ -OPEN1722_INLINE void Avtp_Rvf_SetMr_V0(Avtp_Rvf_t *pdu, bool mr) +OPEN1722_INLINE void Avtp_Rvf_SetMr_V0(Avtp_RvfV0_t *pdu, bool mr) { Avtp_CommonStreamHeader_SetMr_V0((Avtp_CommonStreamHeader_t *)pdu, mr); } @@ -1586,7 +1612,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetMr_V1(Avtp_RvfV1_t *pdu, bool mr) * Version 0 variant of Avtp_Rvf_SetTv(). * @see Avtp_Rvf_SetTv */ -OPEN1722_INLINE void Avtp_Rvf_SetTv_V0(Avtp_Rvf_t *pdu, bool tv) +OPEN1722_INLINE void Avtp_Rvf_SetTv_V0(Avtp_RvfV0_t *pdu, bool tv) { Avtp_CommonStreamHeader_SetTv_V0((Avtp_CommonStreamHeader_t *)pdu, tv); } @@ -1604,7 +1630,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetTv_V1(Avtp_RvfV1_t *pdu, bool tv) * Version 0 variant of Avtp_Rvf_SetTu(). * @see Avtp_Rvf_SetTu */ -OPEN1722_INLINE void Avtp_Rvf_SetTu_V0(Avtp_Rvf_t *pdu, bool tu) +OPEN1722_INLINE void Avtp_Rvf_SetTu_V0(Avtp_RvfV0_t *pdu, bool tu) { Avtp_CommonStreamHeader_SetTu_V0((Avtp_CommonStreamHeader_t *)pdu, tu); } @@ -1623,7 +1649,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetTu_V1(Avtp_RvfV1_t *pdu, bool tu) * 8-bit version 0 field width. * @see Avtp_Rvf_SetSequenceNum */ -OPEN1722_INLINE void Avtp_Rvf_SetSequenceNum_V0(Avtp_Rvf_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Rvf_SetSequenceNum_V0(Avtp_RvfV0_t *pdu, uint32_t value) { Avtp_CommonStreamHeader_SetSequenceNum_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1641,7 +1667,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetSequenceNum_V1(Avtp_RvfV1_t *pdu, uint32_t valu * Version 0 variant of Avtp_Rvf_SetStreamId(). * @see Avtp_Rvf_SetStreamId */ -OPEN1722_INLINE void Avtp_Rvf_SetStreamId_V0(Avtp_Rvf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Rvf_SetStreamId_V0(Avtp_RvfV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetStreamId_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1659,7 +1685,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetStreamId_V1(Avtp_RvfV1_t *pdu, uint64_t value) * Version 0 variant of Avtp_Rvf_SetAvtpTimestamp(). * @see Avtp_Rvf_SetAvtpTimestamp */ -OPEN1722_INLINE void Avtp_Rvf_SetAvtpTimestamp_V0(Avtp_Rvf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Rvf_SetAvtpTimestamp_V0(Avtp_RvfV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetAvtpTimestamp_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1678,7 +1704,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetAvtpTimestamp_V1(Avtp_RvfV1_t *pdu, uint64_t va * absent from version 0, so this is a no-op. * @see Avtp_Rvf_SetPtpGrandmasterIdentity */ -OPEN1722_INLINE void Avtp_Rvf_SetPtpGrandmasterIdentity_V0(Avtp_Rvf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Rvf_SetPtpGrandmasterIdentity_V0(Avtp_RvfV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1696,7 +1722,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetPtpGrandmasterIdentity_V1(Avtp_RvfV1_t *pdu, ui * Version 0 variant of Avtp_Rvf_SetStreamDataLength(). * @see Avtp_Rvf_SetStreamDataLength */ -OPEN1722_INLINE void Avtp_Rvf_SetStreamDataLength_V0(Avtp_Rvf_t *pdu, uint16_t value) +OPEN1722_INLINE void Avtp_Rvf_SetStreamDataLength_V0(Avtp_RvfV0_t *pdu, uint16_t value) { Avtp_CommonStreamHeader_SetStreamDataLength_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1714,7 +1740,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetStreamDataLength_V1(Avtp_RvfV1_t *pdu, uint16_t * Version 0 variant of Avtp_Rvf_SetActivePixels(). * @see Avtp_Rvf_SetActivePixels */ -OPEN1722_INLINE void Avtp_Rvf_SetActivePixels_V0(Avtp_Rvf_t *pdu, uint16_t value) +OPEN1722_INLINE void Avtp_Rvf_SetActivePixels_V0(Avtp_RvfV0_t *pdu, uint16_t value) { Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_ACTIVE_PIXELS, value); } @@ -1732,7 +1758,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetActivePixels_V1(Avtp_RvfV1_t *pdu, uint16_t val * Version 0 variant of Avtp_Rvf_SetTotalLines(). * @see Avtp_Rvf_SetTotalLines */ -OPEN1722_INLINE void Avtp_Rvf_SetTotalLines_V0(Avtp_Rvf_t *pdu, uint16_t value) +OPEN1722_INLINE void Avtp_Rvf_SetTotalLines_V0(Avtp_RvfV0_t *pdu, uint16_t value) { Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_TOTAL_LINES, value); } @@ -1750,7 +1776,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetTotalLines_V1(Avtp_RvfV1_t *pdu, uint16_t value * Version 0 variant of Avtp_Rvf_SetAp(). * @see Avtp_Rvf_SetAp */ -OPEN1722_INLINE void Avtp_Rvf_SetAp_V0(Avtp_Rvf_t *pdu, bool ap) +OPEN1722_INLINE void Avtp_Rvf_SetAp_V0(Avtp_RvfV0_t *pdu, bool ap) { Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_AP, ap); } @@ -1768,7 +1794,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetAp_V1(Avtp_RvfV1_t *pdu, bool ap) * Version 0 variant of Avtp_Rvf_SetF(). * @see Avtp_Rvf_SetF */ -OPEN1722_INLINE void Avtp_Rvf_SetF_V0(Avtp_Rvf_t *pdu, bool f) +OPEN1722_INLINE void Avtp_Rvf_SetF_V0(Avtp_RvfV0_t *pdu, bool f) { Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_F, f); } @@ -1786,7 +1812,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetF_V1(Avtp_RvfV1_t *pdu, bool f) * Version 0 variant of Avtp_Rvf_SetEf(). * @see Avtp_Rvf_SetEf */ -OPEN1722_INLINE void Avtp_Rvf_SetEf_V0(Avtp_Rvf_t *pdu, bool ef) +OPEN1722_INLINE void Avtp_Rvf_SetEf_V0(Avtp_RvfV0_t *pdu, bool ef) { Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_EF, ef); } @@ -1804,7 +1830,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetEf_V1(Avtp_RvfV1_t *pdu, bool ef) * Version 0 variant of Avtp_Rvf_SetEvt(). * @see Avtp_Rvf_SetEvt */ -OPEN1722_INLINE void Avtp_Rvf_SetEvt_V0(Avtp_Rvf_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Rvf_SetEvt_V0(Avtp_RvfV0_t *pdu, uint8_t value) { Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_EVT, value); } @@ -1822,7 +1848,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetEvt_V1(Avtp_RvfV1_t *pdu, uint8_t value) * Version 0 variant of Avtp_Rvf_SetPd(). * @see Avtp_Rvf_SetPd */ -OPEN1722_INLINE void Avtp_Rvf_SetPd_V0(Avtp_Rvf_t *pdu, bool pd) +OPEN1722_INLINE void Avtp_Rvf_SetPd_V0(Avtp_RvfV0_t *pdu, bool pd) { Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_PD, pd); } @@ -1840,7 +1866,7 @@ OPEN1722_INLINE void Avtp_Rvf_SetPd_V1(Avtp_RvfV1_t *pdu, bool pd) * Version 0 variant of Avtp_Rvf_SetI(). * @see Avtp_Rvf_SetI */ -OPEN1722_INLINE void Avtp_Rvf_SetI_V0(Avtp_Rvf_t *pdu, bool i) +OPEN1722_INLINE void Avtp_Rvf_SetI_V0(Avtp_RvfV0_t *pdu, bool i) { Avtp_Rvf_SetField_V0(pdu, AVTP_RVF_FIELD_I, i); } diff --git a/include/avtp/aaf/Aaf.h b/include/avtp/aaf/Aaf.h index 3b4bafdb..ccdfcc05 100644 --- a/include/avtp/aaf/Aaf.h +++ b/include/avtp/aaf/Aaf.h @@ -69,13 +69,20 @@ extern "C" { typedef struct { uint8_t header[AVTP_AAF_HEADER_LEN_V0]; uint8_t payload[0]; -} __attribute__((packed)) Avtp_Aaf_t; +} __attribute__((packed)) Avtp_AafV0_t; typedef struct { uint8_t header[AVTP_AAF_HEADER_LEN_V1]; uint8_t payload[0]; } __attribute__((packed)) Avtp_AafV1_t; +/** + * Version-agnostic handle for AAF PDUs. It is an alias of the version 0 + * layout and is the pointer type of the version-agnostic accessors; version 1 + * PDUs use Avtp_AafV1_t. For version 0 use Avtp_AafV0_t. + */ +typedef Avtp_AafV0_t Avtp_Aaf_t; + /** * AAF 'format' field values (IEEE 1722-2025, Table 10). Values 0x06-0xFF are * reserved. @@ -186,7 +193,7 @@ static const Avtp_FieldDescriptor_t Avtp_AafFieldDescV1[AVTP_AAF_FIELD_MAX] = { * @returns This function returns the value of the field. * @see Avtp_Aaf_GetField */ -OPEN1722_INLINE uint64_t Avtp_Aaf_GetField_V0(const Avtp_Aaf_t *const pdu, Avtp_AafFields_t field) +OPEN1722_INLINE uint64_t Avtp_Aaf_GetField_V0(const Avtp_AafV0_t *const pdu, Avtp_AafFields_t field) { return Avtp_GetField(Avtp_AafFieldDescV0, AVTP_AAF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); @@ -232,7 +239,7 @@ OPEN1722_INLINE uint64_t Avtp_Aaf_GetField(const Avtp_Aaf_t *const pdu, Avtp_Aaf * @param value The value to set. * @see Avtp_Aaf_SetField */ -OPEN1722_INLINE void Avtp_Aaf_SetField_V0(Avtp_Aaf_t *pdu, Avtp_AafFields_t field, uint64_t value) +OPEN1722_INLINE void Avtp_Aaf_SetField_V0(Avtp_AafV0_t *pdu, Avtp_AafFields_t field, uint64_t value) { Avtp_SetField(Avtp_AafFieldDescV0, AVTP_AAF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); } @@ -274,7 +281,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetField(Avtp_Aaf_t *pdu, Avtp_AafFields_t field, * pointer is not read; it keeps the signature aligned with the * version-dispatched accessors. */ -OPEN1722_INLINE uint8_t Avtp_Aaf_GetHeaderLen_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Aaf_GetHeaderLen_V0(const Avtp_AafV0_t *const pdu) { (void)pdu; return (uint8_t)AVTP_AAF_HEADER_LEN_V0; @@ -654,7 +661,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData2(Avtp_Aaf_t *pdu, uint8_t * @return Pointer to AAF frame payload * @see Avtp_Aaf_GetPayload */ -OPEN1722_INLINE const uint8_t *Avtp_Aaf_GetPayload_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE const uint8_t *Avtp_Aaf_GetPayload_V0(const Avtp_AafV0_t *const pdu) { return (const uint8_t *)pdu + AVTP_AAF_HEADER_LEN_V0; } @@ -694,7 +701,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Aaf_GetPayload(const Avtp_Aaf_t *const pdu) * @param payload_length Length of the payload * @see Avtp_Aaf_SetPayload */ -OPEN1722_INLINE void Avtp_Aaf_SetPayload_V0(Avtp_Aaf_t *pdu, uint8_t *payload, +OPEN1722_INLINE void Avtp_Aaf_SetPayload_V0(Avtp_AafV0_t *pdu, uint8_t *payload, uint16_t payload_length) { memcpy((uint8_t *)pdu + AVTP_AAF_HEADER_LEN_V0, payload, payload_length); @@ -736,10 +743,10 @@ OPEN1722_INLINE void Avtp_Aaf_SetPayload(Avtp_Aaf_t *pdu, uint8_t *payload, uint * * @param pdu Pointer to the first bit of a 1722 AAF PDU. */ -OPEN1722_INLINE void Avtp_Aaf_Init(Avtp_Aaf_t *pdu) +OPEN1722_INLINE void Avtp_Aaf_InitV0(Avtp_AafV0_t *pdu) { if (pdu != NULL) { - memset(pdu, 0, sizeof(Avtp_Aaf_t)); + memset(pdu, 0, sizeof(Avtp_AafV0_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_AAF); Avtp_Aaf_SetSv(pdu, true); } @@ -802,6 +809,25 @@ OPEN1722_INLINE bool Avtp_Aaf_IsValid(const Avtp_Aaf_t *const pdu, size_t buffer return true; } +/** + * Initializes an AAF PDU of the given version. The caller must provide a + * buffer of at least AVTP_AAF_HEADER_LEN_V1 octets for version 1 (for + * example an Avtp_AafV1_t); version 0 uses AVTP_AAF_HEADER_LEN_V0 + * octets. Any version other than AVTPDU_VERSION_1 initializes a version 0 PDU. + * + * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- + * or an ACF header. + * @param version AVTPDU header version (AVTPDU_VERSION_0 or AVTPDU_VERSION_1). + */ +OPEN1722_INLINE void Avtp_Aaf_Init(Avtp_Aaf_t *pdu, uint8_t version) +{ + if (version == AVTPDU_VERSION_1) { + Avtp_Aaf_InitV1((Avtp_AafV1_t *)pdu); + } else { + Avtp_Aaf_InitV0(pdu); + } +} + /* * Version-typed named accessors. These select the field layout for one * explicit version and never read the version field; the version-dispatched @@ -814,7 +840,7 @@ OPEN1722_INLINE bool Avtp_Aaf_IsValid(const Avtp_Aaf_t *const pdu, size_t buffer * Version 0 variant of Avtp_Aaf_IsSv(). * @see Avtp_Aaf_IsSv */ -OPEN1722_INLINE bool Avtp_Aaf_IsSv_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE bool Avtp_Aaf_IsSv_V0(const Avtp_AafV0_t *const pdu) { return Avtp_CommonStreamHeader_IsSv_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -832,7 +858,7 @@ OPEN1722_INLINE bool Avtp_Aaf_IsSv_V1(const Avtp_AafV1_t *const pdu) * Version 0 variant of Avtp_Aaf_IsMr(). * @see Avtp_Aaf_IsMr */ -OPEN1722_INLINE bool Avtp_Aaf_IsMr_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE bool Avtp_Aaf_IsMr_V0(const Avtp_AafV0_t *const pdu) { return Avtp_CommonStreamHeader_IsMr_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -850,7 +876,7 @@ OPEN1722_INLINE bool Avtp_Aaf_IsMr_V1(const Avtp_AafV1_t *const pdu) * Version 0 variant of Avtp_Aaf_IsTv(). * @see Avtp_Aaf_IsTv */ -OPEN1722_INLINE bool Avtp_Aaf_IsTv_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE bool Avtp_Aaf_IsTv_V0(const Avtp_AafV0_t *const pdu) { return Avtp_CommonStreamHeader_IsTv_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -868,7 +894,7 @@ OPEN1722_INLINE bool Avtp_Aaf_IsTv_V1(const Avtp_AafV1_t *const pdu) * Version 0 variant of Avtp_Aaf_IsTu(). * @see Avtp_Aaf_IsTu */ -OPEN1722_INLINE bool Avtp_Aaf_IsTu_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE bool Avtp_Aaf_IsTu_V0(const Avtp_AafV0_t *const pdu) { return Avtp_CommonStreamHeader_IsTu_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -887,7 +913,7 @@ OPEN1722_INLINE bool Avtp_Aaf_IsTu_V1(const Avtp_AafV1_t *const pdu) * 8-bit version 0 field width. * @see Avtp_Aaf_GetSequenceNum */ -OPEN1722_INLINE uint32_t Avtp_Aaf_GetSequenceNum_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Aaf_GetSequenceNum_V0(const Avtp_AafV0_t *const pdu) { return Avtp_CommonStreamHeader_GetSequenceNum_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -905,7 +931,7 @@ OPEN1722_INLINE uint32_t Avtp_Aaf_GetSequenceNum_V1(const Avtp_AafV1_t *const pd * Version 0 variant of Avtp_Aaf_GetStreamId(). * @see Avtp_Aaf_GetStreamId */ -OPEN1722_INLINE uint64_t Avtp_Aaf_GetStreamId_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Aaf_GetStreamId_V0(const Avtp_AafV0_t *const pdu) { return Avtp_CommonStreamHeader_GetStreamId_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -923,7 +949,7 @@ OPEN1722_INLINE uint64_t Avtp_Aaf_GetStreamId_V1(const Avtp_AafV1_t *const pdu) * Version 0 variant of Avtp_Aaf_GetAvtpTimestamp(). * @see Avtp_Aaf_GetAvtpTimestamp */ -OPEN1722_INLINE uint64_t Avtp_Aaf_GetAvtpTimestamp_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Aaf_GetAvtpTimestamp_V0(const Avtp_AafV0_t *const pdu) { return Avtp_CommonStreamHeader_GetAvtpTimestamp_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -942,7 +968,7 @@ OPEN1722_INLINE uint64_t Avtp_Aaf_GetAvtpTimestamp_V1(const Avtp_AafV1_t *const * absent from version 0, so this always returns 0. * @see Avtp_Aaf_GetPtpGrandmasterIdentity */ -OPEN1722_INLINE uint64_t Avtp_Aaf_GetPtpGrandmasterIdentity_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Aaf_GetPtpGrandmasterIdentity_V0(const Avtp_AafV0_t *const pdu) { return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V0( (const Avtp_CommonStreamHeader_t *)pdu); @@ -962,7 +988,7 @@ OPEN1722_INLINE uint64_t Avtp_Aaf_GetPtpGrandmasterIdentity_V1(const Avtp_AafV1_ * Version 0 variant of Avtp_Aaf_GetFormat(). * @see Avtp_Aaf_GetFormat */ -OPEN1722_INLINE Avtp_AafFormat_t Avtp_Aaf_GetFormat_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE Avtp_AafFormat_t Avtp_Aaf_GetFormat_V0(const Avtp_AafV0_t *const pdu) { return (Avtp_AafFormat_t)Avtp_Aaf_GetField_V0(pdu, AVTP_AAF_FIELD_FORMAT); } @@ -980,7 +1006,7 @@ OPEN1722_INLINE Avtp_AafFormat_t Avtp_Aaf_GetFormat_V1(const Avtp_AafV1_t *const * Version 0 variant of Avtp_Aaf_GetAafFormatSpecificData1(). * @see Avtp_Aaf_GetAafFormatSpecificData1 */ -OPEN1722_INLINE uint32_t Avtp_Aaf_GetAafFormatSpecificData1_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Aaf_GetAafFormatSpecificData1_V0(const Avtp_AafV0_t *const pdu) { return (uint32_t)Avtp_Aaf_GetField_V0(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1); } @@ -998,7 +1024,7 @@ OPEN1722_INLINE uint32_t Avtp_Aaf_GetAafFormatSpecificData1_V1(const Avtp_AafV1_ * Version 0 variant of Avtp_Aaf_GetStreamDataLength(). * @see Avtp_Aaf_GetStreamDataLength */ -OPEN1722_INLINE uint16_t Avtp_Aaf_GetStreamDataLength_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE uint16_t Avtp_Aaf_GetStreamDataLength_V0(const Avtp_AafV0_t *const pdu) { return Avtp_CommonStreamHeader_GetStreamDataLength_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -1016,7 +1042,7 @@ OPEN1722_INLINE uint16_t Avtp_Aaf_GetStreamDataLength_V1(const Avtp_AafV1_t *con * Version 0 variant of Avtp_Aaf_GetAfsd(). * @see Avtp_Aaf_GetAfsd */ -OPEN1722_INLINE uint8_t Avtp_Aaf_GetAfsd_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Aaf_GetAfsd_V0(const Avtp_AafV0_t *const pdu) { return (uint8_t)Avtp_Aaf_GetField_V0(pdu, AVTP_AAF_FIELD_AFSD); } @@ -1034,7 +1060,7 @@ OPEN1722_INLINE uint8_t Avtp_Aaf_GetAfsd_V1(const Avtp_AafV1_t *const pdu) * Version 0 variant of Avtp_Aaf_IsSp(). * @see Avtp_Aaf_IsSp */ -OPEN1722_INLINE bool Avtp_Aaf_IsSp_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE bool Avtp_Aaf_IsSp_V0(const Avtp_AafV0_t *const pdu) { return (bool)Avtp_Aaf_GetField_V0(pdu, AVTP_AAF_FIELD_SP); } @@ -1052,7 +1078,7 @@ OPEN1722_INLINE bool Avtp_Aaf_IsSp_V1(const Avtp_AafV1_t *const pdu) * Version 0 variant of Avtp_Aaf_GetEvt(). * @see Avtp_Aaf_GetEvt */ -OPEN1722_INLINE uint8_t Avtp_Aaf_GetEvt_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Aaf_GetEvt_V0(const Avtp_AafV0_t *const pdu) { return (uint8_t)Avtp_Aaf_GetField_V0(pdu, AVTP_AAF_FIELD_EVT); } @@ -1070,7 +1096,7 @@ OPEN1722_INLINE uint8_t Avtp_Aaf_GetEvt_V1(const Avtp_AafV1_t *const pdu) * Version 0 variant of Avtp_Aaf_GetAafFormatSpecificData2(). * @see Avtp_Aaf_GetAafFormatSpecificData2 */ -OPEN1722_INLINE uint8_t Avtp_Aaf_GetAafFormatSpecificData2_V0(const Avtp_Aaf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Aaf_GetAafFormatSpecificData2_V0(const Avtp_AafV0_t *const pdu) { return (uint8_t)Avtp_Aaf_GetField_V0(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2); } @@ -1088,7 +1114,7 @@ OPEN1722_INLINE uint8_t Avtp_Aaf_GetAafFormatSpecificData2_V1(const Avtp_AafV1_t * Version 0 variant of Avtp_Aaf_SetSv(). * @see Avtp_Aaf_SetSv */ -OPEN1722_INLINE void Avtp_Aaf_SetSv_V0(Avtp_Aaf_t *pdu, bool sv) +OPEN1722_INLINE void Avtp_Aaf_SetSv_V0(Avtp_AafV0_t *pdu, bool sv) { Avtp_CommonStreamHeader_SetSv_V0((Avtp_CommonStreamHeader_t *)pdu, sv); } @@ -1106,7 +1132,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetSv_V1(Avtp_AafV1_t *pdu, bool sv) * Version 0 variant of Avtp_Aaf_SetMr(). * @see Avtp_Aaf_SetMr */ -OPEN1722_INLINE void Avtp_Aaf_SetMr_V0(Avtp_Aaf_t *pdu, bool mr) +OPEN1722_INLINE void Avtp_Aaf_SetMr_V0(Avtp_AafV0_t *pdu, bool mr) { Avtp_CommonStreamHeader_SetMr_V0((Avtp_CommonStreamHeader_t *)pdu, mr); } @@ -1124,7 +1150,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetMr_V1(Avtp_AafV1_t *pdu, bool mr) * Version 0 variant of Avtp_Aaf_SetTv(). * @see Avtp_Aaf_SetTv */ -OPEN1722_INLINE void Avtp_Aaf_SetTv_V0(Avtp_Aaf_t *pdu, bool tv) +OPEN1722_INLINE void Avtp_Aaf_SetTv_V0(Avtp_AafV0_t *pdu, bool tv) { Avtp_CommonStreamHeader_SetTv_V0((Avtp_CommonStreamHeader_t *)pdu, tv); } @@ -1142,7 +1168,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetTv_V1(Avtp_AafV1_t *pdu, bool tv) * Version 0 variant of Avtp_Aaf_SetTu(). * @see Avtp_Aaf_SetTu */ -OPEN1722_INLINE void Avtp_Aaf_SetTu_V0(Avtp_Aaf_t *pdu, bool tu) +OPEN1722_INLINE void Avtp_Aaf_SetTu_V0(Avtp_AafV0_t *pdu, bool tu) { Avtp_CommonStreamHeader_SetTu_V0((Avtp_CommonStreamHeader_t *)pdu, tu); } @@ -1161,7 +1187,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetTu_V1(Avtp_AafV1_t *pdu, bool tu) * 8-bit version 0 field width. * @see Avtp_Aaf_SetSequenceNum */ -OPEN1722_INLINE void Avtp_Aaf_SetSequenceNum_V0(Avtp_Aaf_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Aaf_SetSequenceNum_V0(Avtp_AafV0_t *pdu, uint32_t value) { Avtp_CommonStreamHeader_SetSequenceNum_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1179,7 +1205,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetSequenceNum_V1(Avtp_AafV1_t *pdu, uint32_t valu * Version 0 variant of Avtp_Aaf_SetStreamId(). * @see Avtp_Aaf_SetStreamId */ -OPEN1722_INLINE void Avtp_Aaf_SetStreamId_V0(Avtp_Aaf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Aaf_SetStreamId_V0(Avtp_AafV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetStreamId_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1197,7 +1223,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetStreamId_V1(Avtp_AafV1_t *pdu, uint64_t value) * Version 0 variant of Avtp_Aaf_SetAvtpTimestamp(). * @see Avtp_Aaf_SetAvtpTimestamp */ -OPEN1722_INLINE void Avtp_Aaf_SetAvtpTimestamp_V0(Avtp_Aaf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Aaf_SetAvtpTimestamp_V0(Avtp_AafV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetAvtpTimestamp_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1216,7 +1242,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetAvtpTimestamp_V1(Avtp_AafV1_t *pdu, uint64_t va * absent from version 0, so this is a no-op. * @see Avtp_Aaf_SetPtpGrandmasterIdentity */ -OPEN1722_INLINE void Avtp_Aaf_SetPtpGrandmasterIdentity_V0(Avtp_Aaf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Aaf_SetPtpGrandmasterIdentity_V0(Avtp_AafV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1234,7 +1260,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetPtpGrandmasterIdentity_V1(Avtp_AafV1_t *pdu, ui * Version 0 variant of Avtp_Aaf_SetFormat(). * @see Avtp_Aaf_SetFormat */ -OPEN1722_INLINE void Avtp_Aaf_SetFormat_V0(Avtp_Aaf_t *pdu, Avtp_AafFormat_t value) +OPEN1722_INLINE void Avtp_Aaf_SetFormat_V0(Avtp_AafV0_t *pdu, Avtp_AafFormat_t value) { Avtp_Aaf_SetField_V0(pdu, AVTP_AAF_FIELD_FORMAT, (uint64_t)value); } @@ -1252,7 +1278,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetFormat_V1(Avtp_AafV1_t *pdu, Avtp_AafFormat_t v * Version 0 variant of Avtp_Aaf_SetAafFormatSpecificData1(). * @see Avtp_Aaf_SetAafFormatSpecificData1 */ -OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData1_V0(Avtp_Aaf_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData1_V0(Avtp_AafV0_t *pdu, uint32_t value) { Avtp_Aaf_SetField_V0(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_1, value); } @@ -1270,7 +1296,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData1_V1(Avtp_AafV1_t *pdu, ui * Version 0 variant of Avtp_Aaf_SetStreamDataLength(). * @see Avtp_Aaf_SetStreamDataLength */ -OPEN1722_INLINE void Avtp_Aaf_SetStreamDataLength_V0(Avtp_Aaf_t *pdu, uint16_t value) +OPEN1722_INLINE void Avtp_Aaf_SetStreamDataLength_V0(Avtp_AafV0_t *pdu, uint16_t value) { Avtp_CommonStreamHeader_SetStreamDataLength_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1288,7 +1314,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetStreamDataLength_V1(Avtp_AafV1_t *pdu, uint16_t * Version 0 variant of Avtp_Aaf_SetAfsd(). * @see Avtp_Aaf_SetAfsd */ -OPEN1722_INLINE void Avtp_Aaf_SetAfsd_V0(Avtp_Aaf_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Aaf_SetAfsd_V0(Avtp_AafV0_t *pdu, uint8_t value) { Avtp_Aaf_SetField_V0(pdu, AVTP_AAF_FIELD_AFSD, value); } @@ -1306,7 +1332,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetAfsd_V1(Avtp_AafV1_t *pdu, uint8_t value) * Version 0 variant of Avtp_Aaf_SetSp(). * @see Avtp_Aaf_SetSp */ -OPEN1722_INLINE void Avtp_Aaf_SetSp_V0(Avtp_Aaf_t *pdu, bool sp) +OPEN1722_INLINE void Avtp_Aaf_SetSp_V0(Avtp_AafV0_t *pdu, bool sp) { Avtp_Aaf_SetField_V0(pdu, AVTP_AAF_FIELD_SP, sp); } @@ -1324,7 +1350,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetSp_V1(Avtp_AafV1_t *pdu, bool sp) * Version 0 variant of Avtp_Aaf_SetEvt(). * @see Avtp_Aaf_SetEvt */ -OPEN1722_INLINE void Avtp_Aaf_SetEvt_V0(Avtp_Aaf_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Aaf_SetEvt_V0(Avtp_AafV0_t *pdu, uint8_t value) { Avtp_Aaf_SetField_V0(pdu, AVTP_AAF_FIELD_EVT, value); } @@ -1342,7 +1368,7 @@ OPEN1722_INLINE void Avtp_Aaf_SetEvt_V1(Avtp_AafV1_t *pdu, uint8_t value) * Version 0 variant of Avtp_Aaf_SetAafFormatSpecificData2(). * @see Avtp_Aaf_SetAafFormatSpecificData2 */ -OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData2_V0(Avtp_Aaf_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Aaf_SetAafFormatSpecificData2_V0(Avtp_AafV0_t *pdu, uint8_t value) { Avtp_Aaf_SetField_V0(pdu, AVTP_AAF_FIELD_AAF_FORMAT_SPECIFIC_DATA_2, value); } diff --git a/include/avtp/aaf/Pcm.h b/include/avtp/aaf/Pcm.h index 9d6dffed..44e7d3df 100644 --- a/include/avtp/aaf/Pcm.h +++ b/include/avtp/aaf/Pcm.h @@ -71,13 +71,20 @@ extern "C" { typedef struct { uint8_t header[AVTP_PCM_HEADER_LEN_V0]; uint8_t payload[0]; -} __attribute__((packed)) Avtp_Pcm_t; +} __attribute__((packed)) Avtp_PcmV0_t; typedef struct { uint8_t header[AVTP_PCM_HEADER_LEN_V1]; uint8_t payload[0]; } __attribute__((packed)) Avtp_PcmV1_t; +/** + * Version-agnostic handle for PCM PDUs. It is an alias of the version 0 + * layout and is the pointer type of the version-agnostic accessors; version 1 + * PDUs use Avtp_PcmV1_t. For version 0 use Avtp_PcmV0_t. + */ +typedef Avtp_PcmV0_t Avtp_Pcm_t; + /** * AAF PCM 'nsr' (nominal sample rate) field values (IEEE 1722-2025, Table 12). * Values 0x0B-0x0F are reserved. @@ -194,7 +201,7 @@ static const Avtp_FieldDescriptor_t Avtp_PcmFieldDescV1[AVTP_PCM_FIELD_MAX] = { * @returns This function returns the value of the field. * @see Avtp_Pcm_GetField */ -OPEN1722_INLINE uint64_t Avtp_Pcm_GetField_V0(const Avtp_Pcm_t *const pdu, Avtp_PcmFields_t field) +OPEN1722_INLINE uint64_t Avtp_Pcm_GetField_V0(const Avtp_PcmV0_t *const pdu, Avtp_PcmFields_t field) { return Avtp_GetField(Avtp_PcmFieldDescV0, AVTP_PCM_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); @@ -240,7 +247,7 @@ OPEN1722_INLINE uint64_t Avtp_Pcm_GetField(const Avtp_Pcm_t *const pdu, Avtp_Pcm * @param value The value to set. * @see Avtp_Pcm_SetField */ -OPEN1722_INLINE void Avtp_Pcm_SetField_V0(Avtp_Pcm_t *pdu, Avtp_PcmFields_t field, uint64_t value) +OPEN1722_INLINE void Avtp_Pcm_SetField_V0(Avtp_PcmV0_t *pdu, Avtp_PcmFields_t field, uint64_t value) { Avtp_SetField(Avtp_PcmFieldDescV0, AVTP_PCM_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); } @@ -282,7 +289,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetField(Avtp_Pcm_t *pdu, Avtp_PcmFields_t field, * pointer is not read; it keeps the signature aligned with the * version-dispatched accessors. */ -OPEN1722_INLINE uint8_t Avtp_Pcm_GetHeaderLen_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Pcm_GetHeaderLen_V0(const Avtp_PcmV0_t *const pdu) { (void)pdu; return (uint8_t)AVTP_PCM_HEADER_LEN_V0; @@ -660,7 +667,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetEvt(Avtp_Pcm_t *pdu, uint8_t value) * @return Pointer to AAF PCM frame payload * @see Avtp_Pcm_GetPayload */ -OPEN1722_INLINE const uint8_t *Avtp_Pcm_GetPayload_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE const uint8_t *Avtp_Pcm_GetPayload_V0(const Avtp_PcmV0_t *const pdu) { return (const uint8_t *)pdu + AVTP_PCM_HEADER_LEN_V0; } @@ -700,7 +707,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Pcm_GetPayload(const Avtp_Pcm_t *const pdu) * @param payload_length Length of the payload * @see Avtp_Pcm_SetPayload */ -OPEN1722_INLINE void Avtp_Pcm_SetPayload_V0(Avtp_Pcm_t *pdu, uint8_t *payload, +OPEN1722_INLINE void Avtp_Pcm_SetPayload_V0(Avtp_PcmV0_t *pdu, uint8_t *payload, uint16_t payload_length) { memcpy((uint8_t *)pdu + AVTP_PCM_HEADER_LEN_V0, payload, payload_length); @@ -742,10 +749,10 @@ OPEN1722_INLINE void Avtp_Pcm_SetPayload(Avtp_Pcm_t *pdu, uint8_t *payload, uint * * @param pdu Pointer to the first bit of a 1722 AAF PCM PDU. */ -OPEN1722_INLINE void Avtp_Pcm_Init(Avtp_Pcm_t *pdu) +OPEN1722_INLINE void Avtp_Pcm_InitV0(Avtp_PcmV0_t *pdu) { if (pdu != NULL) { - memset(pdu, 0, sizeof(Avtp_Pcm_t)); + memset(pdu, 0, sizeof(Avtp_PcmV0_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_AAF); Avtp_Pcm_SetSv(pdu, true); } @@ -843,6 +850,25 @@ OPEN1722_INLINE bool Avtp_Pcm_IsValid(const Avtp_Pcm_t *const pdu, size_t buffer return true; } +/** + * Initializes a PCM PDU of the given version. The caller must provide a + * buffer of at least AVTP_PCM_HEADER_LEN_V1 octets for version 1 (for + * example an Avtp_PcmV1_t); version 0 uses AVTP_PCM_HEADER_LEN_V0 + * octets. Any version other than AVTPDU_VERSION_1 initializes a version 0 PDU. + * + * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- + * or an ACF header. + * @param version AVTPDU header version (AVTPDU_VERSION_0 or AVTPDU_VERSION_1). + */ +OPEN1722_INLINE void Avtp_Pcm_Init(Avtp_Pcm_t *pdu, uint8_t version) +{ + if (version == AVTPDU_VERSION_1) { + Avtp_Pcm_InitV1((Avtp_PcmV1_t *)pdu); + } else { + Avtp_Pcm_InitV0(pdu); + } +} + /* * Version-typed named accessors. These select the field layout for one * explicit version and never read the version field; the version-dispatched @@ -855,7 +881,7 @@ OPEN1722_INLINE bool Avtp_Pcm_IsValid(const Avtp_Pcm_t *const pdu, size_t buffer * Version 0 variant of Avtp_Pcm_IsSv(). * @see Avtp_Pcm_IsSv */ -OPEN1722_INLINE bool Avtp_Pcm_IsSv_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE bool Avtp_Pcm_IsSv_V0(const Avtp_PcmV0_t *const pdu) { return Avtp_CommonStreamHeader_IsSv_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -873,7 +899,7 @@ OPEN1722_INLINE bool Avtp_Pcm_IsSv_V1(const Avtp_PcmV1_t *const pdu) * Version 0 variant of Avtp_Pcm_IsMr(). * @see Avtp_Pcm_IsMr */ -OPEN1722_INLINE bool Avtp_Pcm_IsMr_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE bool Avtp_Pcm_IsMr_V0(const Avtp_PcmV0_t *const pdu) { return Avtp_CommonStreamHeader_IsMr_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -891,7 +917,7 @@ OPEN1722_INLINE bool Avtp_Pcm_IsMr_V1(const Avtp_PcmV1_t *const pdu) * Version 0 variant of Avtp_Pcm_IsTv(). * @see Avtp_Pcm_IsTv */ -OPEN1722_INLINE bool Avtp_Pcm_IsTv_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE bool Avtp_Pcm_IsTv_V0(const Avtp_PcmV0_t *const pdu) { return Avtp_CommonStreamHeader_IsTv_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -909,7 +935,7 @@ OPEN1722_INLINE bool Avtp_Pcm_IsTv_V1(const Avtp_PcmV1_t *const pdu) * Version 0 variant of Avtp_Pcm_IsTu(). * @see Avtp_Pcm_IsTu */ -OPEN1722_INLINE bool Avtp_Pcm_IsTu_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE bool Avtp_Pcm_IsTu_V0(const Avtp_PcmV0_t *const pdu) { return Avtp_CommonStreamHeader_IsTu_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -928,7 +954,7 @@ OPEN1722_INLINE bool Avtp_Pcm_IsTu_V1(const Avtp_PcmV1_t *const pdu) * 8-bit version 0 field width. * @see Avtp_Pcm_GetSequenceNum */ -OPEN1722_INLINE uint32_t Avtp_Pcm_GetSequenceNum_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Pcm_GetSequenceNum_V0(const Avtp_PcmV0_t *const pdu) { return Avtp_CommonStreamHeader_GetSequenceNum_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -946,7 +972,7 @@ OPEN1722_INLINE uint32_t Avtp_Pcm_GetSequenceNum_V1(const Avtp_PcmV1_t *const pd * Version 0 variant of Avtp_Pcm_GetStreamId(). * @see Avtp_Pcm_GetStreamId */ -OPEN1722_INLINE uint64_t Avtp_Pcm_GetStreamId_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Pcm_GetStreamId_V0(const Avtp_PcmV0_t *const pdu) { return Avtp_CommonStreamHeader_GetStreamId_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -964,7 +990,7 @@ OPEN1722_INLINE uint64_t Avtp_Pcm_GetStreamId_V1(const Avtp_PcmV1_t *const pdu) * Version 0 variant of Avtp_Pcm_GetAvtpTimestamp(). * @see Avtp_Pcm_GetAvtpTimestamp */ -OPEN1722_INLINE uint64_t Avtp_Pcm_GetAvtpTimestamp_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Pcm_GetAvtpTimestamp_V0(const Avtp_PcmV0_t *const pdu) { return Avtp_CommonStreamHeader_GetAvtpTimestamp_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -983,7 +1009,7 @@ OPEN1722_INLINE uint64_t Avtp_Pcm_GetAvtpTimestamp_V1(const Avtp_PcmV1_t *const * absent from version 0, so this always returns 0. * @see Avtp_Pcm_GetPtpGrandmasterIdentity */ -OPEN1722_INLINE uint64_t Avtp_Pcm_GetPtpGrandmasterIdentity_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Pcm_GetPtpGrandmasterIdentity_V0(const Avtp_PcmV0_t *const pdu) { return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V0( (const Avtp_CommonStreamHeader_t *)pdu); @@ -1003,7 +1029,7 @@ OPEN1722_INLINE uint64_t Avtp_Pcm_GetPtpGrandmasterIdentity_V1(const Avtp_PcmV1_ * Version 0 variant of Avtp_Pcm_GetFormat(). * @see Avtp_Pcm_GetFormat */ -OPEN1722_INLINE Avtp_AafFormat_t Avtp_Pcm_GetFormat_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE Avtp_AafFormat_t Avtp_Pcm_GetFormat_V0(const Avtp_PcmV0_t *const pdu) { return (Avtp_AafFormat_t)Avtp_Pcm_GetField_V0(pdu, AVTP_PCM_FIELD_FORMAT); } @@ -1021,7 +1047,7 @@ OPEN1722_INLINE Avtp_AafFormat_t Avtp_Pcm_GetFormat_V1(const Avtp_PcmV1_t *const * Version 0 variant of Avtp_Pcm_GetNsr(). * @see Avtp_Pcm_GetNsr */ -OPEN1722_INLINE Avtp_PcmNsr_t Avtp_Pcm_GetNsr_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE Avtp_PcmNsr_t Avtp_Pcm_GetNsr_V0(const Avtp_PcmV0_t *const pdu) { return (Avtp_PcmNsr_t)Avtp_Pcm_GetField_V0(pdu, AVTP_PCM_FIELD_NSR); } @@ -1039,7 +1065,7 @@ OPEN1722_INLINE Avtp_PcmNsr_t Avtp_Pcm_GetNsr_V1(const Avtp_PcmV1_t *const pdu) * Version 0 variant of Avtp_Pcm_GetChannelsPerFrame(). * @see Avtp_Pcm_GetChannelsPerFrame */ -OPEN1722_INLINE uint16_t Avtp_Pcm_GetChannelsPerFrame_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE uint16_t Avtp_Pcm_GetChannelsPerFrame_V0(const Avtp_PcmV0_t *const pdu) { return (uint16_t)Avtp_Pcm_GetField_V0(pdu, AVTP_PCM_FIELD_CHANNELS_PER_FRAME); } @@ -1057,7 +1083,7 @@ OPEN1722_INLINE uint16_t Avtp_Pcm_GetChannelsPerFrame_V1(const Avtp_PcmV1_t *con * Version 0 variant of Avtp_Pcm_GetBitDepth(). * @see Avtp_Pcm_GetBitDepth */ -OPEN1722_INLINE uint8_t Avtp_Pcm_GetBitDepth_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Pcm_GetBitDepth_V0(const Avtp_PcmV0_t *const pdu) { return (uint8_t)Avtp_Pcm_GetField_V0(pdu, AVTP_PCM_FIELD_BIT_DEPTH); } @@ -1075,7 +1101,7 @@ OPEN1722_INLINE uint8_t Avtp_Pcm_GetBitDepth_V1(const Avtp_PcmV1_t *const pdu) * Version 0 variant of Avtp_Pcm_GetStreamDataLength(). * @see Avtp_Pcm_GetStreamDataLength */ -OPEN1722_INLINE uint16_t Avtp_Pcm_GetStreamDataLength_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE uint16_t Avtp_Pcm_GetStreamDataLength_V0(const Avtp_PcmV0_t *const pdu) { return Avtp_CommonStreamHeader_GetStreamDataLength_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -1093,7 +1119,7 @@ OPEN1722_INLINE uint16_t Avtp_Pcm_GetStreamDataLength_V1(const Avtp_PcmV1_t *con * Version 0 variant of Avtp_Pcm_IsSp(). * @see Avtp_Pcm_IsSp */ -OPEN1722_INLINE bool Avtp_Pcm_IsSp_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE bool Avtp_Pcm_IsSp_V0(const Avtp_PcmV0_t *const pdu) { return (bool)Avtp_Pcm_GetField_V0(pdu, AVTP_PCM_FIELD_SP); } @@ -1111,7 +1137,7 @@ OPEN1722_INLINE bool Avtp_Pcm_IsSp_V1(const Avtp_PcmV1_t *const pdu) * Version 0 variant of Avtp_Pcm_GetEvt(). * @see Avtp_Pcm_GetEvt */ -OPEN1722_INLINE uint8_t Avtp_Pcm_GetEvt_V0(const Avtp_Pcm_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Pcm_GetEvt_V0(const Avtp_PcmV0_t *const pdu) { return (uint8_t)Avtp_Pcm_GetField_V0(pdu, AVTP_PCM_FIELD_EVT); } @@ -1129,7 +1155,7 @@ OPEN1722_INLINE uint8_t Avtp_Pcm_GetEvt_V1(const Avtp_PcmV1_t *const pdu) * Version 0 variant of Avtp_Pcm_SetSv(). * @see Avtp_Pcm_SetSv */ -OPEN1722_INLINE void Avtp_Pcm_SetSv_V0(Avtp_Pcm_t *pdu, bool sv) +OPEN1722_INLINE void Avtp_Pcm_SetSv_V0(Avtp_PcmV0_t *pdu, bool sv) { Avtp_CommonStreamHeader_SetSv_V0((Avtp_CommonStreamHeader_t *)pdu, sv); } @@ -1147,7 +1173,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetSv_V1(Avtp_PcmV1_t *pdu, bool sv) * Version 0 variant of Avtp_Pcm_SetMr(). * @see Avtp_Pcm_SetMr */ -OPEN1722_INLINE void Avtp_Pcm_SetMr_V0(Avtp_Pcm_t *pdu, bool mr) +OPEN1722_INLINE void Avtp_Pcm_SetMr_V0(Avtp_PcmV0_t *pdu, bool mr) { Avtp_CommonStreamHeader_SetMr_V0((Avtp_CommonStreamHeader_t *)pdu, mr); } @@ -1165,7 +1191,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetMr_V1(Avtp_PcmV1_t *pdu, bool mr) * Version 0 variant of Avtp_Pcm_SetTv(). * @see Avtp_Pcm_SetTv */ -OPEN1722_INLINE void Avtp_Pcm_SetTv_V0(Avtp_Pcm_t *pdu, bool tv) +OPEN1722_INLINE void Avtp_Pcm_SetTv_V0(Avtp_PcmV0_t *pdu, bool tv) { Avtp_CommonStreamHeader_SetTv_V0((Avtp_CommonStreamHeader_t *)pdu, tv); } @@ -1183,7 +1209,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetTv_V1(Avtp_PcmV1_t *pdu, bool tv) * Version 0 variant of Avtp_Pcm_SetTu(). * @see Avtp_Pcm_SetTu */ -OPEN1722_INLINE void Avtp_Pcm_SetTu_V0(Avtp_Pcm_t *pdu, bool tu) +OPEN1722_INLINE void Avtp_Pcm_SetTu_V0(Avtp_PcmV0_t *pdu, bool tu) { Avtp_CommonStreamHeader_SetTu_V0((Avtp_CommonStreamHeader_t *)pdu, tu); } @@ -1202,7 +1228,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetTu_V1(Avtp_PcmV1_t *pdu, bool tu) * 8-bit version 0 field width. * @see Avtp_Pcm_SetSequenceNum */ -OPEN1722_INLINE void Avtp_Pcm_SetSequenceNum_V0(Avtp_Pcm_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Pcm_SetSequenceNum_V0(Avtp_PcmV0_t *pdu, uint32_t value) { Avtp_CommonStreamHeader_SetSequenceNum_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1220,7 +1246,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetSequenceNum_V1(Avtp_PcmV1_t *pdu, uint32_t valu * Version 0 variant of Avtp_Pcm_SetStreamId(). * @see Avtp_Pcm_SetStreamId */ -OPEN1722_INLINE void Avtp_Pcm_SetStreamId_V0(Avtp_Pcm_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Pcm_SetStreamId_V0(Avtp_PcmV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetStreamId_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1238,7 +1264,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetStreamId_V1(Avtp_PcmV1_t *pdu, uint64_t value) * Version 0 variant of Avtp_Pcm_SetAvtpTimestamp(). * @see Avtp_Pcm_SetAvtpTimestamp */ -OPEN1722_INLINE void Avtp_Pcm_SetAvtpTimestamp_V0(Avtp_Pcm_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Pcm_SetAvtpTimestamp_V0(Avtp_PcmV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetAvtpTimestamp_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1257,7 +1283,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetAvtpTimestamp_V1(Avtp_PcmV1_t *pdu, uint64_t va * absent from version 0, so this is a no-op. * @see Avtp_Pcm_SetPtpGrandmasterIdentity */ -OPEN1722_INLINE void Avtp_Pcm_SetPtpGrandmasterIdentity_V0(Avtp_Pcm_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Pcm_SetPtpGrandmasterIdentity_V0(Avtp_PcmV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1275,7 +1301,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetPtpGrandmasterIdentity_V1(Avtp_PcmV1_t *pdu, ui * Version 0 variant of Avtp_Pcm_SetFormat(). * @see Avtp_Pcm_SetFormat */ -OPEN1722_INLINE void Avtp_Pcm_SetFormat_V0(Avtp_Pcm_t *pdu, Avtp_AafFormat_t value) +OPEN1722_INLINE void Avtp_Pcm_SetFormat_V0(Avtp_PcmV0_t *pdu, Avtp_AafFormat_t value) { Avtp_Pcm_SetField_V0(pdu, AVTP_PCM_FIELD_FORMAT, (uint64_t)value); } @@ -1293,7 +1319,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetFormat_V1(Avtp_PcmV1_t *pdu, Avtp_AafFormat_t v * Version 0 variant of Avtp_Pcm_SetNsr(). * @see Avtp_Pcm_SetNsr */ -OPEN1722_INLINE void Avtp_Pcm_SetNsr_V0(Avtp_Pcm_t *pdu, Avtp_PcmNsr_t value) +OPEN1722_INLINE void Avtp_Pcm_SetNsr_V0(Avtp_PcmV0_t *pdu, Avtp_PcmNsr_t value) { Avtp_Pcm_SetField_V0(pdu, AVTP_PCM_FIELD_NSR, (uint64_t)value); } @@ -1311,7 +1337,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetNsr_V1(Avtp_PcmV1_t *pdu, Avtp_PcmNsr_t value) * Version 0 variant of Avtp_Pcm_SetChannelsPerFrame(). * @see Avtp_Pcm_SetChannelsPerFrame */ -OPEN1722_INLINE void Avtp_Pcm_SetChannelsPerFrame_V0(Avtp_Pcm_t *pdu, uint16_t value) +OPEN1722_INLINE void Avtp_Pcm_SetChannelsPerFrame_V0(Avtp_PcmV0_t *pdu, uint16_t value) { Avtp_Pcm_SetField_V0(pdu, AVTP_PCM_FIELD_CHANNELS_PER_FRAME, value); } @@ -1329,7 +1355,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetChannelsPerFrame_V1(Avtp_PcmV1_t *pdu, uint16_t * Version 0 variant of Avtp_Pcm_SetBitDepth(). * @see Avtp_Pcm_SetBitDepth */ -OPEN1722_INLINE void Avtp_Pcm_SetBitDepth_V0(Avtp_Pcm_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Pcm_SetBitDepth_V0(Avtp_PcmV0_t *pdu, uint8_t value) { Avtp_Pcm_SetField_V0(pdu, AVTP_PCM_FIELD_BIT_DEPTH, value); } @@ -1347,7 +1373,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetBitDepth_V1(Avtp_PcmV1_t *pdu, uint8_t value) * Version 0 variant of Avtp_Pcm_SetStreamDataLength(). * @see Avtp_Pcm_SetStreamDataLength */ -OPEN1722_INLINE void Avtp_Pcm_SetStreamDataLength_V0(Avtp_Pcm_t *pdu, uint16_t value) +OPEN1722_INLINE void Avtp_Pcm_SetStreamDataLength_V0(Avtp_PcmV0_t *pdu, uint16_t value) { Avtp_CommonStreamHeader_SetStreamDataLength_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1365,7 +1391,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetStreamDataLength_V1(Avtp_PcmV1_t *pdu, uint16_t * Version 0 variant of Avtp_Pcm_SetSp(). * @see Avtp_Pcm_SetSp */ -OPEN1722_INLINE void Avtp_Pcm_SetSp_V0(Avtp_Pcm_t *pdu, bool sp) +OPEN1722_INLINE void Avtp_Pcm_SetSp_V0(Avtp_PcmV0_t *pdu, bool sp) { Avtp_Pcm_SetField_V0(pdu, AVTP_PCM_FIELD_SP, sp); } @@ -1383,7 +1409,7 @@ OPEN1722_INLINE void Avtp_Pcm_SetSp_V1(Avtp_PcmV1_t *pdu, bool sp) * Version 0 variant of Avtp_Pcm_SetEvt(). * @see Avtp_Pcm_SetEvt */ -OPEN1722_INLINE void Avtp_Pcm_SetEvt_V0(Avtp_Pcm_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Pcm_SetEvt_V0(Avtp_PcmV0_t *pdu, uint8_t value) { Avtp_Pcm_SetField_V0(pdu, AVTP_PCM_FIELD_EVT, value); } diff --git a/include/avtp/acf/Ntscf.h b/include/avtp/acf/Ntscf.h index 5739dcd2..e8795ed1 100644 --- a/include/avtp/acf/Ntscf.h +++ b/include/avtp/acf/Ntscf.h @@ -70,13 +70,20 @@ extern "C" { typedef struct { uint8_t header[AVTP_NTSCF_HEADER_LEN_V0]; uint8_t payload[0]; -} __attribute__((packed)) Avtp_Ntscf_t; +} __attribute__((packed)) Avtp_NtscfV0_t; typedef struct { uint8_t header[AVTP_NTSCF_HEADER_LEN_V1]; uint8_t payload[0]; } __attribute__((packed)) Avtp_NtscfV1_t; +/** + * Version-agnostic handle for NTSCF PDUs. It is an alias of the version 0 + * layout and is the pointer type of the version-agnostic accessors; version 1 + * PDUs use Avtp_NtscfV1_t. For version 0 use Avtp_NtscfV0_t. + */ +typedef Avtp_NtscfV0_t Avtp_Ntscf_t; + typedef enum { /* Common AVTP alternative header fields */ @@ -139,7 +146,7 @@ static const Avtp_FieldDescriptor_t Avtp_NtscfFieldDescV1[AVTP_NTSCF_FIELD_MAX] * @returns This function returns the value of the field. * @see Avtp_Ntscf_GetField */ -OPEN1722_INLINE uint64_t Avtp_Ntscf_GetField_V0(const Avtp_Ntscf_t *const pdu, +OPEN1722_INLINE uint64_t Avtp_Ntscf_GetField_V0(const Avtp_NtscfV0_t *const pdu, Avtp_NtscfFields_t field) { return Avtp_GetField(Avtp_NtscfFieldDescV0, AVTP_NTSCF_FIELD_MAX, (const uint8_t *)pdu, @@ -188,7 +195,7 @@ OPEN1722_INLINE uint64_t Avtp_Ntscf_GetField(const Avtp_Ntscf_t *const pdu, * @param value The value to set. * @see Avtp_Ntscf_SetField */ -OPEN1722_INLINE void Avtp_Ntscf_SetField_V0(Avtp_Ntscf_t *pdu, Avtp_NtscfFields_t field, +OPEN1722_INLINE void Avtp_Ntscf_SetField_V0(Avtp_NtscfV0_t *pdu, Avtp_NtscfFields_t field, uint64_t value) { Avtp_SetField(Avtp_NtscfFieldDescV0, AVTP_NTSCF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, @@ -235,7 +242,7 @@ OPEN1722_INLINE void Avtp_Ntscf_SetField(Avtp_Ntscf_t *pdu, Avtp_NtscfFields_t f * pointer is not read; it keeps the signature aligned with the * version-dispatched accessors. */ -OPEN1722_INLINE uint8_t Avtp_Ntscf_GetHeaderLen_V0(const Avtp_Ntscf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Ntscf_GetHeaderLen_V0(const Avtp_NtscfV0_t *const pdu) { (void)pdu; return (uint8_t)AVTP_NTSCF_HEADER_LEN_V0; @@ -414,7 +421,7 @@ OPEN1722_INLINE void Avtp_Ntscf_SetStreamId(Avtp_Ntscf_t *pdu, uint64_t value) * @return Pointer to the NTSCF frame payload. * @see Avtp_Ntscf_GetPayload */ -OPEN1722_INLINE const uint8_t *Avtp_Ntscf_GetPayload_V0(const Avtp_Ntscf_t *const pdu) +OPEN1722_INLINE const uint8_t *Avtp_Ntscf_GetPayload_V0(const Avtp_NtscfV0_t *const pdu) { return (const uint8_t *)pdu + AVTP_NTSCF_HEADER_LEN_V0; } @@ -454,7 +461,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Ntscf_GetPayload(const Avtp_Ntscf_t *const p * @param payload_length Length of the payload. * @see Avtp_Ntscf_SetPayload */ -OPEN1722_INLINE void Avtp_Ntscf_SetPayload_V0(Avtp_Ntscf_t *pdu, uint8_t *payload, +OPEN1722_INLINE void Avtp_Ntscf_SetPayload_V0(Avtp_NtscfV0_t *pdu, uint8_t *payload, uint16_t payload_length) { memcpy((uint8_t *)pdu + AVTP_NTSCF_HEADER_LEN_V0, payload, payload_length); @@ -536,10 +543,10 @@ OPEN1722_INLINE bool Avtp_Ntscf_IsValid(const Avtp_Ntscf_t *const pdu, size_t bu * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- * or an ACF header. */ -OPEN1722_INLINE void Avtp_Ntscf_Init(Avtp_Ntscf_t *pdu) +OPEN1722_INLINE void Avtp_Ntscf_InitV0(Avtp_NtscfV0_t *pdu) { if (pdu != NULL) { - memset(pdu, 0, sizeof(Avtp_Ntscf_t)); + memset(pdu, 0, sizeof(Avtp_NtscfV0_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_NTSCF); Avtp_Ntscf_SetSv(pdu, true); } @@ -562,6 +569,25 @@ OPEN1722_INLINE void Avtp_Ntscf_InitV1(Avtp_NtscfV1_t *pdu) } } +/** + * Initializes an NTSCF PDU of the given version. The caller must provide a + * buffer of at least AVTP_NTSCF_HEADER_LEN_V1 octets for version 1 (for + * example an Avtp_NtscfV1_t); version 0 uses AVTP_NTSCF_HEADER_LEN_V0 + * octets. Any version other than AVTPDU_VERSION_1 initializes a version 0 PDU. + * + * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- + * or an ACF header. + * @param version AVTPDU header version (AVTPDU_VERSION_0 or AVTPDU_VERSION_1). + */ +OPEN1722_INLINE void Avtp_Ntscf_Init(Avtp_Ntscf_t *pdu, uint8_t version) +{ + if (version == AVTPDU_VERSION_1) { + Avtp_Ntscf_InitV1((Avtp_NtscfV1_t *)pdu); + } else { + Avtp_Ntscf_InitV0(pdu); + } +} + /* * Version-typed named accessors. These select the field layout for one * explicit version and never read the version field; the version-dispatched @@ -574,7 +600,7 @@ OPEN1722_INLINE void Avtp_Ntscf_InitV1(Avtp_NtscfV1_t *pdu) * Version 0 variant of Avtp_Ntscf_IsSv(). * @see Avtp_Ntscf_IsSv */ -OPEN1722_INLINE bool Avtp_Ntscf_IsSv_V0(const Avtp_Ntscf_t *const pdu) +OPEN1722_INLINE bool Avtp_Ntscf_IsSv_V0(const Avtp_NtscfV0_t *const pdu) { return (bool)Avtp_Ntscf_GetField_V0(pdu, AVTP_NTSCF_FIELD_SV); } @@ -592,7 +618,7 @@ OPEN1722_INLINE bool Avtp_Ntscf_IsSv_V1(const Avtp_NtscfV1_t *const pdu) * Version 0 variant of Avtp_Ntscf_GetNtscfDataLength(). * @see Avtp_Ntscf_GetNtscfDataLength */ -OPEN1722_INLINE uint16_t Avtp_Ntscf_GetNtscfDataLength_V0(const Avtp_Ntscf_t *const pdu) +OPEN1722_INLINE uint16_t Avtp_Ntscf_GetNtscfDataLength_V0(const Avtp_NtscfV0_t *const pdu) { return (uint16_t)Avtp_Ntscf_GetField_V0(pdu, AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH); } @@ -611,7 +637,7 @@ OPEN1722_INLINE uint16_t Avtp_Ntscf_GetNtscfDataLength_V1(const Avtp_NtscfV1_t * * number is the 8-bit sequence_num_lsb field. * @see Avtp_Ntscf_GetSequenceNum */ -OPEN1722_INLINE uint32_t Avtp_Ntscf_GetSequenceNum_V0(const Avtp_Ntscf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Ntscf_GetSequenceNum_V0(const Avtp_NtscfV0_t *const pdu) { return (uint32_t)Avtp_Ntscf_GetField_V0(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB); } @@ -629,7 +655,7 @@ OPEN1722_INLINE uint32_t Avtp_Ntscf_GetSequenceNum_V1(const Avtp_NtscfV1_t *cons * Version 0 variant of Avtp_Ntscf_GetSequenceNumLsb(). * @see Avtp_Ntscf_GetSequenceNumLsb */ -OPEN1722_INLINE uint8_t Avtp_Ntscf_GetSequenceNumLsb_V0(const Avtp_Ntscf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Ntscf_GetSequenceNumLsb_V0(const Avtp_NtscfV0_t *const pdu) { return (uint8_t)Avtp_Ntscf_GetField_V0(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB); } @@ -648,7 +674,7 @@ OPEN1722_INLINE uint8_t Avtp_Ntscf_GetSequenceNumLsb_V1(const Avtp_NtscfV1_t *co * absent from version 0, so this always returns 0. * @see Avtp_Ntscf_GetPtpGrandmasterIdentity */ -OPEN1722_INLINE uint64_t Avtp_Ntscf_GetPtpGrandmasterIdentity_V0(const Avtp_Ntscf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Ntscf_GetPtpGrandmasterIdentity_V0(const Avtp_NtscfV0_t *const pdu) { return Avtp_AlternativeHeader_GetPtpGrandmasterIdentity_V0( (const Avtp_AlternativeHeader_t *)pdu); @@ -668,7 +694,7 @@ OPEN1722_INLINE uint64_t Avtp_Ntscf_GetPtpGrandmasterIdentity_V1(const Avtp_Ntsc * Version 0 variant of Avtp_Ntscf_GetStreamId(). * @see Avtp_Ntscf_GetStreamId */ -OPEN1722_INLINE uint64_t Avtp_Ntscf_GetStreamId_V0(const Avtp_Ntscf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Ntscf_GetStreamId_V0(const Avtp_NtscfV0_t *const pdu) { return Avtp_Ntscf_GetField_V0(pdu, AVTP_NTSCF_FIELD_STREAM_ID); } @@ -686,7 +712,7 @@ OPEN1722_INLINE uint64_t Avtp_Ntscf_GetStreamId_V1(const Avtp_NtscfV1_t *const p * Version 0 variant of Avtp_Ntscf_SetSv(). * @see Avtp_Ntscf_SetSv */ -OPEN1722_INLINE void Avtp_Ntscf_SetSv_V0(Avtp_Ntscf_t *pdu, bool sv) +OPEN1722_INLINE void Avtp_Ntscf_SetSv_V0(Avtp_NtscfV0_t *pdu, bool sv) { Avtp_Ntscf_SetField_V0(pdu, AVTP_NTSCF_FIELD_SV, sv); } @@ -704,7 +730,7 @@ OPEN1722_INLINE void Avtp_Ntscf_SetSv_V1(Avtp_NtscfV1_t *pdu, bool sv) * Version 0 variant of Avtp_Ntscf_SetNtscfDataLength(). * @see Avtp_Ntscf_SetNtscfDataLength */ -OPEN1722_INLINE void Avtp_Ntscf_SetNtscfDataLength_V0(Avtp_Ntscf_t *pdu, uint16_t value) +OPEN1722_INLINE void Avtp_Ntscf_SetNtscfDataLength_V0(Avtp_NtscfV0_t *pdu, uint16_t value) { Avtp_Ntscf_SetField_V0(pdu, AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH, value); } @@ -723,7 +749,7 @@ OPEN1722_INLINE void Avtp_Ntscf_SetNtscfDataLength_V1(Avtp_NtscfV1_t *pdu, uint1 * the 8-bit version 0 sequence_num_lsb field. * @see Avtp_Ntscf_SetSequenceNum */ -OPEN1722_INLINE void Avtp_Ntscf_SetSequenceNum_V0(Avtp_Ntscf_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Ntscf_SetSequenceNum_V0(Avtp_NtscfV0_t *pdu, uint32_t value) { Avtp_Ntscf_SetField_V0(pdu, AVTP_NTSCF_FIELD_SEQUENCE_NUM_LSB, (uint8_t)(value & 0xFFU)); } @@ -744,7 +770,7 @@ OPEN1722_INLINE void Avtp_Ntscf_SetSequenceNum_V1(Avtp_NtscfV1_t *pdu, uint32_t * absent from version 0, so this is a no-op. * @see Avtp_Ntscf_SetPtpGrandmasterIdentity */ -OPEN1722_INLINE void Avtp_Ntscf_SetPtpGrandmasterIdentity_V0(Avtp_Ntscf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Ntscf_SetPtpGrandmasterIdentity_V0(Avtp_NtscfV0_t *pdu, uint64_t value) { Avtp_AlternativeHeader_SetPtpGrandmasterIdentity_V0((Avtp_AlternativeHeader_t *)pdu, value); } @@ -762,7 +788,7 @@ OPEN1722_INLINE void Avtp_Ntscf_SetPtpGrandmasterIdentity_V1(Avtp_NtscfV1_t *pdu * Version 0 variant of Avtp_Ntscf_SetStreamId(). * @see Avtp_Ntscf_SetStreamId */ -OPEN1722_INLINE void Avtp_Ntscf_SetStreamId_V0(Avtp_Ntscf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Ntscf_SetStreamId_V0(Avtp_NtscfV0_t *pdu, uint64_t value) { Avtp_Ntscf_SetField_V0(pdu, AVTP_NTSCF_FIELD_STREAM_ID, value); } diff --git a/include/avtp/acf/Tscf.h b/include/avtp/acf/Tscf.h index 5a6e415d..01d865db 100644 --- a/include/avtp/acf/Tscf.h +++ b/include/avtp/acf/Tscf.h @@ -70,13 +70,20 @@ extern "C" { typedef struct { uint8_t header[AVTP_TSCF_HEADER_LEN_V0]; uint8_t payload[0]; -} __attribute__((packed)) Avtp_Tscf_t; +} __attribute__((packed)) Avtp_TscfV0_t; typedef struct { uint8_t header[AVTP_TSCF_HEADER_LEN_V1]; uint8_t payload[0]; } __attribute__((packed)) Avtp_TscfV1_t; +/** + * Version-agnostic handle for TSCF PDUs. It is an alias of the version 0 + * layout and is the pointer type of the version-agnostic accessors; version 1 + * PDUs use Avtp_TscfV1_t. For version 0 use Avtp_TscfV0_t. + */ +typedef Avtp_TscfV0_t Avtp_Tscf_t; + typedef enum { /* Common AVTP stream header fields */ @@ -154,7 +161,7 @@ static const Avtp_FieldDescriptor_t Avtp_TscfFieldDescV1[AVTP_TSCF_FIELD_MAX] = * @returns This function returns the value of the field. * @see Avtp_Tscf_GetField */ -OPEN1722_INLINE uint64_t Avtp_Tscf_GetField_V0(const Avtp_Tscf_t *const pdu, +OPEN1722_INLINE uint64_t Avtp_Tscf_GetField_V0(const Avtp_TscfV0_t *const pdu, Avtp_TscfFields_t field) { return Avtp_GetField(Avtp_TscfFieldDescV0, AVTP_TSCF_FIELD_MAX, (const uint8_t *)pdu, @@ -202,7 +209,7 @@ OPEN1722_INLINE uint64_t Avtp_Tscf_GetField(const Avtp_Tscf_t *const pdu, Avtp_T * @param value The value to set. * @see Avtp_Tscf_SetField */ -OPEN1722_INLINE void Avtp_Tscf_SetField_V0(Avtp_Tscf_t *pdu, Avtp_TscfFields_t field, +OPEN1722_INLINE void Avtp_Tscf_SetField_V0(Avtp_TscfV0_t *pdu, Avtp_TscfFields_t field, uint64_t value) { Avtp_SetField(Avtp_TscfFieldDescV0, AVTP_TSCF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); @@ -246,7 +253,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetField(Avtp_Tscf_t *pdu, Avtp_TscfFields_t fiel * pointer is not read; it keeps the signature aligned with the * version-dispatched accessors. */ -OPEN1722_INLINE uint8_t Avtp_Tscf_GetHeaderLen_V0(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Tscf_GetHeaderLen_V0(const Avtp_TscfV0_t *const pdu) { (void)pdu; return (uint8_t)AVTP_TSCF_HEADER_LEN_V0; @@ -511,7 +518,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetStreamDataLength(Avtp_Tscf_t *pdu, uint16_t va * @return Pointer to the TSCF frame payload. * @see Avtp_Tscf_GetPayload */ -OPEN1722_INLINE const uint8_t *Avtp_Tscf_GetPayload_V0(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE const uint8_t *Avtp_Tscf_GetPayload_V0(const Avtp_TscfV0_t *const pdu) { return (const uint8_t *)pdu + AVTP_TSCF_HEADER_LEN_V0; } @@ -551,7 +558,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Tscf_GetPayload(const Avtp_Tscf_t *const pdu * @param payload_length Length of the payload. * @see Avtp_Tscf_SetPayload */ -OPEN1722_INLINE void Avtp_Tscf_SetPayload_V0(Avtp_Tscf_t *pdu, uint8_t *payload, +OPEN1722_INLINE void Avtp_Tscf_SetPayload_V0(Avtp_TscfV0_t *pdu, uint8_t *payload, uint16_t payload_length) { memcpy((uint8_t *)pdu + AVTP_TSCF_HEADER_LEN_V0, payload, payload_length); @@ -633,10 +640,10 @@ OPEN1722_INLINE bool Avtp_Tscf_IsValid(const Avtp_Tscf_t *const pdu, size_t buff * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- * or an ACF header. */ -OPEN1722_INLINE void Avtp_Tscf_Init(Avtp_Tscf_t *pdu) +OPEN1722_INLINE void Avtp_Tscf_InitV0(Avtp_TscfV0_t *pdu) { if (pdu != NULL) { - memset(pdu, 0, sizeof(Avtp_Tscf_t)); + memset(pdu, 0, sizeof(Avtp_TscfV0_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_TSCF); Avtp_Tscf_SetSv(pdu, true); } @@ -659,6 +666,25 @@ OPEN1722_INLINE void Avtp_Tscf_InitV1(Avtp_TscfV1_t *pdu) } } +/** + * Initializes a TSCF PDU of the given version. The caller must provide a + * buffer of at least AVTP_TSCF_HEADER_LEN_V1 octets for version 1 (for + * example an Avtp_TscfV1_t); version 0 uses AVTP_TSCF_HEADER_LEN_V0 + * octets. Any version other than AVTPDU_VERSION_1 initializes a version 0 PDU. + * + * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- + * or an ACF header. + * @param version AVTPDU header version (AVTPDU_VERSION_0 or AVTPDU_VERSION_1). + */ +OPEN1722_INLINE void Avtp_Tscf_Init(Avtp_Tscf_t *pdu, uint8_t version) +{ + if (version == AVTPDU_VERSION_1) { + Avtp_Tscf_InitV1((Avtp_TscfV1_t *)pdu); + } else { + Avtp_Tscf_InitV0(pdu); + } +} + /* * Version-typed named accessors. These select the field layout for one * explicit version and never read the version field; the version-dispatched @@ -671,7 +697,7 @@ OPEN1722_INLINE void Avtp_Tscf_InitV1(Avtp_TscfV1_t *pdu) * Version 0 variant of Avtp_Tscf_IsSv(). * @see Avtp_Tscf_IsSv */ -OPEN1722_INLINE bool Avtp_Tscf_IsSv_V0(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE bool Avtp_Tscf_IsSv_V0(const Avtp_TscfV0_t *const pdu) { return Avtp_CommonStreamHeader_IsSv_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -689,7 +715,7 @@ OPEN1722_INLINE bool Avtp_Tscf_IsSv_V1(const Avtp_TscfV1_t *const pdu) * Version 0 variant of Avtp_Tscf_IsMr(). * @see Avtp_Tscf_IsMr */ -OPEN1722_INLINE bool Avtp_Tscf_IsMr_V0(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE bool Avtp_Tscf_IsMr_V0(const Avtp_TscfV0_t *const pdu) { return Avtp_CommonStreamHeader_IsMr_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -707,7 +733,7 @@ OPEN1722_INLINE bool Avtp_Tscf_IsMr_V1(const Avtp_TscfV1_t *const pdu) * Version 0 variant of Avtp_Tscf_IsTv(). * @see Avtp_Tscf_IsTv */ -OPEN1722_INLINE bool Avtp_Tscf_IsTv_V0(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE bool Avtp_Tscf_IsTv_V0(const Avtp_TscfV0_t *const pdu) { return Avtp_CommonStreamHeader_IsTv_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -725,7 +751,7 @@ OPEN1722_INLINE bool Avtp_Tscf_IsTv_V1(const Avtp_TscfV1_t *const pdu) * Version 0 variant of Avtp_Tscf_IsTu(). * @see Avtp_Tscf_IsTu */ -OPEN1722_INLINE bool Avtp_Tscf_IsTu_V0(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE bool Avtp_Tscf_IsTu_V0(const Avtp_TscfV0_t *const pdu) { return Avtp_CommonStreamHeader_IsTu_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -743,7 +769,7 @@ OPEN1722_INLINE bool Avtp_Tscf_IsTu_V1(const Avtp_TscfV1_t *const pdu) * Version 0 variant of Avtp_Tscf_GetSequenceNum(). * @see Avtp_Tscf_GetSequenceNum */ -OPEN1722_INLINE uint32_t Avtp_Tscf_GetSequenceNum_V0(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Tscf_GetSequenceNum_V0(const Avtp_TscfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetSequenceNum_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -762,7 +788,7 @@ OPEN1722_INLINE uint32_t Avtp_Tscf_GetSequenceNum_V1(const Avtp_TscfV1_t *const * 8-bit sequence_num field. * @see Avtp_Tscf_GetSequenceNumLsb */ -OPEN1722_INLINE uint8_t Avtp_Tscf_GetSequenceNumLsb_V0(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Tscf_GetSequenceNumLsb_V0(const Avtp_TscfV0_t *const pdu) { return (uint8_t)Avtp_Tscf_GetField_V0(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM); } @@ -782,7 +808,7 @@ OPEN1722_INLINE uint8_t Avtp_Tscf_GetSequenceNumLsb_V1(const Avtp_TscfV1_t *cons * Version 0 variant of Avtp_Tscf_GetStreamId(). * @see Avtp_Tscf_GetStreamId */ -OPEN1722_INLINE uint64_t Avtp_Tscf_GetStreamId_V0(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Tscf_GetStreamId_V0(const Avtp_TscfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetStreamId_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -800,7 +826,7 @@ OPEN1722_INLINE uint64_t Avtp_Tscf_GetStreamId_V1(const Avtp_TscfV1_t *const pdu * Version 0 variant of Avtp_Tscf_GetAvtpTimestamp(). * @see Avtp_Tscf_GetAvtpTimestamp */ -OPEN1722_INLINE uint64_t Avtp_Tscf_GetAvtpTimestamp_V0(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Tscf_GetAvtpTimestamp_V0(const Avtp_TscfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetAvtpTimestamp_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -819,7 +845,7 @@ OPEN1722_INLINE uint64_t Avtp_Tscf_GetAvtpTimestamp_V1(const Avtp_TscfV1_t *cons * absent from version 0, so this always returns 0. * @see Avtp_Tscf_GetPtpGrandmasterIdentity */ -OPEN1722_INLINE uint64_t Avtp_Tscf_GetPtpGrandmasterIdentity_V0(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Tscf_GetPtpGrandmasterIdentity_V0(const Avtp_TscfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V0( (const Avtp_CommonStreamHeader_t *)pdu); @@ -839,7 +865,7 @@ OPEN1722_INLINE uint64_t Avtp_Tscf_GetPtpGrandmasterIdentity_V1(const Avtp_TscfV * Version 0 variant of Avtp_Tscf_GetStreamDataLength(). * @see Avtp_Tscf_GetStreamDataLength */ -OPEN1722_INLINE uint16_t Avtp_Tscf_GetStreamDataLength_V0(const Avtp_Tscf_t *const pdu) +OPEN1722_INLINE uint16_t Avtp_Tscf_GetStreamDataLength_V0(const Avtp_TscfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetStreamDataLength_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -857,7 +883,7 @@ OPEN1722_INLINE uint16_t Avtp_Tscf_GetStreamDataLength_V1(const Avtp_TscfV1_t *c * Version 0 variant of Avtp_Tscf_SetSv(). * @see Avtp_Tscf_SetSv */ -OPEN1722_INLINE void Avtp_Tscf_SetSv_V0(Avtp_Tscf_t *pdu, bool sv) +OPEN1722_INLINE void Avtp_Tscf_SetSv_V0(Avtp_TscfV0_t *pdu, bool sv) { Avtp_CommonStreamHeader_SetSv_V0((Avtp_CommonStreamHeader_t *)pdu, sv); } @@ -875,7 +901,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetSv_V1(Avtp_TscfV1_t *pdu, bool sv) * Version 0 variant of Avtp_Tscf_SetMr(). * @see Avtp_Tscf_SetMr */ -OPEN1722_INLINE void Avtp_Tscf_SetMr_V0(Avtp_Tscf_t *pdu, bool mr) +OPEN1722_INLINE void Avtp_Tscf_SetMr_V0(Avtp_TscfV0_t *pdu, bool mr) { Avtp_CommonStreamHeader_SetMr_V0((Avtp_CommonStreamHeader_t *)pdu, mr); } @@ -893,7 +919,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetMr_V1(Avtp_TscfV1_t *pdu, bool mr) * Version 0 variant of Avtp_Tscf_SetTv(). * @see Avtp_Tscf_SetTv */ -OPEN1722_INLINE void Avtp_Tscf_SetTv_V0(Avtp_Tscf_t *pdu, bool tv) +OPEN1722_INLINE void Avtp_Tscf_SetTv_V0(Avtp_TscfV0_t *pdu, bool tv) { Avtp_CommonStreamHeader_SetTv_V0((Avtp_CommonStreamHeader_t *)pdu, tv); } @@ -911,7 +937,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetTv_V1(Avtp_TscfV1_t *pdu, bool tv) * Version 0 variant of Avtp_Tscf_SetTu(). * @see Avtp_Tscf_SetTu */ -OPEN1722_INLINE void Avtp_Tscf_SetTu_V0(Avtp_Tscf_t *pdu, bool tu) +OPEN1722_INLINE void Avtp_Tscf_SetTu_V0(Avtp_TscfV0_t *pdu, bool tu) { Avtp_CommonStreamHeader_SetTu_V0((Avtp_CommonStreamHeader_t *)pdu, tu); } @@ -930,7 +956,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetTu_V1(Avtp_TscfV1_t *pdu, bool tu) * 8-bit version 0 sequence_num field. * @see Avtp_Tscf_SetSequenceNum */ -OPEN1722_INLINE void Avtp_Tscf_SetSequenceNum_V0(Avtp_Tscf_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Tscf_SetSequenceNum_V0(Avtp_TscfV0_t *pdu, uint32_t value) { Avtp_Tscf_SetField_V0(pdu, AVTP_TSCF_FIELD_SEQUENCE_NUM, value); } @@ -951,7 +977,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetSequenceNum_V1(Avtp_TscfV1_t *pdu, uint32_t va * Version 0 variant of Avtp_Tscf_SetStreamId(). * @see Avtp_Tscf_SetStreamId */ -OPEN1722_INLINE void Avtp_Tscf_SetStreamId_V0(Avtp_Tscf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Tscf_SetStreamId_V0(Avtp_TscfV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetStreamId_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -969,7 +995,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetStreamId_V1(Avtp_TscfV1_t *pdu, uint64_t value * Version 0 variant of Avtp_Tscf_SetAvtpTimestamp(). * @see Avtp_Tscf_SetAvtpTimestamp */ -OPEN1722_INLINE void Avtp_Tscf_SetAvtpTimestamp_V0(Avtp_Tscf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Tscf_SetAvtpTimestamp_V0(Avtp_TscfV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetAvtpTimestamp_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -988,7 +1014,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetAvtpTimestamp_V1(Avtp_TscfV1_t *pdu, uint64_t * absent from version 0, so this is a no-op. * @see Avtp_Tscf_SetPtpGrandmasterIdentity */ -OPEN1722_INLINE void Avtp_Tscf_SetPtpGrandmasterIdentity_V0(Avtp_Tscf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Tscf_SetPtpGrandmasterIdentity_V0(Avtp_TscfV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1006,7 +1032,7 @@ OPEN1722_INLINE void Avtp_Tscf_SetPtpGrandmasterIdentity_V1(Avtp_TscfV1_t *pdu, * Version 0 variant of Avtp_Tscf_SetStreamDataLength(). * @see Avtp_Tscf_SetStreamDataLength */ -OPEN1722_INLINE void Avtp_Tscf_SetStreamDataLength_V0(Avtp_Tscf_t *pdu, uint16_t value) +OPEN1722_INLINE void Avtp_Tscf_SetStreamDataLength_V0(Avtp_TscfV0_t *pdu, uint16_t value) { Avtp_CommonStreamHeader_SetStreamDataLength_V0((Avtp_CommonStreamHeader_t *)pdu, value); } diff --git a/include/avtp/cvf/Cvf.h b/include/avtp/cvf/Cvf.h index 8fe439b8..10ae5cfe 100644 --- a/include/avtp/cvf/Cvf.h +++ b/include/avtp/cvf/Cvf.h @@ -69,13 +69,20 @@ extern "C" { typedef struct { uint8_t header[AVTP_CVF_HEADER_LEN_V0]; uint8_t payload[0]; -} __attribute__((packed)) Avtp_Cvf_t; +} __attribute__((packed)) Avtp_CvfV0_t; typedef struct { uint8_t header[AVTP_CVF_HEADER_LEN_V1]; uint8_t payload[0]; } __attribute__((packed)) Avtp_CvfV1_t; +/** + * Version-agnostic handle for CVF PDUs. It is an alias of the version 0 + * layout and is the pointer type of the version-agnostic accessors; version 1 + * PDUs use Avtp_CvfV1_t. For version 0 use Avtp_CvfV0_t. + */ +typedef Avtp_CvfV0_t Avtp_Cvf_t; + /** * CVF 'format' field values (IEEE 1722-2025, Table 20). Values 0x00-0x01 and * 0x03-0xFF are reserved. @@ -190,7 +197,7 @@ static const Avtp_FieldDescriptor_t Avtp_CvfFieldDescV1[AVTP_CVF_FIELD_MAX] = { * @returns This function returns the value of the field. * @see Avtp_Cvf_GetField */ -OPEN1722_INLINE uint64_t Avtp_Cvf_GetField_V0(const Avtp_Cvf_t *const pdu, Avtp_CvfFields_t field) +OPEN1722_INLINE uint64_t Avtp_Cvf_GetField_V0(const Avtp_CvfV0_t *const pdu, Avtp_CvfFields_t field) { return Avtp_GetField(Avtp_CvfFieldDescV0, AVTP_CVF_FIELD_MAX, (const uint8_t *)pdu, (uint8_t)field); @@ -236,7 +243,7 @@ OPEN1722_INLINE uint64_t Avtp_Cvf_GetField(const Avtp_Cvf_t *const pdu, Avtp_Cvf * @param value The value to set. * @see Avtp_Cvf_SetField */ -OPEN1722_INLINE void Avtp_Cvf_SetField_V0(Avtp_Cvf_t *pdu, Avtp_CvfFields_t field, uint64_t value) +OPEN1722_INLINE void Avtp_Cvf_SetField_V0(Avtp_CvfV0_t *pdu, Avtp_CvfFields_t field, uint64_t value) { Avtp_SetField(Avtp_CvfFieldDescV0, AVTP_CVF_FIELD_MAX, (uint8_t *)pdu, (uint8_t)field, value); } @@ -278,7 +285,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetField(Avtp_Cvf_t *pdu, Avtp_CvfFields_t field, * pointer is not read; it keeps the signature aligned with the * version-dispatched accessors. */ -OPEN1722_INLINE uint8_t Avtp_Cvf_GetHeaderLen_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Cvf_GetHeaderLen_V0(const Avtp_CvfV0_t *const pdu) { (void)pdu; return (uint8_t)AVTP_CVF_HEADER_LEN_V0; @@ -635,7 +642,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetEvt(Avtp_Cvf_t *pdu, uint8_t value) * @return Pointer to CVF stream data * @see Avtp_Cvf_GetPayload */ -OPEN1722_INLINE const uint8_t *Avtp_Cvf_GetPayload_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE const uint8_t *Avtp_Cvf_GetPayload_V0(const Avtp_CvfV0_t *const pdu) { return (const uint8_t *)pdu + AVTP_CVF_HEADER_LEN_V0; } @@ -678,7 +685,7 @@ OPEN1722_INLINE const uint8_t *Avtp_Cvf_GetPayload(const Avtp_Cvf_t *const pdu) * @param payload_length Length of the payload * @see Avtp_Cvf_SetPayload */ -OPEN1722_INLINE void Avtp_Cvf_SetPayload_V0(Avtp_Cvf_t *pdu, uint8_t *payload, +OPEN1722_INLINE void Avtp_Cvf_SetPayload_V0(Avtp_CvfV0_t *pdu, uint8_t *payload, uint16_t payload_length) { memcpy((uint8_t *)pdu + AVTP_CVF_HEADER_LEN_V0, payload, payload_length); @@ -720,10 +727,10 @@ OPEN1722_INLINE void Avtp_Cvf_SetPayload(Avtp_Cvf_t *pdu, uint8_t *payload, uint * * @param pdu Pointer to the first bit of a 1722 CVF PDU. */ -OPEN1722_INLINE void Avtp_Cvf_Init(Avtp_Cvf_t *pdu) +OPEN1722_INLINE void Avtp_Cvf_InitV0(Avtp_CvfV0_t *pdu) { if (pdu != NULL) { - memset(pdu, 0, sizeof(Avtp_Cvf_t)); + memset(pdu, 0, sizeof(Avtp_CvfV0_t)); Avtp_CommonHeader_SetSubtype((Avtp_CommonHeader_t *)pdu, AVTP_SUBTYPE_CVF); Avtp_Cvf_SetFormat(pdu, AVTP_CVF_FORMAT_RFC); Avtp_Cvf_SetSv(pdu, true); @@ -788,6 +795,25 @@ OPEN1722_INLINE bool Avtp_Cvf_IsValid(const Avtp_Cvf_t *const pdu, size_t buffer return true; } +/** + * Initializes a CVF PDU of the given version. The caller must provide a + * buffer of at least AVTP_CVF_HEADER_LEN_V1 octets for version 1 (for + * example an Avtp_CvfV1_t); version 0 uses AVTP_CVF_HEADER_LEN_V0 + * octets. Any version other than AVTPDU_VERSION_1 initializes a version 0 PDU. + * + * @param pdu Pointer to the first bit of a 1722 PDU. This is typically an AVTP- + * or an ACF header. + * @param version AVTPDU header version (AVTPDU_VERSION_0 or AVTPDU_VERSION_1). + */ +OPEN1722_INLINE void Avtp_Cvf_Init(Avtp_Cvf_t *pdu, uint8_t version) +{ + if (version == AVTPDU_VERSION_1) { + Avtp_Cvf_InitV1((Avtp_CvfV1_t *)pdu); + } else { + Avtp_Cvf_InitV0(pdu); + } +} + /* * Version-typed named accessors. These select the field layout for one * explicit version and never read the version field; the version-dispatched @@ -800,7 +826,7 @@ OPEN1722_INLINE bool Avtp_Cvf_IsValid(const Avtp_Cvf_t *const pdu, size_t buffer * Version 0 variant of Avtp_Cvf_IsSv(). * @see Avtp_Cvf_IsSv */ -OPEN1722_INLINE bool Avtp_Cvf_IsSv_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Cvf_IsSv_V0(const Avtp_CvfV0_t *const pdu) { return Avtp_CommonStreamHeader_IsSv_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -818,7 +844,7 @@ OPEN1722_INLINE bool Avtp_Cvf_IsSv_V1(const Avtp_CvfV1_t *const pdu) * Version 0 variant of Avtp_Cvf_IsMr(). * @see Avtp_Cvf_IsMr */ -OPEN1722_INLINE bool Avtp_Cvf_IsMr_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Cvf_IsMr_V0(const Avtp_CvfV0_t *const pdu) { return Avtp_CommonStreamHeader_IsMr_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -836,7 +862,7 @@ OPEN1722_INLINE bool Avtp_Cvf_IsMr_V1(const Avtp_CvfV1_t *const pdu) * Version 0 variant of Avtp_Cvf_IsTv(). * @see Avtp_Cvf_IsTv */ -OPEN1722_INLINE bool Avtp_Cvf_IsTv_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Cvf_IsTv_V0(const Avtp_CvfV0_t *const pdu) { return Avtp_CommonStreamHeader_IsTv_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -854,7 +880,7 @@ OPEN1722_INLINE bool Avtp_Cvf_IsTv_V1(const Avtp_CvfV1_t *const pdu) * Version 0 variant of Avtp_Cvf_IsTu(). * @see Avtp_Cvf_IsTu */ -OPEN1722_INLINE bool Avtp_Cvf_IsTu_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Cvf_IsTu_V0(const Avtp_CvfV0_t *const pdu) { return Avtp_CommonStreamHeader_IsTu_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -873,7 +899,7 @@ OPEN1722_INLINE bool Avtp_Cvf_IsTu_V1(const Avtp_CvfV1_t *const pdu) * 8-bit version 0 field width. * @see Avtp_Cvf_GetSequenceNum */ -OPEN1722_INLINE uint32_t Avtp_Cvf_GetSequenceNum_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE uint32_t Avtp_Cvf_GetSequenceNum_V0(const Avtp_CvfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetSequenceNum_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -891,7 +917,7 @@ OPEN1722_INLINE uint32_t Avtp_Cvf_GetSequenceNum_V1(const Avtp_CvfV1_t *const pd * Version 0 variant of Avtp_Cvf_GetStreamId(). * @see Avtp_Cvf_GetStreamId */ -OPEN1722_INLINE uint64_t Avtp_Cvf_GetStreamId_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Cvf_GetStreamId_V0(const Avtp_CvfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetStreamId_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -909,7 +935,7 @@ OPEN1722_INLINE uint64_t Avtp_Cvf_GetStreamId_V1(const Avtp_CvfV1_t *const pdu) * Version 0 variant of Avtp_Cvf_GetAvtpTimestamp(). * @see Avtp_Cvf_GetAvtpTimestamp */ -OPEN1722_INLINE uint64_t Avtp_Cvf_GetAvtpTimestamp_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Cvf_GetAvtpTimestamp_V0(const Avtp_CvfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetAvtpTimestamp_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -928,7 +954,7 @@ OPEN1722_INLINE uint64_t Avtp_Cvf_GetAvtpTimestamp_V1(const Avtp_CvfV1_t *const * absent from version 0, so this always returns 0. * @see Avtp_Cvf_GetPtpGrandmasterIdentity */ -OPEN1722_INLINE uint64_t Avtp_Cvf_GetPtpGrandmasterIdentity_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE uint64_t Avtp_Cvf_GetPtpGrandmasterIdentity_V0(const Avtp_CvfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetPtpGrandmasterIdentity_V0( (const Avtp_CommonStreamHeader_t *)pdu); @@ -948,7 +974,7 @@ OPEN1722_INLINE uint64_t Avtp_Cvf_GetPtpGrandmasterIdentity_V1(const Avtp_CvfV1_ * Version 0 variant of Avtp_Cvf_GetFormat(). * @see Avtp_Cvf_GetFormat */ -OPEN1722_INLINE Avtp_CvfFormat_t Avtp_Cvf_GetFormat_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE Avtp_CvfFormat_t Avtp_Cvf_GetFormat_V0(const Avtp_CvfV0_t *const pdu) { return (Avtp_CvfFormat_t)Avtp_Cvf_GetField_V0(pdu, AVTP_CVF_FIELD_FORMAT); } @@ -966,7 +992,7 @@ OPEN1722_INLINE Avtp_CvfFormat_t Avtp_Cvf_GetFormat_V1(const Avtp_CvfV1_t *const * Version 0 variant of Avtp_Cvf_GetFormatSubtype(). * @see Avtp_Cvf_GetFormatSubtype */ -OPEN1722_INLINE Avtp_CvfFormatSubtype_t Avtp_Cvf_GetFormatSubtype_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE Avtp_CvfFormatSubtype_t Avtp_Cvf_GetFormatSubtype_V0(const Avtp_CvfV0_t *const pdu) { return (Avtp_CvfFormatSubtype_t)Avtp_Cvf_GetField_V0(pdu, AVTP_CVF_FIELD_FORMAT_SUBTYPE); } @@ -984,7 +1010,7 @@ OPEN1722_INLINE Avtp_CvfFormatSubtype_t Avtp_Cvf_GetFormatSubtype_V1(const Avtp_ * Version 0 variant of Avtp_Cvf_GetStreamDataLength(). * @see Avtp_Cvf_GetStreamDataLength */ -OPEN1722_INLINE uint16_t Avtp_Cvf_GetStreamDataLength_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE uint16_t Avtp_Cvf_GetStreamDataLength_V0(const Avtp_CvfV0_t *const pdu) { return Avtp_CommonStreamHeader_GetStreamDataLength_V0((const Avtp_CommonStreamHeader_t *)pdu); } @@ -1002,7 +1028,7 @@ OPEN1722_INLINE uint16_t Avtp_Cvf_GetStreamDataLength_V1(const Avtp_CvfV1_t *con * Version 0 variant of Avtp_Cvf_IsPtv(). * @see Avtp_Cvf_IsPtv */ -OPEN1722_INLINE bool Avtp_Cvf_IsPtv_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Cvf_IsPtv_V0(const Avtp_CvfV0_t *const pdu) { return (bool)Avtp_Cvf_GetField_V0(pdu, AVTP_CVF_FIELD_PTV); } @@ -1020,7 +1046,7 @@ OPEN1722_INLINE bool Avtp_Cvf_IsPtv_V1(const Avtp_CvfV1_t *const pdu) * Version 0 variant of Avtp_Cvf_IsM(). * @see Avtp_Cvf_IsM */ -OPEN1722_INLINE bool Avtp_Cvf_IsM_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE bool Avtp_Cvf_IsM_V0(const Avtp_CvfV0_t *const pdu) { return (bool)Avtp_Cvf_GetField_V0(pdu, AVTP_CVF_FIELD_M); } @@ -1038,7 +1064,7 @@ OPEN1722_INLINE bool Avtp_Cvf_IsM_V1(const Avtp_CvfV1_t *const pdu) * Version 0 variant of Avtp_Cvf_GetEvt(). * @see Avtp_Cvf_GetEvt */ -OPEN1722_INLINE uint8_t Avtp_Cvf_GetEvt_V0(const Avtp_Cvf_t *const pdu) +OPEN1722_INLINE uint8_t Avtp_Cvf_GetEvt_V0(const Avtp_CvfV0_t *const pdu) { return (uint8_t)Avtp_Cvf_GetField_V0(pdu, AVTP_CVF_FIELD_EVT); } @@ -1056,7 +1082,7 @@ OPEN1722_INLINE uint8_t Avtp_Cvf_GetEvt_V1(const Avtp_CvfV1_t *const pdu) * Version 0 variant of Avtp_Cvf_SetSv(). * @see Avtp_Cvf_SetSv */ -OPEN1722_INLINE void Avtp_Cvf_SetSv_V0(Avtp_Cvf_t *pdu, bool sv) +OPEN1722_INLINE void Avtp_Cvf_SetSv_V0(Avtp_CvfV0_t *pdu, bool sv) { Avtp_CommonStreamHeader_SetSv_V0((Avtp_CommonStreamHeader_t *)pdu, sv); } @@ -1074,7 +1100,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetSv_V1(Avtp_CvfV1_t *pdu, bool sv) * Version 0 variant of Avtp_Cvf_SetMr(). * @see Avtp_Cvf_SetMr */ -OPEN1722_INLINE void Avtp_Cvf_SetMr_V0(Avtp_Cvf_t *pdu, bool mr) +OPEN1722_INLINE void Avtp_Cvf_SetMr_V0(Avtp_CvfV0_t *pdu, bool mr) { Avtp_CommonStreamHeader_SetMr_V0((Avtp_CommonStreamHeader_t *)pdu, mr); } @@ -1092,7 +1118,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetMr_V1(Avtp_CvfV1_t *pdu, bool mr) * Version 0 variant of Avtp_Cvf_SetTv(). * @see Avtp_Cvf_SetTv */ -OPEN1722_INLINE void Avtp_Cvf_SetTv_V0(Avtp_Cvf_t *pdu, bool tv) +OPEN1722_INLINE void Avtp_Cvf_SetTv_V0(Avtp_CvfV0_t *pdu, bool tv) { Avtp_CommonStreamHeader_SetTv_V0((Avtp_CommonStreamHeader_t *)pdu, tv); } @@ -1110,7 +1136,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetTv_V1(Avtp_CvfV1_t *pdu, bool tv) * Version 0 variant of Avtp_Cvf_SetTu(). * @see Avtp_Cvf_SetTu */ -OPEN1722_INLINE void Avtp_Cvf_SetTu_V0(Avtp_Cvf_t *pdu, bool tu) +OPEN1722_INLINE void Avtp_Cvf_SetTu_V0(Avtp_CvfV0_t *pdu, bool tu) { Avtp_CommonStreamHeader_SetTu_V0((Avtp_CommonStreamHeader_t *)pdu, tu); } @@ -1129,7 +1155,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetTu_V1(Avtp_CvfV1_t *pdu, bool tu) * 8-bit version 0 field width. * @see Avtp_Cvf_SetSequenceNum */ -OPEN1722_INLINE void Avtp_Cvf_SetSequenceNum_V0(Avtp_Cvf_t *pdu, uint32_t value) +OPEN1722_INLINE void Avtp_Cvf_SetSequenceNum_V0(Avtp_CvfV0_t *pdu, uint32_t value) { Avtp_CommonStreamHeader_SetSequenceNum_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1147,7 +1173,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetSequenceNum_V1(Avtp_CvfV1_t *pdu, uint32_t valu * Version 0 variant of Avtp_Cvf_SetStreamId(). * @see Avtp_Cvf_SetStreamId */ -OPEN1722_INLINE void Avtp_Cvf_SetStreamId_V0(Avtp_Cvf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Cvf_SetStreamId_V0(Avtp_CvfV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetStreamId_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1165,7 +1191,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetStreamId_V1(Avtp_CvfV1_t *pdu, uint64_t value) * Version 0 variant of Avtp_Cvf_SetAvtpTimestamp(). * @see Avtp_Cvf_SetAvtpTimestamp */ -OPEN1722_INLINE void Avtp_Cvf_SetAvtpTimestamp_V0(Avtp_Cvf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Cvf_SetAvtpTimestamp_V0(Avtp_CvfV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetAvtpTimestamp_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1184,7 +1210,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetAvtpTimestamp_V1(Avtp_CvfV1_t *pdu, uint64_t va * absent from version 0, so this is a no-op. * @see Avtp_Cvf_SetPtpGrandmasterIdentity */ -OPEN1722_INLINE void Avtp_Cvf_SetPtpGrandmasterIdentity_V0(Avtp_Cvf_t *pdu, uint64_t value) +OPEN1722_INLINE void Avtp_Cvf_SetPtpGrandmasterIdentity_V0(Avtp_CvfV0_t *pdu, uint64_t value) { Avtp_CommonStreamHeader_SetPtpGrandmasterIdentity_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1202,7 +1228,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetPtpGrandmasterIdentity_V1(Avtp_CvfV1_t *pdu, ui * Version 0 variant of Avtp_Cvf_SetFormat(). * @see Avtp_Cvf_SetFormat */ -OPEN1722_INLINE void Avtp_Cvf_SetFormat_V0(Avtp_Cvf_t *pdu, Avtp_CvfFormat_t value) +OPEN1722_INLINE void Avtp_Cvf_SetFormat_V0(Avtp_CvfV0_t *pdu, Avtp_CvfFormat_t value) { Avtp_Cvf_SetField_V0(pdu, AVTP_CVF_FIELD_FORMAT, (uint64_t)value); } @@ -1220,7 +1246,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetFormat_V1(Avtp_CvfV1_t *pdu, Avtp_CvfFormat_t v * Version 0 variant of Avtp_Cvf_SetFormatSubtype(). * @see Avtp_Cvf_SetFormatSubtype */ -OPEN1722_INLINE void Avtp_Cvf_SetFormatSubtype_V0(Avtp_Cvf_t *pdu, Avtp_CvfFormatSubtype_t value) +OPEN1722_INLINE void Avtp_Cvf_SetFormatSubtype_V0(Avtp_CvfV0_t *pdu, Avtp_CvfFormatSubtype_t value) { Avtp_Cvf_SetField_V0(pdu, AVTP_CVF_FIELD_FORMAT_SUBTYPE, (uint64_t)value); } @@ -1238,7 +1264,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetFormatSubtype_V1(Avtp_CvfV1_t *pdu, Avtp_CvfFor * Version 0 variant of Avtp_Cvf_SetStreamDataLength(). * @see Avtp_Cvf_SetStreamDataLength */ -OPEN1722_INLINE void Avtp_Cvf_SetStreamDataLength_V0(Avtp_Cvf_t *pdu, uint16_t value) +OPEN1722_INLINE void Avtp_Cvf_SetStreamDataLength_V0(Avtp_CvfV0_t *pdu, uint16_t value) { Avtp_CommonStreamHeader_SetStreamDataLength_V0((Avtp_CommonStreamHeader_t *)pdu, value); } @@ -1256,7 +1282,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetStreamDataLength_V1(Avtp_CvfV1_t *pdu, uint16_t * Version 0 variant of Avtp_Cvf_SetPtv(). * @see Avtp_Cvf_SetPtv */ -OPEN1722_INLINE void Avtp_Cvf_SetPtv_V0(Avtp_Cvf_t *pdu, bool ptv) +OPEN1722_INLINE void Avtp_Cvf_SetPtv_V0(Avtp_CvfV0_t *pdu, bool ptv) { Avtp_Cvf_SetField_V0(pdu, AVTP_CVF_FIELD_PTV, ptv); } @@ -1274,7 +1300,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetPtv_V1(Avtp_CvfV1_t *pdu, bool ptv) * Version 0 variant of Avtp_Cvf_SetM(). * @see Avtp_Cvf_SetM */ -OPEN1722_INLINE void Avtp_Cvf_SetM_V0(Avtp_Cvf_t *pdu, bool m) +OPEN1722_INLINE void Avtp_Cvf_SetM_V0(Avtp_CvfV0_t *pdu, bool m) { Avtp_Cvf_SetField_V0(pdu, AVTP_CVF_FIELD_M, m); } @@ -1292,7 +1318,7 @@ OPEN1722_INLINE void Avtp_Cvf_SetM_V1(Avtp_CvfV1_t *pdu, bool m) * Version 0 variant of Avtp_Cvf_SetEvt(). * @see Avtp_Cvf_SetEvt */ -OPEN1722_INLINE void Avtp_Cvf_SetEvt_V0(Avtp_Cvf_t *pdu, uint8_t value) +OPEN1722_INLINE void Avtp_Cvf_SetEvt_V0(Avtp_CvfV0_t *pdu, uint8_t value) { Avtp_Cvf_SetField_V0(pdu, AVTP_CVF_FIELD_EVT, value); } diff --git a/unit/test-aaf.c b/unit/test-aaf.c index 123ad439..ea457a0c 100644 --- a/unit/test-aaf.c +++ b/unit/test-aaf.c @@ -74,9 +74,9 @@ static void aaf_init(void **state) assert_int_equal(sizeof(Avtp_Aaf_t), AVTP_AAF_HEADER_LEN_V0); /* Passing a NULL pointer must be a no-op. */ - Avtp_Aaf_Init(NULL); + Avtp_Aaf_InitV0(NULL); - Avtp_Aaf_Init((Avtp_Aaf_t *)pdu); + Avtp_Aaf_InitV0((Avtp_Aaf_t *)pdu); memset(init_pdu, 0, AVTP_AAF_HEADER_LEN_V0); init_pdu[0] = AVTP_SUBTYPE_AAF; /* subtype = AAF */ init_pdu[1] = 0x80; /* sv = 1, version = 0 */ @@ -103,13 +103,37 @@ static void aaf_init_v1(void **state) assert_int_equal(Avtp_Aaf_GetHeaderLen((Avtp_Aaf_t *)pdu), AVTP_AAF_HEADER_LEN_V1); } +static void aaf_init_version(void **state) +{ + (void)state; + uint8_t typed[MAX_PDU_SIZE]; + uint8_t generic[MAX_PDU_SIZE]; + + assert_int_equal(sizeof(Avtp_Aaf_t), sizeof(Avtp_AafV0_t)); + + Avtp_Aaf_InitV0((Avtp_Aaf_t *)typed); + Avtp_Aaf_Init((Avtp_Aaf_t *)generic, AVTPDU_VERSION_0); + assert_memory_equal(typed, generic, AVTP_AAF_HEADER_LEN_V0); + + Avtp_Aaf_InitV1((Avtp_AafV1_t *)typed); + Avtp_Aaf_Init((Avtp_Aaf_t *)generic, AVTPDU_VERSION_1); + assert_memory_equal(typed, generic, AVTP_AAF_HEADER_LEN_V1); + + /* Unsupported versions initialize a version 0 PDU. */ + Avtp_Aaf_Init((Avtp_Aaf_t *)generic, 2); + Avtp_Aaf_InitV0((Avtp_Aaf_t *)typed); + assert_memory_equal(typed, generic, AVTP_AAF_HEADER_LEN_V0); + assert_int_equal(Avtp_CommonHeader_GetVersion((Avtp_CommonHeader_t *)generic), + AVTPDU_VERSION_0); +} + static void aaf_is_valid(void **state) { (void)state; uint8_t pdu[MAX_PDU_SIZE]; Avtp_Aaf_t *aaf = (Avtp_Aaf_t *)pdu; - Avtp_Aaf_Init(aaf); + Avtp_Aaf_InitV0(aaf); assert_true(Avtp_Aaf_IsValid(aaf, AVTP_AAF_HEADER_LEN_V0)); /* NULL pdu. */ @@ -120,11 +144,11 @@ static void aaf_is_valid(void **state) assert_false(Avtp_Aaf_IsValid(aaf, MAX_PDU_SIZE)); /* Buffer smaller than the AAF header. */ - Avtp_Aaf_Init(aaf); + Avtp_Aaf_InitV0(aaf); assert_false(Avtp_Aaf_IsValid(aaf, AVTP_AAF_HEADER_LEN_V0 - 1)); /* stream_data_length does not fit into the buffer. */ - Avtp_Aaf_Init(aaf); + Avtp_Aaf_InitV0(aaf); Avtp_Aaf_SetStreamDataLength(aaf, 10); assert_false(Avtp_Aaf_IsValid(aaf, AVTP_AAF_HEADER_LEN_V0 + 9)); assert_true(Avtp_Aaf_IsValid(aaf, AVTP_AAF_HEADER_LEN_V0 + 10)); @@ -137,7 +161,7 @@ static void aaf_is_valid(void **state) assert_false(Avtp_Aaf_IsValid((Avtp_Aaf_t *)pdu, AVTP_AAF_HEADER_LEN_V1 - 1)); /* Unsupported version is rejected. */ - Avtp_Aaf_Init(aaf); + Avtp_Aaf_InitV0(aaf); Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, 2); assert_false(Avtp_Aaf_IsValid(aaf, MAX_PDU_SIZE)); } @@ -215,7 +239,7 @@ static void aaf_flag_fields(void **state) uint8_t pdu[MAX_PDU_SIZE]; Avtp_Aaf_t *aaf = (Avtp_Aaf_t *)pdu; - Avtp_Aaf_Init(aaf); + Avtp_Aaf_InitV0(aaf); assert_true(Avtp_Aaf_IsSv(aaf)); Avtp_Aaf_SetSv(aaf, false); @@ -345,7 +369,7 @@ static void aaf_payload(void **state) uint8_t payload_out[8] = {0}; Avtp_Aaf_t *aaf = (Avtp_Aaf_t *)pdu; - Avtp_Aaf_Init(aaf); + Avtp_Aaf_InitV0(aaf); Avtp_Aaf_SetPayload(aaf, payload, sizeof(payload)); assert_ptr_equal(Avtp_Aaf_GetPayload(aaf), pdu + AVTP_AAF_HEADER_LEN_V0); @@ -386,7 +410,7 @@ static void aaf_typed_fields_v0(void **state) uint8_t pdu[AVTP_AAF_HEADER_LEN_V1]; Avtp_Aaf_t *aaf = (Avtp_Aaf_t *)pdu; - Avtp_Aaf_Init(aaf); + Avtp_Aaf_InitV0(aaf); for (uint8_t f = 0; f < AVTP_AAF_FIELD_MAX; f++) { uint8_t bits = Avtp_AafFieldDescV0[f].bits; @@ -430,7 +454,7 @@ static void aaf_typed_named(void **state) Avtp_AafV1_t *v1 = (Avtp_AafV1_t *)pdu; /* Version 0. */ - Avtp_Aaf_Init(v0); + Avtp_Aaf_InitV0(v0); Avtp_Aaf_SetSv_V0(v0, true); Avtp_Aaf_SetMr_V0(v0, true); Avtp_Aaf_SetTv_V0(v0, true); @@ -516,7 +540,7 @@ static void aaf_typed_helpers(void **state) uint8_t pdu[MAX_PDU_SIZE]; uint8_t payload[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - Avtp_Aaf_Init((Avtp_Aaf_t *)pdu); + Avtp_Aaf_InitV0((Avtp_Aaf_t *)pdu); assert_int_equal(Avtp_Aaf_GetHeaderLen_V0((Avtp_Aaf_t *)pdu), AVTP_AAF_HEADER_LEN_V0); assert_ptr_equal(Avtp_Aaf_GetPayload_V0((Avtp_Aaf_t *)pdu), pdu + AVTP_AAF_HEADER_LEN_V0); Avtp_Aaf_SetPayload_V0((Avtp_Aaf_t *)pdu, payload, sizeof(payload)); @@ -534,6 +558,7 @@ int main(void) const struct CMUnitTest tests[] = { cmocka_unit_test(aaf_init), cmocka_unit_test(aaf_init_v1), + cmocka_unit_test(aaf_init_version), cmocka_unit_test(aaf_is_valid), cmocka_unit_test(aaf_field_descriptors_cover_header), cmocka_unit_test(aaf_common_field_consistency), diff --git a/unit/test-crf.c b/unit/test-crf.c index 9029b63b..ef600f42 100644 --- a/unit/test-crf.c +++ b/unit/test-crf.c @@ -69,7 +69,7 @@ static uint64_t mask_field_value(uint8_t bits, uint64_t value) /* Initializes a minimal but valid CRF frame. */ static void init_valid_crf(Avtp_Crf_t *pdu) { - Avtp_Crf_Init(pdu); + Avtp_Crf_InitV0(pdu); Avtp_Crf_SetCrfDataLength(pdu, 8); Avtp_Crf_SetTimestampInterval(pdu, 1); } @@ -83,9 +83,9 @@ static void crf_init(void **state) assert_int_equal(sizeof(Avtp_Crf_t), AVTP_CRF_HEADER_LEN_V0); /* Passing a NULL pointer must be a no-op. */ - Avtp_Crf_Init(NULL); + Avtp_Crf_InitV0(NULL); - Avtp_Crf_Init((Avtp_Crf_t *)pdu); + Avtp_Crf_InitV0((Avtp_Crf_t *)pdu); memset(init_pdu, 0, AVTP_CRF_HEADER_LEN_V0); init_pdu[0] = AVTP_SUBTYPE_CRF; /* subtype = CRF */ init_pdu[1] = 0x80; /* sv = 1, version = 0 */ @@ -112,6 +112,30 @@ static void crf_init_v1(void **state) assert_int_equal(Avtp_Crf_GetHeaderLen((Avtp_Crf_t *)pdu), AVTP_CRF_HEADER_LEN_V1); } +static void crf_init_version(void **state) +{ + (void)state; + uint8_t typed[MAX_PDU_SIZE]; + uint8_t generic[MAX_PDU_SIZE]; + + assert_int_equal(sizeof(Avtp_Crf_t), sizeof(Avtp_CrfV0_t)); + + Avtp_Crf_InitV0((Avtp_Crf_t *)typed); + Avtp_Crf_Init((Avtp_Crf_t *)generic, AVTPDU_VERSION_0); + assert_memory_equal(typed, generic, AVTP_CRF_HEADER_LEN_V0); + + Avtp_Crf_InitV1((Avtp_CrfV1_t *)typed); + Avtp_Crf_Init((Avtp_Crf_t *)generic, AVTPDU_VERSION_1); + assert_memory_equal(typed, generic, AVTP_CRF_HEADER_LEN_V1); + + /* Unsupported versions initialize a version 0 PDU. */ + Avtp_Crf_Init((Avtp_Crf_t *)generic, 2); + Avtp_Crf_InitV0((Avtp_Crf_t *)typed); + assert_memory_equal(typed, generic, AVTP_CRF_HEADER_LEN_V0); + assert_int_equal(Avtp_CommonHeader_GetVersion((Avtp_CommonHeader_t *)generic), + AVTPDU_VERSION_0); +} + static void crf_is_valid(void **state) { (void)state; @@ -232,7 +256,7 @@ static void crf_flag_fields(void **state) uint8_t pdu[MAX_PDU_SIZE]; Avtp_Crf_t *crf = (Avtp_Crf_t *)pdu; - Avtp_Crf_Init(crf); + Avtp_Crf_InitV0(crf); assert_true(Avtp_Crf_IsSv(crf)); Avtp_Crf_SetSv(crf, false); @@ -345,7 +369,7 @@ static void crf_payload(void **state) uint8_t payload_out[8] = {0}; Avtp_Crf_t *crf = (Avtp_Crf_t *)pdu; - Avtp_Crf_Init(crf); + Avtp_Crf_InitV0(crf); Avtp_Crf_SetPayload(crf, payload, sizeof(payload)); assert_ptr_equal(Avtp_Crf_GetPayload(crf), pdu + AVTP_CRF_HEADER_LEN_V0); @@ -384,7 +408,7 @@ static void crf_typed_fields_v0(void **state) uint8_t pdu[AVTP_CRF_HEADER_LEN_V1]; Avtp_Crf_t *crf = (Avtp_Crf_t *)pdu; - Avtp_Crf_Init(crf); + Avtp_Crf_InitV0(crf); for (uint8_t f = 0; f < AVTP_CRF_FIELD_MAX; f++) { uint8_t bits = Avtp_CrfFieldDescV0[f].bits; @@ -428,7 +452,7 @@ static void crf_typed_named(void **state) Avtp_CrfV1_t *v1 = (Avtp_CrfV1_t *)pdu; /* Version 0. */ - Avtp_Crf_Init(v0); + Avtp_Crf_InitV0(v0); Avtp_Crf_SetSv_V0(v0, true); Avtp_Crf_SetMr_V0(v0, true); Avtp_Crf_SetFs_V0(v0, true); @@ -507,7 +531,7 @@ static void crf_typed_helpers(void **state) uint8_t pdu[MAX_PDU_SIZE]; uint8_t payload[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - Avtp_Crf_Init((Avtp_Crf_t *)pdu); + Avtp_Crf_InitV0((Avtp_Crf_t *)pdu); assert_int_equal(Avtp_Crf_GetHeaderLen_V0((Avtp_Crf_t *)pdu), AVTP_CRF_HEADER_LEN_V0); assert_ptr_equal(Avtp_Crf_GetPayload_V0((Avtp_Crf_t *)pdu), pdu + AVTP_CRF_HEADER_LEN_V0); Avtp_Crf_SetPayload_V0((Avtp_Crf_t *)pdu, payload, sizeof(payload)); @@ -525,6 +549,7 @@ int main(void) const struct CMUnitTest tests[] = { cmocka_unit_test(crf_init), cmocka_unit_test(crf_init_v1), + cmocka_unit_test(crf_init_version), cmocka_unit_test(crf_is_valid), cmocka_unit_test(crf_field_descriptors_cover_header), cmocka_unit_test(crf_ah_field_consistency), diff --git a/unit/test-cvf.c b/unit/test-cvf.c index 73d95f2f..0091d60b 100644 --- a/unit/test-cvf.c +++ b/unit/test-cvf.c @@ -82,9 +82,9 @@ static void cvf_init(void **state) assert_int_equal(sizeof(Avtp_Cvf_t), AVTP_CVF_HEADER_LEN_V0); /* Passing a NULL pointer must be a no-op. */ - Avtp_Cvf_Init(NULL); + Avtp_Cvf_InitV0(NULL); - Avtp_Cvf_Init((Avtp_Cvf_t *)pdu); + Avtp_Cvf_InitV0((Avtp_Cvf_t *)pdu); memset(init_pdu, 0, AVTP_CVF_HEADER_LEN_V0); init_pdu[0] = AVTP_SUBTYPE_CVF; /* subtype = CVF */ init_pdu[1] = 0x80; /* sv = 1, version = 0 */ @@ -113,12 +113,36 @@ static void cvf_init_v1(void **state) assert_int_equal(Avtp_Cvf_GetHeaderLen((Avtp_Cvf_t *)pdu), AVTP_CVF_HEADER_LEN_V1); } +static void cvf_init_version(void **state) +{ + (void)state; + uint8_t typed[MAX_PDU_SIZE]; + uint8_t generic[MAX_PDU_SIZE]; + + assert_int_equal(sizeof(Avtp_Cvf_t), sizeof(Avtp_CvfV0_t)); + + Avtp_Cvf_InitV0((Avtp_Cvf_t *)typed); + Avtp_Cvf_Init((Avtp_Cvf_t *)generic, AVTPDU_VERSION_0); + assert_memory_equal(typed, generic, AVTP_CVF_HEADER_LEN_V0); + + Avtp_Cvf_InitV1((Avtp_CvfV1_t *)typed); + Avtp_Cvf_Init((Avtp_Cvf_t *)generic, AVTPDU_VERSION_1); + assert_memory_equal(typed, generic, AVTP_CVF_HEADER_LEN_V1); + + /* Unsupported versions initialize a version 0 PDU. */ + Avtp_Cvf_Init((Avtp_Cvf_t *)generic, 2); + Avtp_Cvf_InitV0((Avtp_Cvf_t *)typed); + assert_memory_equal(typed, generic, AVTP_CVF_HEADER_LEN_V0); + assert_int_equal(Avtp_CommonHeader_GetVersion((Avtp_CommonHeader_t *)generic), + AVTPDU_VERSION_0); +} + static void cvf_is_valid(void **state) { (void)state; uint8_t pdu[MAX_PDU_SIZE]; - Avtp_Cvf_Init((Avtp_Cvf_t *)pdu); + Avtp_Cvf_InitV0((Avtp_Cvf_t *)pdu); assert_true(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN_V0)); /* NULL pdu. */ @@ -129,11 +153,11 @@ static void cvf_is_valid(void **state) assert_false(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, MAX_PDU_SIZE)); /* Buffer smaller than the CVF header. */ - Avtp_Cvf_Init((Avtp_Cvf_t *)pdu); + Avtp_Cvf_InitV0((Avtp_Cvf_t *)pdu); assert_false(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN_V0 - 1)); /* stream_data_length does not fit into the buffer. */ - Avtp_Cvf_Init((Avtp_Cvf_t *)pdu); + Avtp_Cvf_InitV0((Avtp_Cvf_t *)pdu); Avtp_Cvf_SetStreamDataLength((Avtp_Cvf_t *)pdu, 10); assert_false(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN_V0 + 9)); assert_true(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN_V0 + 10)); @@ -146,7 +170,7 @@ static void cvf_is_valid(void **state) assert_false(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, AVTP_CVF_HEADER_LEN_V1 - 1)); /* Unsupported version is rejected. */ - Avtp_Cvf_Init((Avtp_Cvf_t *)pdu); + Avtp_Cvf_InitV0((Avtp_Cvf_t *)pdu); Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, 2); assert_false(Avtp_Cvf_IsValid((Avtp_Cvf_t *)pdu, MAX_PDU_SIZE)); } @@ -220,7 +244,7 @@ static void cvf_flag_fields(void **state) uint8_t pdu[MAX_PDU_SIZE]; Avtp_Cvf_t *cvf = (Avtp_Cvf_t *)pdu; - Avtp_Cvf_Init(cvf); + Avtp_Cvf_InitV0(cvf); assert_true(Avtp_Cvf_IsSv(cvf)); Avtp_Cvf_SetSv(cvf, false); @@ -350,7 +374,7 @@ static void cvf_payload(void **state) uint8_t payload_out[8] = {0}; Avtp_Cvf_t *cvf = (Avtp_Cvf_t *)pdu; - Avtp_Cvf_Init(cvf); + Avtp_Cvf_InitV0(cvf); Avtp_Cvf_SetPayload(cvf, payload, sizeof(payload)); assert_ptr_equal(Avtp_Cvf_GetPayload(cvf), pdu + AVTP_CVF_HEADER_LEN_V0); @@ -694,7 +718,7 @@ static void cvf_typed_fields_v0(void **state) uint8_t pdu[AVTP_CVF_HEADER_LEN_V1]; Avtp_Cvf_t *cvf = (Avtp_Cvf_t *)pdu; - Avtp_Cvf_Init(cvf); + Avtp_Cvf_InitV0(cvf); for (uint8_t f = 0; f < AVTP_CVF_FIELD_MAX; f++) { uint8_t bits = Avtp_CvfFieldDescV0[f].bits; @@ -738,7 +762,7 @@ static void cvf_typed_named(void **state) Avtp_CvfV1_t *v1 = (Avtp_CvfV1_t *)pdu; /* Version 0. */ - Avtp_Cvf_Init(v0); + Avtp_Cvf_InitV0(v0); Avtp_Cvf_SetSv_V0(v0, true); Avtp_Cvf_SetSequenceNum_V0(v0, 0x55); Avtp_Cvf_SetStreamId_V0(v0, 0xAABBCCDDEEFF0001ULL); @@ -815,7 +839,7 @@ static void cvf_typed_helpers(void **state) uint8_t pdu[MAX_PDU_SIZE]; uint8_t payload[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - Avtp_Cvf_Init((Avtp_Cvf_t *)pdu); + Avtp_Cvf_InitV0((Avtp_Cvf_t *)pdu); assert_int_equal(Avtp_Cvf_GetHeaderLen_V0((Avtp_Cvf_t *)pdu), AVTP_CVF_HEADER_LEN_V0); assert_ptr_equal(Avtp_Cvf_GetPayload_V0((Avtp_Cvf_t *)pdu), pdu + AVTP_CVF_HEADER_LEN_V0); Avtp_Cvf_SetPayload_V0((Avtp_Cvf_t *)pdu, payload, sizeof(payload)); @@ -833,6 +857,7 @@ int main(void) const struct CMUnitTest tests[] = { cmocka_unit_test(cvf_init), cmocka_unit_test(cvf_init_v1), + cmocka_unit_test(cvf_init_version), cmocka_unit_test(cvf_is_valid), cmocka_unit_test(cvf_field_descriptors_cover_header), cmocka_unit_test(cvf_common_field_consistency), diff --git a/unit/test-ntscf.c b/unit/test-ntscf.c index 30d2fcab..59fd2390 100644 --- a/unit/test-ntscf.c +++ b/unit/test-ntscf.c @@ -74,9 +74,9 @@ static void ntscf_init(void **state) assert_int_equal(sizeof(Avtp_Ntscf_t), AVTP_NTSCF_HEADER_LEN_V0); /* Passing a NULL pointer must be a no-op. */ - Avtp_Ntscf_Init(NULL); + Avtp_Ntscf_InitV0(NULL); - Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); + Avtp_Ntscf_InitV0((Avtp_Ntscf_t *)pdu); memset(init_pdu, 0, AVTP_NTSCF_HEADER_LEN_V0); init_pdu[0] = AVTP_SUBTYPE_NTSCF; /* subtype = NTSCF */ init_pdu[1] = 0x80; /* sv = 1, version = 0 */ @@ -103,13 +103,37 @@ static void ntscf_init_v1(void **state) assert_int_equal(Avtp_Ntscf_GetHeaderLen((Avtp_Ntscf_t *)pdu), AVTP_NTSCF_HEADER_LEN_V1); } +static void ntscf_init_version(void **state) +{ + (void)state; + uint8_t typed[MAX_PDU_SIZE]; + uint8_t generic[MAX_PDU_SIZE]; + + assert_int_equal(sizeof(Avtp_Ntscf_t), sizeof(Avtp_NtscfV0_t)); + + Avtp_Ntscf_InitV0((Avtp_Ntscf_t *)typed); + Avtp_Ntscf_Init((Avtp_Ntscf_t *)generic, AVTPDU_VERSION_0); + assert_memory_equal(typed, generic, AVTP_NTSCF_HEADER_LEN_V0); + + Avtp_Ntscf_InitV1((Avtp_NtscfV1_t *)typed); + Avtp_Ntscf_Init((Avtp_Ntscf_t *)generic, AVTPDU_VERSION_1); + assert_memory_equal(typed, generic, AVTP_NTSCF_HEADER_LEN_V1); + + /* Unsupported versions initialize a version 0 PDU. */ + Avtp_Ntscf_Init((Avtp_Ntscf_t *)generic, 2); + Avtp_Ntscf_InitV0((Avtp_Ntscf_t *)typed); + assert_memory_equal(typed, generic, AVTP_NTSCF_HEADER_LEN_V0); + assert_int_equal(Avtp_CommonHeader_GetVersion((Avtp_CommonHeader_t *)generic), + AVTPDU_VERSION_0); +} + static void ntscf_is_valid(void **state) { (void)state; uint8_t pdu[MAX_PDU_SIZE]; /* Valid version 0 frame with no payload. */ - Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); + Avtp_Ntscf_InitV0((Avtp_Ntscf_t *)pdu); assert_true(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, AVTP_NTSCF_HEADER_LEN_V0)); /* Not an NTSCF frame. */ @@ -117,11 +141,11 @@ static void ntscf_is_valid(void **state) assert_false(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, MAX_PDU_SIZE)); /* Buffer smaller than the version 0 header. */ - Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); + Avtp_Ntscf_InitV0((Avtp_Ntscf_t *)pdu); assert_false(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, AVTP_NTSCF_HEADER_LEN_V0 - 1)); /* ntscf_data_length must fit after the header. */ - Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); + Avtp_Ntscf_InitV0((Avtp_Ntscf_t *)pdu); Avtp_Ntscf_SetNtscfDataLength((Avtp_Ntscf_t *)pdu, 28); assert_false(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, AVTP_NTSCF_HEADER_LEN_V0 + 27)); assert_true(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, AVTP_NTSCF_HEADER_LEN_V0 + 28)); @@ -132,7 +156,7 @@ static void ntscf_is_valid(void **state) assert_false(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, AVTP_NTSCF_HEADER_LEN_V1 - 1)); /* Unsupported version is rejected. */ - Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); + Avtp_Ntscf_InitV0((Avtp_Ntscf_t *)pdu); Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, 2); assert_false(Avtp_Ntscf_IsValid((Avtp_Ntscf_t *)pdu, MAX_PDU_SIZE)); } @@ -267,7 +291,7 @@ static void ntscf_payload(void **state) uint8_t pdu[MAX_PDU_SIZE]; uint8_t payload[4] = {0xDE, 0xAD, 0xBE, 0xEF}; - Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); + Avtp_Ntscf_InitV0((Avtp_Ntscf_t *)pdu); assert_ptr_equal(Avtp_Ntscf_GetPayload((Avtp_Ntscf_t *)pdu), pdu + AVTP_NTSCF_HEADER_LEN_V0); Avtp_Ntscf_SetPayload((Avtp_Ntscf_t *)pdu, payload, sizeof(payload)); assert_memory_equal(pdu + AVTP_NTSCF_HEADER_LEN_V0, payload, sizeof(payload)); @@ -300,7 +324,7 @@ static void ntscf_typed_fields_v0(void **state) uint8_t pdu[AVTP_NTSCF_HEADER_LEN_V1]; Avtp_Ntscf_t *ntscf = (Avtp_Ntscf_t *)pdu; - Avtp_Ntscf_Init(ntscf); + Avtp_Ntscf_InitV0(ntscf); for (uint8_t f = 0; f < AVTP_NTSCF_FIELD_MAX; f++) { uint8_t bits = Avtp_NtscfFieldDescV0[f].bits; @@ -346,7 +370,7 @@ static void ntscf_typed_named(void **state) Avtp_NtscfV1_t *v1 = (Avtp_NtscfV1_t *)pdu; /* Version 0. */ - Avtp_Ntscf_Init(v0); + Avtp_Ntscf_InitV0(v0); Avtp_Ntscf_SetSv_V0(v0, true); Avtp_Ntscf_SetSequenceNum_V0(v0, 0xAB); Avtp_Ntscf_SetNtscfDataLength_V0(v0, 0x123); @@ -395,7 +419,7 @@ static void ntscf_typed_helpers(void **state) uint8_t pdu[MAX_PDU_SIZE]; uint8_t payload[4] = {0xDE, 0xAD, 0xBE, 0xEF}; - Avtp_Ntscf_Init((Avtp_Ntscf_t *)pdu); + Avtp_Ntscf_InitV0((Avtp_Ntscf_t *)pdu); assert_int_equal(Avtp_Ntscf_GetHeaderLen_V0((Avtp_Ntscf_t *)pdu), AVTP_NTSCF_HEADER_LEN_V0); assert_ptr_equal(Avtp_Ntscf_GetPayload_V0((Avtp_Ntscf_t *)pdu), pdu + AVTP_NTSCF_HEADER_LEN_V0); Avtp_Ntscf_SetPayload_V0((Avtp_Ntscf_t *)pdu, payload, sizeof(payload)); @@ -414,6 +438,7 @@ int main(void) const struct CMUnitTest tests[] = { cmocka_unit_test(ntscf_init), cmocka_unit_test(ntscf_init_v1), + cmocka_unit_test(ntscf_init_version), cmocka_unit_test(ntscf_is_valid), cmocka_unit_test(ntscf_field_descriptors_cover_header), cmocka_unit_test(ntscf_ah_field_consistency), diff --git a/unit/test-pcm.c b/unit/test-pcm.c index 3bcef976..aa93ee75 100644 --- a/unit/test-pcm.c +++ b/unit/test-pcm.c @@ -69,7 +69,7 @@ static uint64_t mask_field_value(uint8_t bits, uint64_t value) /* Initializes a minimal but valid AAF PCM frame. */ static void init_valid_pcm(Avtp_Pcm_t *pdu) { - Avtp_Pcm_Init(pdu); + Avtp_Pcm_InitV0(pdu); Avtp_Pcm_SetChannelsPerFrame(pdu, 2); Avtp_Pcm_SetBitDepth(pdu, 16); } @@ -83,9 +83,9 @@ static void pcm_init(void **state) assert_int_equal(sizeof(Avtp_Pcm_t), AVTP_PCM_HEADER_LEN_V0); /* Passing a NULL pointer must be a no-op. */ - Avtp_Pcm_Init(NULL); + Avtp_Pcm_InitV0(NULL); - Avtp_Pcm_Init((Avtp_Pcm_t *)pdu); + Avtp_Pcm_InitV0((Avtp_Pcm_t *)pdu); memset(init_pdu, 0, AVTP_PCM_HEADER_LEN_V0); init_pdu[0] = AVTP_SUBTYPE_AAF; /* subtype = AAF */ init_pdu[1] = 0x80; /* sv = 1, version = 0 */ @@ -112,6 +112,30 @@ static void pcm_init_v1(void **state) assert_int_equal(Avtp_Pcm_GetHeaderLen((Avtp_Pcm_t *)pdu), AVTP_PCM_HEADER_LEN_V1); } +static void pcm_init_version(void **state) +{ + (void)state; + uint8_t typed[MAX_PDU_SIZE]; + uint8_t generic[MAX_PDU_SIZE]; + + assert_int_equal(sizeof(Avtp_Pcm_t), sizeof(Avtp_PcmV0_t)); + + Avtp_Pcm_InitV0((Avtp_Pcm_t *)typed); + Avtp_Pcm_Init((Avtp_Pcm_t *)generic, AVTPDU_VERSION_0); + assert_memory_equal(typed, generic, AVTP_PCM_HEADER_LEN_V0); + + Avtp_Pcm_InitV1((Avtp_PcmV1_t *)typed); + Avtp_Pcm_Init((Avtp_Pcm_t *)generic, AVTPDU_VERSION_1); + assert_memory_equal(typed, generic, AVTP_PCM_HEADER_LEN_V1); + + /* Unsupported versions initialize a version 0 PDU. */ + Avtp_Pcm_Init((Avtp_Pcm_t *)generic, 2); + Avtp_Pcm_InitV0((Avtp_Pcm_t *)typed); + assert_memory_equal(typed, generic, AVTP_PCM_HEADER_LEN_V0); + assert_int_equal(Avtp_CommonHeader_GetVersion((Avtp_CommonHeader_t *)generic), + AVTPDU_VERSION_0); +} + static void pcm_is_valid(void **state) { (void)state; @@ -295,7 +319,7 @@ static void pcm_flag_fields(void **state) uint8_t pdu[MAX_PDU_SIZE]; Avtp_Pcm_t *pcm = (Avtp_Pcm_t *)pdu; - Avtp_Pcm_Init(pcm); + Avtp_Pcm_InitV0(pcm); assert_true(Avtp_Pcm_IsSv(pcm)); Avtp_Pcm_SetSv(pcm, false); @@ -433,7 +457,7 @@ static void pcm_payload(void **state) uint8_t payload_out[8] = {0}; Avtp_Pcm_t *pcm = (Avtp_Pcm_t *)pdu; - Avtp_Pcm_Init(pcm); + Avtp_Pcm_InitV0(pcm); Avtp_Pcm_SetPayload(pcm, payload, sizeof(payload)); assert_ptr_equal(Avtp_Pcm_GetPayload(pcm), pdu + AVTP_PCM_HEADER_LEN_V0); @@ -474,7 +498,7 @@ static void pcm_typed_fields_v0(void **state) uint8_t pdu[AVTP_PCM_HEADER_LEN_V1]; Avtp_Pcm_t *pcm = (Avtp_Pcm_t *)pdu; - Avtp_Pcm_Init(pcm); + Avtp_Pcm_InitV0(pcm); for (uint8_t f = 0; f < AVTP_PCM_FIELD_MAX; f++) { uint8_t bits = Avtp_PcmFieldDescV0[f].bits; @@ -518,7 +542,7 @@ static void pcm_typed_named(void **state) Avtp_PcmV1_t *v1 = (Avtp_PcmV1_t *)pdu; /* Version 0. */ - Avtp_Pcm_Init(v0); + Avtp_Pcm_InitV0(v0); Avtp_Pcm_SetSv_V0(v0, true); Avtp_Pcm_SetSequenceNum_V0(v0, 0x55); Avtp_Pcm_SetStreamId_V0(v0, 0xAABBCCDDEEFF0001ULL); @@ -603,7 +627,7 @@ static void pcm_typed_helpers(void **state) uint8_t pdu[MAX_PDU_SIZE]; uint8_t payload[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - Avtp_Pcm_Init((Avtp_Pcm_t *)pdu); + Avtp_Pcm_InitV0((Avtp_Pcm_t *)pdu); assert_int_equal(Avtp_Pcm_GetHeaderLen_V0((Avtp_Pcm_t *)pdu), AVTP_PCM_HEADER_LEN_V0); assert_ptr_equal(Avtp_Pcm_GetPayload_V0((Avtp_Pcm_t *)pdu), pdu + AVTP_PCM_HEADER_LEN_V0); Avtp_Pcm_SetPayload_V0((Avtp_Pcm_t *)pdu, payload, sizeof(payload)); @@ -621,6 +645,7 @@ int main(void) const struct CMUnitTest tests[] = { cmocka_unit_test(pcm_init), cmocka_unit_test(pcm_init_v1), + cmocka_unit_test(pcm_init_version), cmocka_unit_test(pcm_is_valid), cmocka_unit_test(pcm_field_descriptors_cover_header), cmocka_unit_test(pcm_common_field_consistency), diff --git a/unit/test-rvf.c b/unit/test-rvf.c index f1a795f7..253c3484 100644 --- a/unit/test-rvf.c +++ b/unit/test-rvf.c @@ -71,7 +71,7 @@ static uint64_t mask_field_value(uint8_t bits, uint64_t value) /* Initializes a minimal but valid RVF frame. */ static void init_valid_rvf(Avtp_Rvf_t *pdu) { - Avtp_Rvf_Init(pdu); + Avtp_Rvf_InitV0(pdu); Avtp_Rvf_SetStreamDataLength(pdu, AVTP_RVF_RAW_HEADER_LEN); } @@ -84,9 +84,9 @@ static void rvf_init(void **state) assert_int_equal(sizeof(Avtp_Rvf_t), AVTP_RVF_HEADER_LEN_V0); /* Passing a NULL pointer must be a no-op. */ - Avtp_Rvf_Init(NULL); + Avtp_Rvf_InitV0(NULL); - Avtp_Rvf_Init((Avtp_Rvf_t *)pdu); + Avtp_Rvf_InitV0((Avtp_Rvf_t *)pdu); memset(init_pdu, 0, AVTP_RVF_HEADER_LEN_V0); init_pdu[0] = AVTP_SUBTYPE_RVF; /* subtype = RVF */ init_pdu[1] = 0x80; /* sv = 1, version = 0 */ @@ -113,6 +113,30 @@ static void rvf_init_v1(void **state) assert_int_equal(Avtp_Rvf_GetHeaderLen((Avtp_Rvf_t *)pdu), AVTP_RVF_HEADER_LEN_V1); } +static void rvf_init_version(void **state) +{ + (void)state; + uint8_t typed[MAX_PDU_SIZE]; + uint8_t generic[MAX_PDU_SIZE]; + + assert_int_equal(sizeof(Avtp_Rvf_t), sizeof(Avtp_RvfV0_t)); + + Avtp_Rvf_InitV0((Avtp_Rvf_t *)typed); + Avtp_Rvf_Init((Avtp_Rvf_t *)generic, AVTPDU_VERSION_0); + assert_memory_equal(typed, generic, AVTP_RVF_HEADER_LEN_V0); + + Avtp_Rvf_InitV1((Avtp_RvfV1_t *)typed); + Avtp_Rvf_Init((Avtp_Rvf_t *)generic, AVTPDU_VERSION_1); + assert_memory_equal(typed, generic, AVTP_RVF_HEADER_LEN_V1); + + /* Unsupported versions initialize a version 0 PDU. */ + Avtp_Rvf_Init((Avtp_Rvf_t *)generic, 2); + Avtp_Rvf_InitV0((Avtp_Rvf_t *)typed); + assert_memory_equal(typed, generic, AVTP_RVF_HEADER_LEN_V0); + assert_int_equal(Avtp_CommonHeader_GetVersion((Avtp_CommonHeader_t *)generic), + AVTPDU_VERSION_0); +} + static void rvf_is_valid(void **state) { (void)state; @@ -226,7 +250,7 @@ static void rvf_flag_fields(void **state) uint8_t pdu[MAX_PDU_SIZE]; Avtp_Rvf_t *rvf = (Avtp_Rvf_t *)pdu; - Avtp_Rvf_Init(rvf); + Avtp_Rvf_InitV0(rvf); assert_true(Avtp_Rvf_IsSv(rvf)); Avtp_Rvf_SetSv(rvf, false); @@ -382,7 +406,7 @@ static void rvf_payload(void **state) uint8_t payload_out[12] = {0}; Avtp_Rvf_t *rvf = (Avtp_Rvf_t *)pdu; - Avtp_Rvf_Init(rvf); + Avtp_Rvf_InitV0(rvf); Avtp_Rvf_SetPayload(rvf, payload, sizeof(payload)); assert_ptr_equal(Avtp_Rvf_GetPayload(rvf), pdu + AVTP_RVF_HEADER_LEN_V0); @@ -557,7 +581,7 @@ static void rvf_raw_header_overlay(void **state) Avtp_Rvf_t *rvf = (Avtp_Rvf_t *)pdu; Avtp_RvfRawHeader_t *raw = (Avtp_RvfRawHeader_t *)rvf->payload; - Avtp_Rvf_Init(rvf); + Avtp_Rvf_InitV0(rvf); Avtp_Rvf_SetStreamDataLength(rvf, AVTP_RVF_RAW_HEADER_LEN); Avtp_RvfRawHeader_Init(raw); @@ -573,7 +597,7 @@ static void rvf_typed_fields_v0(void **state) uint8_t pdu[AVTP_RVF_HEADER_LEN_V1]; Avtp_Rvf_t *rvf = (Avtp_Rvf_t *)pdu; - Avtp_Rvf_Init(rvf); + Avtp_Rvf_InitV0(rvf); for (uint8_t f = 0; f < AVTP_RVF_FIELD_MAX; f++) { uint8_t bits = Avtp_RvfFieldDescV0[f].bits; @@ -617,7 +641,7 @@ static void rvf_typed_named(void **state) Avtp_RvfV1_t *v1 = (Avtp_RvfV1_t *)pdu; /* Version 0. */ - Avtp_Rvf_Init(v0); + Avtp_Rvf_InitV0(v0); Avtp_Rvf_SetSv_V0(v0, true); Avtp_Rvf_SetSequenceNum_V0(v0, 0x55); Avtp_Rvf_SetStreamId_V0(v0, 0xAABBCCDDEEFF0001ULL); @@ -706,7 +730,7 @@ static void rvf_typed_helpers(void **state) uint8_t pdu[MAX_PDU_SIZE]; uint8_t payload[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - Avtp_Rvf_Init((Avtp_Rvf_t *)pdu); + Avtp_Rvf_InitV0((Avtp_Rvf_t *)pdu); assert_int_equal(Avtp_Rvf_GetHeaderLen_V0((Avtp_Rvf_t *)pdu), AVTP_RVF_HEADER_LEN_V0); assert_ptr_equal(Avtp_Rvf_GetPayload_V0((Avtp_Rvf_t *)pdu), pdu + AVTP_RVF_HEADER_LEN_V0); Avtp_Rvf_SetPayload_V0((Avtp_Rvf_t *)pdu, payload, sizeof(payload)); @@ -724,6 +748,7 @@ int main(void) const struct CMUnitTest tests[] = { cmocka_unit_test(rvf_init), cmocka_unit_test(rvf_init_v1), + cmocka_unit_test(rvf_init_version), cmocka_unit_test(rvf_is_valid), cmocka_unit_test(rvf_field_descriptors_cover_header), cmocka_unit_test(rvf_common_field_consistency), diff --git a/unit/test-tscf.c b/unit/test-tscf.c index 7fa41206..bbd2bc0f 100644 --- a/unit/test-tscf.c +++ b/unit/test-tscf.c @@ -75,9 +75,9 @@ static void tscf_init(void **state) assert_int_equal(sizeof(Avtp_TscfV1_t), AVTP_TSCF_HEADER_LEN_V1); /* Passing a NULL pointer must be a no-op. */ - Avtp_Tscf_Init(NULL); + Avtp_Tscf_InitV0(NULL); - Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); + Avtp_Tscf_InitV0((Avtp_Tscf_t *)pdu); memset(init_pdu, 0, AVTP_TSCF_HEADER_LEN_V0); init_pdu[0] = AVTP_SUBTYPE_TSCF; /* subtype = TSCF */ init_pdu[1] = 0x80; /* sv = 1, version = 0 */ @@ -105,6 +105,30 @@ static void tscf_init_v1(void **state) AVTP_TSCF_HEADER_LEN_V1); } +static void tscf_init_version(void **state) +{ + (void)state; + uint8_t typed[MAX_PDU_SIZE]; + uint8_t generic[MAX_PDU_SIZE]; + + assert_int_equal(sizeof(Avtp_Tscf_t), sizeof(Avtp_TscfV0_t)); + + Avtp_Tscf_InitV0((Avtp_Tscf_t *)typed); + Avtp_Tscf_Init((Avtp_Tscf_t *)generic, AVTPDU_VERSION_0); + assert_memory_equal(typed, generic, AVTP_TSCF_HEADER_LEN_V0); + + Avtp_Tscf_InitV1((Avtp_TscfV1_t *)typed); + Avtp_Tscf_Init((Avtp_Tscf_t *)generic, AVTPDU_VERSION_1); + assert_memory_equal(typed, generic, AVTP_TSCF_HEADER_LEN_V1); + + /* Unsupported versions initialize a version 0 PDU. */ + Avtp_Tscf_Init((Avtp_Tscf_t *)generic, 2); + Avtp_Tscf_InitV0((Avtp_Tscf_t *)typed); + assert_memory_equal(typed, generic, AVTP_TSCF_HEADER_LEN_V0); + assert_int_equal(Avtp_CommonHeader_GetVersion((Avtp_CommonHeader_t *)generic), + AVTPDU_VERSION_0); +} + static void tscf_v0_layout(void **state) { (void)state; @@ -112,7 +136,7 @@ static void tscf_v0_layout(void **state) uint8_t snapshot[AVTP_TSCF_HEADER_LEN_V0]; Avtp_Tscf_t *tscf = (Avtp_Tscf_t *)pdu; - Avtp_Tscf_Init(tscf); + Avtp_Tscf_InitV0(tscf); Avtp_Tscf_SetSequenceNum(tscf, 0xAB); assert_int_equal(Avtp_Tscf_GetSequenceNum(tscf), 0xAB); @@ -172,7 +196,7 @@ static void tscf_is_valid(void **state) uint8_t pdu[MAX_PDU_SIZE]; /* Valid version 0 frame with no payload. */ - Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); + Avtp_Tscf_InitV0((Avtp_Tscf_t *)pdu); assert_true(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, AVTP_TSCF_HEADER_LEN_V0)); /* Not a TSCF frame. */ @@ -180,11 +204,11 @@ static void tscf_is_valid(void **state) assert_false(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, MAX_PDU_SIZE)); /* Buffer smaller than the version 0 header. */ - Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); + Avtp_Tscf_InitV0((Avtp_Tscf_t *)pdu); assert_false(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, AVTP_TSCF_HEADER_LEN_V0 - 1)); /* stream_data_length must fit after the header. */ - Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); + Avtp_Tscf_InitV0((Avtp_Tscf_t *)pdu); Avtp_Tscf_SetStreamDataLength((Avtp_Tscf_t *)pdu, 10); assert_false(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, AVTP_TSCF_HEADER_LEN_V0 + 9)); assert_true(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, AVTP_TSCF_HEADER_LEN_V0 + 10)); @@ -195,7 +219,7 @@ static void tscf_is_valid(void **state) assert_false(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, AVTP_TSCF_HEADER_LEN_V1 - 1)); /* Unsupported version is rejected. */ - Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); + Avtp_Tscf_InitV0((Avtp_Tscf_t *)pdu); Avtp_CommonHeader_SetVersion((Avtp_CommonHeader_t *)pdu, 2); assert_false(Avtp_Tscf_IsValid((Avtp_Tscf_t *)pdu, MAX_PDU_SIZE)); } @@ -206,7 +230,7 @@ static void tscf_payload(void **state) uint8_t pdu[MAX_PDU_SIZE]; uint8_t payload[4] = {0xDE, 0xAD, 0xBE, 0xEF}; - Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); + Avtp_Tscf_InitV0((Avtp_Tscf_t *)pdu); assert_ptr_equal(Avtp_Tscf_GetPayload((Avtp_Tscf_t *)pdu), pdu + AVTP_TSCF_HEADER_LEN_V0); Avtp_Tscf_SetPayload((Avtp_Tscf_t *)pdu, payload, sizeof(payload)); assert_memory_equal(pdu + AVTP_TSCF_HEADER_LEN_V0, payload, sizeof(payload)); @@ -290,7 +314,7 @@ static void tscf_typed_fields_v0(void **state) uint8_t pdu[AVTP_TSCF_HEADER_LEN_V1]; Avtp_Tscf_t *tscf = (Avtp_Tscf_t *)pdu; - Avtp_Tscf_Init(tscf); + Avtp_Tscf_InitV0(tscf); for (uint8_t f = 0; f < AVTP_TSCF_FIELD_MAX; f++) { uint8_t bits = Avtp_TscfFieldDescV0[f].bits; @@ -336,7 +360,7 @@ static void tscf_typed_named(void **state) Avtp_TscfV1_t *v1 = (Avtp_TscfV1_t *)pdu; /* Version 0. */ - Avtp_Tscf_Init(v0); + Avtp_Tscf_InitV0(v0); Avtp_Tscf_SetSv_V0(v0, true); Avtp_Tscf_SetSequenceNum_V0(v0, 0xAB); Avtp_Tscf_SetStreamId_V0(v0, 0x0102030405060708ULL); @@ -393,7 +417,7 @@ static void tscf_typed_helpers(void **state) uint8_t pdu[MAX_PDU_SIZE]; uint8_t payload[4] = {0xDE, 0xAD, 0xBE, 0xEF}; - Avtp_Tscf_Init((Avtp_Tscf_t *)pdu); + Avtp_Tscf_InitV0((Avtp_Tscf_t *)pdu); assert_int_equal(Avtp_Tscf_GetHeaderLen_V0((Avtp_Tscf_t *)pdu), AVTP_TSCF_HEADER_LEN_V0); assert_ptr_equal(Avtp_Tscf_GetPayload_V0((Avtp_Tscf_t *)pdu), pdu + AVTP_TSCF_HEADER_LEN_V0); Avtp_Tscf_SetPayload_V0((Avtp_Tscf_t *)pdu, payload, sizeof(payload)); @@ -411,6 +435,7 @@ int main(void) const struct CMUnitTest tests[] = { cmocka_unit_test(tscf_init), cmocka_unit_test(tscf_init_v1), + cmocka_unit_test(tscf_init_version), cmocka_unit_test(tscf_v0_layout), cmocka_unit_test(tscf_v1_layout), cmocka_unit_test(tscf_is_valid),