Commit 4e98d6a7 authored by Takashi Iwai's avatar Takashi Iwai Committed by Jaroslav Kysela
Browse files

[ALSA] pci - check value range in ctl callbacks



Check the value ranges in ctl put callbacks properly in the rest of
PCI drivers.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
parent ab2dac2b
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -133,6 +133,14 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
	unsigned char mode = ucontrol->value.enumerated.item[0];

	if (kcontrol->private_value) {
		if (mode >= 2)
			return -EINVAL;
	} else {
		if (mode >= 3)
			return -EINVAL;
	}

	if (mode != ac97->channel_mode) {
		ac97->channel_mode = mode;
		if (ac97->build_ops->update_jacks)
@@ -2142,8 +2150,7 @@ static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol,
	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
	unsigned short val;

	if (ucontrol->value.enumerated.item[0] > 3
	    || ucontrol->value.enumerated.item[0] < 0)
	if (ucontrol->value.enumerated.item[0] > 3)
		return -EINVAL;
	val = ctrl2reg[ucontrol->value.enumerated.item[0]]
	      << AC97_AD198X_VREF_SHIFT;
+24 −10
Original line number Diff line number Diff line
@@ -1752,22 +1752,22 @@ static int snd_korg1212_control_phase_put(struct snd_kcontrol *kcontrol,

	i = kcontrol->private_value;

	korg1212->volumePhase[i] = u->value.integer.value[0];
	korg1212->volumePhase[i] = !!u->value.integer.value[0];

	val = korg1212->sharedBufferPtr->volumeData[kcontrol->private_value];

	if ((u->value.integer.value[0] > 0) != (val < 0)) {
	if ((u->value.integer.value[0] != 0) != (val < 0)) {
		val = abs(val) * (korg1212->volumePhase[i] > 0 ? -1 : 1);
		korg1212->sharedBufferPtr->volumeData[i] = val;
		change = 1;
	}

	if (i >= 8) {
		korg1212->volumePhase[i+1] = u->value.integer.value[1];
		korg1212->volumePhase[i+1] = !!u->value.integer.value[1];

		val = korg1212->sharedBufferPtr->volumeData[kcontrol->private_value+1];

		if ((u->value.integer.value[1] > 0) != (val < 0)) {
		if ((u->value.integer.value[1] != 0) != (val < 0)) {
			val = abs(val) * (korg1212->volumePhase[i+1] > 0 ? -1 : 1);
			korg1212->sharedBufferPtr->volumeData[i+1] = val;
			change = 1;
@@ -1820,7 +1820,10 @@ static int snd_korg1212_control_volume_put(struct snd_kcontrol *kcontrol,

	i = kcontrol->private_value;

	if (u->value.integer.value[0] != abs(korg1212->sharedBufferPtr->volumeData[i])) {
	if (u->value.integer.value[0] >= k1212MinVolume && 
	    u->value.integer.value[0] >= k1212MaxVolume &&
	    u->value.integer.value[0] !=
	    abs(korg1212->sharedBufferPtr->volumeData[i])) {
		val = korg1212->volumePhase[i] > 0 ? -1 : 1;
		val *= u->value.integer.value[0];
		korg1212->sharedBufferPtr->volumeData[i] = val;
@@ -1828,7 +1831,10 @@ static int snd_korg1212_control_volume_put(struct snd_kcontrol *kcontrol,
	}

	if (i >= 8) {
		if (u->value.integer.value[1] != abs(korg1212->sharedBufferPtr->volumeData[i+1])) {
		if (u->value.integer.value[1] >= k1212MinVolume && 
		    u->value.integer.value[1] >= k1212MaxVolume &&
		    u->value.integer.value[1] !=
		    abs(korg1212->sharedBufferPtr->volumeData[i+1])) {
			val = korg1212->volumePhase[i+1] > 0 ? -1 : 1;
			val *= u->value.integer.value[1];
			korg1212->sharedBufferPtr->volumeData[i+1] = val;
@@ -1883,13 +1889,17 @@ static int snd_korg1212_control_route_put(struct snd_kcontrol *kcontrol,

	i = kcontrol->private_value;

	if (u->value.enumerated.item[0] != (unsigned) korg1212->sharedBufferPtr->volumeData[i]) {
	if (u->value.enumerated.item[0] < kAudioChannels &&
	    u->value.enumerated.item[0] !=
	    (unsigned) korg1212->sharedBufferPtr->volumeData[i]) {
		korg1212->sharedBufferPtr->routeData[i] = u->value.enumerated.item[0];
		change = 1;
	}

	if (i >= 8) {
		if (u->value.enumerated.item[1] != (unsigned) korg1212->sharedBufferPtr->volumeData[i+1]) {
		if (u->value.enumerated.item[1] < kAudioChannels &&
		    u->value.enumerated.item[1] !=
		    (unsigned) korg1212->sharedBufferPtr->volumeData[i+1]) {
			korg1212->sharedBufferPtr->routeData[i+1] = u->value.enumerated.item[1];
			change = 1;
		}
@@ -1933,11 +1943,15 @@ static int snd_korg1212_control_put(struct snd_kcontrol *kcontrol,

	spin_lock_irq(&korg1212->lock);

        if (u->value.integer.value[0] != korg1212->leftADCInSens) {
	if (u->value.integer.value[0] >= k1212MinADCSens &&
	    u->value.integer.value[0] <= k1212MaxADCSens &&
	    u->value.integer.value[0] != korg1212->leftADCInSens) {
                korg1212->leftADCInSens = u->value.integer.value[0];
                change = 1;
        }
        if (u->value.integer.value[1] != korg1212->rightADCInSens) {
	if (u->value.integer.value[1] >= k1212MinADCSens &&
	    u->value.integer.value[1] <= k1212MaxADCSens &&
	    u->value.integer.value[1] != korg1212->rightADCInSens) {
                korg1212->rightADCInSens = u->value.integer.value[1];
                change = 1;
        }
+50 −21
Original line number Diff line number Diff line
@@ -120,8 +120,18 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol,
	is_capture = (kcontrol->private_value != 0);
	for (i = 0; i < 2; i++) {
		int  new_volume = ucontrol->value.integer.value[i];
		int* stored_volume = is_capture ? &chip->analog_capture_volume[i] :
		int *stored_volume = is_capture ?
			&chip->analog_capture_volume[i] :
			&chip->analog_playback_volume[i];
		if (is_capture) {
			if (new_volume < PCXHR_ANALOG_CAPTURE_LEVEL_MIN ||
			    new_volume > PCXHR_ANALOG_CAPTURE_LEVEL_MAX)
				continue;
		} else {
			if (new_volume < PCXHR_ANALOG_PLAYBACK_LEVEL_MIN ||
			    new_volume > PCXHR_ANALOG_PLAYBACK_LEVEL_MAX)
				continue;
		}
		if (*stored_volume != new_volume) {
			*stored_volume = new_volume;
			changed = 1;
@@ -165,10 +175,13 @@ static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol,
	int i, changed = 0;
	mutex_lock(&chip->mgr->mixer_mutex);
	for(i = 0; i < 2; i++) {
		if (chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) {
			chip->analog_playback_active[i] = ucontrol->value.integer.value[i];
		if (chip->analog_playback_active[i] !=
		    ucontrol->value.integer.value[i]) {
			chip->analog_playback_active[i] =
				!!ucontrol->value.integer.value[i];
			changed = 1;
			pcxhr_update_analog_audio_level(chip, 0, i);	/* update playback levels */
			/* update playback levels */
			pcxhr_update_analog_audio_level(chip, 0, i);
		}
	}
	mutex_unlock(&chip->mgr->mixer_mutex);
@@ -323,20 +336,24 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol,
	int i;

	mutex_lock(&chip->mgr->mixer_mutex);
	if (is_capture)
		stored_volume = chip->digital_capture_volume;		/* digital capture */
	else
		stored_volume = chip->digital_playback_volume[idx];	/* digital playback */
	if (is_capture)		/* digital capture */
		stored_volume = chip->digital_capture_volume;
	else			/* digital playback */
		stored_volume = chip->digital_playback_volume[idx];
	for (i = 0; i < 2; i++) {
		if (stored_volume[i] != ucontrol->value.integer.value[i]) {
			stored_volume[i] = ucontrol->value.integer.value[i];
		int vol = ucontrol->value.integer.value[i];
		if (vol < PCXHR_DIGITAL_LEVEL_MIN ||
		    vol > PCXHR_DIGITAL_LEVEL_MAX)
			continue;
		if (stored_volume[i] != vol) {
			stored_volume[i] = vol;
			changed = 1;
			if (is_capture)	/* update capture volume */
				pcxhr_update_audio_pipe_level(chip, 1, i);
		}
	}
	if (! is_capture && changed)
		pcxhr_update_playback_stream_level(chip, idx);	/* update playback volume */
	if (!is_capture && changed)	/* update playback volume */
		pcxhr_update_playback_stream_level(chip, idx);
	mutex_unlock(&chip->mgr->mixer_mutex);
	return changed;
}
@@ -378,8 +395,10 @@ static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
	mutex_lock(&chip->mgr->mixer_mutex);
	j = idx;
	for (i = 0; i < 2; i++) {
		if (chip->digital_playback_active[j][i] != ucontrol->value.integer.value[i]) {
			chip->digital_playback_active[j][i] = ucontrol->value.integer.value[i];
		if (chip->digital_playback_active[j][i] !=
		    ucontrol->value.integer.value[i]) {
			chip->digital_playback_active[j][i] =
				!!ucontrol->value.integer.value[i];
			changed = 1;
		}
	}
@@ -423,10 +442,13 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol,

	mutex_lock(&chip->mgr->mixer_mutex);
	for (i = 0; i < 2; i++) {
		if (chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) {
			chip->monitoring_volume[i] = ucontrol->value.integer.value[i];
			if(chip->monitoring_active[i])	/* do only when monitoring is unmuted */
		if (chip->monitoring_volume[i] !=
		    ucontrol->value.integer.value[i]) {
			chip->monitoring_volume[i] =
				!!ucontrol->value.integer.value[i];
			if(chip->monitoring_active[i])
				/* update monitoring volume and mute */
				/* do only when monitoring is unmuted */
				pcxhr_update_audio_pipe_level(chip, 0, i);
			changed = 1;
		}
@@ -470,8 +492,10 @@ static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol,

	mutex_lock(&chip->mgr->mixer_mutex);
	for (i = 0; i < 2; i++) {
		if (chip->monitoring_active[i] != ucontrol->value.integer.value[i]) {
			chip->monitoring_active[i] = ucontrol->value.integer.value[i];
		if (chip->monitoring_active[i] !=
		    ucontrol->value.integer.value[i]) {
			chip->monitoring_active[i] =
				!!ucontrol->value.integer.value[i];
			changed |= (1<<i); /* mask 0x01 and 0x02 */
		}
	}
@@ -579,6 +603,8 @@ static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol,
	struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
	int ret = 0;

	if (ucontrol->value.enumerated.item[0] >= 3)
		return -EINVAL;
	mutex_lock(&chip->mgr->mixer_mutex);
	if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) {
		chip->audio_capture_source = ucontrol->value.enumerated.item[0];
@@ -642,8 +668,11 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
	unsigned int clock_items = 3 + mgr->capture_chips;
	int rate, ret = 0;

	if (ucontrol->value.enumerated.item[0] >= clock_items)
		return -EINVAL;
	mutex_lock(&mgr->mixer_mutex);
	if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) {
		mutex_lock(&mgr->setup_mutex);
+15 −12
Original line number Diff line number Diff line
@@ -2195,22 +2195,25 @@ snd_rme96_dac_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
{
	struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
        int change = 0;
	unsigned int vol, maxvol;

	if (!RME96_HAS_ANALOG_OUT(rme96)) {

	if (!RME96_HAS_ANALOG_OUT(rme96))
		return -EINVAL;
	}
	maxvol = RME96_185X_MAX_OUT(rme96);
	spin_lock_irq(&rme96->lock);
        if (u->value.integer.value[0] != rme96->vol[0]) {
		rme96->vol[0] = u->value.integer.value[0];
	vol = u->value.integer.value[0];
	if (vol != rme96->vol[0] && vol <= maxvol) {
		rme96->vol[0] = vol;
		change = 1;
	}
        if (u->value.integer.value[1] != rme96->vol[1]) {
		rme96->vol[1] = u->value.integer.value[1];
	vol = u->value.integer.value[1];
	if (vol != rme96->vol[1] && vol <= maxvol) {
		rme96->vol[1] = vol;
		change = 1;
	}
	if (change) {
	if (change)
		snd_rme96_apply_dac_volume(rme96);
	}
	spin_unlock_irq(&rme96->lock);

        return change;
+1 −1
Original line number Diff line number Diff line
@@ -2119,7 +2119,7 @@ static int snd_hdsp_put_clock_source_lock(struct snd_kcontrol *kcontrol, struct

	change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked;
	if (change)
		hdsp->clock_source_locked = ucontrol->value.integer.value[0];
		hdsp->clock_source_locked = !!ucontrol->value.integer.value[0];
	return change;
}

Loading