[PATCH] ALSA: core - add more card sysfs entries
Takashi Sakamoto
o-takashi at sakamocchi.jp
Thu Apr 8 12:38:19 CEST 2021
On Thu, Apr 08, 2021 at 11:43:14AM +0200, Jaroslav Kysela wrote:
> There are several strings which are describing the card. As time goes,
> we have new universal drivers which probe components in a way, which
> is disassociated from the card structure (ASoC). Also, some drivers
> may require to select another firmware depending on the specific
> platform using udev. The new firmware may change the sound card behaviour.
>
> This patch allows flexible modifications of the card description
> from the user space to handle the specific boot / plug-in settings.
>
> Cc: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>
> Cc: Mark Brown <broonie at kernel.org>
> Signed-off-by: Jaroslav Kysela <perex at perex.cz>
> ---
> sound/core/init.c | 166 +++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 155 insertions(+), 11 deletions(-)
>
> diff --git a/sound/core/init.c b/sound/core/init.c
> index ef41f5b3a240..01b26912a4d0 100644
> --- a/sound/core/init.c
> +++ b/sound/core/init.c
> @@ -662,6 +662,33 @@ void snd_card_set_id(struct snd_card *card, const char *nid)
> }
> EXPORT_SYMBOL(snd_card_set_id);
>
> +#define EXTRA_ID_CHARS "_-"
> +#define EXTRA_NAME_CHARS " _-.:"
> +
> +static bool safe_attr_strcpy(char *dst, size_t dst_count,
> + const char *src, size_t src_count,
> + const char *extra_characters)
> +{
> + size_t idx, copy;
> + int c;
> +
> + copy = src_count >= dst_count ? dst_count - 1 : src_count;
> + for (idx = 0; idx < copy; idx++) {
> + c = src[idx];
> + if (c < ' ') {
> + copy = idx;
> + break;
> + }
> + if (!isalnum(c) && !strchr(extra_characters, c))
> + return false;
> + }
> + if (copy < 3)
> + return false;
> + memcpy(dst, src, copy);
> + dst[copy] = '\0';
> + return true;
> +}
> +
> static ssize_t
> card_id_show_attr(struct device *dev,
> struct device_attribute *attr, char *buf)
> @@ -676,18 +703,10 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
> {
> struct snd_card *card = container_of(dev, struct snd_card, card_dev);
> char buf1[sizeof(card->id)];
> - size_t copy = count > sizeof(card->id) - 1 ?
> - sizeof(card->id) - 1 : count;
> - size_t idx;
> - int c;
>
> - for (idx = 0; idx < copy; idx++) {
> - c = buf[idx];
> - if (!isalnum(c) && c != '_' && c != '-')
> - return -EINVAL;
> - }
> - memcpy(buf1, buf, copy);
> - buf1[copy] = '\0';
> + if (!safe_attr_strcpy(buf1, sizeof(buf1), buf, count, EXTRA_ID_CHARS))
> + return -EINVAL;
> +
> mutex_lock(&snd_card_mutex);
> if (!card_id_ok(NULL, buf1)) {
> mutex_unlock(&snd_card_mutex);
> @@ -712,9 +731,134 @@ card_number_show_attr(struct device *dev,
>
> static DEVICE_ATTR(number, 0444, card_number_show_attr, NULL);
Use DEVICE_ATTR_RO() instead.
> +static ssize_t
> +card_driver_show_attr(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> + struct snd_card *card = container_of(dev, struct snd_card, card_dev);
> + return scnprintf(buf, PAGE_SIZE, "%s\n", card->driver);
> +}
> +
> +static ssize_t
> +card_driver_store_attr(struct device *dev, struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct snd_card *card = container_of(dev, struct snd_card, card_dev);
> + char driver1[sizeof(card->driver)];
> +
> + if (!safe_attr_strcpy(driver1, sizeof(driver1), buf, count, EXTRA_NAME_CHARS))
> + return -EINVAL;
> + mutex_lock(&snd_card_mutex);
> + strcpy(card->driver, driver1);
> + mutex_unlock(&snd_card_mutex);
> + return count;
> +}
> +
> +static DEVICE_ATTR(driver, 0644, card_driver_show_attr, card_driver_store_attr);
Use DEVICE_ATTR_RW() instead.
> +static ssize_t
> +card_name_show_attr(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> + struct snd_card *card = container_of(dev, struct snd_card, card_dev);
> + return scnprintf(buf, PAGE_SIZE, "%s\n", card->shortname);
> +}
> +
> +static ssize_t
> +card_name_store_attr(struct device *dev, struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct snd_card *card = container_of(dev, struct snd_card, card_dev);
> + char name1[sizeof(card->shortname)];
> +
> + if (!safe_attr_strcpy(name1, sizeof(name1), buf, count, EXTRA_NAME_CHARS))
> + return -EINVAL;
> + mutex_lock(&snd_card_mutex);
> + strcpy(card->shortname, name1);
> + mutex_unlock(&snd_card_mutex);
> + return count;
> +}
> +
> +static DEVICE_ATTR(name, 0644, card_name_show_attr, card_name_store_attr);
Use DEVICE_ATTR_RW() instead.
> +static ssize_t
> +card_longname_show_attr(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> + struct snd_card *card = container_of(dev, struct snd_card, card_dev);
> + return scnprintf(buf, PAGE_SIZE, "%s\n", card->longname);
> +}
> +
> +static ssize_t
> +card_longname_store_attr(struct device *dev, struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct snd_card *card = container_of(dev, struct snd_card, card_dev);
> + char longname1[sizeof(card->longname)];
> +
> + if (!safe_attr_strcpy(longname1, sizeof(longname1), buf, count, EXTRA_NAME_CHARS))
> + return -EINVAL;
> + mutex_lock(&snd_card_mutex);
> + strcpy(card->longname, longname1);
> + mutex_unlock(&snd_card_mutex);
> + return count;
> +}
> +
> +static DEVICE_ATTR(longname, 0644, card_longname_show_attr, card_longname_store_attr);
Use DEVICE_ATTR_RW() instead.
> +static ssize_t
> +card_mixername_show_attr(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> + struct snd_card *card = container_of(dev, struct snd_card, card_dev);
> + return scnprintf(buf, PAGE_SIZE, "%s\n", card->mixername);
> +}
> +
> +static ssize_t
> +card_mixername_store_attr(struct device *dev, struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct snd_card *card = container_of(dev, struct snd_card, card_dev);
> + char mixername1[sizeof(card->mixername)];
> +
> + if (!safe_attr_strcpy(mixername1, sizeof(mixername1), buf, count, EXTRA_NAME_CHARS))
> + return -EINVAL;
> + mutex_lock(&snd_card_mutex);
> + strcpy(card->mixername, mixername1);
> + mutex_unlock(&snd_card_mutex);
> + return count;
> +}
> +
> +static DEVICE_ATTR(mixername, 0644, card_mixername_show_attr, card_mixername_store_attr);
Use DEVICE_ATTR_RW() instead.
> +static ssize_t
> +card_components_show_attr(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> + struct snd_card *card = container_of(dev, struct snd_card, card_dev);
> + return scnprintf(buf, PAGE_SIZE, "%s\n", card->components);
> +}
> +
> +static ssize_t
> +card_components_store_attr(struct device *dev, struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct snd_card *card = container_of(dev, struct snd_card, card_dev);
> + char components1[sizeof(card->components)];
> +
> + if (!safe_attr_strcpy(components1, sizeof(components1), buf, count, EXTRA_NAME_CHARS))
> + return -EINVAL;
> + mutex_lock(&snd_card_mutex);
> + strcpy(card->components, components1);
> + mutex_unlock(&snd_card_mutex);
> + return count;
> +}
> +
> +static DEVICE_ATTR(components, 0644, card_components_show_attr, card_components_store_attr);
Use DEVICE_ATTR_RW() instead.
> static struct attribute *card_dev_attrs[] = {
> &dev_attr_id.attr,
> &dev_attr_number.attr,
> + &dev_attr_driver.attr,
> + &dev_attr_name.attr,
> + &dev_attr_longname.attr,
> + &dev_attr_mixername.attr,
> + &dev_attr_components.attr,
> NULL
> };
>
> --
> 2.30.2
It should be done to emit snd_ctl_event when changing card parameters.
Silent change is the worst since many userspace applications can refer
to them in advance.
Regards
Takashi Sakamoto
More information about the Alsa-devel
mailing list