diff options
author | Takashi Iwai <tiwai@suse.de> | 2007-11-15 09:54:38 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:29:24 -0500 |
commit | 68ea7b2f2d8c1effd662fded04e9a589cb640da6 (patch) | |
tree | e104282748345692c2a71572a260bf926501ebde | |
parent | 7e39e2273a9b8182ed1b21af5444e29843fc06ca (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.c | 3 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 6 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 50 |
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 | ||
377 | static 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 | |||
387 | static 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 | |||
394 | static 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 | |||
376 | static struct hda_verb stac9200_core_init[] = { | 413 | static 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); |