diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-03-02 08:25:17 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-03-02 11:28:54 -0500 |
commit | 43b62713f67d9f0655f3a61f5bd14d6297ddd3ce (patch) | |
tree | fd05fb617e177808c164371f4c596f6d7a087026 /sound/pci/hda/hda_hwdep.c | |
parent | 6e655bf21697d2594243098a14e0699e8d4a4059 (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.c | 112 |
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 */ | ||
34 | struct 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 | ||
100 | static void clear_hwdep_elements(struct hda_codec *codec) | 106 | static 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 | ||
315 | static 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 | |||
327 | static 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 | |||
309 | static ssize_t hints_store(struct device *dev, | 342 | static 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 | */ | ||
495 | const 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 | } | ||
500 | EXPORT_SYMBOL_HDA(snd_hda_get_hint); | ||
501 | |||
502 | int 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 | } | ||
515 | EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint); | ||
516 | |||
431 | #endif /* CONFIG_SND_HDA_RECONFIG */ | 517 | #endif /* CONFIG_SND_HDA_RECONFIG */ |