Commit 68ea7b2f authored by Takashi Iwai's avatar Takashi Iwai Committed by Jaroslav Kysela

[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: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
parent 7e39e227
...@@ -2337,7 +2337,8 @@ int snd_hda_ch_mode_put(struct hda_codec *codec, ...@@ -2337,7 +2337,8 @@ int snd_hda_ch_mode_put(struct hda_codec *codec,
unsigned int mode; unsigned int mode;
mode = ucontrol->value.enumerated.item[0]; mode = ucontrol->value.enumerated.item[0];
snd_assert(mode < num_chmodes, return -EINVAL); if (mode >= num_chmodes)
return -EINVAL;
if (*max_channelsp == chmode[mode].channels) if (*max_channelsp == chmode[mode].channels)
return 0; return 0;
/* change the current channel setting */ /* change the current channel setting */
......
...@@ -370,7 +370,7 @@ static int ad198x_eapd_put(struct snd_kcontrol *kcontrol, ...@@ -370,7 +370,7 @@ static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
int invert = (kcontrol->private_value >> 8) & 1; int invert = (kcontrol->private_value >> 8) & 1;
hda_nid_t nid = kcontrol->private_value & 0xff; hda_nid_t nid = kcontrol->private_value & 0xff;
unsigned int eapd; unsigned int eapd;
eapd = ucontrol->value.integer.value[0]; eapd = !!ucontrol->value.integer.value[0];
if (invert) if (invert)
eapd = !eapd; eapd = !eapd;
if (eapd == spec->cur_eapd) if (eapd == spec->cur_eapd)
...@@ -1021,6 +1021,8 @@ static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ ...@@ -1021,6 +1021,8 @@ static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *spec = codec->spec; struct ad198x_spec *spec = codec->spec;
if (ucontrol->value.enumerated.item[0] > 1)
return -EINVAL;
if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
spec->spdif_route = ucontrol->value.enumerated.item[0]; spec->spdif_route = ucontrol->value.enumerated.item[0];
snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0, 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,6 +1968,8 @@ static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
int change; int change;
val = ucontrol->value.enumerated.item[0]; val = ucontrol->value.enumerated.item[0];
if (val > 3)
return -EINVAL;
if (!val) { if (!val) {
sel = snd_hda_codec_read(codec, 0x1d, 0, sel = snd_hda_codec_read(codec, 0x1d, 0,
AC_VERB_GET_AMP_GAIN_MUTE, AC_VERB_GET_AMP_GAIN_MUTE,
......
...@@ -373,7 +373,7 @@ static int cxt_eapd_put(struct snd_kcontrol *kcontrol, ...@@ -373,7 +373,7 @@ static int cxt_eapd_put(struct snd_kcontrol *kcontrol,
hda_nid_t nid = kcontrol->private_value & 0xff; hda_nid_t nid = kcontrol->private_value & 0xff;
unsigned int eapd; unsigned int eapd;
eapd = ucontrol->value.integer.value[0]; eapd = !!ucontrol->value.integer.value[0];
if (invert) if (invert)
eapd = !eapd; eapd = !eapd;
if (eapd == spec->cur_eapd) if (eapd == spec->cur_eapd)
......
...@@ -349,12 +349,13 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, ...@@ -349,12 +349,13 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol,
struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
unsigned int dac_mode; unsigned int dac_mode;
unsigned int val;
if (spec->aloopback == ucontrol->value.integer.value[0]) val = !!ucontrol->value.integer.value[0];
if (spec->aloopback == val)
return 0; return 0;
spec->aloopback = ucontrol->value.integer.value[0]; spec->aloopback = val;
dac_mode = snd_hda_codec_read(codec, codec->afg, 0, dac_mode = snd_hda_codec_read(codec, codec->afg, 0,
kcontrol->private_value & 0xFFFF, 0x0); kcontrol->private_value & 0xFFFF, 0x0);
...@@ -373,6 +374,42 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, ...@@ -373,6 +374,42 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol,
return 1; return 1;
} }
static int stac92xx_volknob_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 127;
return 0;
}
static int stac92xx_volknob_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = kcontrol->private_value & 0xff;
return 0;
}
static int stac92xx_volknob_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned int oval = kcontrol->private_value & 0xff;
unsigned int val;
val = ucontrol->value.integer.value[0] & 0xff;
if (val == oval)
return 0;
kcontrol->private_value &= ~0xff;
kcontrol->private_value |= val;
snd_hda_codec_write_cache(codec, kcontrol->private_value >> 16, 0,
AC_VERB_SET_VOLUME_KNOB_CONTROL, val | 0x80);
return 1;
}
static struct hda_verb stac9200_core_init[] = { static struct hda_verb stac9200_core_init[] = {
/* set dac0mux for dac converter */ /* set dac0mux for dac converter */
{ 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, { 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,7 +1625,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
hda_nid_t nid = kcontrol->private_value >> 8; hda_nid_t nid = kcontrol->private_value >> 8;
int io_idx = kcontrol-> private_value & 0xff; int io_idx = kcontrol-> private_value & 0xff;
unsigned short val = ucontrol->value.integer.value[0]; unsigned short val = !!ucontrol->value.integer.value[0];
spec->io_switch[io_idx] = val; spec->io_switch[io_idx] = val;
...@@ -1628,11 +1665,12 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol, ...@@ -1628,11 +1665,12 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
hda_nid_t nid = kcontrol->private_value & 0xff; hda_nid_t nid = kcontrol->private_value & 0xff;
unsigned int val = !!ucontrol->value.integer.value[0];
if (spec->clfe_swap == ucontrol->value.integer.value[0]) if (spec->clfe_swap == val)
return 0; return 0;
spec->clfe_swap = ucontrol->value.integer.value[0]; spec->clfe_swap = val;
snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
spec->clfe_swap ? 0x4 : 0x0); spec->clfe_swap ? 0x4 : 0x0);
......
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