aboutsummaryrefslogtreecommitdiffstats
path: root/sound/i2c/other/ak4xxx-adda.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2007-11-15 10:15:29 -0500
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:29:25 -0500
commit02ff1324930675599694bb1285afc4341f98a7a1 (patch)
treed0907abb1526a32eb0268eeb4fe31da6752eb7a9 /sound/i2c/other/ak4xxx-adda.c
parentd4079ac49a08e36d6839a9ceb26aec8c24c9ed82 (diff)
[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>
Diffstat (limited to 'sound/i2c/other/ak4xxx-adda.c')
-rw-r--r--sound/i2c/other/ak4xxx-adda.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index de03f689fa2e..39bb03add7e1 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -377,8 +377,11 @@ static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr,
377static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol, 377static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol,
378 struct snd_ctl_elem_value *ucontrol) 378 struct snd_ctl_elem_value *ucontrol)
379{ 379{
380 return put_ak_reg(kcontrol, AK_GET_ADDR(kcontrol->private_value), 380 unsigned int mask = AK_GET_MASK(kcontrol->private_value);
381 ucontrol->value.integer.value[0]); 381 unsigned int val = ucontrol->value.integer.value[0];
382 if (val > mask)
383 return -EINVAL;
384 return put_ak_reg(kcontrol, AK_GET_ADDR(kcontrol->private_value), val);
382} 385}
383 386
384static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, 387static 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,
409 struct snd_ctl_elem_value *ucontrol) 412 struct snd_ctl_elem_value *ucontrol)
410{ 413{
411 int addr = AK_GET_ADDR(kcontrol->private_value); 414 int addr = AK_GET_ADDR(kcontrol->private_value);
415 unsigned int mask = AK_GET_MASK(kcontrol->private_value);
416 unsigned int val[2];
412 int change; 417 int change;
413 418
414 change = put_ak_reg(kcontrol, addr, ucontrol->value.integer.value[0]); 419 val[0] = ucontrol->value.integer.value[0];
415 change |= put_ak_reg(kcontrol, addr + 1, 420 val[1] = ucontrol->value.integer.value[1];
416 ucontrol->value.integer.value[1]); 421 if (val[0] > mask || val[1] > mask)
422 return -EINVAL;
423 change = put_ak_reg(kcontrol, addr, val[0]);
424 change |= put_ak_reg(kcontrol, addr + 1, val[1]);
417 return change; 425 return change;
418} 426}
419 427
@@ -508,6 +516,18 @@ static int ak4xxx_switch_put(struct snd_kcontrol *kcontrol,
508 516
509#define AK5365_NUM_INPUTS 5 517#define AK5365_NUM_INPUTS 5
510 518
519static int ak4xxx_capture_num_inputs(struct snd_akm4xxx *ak, int mixer_ch)
520{
521 int num_names;
522 const char **input_names;
523
524 input_names = ak->adc_info[mixer_ch].input_names;
525 num_names = 0;
526 while (num_names < AK5365_NUM_INPUTS && input_names[num_names])
527 ++num_names;
528 return num_names;
529}
530
511static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol, 531static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol,
512 struct snd_ctl_elem_info *uinfo) 532 struct snd_ctl_elem_info *uinfo)
513{ 533{
@@ -516,18 +536,16 @@ static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol,
516 const char **input_names; 536 const char **input_names;
517 int num_names, idx; 537 int num_names, idx;
518 538
519 input_names = ak->adc_info[mixer_ch].input_names; 539 num_names = ak4xxx_capture_num_inputs(ak, mixer_ch);
520 540 if (!num_names)
521 num_names = 0; 541 return -EINVAL;
522 while (num_names < AK5365_NUM_INPUTS && input_names[num_names])
523 ++num_names;
524
525 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 542 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
526 uinfo->count = 1; 543 uinfo->count = 1;
527 uinfo->value.enumerated.items = num_names; 544 uinfo->value.enumerated.items = num_names;
528 idx = uinfo->value.enumerated.item; 545 idx = uinfo->value.enumerated.item;
529 if (idx >= num_names) 546 if (idx >= num_names)
530 return -EINVAL; 547 return -EINVAL;
548 input_names = ak->adc_info[mixer_ch].input_names;
531 strncpy(uinfo->value.enumerated.name, input_names[idx], 549 strncpy(uinfo->value.enumerated.name, input_names[idx],
532 sizeof(uinfo->value.enumerated.name)); 550 sizeof(uinfo->value.enumerated.name));
533 return 0; 551 return 0;
@@ -551,10 +569,15 @@ static int ak4xxx_capture_source_put(struct snd_kcontrol *kcontrol,
551 struct snd_ctl_elem_value *ucontrol) 569 struct snd_ctl_elem_value *ucontrol)
552{ 570{
553 struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); 571 struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
572 int mixer_ch = AK_GET_SHIFT(kcontrol->private_value);
554 int chip = AK_GET_CHIP(kcontrol->private_value); 573 int chip = AK_GET_CHIP(kcontrol->private_value);
555 int addr = AK_GET_ADDR(kcontrol->private_value); 574 int addr = AK_GET_ADDR(kcontrol->private_value);
556 int mask = AK_GET_MASK(kcontrol->private_value); 575 int mask = AK_GET_MASK(kcontrol->private_value);
557 unsigned char oval, val; 576 unsigned char oval, val;
577 int num_names = ak4xxx_capture_num_inputs(ak, mixer_ch);
578
579 if (ucontrol->value.enumerated.item[0] >= num_names)
580 return -EINVAL;
558 581
559 oval = snd_akm4xxx_get(ak, chip, addr); 582 oval = snd_akm4xxx_get(ak, chip, addr);
560 val = oval & ~mask; 583 val = oval & ~mask;