Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

usb: device_next: uac2: Generate Feature Unit descriptor #79634

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions dts/bindings/usb/uac2/zephyr,uac2-feature-unit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

description: USB Audio Class 2 Feature Unit entity

compatible: "zephyr,uac2-feature-unit"

# string-array properties start with Primary channel 0 and follow with Logical
# channel(s). The "not-present" value is allowed to facilitate having controls
# that are not present on the Primary channel, but only present at the Logical
# channel(s).

properties:
data-source:
type: phandle
description: Unit or Terminal to which this Feature Unit is connected

mute-control:
type: string-array
description: Mute Control capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

volume-control:
type: string-array
description: Volume Control capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

bass-control:
type: string-array
description: Bass Control capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

mid-control:
type: string-array
description: Mid Control capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

treble-control:
type: string-array
description: Treble Control capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

graphic-equalizer-control:
type: string-array
description: Graphic Equalizer capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

automatic-gain-control:
type: string-array
description: Automatic Gain Control capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

delay-control:
type: string-array
description: Delay Control capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

bass-boost-control:
type: string-array
description: Bass Boost Control capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

loundness-control:
type: string-array
description: Loundness Control capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

input-gain-control:
type: string-array
description: Input Gain Control capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

input-gain-pad-control:
type: string-array
description: Input Gain Pad Control capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

phase-inverter-control:
type: string-array
description: Phase Inverter Control capabilities
enum:
- "read-only"
- "host-programmable"
- "not-present"

underflow-control:
type: string-array
description: Underflow Control capabilities
enum:
- "read-only"
- "not-present"

overflow-control:
type: string-array
description: Overflow Control capabilities
enum:
- "read-only"
- "not-present"
139 changes: 130 additions & 9 deletions subsys/usb/device_next/class/usbd_uac2_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@
#define EXT_FORMAT_TYPE_II 130
#define EXT_FORMAT_TYPE_III 131

/* Convert 0 to empty and everything else to itself */
#define EMPTY_ON_ZERO(value) COND_CODE_0(value, (), (value))

/* Automatically assign Entity IDs based on entities order in devicetree */
#define ENTITY_ID(e) UTIL_INC(DT_NODE_CHILD_IDX(e))

Expand Down Expand Up @@ -168,13 +171,27 @@
* control is present but read-only and 0b11 when control can be programmed by
* host. Value 0b10 is not allowed by the specification.
*/
#define CONTROL_BITS(entity, control_name, bitshift) \
#define CONTROL_NOT_PRESENT 0x0
#define CONTROL_READ_ONLY 0x1
#define CONTROL_HOST_PROGRAMMABLE 0x3

#define CONTROL_TOKEN(entity, control_name) \
COND_CODE_1(DT_NODE_HAS_PROP(entity, control_name), \
(COND_CODE_0(DT_ENUM_IDX(entity, control_name), \
((0x1 << bitshift)) /* read-only */, \
((0x3 << bitshift)) /* host-programmable */)), \
((0x0 << bitshift)) /* control not present */)
(DT_STRING_UPPER_TOKEN(entity, control_name)), \
(NOT_PRESENT))

#define CONTROL_BITS(entity, control_name, bitshift) \
(UTIL_CAT(CONTROL_, CONTROL_TOKEN(entity, control_name)) << bitshift)

#define CONTROL_TOKEN_BY_IDX(entity, control_name, idx) \
COND_CODE_1(DT_PROP_HAS_IDX(entity, control_name, idx), \
(DT_STRING_UPPER_TOKEN_BY_IDX(entity, control_name, idx)), \
(NOT_PRESENT))

#define CONTROL_BITS_BY_IDX(entity, control_name, idx, bitshift) \
(UTIL_CAT(CONTROL_, CONTROL_TOKEN_BY_IDX(entity, control_name, idx)) \
<< bitshift)

Check notice on line 194 in subsys/usb/device_next/class/usbd_uac2_macros.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/usb/device_next/class/usbd_uac2_macros.h:194 -#define CONTROL_NOT_PRESENT 0x0 -#define CONTROL_READ_ONLY 0x1 -#define CONTROL_HOST_PROGRAMMABLE 0x3 - -#define CONTROL_TOKEN(entity, control_name) \ +#define CONTROL_NOT_PRESENT 0x0 +#define CONTROL_READ_ONLY 0x1 +#define CONTROL_HOST_PROGRAMMABLE 0x3 + +#define CONTROL_TOKEN(entity, control_name) \ COND_CODE_1(DT_NODE_HAS_PROP(entity, control_name), \ (DT_STRING_UPPER_TOKEN(entity, control_name)), \ (NOT_PRESENT)) -#define CONTROL_BITS(entity, control_name, bitshift) \ +#define CONTROL_BITS(entity, control_name, bitshift) \ (UTIL_CAT(CONTROL_, CONTROL_TOKEN(entity, control_name)) << bitshift) -#define CONTROL_TOKEN_BY_IDX(entity, control_name, idx) \ +#define CONTROL_TOKEN_BY_IDX(entity, control_name, idx) \ COND_CODE_1(DT_PROP_HAS_IDX(entity, control_name, idx), \ (DT_STRING_UPPER_TOKEN_BY_IDX(entity, control_name, idx)), \ (NOT_PRESENT)) -#define CONTROL_BITS_BY_IDX(entity, control_name, idx, bitshift) \ - (UTIL_CAT(CONTROL_, CONTROL_TOKEN_BY_IDX(entity, control_name, idx)) \ - << bitshift) +#define CONTROL_BITS_BY_IDX(entity, control_name, idx, bitshift) \ + (UTIL_CAT(CONTROL_, CONTROL_TOKEN_BY_IDX(entity, control_name, idx)) << bitshift)
#define CLOCK_SOURCE_CONTROLS(entity) \
CONTROL_BITS(entity, frequency_control, 0) | \
CONTROL_BITS(entity, validity_control, 2)
Expand All @@ -194,6 +211,23 @@
CONTROL_BITS(entity, underflow_control, 6) | \
CONTROL_BITS(entity, overflow_control, 8)

#define FEATURE_UNIT_CHANNEL_CONTROLS(entity, ch) \
CONTROL_BITS_BY_IDX(entity, mute_control, ch, 0) | \
CONTROL_BITS_BY_IDX(entity, volume_control, ch, 2) | \
CONTROL_BITS_BY_IDX(entity, bass_control, ch, 4) | \
CONTROL_BITS_BY_IDX(entity, mid_control, ch, 6) | \
CONTROL_BITS_BY_IDX(entity, treble_control, ch, 8) | \
CONTROL_BITS_BY_IDX(entity, graphic_equalizer_control, ch, 10) | \
CONTROL_BITS_BY_IDX(entity, automatic_gain_control, ch, 12) | \
CONTROL_BITS_BY_IDX(entity, delay_control, ch, 14) | \
CONTROL_BITS_BY_IDX(entity, bass_boost_control, ch, 16) | \
CONTROL_BITS_BY_IDX(entity, loudness_control, ch, 18) | \
CONTROL_BITS_BY_IDX(entity, input_gain_control, ch, 20) | \
CONTROL_BITS_BY_IDX(entity, input_gain_pad_control, ch, 22) | \
CONTROL_BITS_BY_IDX(entity, phase_inverter_control, ch, 24) | \
CONTROL_BITS_BY_IDX(entity, underflow_control, ch, 26) | \
CONTROL_BITS_BY_IDX(entity, overflow_control, ch, 28)

Check notice on line 230 in subsys/usb/device_next/class/usbd_uac2_macros.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/usb/device_next/class/usbd_uac2_macros.h:230 -#define FEATURE_UNIT_CHANNEL_CONTROLS(entity, ch) \ - CONTROL_BITS_BY_IDX(entity, mute_control, ch, 0) | \ - CONTROL_BITS_BY_IDX(entity, volume_control, ch, 2) | \ - CONTROL_BITS_BY_IDX(entity, bass_control, ch, 4) | \ - CONTROL_BITS_BY_IDX(entity, mid_control, ch, 6) | \ - CONTROL_BITS_BY_IDX(entity, treble_control, ch, 8) | \ - CONTROL_BITS_BY_IDX(entity, graphic_equalizer_control, ch, 10) | \ - CONTROL_BITS_BY_IDX(entity, automatic_gain_control, ch, 12) | \ - CONTROL_BITS_BY_IDX(entity, delay_control, ch, 14) | \ - CONTROL_BITS_BY_IDX(entity, bass_boost_control, ch, 16) | \ - CONTROL_BITS_BY_IDX(entity, loudness_control, ch, 18) | \ - CONTROL_BITS_BY_IDX(entity, input_gain_control, ch, 20) | \ - CONTROL_BITS_BY_IDX(entity, input_gain_pad_control, ch, 22) | \ - CONTROL_BITS_BY_IDX(entity, phase_inverter_control, ch, 24) | \ - CONTROL_BITS_BY_IDX(entity, underflow_control, ch, 26) | \ - CONTROL_BITS_BY_IDX(entity, overflow_control, ch, 28) +#define FEATURE_UNIT_CHANNEL_CONTROLS(entity, ch) \ + CONTROL_BITS_BY_IDX(entity, mute_control, ch, 0) | \ + CONTROL_BITS_BY_IDX(entity, volume_control, ch, 2) | \ + CONTROL_BITS_BY_IDX(entity, bass_control, ch, 4) | \ + CONTROL_BITS_BY_IDX(entity, mid_control, ch, 6) | \ + CONTROL_BITS_BY_IDX(entity, treble_control, ch, 8) | \ + CONTROL_BITS_BY_IDX(entity, graphic_equalizer_control, ch, 10) | \ + CONTROL_BITS_BY_IDX(entity, automatic_gain_control, ch, 12) | \ + CONTROL_BITS_BY_IDX(entity, delay_control, ch, 14) | \ + CONTROL_BITS_BY_IDX(entity, bass_boost_control, ch, 16) | \ + CONTROL_BITS_BY_IDX(entity, loudness_control, ch, 18) | \ + CONTROL_BITS_BY_IDX(entity, input_gain_control, ch, 20) | \ + CONTROL_BITS_BY_IDX(entity, input_gain_pad_control, ch, 22) | \ + CONTROL_BITS_BY_IDX(entity, phase_inverter_control, ch, 24) | \ + CONTROL_BITS_BY_IDX(entity, underflow_control, ch, 26) | \ + CONTROL_BITS_BY_IDX(entity, overflow_control, ch, 28)
#define AUDIO_STREAMING_DATA_ENDPOINT_CONTROLS(node) \
CONTROL_BITS(node, pitch_control, 0) | \
CONTROL_BITS(node, data_overrun_control, 2) | \
Expand Down Expand Up @@ -233,11 +267,25 @@

#define SPATIAL_LOCATIONS_U32(entity) \
(FOR_EACH_IDX(ARRAY_BIT, (|), SPATIAL_LOCATIONS_ARRAY(entity)))
#define NUM_SPATIAL_LOCATIONS(entity) \
(FOR_EACH(IDENTITY, (+), SPATIAL_LOCATIONS_ARRAY(entity)))
#define NUM_SPATIAL_LOCATIONS(entity) \
NUM_VA_ARGS(LIST_DROP_EMPTY( \
FOR_EACH(EMPTY_ON_ZERO, (,), SPATIAL_LOCATIONS_ARRAY(entity)) \
))
#define SPATIAL_LOCATIONS(entity) U32_LE(SPATIAL_LOCATIONS_U32(entity))

#define FEATURE_UNIT_NUM_CHANNELS(entity) \
NUM_SPATIAL_LOCATIONS(DT_PHANDLE_BY_IDX(entity, data_source, 0))

#define FEATURE_UNIT_CONTROLS_BY_IDX(i, entity) \
U32_LE(FEATURE_UNIT_CHANNEL_CONTROLS(entity, i))

#define FEATURE_UNIT_CONTROLS_ARRAYS(entity) \
LISTIFY(UTIL_INC(FEATURE_UNIT_NUM_CHANNELS(entity)), \
FEATURE_UNIT_CONTROLS_BY_IDX, (,), entity)

#define FEATURE_UNIT_DESCRIPTOR_LENGTH(entity) \
(6 + (FEATURE_UNIT_NUM_CHANNELS(entity) + 1) * 4)

Check notice on line 288 in subsys/usb/device_next/class/usbd_uac2_macros.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/usb/device_next/class/usbd_uac2_macros.h:288 -#define NUM_SPATIAL_LOCATIONS(entity) \ - NUM_VA_ARGS(LIST_DROP_EMPTY( \ - FOR_EACH(EMPTY_ON_ZERO, (,), SPATIAL_LOCATIONS_ARRAY(entity)) \ - )) +#define NUM_SPATIAL_LOCATIONS(entity) \ + NUM_VA_ARGS(LIST_DROP_EMPTY(FOR_EACH(EMPTY_ON_ZERO, (, ), SPATIAL_LOCATIONS_ARRAY(entity)))) #define SPATIAL_LOCATIONS(entity) U32_LE(SPATIAL_LOCATIONS_U32(entity)) -#define FEATURE_UNIT_NUM_CHANNELS(entity) \ +#define FEATURE_UNIT_NUM_CHANNELS(entity) \ NUM_SPATIAL_LOCATIONS(DT_PHANDLE_BY_IDX(entity, data_source, 0)) -#define FEATURE_UNIT_CONTROLS_BY_IDX(i, entity) \ - U32_LE(FEATURE_UNIT_CHANNEL_CONTROLS(entity, i)) - -#define FEATURE_UNIT_CONTROLS_ARRAYS(entity) \ +#define FEATURE_UNIT_CONTROLS_BY_IDX(i, entity) U32_LE(FEATURE_UNIT_CHANNEL_CONTROLS(entity, i)) + +#define FEATURE_UNIT_CONTROLS_ARRAYS(entity) \ LISTIFY(UTIL_INC(FEATURE_UNIT_NUM_CHANNELS(entity)), \ FEATURE_UNIT_CONTROLS_BY_IDX, (,), entity) -#define FEATURE_UNIT_DESCRIPTOR_LENGTH(entity) \ - (6 + (FEATURE_UNIT_NUM_CHANNELS(entity) + 1) * 4) +#define FEATURE_UNIT_DESCRIPTOR_LENGTH(entity) (6 + (FEATURE_UNIT_NUM_CHANNELS(entity) + 1) * 4)
/* 4.7.2.1 Clock Source Descriptor */
#define CLOCK_SOURCE_DESCRIPTOR(entity) \
0x08, /* bLength */ \
Expand Down Expand Up @@ -277,6 +325,16 @@
U16_LE(OUTPUT_TERMINAL_CONTROLS(entity)), /* bmControls */ \
0x00, /* iTerminal */

/* 4.7.2.8 Feature Unit Descriptor */
#define FEATURE_UNIT_DESCRIPTOR(entity) \
FEATURE_UNIT_DESCRIPTOR_LENGTH(entity), /* bLength */ \
CS_INTERFACE, /* bDescriptorType */ \
AC_DESCRIPTOR_FEATURE_UNIT, /* bDescriptorSubtype */\
ENTITY_ID(entity), /* bUnitID */ \
CONNECTED_ENTITY_ID(entity, data_source), /* bSourceID */ \
FEATURE_UNIT_CONTROLS_ARRAYS(entity), /* bmaControls 0..ch */ \
0x00, /* iFeature */

#define ENTITY_HEADER(entity) \
IF_ENABLED(DT_NODE_HAS_COMPAT(entity, zephyr_uac2_clock_source), ( \
CLOCK_SOURCE_DESCRIPTOR(entity) \
Expand All @@ -286,6 +344,9 @@
)) \
IF_ENABLED(DT_NODE_HAS_COMPAT(entity, zephyr_uac2_output_terminal), ( \
OUTPUT_TERMINAL_DESCRIPTOR(entity) \
)) \
IF_ENABLED(DT_NODE_HAS_COMPAT(entity, zephyr_uac2_feature_unit), ( \

Check notice on line 348 in subsys/usb/device_next/class/usbd_uac2_macros.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/usb/device_next/class/usbd_uac2_macros.h:348 -#define FEATURE_UNIT_DESCRIPTOR(entity) \ - FEATURE_UNIT_DESCRIPTOR_LENGTH(entity), /* bLength */ \ - CS_INTERFACE, /* bDescriptorType */ \ - AC_DESCRIPTOR_FEATURE_UNIT, /* bDescriptorSubtype */\ - ENTITY_ID(entity), /* bUnitID */ \ - CONNECTED_ENTITY_ID(entity, data_source), /* bSourceID */ \ - FEATURE_UNIT_CONTROLS_ARRAYS(entity), /* bmaControls 0..ch */ \ - 0x00, /* iFeature */ - -#define ENTITY_HEADER(entity) \ +#define FEATURE_UNIT_DESCRIPTOR(entity) \ + FEATURE_UNIT_DESCRIPTOR_LENGTH(entity), /* bLength */ \ + CS_INTERFACE, /* bDescriptorType */ \ + AC_DESCRIPTOR_FEATURE_UNIT, /* bDescriptorSubtype */ \ + ENTITY_ID(entity), /* bUnitID */ \ + CONNECTED_ENTITY_ID(entity, data_source), /* bSourceID */ \ + FEATURE_UNIT_CONTROLS_ARRAYS(entity), /* bmaControls 0..ch */ \ + 0x00, /* iFeature */ + +#define ENTITY_HEADER(entity) \ IF_ENABLED(DT_NODE_HAS_COMPAT(entity, zephyr_uac2_clock_source), ( \ CLOCK_SOURCE_DESCRIPTOR(entity) \ - )) \ + )) \ IF_ENABLED(DT_NODE_HAS_COMPAT(entity, zephyr_uac2_input_terminal), ( \ INPUT_TERMINAL_DESCRIPTOR(entity) \ - )) \ + )) \ IF_ENABLED(DT_NODE_HAS_COMPAT(entity, zephyr_uac2_output_terminal), ( \ OUTPUT_TERMINAL_DESCRIPTOR(entity) \ - )) \ + )) \
FEATURE_UNIT_DESCRIPTOR(entity) \
))

#define ENTITY_HEADER_ARRAYS(entity) \
Expand Down Expand Up @@ -318,6 +379,23 @@
(FORMAT_TYPE_I), (FORMAT_TYPE_IV))
#define AUDIO_STREAMING_FORMATS(node) U32_LE(0x00000001)

#define FEATURE_UNIT_CHANNEL_CLUSTER(node) \
IF_ENABLED(DT_NODE_HAS_COMPAT(DT_PROP(node, data_source), \
zephyr_uac2_input_terminal), ( \
DT_PROP(node, data_source) \
))

/* Track back Output Terminal data source to entity that has channel cluster */
#define OUTPUT_TERMINAL_CHANNEL_CLUSTER(node) \
IF_ENABLED(DT_NODE_HAS_COMPAT(DT_PROP(node, data_source), \
zephyr_uac2_input_terminal), ( \
DT_PROP(node, data_source) \
)) \
IF_ENABLED(DT_NODE_HAS_COMPAT(DT_PROP(node, data_source), \

Check notice on line 394 in subsys/usb/device_next/class/usbd_uac2_macros.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/usb/device_next/class/usbd_uac2_macros.h:394 -#define FEATURE_UNIT_CHANNEL_CLUSTER(node) \ +#define FEATURE_UNIT_CHANNEL_CLUSTER(node) \ IF_ENABLED(DT_NODE_HAS_COMPAT(DT_PROP(node, data_source), \ zephyr_uac2_input_terminal), ( \ DT_PROP(node, data_source) \ )) /* Track back Output Terminal data source to entity that has channel cluster */ -#define OUTPUT_TERMINAL_CHANNEL_CLUSTER(node) \ +#define OUTPUT_TERMINAL_CHANNEL_CLUSTER(node) \ IF_ENABLED(DT_NODE_HAS_COMPAT(DT_PROP(node, data_source), \ zephyr_uac2_input_terminal), ( \ DT_PROP(node, data_source) \ - )) \ + )) \
zephyr_uac2_feature_unit), ( \
FEATURE_UNIT_CHANNEL_CLUSTER(DT_PROP(node, data_source))\
))

/* If AudioStreaming is linked to input terminal, obtain the channel cluster
* configuration from the linked terminal. Otherwise (it has to be connected
* to output terminal) obtain the channel cluster configuration from data source
Expand All @@ -328,9 +406,9 @@
zephyr_uac2_input_terminal), ( \
DT_PROP(node, linked_terminal) \
)) \
IF_ENABLED(DT_NODE_HAS_COMPAT(DT_PROP(node, linked_terminal), \

Check notice on line 409 in subsys/usb/device_next/class/usbd_uac2_macros.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/usb/device_next/class/usbd_uac2_macros.h:409 -#define AUDIO_STREAMING_CHANNEL_CLUSTER(node) \ +#define AUDIO_STREAMING_CHANNEL_CLUSTER(node) \ IF_ENABLED(DT_NODE_HAS_COMPAT(DT_PROP(node, linked_terminal), \ zephyr_uac2_input_terminal), ( \ DT_PROP(node, linked_terminal) \ - )) \ + )) \
zephyr_uac2_output_terminal), ( \
DT_PROP(DT_PROP(node, linked_terminal), data_source) \
zephyr_uac2_output_terminal), (OUTPUT_TERMINAL_CHANNEL_CLUSTER( \
DT_PROP(node, linked_terminal)) \
))

#define AUDIO_STREAMING_NUM_SPATIAL_LOCATIONS(node) \
Expand Down Expand Up @@ -928,6 +1006,42 @@
DT_NODE_HAS_COMPAT(DT_PROP(entity, assoc_terminal), \
zephyr_uac2_input_terminal))

#define VALIDATE_OUTPUT_TERMINAL_DATA_SOURCE(entity) \
UTIL_OR(DT_NODE_HAS_COMPAT(DT_PROP(entity, data_source), \
zephyr_uac2_input_terminal), \
DT_NODE_HAS_COMPAT(DT_PROP(entity, data_source), \
zephyr_uac2_feature_unit))

#define VALIDATE_FEATURE_UNIT_DATA_SOURCE(entity) \
DT_NODE_HAS_COMPAT(DT_PROP(entity, data_source), \
zephyr_uac2_input_terminal)

#define BUILD_ASSERT_FEATURE_UNIT_CONTROL(fu, control) \
BUILD_ASSERT(UTIL_OR(UTIL_NOT(DT_NODE_HAS_PROP(fu, control)), \
DT_PROP_LEN(fu, control) <= 1 + FEATURE_UNIT_NUM_CHANNELS(fu)), \
"Feature Unit " DT_NODE_PATH(fu) " has " \
STRINGIFY(FEATURE_UNIT_NUM_CHANNELS(fu)) " logical channel(s) " \
"but its property " #control " has " \
STRINGIFY(DT_PROP_LEN(fu, control)) " values" \
);

#define BUILD_ASSERT_FEATURE_UNIT_CONTROLS_LENGTH(entity) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, mute_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, volume_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, bass_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, mid_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, treble_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, graphic_equalizer_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, automatic_gain_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, delay_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, bass_boost_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, loudness_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, input_gain_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, input_gain_pad_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, phase_inverter_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, underflow_control) \
BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, overflow_control)

Check notice on line 1043 in subsys/usb/device_next/class/usbd_uac2_macros.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/usb/device_next/class/usbd_uac2_macros.h:1043 -#define VALIDATE_OUTPUT_TERMINAL_DATA_SOURCE(entity) \ - UTIL_OR(DT_NODE_HAS_COMPAT(DT_PROP(entity, data_source), \ - zephyr_uac2_input_terminal), \ - DT_NODE_HAS_COMPAT(DT_PROP(entity, data_source), \ - zephyr_uac2_feature_unit)) - -#define VALIDATE_FEATURE_UNIT_DATA_SOURCE(entity) \ - DT_NODE_HAS_COMPAT(DT_PROP(entity, data_source), \ - zephyr_uac2_input_terminal) - -#define BUILD_ASSERT_FEATURE_UNIT_CONTROL(fu, control) \ - BUILD_ASSERT(UTIL_OR(UTIL_NOT(DT_NODE_HAS_PROP(fu, control)), \ - DT_PROP_LEN(fu, control) <= 1 + FEATURE_UNIT_NUM_CHANNELS(fu)), \ - "Feature Unit " DT_NODE_PATH(fu) " has " \ - STRINGIFY(FEATURE_UNIT_NUM_CHANNELS(fu)) " logical channel(s) " \ - "but its property " #control " has " \ - STRINGIFY(DT_PROP_LEN(fu, control)) " values" \ - ); - -#define BUILD_ASSERT_FEATURE_UNIT_CONTROLS_LENGTH(entity) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, mute_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, volume_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, bass_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, mid_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, treble_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, graphic_equalizer_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, automatic_gain_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, delay_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, bass_boost_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, loudness_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, input_gain_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, input_gain_pad_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, phase_inverter_control) \ - BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, underflow_control) \ +#define VALIDATE_OUTPUT_TERMINAL_DATA_SOURCE(entity) \ + UTIL_OR(DT_NODE_HAS_COMPAT(DT_PROP(entity, data_source), zephyr_uac2_input_terminal), \ + DT_NODE_HAS_COMPAT(DT_PROP(entity, data_source), zephyr_uac2_feature_unit)) + +#define VALIDATE_FEATURE_UNIT_DATA_SOURCE(entity) \ + DT_NODE_HAS_COMPAT(DT_PROP(entity, data_source), zephyr_uac2_input_terminal) + +#define BUILD_ASSERT_FEATURE_UNIT_CONTROL(fu, control) \ + BUILD_ASSERT(UTIL_OR(UTIL_NOT(DT_NODE_HAS_PROP(fu, control)), \ + DT_PROP_LEN(fu, control) <= 1 + FEATURE_UNIT_NUM_CHANNELS(fu)), \ + "Feature Unit " DT_NODE_PATH(fu) " has " STRINGIFY(FEATURE_UNIT_NUM_CHANNELS(fu)) " logical channel(s) " \ + "but its property " #control \ + " has " STRINGIFY(DT_PROP_LEN(fu, control)) " values"); + +#define BUILD_ASSERT_FEATURE_UNIT_CONTROLS_LENGTH(entity) \ + BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, mute_control) \ + BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, volume_control) \ + BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, bass_control) \ + BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, mid_control) \ + BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, treble_control) \ + BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, graphic_equalizer_control) \ + BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, automatic_gain_control) \ + BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, delay_control) \ + BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, bass_boost_control) \ + BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, loudness_control) \ + BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, input_gain_control) \ + BUILD_ASSERT_FEATURE_UNIT_CONTROL(entity, input_gain_pad_contro

#define NEEDS_SUBSLOT_SIZE_AND_BIT_RESOLUTION(node) UTIL_OR( \
UTIL_OR(IS_EQ(AUDIO_STREAMING_FORMAT_TYPE(node), FORMAT_TYPE_I), \
IS_EQ(AUDIO_STREAMING_FORMAT_TYPE(node), FORMAT_TYPE_III)), \
Expand Down Expand Up @@ -973,8 +1087,15 @@
IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_output_terminal), ( \
BUILD_ASSERT(VALIDATE_OUTPUT_TERMINAL_ASSOCIATION(node), \
"Terminals associations must be Input<->Output"); \
BUILD_ASSERT(VALIDATE_OUTPUT_TERMINAL_DATA_SOURCE(node), \
"Unsupported Output Terminal data source"); \
)) \
IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_feature_unit), ( \
BUILD_ASSERT(VALIDATE_FEATURE_UNIT_DATA_SOURCE(node), \
"Unsupported Feature Unit data source"); \
BUILD_ASSERT_FEATURE_UNIT_CONTROLS_LENGTH(node); \
)) \
IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \

Check notice on line 1098 in subsys/usb/device_next/class/usbd_uac2_macros.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/usb/device_next/class/usbd_uac2_macros.h:1098 -#define VALIDATE_NODE(node) \ +#define VALIDATE_NODE(node) \ IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_clock_source), ( \ BUILD_ASSERT(DT_PROP_LEN(node, sampling_frequencies), \ "Sampling frequencies array must not be empty"); \ BUILD_ASSERT(IS_ARRAY_SORTED(node, sampling_frequencies), \ "Sampling frequencies array must be sorted ascending"); \ - )) \ + )) \ IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_input_terminal), ( \ BUILD_ASSERT(!((SPATIAL_LOCATIONS_U32(node) & BIT(31))) || \ SPATIAL_LOCATIONS_U32(node) == BIT(31), \ "Raw Data set alongside other spatial locations"); \ BUILD_ASSERT(VALIDATE_INPUT_TERMINAL_ASSOCIATION(node), \ "Terminals associations must be Input<->Output"); \ - )) \ + )) \ IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_output_terminal), ( \ BUILD_ASSERT(VALIDATE_OUTPUT_TERMINAL_ASSOCIATION(node), \ "Terminals associations must be Input<->Output"); \ BUILD_ASSERT(VALIDATE_OUTPUT_TERMINAL_DATA_SOURCE(node), \ "Unsupported Output Terminal data source"); \ - )) \ + )) \ IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_feature_unit), ( \ BUILD_ASSERT(VALIDATE_FEATURE_UNIT_DATA_SOURCE(node), \ "Unsupported Feature Unit data source"); \ BUILD_ASSERT_FEATURE_UNIT_CONTROLS_LENGTH(node); \ - )) \ + )) \
BUILD_ASSERT(VALIDATE_LINKED_TERMINAL(node), \
"Linked Terminal must be Input or Output Terminal"); \
BUILD_ASSERT(!NEEDS_SUBSLOT_SIZE_AND_BIT_RESOLUTION(node) || \
Expand Down
23 changes: 21 additions & 2 deletions tests/subsys/usb/uac2/app.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,19 @@
front-right;
};

out_feature_unit: out_feature_unit {
compatible = "zephyr,uac2-feature-unit";
data-source = <&out_terminal>;
mute-control = "host-programmable";
automatic-gain-control =
"host-programmable" /* Primary */,
"host-programmable" /* Channel 1 */,
"host-programmable" /* Channel 2 */;
};

headphones_output: headphones {
compatible = "zephyr,uac2-output-terminal";
data-source = <&out_terminal>;
data-source = <&out_feature_unit>;
clock-source = <&uac_aclk>;
terminal-type = <BIDIRECTIONAL_TERMINAL_HEADSET>;
assoc-terminal = <&mic_input>;
Expand All @@ -50,9 +60,18 @@
front-left;
};

in_feature_unit: in_feature_unit {
compatible = "zephyr,uac2-feature-unit";
data-source = <&mic_input>;
mute-control = "host-programmable";
automatic-gain-control =
"not-present" /* Primary */,
"host-programmable" /* Channel 1 */;
};

in_terminal: in_terminal {
compatible = "zephyr,uac2-output-terminal";
data-source = <&mic_input>;
data-source = <&in_feature_unit>;
clock-source = <&uac_aclk>;
terminal-type = <USB_TERMINAL_STREAMING>;
};
Expand Down
Loading
Loading