[PATCH] usb-audio: Input source control - digidesign mbox

Takashi Iwai tiwai at suse.de
Wed Aug 11 17:26:10 CEST 2021


On Sun, 08 Aug 2021 07:09:31 +0200,
Damien Zammit wrote:
> 
> This adds a second mixer control to Digidesign Mbox
> to select between Analog/SPDIF capture.
> 
> Users will note that selecting the SPDIF input source
> automatically switches the clock mode to sync to SPDIF,
> which is a feature of the hardware.
> 
> (You can change the clock source back to internal if you want
> to capture from spdif but not sync to its clock although this mode
> is probably not recommended).
> 
> Unfortunately, starting the stream resets both modes
> to Internally clocked and Analog input mode.

Please add your Signed-off-by line.  It's mandatory.

About the code change:
> @@ -596,31 +596,53 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
>  
>  /* Digidesign Mbox 1 clock source switch (internal/spdif) */
>  
> -static int snd_mbox1_switch_get(struct snd_kcontrol *kctl,
> -				struct snd_ctl_elem_value *ucontrol)
> +static int snd_mbox1_clk_switch_get(struct snd_kcontrol *kctl,
> +				    struct snd_ctl_elem_value *ucontrol)
>  {
> +	struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
> +	struct snd_usb_audio *chip = list->mixer->chip;
> +	unsigned char buff[3];
> +

You need to wrap the execution with snd_usb_lock_shutdown() /
snd_usb_unlock_shutdown().

> +	/* Read clock source */
> +	snd_usb_ctl_msg(chip->dev,
> +				usb_rcvctrlpipe(chip->dev, 0), 0x81,
> +				USB_DIR_IN |
> +				USB_TYPE_CLASS |
> +				USB_RECIP_ENDPOINT, 0x100, 0x81, buff, 3);

Please try to align the indent level.
And, the execution error check is missing.

Also, I believe it'd be wise to make it a helper function, as this is
used in another place, too.  Ditto for other snd_usb_ctl_msg() calls,
too.

> +static int snd_mbox1_src_switch_get(struct snd_kcontrol *kctl,
> +				    struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
> +	struct snd_usb_audio *chip = list->mixer->chip;
> +	unsigned char source[1];

Missing snd_usb_lock_shutdown() / *_unlock_*() here, too.

> +	/* Read input source */
> +	snd_usb_ctl_msg(chip->dev,
> +				usb_rcvctrlpipe(chip->dev, 0), 0x81,
> +				USB_DIR_IN |
> +				USB_TYPE_CLASS |
> +				USB_RECIP_INTERFACE, 0x00, 0x500, source, 1);

Check the error.

> +	kctl->private_value = source[0] - 1;

The value returned from the hardware isn't reliable.  Check whether
it's a valid value.


> +	ucontrol->value.enumerated.item[0] = kctl->private_value;
> +	return 0;
> +}
> +
> +static int snd_mbox1_src_switch_update(struct usb_mixer_interface *mixer, int val)
> +{
> +	struct snd_usb_audio *chip = mixer->chip;
> +	int err;
> +	unsigned char buff[3];
> +	unsigned char source[1];
> +
> +	err = snd_usb_lock_shutdown(chip);
> +	if (err < 0)
> +		return err;
> +
> +	/* Read input source */
> +	err = snd_usb_ctl_msg(chip->dev,
> +				usb_rcvctrlpipe(chip->dev, 0), 0x81,
> +				USB_DIR_IN |
> +				USB_TYPE_CLASS |
> +				USB_RECIP_INTERFACE, 0x00, 0x500, source, 1);
> +	if (err < 0)
> +		goto err;
> +
> +	/* 2 possibilities:	ANALOG Source  -> 0x01
> +	 *			S/PDIF Source  -> 0x02
> +	 * Setting the input source to S/PDIF resets the clock source to S/PDIF
> +	 */
> +	source[0] = (val + 1) & 0xff;

Here better to trust private_value is a valid value, and you can drop
the superfluous "& 0xff".  It's cut down anyway.


thanks,

Takashi


More information about the Alsa-devel mailing list