aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2007-11-15 09:54:38 -0500
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:29:24 -0500
commit68ea7b2f2d8c1effd662fded04e9a589cb640da6 (patch)
treee104282748345692c2a71572a260bf926501ebde
parent7e39e2273a9b8182ed1b21af5444e29843fc06ca (diff)
[ALSA] hda-codec - Check value range in ctl callbacks
Check the value ranges in ctl put callbacks properly so that invalid values won't be stored or written to registers. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r--sound/pci/hda/hda_codec.c3
-rw-r--r--sound/pci/hda/patch_analog.c6
-rw-r--r--sound/pci/hda/patch_conexant.c2
-rw-r--r--sound/pci/hda/patch_sigmatel.c50
4 files changed, 52 insertions, 9 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 39240e0ea568..23d3befef57b 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2337,7 +2337,8 @@ int snd_hda_ch_mode_put(struct hda_codec *codec,
2337 unsigned int mode; 2337 unsigned int mode;
2338 2338
2339 mode = ucontrol->value.enumerated.item[0]; 2339 mode = ucontrol->value.enumerated.item[0];
2340 snd_assert(mode < num_chmodes, return -EINVAL); 2340 if (mode >= num_chmodes)
2341 return -EINVAL;
2341 if (*max_channelsp == chmode[mode].channels) 2342 if (*max_channelsp == chmode[mode].channels)
2342 return 0; 2343 return 0;
2343 /* change the current channel setting */ 2344 /* change the current channel setting */
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index cfe064a75ca6..b2c53809603e 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -370,7 +370,7 @@ static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
370 int invert = (kcontrol->private_value >> 8) & 1; 370 int invert = (kcontrol->private_value >> 8) & 1;
371 hda_nid_t nid = kcontrol->private_value & 0xff; 371 hda_nid_t nid = kcontrol->private_value & 0xff;
372 unsigned int eapd; 372 unsigned int eapd;
373 eapd = ucontrol->value.integer.value[0]; 373 eapd = !!ucontrol->value.integer.value[0];
374 if (invert) 374 if (invert)
375 eapd = !eapd; 375 eapd = !eapd;
376 if (eapd == spec->cur_eapd) 376 if (eapd == spec->cur_eapd)
@@ -1021,6 +1021,8 @@ static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
1021 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1021 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1022 struct ad198x_spec *spec = codec->spec; 1022 struct ad198x_spec *spec = codec->spec;
1023 1023
1024 if (ucontrol->value.enumerated.item[0] > 1)
1025 return -EINVAL;
1024 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { 1026 if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
1025 spec->spdif_route = ucontrol->value.enumerated.item[0]; 1027 spec->spdif_route = ucontrol->value.enumerated.item[0];
1026 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0, 1028 snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0,
@@ -1966,6 +1968,8 @@ static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
1966 int change; 1968 int change;
1967 1969
1968 val = ucontrol->value.enumerated.item[0]; 1970 val = ucontrol->value.enumerated.item[0];
1971 if (val > 3)
1972 return -EINVAL;
1969 if (!val) { 1973 if (!val) {
1970 sel = snd_hda_codec_read(codec, 0x1d, 0, 1974 sel = snd_hda_codec_read(codec, 0x1d, 0,
1971 AC_VERB_GET_AMP_GAIN_MUTE, 1975 AC_VERB_GET_AMP_GAIN_MUTE,
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index beda2978147d..68f23b823e25 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -373,7 +373,7 @@ static int cxt_eapd_put(struct snd_kcontrol *kcontrol,
373 hda_nid_t nid = kcontrol->private_value & 0xff; 373 hda_nid_t nid = kcontrol->private_value & 0xff;
374 unsigned int eapd; 374 unsigned int eapd;
375 375
376 eapd = ucontrol->value.integer.value[0]; 376 eapd = !!ucontrol->value.integer.value[0];
377 if (invert) 377 if (invert)
378 eapd = !eapd; 378 eapd = !eapd;
379 if (eapd == spec->cur_eapd) 379 if (eapd == spec->cur_eapd)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index c4447b160a5a..0817f42a7c86 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -349,12 +349,13 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol,
349 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 349 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
350 struct sigmatel_spec *spec = codec->spec; 350 struct sigmatel_spec *spec = codec->spec;
351 unsigned int dac_mode; 351 unsigned int dac_mode;
352 unsigned int val;
352 353
353 if (spec->aloopback == ucontrol->value.integer.value[0]) 354 val = !!ucontrol->value.integer.value[0];
355 if (spec->aloopback == val)
354 return 0; 356 return 0;
355 357
356 spec->aloopback = ucontrol->value.integer.value[0]; 358 spec->aloopback = val;
357
358 359
359 dac_mode = snd_hda_codec_read(codec, codec->afg, 0, 360 dac_mode = snd_hda_codec_read(codec, codec->afg, 0,
360 kcontrol->private_value & 0xFFFF, 0x0); 361 kcontrol->private_value & 0xFFFF, 0x0);
@@ -373,6 +374,42 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol,
373 return 1; 374 return 1;
374} 375}
375 376
377static int stac92xx_volknob_info(struct snd_kcontrol *kcontrol,
378 struct snd_ctl_elem_info *uinfo)
379{
380 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
381 uinfo->count = 1;
382 uinfo->value.integer.min = 0;
383 uinfo->value.integer.max = 127;
384 return 0;
385}
386
387static int stac92xx_volknob_get(struct snd_kcontrol *kcontrol,
388 struct snd_ctl_elem_value *ucontrol)
389{
390 ucontrol->value.integer.value[0] = kcontrol->private_value & 0xff;
391 return 0;
392}
393
394static int stac92xx_volknob_put(struct snd_kcontrol *kcontrol,
395 struct snd_ctl_elem_value *ucontrol)
396{
397 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
398 unsigned int oval = kcontrol->private_value & 0xff;
399 unsigned int val;
400
401 val = ucontrol->value.integer.value[0] & 0xff;
402 if (val == oval)
403 return 0;
404
405 kcontrol->private_value &= ~0xff;
406 kcontrol->private_value |= val;
407
408 snd_hda_codec_write_cache(codec, kcontrol->private_value >> 16, 0,
409 AC_VERB_SET_VOLUME_KNOB_CONTROL, val | 0x80);
410 return 1;
411}
412
376static struct hda_verb stac9200_core_init[] = { 413static struct hda_verb stac9200_core_init[] = {
377 /* set dac0mux for dac converter */ 414 /* set dac0mux for dac converter */
378 { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, 415 { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -1588,7 +1625,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
1588 struct sigmatel_spec *spec = codec->spec; 1625 struct sigmatel_spec *spec = codec->spec;
1589 hda_nid_t nid = kcontrol->private_value >> 8; 1626 hda_nid_t nid = kcontrol->private_value >> 8;
1590 int io_idx = kcontrol-> private_value & 0xff; 1627 int io_idx = kcontrol-> private_value & 0xff;
1591 unsigned short val = ucontrol->value.integer.value[0]; 1628 unsigned short val = !!ucontrol->value.integer.value[0];
1592 1629
1593 spec->io_switch[io_idx] = val; 1630 spec->io_switch[io_idx] = val;
1594 1631
@@ -1628,11 +1665,12 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
1628 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1665 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1629 struct sigmatel_spec *spec = codec->spec; 1666 struct sigmatel_spec *spec = codec->spec;
1630 hda_nid_t nid = kcontrol->private_value & 0xff; 1667 hda_nid_t nid = kcontrol->private_value & 0xff;
1668 unsigned int val = !!ucontrol->value.integer.value[0];
1631 1669
1632 if (spec->clfe_swap == ucontrol->value.integer.value[0]) 1670 if (spec->clfe_swap == val)
1633 return 0; 1671 return 0;
1634 1672
1635 spec->clfe_swap = ucontrol->value.integer.value[0]; 1673 spec->clfe_swap = val;
1636 1674
1637 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, 1675 snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
1638 spec->clfe_swap ? 0x4 : 0x0); 1676 spec->clfe_swap ? 0x4 : 0x0);