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@linux.intel.com Cc: Mark Brown broonie@kernel.org Signed-off-by: Jaroslav Kysela perex@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);
+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); + +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); + +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); + +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); + +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); + 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 };