Skip to content

dt-bindings: usb: initial USB Audio Class 2 support #65972

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

Merged
merged 4 commits into from
Dec 15, 2023

Conversation

tmon-nordic
Copy link
Contributor

USB Audio Class 2 (UAC2) includes a method to describe audio device topology to host using a set of class specific descriptors. The audio device description includes complete sample clock topology and audio processing organization.

Zephyr specific bindings are supposed to allow user to create reasonably simple audio device description using devicetree syntax. The bindings currently include only the absolute minimum set required for headset example. Bindings for other entities (Clock Selector, Clock Multiplier, Mixer Unit, Selector Unit, Feature Unit, Sample Rate Converter, variuos Effect Units, various Processing Units, Extension Unit) can be added later together with the actual USB class implementation.

The main idea is that user does create one zephyr,uac2 compatible node for every USB Audio 2 class instance. Note that in majority of cases just one USB Audio 2 class is necessary because the number of streaming interfaces is virtually unlimited (USB Audio 2 class can have up to 255 entities). The zephyr,uac2 node includes child nodes with compatibles set to desired entity or audiostreaming interface. The parent-child relationship is necessary to allow grouping entities to correct audio class instance.

Initial set of macros to generate class specific descriptors based on devicetree nodes. Descriptors are generated as uint8_t array initializer list because there is variable number of entities in between standard USB interface and endpoint descriptors. Because the descriptors are automatically generated there is no real point in trying to generate corresponding C structures (especially that some entity descriptors have variably sized fields in the middle of descriptor, e.g. Clock Selector).

Compare devicetree generated class specific descriptors for headset example against reference hex values.


The PR is opened to allow early review/feedback on the in-progress USB Audio 2 class implementation for next device stack. Included is a simple headset example and corresponding testcase for generated descriptors. While at this point I do not foresee any need for changing the bindings, the PR is opened with DNM label to allow me to revise the bindings in case I discover some major flaw during actual class implementation.

@tmon-nordic tmon-nordic added the DNM This PR should not be merged (Do Not Merge) label Nov 30, 2023
@zephyrbot zephyrbot added area: Devicetree Binding PR modifies or adds a Device Tree binding area: USB Universal Serial Bus labels Nov 30, 2023
@tmon-nordic tmon-nordic requested a review from koffes November 30, 2023 12:46
@koffes koffes requested review from rick1082 and alexsven December 4, 2023 10:42
@tmon-nordic tmon-nordic force-pushed the devicetree-uac2 branch 2 times, most recently from dcdee06 to 2072edb Compare December 4, 2023 12:34
@tmon-nordic tmon-nordic removed the DNM This PR should not be merged (Do Not Merge) label Dec 5, 2023
@tmon-nordic
Copy link
Contributor Author

Removed DNM label because I managed to generate complete descriptors set and determine offsets for isochronous endpoint addresses (necessary due to the runtime endpoint "fixup"). While actual class implementation will require some more macros, all the heavy macrobatics should be done (at least for the initial "simple" headset support).

Copy link
Member

@gmarull gmarull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_USB_AUDIO_H
#define ZEPHYR_INCLUDE_DT_BINDINGS_USB_AUDIO_H

/* USB Device Class Definition for Audio Devices Release 2.0 May 31, 2006
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I'd suggest adding proper Doxygen docstrings here, and make all these values appear in a USB audio subgroup.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to use the descriptions from actual specification, but USB Device Class Definition for Terminal Types licensing has

...
A LICENSE IS HEREBY GRANTED TO REPRODUCE THIS SPECIFICATION FOR INTERNAL
USE ONLY. NO OTHER LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE,
IS GRANTED OR INTENDED HEREBY.
...

Therefore I believe I cannot just copy the descriptions to doxygen tags. What would be the approach then?

- "decoded-pcm-samples"

subslot-size:
type: int
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enum: [1, 2, 3, 4]?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's necessary. There is a build-time assert validating parameters and it does fail the build with correct error message if the value is outside range.

Comment on lines +51 to +57
#define AUDIO 0x01

/* A.5 Audio Interface Subclass Codes */
#define INTERFACE_SUBCLASS_UNDEFINED 0x00
#define AUDIOCONTROL 0x01
#define AUDIOSTREAMING 0x02
#define MIDISTREAMING 0x03
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note, we also have them in include/zephyr/usb/class/usb_audio.h.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old usb public usb audio header is not useful at all for the new implementation. The two versions of the spec differ too much. The USB Audio 2 implementation is targeted towards the device-next stack and will use new application API.

Moreover, AUDIOCONTROL, AUDIOSTREAMING, MIDISTREAMING are really implementation details that should not be part of public API at all. I prefer to just leave the include/zephyr/usb/class/usb_audio.h intact as it'll be removed anyway after we deprecate and then remove the old USB stack.

USB Audio Class 2 (UAC2) includes a method to describe audio device
topology to host using a set of class specific descriptors. The audio
device description includes complete sample clock topology and audio
processing organization.

Zephyr specific bindings are supposed to allow user to create reasonably
simple audio device description using devicetree syntax. The bindings
currently include only the absolute minimum set required for headset
example. Bindings for other entities (Clock Selector, Clock Multiplier,
Mixer Unit, Selector Unit, Feature Unit, Sample Rate Converter,
variuos Effect Units, various Processing Units, Extension Unit) can be
added later together with the actual USB class implementation.

The main idea is that user does create one zephyr,uac2 compatible node
for every USB Audio 2 class instance. Note that in majority of cases
just one USB Audio 2 class is necessary because the number of streaming
interfaces is virtually unlimited (USB Audio 2 class can have up to 255
entities). The zephyr,uac2 node includes child nodes with compatibles
set to desired entity or audiostreaming interface. The parent-child
relationship is necessary to allow grouping entities to correct audio
class instance.

Signed-off-by: Tomasz Moń <[email protected]>
Initial set of macros to generate class specific descriptors based on
devicetree nodes. Descriptors are generated as uint8_t array initializer
list because there is variable number of entities in between standard
USB interface and endpoint descriptors. Because the descriptors are
automatically generated there is no real point in trying to generate
corresponding C structures (especially that some entity descriptors have
variably sized fields in the middle of descriptor, e.g. Clock Selector).

Signed-off-by: Tomasz Moń <[email protected]>
Compare devicetree generated class specific descriptors for headset
example against reference hex values.

Signed-off-by: Tomasz Moń <[email protected]>
Add macros to initialize full set of descriptors required for USB Audio
Class 2 instance. Descriptors start with Interface Association
Descriptor that binds together the AudioControl interface and all
AudioStreaming interfaces.

AudioStreaming interfaces have alternate setting 0 without any endpoints
and alternate setting 1 with isochronous endpoint with max packet size
calculated on maximum sample frequency, number of channels, subslot size
and clock synchronization (asynchronous endpoints require +1 sample).

Signed-off-by: Tomasz Moń <[email protected]>
@carlescufi carlescufi merged commit 3e73688 into zephyrproject-rtos:main Dec 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Devicetree Binding PR modifies or adds a Device Tree binding area: USB Universal Serial Bus
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants