Skip to content

Commit

Permalink
[ALSA] hda-codec - Check value range in ctl callbacks
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Takashi Iwai authored and Jaroslav Kysela committed Jan 31, 2008
1 parent 7e39e22 commit 68ea7b2
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 9 deletions.
3 changes: 2 additions & 1 deletion sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -2337,7 +2337,8 @@ int snd_hda_ch_mode_put(struct hda_codec *codec,
unsigned int mode;

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)
return 0;
/* change the current channel setting */
Expand Down
6 changes: 5 additions & 1 deletion sound/pci/hda/patch_analog.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ static int ad198x_eapd_put(struct snd_kcontrol *kcontrol,
int invert = (kcontrol->private_value >> 8) & 1;
hda_nid_t nid = kcontrol->private_value & 0xff;
unsigned int eapd;
eapd = ucontrol->value.integer.value[0];
eapd = !!ucontrol->value.integer.value[0];
if (invert)
eapd = !eapd;
if (eapd == spec->cur_eapd)
Expand Down Expand Up @@ -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 ad198x_spec *spec = codec->spec;

if (ucontrol->value.enumerated.item[0] > 1)
return -EINVAL;
if (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,
Expand Down Expand Up @@ -1966,6 +1968,8 @@ static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
int change;

val = ucontrol->value.enumerated.item[0];
if (val > 3)
return -EINVAL;
if (!val) {
sel = snd_hda_codec_read(codec, 0x1d, 0,
AC_VERB_GET_AMP_GAIN_MUTE,
Expand Down
2 changes: 1 addition & 1 deletion sound/pci/hda/patch_conexant.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ static int cxt_eapd_put(struct snd_kcontrol *kcontrol,
hda_nid_t nid = kcontrol->private_value & 0xff;
unsigned int eapd;

eapd = ucontrol->value.integer.value[0];
eapd = !!ucontrol->value.integer.value[0];
if (invert)
eapd = !eapd;
if (eapd == spec->cur_eapd)
Expand Down
50 changes: 44 additions & 6 deletions sound/pci/hda/patch_sigmatel.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,12 +349,13 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol,
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec;
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;

spec->aloopback = ucontrol->value.integer.value[0];

spec->aloopback = val;

dac_mode = snd_hda_codec_read(codec, codec->afg, 0,
kcontrol->private_value & 0xFFFF, 0x0);
Expand All @@ -373,6 +374,42 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol,
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[] = {
/* set dac0mux for dac converter */
{ 0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
Expand Down Expand Up @@ -1588,7 +1625,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
struct sigmatel_spec *spec = codec->spec;
hda_nid_t nid = kcontrol->private_value >> 8;
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;

Expand Down Expand Up @@ -1628,11 +1665,12 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec;
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;

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,
spec->clfe_swap ? 0x4 : 0x0);
Expand Down

0 comments on commit 68ea7b2

Please sign in to comment.