Skip to content

Commit 41c25e1

Browse files
committed
ALSA: usb-audio: More relaxed check of MIDI jack names
The USB audio driver tries to retrieve MIDI jack name strings that can be used for rawmidi substream names and sequencer port names, but its checking is too strict: often the firmware provides the jack info for unexpected directions, and then we miss the info although it's present. In this patch, the code to extract the jack info is changed to allow both in and out directions in a single loop. That is, the former two functions to obtain the descriptor pointers for jack in and out are changed to a single function that returns iJack of the corresponding jack ID, no matter which direction is used. It's a code simplification at the same time as well as the fix. Fixes: eb596e0 ("ALSA: usb-audio: generate midi streaming substream names from jack names") Link: https://lore.kernel.org/r/20240215153144.26047-1-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 32f03f4 commit 41c25e1

File tree

1 file changed

+25
-48
lines changed

1 file changed

+25
-48
lines changed

sound/usb/midi.c

Lines changed: 25 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,50 +1742,44 @@ static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number,
17421742
}
17431743
}
17441744

1745-
static struct usb_midi_in_jack_descriptor *find_usb_in_jack_descriptor(
1746-
struct usb_host_interface *hostif, uint8_t jack_id)
1745+
/* return iJack for the corresponding jackID */
1746+
static int find_usb_ijack(struct usb_host_interface *hostif, uint8_t jack_id)
17471747
{
17481748
unsigned char *extra = hostif->extra;
17491749
int extralen = hostif->extralen;
1750+
struct usb_descriptor_header *h;
1751+
struct usb_midi_out_jack_descriptor *outjd;
1752+
struct usb_midi_in_jack_descriptor *injd;
1753+
size_t sz;
17501754

17511755
while (extralen > 4) {
1752-
struct usb_midi_in_jack_descriptor *injd =
1753-
(struct usb_midi_in_jack_descriptor *)extra;
1756+
h = (struct usb_descriptor_header *)extra;
1757+
if (h->bDescriptorType != USB_DT_CS_INTERFACE)
1758+
goto next;
17541759

1760+
outjd = (struct usb_midi_out_jack_descriptor *)h;
1761+
if (h->bLength >= sizeof(*outjd) &&
1762+
outjd->bDescriptorSubtype == UAC_MIDI_OUT_JACK &&
1763+
outjd->bJackID == jack_id) {
1764+
sz = USB_DT_MIDI_OUT_SIZE(outjd->bNrInputPins);
1765+
if (outjd->bLength < sz)
1766+
goto next;
1767+
return *(extra + sz - 1);
1768+
}
1769+
1770+
injd = (struct usb_midi_in_jack_descriptor *)h;
17551771
if (injd->bLength >= sizeof(*injd) &&
1756-
injd->bDescriptorType == USB_DT_CS_INTERFACE &&
17571772
injd->bDescriptorSubtype == UAC_MIDI_IN_JACK &&
1758-
injd->bJackID == jack_id)
1759-
return injd;
1760-
if (!extra[0])
1761-
break;
1762-
extralen -= extra[0];
1763-
extra += extra[0];
1764-
}
1765-
return NULL;
1766-
}
1767-
1768-
static struct usb_midi_out_jack_descriptor *find_usb_out_jack_descriptor(
1769-
struct usb_host_interface *hostif, uint8_t jack_id)
1770-
{
1771-
unsigned char *extra = hostif->extra;
1772-
int extralen = hostif->extralen;
1773+
injd->bJackID == jack_id)
1774+
return injd->iJack;
17731775

1774-
while (extralen > 4) {
1775-
struct usb_midi_out_jack_descriptor *outjd =
1776-
(struct usb_midi_out_jack_descriptor *)extra;
1777-
1778-
if (outjd->bLength >= sizeof(*outjd) &&
1779-
outjd->bDescriptorType == USB_DT_CS_INTERFACE &&
1780-
outjd->bDescriptorSubtype == UAC_MIDI_OUT_JACK &&
1781-
outjd->bJackID == jack_id)
1782-
return outjd;
1776+
next:
17831777
if (!extra[0])
17841778
break;
17851779
extralen -= extra[0];
17861780
extra += extra[0];
17871781
}
1788-
return NULL;
1782+
return 0;
17891783
}
17901784

17911785
static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi,
@@ -1796,13 +1790,10 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi,
17961790
const char *name_format;
17971791
struct usb_interface *intf;
17981792
struct usb_host_interface *hostif;
1799-
struct usb_midi_in_jack_descriptor *injd;
1800-
struct usb_midi_out_jack_descriptor *outjd;
18011793
uint8_t jack_name_buf[32];
18021794
uint8_t *default_jack_name = "MIDI";
18031795
uint8_t *jack_name = default_jack_name;
18041796
uint8_t iJack;
1805-
size_t sz;
18061797
int res;
18071798

18081799
struct snd_rawmidi_substream *substream =
@@ -1816,21 +1807,7 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi,
18161807
intf = umidi->iface;
18171808
if (intf && jack_id >= 0) {
18181809
hostif = intf->cur_altsetting;
1819-
iJack = 0;
1820-
if (stream != SNDRV_RAWMIDI_STREAM_OUTPUT) {
1821-
/* in jacks connect to outs */
1822-
outjd = find_usb_out_jack_descriptor(hostif, jack_id);
1823-
if (outjd) {
1824-
sz = USB_DT_MIDI_OUT_SIZE(outjd->bNrInputPins);
1825-
if (outjd->bLength >= sz)
1826-
iJack = *(((uint8_t *) outjd) + sz - sizeof(uint8_t));
1827-
}
1828-
} else {
1829-
/* and out jacks connect to ins */
1830-
injd = find_usb_in_jack_descriptor(hostif, jack_id);
1831-
if (injd)
1832-
iJack = injd->iJack;
1833-
}
1810+
iJack = find_usb_ijack(hostif, jack_id);
18341811
if (iJack != 0) {
18351812
res = usb_string(umidi->dev, iJack, jack_name_buf,
18361813
ARRAY_SIZE(jack_name_buf));

0 commit comments

Comments
 (0)