[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <3cb73dae8e8ac1a29c856dc5c86064d568003316.camel@opensource.cirrus.com>
Date: Mon, 27 Oct 2025 11:50:32 +0000
From: Maciej Strozek <mstrozek@...nsource.cirrus.com>
To: Takashi Iwai <tiwai@...e.de>, Jaroslav Kysela <perex@...ex.cz>
Cc: alsa-devel@...a-project.org, patches@...nsource.cirrus.com,
linux-sound@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH] ALSA: sound: Increase max size of components field
W dniu pon, 27.10.2025 o godzinie 10∶04 +0100, użytkownik Takashi Iwai
napisał:
> On Thu, 23 Oct 2025 13:56:26 +0200,
> Jaroslav Kysela wrote:
> >
> > Or, we may introduce a separate ioctl for the components string.
> > The
> > stripped components string in struct snd_ctl_card_info may have a
> > special ASCII mark like '>' at the end of string specifying the
> > availability of the complete string through another ioctl. I would
> > prefer this solution.
> >
> > Also, the components string may be dynamic in the kernel structure
> > (pointer) to save some space. 256 bytes is not small number.
>
> As Jaroslav suggested, we need a different solution to keep the
> compatibility.
>
> My gut feeling is for the option to provide a new ioctl as it can be
> most straightforward, but we can discuss further which is the good
> choice.
>
Thank you for the advice! Not sure if I understand Jaroslav's new ioctl
approach properly, can you have a look at the quick draft below and say
if this is (more or less) what you would expect? If it is OK then I
will prepare a proper V2 patch here with a corresponding change for
alsa-lib repo too.
diff --git a/include/sound/core.h b/include/sound/core.h
index 0eb2e3ee0dd5..c4e52fb1704b 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -88,7 +88,9 @@ struct snd_card {
char irq_descr[32]; /* Interrupt description */
char mixername[80]; /* mixer name */
char components[256]; /* card components delimited
with
- space
*/
+ space */
+ char *components_pointer; /* full components string */
+ size_t components_pointer_len; /* length of full components
string */
struct module *module; /* top-level module */
void *private_data; /* private data for soundcard
*/
@@ -297,6 +299,7 @@ int snd_card_info_init(void);
int snd_card_add_dev_attr(struct snd_card *card,
const struct attribute_group *group);
int snd_component_add(struct snd_card *card, const char *component);
+int snd_card_add_components(struct snd_card *card, const char
*component);
int snd_card_file_add(struct snd_card *card, struct file *file);
int snd_card_file_remove(struct snd_card *card, struct file *file);
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index c302698fb685..7d53f6da59e2 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -1069,7 +1069,12 @@ struct snd_ctl_card_info {
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[256]; /* card components / fine
identification, delimited with one space (AC97 etc..) */
+ unsigned char components[128]; /* card components / fine
identification, delimited with one space (AC97 etc..) */
+};
+
+struct snd_ctl_card_components {
+ int len;
+ unsigned char *components;
};
typedef int __bitwise snd_ctl_elem_type_t;
@@ -1198,6 +1203,7 @@ struct snd_ctl_tlv {
#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct
snd_ctl_card_info)
+#define SNDRV_CTL_IOCTL_CARD_COMPONENTS _IOWR('U', 0x02, struct
snd_ctl_card_components)
#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct
snd_ctl_elem_list)
#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct
snd_ctl_elem_info)
#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct
snd_ctl_elem_value)
diff --git a/sound/core/control.c b/sound/core/control.c
index 9c3fd5113a61..5a96a2ed4a45 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -886,6 +886,23 @@ static int snd_ctl_card_info(struct snd_card
*card, struct snd_ctl_file * ctl,
return 0;
}
+static int snd_ctl_card_components(struct snd_card *card, void __user
*arg)
+{
+ struct snd_ctl_card_components *info __free(kfree) = NULL;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ scoped_guard(rwsem_read, &snd_ioctl_rwsem) {
+ strscpy(info->components, card->components, info->len);
+ }
+
+ if (copy_to_user(arg, info, sizeof(struct
snd_ctl_card_components)))
+ return -EFAULT;
+ return 0;
+}
+
static int snd_ctl_elem_list(struct snd_card *card,
struct snd_ctl_elem_list *list)
{
@@ -1914,6 +1931,8 @@ static long snd_ctl_ioctl(struct file *file,
unsigned int cmd, unsigned long arg
return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0;
case SNDRV_CTL_IOCTL_CARD_INFO:
return snd_ctl_card_info(card, ctl, cmd, argp);
+ case SNDRV_CTL_IOCTL_CARD_COMPONENTS:
+ return snd_ctl_card_components(card, argp);
case SNDRV_CTL_IOCTL_ELEM_LIST:
return snd_ctl_elem_list_user(card, argp);
case SNDRV_CTL_IOCTL_ELEM_INFO:
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 6459809ed364..edb7b28d8177 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -416,7 +416,7 @@ static int snd_ctl_elem_add_compat(struct
snd_ctl_file *file,
break;
}
return snd_ctl_elem_add(file, data, replace);
-}
+}
enum {
SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct
snd_ctl_elem_list32),
@@ -445,6 +445,7 @@ static inline long snd_ctl_ioctl_compat(struct file
*file, unsigned int cmd, uns
switch (cmd) {
case SNDRV_CTL_IOCTL_PVERSION:
case SNDRV_CTL_IOCTL_CARD_INFO:
+ case SNDRV_CTL_IOCTL_CARD_COMPONENTS:
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
case SNDRV_CTL_IOCTL_POWER:
case SNDRV_CTL_IOCTL_POWER_STATE:
diff --git a/sound/core/init.c b/sound/core/init.c
index c372b3228785..a7ac62ace1dc 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -587,6 +587,9 @@ static int snd_card_do_free(struct snd_card *card)
snd_device_free_all(card);
if (card->private_free)
card->private_free(card);
+ kfree(card->components_pointer);
+ card->components_pointer = NULL;
+ card->components_pointer_len = 0;
if (snd_info_card_free(card) < 0) {
dev_warn(card->dev, "unable to free card info\n");
/* Not fatal error */
@@ -714,7 +717,7 @@ static void snd_card_set_id_no_lock(struct snd_card
*card, const char *src,
int len, loops;
bool is_default = false;
char *id;
-
+
copy_valid_id_string(card, src, nid);
id = card->id;
@@ -1023,11 +1026,13 @@ int __init snd_card_info_init(void)
*
* Return: Zero otherwise a negative error code.
*/
-
+
int snd_component_add(struct snd_card *card, const char *component)
{
char *ptr;
int len = strlen(component);
+ int new_len;
+ char *buffer;
ptr = strstr(card->components, component);
if (ptr != NULL) {
@@ -1035,8 +1040,28 @@ int snd_component_add(struct snd_card *card,
const char *component)
return 1;
}
if (strlen(card->components) + 1 + len + 1 > sizeof(card-
>components)) {
- snd_BUG();
- return -ENOMEM;
+ if (card->components[sizeof(card->components) - 2] !=
'>') {
+ // TODO: figure out if it is not deleting a
character from an existing component
+ card->components[sizeof(card->components) - 2]
= '>';
+ card->components[sizeof(card->components) - 1]
= '\0';
+ }
+
+ if (card->components_pointer) {
+ new_len = strlen(card->components_pointer) + 1
+ len;
+ buffer = krealloc(card->components_pointer,
new_len, GFP_KERNEL);
+ } else {
+ new_len = strlen(card->components) + 1 + len;
+ buffer = kmalloc(new_len, GFP_KERNEL);
+ memcpy(buffer, card->components, strlen(card-
>components));
+ }
+ if (!buffer)
+ return -ENOMEM;
+
+ strcat(buffer, component);
+
+ card->components_pointer = buffer;
+ card->components_pointer_len = new_len;
+
}
if (card->components[0] != '\0')
strcat(card->components, " ");
--
Regards,
Maciej
Powered by blists - more mailing lists