mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
[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>
This commit is contained in:
parent
d05ab185b7
commit
d4079ac49a
6 changed files with 79 additions and 33 deletions
|
@ -175,10 +175,12 @@ static int snd_pmac_awacs_put_volume(struct snd_kcontrol *kcontrol,
|
||||||
int inverted = (kcontrol->private_value >> 16) & 1;
|
int inverted = (kcontrol->private_value >> 16) & 1;
|
||||||
int val, oldval;
|
int val, oldval;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int vol[2];
|
unsigned int vol[2];
|
||||||
|
|
||||||
vol[0] = ucontrol->value.integer.value[0];
|
vol[0] = ucontrol->value.integer.value[0];
|
||||||
vol[1] = ucontrol->value.integer.value[1];
|
vol[1] = ucontrol->value.integer.value[1];
|
||||||
|
if (vol[0] > 0x0f || vol[1] > 0x0f)
|
||||||
|
return -EINVAL;
|
||||||
if (inverted) {
|
if (inverted) {
|
||||||
vol[0] = 0x0f - vol[0];
|
vol[0] = 0x0f - vol[0];
|
||||||
vol[1] = 0x0f - vol[1];
|
vol[1] = 0x0f - vol[1];
|
||||||
|
@ -421,10 +423,14 @@ static int snd_pmac_awacs_put_tone_amp(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
||||||
int index = kcontrol->private_value;
|
int index = kcontrol->private_value;
|
||||||
struct awacs_amp *amp = chip->mixer_data;
|
struct awacs_amp *amp = chip->mixer_data;
|
||||||
|
unsigned int val;
|
||||||
snd_assert(amp, return -EINVAL);
|
snd_assert(amp, return -EINVAL);
|
||||||
snd_assert(index >= 0 && index <= 1, return -EINVAL);
|
snd_assert(index >= 0 && index <= 1, return -EINVAL);
|
||||||
if (ucontrol->value.integer.value[0] != amp->amp_tone[index]) {
|
val = ucontrol->value.integer.value[0];
|
||||||
amp->amp_tone[index] = 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]);
|
awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -456,9 +462,13 @@ static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
||||||
struct awacs_amp *amp = chip->mixer_data;
|
struct awacs_amp *amp = chip->mixer_data;
|
||||||
|
unsigned int val;
|
||||||
snd_assert(amp, return -EINVAL);
|
snd_assert(amp, return -EINVAL);
|
||||||
if (ucontrol->value.integer.value[0] != amp->amp_master) {
|
val = ucontrol->value.integer.value[0];
|
||||||
amp->amp_master = 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);
|
awacs_amp_set_master(amp, amp->amp_master);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,10 +195,13 @@ static int snd_pmac_put_beep(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_value *ucontrol)
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
||||||
int oval;
|
unsigned int oval, nval;
|
||||||
snd_assert(chip->beep, return -ENXIO);
|
snd_assert(chip->beep, return -ENXIO);
|
||||||
oval = chip->beep->volume;
|
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;
|
return oval != chip->beep->volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,9 @@ snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address,
|
||||||
{
|
{
|
||||||
int hardvolume, lvolume, rvolume;
|
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;
|
lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0;
|
||||||
rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0;
|
rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0;
|
||||||
|
|
||||||
|
@ -301,14 +304,14 @@ static int snd_pmac_burgundy_put_volume_out(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
||||||
unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
|
unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
|
||||||
int stereo = (kcontrol->private_value >> 24) & 1;
|
int stereo = (kcontrol->private_value >> 24) & 1;
|
||||||
int oval, val;
|
unsigned int oval, val;
|
||||||
|
|
||||||
oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
|
oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
|
||||||
val = ucontrol->value.integer.value[0];
|
val = ucontrol->value.integer.value[0] & 15;
|
||||||
if (stereo)
|
if (stereo)
|
||||||
val |= ucontrol->value.integer.value[1] << 4;
|
val |= (ucontrol->value.integer.value[1] & 15) << 4;
|
||||||
else
|
else
|
||||||
val |= ucontrol->value.integer.value[0] << 4;
|
val |= val << 4;
|
||||||
val = ~val & 0xff;
|
val = ~val & 0xff;
|
||||||
snd_pmac_burgundy_wcb(chip, addr, val);
|
snd_pmac_burgundy_wcb(chip, addr, val);
|
||||||
return val != oval;
|
return val != oval;
|
||||||
|
|
|
@ -115,7 +115,7 @@ static int daca_put_deemphasis(struct snd_kcontrol *kcontrol,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
change = mix->deemphasis != ucontrol->value.integer.value[0];
|
change = mix->deemphasis != ucontrol->value.integer.value[0];
|
||||||
if (change) {
|
if (change) {
|
||||||
mix->deemphasis = ucontrol->value.integer.value[0];
|
mix->deemphasis = !!ucontrol->value.integer.value[0];
|
||||||
daca_set_volume(mix);
|
daca_set_volume(mix);
|
||||||
}
|
}
|
||||||
return change;
|
return change;
|
||||||
|
@ -149,15 +149,20 @@ static int daca_put_volume(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
||||||
struct pmac_daca *mix;
|
struct pmac_daca *mix;
|
||||||
|
unsigned int vol[2];
|
||||||
int change;
|
int change;
|
||||||
|
|
||||||
if (! (mix = chip->mixer_data))
|
if (! (mix = chip->mixer_data))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
change = mix->left_vol != ucontrol->value.integer.value[0] ||
|
vol[0] = ucontrol->value.integer.value[0];
|
||||||
mix->right_vol != ucontrol->value.integer.value[1];
|
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) {
|
if (change) {
|
||||||
mix->left_vol = ucontrol->value.integer.value[0];
|
mix->left_vol = vol[0];
|
||||||
mix->right_vol = ucontrol->value.integer.value[1];
|
mix->right_vol = vol[1];
|
||||||
daca_set_volume(mix);
|
daca_set_volume(mix);
|
||||||
}
|
}
|
||||||
return change;
|
return change;
|
||||||
|
@ -188,7 +193,7 @@ static int daca_put_amp(struct snd_kcontrol *kcontrol,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
change = mix->amp_on != ucontrol->value.integer.value[0];
|
change = mix->amp_on != ucontrol->value.integer.value[0];
|
||||||
if (change) {
|
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,
|
i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG,
|
||||||
mix->amp_on ? 0x05 : 0x04);
|
mix->amp_on ? 0x05 : 0x04);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1028,7 +1028,7 @@ static int pmac_auto_mute_put(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
||||||
if (ucontrol->value.integer.value[0] != chip->auto_mute) {
|
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)
|
if (chip->update_automute)
|
||||||
chip->update_automute(chip, 1);
|
chip->update_automute(chip, 1);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -275,14 +275,20 @@ static int tumbler_put_master_volume(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
||||||
struct pmac_tumbler *mix = chip->mixer_data;
|
struct pmac_tumbler *mix = chip->mixer_data;
|
||||||
|
unsigned int vol[2];
|
||||||
int change;
|
int change;
|
||||||
|
|
||||||
snd_assert(mix, return -ENODEV);
|
snd_assert(mix, return -ENODEV);
|
||||||
change = mix->master_vol[0] != ucontrol->value.integer.value[0] ||
|
vol[0] = ucontrol->value.integer.value[0];
|
||||||
mix->master_vol[1] != ucontrol->value.integer.value[1];
|
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) {
|
if (change) {
|
||||||
mix->master_vol[0] = ucontrol->value.integer.value[0];
|
mix->master_vol[0] = vol[0];
|
||||||
mix->master_vol[1] = ucontrol->value.integer.value[1];
|
mix->master_vol[1] = vol[1];
|
||||||
tumbler_set_master_volume(mix);
|
tumbler_set_master_volume(mix);
|
||||||
}
|
}
|
||||||
return change;
|
return change;
|
||||||
|
@ -417,13 +423,22 @@ static int tumbler_put_drc_value(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
||||||
struct pmac_tumbler *mix;
|
struct pmac_tumbler *mix;
|
||||||
|
unsigned int val;
|
||||||
int change;
|
int change;
|
||||||
|
|
||||||
if (! (mix = chip->mixer_data))
|
if (! (mix = chip->mixer_data))
|
||||||
return -ENODEV;
|
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) {
|
if (change) {
|
||||||
mix->drc_range = ucontrol->value.integer.value[0];
|
mix->drc_range = val;
|
||||||
if (chip->model == PMAC_TUMBLER)
|
if (chip->model == PMAC_TUMBLER)
|
||||||
tumbler_set_drc(mix);
|
tumbler_set_drc(mix);
|
||||||
else
|
else
|
||||||
|
@ -530,13 +545,17 @@ static int tumbler_put_mono(struct snd_kcontrol *kcontrol,
|
||||||
struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
|
struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
|
||||||
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
||||||
struct pmac_tumbler *mix;
|
struct pmac_tumbler *mix;
|
||||||
|
unsigned int vol;
|
||||||
int change;
|
int change;
|
||||||
|
|
||||||
if (! (mix = chip->mixer_data))
|
if (! (mix = chip->mixer_data))
|
||||||
return -ENODEV;
|
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) {
|
if (change) {
|
||||||
mix->mono_vol[info->index] = ucontrol->value.integer.value[0];
|
mix->mono_vol[info->index] = vol;
|
||||||
tumbler_set_mono_volume(mix, info);
|
tumbler_set_mono_volume(mix, info);
|
||||||
}
|
}
|
||||||
return change;
|
return change;
|
||||||
|
@ -672,15 +691,21 @@ static int snapper_put_mix(struct snd_kcontrol *kcontrol,
|
||||||
int idx = (int)kcontrol->private_value;
|
int idx = (int)kcontrol->private_value;
|
||||||
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
|
||||||
struct pmac_tumbler *mix;
|
struct pmac_tumbler *mix;
|
||||||
|
unsigned int vol[2];
|
||||||
int change;
|
int change;
|
||||||
|
|
||||||
if (! (mix = chip->mixer_data))
|
if (! (mix = chip->mixer_data))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
change = mix->mix_vol[idx][0] != ucontrol->value.integer.value[0] ||
|
vol[0] = ucontrol->value.integer.value[0];
|
||||||
mix->mix_vol[idx][1] != ucontrol->value.integer.value[1];
|
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) {
|
if (change) {
|
||||||
mix->mix_vol[idx][0] = ucontrol->value.integer.value[0];
|
mix->mix_vol[idx][0] = vol[0];
|
||||||
mix->mix_vol[idx][1] = ucontrol->value.integer.value[1];
|
mix->mix_vol[idx][1] = vol[1];
|
||||||
snapper_set_mix_vol(mix, idx);
|
snapper_set_mix_vol(mix, idx);
|
||||||
}
|
}
|
||||||
return change;
|
return change;
|
||||||
|
@ -784,7 +809,7 @@ static int snapper_get_capture_source(struct snd_kcontrol *kcontrol,
|
||||||
struct pmac_tumbler *mix = chip->mixer_data;
|
struct pmac_tumbler *mix = chip->mixer_data;
|
||||||
|
|
||||||
snd_assert(mix, return -ENODEV);
|
snd_assert(mix, return -ENODEV);
|
||||||
ucontrol->value.integer.value[0] = mix->capture_source;
|
ucontrol->value.enumerated.value[0] = mix->capture_source;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -796,9 +821,9 @@ static int snapper_put_capture_source(struct snd_kcontrol *kcontrol,
|
||||||
int change;
|
int change;
|
||||||
|
|
||||||
snd_assert(mix, return -ENODEV);
|
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) {
|
if (change) {
|
||||||
mix->capture_source = !!ucontrol->value.integer.value[0];
|
mix->capture_source = !!ucontrol->value.enumerated.item[0];
|
||||||
snapper_set_capture_source(mix);
|
snapper_set_capture_source(mix);
|
||||||
}
|
}
|
||||||
return change;
|
return change;
|
||||||
|
|
Loading…
Reference in a new issue