Re: [PATCH] ALSA: usb-audio: allow -EPIPE errors for some v2 messages

Takashi Iwai
2021-10-12T07:35:24Z

On Mon, 11 Oct 2021 19:23:05 +0200,
Greg Kroah-Hartman wrote:
>
> On Mon, Oct 11, 2021 at 06:07:01PM +0200, Takashi Iwai wrote:
> > Could you also post the contents of /proc/asound/card*/usbmixer (only
> > for the corresponding device), too?
>
> Sure, here it is:
>
> USB Mixer: usb_id=0x30be0101, ctrlif=0, ctlerr=0
> Card: Schiit Audio Schiit Hel at usb-0000:47:00.1-2.2, high speed
> Unit: 5
> Control: name="Mic - Input Jack", index=0
> Info: id=5, control=2, cmask=0x0, channels=1, type="BOOLEAN"
> Volume: min=0, max=1, dBmin=0, dBmax=0
> Unit: 7
> Control: name="Speaker - Output Jack", index=0
> Info: id=7, control=2, cmask=0x0, channels=1, type="BOOLEAN"
> Volume: min=0, max=1, dBmin=0, dBmax=0
> Unit: 13
> Control: name="PCM Playback Switch", index=0
> Info: id=13, control=1, cmask=0x0, channels=1, type="INV_BOOLEAN"
> Volume: min=0, max=1, dBmin=0, dBmax=0
> Unit: 17
> Control: name="Mic Capture Switch", index=0
> Info: id=17, control=1, cmask=0x0, channels=1, type="INV_BOOLEAN"
> Volume: min=0, max=1, dBmin=0, dBmax=0
> Unit: 18
> Control: name="Clock Source 18 Validity", index=0
> Info: id=18, control=2, cmask=0x0, channels=1, type="BOOLEAN"
> Volume: min=0, max=1, dBmin=0, dBmax=0
> Unit: 22
> Control: name="Clock Source 22 Validity", index=0
> Info: id=22, control=2, cmask=0x0, channels=1, type="BOOLEAN"
> Volume: min=0, max=1, dBmin=0, dBmax=0

Hm, I expected more exotic control that failed, but it was Mic Capture
Switch, which should be treated normally.

Could you try the patch below? This will still show other warning
messages, but it'll forcibly initialize the mixer elements at probe
time, and the rest should work.

Once after it's confirmed to work, we may shut up the device warnings
with a quirk.

thanks,

Takashi

--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -361,9 +361,8 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,

memset(buf, 0, sizeof(buf));

- ret = snd_usb_lock_shutdown(chip) ? -EIO : 0;
- if (ret)
- goto error;
+ if (snd_usb_lock_shutdown(chip))
+ return -EIO;

idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8);
ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
@@ -372,8 +371,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,
snd_usb_unlock_shutdown(chip);

if (ret < 0) {
-error:
- usb_audio_err(chip,
+ usb_audio_dbg(chip,
"cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
request, validx, idx, cval->val_type);
return ret;
@@ -1201,12 +1199,32 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
}
}

+/* forcibly initialize the current mixer value; if GET_CUR fails, set to
+ * the minimum as default
+ */
+static void init_cur_mix_raw(struct usb_mixer_elem_info *cval, int ch, int idx)
+{
+ int val, err;
+
+ err = snd_usb_get_cur_mix_value(cval, ch, idx, &val);
+ if (!err)
+ return;
+ if (!cval->head.mixer->ignore_ctl_error)
+ usb_audio_warn(cval->head.mixer->chip,
+ "%d:%d: failed to get current value for ch %d (%d)\n",
+ cval->head.id, mixer_ctrl_intf(cval->head.mixer),
+ ch, err);
+ snd_usb_set_cur_mix_value(cval, ch, idx, cval->min);
+}
+
/*
* retrieve the minimum and maximum values for the specified control
*/
static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
int default_min, struct snd_kcontrol *kctl)
{
+ int i, idx;
+
/* for failsafe */
cval->min = default_min;
cval->max = cval->min + 1;
@@ -1219,7 +1237,6 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
} else {
int minchn = 0;
if (cval->cmask) {
- int i;
for (i = 0; i < MAX_CHANNELS; i++)
if (cval->cmask & (1 << i)) {
minchn = i + 1;
@@ -1320,6 +1337,19 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
}
}

+ /* initialize all elements */
+ if (!cval->cmask) {
+ init_cur_mix_raw(cval, 0, 0);
+ } else {
+ idx = 0;
+ for (i = 0; i < MAX_CHANNELS; i++) {
+ if (cval->cmask & (1 << i)) {
+ init_cur_mix_raw(cval, i + 1, idx);
+ idx++;
+ }
+ }
+ }
+
return 0;
}