aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_hwdep.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-03-02 08:25:17 -0500
committerTakashi Iwai <tiwai@suse.de>2009-03-02 11:28:54 -0500
commit43b62713f67d9f0655f3a61f5bd14d6297ddd3ce (patch)
treefd05fb617e177808c164371f4c596f6d7a087026 /sound/pci/hda/hda_hwdep.c
parent6e655bf21697d2594243098a14e0699e8d4a4059 (diff)
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: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_hwdep.c')
-rw-r--r--sound/pci/hda/hda_hwdep.c112
1 files changed, 99 insertions, 13 deletions
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index 4af484b8240c..5e554de9cd9b 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -30,6 +30,12 @@
30#include <sound/hda_hwdep.h> 30#include <sound/hda_hwdep.h>
31#include <sound/minors.h> 31#include <sound/minors.h>
32 32
33/* hint string pair */
34struct hda_hint {
35 const char *key;
36 const char *val; /* contained in the same alloc as key */
37};
38
33/* 39/*
34 * write/read an out-of-bound verb 40 * write/read an out-of-bound verb
35 */ 41 */
@@ -99,15 +105,15 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
99 105
100static void clear_hwdep_elements(struct hda_codec *codec) 106static void clear_hwdep_elements(struct hda_codec *codec)
101{ 107{
102 char **head;
103 int i; 108 int i;
104 109
105 /* clear init verbs */ 110 /* clear init verbs */
106 snd_array_free(&codec->init_verbs); 111 snd_array_free(&codec->init_verbs);
107 /* clear hints */ 112 /* clear hints */
108 head = codec->hints.list; 113 for (i = 0; i < codec->hints.used; i++) {
109 for (i = 0; i < codec->hints.used; i++, head++) 114 struct hda_hint *hint = snd_array_elem(&codec->hints, i);
110 kfree(*head); 115 kfree(hint->key); /* we don't need to free hint->val */
116 }
111 snd_array_free(&codec->hints); 117 snd_array_free(&codec->hints);
112 snd_array_free(&codec->user_pins); 118 snd_array_free(&codec->user_pins);
113} 119}
@@ -141,7 +147,7 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
141#endif 147#endif
142 148
143 snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); 149 snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
144 snd_array_init(&codec->hints, sizeof(char *), 32); 150 snd_array_init(&codec->hints, sizeof(struct hda_hint), 32);
145 snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); 151 snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16);
146 152
147 return 0; 153 return 0;
@@ -306,26 +312,81 @@ static ssize_t init_verbs_store(struct device *dev,
306 return count; 312 return count;
307} 313}
308 314
315static struct hda_hint *get_hint(struct hda_codec *codec, const char *key)
316{
317 int i;
318
319 for (i = 0; i < codec->hints.used; i++) {
320 struct hda_hint *hint = snd_array_elem(&codec->hints, i);
321 if (!strcmp(hint->key, key))
322 return hint;
323 }
324 return NULL;
325}
326
327static void remove_trail_spaces(char *str)
328{
329 char *p;
330 if (!*str)
331 return;
332 p = str + strlen(str) - 1;
333 for (; isspace(*p); p--) {
334 *p = 0;
335 if (p == str)
336 return;
337 }
338}
339
340#define MAX_HINTS 1024
341
309static ssize_t hints_store(struct device *dev, 342static ssize_t hints_store(struct device *dev,
310 struct device_attribute *attr, 343 struct device_attribute *attr,
311 const char *buf, size_t count) 344 const char *buf, size_t count)
312{ 345{
313 struct snd_hwdep *hwdep = dev_get_drvdata(dev); 346 struct snd_hwdep *hwdep = dev_get_drvdata(dev);
314 struct hda_codec *codec = hwdep->private_data; 347 struct hda_codec *codec = hwdep->private_data;
315 char *p; 348 char *key, *val;
316 char **hint; 349 struct hda_hint *hint;
317 350
318 if (!*buf || isspace(*buf) || *buf == '#' || *buf == '\n') 351 while (isspace(*buf))
352 buf++;
353 if (!*buf || *buf == '#' || *buf == '\n')
319 return count; 354 return count;
320 p = kstrndup_noeol(buf, 1024); 355 if (*buf == '=')
321 if (!p) 356 return -EINVAL;
357 key = kstrndup_noeol(buf, 1024);
358 if (!key)
322 return -ENOMEM; 359 return -ENOMEM;
323 hint = snd_array_new(&codec->hints); 360 /* extract key and val */
361 val = strchr(key, '=');
362 if (!val) {
363 kfree(key);
364 return -EINVAL;
365 }
366 *val++ = 0;
367 while (isspace(*val))
368 val++;
369 remove_trail_spaces(key);
370 remove_trail_spaces(val);
371 hint = get_hint(codec, key);
372 if (hint) {
373 /* replace */
374 kfree(hint->key);
375 hint->key = key;
376 hint->val = val;
377 return count;
378 }
379 /* allocate a new hint entry */
380 if (codec->hints.used >= MAX_HINTS)
381 hint = NULL;
382 else
383 hint = snd_array_new(&codec->hints);
324 if (!hint) { 384 if (!hint) {
325 kfree(p); 385 kfree(key);
326 return -ENOMEM; 386 return -ENOMEM;
327 } 387 }
328 *hint = p; 388 hint->key = key;
389 hint->val = val;
329 return count; 390 return count;
330} 391}
331 392
@@ -428,4 +489,29 @@ int snd_hda_hwdep_add_sysfs(struct hda_codec *codec)
428 return 0; 489 return 0;
429} 490}
430 491
492/*
493 * Look for hint string
494 */
495const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
496{
497 struct hda_hint *hint = get_hint(codec, key);
498 return hint ? hint->val : NULL;
499}
500EXPORT_SYMBOL_HDA(snd_hda_get_hint);
501
502int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
503{
504 const char *p = snd_hda_get_hint(codec, key);
505 if (!p || !*p)
506 return -ENOENT;
507 switch (toupper(*p)) {
508 case 'T': /* true */
509 case 'Y': /* yes */
510 case '1':
511 return 1;
512 }
513 return 0;
514}
515EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint);
516
431#endif /* CONFIG_SND_HDA_RECONFIG */ 517#endif /* CONFIG_SND_HDA_RECONFIG */