Commit 43b62713 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Add hint string helper functions

Added snd_hda_get_hint() and snd_hda_get_bool_hint() helper functions
to retrieve a hint value.

Internally, the hint is stored in a pair of two strings, key and val.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 6e655bf2
...@@ -30,6 +30,12 @@ ...@@ -30,6 +30,12 @@
#include <sound/hda_hwdep.h> #include <sound/hda_hwdep.h>
#include <sound/minors.h> #include <sound/minors.h>
/* hint string pair */
struct hda_hint {
const char *key;
const char *val; /* contained in the same alloc as key */
};
/* /*
* write/read an out-of-bound verb * write/read an out-of-bound verb
*/ */
...@@ -99,15 +105,15 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) ...@@ -99,15 +105,15 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
static void clear_hwdep_elements(struct hda_codec *codec) static void clear_hwdep_elements(struct hda_codec *codec)
{ {
char **head;
int i; int i;
/* clear init verbs */ /* clear init verbs */
snd_array_free(&codec->init_verbs); snd_array_free(&codec->init_verbs);
/* clear hints */ /* clear hints */
head = codec->hints.list; for (i = 0; i < codec->hints.used; i++) {
for (i = 0; i < codec->hints.used; i++, head++) struct hda_hint *hint = snd_array_elem(&codec->hints, i);
kfree(*head); kfree(hint->key); /* we don't need to free hint->val */
}
snd_array_free(&codec->hints); snd_array_free(&codec->hints);
snd_array_free(&codec->user_pins); snd_array_free(&codec->user_pins);
} }
...@@ -141,7 +147,7 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) ...@@ -141,7 +147,7 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
#endif #endif
snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
snd_array_init(&codec->hints, sizeof(char *), 32); snd_array_init(&codec->hints, sizeof(struct hda_hint), 32);
snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16);
return 0; return 0;
...@@ -306,26 +312,81 @@ static ssize_t init_verbs_store(struct device *dev, ...@@ -306,26 +312,81 @@ static ssize_t init_verbs_store(struct device *dev,
return count; return count;
} }
static struct hda_hint *get_hint(struct hda_codec *codec, const char *key)
{
int i;
for (i = 0; i < codec->hints.used; i++) {
struct hda_hint *hint = snd_array_elem(&codec->hints, i);
if (!strcmp(hint->key, key))
return hint;
}
return NULL;
}
static void remove_trail_spaces(char *str)
{
char *p;
if (!*str)
return;
p = str + strlen(str) - 1;
for (; isspace(*p); p--) {
*p = 0;
if (p == str)
return;
}
}
#define MAX_HINTS 1024
static ssize_t hints_store(struct device *dev, static ssize_t hints_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct snd_hwdep *hwdep = dev_get_drvdata(dev); struct snd_hwdep *hwdep = dev_get_drvdata(dev);
struct hda_codec *codec = hwdep->private_data; struct hda_codec *codec = hwdep->private_data;
char *p; char *key, *val;
char **hint; struct hda_hint *hint;
if (!*buf || isspace(*buf) || *buf == '#' || *buf == '\n') while (isspace(*buf))
buf++;
if (!*buf || *buf == '#' || *buf == '\n')
return count; return count;
p = kstrndup_noeol(buf, 1024); if (*buf == '=')
if (!p) return -EINVAL;
key = kstrndup_noeol(buf, 1024);
if (!key)
return -ENOMEM; return -ENOMEM;
hint = snd_array_new(&codec->hints); /* extract key and val */
val = strchr(key, '=');
if (!val) {
kfree(key);
return -EINVAL;
}
*val++ = 0;
while (isspace(*val))
val++;
remove_trail_spaces(key);
remove_trail_spaces(val);
hint = get_hint(codec, key);
if (hint) {
/* replace */
kfree(hint->key);
hint->key = key;
hint->val = val;
return count;
}
/* allocate a new hint entry */
if (codec->hints.used >= MAX_HINTS)
hint = NULL;
else
hint = snd_array_new(&codec->hints);
if (!hint) { if (!hint) {
kfree(p); kfree(key);
return -ENOMEM; return -ENOMEM;
} }
*hint = p; hint->key = key;
hint->val = val;
return count; return count;
} }
...@@ -428,4 +489,29 @@ int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) ...@@ -428,4 +489,29 @@ int snd_hda_hwdep_add_sysfs(struct hda_codec *codec)
return 0; return 0;
} }
/*
* Look for hint string
*/
const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
{
struct hda_hint *hint = get_hint(codec, key);
return hint ? hint->val : NULL;
}
EXPORT_SYMBOL_HDA(snd_hda_get_hint);
int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
{
const char *p = snd_hda_get_hint(codec, key);
if (!p || !*p)
return -ENOENT;
switch (toupper(*p)) {
case 'T': /* true */
case 'Y': /* yes */
case '1':
return 1;
}
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint);
#endif /* CONFIG_SND_HDA_RECONFIG */ #endif /* CONFIG_SND_HDA_RECONFIG */
...@@ -433,6 +433,23 @@ static inline int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) ...@@ -433,6 +433,23 @@ static inline int snd_hda_hwdep_add_sysfs(struct hda_codec *codec)
} }
#endif #endif
#ifdef CONFIG_SND_HDA_RECONFIG
const char *snd_hda_get_hint(struct hda_codec *codec, const char *key);
int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key);
#else
static inline
const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
{
return NULL;
}
static inline
int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
{
return -ENOENT;
}
#endif
/* /*
* power-management * power-management
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment