[ALSA] powermac - Check value range in ctl callbacks

Check the value ranges in ctl put callbacks properly in snd-powermac
driver.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 05dabe4..b15bfb6 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -175,10 +175,12 @@
 	int inverted = (kcontrol->private_value >> 16) & 1;
 	int val, oldval;
 	unsigned long flags;
-	int vol[2];
+	unsigned int vol[2];
 
 	vol[0] = ucontrol->value.integer.value[0];
 	vol[1] = ucontrol->value.integer.value[1];
+	if (vol[0] > 0x0f || vol[1] > 0x0f)
+		return -EINVAL;
 	if (inverted) {
 		vol[0] = 0x0f - vol[0];
 		vol[1] = 0x0f - vol[1];
@@ -421,10 +423,14 @@
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 	int index = kcontrol->private_value;
 	struct awacs_amp *amp = chip->mixer_data;
+	unsigned int val;
 	snd_assert(amp, return -EINVAL);
 	snd_assert(index >= 0 && index <= 1, return -EINVAL);
-	if (ucontrol->value.integer.value[0] != amp->amp_tone[index]) {
-		amp->amp_tone[index] = ucontrol->value.integer.value[0];
+	val = ucontrol->value.integer.value[0];
+	if (val > 14)
+		return -EINVAL;
+	if (val != amp->amp_tone[index]) {
+		amp->amp_tone[index] = val;
 		awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
 		return 1;
 	}
@@ -456,9 +462,13 @@
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 	struct awacs_amp *amp = chip->mixer_data;
+	unsigned int val;
 	snd_assert(amp, return -EINVAL);
-	if (ucontrol->value.integer.value[0] != amp->amp_master) {
-		amp->amp_master = ucontrol->value.integer.value[0];
+	val = ucontrol->value.integer.value[0];
+	if (val > 99)
+		return -EINVAL;
+	if (val != amp->amp_master) {
+		amp->amp_master = val;
 		awacs_amp_set_master(amp, amp->amp_master);
 		return 1;
 	}
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index 566b5ab..465dd04 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -195,10 +195,13 @@
 			     struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	int oval;
+	unsigned int oval, nval;
 	snd_assert(chip->beep, return -ENXIO);
 	oval = chip->beep->volume;
-	chip->beep->volume = ucontrol->value.integer.value[0];
+	nval = ucontrol->value.integer.value[0];
+	if (nval > 100)
+		return -EINVAL;
+	chip->beep->volume = nval;
 	return oval != chip->beep->volume;
 }
 
diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
index e02263f..fec74e8 100644
--- a/sound/ppc/burgundy.c
+++ b/sound/ppc/burgundy.c
@@ -136,6 +136,9 @@
 {
 	int hardvolume, lvolume, rvolume;
 
+	if (volume[0] < 0 || volume[0] > 100 ||
+	    volume[1] < 0 || volume[1] > 100)
+		return; /* -EINVAL */
 	lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0;
 	rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0;
 
@@ -301,14 +304,14 @@
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
 	int stereo = (kcontrol->private_value >> 24) & 1;
-	int oval, val;
+	unsigned int oval, val;
 
 	oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
-	val = ucontrol->value.integer.value[0];
+	val = ucontrol->value.integer.value[0] & 15;
 	if (stereo)
-		val |= ucontrol->value.integer.value[1] << 4;
+		val |= (ucontrol->value.integer.value[1] & 15) << 4;
 	else
-		val |= ucontrol->value.integer.value[0] << 4;
+		val |= val << 4;
 	val = ~val & 0xff;
 	snd_pmac_burgundy_wcb(chip, addr, val);
 	return val != oval;
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index c5a1f0b..0c81457 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -115,7 +115,7 @@
 		return -ENODEV;
 	change = mix->deemphasis != ucontrol->value.integer.value[0];
 	if (change) {
-		mix->deemphasis = ucontrol->value.integer.value[0];
+		mix->deemphasis = !!ucontrol->value.integer.value[0];
 		daca_set_volume(mix);
 	}
 	return change;
@@ -149,15 +149,20 @@
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 	struct pmac_daca *mix;
+	unsigned int vol[2];
 	int change;
 
 	if (! (mix = chip->mixer_data))
 		return -ENODEV;
-	change = mix->left_vol != ucontrol->value.integer.value[0] ||
-		mix->right_vol != ucontrol->value.integer.value[1];
+	vol[0] = ucontrol->value.integer.value[0];
+	vol[1] = ucontrol->value.integer.value[1];
+	if (vol[0] > DACA_VOL_MAX || vol[1] > DACA_VOL_MAX)
+		return -EINVAL;
+	change = mix->left_vol != vol[0] ||
+		mix->right_vol != vol[1];
 	if (change) {
-		mix->left_vol = ucontrol->value.integer.value[0];
-		mix->right_vol = ucontrol->value.integer.value[1];
+		mix->left_vol = vol[0];
+		mix->right_vol = vol[1];
 		daca_set_volume(mix);
 	}
 	return change;
@@ -188,7 +193,7 @@
 		return -ENODEV;
 	change = mix->amp_on != ucontrol->value.integer.value[0];
 	if (change) {
-		mix->amp_on = ucontrol->value.integer.value[0];
+		mix->amp_on = !!ucontrol->value.integer.value[0];
 		i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG,
 					  mix->amp_on ? 0x05 : 0x04);
 	}
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 4f9b19c..8c47beb 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -1028,7 +1028,7 @@
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 	if (ucontrol->value.integer.value[0] != chip->auto_mute) {
-		chip->auto_mute = ucontrol->value.integer.value[0];
+		chip->auto_mute = !!ucontrol->value.integer.value[0];
 		if (chip->update_automute)
 			chip->update_automute(chip, 1);
 		return 1;
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 5821cdd..bacff3d 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -275,14 +275,20 @@
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 	struct pmac_tumbler *mix = chip->mixer_data;
+	unsigned int vol[2];
 	int change;
 
 	snd_assert(mix, return -ENODEV);
-	change = mix->master_vol[0] != ucontrol->value.integer.value[0] ||
-		mix->master_vol[1] != ucontrol->value.integer.value[1];
+	vol[0] = ucontrol->value.integer.value[0];
+	vol[1] = ucontrol->value.integer.value[1];
+	if (vol[0] >= ARRAY_SIZE(master_volume_table) ||
+	    vol[1] >= ARRAY_SIZE(master_volume_table))
+		return -EINVAL;
+	change = mix->master_vol[0] != vol[0] ||
+		mix->master_vol[1] != vol[1];
 	if (change) {
-		mix->master_vol[0] = ucontrol->value.integer.value[0];
-		mix->master_vol[1] = ucontrol->value.integer.value[1];
+		mix->master_vol[0] = vol[0];
+		mix->master_vol[1] = vol[1];
 		tumbler_set_master_volume(mix);
 	}
 	return change;
@@ -417,13 +423,22 @@
 {
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 	struct pmac_tumbler *mix;
+	unsigned int val;
 	int change;
 
 	if (! (mix = chip->mixer_data))
 		return -ENODEV;
-	change = mix->drc_range != ucontrol->value.integer.value[0];
+	val = ucontrol->value.integer.value[0];
+	if (chip->model == PMAC_TUMBLER) {
+		if (val > TAS3001_DRC_MAX)
+			return -EINVAL;
+	} else {
+		if (val > TAS3004_DRC_MAX)
+			return -EINVAL;
+	}
+	change = mix->drc_range != val;
 	if (change) {
-		mix->drc_range = ucontrol->value.integer.value[0];
+		mix->drc_range = val;
 		if (chip->model == PMAC_TUMBLER)
 			tumbler_set_drc(mix);
 		else
@@ -530,13 +545,17 @@
 	struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 	struct pmac_tumbler *mix;
+	unsigned int vol;
 	int change;
 
 	if (! (mix = chip->mixer_data))
 		return -ENODEV;
-	change = mix->mono_vol[info->index] != ucontrol->value.integer.value[0];
+	vol = ucontrol->value.integer.value[0];
+	if (vol >= info->max)
+		return -EINVAL;
+	change = mix->mono_vol[info->index] != vol;
 	if (change) {
-		mix->mono_vol[info->index] = ucontrol->value.integer.value[0];
+		mix->mono_vol[info->index] = vol;
 		tumbler_set_mono_volume(mix, info);
 	}
 	return change;
@@ -672,15 +691,21 @@
 	int idx = (int)kcontrol->private_value;
 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
 	struct pmac_tumbler *mix;
+	unsigned int vol[2];
 	int change;
 
 	if (! (mix = chip->mixer_data))
 		return -ENODEV;
-	change = mix->mix_vol[idx][0] != ucontrol->value.integer.value[0] ||
-		mix->mix_vol[idx][1] != ucontrol->value.integer.value[1];
+	vol[0] = ucontrol->value.integer.value[0];
+	vol[1] = ucontrol->value.integer.value[1];
+	if (vol[0] >= ARRAY_SIZE(mixer_volume_table) ||
+	    vol[1] >= ARRAY_SIZE(mixer_volume_table))
+		return -EINVAL;
+	change = mix->mix_vol[idx][0] != vol[0] ||
+		mix->mix_vol[idx][1] != vol[1];
 	if (change) {
-		mix->mix_vol[idx][0] = ucontrol->value.integer.value[0];
-		mix->mix_vol[idx][1] = ucontrol->value.integer.value[1];
+		mix->mix_vol[idx][0] = vol[0];
+		mix->mix_vol[idx][1] = vol[1];
 		snapper_set_mix_vol(mix, idx);
 	}
 	return change;
@@ -784,7 +809,7 @@
 	struct pmac_tumbler *mix = chip->mixer_data;
 
 	snd_assert(mix, return -ENODEV);
-	ucontrol->value.integer.value[0] = mix->capture_source;
+	ucontrol->value.enumerated.value[0] = mix->capture_source;
 	return 0;
 }
 
@@ -796,9 +821,9 @@
 	int change;
 
 	snd_assert(mix, return -ENODEV);
-	change = ucontrol->value.integer.value[0] != mix->capture_source;
+	change = ucontrol->value.enuemerated.item[0] != mix->capture_source;
 	if (change) {
-		mix->capture_source = !!ucontrol->value.integer.value[0];
+		mix->capture_source = !!ucontrol->value.enumerated.item[0];
 		snapper_set_capture_source(mix);
 	}
 	return change;