[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