[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