Mt 146605: remove 27 uac2 channel limitation#38
Mt 146605: remove 27 uac2 channel limitation#38Overdr0ne wants to merge 2 commits intoMultiTracksDotCom:developfrom
Conversation
UAC2_CHANNEL_MASK (0x07FFFFFF) covers only the 27 named spatial positions in wChannelConfig (UAC2 spec §4.1, bits 0-26). Bits 27-30 are reserved and must be zero; using them to encode a channel count causes host rejection. Remove the hard rejection of masks that exceed UAC2_CHANNEL_MASK. Instead, when any bit outside bits 0-26 is set, emit wChannelConfig=0 in the USB descriptors. Per the spec, wChannelConfig=0 signals non-predefined spatial locations; bNrChannels then carries the actual channel count (derived from the popcount of the full mask as before). Masks within 0x07FFFFFF continue to use the standard spatial bitmap, preserving full backward compatibility.
…ed mode Expand the c_chmask and p_chmask descriptions to explain how the channel mask is interpreted: masks within bits 0-26 (the 27 UAC2-defined spatial positions) are passed directly as wChannelConfig; masks with any bit set outside 0-26 trigger non-predefined spatial location mode (wChannelConfig=0), which supports more than 27 channels with the count given by the popcount of the full mask.
There was a problem hiding this comment.
Pull request overview
This PR updates the USB gadget UAC2 function so devices can advertise more than the 27 predefined UAC2 spatial channels by using the spec-defined “non-predefined spatial locations” mode (channel config set to 0) while still reporting the true channel count.
Changes:
- Removes the validation that rejected channel masks with bits outside the predefined 27 spatial positions.
- Sets UAC2 descriptors’ channel config to
0when the configured channel mask exceeds the predefined spatial channel range, while keepingbNrChannelsderived from the mask popcount. - Documents the updated
c_chmask/p_chmasksemantics in the configfs ABI doc.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| drivers/usb/gadget/function/f_uac2.c | Allows >27 channels by emitting “non-predefined” channel config (bmChannelConfig = 0) when the mask exceeds predefined spatial bits, while keeping channel count from popcount. |
| Documentation/ABI/testing/configfs-usb-gadget-uac2 | Explains how channel masks map to descriptor channel configuration and channel count under the new behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| u32 c_chanconfig = (uac2_opts->c_chmask & ~UAC2_CHANNEL_MASK) ? | ||
| 0 : uac2_opts->c_chmask; | ||
| u32 p_chanconfig = (uac2_opts->p_chmask & ~UAC2_CHANNEL_MASK) ? | ||
| 0 : uac2_opts->p_chmask; | ||
| usb_out_it_desc.bNrChannels = num_channels(uac2_opts->c_chmask); | ||
| usb_out_it_desc.bmChannelConfig = cpu_to_le32(uac2_opts->c_chmask); | ||
| usb_out_it_desc.bmChannelConfig = cpu_to_le32(c_chanconfig); | ||
| io_in_it_desc.bNrChannels = num_channels(uac2_opts->p_chmask); | ||
| io_in_it_desc.bmChannelConfig = cpu_to_le32(uac2_opts->p_chmask); | ||
| io_in_it_desc.bmChannelConfig = cpu_to_le32(p_chanconfig); |
There was a problem hiding this comment.
p_chmask/c_chmask in f_uac2_opts are signed ints (see u_uac2.h). With this change, supporting 32 channels typically means using bit 31 (e.g., 0xffffffff), which turns the stored mask into a negative value and relies on implementation-defined conversions when assigning/parsing/printing. To make >27-channel support robust, consider switching the mask types to u32 (in f_uac2_opts, uac_params, etc.) or at minimum cast to u32 before bit tests/descriptor assignment so the logic doesn't depend on signedness.
| bits 0-26 are used directly as wChannelConfig | ||
| in the USB descriptor. Any bit set outside | ||
| 0-26 triggers non-predefined spatial location | ||
| mode (wChannelConfig=0), which allows more |
There was a problem hiding this comment.
This documentation describes programming "wChannelConfig" for UAC2, but the UAC2 descriptors use the 32-bit bmChannelConfig field name. Please update the terminology to bmChannelConfig so readers don't confuse it with the UAC1 wChannelConfig field.
| bits 0-26 are used directly as wChannelConfig | |
| in the USB descriptor. Any bit set outside | |
| 0-26 triggers non-predefined spatial location | |
| mode (wChannelConfig=0), which allows more | |
| bits 0-26 are used directly as bmChannelConfig | |
| in the USB descriptor. Any bit set outside | |
| 0-26 triggers non-predefined spatial location | |
| mode (bmChannelConfig=0), which allows more |
| * UAC2 spec §4.1: wChannelConfig bits 27-30 are reserved and must be | ||
| * zero. For channel masks that exceed the 27 defined spatial positions | ||
| * (bits 0-26), use wChannelConfig=0 (non-predefined spatial locations) |
There was a problem hiding this comment.
The comment refers to "wChannelConfig", but in UAC2 the field in these descriptors is bmChannelConfig (32-bit). Using the UAC1 name here is misleading and makes it harder to cross-reference the spec/headers; please rename the comment text to bmChannelConfig consistently (and keep the bit-range discussion tied to bmChannelConfig).
| * UAC2 spec §4.1: wChannelConfig bits 27-30 are reserved and must be | |
| * zero. For channel masks that exceed the 27 defined spatial positions | |
| * (bits 0-26), use wChannelConfig=0 (non-predefined spatial locations) | |
| * UAC2 spec §4.1: bmChannelConfig bits 27-30 are reserved and must be | |
| * zero. For channel masks that exceed the 27 defined spatial positions | |
| * (bits 0-26), use bmChannelConfig=0 (non-predefined spatial locations) |
|
@Overdr0ne please address copilot comments |
|
I have confirmed that after changing Connect app mask to 32 channels, I get 32 channels when connecting iPad. I further confirmed good audio quality out the new 28, 29, 30 and 31 channels. Did not regress test all audio channels though. That can be an exercise as we complete further integration. After first code review thumbs up, should be fairly quick to complete devQA. |
MT-146605
By default, uac2 predefines 27 spatial channels, and hosts will reject anything greater than that. However, the uac2 spec specifies that if wChannelConfig=0 is set in the USB descriptors, the host is signaled that we are not using predefined channels. This special case was actually missing from the upstream driver, so I've added support for it here.
With this change, I now see 32 channels showing up in garageband on ios, and when i connect usb1 for example to linux, i can see bNrChannels=32 there, with this hacky grep from lsusb:
And on mt-connect:
That's about all I've done in terms of testing. I'm not sure what all the consequences of this will be. So far I don't think we've been using those predefined spatial channels for anything, though I have seen them show up in
pw-link ls. I imagine it may just mean, on the output side, in iOS or Linux or wherever, we might have to manually map channels where we might otherwise have had them mapped automatically.DevQA: @AmeNote-Michael