Skip to content

control: ucm: add ioctl to retrieve full card components#494

Draft
mstrozek wants to merge 1 commit intoalsa-project:masterfrom
mstrozek:components
Draft

control: ucm: add ioctl to retrieve full card components#494
mstrozek wants to merge 1 commit intoalsa-project:masterfrom
mstrozek:components

Conversation

@mstrozek
Copy link

@mstrozek mstrozek commented Jan 22, 2026

The fixed-size components field in SNDRV_CTL_IOCTL_CARD_INFO can be too small on systems with many audio devices. The kernel [1] will provide a new ioctl to read the full string while truncating the original in card_info if it grows too big. Make sure alsa-lib can read the full string if the original is truncated.

[1] link to v3

mstrozek added a commit to mstrozek/alsa-utils that referenced this pull request Jan 22, 2026
Changes added to kernel [1] and alsa-lib [2] allow usage of an extended
components string, amend amixer to allow display of the new string.

[1] https://lore.kernel.org/all/20260122111249.67319-1-mstrozek@opensource.cirrus.com/
[2] alsa-project/alsa-lib#494
Signed-off-by: Maciej Strozek <mstrozek@opensource.cirrus.com>
@mstrozek mstrozek marked this pull request as ready for review January 22, 2026 11:19
@perexg
Copy link
Member

perexg commented Jan 22, 2026

Thanks for your change, but the situation with new components string can be handled using new internal structure in alsa-lib like:

diff --git a/include/local.h b/include/local.h
index a6996759..97701754 100644
--- a/include/local.h
+++ b/include/local.h
@@ -101,7 +101,19 @@
 #define _snd_pcm_sw_params snd_pcm_sw_params
 #define _snd_pcm_status snd_pcm_status
 
-#define _snd_ctl_card_info snd_ctl_card_info
+/* V2 structure - increased components string from 128 bytes to 512 bytes */
+struct _snd_ctl_card_info {
+       int card;                       /* card number */
+       int pad;                        /* reserved for future (was type) */
+       unsigned char id[16];           /* ID of card (user selectable) */
+       unsigned char driver[16];       /* Driver name */
+       unsigned char name[32];         /* Short name of soundcard */
+       unsigned char longname[80];     /* name + info text about soundcard */
+       unsigned char reserved_[16];    /* reserved for future (was ID of mixer) */
+       unsigned char mixername[80];    /* visual mixer identification */
+       unsigned char components[512];  /* card components / fine identification, delimited with one space (AC97 etc..) */
+};
+
 #define _snd_ctl_elem_id snd_ctl_elem_id
 #define _snd_ctl_elem_list snd_ctl_elem_list
 #define _snd_ctl_elem_info snd_ctl_elem_info
diff --git a/src/control/control_hw.c b/src/control/control_hw.c
index 962cd796..30825a80 100644
--- a/src/control/control_hw.c
+++ b/src/control/control_hw.c
@@ -129,10 +129,14 @@ static int snd_ctl_hw_subscribe_events(snd_ctl_t *handle, int subscribe)
 static int snd_ctl_hw_card_info(snd_ctl_t *handle, snd_ctl_card_info_t *info)
 {
        snd_ctl_hw_t *hw = handle->private_data;
-       if (ioctl(hw->fd, SNDRV_CTL_IOCTL_CARD_INFO, info) < 0) {
+       struct snd_ctl_card_info kinfo;
+       if (ioctl(hw->fd, SNDRV_CTL_IOCTL_CARD_INFO, &kinfo) < 0) {
                snd_errornum(CONTROL, "SNDRV_CTL_IOCTL_CARD_INFO failed");
                return -errno;
        }
+       snd_ctl_card_info_clear(info);
+       ... copy data from kinfo to info here..
+       ... if necessary ('>' postfix in the components string) - call SNDRV_CTL_IOCTL_CARD_COMPONENTS ...
        return 0;
 }

Difference for memory allocations should be already covered using snd_ctl_card_info_sizeof(), snd_ctl_card_info_alloca() and snd_ctl_card_info_malloc() functions.

@mstrozek mstrozek marked this pull request as draft January 29, 2026 10:45
@mstrozek mstrozek force-pushed the components branch 2 times, most recently from d90ae37 to e1352ee Compare February 19, 2026 13:51
return -errno;
}
comp.length = sizeof(comp.components);
if (ioctl(hw->fd, SNDRV_CTL_IOCTL_CARD_COMPONENTS, &comp) < 0) {
Copy link
Member

Choose a reason for hiding this comment

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

I don't follow the second call. If the ioctl structure defined array with 512 bytes, it cannot be beyond sizeof(comp.components). Perhaps, you may just add assert to assure that "sizeof(info.components) == sizeof(comp.components)" and keep the bogus comp.length check.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, it does not make much sense if the size is fixed to 512 bytes... or do you think it might be better to make 'components' a dynamic array? and allocate it to the queried length received in the first call?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I think that Takashi meant to use pointer to the string array in the structure like we do in e.g. struct snd_xferi. Note: The ioctl for 32-bit code must be added to sound/core/control_compat.c (kernel) for this variant.

Copy link
Author

Choose a reason for hiding this comment

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

Done now, hopefully this makes more sense.
Kernel v3 patch with the 32-bit code will come soon

Copy link
Author

Choose a reason for hiding this comment

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

Also now added some better handling in snd_ctl_card_info_free/_clear/_copy()

@mstrozek mstrozek force-pushed the components branch 3 times, most recently from bdbc0d4 to 1ab0036 Compare February 24, 2026 14:02
@mstrozek mstrozek requested a review from perexg February 24, 2026 14:03
include/local.h Outdated
unsigned char longname[80]; /* name + info text about soundcard */
unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */
unsigned char mixername[80]; /* visual mixer identification */
char *components;
Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately, for alsa-lib, the all data must be allocated together ahead. See snd_ctl_card_info_alloca. So, please, return back fixed array to this structure.

Copy link
Author

Choose a reason for hiding this comment

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

Returned to components[512]. In this case also removed the "length query" from the ioctl, writing into info->components directly and only running a quick sanity xheck on the length, though not sure if it is necessary

The fixed-size components field in SNDRV_CTL_IOCTL_CARD_INFO can be too
small on systems with many audio devices. The kernel [1] will provide a
new ioctl to read the full string while truncating the original in
card_info if it grows too big. Make sure alsa-lib can read the full
string if the original is truncated.

[1] link to v3

Signed-off-by: Maciej Strozek <mstrozek@opensource.cirrus.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants