[alsa-devel] [PATCH] ALSA: usb-audio: Support changing input on Sound Blaster E1

Takashi Iwai tiwai at suse.de
Tue Jan 16 12:46:36 CET 2018


On Tue, 16 Jan 2018 05:38:27 +0100,
Ian Douglas Scott wrote:
> 
> The E1 has two headphone jacks, one of which can be set as a microphone
> input. In the default mode, it uses the built-in microphone as an input.
> By sending a special command, the second headphone jack is instead used
> as an input.
> 
> This might work with the E3 as well, but I don't have one of those to
> test it.
> 
> Signed-off-by: Ian Douglas Scott <ian at iandouglasscott.com>
> ---
>  sound/usb/mixer_quirks.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 79 insertions(+)
> 
> diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
> index e1e7ce9ab217..a91a0b75f6db 100644
> --- a/sound/usb/mixer_quirks.c
> +++ b/sound/usb/mixer_quirks.c
> @@ -27,6 +27,7 @@
>   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
>   */
>  
> +#include <linux/hid.h>
>  #include <linux/init.h>
>  #include <linux/slab.h>
>  #include <linux/usb.h>
> @@ -1721,6 +1722,80 @@ static int snd_microii_controls_create(struct usb_mixer_interface *mixer)
>  	return 0;
>  }
>  
> +static int snd_soundblaster_e1_switch_get(struct snd_kcontrol *kcontrol,
> +					  struct snd_ctl_elem_value *ucontrol)
> +{
> +	ucontrol->value.integer.value[0] = kcontrol->private_value;
> +	return 0;
> +}
> +
> +static int snd_soundblaster_e1_switch_update(struct usb_mixer_interface *mixer,
> +					     unsigned char state)
> +{
> +	struct snd_usb_audio *chip = mixer->chip;
> +	int err;
> +	unsigned char buff[2];
> +
> +	buff[0] = 0x02;
> +	buff[1] = state ? 0x02 : 0x00;
> +
> +	err = snd_usb_lock_shutdown(chip);
> +	if (err < 0)
> +		return err;
> +	err = snd_usb_ctl_msg(chip->dev,
> +			      usb_sndctrlpipe(chip->dev, 0),
> +			      HID_REQ_SET_REPORT,
> +			      USB_TYPE_CLASS | USB_RECIP_INTERFACE
> +					     | USB_DIR_OUT,
> +			      0x0202, 3,
> +			      buff, 2);
> +	snd_usb_unlock_shutdown(chip);
> +	return err;
> +}
> +
> +static int snd_soundblaster_e1_switch_put(struct snd_kcontrol *kcontrol,
> +					  struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
> +	unsigned char value = ucontrol->value.integer.value[0];
> +
> +	kcontrol->private_value = value;
> +	return snd_soundblaster_e1_switch_update(list->mixer, value);
> +}

The put callback returns three types of values: a negative error, 0
for unchanged values, and 1 for the value change.  Also, the passed
value should be checked beforehand.  So, it should be like: 

static int snd_soundblaster_e1_switch_put(struct snd_kcontrol *kcontrol,
					  struct snd_ctl_elem_value *ucontrol)
{
	struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
	unsigned char value = !!ucontrol->value.integer.value[0];

	if (kcontrol->private_value = value)
		return 0;
	kcontrol->private_value = value;
	return snd_soundblaster_e1_switch_update(list->mixer, value);
}


thanks,

Takashi


More information about the Alsa-devel mailing list