1 /* 2 * Copyright (c) 2023 Nordic Semiconductor ASA 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /* The macros in this file are not public, applications should not use them. 8 * The macros are used to translate devicetree zephyr,uac2 compatible nodes 9 * into uint8_t array initializer. The output should be treated as a binary blob 10 * for the USB host to use (and parse). 11 */ 12 13 #include <zephyr/sys/util.h> 14 #include <zephyr/usb/usb_ch9.h> 15 16 #ifndef ZEPHYR_INCLUDE_USBD_UAC2_MACROS_H_ 17 #define ZEPHYR_INCLUDE_USBD_UAC2_MACROS_H_ 18 19 #define ARRAY_BIT(idx, value) (value##ull << idx) 20 21 #define U16_LE(value) ((value) & 0xFF), (((value) & 0xFF00) >> 8) 22 #define U32_LE(value) \ 23 ((value) & 0xFF), \ 24 (((value) & 0xFF00) >> 8), \ 25 (((value) & 0xFF0000) >> 16), \ 26 (((value) & 0xFF000000) >> 24) 27 28 #define ARRAY_ELEMENT_LESS_THAN_NEXT(node, prop, idx) \ 29 COND_CODE_1(IS_EQ(idx, UTIL_DEC(DT_PROP_LEN(node, prop))), \ 30 (1 /* nothing to compare the last element against */), \ 31 ((DT_PROP_BY_IDX(node, prop, idx) < \ 32 DT_PROP_BY_IDX(node, prop, UTIL_INC(idx))))) 33 #define IS_ARRAY_SORTED(node, prop) \ 34 DT_FOREACH_PROP_ELEM_SEP(node, prop, ARRAY_ELEMENT_LESS_THAN_NEXT, (&&)) 35 36 #define FIRST_INTERFACE_NUMBER 0x00 37 #define FIRST_IN_EP_ADDR 0x81 38 #define FIRST_OUT_EP_ADDR 0x01 39 40 /* A.1 Audio Function Class Code */ 41 #define AUDIO_FUNCTION AUDIO 42 43 /* A.2 Audio Function Subclass Codes */ 44 #define FUNCTION_SUBCLASS_UNDEFINED 0x00 45 46 /* A.3 Audio Function Protocol Codes */ 47 #define FUNCTION_PROTOCOL_UNDEFINED 0x00 48 #define AF_VERSION_02_00 IP_VERSION_02_00 49 50 /* A.4 Audio Interface Class Code */ 51 #define AUDIO 0x01 52 53 /* A.5 Audio Interface Subclass Codes */ 54 #define INTERFACE_SUBCLASS_UNDEFINED 0x00 55 #define AUDIOCONTROL 0x01 56 #define AUDIOSTREAMING 0x02 57 #define MIDISTREAMING 0x03 58 59 /* A.6 Audio Interface Protocol Codes */ 60 #define INTERFACE_PROTOCOL_UNDEFINED 0x00 61 #define IP_VERSION_02_00 0x20 62 63 /* A.8 Audio Class-Specific Descriptor Types */ 64 #define CS_UNDEFINED 0x20 65 #define CS_DEVICE 0x21 66 #define CS_CONFIGURATION 0x22 67 #define CS_STRING 0x23 68 #define CS_INTERFACE 0x24 69 #define CS_ENDPOINT 0x25 70 71 /* A.9 Audio Class-Specific AC Interface Descriptor Subtypes */ 72 #define AC_DESCRIPTOR_UNDEFINED 0x00 73 #define AC_DESCRIPTOR_HEADER 0x01 74 #define AC_DESCRIPTOR_INPUT_TERMINAL 0x02 75 #define AC_DESCRIPTOR_OUTPUT_TERMINAL 0x03 76 #define AC_DESCRIPTOR_MIXER_UNIT 0x04 77 #define AC_DESCRIPTOR_SELECTOR_UNIT 0x05 78 #define AC_DESCRIPTOR_FEATURE_UNIT 0x06 79 #define AC_DESCRIPTOR_EFFECT_UNIT 0x07 80 #define AC_DESCRIPTOR_PROCESSING_UNIT 0x08 81 #define AC_DESCRIPTOR_EXTENSION_UNIT 0x09 82 #define AC_DESCRIPTOR_CLOCK_SOURCE 0x0A 83 #define AC_DESCRIPTOR_CLOCK_SELECTOR 0x0B 84 #define AC_DESCRIPTOR_CLOCK_MULTIPLIER 0x0C 85 #define AC_DESCRIPTOR_SAMPLE_RATE_CONVERTER 0x0D 86 87 /* A.10 Audio Class-Specific AS Interface Descriptor Subtypes */ 88 #define AS_DESCRIPTOR_UNDEFINED 0x00 89 #define AS_DESCRIPTOR_GENERAL 0x01 90 #define AS_DESCRIPTOR_FORMAT_TYPE 0x02 91 #define AS_DESCRIPTOR_ENCODER 0x03 92 #define AS_DESCRIPTOR_DECODER 0x04 93 94 /* A.13 Audio Class-Specific Endpoint Descriptor Subtypes */ 95 #define DESCRIPTOR_UNDEFINED 0x00 96 #define EP_GENERAL 0x01 97 98 /* Universal Serial Bus Device Class Definition for Audio Data Formats 99 * Release 2.0, May 31, 2006. A.1 Format Type Codes 100 * Values are in decimal to facilitate use with IS_EQ() macro. 101 */ 102 #define FORMAT_TYPE_UNDEFINED 0 103 #define FORMAT_TYPE_I 1 104 #define FORMAT_TYPE_II 2 105 #define FORMAT_TYPE_III 3 106 #define FORMAT_TYPE_IV 4 107 #define EXT_FORMAT_TYPE_I 129 108 #define EXT_FORMAT_TYPE_II 130 109 #define EXT_FORMAT_TYPE_III 131 110 111 /* Automatically assign Entity IDs based on entities order in devicetree */ 112 #define ENTITY_ID(e) UTIL_INC(DT_NODE_CHILD_IDX(e)) 113 114 /* Name of uint8_t array holding descriptor data */ 115 #define DESCRIPTOR_NAME(prefix, node) uac2_## prefix ## _ ## node 116 117 /* Connected Entity ID or 0 if property is not defined. Rely on devicetree 118 * "required: true" to fail compilation if mandatory handle (e.g. clock source) 119 * is absent. 120 */ 121 #define CONNECTED_ENTITY_ID(entity, phandle) \ 122 COND_CODE_1(DT_NODE_HAS_PROP(entity, phandle), \ 123 (ENTITY_ID(DT_PHANDLE_BY_IDX(entity, phandle, 0))), (0)) 124 125 #define ID_IF_TERMINAL_ASSOCIATES_WITH_TARGET(entity, target_id) \ 126 IF_ENABLED(UTIL_AND(IS_EQ( \ 127 CONNECTED_ENTITY_ID(entity, assoc_terminal), target_id), \ 128 UTIL_OR( \ 129 DT_NODE_HAS_COMPAT(entity, zephyr_uac2_input_terminal), \ 130 DT_NODE_HAS_COMPAT(entity, zephyr_uac2_output_terminal) \ 131 )), (ENTITY_ID(entity))) 132 133 /* Find ID of terminal entity associated with given terminal entity. This macro 134 * evaluates to "+ 0" if there isn't any terminal entity associated. If there 135 * are terminal entities associated with given terminal, then the macro evalues 136 * to "IDs + 0" where IDs are the terminal entities ID separated by spaces. 137 * 138 * If there is exactly one ID then compiler will compute correct value. 139 * If there is more than one associated entity, then it will fail at build time 140 * (as it should) because the caller expects single integer. 141 */ 142 #define FIND_ASSOCIATED_TERMINAL(entity) \ 143 DT_FOREACH_CHILD_VARGS(DT_PARENT(entity), \ 144 ID_IF_TERMINAL_ASSOCIATES_WITH_TARGET, ENTITY_ID(entity)) + 0 145 146 /* If entity has assoc_terminal property, return the entity ID of associated 147 * terminal. Otherwise, search if any other terminal entity points to us and 148 * use its ID. If search yields no results then this evaluates to "+ 0" which 149 * matches the value USB Audio Class expects in bAssocTerminal if no association 150 * exists. 151 * 152 * This is a workaround for lack of cyclic dependencies support in devicetree. 153 */ 154 #define ASSOCIATED_TERMINAL_ID(entity) \ 155 COND_CODE_1(DT_NODE_HAS_PROP(entity, assoc_terminal), \ 156 (CONNECTED_ENTITY_ID(entity, assoc_terminal)), \ 157 (FIND_ASSOCIATED_TERMINAL(entity))) 158 159 160 #define CLOCK_SOURCE_ATTRIBUTES(entity) \ 161 (DT_ENUM_IDX(entity, clock_type)) | \ 162 (DT_PROP(entity, sof_synchronized) << 2) 163 164 /* Control properties are optional enums in devicetree that can either be 165 * "read-only" or "host-programmable". If the property is missing, then it means 166 * that control is not present. Convert the control property into actual values 167 * used by USB Audio Class, i.e. 0b00 when control is not present, 0b01 when 168 * control is present but read-only and 0b11 when control can be programmed by 169 * host. Value 0b10 is not allowed by the specification. 170 */ 171 #define CONTROL_BITS(entity, control_name, bitshift) \ 172 COND_CODE_1(DT_NODE_HAS_PROP(entity, control_name), \ 173 (COND_CODE_0(DT_ENUM_IDX(entity, control_name), \ 174 ((0x1 << bitshift)) /* read-only */, \ 175 ((0x3 << bitshift)) /* host-programmable */)), \ 176 ((0x0 << bitshift)) /* control not present */) 177 178 #define CLOCK_SOURCE_CONTROLS(entity) \ 179 CONTROL_BITS(entity, frequency_control, 0) | \ 180 CONTROL_BITS(entity, validity_control, 2) 181 182 #define INPUT_TERMINAL_CONTROLS(entity) \ 183 CONTROL_BITS(entity, copy_protect_control, 0) | \ 184 CONTROL_BITS(entity, connector_control, 2) | \ 185 CONTROL_BITS(entity, overload_control, 4) | \ 186 CONTROL_BITS(entity, cluster_control, 6) | \ 187 CONTROL_BITS(entity, underflow_control, 8) | \ 188 CONTROL_BITS(entity, overflow_control, 10) 189 190 #define OUTPUT_TERMINAL_CONTROLS(entity) \ 191 CONTROL_BITS(entity, copy_protect_control, 0) | \ 192 CONTROL_BITS(entity, connector_control, 2) | \ 193 CONTROL_BITS(entity, overload_control, 4) | \ 194 CONTROL_BITS(entity, underflow_control, 6) | \ 195 CONTROL_BITS(entity, overflow_control, 8) 196 197 #define AUDIO_STREAMING_DATA_ENDPOINT_CONTROLS(node) \ 198 CONTROL_BITS(node, pitch_control, 0) | \ 199 CONTROL_BITS(node, data_overrun_control, 2) | \ 200 CONTROL_BITS(node, data_underrun_control, 4) 201 202 /* 4.1 Audio Channel Cluster Descriptor */ 203 #define SPATIAL_LOCATIONS_ARRAY(cluster) \ 204 DT_PROP(cluster, front_left), \ 205 DT_PROP(cluster, front_right), \ 206 DT_PROP(cluster, front_center), \ 207 DT_PROP(cluster, low_frequency_effects), \ 208 DT_PROP(cluster, back_left), \ 209 DT_PROP(cluster, back_right), \ 210 DT_PROP(cluster, front_left_of_center), \ 211 DT_PROP(cluster, front_right_of_center), \ 212 DT_PROP(cluster, back_center), \ 213 DT_PROP(cluster, side_left), \ 214 DT_PROP(cluster, side_right), \ 215 DT_PROP(cluster, top_center), \ 216 DT_PROP(cluster, top_front_left), \ 217 DT_PROP(cluster, top_front_center), \ 218 DT_PROP(cluster, top_front_right), \ 219 DT_PROP(cluster, top_back_left), \ 220 DT_PROP(cluster, top_back_center), \ 221 DT_PROP(cluster, top_back_right), \ 222 DT_PROP(cluster, top_front_left_of_center), \ 223 DT_PROP(cluster, top_front_right_of_center), \ 224 DT_PROP(cluster, left_low_frequency_effects), \ 225 DT_PROP(cluster, right_low_frequency_effects), \ 226 DT_PROP(cluster, top_side_left), \ 227 DT_PROP(cluster, top_side_right), \ 228 DT_PROP(cluster, bottom_center), \ 229 DT_PROP(cluster, back_left_of_center), \ 230 DT_PROP(cluster, back_right_of_center), \ 231 0, 0, 0, 0, /* D27..D30: Reserved */ \ 232 DT_PROP(cluster, raw_data) 233 234 #define SPATIAL_LOCATIONS_U32(entity) \ 235 (FOR_EACH_IDX(ARRAY_BIT, (|), SPATIAL_LOCATIONS_ARRAY(entity))) 236 #define NUM_SPATIAL_LOCATIONS(entity) \ 237 (FOR_EACH(IDENTITY, (+), SPATIAL_LOCATIONS_ARRAY(entity))) 238 #define SPATIAL_LOCATIONS(entity) U32_LE(SPATIAL_LOCATIONS_U32(entity)) 239 240 241 /* 4.7.2.1 Clock Source Descriptor */ 242 #define CLOCK_SOURCE_DESCRIPTOR(entity) \ 243 0x08, /* bLength */ \ 244 CS_INTERFACE, /* bDescriptorType */ \ 245 AC_DESCRIPTOR_CLOCK_SOURCE, /* bDescriptorSubtype */\ 246 ENTITY_ID(entity), /* bClockID */ \ 247 CLOCK_SOURCE_ATTRIBUTES(entity), /* bmAttributes */ \ 248 CLOCK_SOURCE_CONTROLS(entity), /* bmControls */ \ 249 CONNECTED_ENTITY_ID(entity, assoc_terminal), /* bAssocTerminal */ \ 250 0x00, /* iClockSource */ 251 252 /* 4.7.2.4 Input Terminal Descriptor */ 253 #define INPUT_TERMINAL_DESCRIPTOR(entity) \ 254 0x11, /* bLength */ \ 255 CS_INTERFACE, /* bDescriptorType */ \ 256 AC_DESCRIPTOR_INPUT_TERMINAL, /* bDescriptorSubtype */\ 257 ENTITY_ID(entity), /* bTerminalID */ \ 258 U16_LE(DT_PROP(entity, terminal_type)), /* wTerminalType */ \ 259 ASSOCIATED_TERMINAL_ID(entity), /* bAssocTerminal */ \ 260 CONNECTED_ENTITY_ID(entity, clock_source), /* bCSourceID */ \ 261 NUM_SPATIAL_LOCATIONS(entity), /* bNrChannels */ \ 262 SPATIAL_LOCATIONS(entity), /* bmChannelConfig */ \ 263 0x00, /* iChannelNames */ \ 264 U16_LE(INPUT_TERMINAL_CONTROLS(entity)), /* bmControls */ \ 265 0x00, /* iTerminal */ 266 267 /* 4.7.2.5 Output Terminal Descriptor */ 268 #define OUTPUT_TERMINAL_DESCRIPTOR(entity) \ 269 0x0C, /* bLength */ \ 270 CS_INTERFACE, /* bDescriptorType */ \ 271 AC_DESCRIPTOR_OUTPUT_TERMINAL, /* bDescriptorSubtype */\ 272 ENTITY_ID(entity), /* bTerminalID */ \ 273 U16_LE(DT_PROP(entity, terminal_type)), /* wTerminalType */ \ 274 ASSOCIATED_TERMINAL_ID(entity), /* bAssocTerminal */ \ 275 CONNECTED_ENTITY_ID(entity, data_source), /* bSourceID */ \ 276 CONNECTED_ENTITY_ID(entity, clock_source), /* bCSourceID */ \ 277 U16_LE(OUTPUT_TERMINAL_CONTROLS(entity)), /* bmControls */ \ 278 0x00, /* iTerminal */ 279 280 #define ENTITY_HEADER(entity) \ 281 IF_ENABLED(DT_NODE_HAS_COMPAT(entity, zephyr_uac2_clock_source), ( \ 282 CLOCK_SOURCE_DESCRIPTOR(entity) \ 283 )) \ 284 IF_ENABLED(DT_NODE_HAS_COMPAT(entity, zephyr_uac2_input_terminal), ( \ 285 INPUT_TERMINAL_DESCRIPTOR(entity) \ 286 )) \ 287 IF_ENABLED(DT_NODE_HAS_COMPAT(entity, zephyr_uac2_output_terminal), ( \ 288 OUTPUT_TERMINAL_DESCRIPTOR(entity) \ 289 )) 290 291 #define ENTITY_HEADER_ARRAYS(entity) \ 292 IF_ENABLED(UTIL_NOT(IS_EMPTY(ENTITY_HEADER(entity))), ( \ 293 static uint8_t DESCRIPTOR_NAME(ac_entity, entity)[] = { \ 294 ENTITY_HEADER(entity) \ 295 }; \ 296 )) 297 298 #define ENTITY_HEADER_PTRS(entity) \ 299 IF_ENABLED(UTIL_NOT(IS_EMPTY(ENTITY_HEADER(entity))), ( \ 300 (struct usb_desc_header *) &DESCRIPTOR_NAME(ac_entity, entity), \ 301 )) 302 303 #define ENTITY_HEADERS(node) DT_FOREACH_CHILD(node, ENTITY_HEADER) 304 #define ENTITY_HEADERS_ARRAYS(node) DT_FOREACH_CHILD(node, ENTITY_HEADER_ARRAYS) 305 #define ENTITY_HEADERS_PTRS(node) DT_FOREACH_CHILD(node, ENTITY_HEADER_PTRS) 306 #define ENTITY_HEADERS_LENGTH(node) sizeof((uint8_t []){ENTITY_HEADERS(node)}) 307 308 #define AUDIO_STREAMING_CONTROLS(node) \ 309 CONTROL_BITS(entity, active_alternate_setting_control, 0) | \ 310 CONTROL_BITS(entity, valid_alternate_settings_control, 2) 311 312 /* TODO: Support other format types. Currently the PCM format (0x00000001) is 313 * hardcoded and format type is either I or IV depending on whether the 314 * interface has isochronous endpoint or not. 315 */ 316 #define AUDIO_STREAMING_FORMAT_TYPE(node) \ 317 COND_CODE_0(DT_PROP(node, external_interface), \ 318 (FORMAT_TYPE_I), (FORMAT_TYPE_IV)) 319 #define AUDIO_STREAMING_FORMATS(node) U32_LE(0x00000001) 320 321 /* If AudioStreaming is linked to input terminal, obtain the channel cluster 322 * configuration from the linked terminal. Otherwise (it has to be connected 323 * to output terminal) obtain the channel cluster configuration from data source 324 * entity. 325 */ 326 #define AUDIO_STREAMING_CHANNEL_CLUSTER(node) \ 327 IF_ENABLED(DT_NODE_HAS_COMPAT(DT_PROP(node, linked_terminal), \ 328 zephyr_uac2_input_terminal), ( \ 329 DT_PROP(node, linked_terminal) \ 330 )) \ 331 IF_ENABLED(DT_NODE_HAS_COMPAT(DT_PROP(node, linked_terminal), \ 332 zephyr_uac2_output_terminal), ( \ 333 DT_PROP(DT_PROP(node, linked_terminal), data_source) \ 334 )) 335 336 #define AUDIO_STREAMING_NUM_SPATIAL_LOCATIONS(node) \ 337 NUM_SPATIAL_LOCATIONS(AUDIO_STREAMING_CHANNEL_CLUSTER(node)) 338 #define AUDIO_STREAMING_SPATIAL_LOCATIONS(node) \ 339 SPATIAL_LOCATIONS(AUDIO_STREAMING_CHANNEL_CLUSTER(node)) 340 341 /* 4.9.2 Class-Specific AS Interface Descriptor */ 342 #define AUDIO_STREAMING_GENERAL_DESCRIPTOR(node) \ 343 0x10, /* bLength */ \ 344 CS_INTERFACE, /* bDescriptorType */ \ 345 AS_DESCRIPTOR_GENERAL, /* bDescriptorSubtype */\ 346 CONNECTED_ENTITY_ID(node, linked_terminal), /* bTerminalLink */ \ 347 AUDIO_STREAMING_CONTROLS(node), /* bmControls*/ \ 348 AUDIO_STREAMING_FORMAT_TYPE(node), /* bFormatType */ \ 349 AUDIO_STREAMING_FORMATS(node), /* bmFormats */ \ 350 AUDIO_STREAMING_NUM_SPATIAL_LOCATIONS(node), /* bNrChannels */ \ 351 AUDIO_STREAMING_SPATIAL_LOCATIONS(node), /* bmChannelConfig */ \ 352 0x00, /* iChannelNames */ 353 354 /* Universal Serial Bus Device Class Definition for Audio Data Formats 355 * Release 2.0, May 31, 2006. 2.3.1.6 Type I Format Type Descriptor 356 */ 357 #define AUDIO_STREAMING_FORMAT_I_TYPE_DESCRIPTOR(node) \ 358 0x06, /* bLength */ \ 359 CS_INTERFACE, /* bDescriptorType */ \ 360 AS_DESCRIPTOR_FORMAT_TYPE, /* bDescriptorSubtype */\ 361 FORMAT_TYPE_I, /* bFormatType */ \ 362 DT_PROP(node, subslot_size), /* bSubslotSize */ \ 363 DT_PROP(node, bit_resolution), /* bBitResolution */ 364 365 /* Universal Serial Bus Device Class Definition for Audio Data Formats 366 * Release 2.0, May 31, 2006. 2.3.4.1 Type IV Format Type Descriptor 367 */ 368 #define AUDIO_STREAMING_FORMAT_IV_TYPE_DESCRIPTOR(node) \ 369 0x04, /* bLength */ \ 370 CS_INTERFACE, /* bDescriptorType */ \ 371 AS_DESCRIPTOR_FORMAT_TYPE, /* bDescriptorSubtype */\ 372 FORMAT_TYPE_IV, /* bFormatType */ 373 374 /* 4.9.3 Class-Specific AS Format Type Descriptor */ 375 #define AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR(node) \ 376 IF_ENABLED(IS_EQ(AUDIO_STREAMING_FORMAT_TYPE(node), FORMAT_TYPE_I), ( \ 377 AUDIO_STREAMING_FORMAT_I_TYPE_DESCRIPTOR(node))) \ 378 IF_ENABLED(IS_EQ(AUDIO_STREAMING_FORMAT_TYPE(node), FORMAT_TYPE_IV), ( \ 379 AUDIO_STREAMING_FORMAT_IV_TYPE_DESCRIPTOR(node))) 380 381 #define AUDIO_STREAMING_INTERFACE_DESCRIPTORS(node) \ 382 AUDIO_STREAMING_GENERAL_DESCRIPTOR(node) \ 383 AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR(node) 384 385 #define AUDIO_STREAMING_INTERFACE_DESCRIPTORS_ARRAYS(node) \ 386 static uint8_t DESCRIPTOR_NAME(as_general_desc, node)[] = { \ 387 AUDIO_STREAMING_GENERAL_DESCRIPTOR(node) \ 388 }; \ 389 static uint8_t DESCRIPTOR_NAME(as_format_desc, node)[] = { \ 390 AUDIO_STREAMING_FORMAT_TYPE_DESCRIPTOR(node) \ 391 }; 392 393 #define AUDIO_STREAMING_INTERFACE_DESCRIPTORS_PTRS(node) \ 394 (struct usb_desc_header *) &DESCRIPTOR_NAME(as_general_desc, node), \ 395 (struct usb_desc_header *) &DESCRIPTOR_NAME(as_format_desc, node), 396 397 /* 4.7.2 Class-Specific AC Interface Descriptor */ 398 #define AC_INTERFACE_HEADER_DESCRIPTOR(node) \ 399 0x09, /* bLength */ \ 400 CS_INTERFACE, /* bDescriptorType */ \ 401 AC_DESCRIPTOR_HEADER, /* bDescriptorSubtype */\ 402 U16_LE(0x0200), /* bcdADC */ \ 403 DT_PROP(node, audio_function), /* bCategory */ \ 404 U16_LE(9 + ENTITY_HEADERS_LENGTH(node)), /* wTotalLength */ \ 405 0x00, /* bmControls */ \ 406 407 #define AC_INTERFACE_HEADER_DESCRIPTOR_ARRAY(node) \ 408 static uint8_t DESCRIPTOR_NAME(ac_header, node)[] = { \ 409 AC_INTERFACE_HEADER_DESCRIPTOR(node) \ 410 }; 411 412 #define AC_INTERFACE_HEADER_DESCRIPTOR_PTR(node) \ 413 (struct usb_desc_header *) &DESCRIPTOR_NAME(ac_header, node), 414 415 #define IS_AUDIOSTREAMING_INTERFACE(node) \ 416 DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming) 417 418 #define UAC2_NUM_INTERFACES(node) \ 419 1 /* AudioControl interface */ + \ 420 DT_FOREACH_CHILD_SEP(node, IS_AUDIOSTREAMING_INTERFACE, (+)) 421 422 /* 4.6 Interface Association Descriptor */ 423 #define UAC2_INTERFACE_ASSOCIATION_DESCRIPTOR(node) \ 424 0x08, /* bLength */ \ 425 USB_DESC_INTERFACE_ASSOC, /* bDescriptorType */ \ 426 FIRST_INTERFACE_NUMBER, /* bFirstInterface */ \ 427 UAC2_NUM_INTERFACES(node), /* bInterfaceCount */ \ 428 AUDIO_FUNCTION, /* bFunctionClass */ \ 429 FUNCTION_SUBCLASS_UNDEFINED, /* bFunctionSubclass */ \ 430 AF_VERSION_02_00, /* bFunctionProtocol */ \ 431 0x00, /* iFunction */ 432 433 #define UAC2_INTERFACE_ASSOCIATION_DESCRIPTOR_ARRAY(node) \ 434 static uint8_t DESCRIPTOR_NAME(iad, node)[] = { \ 435 UAC2_INTERFACE_ASSOCIATION_DESCRIPTOR(node) \ 436 }; 437 438 #define UAC2_INTERFACE_ASSOCIATION_DESCRIPTOR_PTR(node) \ 439 (struct usb_desc_header *) &DESCRIPTOR_NAME(iad, node), 440 441 /* 4.7.1 Standard AC Interface Descriptor */ 442 #define AC_INTERFACE_DESCRIPTOR(node) \ 443 0x09, /* bLength */ \ 444 USB_DESC_INTERFACE, /* bDescriptorType */ \ 445 FIRST_INTERFACE_NUMBER, /* bInterfaceNumber */ \ 446 0x00, /* bAlternateSetting */ \ 447 DT_PROP(node, interrupt_endpoint), /* bNumEndpoints */ \ 448 AUDIO, /* bInterfaceClass */ \ 449 AUDIOCONTROL, /* bInterfaceSubClass */\ 450 IP_VERSION_02_00, /* bInterfaceProtocol */\ 451 0x00, /* iInterface */ 452 453 #define AC_INTERFACE_DESCRIPTOR_ARRAY(node) \ 454 static uint8_t DESCRIPTOR_NAME(ac_interface, node)[] = { \ 455 AC_INTERFACE_DESCRIPTOR(node) \ 456 }; 457 458 #define AC_INTERFACE_DESCRIPTOR_PTR(node) \ 459 (struct usb_desc_header *) &DESCRIPTOR_NAME(ac_interface, node), 460 461 /* 4.8.2.1 Standard AC Interrupt Endpoint Descriptor */ 462 #define AC_ENDPOINT_DESCRIPTOR(node) \ 463 0x07, /* bLength */ \ 464 USB_DESC_ENDPOINT, /* bDescriptorType */ \ 465 FIRST_IN_EP_ADDR, /* bEndpointAddress */ \ 466 USB_EP_TYPE_INTERRUPT, /* bmAttributes */ \ 467 0x06, /* wMaxPacketSize */ \ 468 0x01, /* bInterval */ \ 469 470 #define AC_ENDPOINT_DESCRIPTOR_ARRAY(node) \ 471 static uint8_t DESCRIPTOR_NAME(ac_endpoint, node)[] = { \ 472 AC_ENDPOINT_DESCRIPTOR(node) \ 473 }; 474 475 #define AC_ENDPOINT_DESCRIPTOR_PTR(node) \ 476 (struct usb_desc_header *) &DESCRIPTOR_NAME(ac_endpoint, node), 477 478 #define FIND_AUDIOSTREAMING(node, fn, ...) \ 479 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \ 480 fn(node, __VA_ARGS__))) 481 482 #define FOR_EACH_AUDIOSTREAMING_INTERFACE(node, fn, ...) \ 483 DT_FOREACH_CHILD_VARGS(node, FIND_AUDIOSTREAMING, fn, __VA_ARGS__) 484 485 #define COUNT_AS_INTERFACES_BEFORE_IDX(node, idx) \ 486 + 1 * (DT_NODE_CHILD_IDX(node) < idx) 487 488 #define AS_INTERFACE_NUMBER(node) \ 489 FIRST_INTERFACE_NUMBER + 1 /* AudioControl interface */ + \ 490 FOR_EACH_AUDIOSTREAMING_INTERFACE(DT_PARENT(node), \ 491 COUNT_AS_INTERFACES_BEFORE_IDX, DT_NODE_CHILD_IDX(node)) 492 493 #define AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node) \ 494 UTIL_NOT(DT_PROP(node, external_interface)) 495 496 #define AS_IS_USB_ISO_IN(node) \ 497 UTIL_AND(AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node), \ 498 DT_NODE_HAS_COMPAT(DT_PROP(node, linked_terminal), \ 499 zephyr_uac2_output_terminal)) 500 501 #define AS_IS_USB_ISO_OUT(node) \ 502 UTIL_AND(AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node), \ 503 DT_NODE_HAS_COMPAT(DT_PROP(node, linked_terminal), \ 504 zephyr_uac2_input_terminal)) 505 506 #define CLK_IS_SOF_SYNCHRONIZED(entity) \ 507 IF_ENABLED(DT_NODE_HAS_COMPAT(entity, zephyr_uac2_clock_source), ( \ 508 DT_PROP(entity, sof_synchronized) \ 509 )) 510 511 /* Sampling frequencies are sorted (asserted at compile time), so just grab 512 * last sampling frequency. 513 */ 514 #define CLK_MAX_FREQUENCY(entity) \ 515 IF_ENABLED(DT_NODE_HAS_COMPAT(entity, zephyr_uac2_clock_source), ( \ 516 DT_PROP_BY_IDX(entity, sampling_frequencies, \ 517 UTIL_DEC(DT_PROP_LEN(entity, sampling_frequencies))) \ 518 )) 519 520 #define AS_CLK_SOURCE(node) \ 521 DT_PROP(DT_PROP(node, linked_terminal), clock_source) 522 523 #define AS_CLK_MAX_FREQUENCY(node) \ 524 CLK_MAX_FREQUENCY(AS_CLK_SOURCE(node)) 525 526 #define AS_IS_SOF_SYNCHRONIZED(node) \ 527 CLK_IS_SOF_SYNCHRONIZED(AS_CLK_SOURCE(node)) 528 529 #define AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node) \ 530 UTIL_AND(UTIL_AND(AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node), \ 531 UTIL_NOT(DT_PROP(node, implicit_feedback))), \ 532 UTIL_AND(UTIL_NOT(AS_IS_SOF_SYNCHRONIZED(node)), \ 533 AS_IS_USB_ISO_OUT(node))) 534 535 #define AS_INTERFACE_NUM_ENDPOINTS(node) \ 536 (AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node) + \ 537 AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node)) 538 539 /* 4.9.1 Standard AS Interface Descriptor */ 540 #define AS_INTERFACE_DESCRIPTOR(node, alternate, numendpoints) \ 541 0x09, /* bLength */ \ 542 USB_DESC_INTERFACE, /* bDescriptorType */ \ 543 AS_INTERFACE_NUMBER(node), /* bInterfaceNumber */ \ 544 alternate, /* bAlternateSetting */ \ 545 numendpoints, /* bNumEndpoints */ \ 546 AUDIO, /* bInterfaceClass */ \ 547 AUDIOSTREAMING, /* bInterfaceSubClass */\ 548 IP_VERSION_02_00, /* bInterfaceProtocol */\ 549 0x00, /* iInterface */ 550 551 #define AS_INTERFACE_DESCRIPTOR_ARRAY(node, alternate, numendpoints) \ 552 static uint8_t DESCRIPTOR_NAME(as_if_alt##alternate, node)[] = { \ 553 AS_INTERFACE_DESCRIPTOR(node, alternate, numendpoints) \ 554 }; 555 556 #define AS_INTERFACE_DESCRIPTOR_PTR(node, alternate) \ 557 (struct usb_desc_header *) &DESCRIPTOR_NAME(as_if_alt##alternate, node), 558 559 #define COUNT_AS_OUT_ENDPOINTS_BEFORE_IDX(node, idx) \ 560 + AS_IS_USB_ISO_OUT(node) * (DT_NODE_CHILD_IDX(node) < idx) 561 562 #define COUNT_AS_IN_ENDPOINTS_BEFORE_IDX(node, idx) \ 563 + (AS_IS_USB_ISO_IN(node) + AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node)) \ 564 * (DT_NODE_CHILD_IDX(node) < idx) 565 566 /* FIXME: Ensure that the explicit feedback endpoints assignments match 567 * numbering requirements from Universal Serial Bus Specification Revision 2.0 568 * 9.6.6 Endpoint. This FIXME is not limited to the macros here but also to 569 * actual USB stack endpoint fixup (so the fixup does not break the numbering). 570 * 571 * This FIXME does not affect nRF52 and nRF53 when implicit feedback is used 572 * because the endpoints after fixup will be 0x08 and 0x88 because there are 573 * only two isochronous endpoints on these devices (one IN, one OUT). 574 */ 575 #define AS_NEXT_OUT_EP_ADDR(node) \ 576 FIRST_OUT_EP_ADDR + \ 577 FOR_EACH_AUDIOSTREAMING_INTERFACE(DT_PARENT(node), \ 578 COUNT_AS_OUT_ENDPOINTS_BEFORE_IDX, DT_NODE_CHILD_IDX(node)) 579 580 #define AS_NEXT_IN_EP_ADDR(node) \ 581 FIRST_IN_EP_ADDR + DT_PROP(DT_PARENT(node), interrupt_endpoint) + \ 582 FOR_EACH_AUDIOSTREAMING_INTERFACE(DT_PARENT(node), \ 583 COUNT_AS_IN_ENDPOINTS_BEFORE_IDX, DT_NODE_CHILD_IDX(node)) 584 585 #define AS_DATA_EP_ADDR(node) \ 586 COND_CODE_1(AS_IS_USB_ISO_OUT(node), \ 587 (AS_NEXT_OUT_EP_ADDR(node)), \ 588 (AS_NEXT_IN_EP_ADDR(node))) 589 590 #define AS_BYTES_PER_SAMPLE(node) \ 591 DT_PROP(node, subslot_size) 592 593 /* Asynchronous endpoints needs space for 1 extra sample */ 594 #define AS_SAMPLES_PER_PACKET(node) \ 595 ((ROUND_UP(AS_CLK_MAX_FREQUENCY(node), 1000) / 1000) + \ 596 UTIL_NOT(AS_IS_SOF_SYNCHRONIZED(node))) 597 598 #define AS_DATA_EP_SYNC_TYPE(node) \ 599 COND_CODE_1(AS_IS_SOF_SYNCHRONIZED(node), (0x3 << 2), (0x1 << 2)) 600 601 #define AS_DATA_EP_USAGE_TYPE(node) \ 602 COND_CODE_1(UTIL_AND(DT_PROP(node, implicit_feedback), \ 603 UTIL_NOT(AS_IS_USB_ISO_OUT(node))), (0x2 << 4), (0x0 << 4)) 604 605 #define AS_DATA_EP_ATTR(node) \ 606 USB_EP_TYPE_ISO | AS_DATA_EP_SYNC_TYPE(node) | \ 607 AS_DATA_EP_USAGE_TYPE(node) 608 609 #define AS_DATA_EP_MAX_PACKET_SIZE(node) \ 610 AUDIO_STREAMING_NUM_SPATIAL_LOCATIONS(node) * \ 611 AS_BYTES_PER_SAMPLE(node) * AS_SAMPLES_PER_PACKET(node) 612 613 /* 4.10.1.1 Standard AS Isochronous Audio Data Endpoint Descriptor */ 614 #define STANDARD_AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTOR(node) \ 615 0x07, /* bLength */ \ 616 USB_DESC_ENDPOINT, /* bDescriptorType */ \ 617 AS_DATA_EP_ADDR(node), /* bEndpointAddress */ \ 618 AS_DATA_EP_ATTR(node), /* bmAttributes */ \ 619 U16_LE(AS_DATA_EP_MAX_PACKET_SIZE(node)), /* wMaxPacketSize */ \ 620 0x01, /* bInterval */ 621 622 #define LOCK_DELAY_UNITS(node) \ 623 COND_CODE_1(DT_NODE_HAS_PROP(node, lock_delay_units), \ 624 (1 + DT_ENUM_IDX(node, lock_delay_units)), \ 625 (0 /* Undefined */)) 626 627 /* 4.10.1.2 Class-Specific AS Isochronous Audio Data Endpoint Descriptor */ 628 #define CLASS_SPECIFIC_AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTOR(node) \ 629 0x08, /* bLength */ \ 630 CS_ENDPOINT, /* bDescriptorType */ \ 631 EP_GENERAL, /* bDescriptorSubtype */\ 632 0x00, /* bmAttributes */ \ 633 AUDIO_STREAMING_DATA_ENDPOINT_CONTROLS(node), /* bmControls */ \ 634 LOCK_DELAY_UNITS(node), /* bLockDelayUnits */ \ 635 U16_LE(DT_PROP_OR(node, lock_delay, 0)), /* wLockDelay */ 636 637 #define AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTORS(node) \ 638 STANDARD_AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTOR(node) \ 639 CLASS_SPECIFIC_AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTOR(node) 640 641 #define AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTORS_ARRAYS(node) \ 642 static uint8_t DESCRIPTOR_NAME(std_data_ep, node)[] = { \ 643 STANDARD_AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTOR(node) \ 644 }; \ 645 static uint8_t DESCRIPTOR_NAME(cs_data_ep, node)[] = { \ 646 CLASS_SPECIFIC_AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTOR(node) \ 647 }; 648 649 #define AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTORS_PTRS(node) \ 650 (struct usb_desc_header *) &DESCRIPTOR_NAME(std_data_ep, node), \ 651 (struct usb_desc_header *) &DESCRIPTOR_NAME(cs_data_ep, node), 652 653 #define AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR(node) \ 654 0x07, /* bLength */ \ 655 USB_DESC_ENDPOINT, /* bDescriptorType */ \ 656 AS_NEXT_IN_EP_ADDR(node), /* bEndpointAddress */ \ 657 0x11, /* bmAttributes */ \ 658 U16_LE(0x03), /* FIXME: 4 on High-Speed*/ /* wMaxPacketSize */ \ 659 0x01, /* TODO: adjust to P 5.12.4.2 Feedback */ /* bInterval */ 660 661 #define AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR_ARRAY(node) \ 662 static uint8_t DESCRIPTOR_NAME(feedback_ep, node)[] = { \ 663 AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR(node) \ 664 }; 665 666 #define AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR_PTR(node) \ 667 (struct usb_desc_header *) &DESCRIPTOR_NAME(feedback_ep, node), 668 669 #define AS_DESCRIPTORS(node) \ 670 AS_INTERFACE_DESCRIPTOR(node, 0, 0) \ 671 IF_ENABLED(AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node), ( \ 672 AS_INTERFACE_DESCRIPTOR(node, 1, \ 673 AS_INTERFACE_NUM_ENDPOINTS(node)))) \ 674 AUDIO_STREAMING_INTERFACE_DESCRIPTORS(node) \ 675 IF_ENABLED(AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node), ( \ 676 AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTORS(node) \ 677 IF_ENABLED(AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node), ( \ 678 AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR(node))) \ 679 )) 680 681 #define AS_DESCRIPTORS_ARRAYS(node) \ 682 AS_INTERFACE_DESCRIPTOR_ARRAY(node, 0, 0) \ 683 IF_ENABLED(AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node), ( \ 684 AS_INTERFACE_DESCRIPTOR_ARRAY(node, 1, \ 685 AS_INTERFACE_NUM_ENDPOINTS(node)))) \ 686 AUDIO_STREAMING_INTERFACE_DESCRIPTORS_ARRAYS(node) \ 687 IF_ENABLED(AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node), ( \ 688 AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTORS_ARRAYS(node) \ 689 IF_ENABLED(AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node), ( \ 690 AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR_ARRAY(node))) \ 691 )) 692 693 #define AS_DESCRIPTORS_PTRS(node) \ 694 AS_INTERFACE_DESCRIPTOR_PTR(node, 0) \ 695 IF_ENABLED(AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node), ( \ 696 AS_INTERFACE_DESCRIPTOR_PTR(node, 1))) \ 697 AUDIO_STREAMING_INTERFACE_DESCRIPTORS_PTRS(node) \ 698 IF_ENABLED(AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node), ( \ 699 AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTORS_PTRS(node) \ 700 IF_ENABLED(AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node), ( \ 701 AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR_PTR(node))) \ 702 )) 703 704 #define AS_DESCRIPTORS_IF_AUDIOSTREAMING(node) \ 705 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \ 706 AS_DESCRIPTORS(node))) 707 708 #define AS_DESCRIPTORS_ARRAYS_IF_AUDIOSTREAMING(node) \ 709 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \ 710 AS_DESCRIPTORS_ARRAYS(node))) 711 712 #define AS_DESCRIPTORS_PTRS_IF_AUDIOSTREAMING(node) \ 713 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \ 714 AS_DESCRIPTORS_PTRS(node))) 715 716 #define UAC2_AUDIO_CONTROL_DESCRIPTORS(node) \ 717 AC_INTERFACE_DESCRIPTOR(node) \ 718 AC_INTERFACE_HEADER_DESCRIPTOR(node) \ 719 ENTITY_HEADERS(node) \ 720 IF_ENABLED(DT_PROP(node, interrupt_endpoint), ( \ 721 AC_ENDPOINT_DESCRIPTOR(node))) 722 723 #define UAC2_AUDIO_CONTROL_DESCRIPTOR_ARRAYS(node) \ 724 AC_INTERFACE_DESCRIPTOR_ARRAY(node) \ 725 AC_INTERFACE_HEADER_DESCRIPTOR_ARRAY(node) \ 726 ENTITY_HEADERS_ARRAYS(node) \ 727 IF_ENABLED(DT_PROP(node, interrupt_endpoint), ( \ 728 AC_ENDPOINT_DESCRIPTOR_ARRAY(node))) 729 730 #define UAC2_AUDIO_CONTROL_DESCRIPTOR_PTRS(node) \ 731 AC_INTERFACE_DESCRIPTOR_PTR(node) \ 732 AC_INTERFACE_HEADER_DESCRIPTOR_PTR(node) \ 733 ENTITY_HEADERS_PTRS(node) \ 734 IF_ENABLED(DT_PROP(node, interrupt_endpoint), ( \ 735 AC_ENDPOINT_DESCRIPTOR_PTR(node))) 736 737 #define UAC2_DESCRIPTOR_ARRAYS(node) \ 738 UAC2_INTERFACE_ASSOCIATION_DESCRIPTOR_ARRAY(node) \ 739 UAC2_AUDIO_CONTROL_DESCRIPTOR_ARRAYS(node) \ 740 DT_FOREACH_CHILD(node, AS_DESCRIPTORS_ARRAYS_IF_AUDIOSTREAMING) 741 742 #define UAC2_DESCRIPTOR_PTRS(node) \ 743 UAC2_INTERFACE_ASSOCIATION_DESCRIPTOR_PTR(node) \ 744 UAC2_AUDIO_CONTROL_DESCRIPTOR_PTRS(node) \ 745 DT_FOREACH_CHILD(node, AS_DESCRIPTORS_PTRS_IF_AUDIOSTREAMING) \ 746 NULL 747 748 #define UAC2_DESCRIPTORS(node) \ 749 UAC2_INTERFACE_ASSOCIATION_DESCRIPTOR(node) \ 750 UAC2_AUDIO_CONTROL_DESCRIPTORS(node) \ 751 DT_FOREACH_CHILD(node, AS_DESCRIPTORS_IF_AUDIOSTREAMING) 752 753 754 /* Helper macros to determine endpoint offset within complete UAC2 blob */ 755 #define COUNT_AS_DESCRIPTORS_BYTES_UP_TO_IDX(node, idx) \ 756 (sizeof((uint8_t []){AS_DESCRIPTORS_IF_AUDIOSTREAMING(node)}) * \ 757 (DT_NODE_CHILD_IDX(node) <= idx)) 758 759 #define UAC2_DESCRIPTOR_AS_DESC_END_OFFSET(node) \ 760 (sizeof((uint8_t []){ \ 761 UAC2_INTERFACE_ASSOCIATION_DESCRIPTOR(DT_PARENT(node)) \ 762 UAC2_AUDIO_CONTROL_DESCRIPTORS(DT_PARENT(node)) \ 763 })) + DT_FOREACH_CHILD_SEP_VARGS(DT_PARENT(node), \ 764 COUNT_AS_DESCRIPTORS_BYTES_UP_TO_IDX, (+), \ 765 DT_NODE_CHILD_IDX(node)) 766 767 #define AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTORS_SIZE(node) \ 768 (sizeof((uint8_t []) {AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTORS(node)})) 769 770 #define AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR_SIZE(node) \ 771 COND_CODE_1(AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node), \ 772 (sizeof((uint8_t []) { \ 773 AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR(node) \ 774 })), (0)) 775 776 /* Return offset inside UAC2_DESCRIPTORS(DT_PARENT(node)) poiting to data 777 * endpoint address belonging to given AudioStreaming interface node. 778 * 779 * It is programmer error to call this macro with node other than AudioStreaming 780 * or when AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node) is 0. 781 */ 782 #define UAC2_DESCRIPTOR_AS_DATA_EP_OFFSET(node) \ 783 UAC2_DESCRIPTOR_AS_DESC_END_OFFSET(node) \ 784 - AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR_SIZE(node) \ 785 - AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTORS_SIZE(node) \ 786 + offsetof(struct usb_ep_descriptor, bEndpointAddress) 787 788 /* Return offset inside UAC2_DESCRIPTORS(DT_PARENT(node)) poiting to feedback 789 * endpoint address belonging to given AudioStreaming interface node. 790 * 791 * It is programmer error to call this macro with node other than AudioStreaming 792 * or when AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node) is 0. 793 */ 794 #define UAC2_DESCRIPTOR_AS_FEEDBACK_EP_OFFSET(node) \ 795 UAC2_DESCRIPTOR_AS_DESC_END_OFFSET(node) \ 796 - AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR_SIZE(node) \ 797 + offsetof(struct usb_ep_descriptor, bEndpointAddress) 798 799 /* Helper macros to determine endpoint descriptor offset within descriptor set */ 800 #define COUNT_PTRS(...) sizeof((struct usb_desc_header *[]){__VA_ARGS__}) \ 801 / sizeof(struct usb_desc_header *) 802 803 #define COUNT_AS_DESCRIPTORS_UP_TO_IDX(node, idx) \ 804 (COUNT_PTRS(AS_DESCRIPTORS_PTRS_IF_AUDIOSTREAMING(node))) * \ 805 (DT_NODE_CHILD_IDX(node) <= idx) 806 807 #define UAC2_DESCRIPTOR_AS_DESC_END_COUNT(node) \ 808 (COUNT_PTRS( \ 809 UAC2_INTERFACE_ASSOCIATION_DESCRIPTOR_PTR(DT_PARENT(node)) \ 810 UAC2_AUDIO_CONTROL_DESCRIPTOR_PTRS(DT_PARENT(node)) \ 811 )) + DT_FOREACH_CHILD_SEP_VARGS(DT_PARENT(node), \ 812 COUNT_AS_DESCRIPTORS_UP_TO_IDX, (+), \ 813 DT_NODE_CHILD_IDX(node)) 814 815 #define AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTORS_COUNT(node) \ 816 COUNT_PTRS(AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTORS_PTRS(node)) 817 818 #define AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR_COUNT(node) \ 819 COND_CODE_1(AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node), \ 820 (COUNT_PTRS( \ 821 AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR_PTR(node) \ 822 )), (0)) 823 824 /* Return index inside UAC2_DESCRIPTOR_PTRS(DT_PARENT(node)) poiting to data 825 * endpoint descriptor belonging to given AudioStreaming interface node. 826 * 827 * It is programmer error to call this macro with node other than AudioStreaming 828 * or when AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node) is 0. 829 */ 830 #define UAC2_DESCRIPTOR_AS_DATA_EP_INDEX(node) \ 831 UAC2_DESCRIPTOR_AS_DESC_END_COUNT(node) \ 832 - AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR_COUNT(node) \ 833 - AS_ISOCHRONOUS_DATA_ENDPOINT_DESCRIPTORS_COUNT(node) 834 835 /* Return index inside UAC2_DESCRIPTOR_PTRS(DT_PARENT(node)) poiting to feedback 836 * endpoint descriptor belonging to given AudioStreaming interface node. 837 * 838 * It is programmer error to call this macro with node other than AudioStreaming 839 * or when AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node) is 0. 840 */ 841 #define UAC2_DESCRIPTOR_AS_FEEDBACK_EP_INDEX(node) \ 842 UAC2_DESCRIPTOR_AS_DESC_END_COUNT(node) \ 843 - AS_EXPLICIT_FEEDBACK_ENDPOINT_DESCRIPTOR_COUNT(node) 844 845 /* Helper macros to validate USB Audio Class 2 devicetree entries. 846 * Macros above do rely on the assumptions checked below. 847 */ 848 #define VALIDATE_INPUT_TERMINAL_ASSOCIATION(entity) \ 849 UTIL_OR(UTIL_NOT(DT_NODE_HAS_PROP(entity, assoc_terminal)), \ 850 DT_NODE_HAS_COMPAT(DT_PROP(entity, assoc_terminal), \ 851 zephyr_uac2_output_terminal)) 852 853 #define VALIDATE_OUTPUT_TERMINAL_ASSOCIATION(entity) \ 854 UTIL_OR(UTIL_NOT(DT_NODE_HAS_PROP(entity, assoc_terminal)), \ 855 DT_NODE_HAS_COMPAT(DT_PROP(entity, assoc_terminal), \ 856 zephyr_uac2_input_terminal)) 857 858 #define NEEDS_SUBSLOT_SIZE_AND_BIT_RESOLUTION(node) UTIL_OR( \ 859 UTIL_OR(IS_EQ(AUDIO_STREAMING_FORMAT_TYPE(node), FORMAT_TYPE_I), \ 860 IS_EQ(AUDIO_STREAMING_FORMAT_TYPE(node), FORMAT_TYPE_III)), \ 861 UTIL_OR(IS_EQ(AUDIO_STREAMING_FORMAT_TYPE(node), EXT_FORMAT_TYPE_I), \ 862 IS_EQ(AUDIO_STREAMING_FORMAT_TYPE(node), EXT_FORMAT_TYPE_III))) 863 864 #define VALIDATE_SUBSLOT_SIZE(node) \ 865 (DT_PROP(node, subslot_size) >= 1 && DT_PROP(node, subslot_size) <= 4) 866 867 #define VALIDATE_BIT_RESOLUTION(node) \ 868 (DT_PROP(node, bit_resolution) <= (DT_PROP(node, subslot_size) * 8)) 869 870 #define VALIDATE_LINKED_TERMINAL(node) \ 871 UTIL_OR(DT_NODE_HAS_COMPAT(DT_PROP(node, linked_terminal), \ 872 zephyr_uac2_input_terminal), \ 873 DT_NODE_HAS_COMPAT(DT_PROP(node, linked_terminal), \ 874 zephyr_uac2_output_terminal)) 875 876 #define VALIDATE_NODE(node) \ 877 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_clock_source), ( \ 878 BUILD_ASSERT(DT_PROP_LEN(node, sampling_frequencies), \ 879 "Sampling frequencies array must not be empty"); \ 880 BUILD_ASSERT(IS_ARRAY_SORTED(node, sampling_frequencies), \ 881 "Sampling frequencies array must be sorted ascending"); \ 882 )) \ 883 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_input_terminal), ( \ 884 BUILD_ASSERT(!((SPATIAL_LOCATIONS_U32(node) & BIT(31))) || \ 885 SPATIAL_LOCATIONS_U32(node) == BIT(31), \ 886 "Raw Data set alongside other spatial locations"); \ 887 BUILD_ASSERT(VALIDATE_INPUT_TERMINAL_ASSOCIATION(node), \ 888 "Terminals associations must be Input<->Output"); \ 889 )) \ 890 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_output_terminal), ( \ 891 BUILD_ASSERT(VALIDATE_OUTPUT_TERMINAL_ASSOCIATION(node), \ 892 "Terminals associations must be Input<->Output"); \ 893 )) \ 894 IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \ 895 BUILD_ASSERT(VALIDATE_LINKED_TERMINAL(node), \ 896 "Linked Terminal must be Input or Output Terminal"); \ 897 BUILD_ASSERT(!NEEDS_SUBSLOT_SIZE_AND_BIT_RESOLUTION(node) || \ 898 VALIDATE_SUBSLOT_SIZE(node), \ 899 "Subslot Size can only be 1, 2, 3 or 4"); \ 900 BUILD_ASSERT(!NEEDS_SUBSLOT_SIZE_AND_BIT_RESOLUTION(node) || \ 901 VALIDATE_BIT_RESOLUTION(node), \ 902 "Bit Resolution must fit inside Subslot Size"); \ 903 BUILD_ASSERT(!DT_PROP(node, implicit_feedback) || \ 904 !AS_IS_SOF_SYNCHRONIZED(node), \ 905 "Implicit feedback on SOF synchronized clock"); \ 906 )) 907 908 #endif /* ZEPHYR_INCLUDE_USBD_UAC2_MACROS_H_ */ 909