[alsa-devel] ALSA: usb-audio: work around Anroid accessory firmware bug

Takashi Iwai tiwai at suse.de
Mon Jun 17 09:59:35 CEST 2013


At Sat, 15 Jun 2013 11:21:09 +0200,
Clemens Ladisch wrote:
> 
> When the Android firmware enables the audio interfaces in accessory
> mode, it always declares in the control interface's baInterfaceNr array
> that interfaces 0 and 1 belong to the audio function.  However, the
> accessory interface itself, if also enabled, already is at index 0 and
> shifts the actual audio interface numbers to 1 and 2, which prevents the
> PCM streaming interface from being seen by the host driver.
> 
> To get the PCM interface interface to work, detect when the descriptors
> point to the (for this driver useless) accessory interface, and redirect
> to the correct one.
> 
> Reported-by: Jeremy Rosen <jeremy.rosen at openwide.fr>
> Tested-by: Jeremy Rosen <jeremy.rosen at openwide.fr>
> Cc: <stable at vger.kernel.org>
> Signed-off-by: Clemens Ladisch <clemens at ladisch.de>

Thanks, applied (with a typo correction of the subject line :)


Takashi

> ---
>  sound/usb/card.c |   22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/sound/usb/card.c b/sound/usb/card.c
> index 563854a..5a5153c 100644
> --- a/sound/usb/card.c
> +++ b/sound/usb/card.c
> @@ -148,14 +148,32 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
>  		return -EINVAL;
>  	}
> 
> +	alts = &iface->altsetting[0];
> +	altsd = get_iface_desc(alts);
> +
> +	/*
> +	 * Android with both accessory and audio interfaces enabled gets the
> +	 * interface numbers wrong.
> +	 */
> +	if ((chip->usb_id == USB_ID(0x18d1, 0x2d04) ||
> +	     chip->usb_id == USB_ID(0x18d1, 0x2d05)) &&
> +	    interface == 0 &&
> +	    altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
> +	    altsd->bInterfaceSubClass == USB_SUBCLASS_VENDOR_SPEC) {
> +		interface = 2;
> +		iface = usb_ifnum_to_if(dev, interface);
> +		if (!iface)
> +			return -EINVAL;
> +		alts = &iface->altsetting[0];
> +		altsd = get_iface_desc(alts);
> +	}
> +
>  	if (usb_interface_claimed(iface)) {
>  		snd_printdd(KERN_INFO "%d:%d:%d: skipping, already claimed\n",
>  						dev->devnum, ctrlif, interface);
>  		return -EINVAL;
>  	}
> 
> -	alts = &iface->altsetting[0];
> -	altsd = get_iface_desc(alts);
>  	if ((altsd->bInterfaceClass == USB_CLASS_AUDIO ||
>  	     altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
>  	    altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) {
> 


More information about the Alsa-devel mailing list