Skip to content

Mt 146605: remove 27 uac2 channel limitation#38

Open
Overdr0ne wants to merge 2 commits intoMultiTracksDotCom:developfrom
Overdr0ne:MT-146605
Open

Mt 146605: remove 27 uac2 channel limitation#38
Overdr0ne wants to merge 2 commits intoMultiTracksDotCom:developfrom
Overdr0ne:MT-146605

Conversation

@Overdr0ne
Copy link
Copy Markdown

@Overdr0ne Overdr0ne commented Apr 13, 2026

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:

lsusb -v -d 3832:0240 2>/dev/null|grep 32
Bus 001 Device 021: ID 3832:0240 http://MultiTracks.com , LLC MT Connect 1
  idVendor           0x3832 http://MultiTracks.com , LLC
      bFunctionProtocol      32
      bInterfaceProtocol     32
        bNrChannels            32
        bmaControls(32)    0x00000000
        bNrChannels            32
        bmaControls(32)    0x00000000
      bInterfaceProtocol     32
      bInterfaceProtocol     32
        bNrChannels            32
      bInterfaceProtocol     32
      bInterfaceProtocol     32
        bNrChannels            32

And on mt-connect:

printf "0x%x\n" $(cat /sys/kernel/config/usb_gadget/mtc0/functions/uac2.usb0/c_chmask)
0xffffffff

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

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.
Copilot AI review requested due to automatic review settings April 13, 2026 21:58
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 0 when the configured channel mask exceeds the predefined spatial channel range, while keeping bNrChannels derived from the mask popcount.
  • Documents the updated c_chmask / p_chmask semantics 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.

Comment on lines +1096 to +1103
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);
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +14
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
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
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

Copilot uses AI. Check for mistakes.
Comment on lines +1090 to +1092
* 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)
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

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

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).

Suggested change
* 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)

Copilot uses AI. Check for mistakes.
@vlaarco
Copy link
Copy Markdown
Collaborator

vlaarco commented Apr 14, 2026

@Overdr0ne please address copilot comments

@AmeNote-Michael
Copy link
Copy Markdown

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants