Skip to content

Commit 342cda2

Browse files
cladischtiwai
authored andcommitted
ALSA: usb-audio: work around Android accessory firmware bug
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 <[email protected]> Tested-by: Jeremy Rosen <[email protected]> Cc: <[email protected]> Signed-off-by: Clemens Ladisch <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent d81bf8c commit 342cda2

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

sound/usb/card.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,32 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
147147
return -EINVAL;
148148
}
149149

150+
alts = &iface->altsetting[0];
151+
altsd = get_iface_desc(alts);
152+
153+
/*
154+
* Android with both accessory and audio interfaces enabled gets the
155+
* interface numbers wrong.
156+
*/
157+
if ((chip->usb_id == USB_ID(0x18d1, 0x2d04) ||
158+
chip->usb_id == USB_ID(0x18d1, 0x2d05)) &&
159+
interface == 0 &&
160+
altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
161+
altsd->bInterfaceSubClass == USB_SUBCLASS_VENDOR_SPEC) {
162+
interface = 2;
163+
iface = usb_ifnum_to_if(dev, interface);
164+
if (!iface)
165+
return -EINVAL;
166+
alts = &iface->altsetting[0];
167+
altsd = get_iface_desc(alts);
168+
}
169+
150170
if (usb_interface_claimed(iface)) {
151171
snd_printdd(KERN_INFO "%d:%d:%d: skipping, already claimed\n",
152172
dev->devnum, ctrlif, interface);
153173
return -EINVAL;
154174
}
155175

156-
alts = &iface->altsetting[0];
157-
altsd = get_iface_desc(alts);
158176
if ((altsd->bInterfaceClass == USB_CLASS_AUDIO ||
159177
altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
160178
altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) {

0 commit comments

Comments
 (0)