diff options
author | Takashi Iwai <tiwai@suse.de> | 2007-11-15 10:15:29 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:29:25 -0500 |
commit | 02ff1324930675599694bb1285afc4341f98a7a1 (patch) | |
tree | d0907abb1526a32eb0268eeb4fe31da6752eb7a9 /sound/i2c | |
parent | d4079ac49a08e36d6839a9ceb26aec8c24c9ed82 (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')
-rw-r--r-- | sound/i2c/other/ak4xxx-adda.c | 45 |
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, | |||
377 | static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol, | 377 | static 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 | ||
384 | static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, | 387 | 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, | |||
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 | ||
519 | static 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 | |||
511 | static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol, | 531 | static 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; |