[ALSA] ak4xxx - Check value ranges in ctl callbacks
Check the value ranges in ctl put callbacks properly in ak4xxx-adda driver. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
committed by
Jaroslav Kysela
parent
d4079ac49a
commit
02ff132493
@@ -377,8 +377,11 @@ static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr,
|
|||||||
static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol,
|
static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_value *ucontrol)
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
return put_ak_reg(kcontrol, AK_GET_ADDR(kcontrol->private_value),
|
unsigned int mask = AK_GET_MASK(kcontrol->private_value);
|
||||||
ucontrol->value.integer.value[0]);
|
unsigned int val = ucontrol->value.integer.value[0];
|
||||||
|
if (val > mask)
|
||||||
|
return -EINVAL;
|
||||||
|
return put_ak_reg(kcontrol, AK_GET_ADDR(kcontrol->private_value), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol,
|
static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol,
|
||||||
@@ -409,11 +412,16 @@ static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_value *ucontrol)
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
int addr = AK_GET_ADDR(kcontrol->private_value);
|
int addr = AK_GET_ADDR(kcontrol->private_value);
|
||||||
|
unsigned int mask = AK_GET_MASK(kcontrol->private_value);
|
||||||
|
unsigned int val[2];
|
||||||
int change;
|
int change;
|
||||||
|
|
||||||
change = put_ak_reg(kcontrol, addr, ucontrol->value.integer.value[0]);
|
val[0] = ucontrol->value.integer.value[0];
|
||||||
change |= put_ak_reg(kcontrol, addr + 1,
|
val[1] = ucontrol->value.integer.value[1];
|
||||||
ucontrol->value.integer.value[1]);
|
if (val[0] > mask || val[1] > mask)
|
||||||
|
return -EINVAL;
|
||||||
|
change = put_ak_reg(kcontrol, addr, val[0]);
|
||||||
|
change |= put_ak_reg(kcontrol, addr + 1, val[1]);
|
||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,6 +516,18 @@ static int ak4xxx_switch_put(struct snd_kcontrol *kcontrol,
|
|||||||
|
|
||||||
#define AK5365_NUM_INPUTS 5
|
#define AK5365_NUM_INPUTS 5
|
||||||
|
|
||||||
|
static int ak4xxx_capture_num_inputs(struct snd_akm4xxx *ak, int mixer_ch)
|
||||||
|
{
|
||||||
|
int num_names;
|
||||||
|
const char **input_names;
|
||||||
|
|
||||||
|
input_names = ak->adc_info[mixer_ch].input_names;
|
||||||
|
num_names = 0;
|
||||||
|
while (num_names < AK5365_NUM_INPUTS && input_names[num_names])
|
||||||
|
++num_names;
|
||||||
|
return num_names;
|
||||||
|
}
|
||||||
|
|
||||||
static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol,
|
static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
@@ -516,18 +536,16 @@ static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol,
|
|||||||
const char **input_names;
|
const char **input_names;
|
||||||
int num_names, idx;
|
int num_names, idx;
|
||||||
|
|
||||||
input_names = ak->adc_info[mixer_ch].input_names;
|
num_names = ak4xxx_capture_num_inputs(ak, mixer_ch);
|
||||||
|
if (!num_names)
|
||||||
num_names = 0;
|
return -EINVAL;
|
||||||
while (num_names < AK5365_NUM_INPUTS && input_names[num_names])
|
|
||||||
++num_names;
|
|
||||||
|
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
|
||||||
uinfo->count = 1;
|
uinfo->count = 1;
|
||||||
uinfo->value.enumerated.items = num_names;
|
uinfo->value.enumerated.items = num_names;
|
||||||
idx = uinfo->value.enumerated.item;
|
idx = uinfo->value.enumerated.item;
|
||||||
if (idx >= num_names)
|
if (idx >= num_names)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
input_names = ak->adc_info[mixer_ch].input_names;
|
||||||
strncpy(uinfo->value.enumerated.name, input_names[idx],
|
strncpy(uinfo->value.enumerated.name, input_names[idx],
|
||||||
sizeof(uinfo->value.enumerated.name));
|
sizeof(uinfo->value.enumerated.name));
|
||||||
return 0;
|
return 0;
|
||||||
@@ -551,10 +569,15 @@ static int ak4xxx_capture_source_put(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_value *ucontrol)
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
|
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
|
||||||
|
int mixer_ch = AK_GET_SHIFT(kcontrol->private_value);
|
||||||
int chip = AK_GET_CHIP(kcontrol->private_value);
|
int chip = AK_GET_CHIP(kcontrol->private_value);
|
||||||
int addr = AK_GET_ADDR(kcontrol->private_value);
|
int addr = AK_GET_ADDR(kcontrol->private_value);
|
||||||
int mask = AK_GET_MASK(kcontrol->private_value);
|
int mask = AK_GET_MASK(kcontrol->private_value);
|
||||||
unsigned char oval, val;
|
unsigned char oval, val;
|
||||||
|
int num_names = ak4xxx_capture_num_inputs(ak, mixer_ch);
|
||||||
|
|
||||||
|
if (ucontrol->value.enumerated.item[0] >= num_names)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
oval = snd_akm4xxx_get(ak, chip, addr);
|
oval = snd_akm4xxx_get(ak, chip, addr);
|
||||||
val = oval & ~mask;
|
val = oval & ~mask;
|
||||||
|
Reference in New Issue
Block a user