From 59e5559dad7ab60f0dd87714d7f52bfc42dd1931 Mon Sep 17 00:00:00 2001 From: hselasky Date: Sun, 28 Sep 2014 12:55:13 +0000 Subject: [PATCH] Instead of creating the full range of possible ports, try to figure out the actual number of so-called "embedded jacks" which are present when a USB MIDI device is attaching. MFC after: 3 days --- sys/dev/sound/usb/uaudio.c | 59 ++++++++++++++++++++++------------- sys/dev/sound/usb/uaudioreg.h | 8 +++++ 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c index b24a6399872a..3d48abca05c6 100644 --- a/sys/dev/sound/usb/uaudio.c +++ b/sys/dev/sound/usb/uaudio.c @@ -232,7 +232,7 @@ struct uaudio_chan { #define UAUDIO_SYNC_LESS 2 }; -#define UMIDI_CABLES_MAX 16 /* units */ +#define UMIDI_EMB_JACK_MAX 16 /* units */ #define UMIDI_TX_FRAMES 256 /* units */ #define UMIDI_TX_BUFFER (UMIDI_TX_FRAMES * 4) /* bytes */ @@ -263,7 +263,7 @@ struct umidi_sub_chan { struct umidi_chan { - struct umidi_sub_chan sub[UMIDI_CABLES_MAX]; + struct umidi_sub_chan sub[UMIDI_EMB_JACK_MAX]; struct mtx mtx; struct usb_xfer *xfer[UMIDI_N_TRANSFER]; @@ -275,7 +275,7 @@ struct umidi_chan { uint8_t write_open_refcount; uint8_t curr_cable; - uint8_t max_cable; + uint8_t max_emb_jack; uint8_t valid; uint8_t single_command; }; @@ -1481,6 +1481,7 @@ uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb_device *udev, union uaudio_asid asid = { NULL }; union uaudio_asf1d asf1d = { NULL }; union uaudio_sed sed = { NULL }; + struct usb_midi_streaming_endpoint_descriptor *msid = NULL; usb_endpoint_descriptor_audio_t *ed1 = NULL; const struct usb_audio_control_descriptor *acdp = NULL; struct usb_config_descriptor *cd = usbd_get_config_descriptor(udev); @@ -1498,6 +1499,7 @@ uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb_device *udev, uint8_t bChannels; uint8_t bBitResolution; uint8_t audio_if = 0; + uint8_t midi_if = 0; uint8_t uma_if_class; while ((desc = usb_desc_foreach(cd, desc))) { @@ -1533,7 +1535,8 @@ uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb_device *udev, ((id->bInterfaceClass == UICLASS_VENDOR) && (sc->sc_uq_au_vendor_class != 0))); - if ((uma_if_class != 0) && (id->bInterfaceSubClass == UISUBCLASS_AUDIOSTREAM)) { + if ((uma_if_class != 0) && + (id->bInterfaceSubClass == UISUBCLASS_AUDIOSTREAM)) { audio_if = 1; } else { audio_if = 0; @@ -1545,13 +1548,16 @@ uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb_device *udev, /* * XXX could allow multiple MIDI interfaces */ + midi_if = 1; if ((sc->sc_midi_chan.valid == 0) && - usbd_get_iface(udev, curidx)) { + (usbd_get_iface(udev, curidx) != NULL)) { sc->sc_midi_chan.iface_index = curidx; sc->sc_midi_chan.iface_alt_index = alt_index; sc->sc_midi_chan.valid = 1; } + } else { + midi_if = 0; } asid.v1 = NULL; asf1d.v1 = NULL; @@ -1560,14 +1566,25 @@ uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb_device *udev, } if (audio_if == 0) { - if ((acdp == NULL) && - (desc->bDescriptorType == UDESC_CS_INTERFACE) && - (desc->bDescriptorSubtype == UDESCSUB_AC_HEADER) && - (desc->bLength >= sizeof(*acdp))) { - acdp = (void *)desc; - audio_rev = UGETW(acdp->bcdADC); - } + if (midi_if == 0) { + if ((acdp == NULL) && + (desc->bDescriptorType == UDESC_CS_INTERFACE) && + (desc->bDescriptorSubtype == UDESCSUB_AC_HEADER) && + (desc->bLength >= sizeof(*acdp))) { + acdp = (void *)desc; + audio_rev = UGETW(acdp->bcdADC); + } + } else { + msid = (void *)desc; + /* get the maximum number of embedded jacks in use, if any */ + if (msid->bLength >= sizeof(*msid) && + msid->bDescriptorType == UDESC_CS_ENDPOINT && + msid->bDescriptorSubtype == MS_GENERAL && + msid->bNumEmbMIDIJack > sc->sc_midi_chan.max_emb_jack) { + sc->sc_midi_chan.max_emb_jack = msid->bNumEmbMIDIJack; + } + } /* * Don't collect any USB audio descriptors if * this is not an USB audio stream interface. @@ -5219,8 +5236,7 @@ umidi_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) */ sub = &chan->sub[cn]; - if ((cmd_len != 0) && - (cn < chan->max_cable) && + if ((cmd_len != 0) && (cn < chan->max_emb_jack) && (sub->read_open != 0)) { /* Send data to the application */ @@ -5456,7 +5472,7 @@ umidi_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) } chan->curr_cable++; - if (chan->curr_cable >= chan->max_cable) + if (chan->curr_cable >= chan->max_emb_jack) chan->curr_cable = 0; if (chan->curr_cable == start_cable) { @@ -5493,7 +5509,7 @@ umidi_sub_by_fifo(struct usb_fifo *fifo) struct umidi_sub_chan *sub; uint32_t n; - for (n = 0; n < UMIDI_CABLES_MAX; n++) { + for (n = 0; n < UMIDI_EMB_JACK_MAX; n++) { sub = &chan->sub[n]; if ((sub->fifo.fp[USB_FIFO_RX] == fifo) || (sub->fifo.fp[USB_FIFO_TX] == fifo)) { @@ -5676,12 +5692,12 @@ umidi_probe(device_t dev) if (chan->single_command != 0) device_printf(dev, "Single command MIDI quirk enabled\n"); - if ((chan->max_cable > UMIDI_CABLES_MAX) || - (chan->max_cable == 0)) { - chan->max_cable = UMIDI_CABLES_MAX; + if ((chan->max_emb_jack == 0) || + (chan->max_emb_jack > UMIDI_EMB_JACK_MAX)) { + chan->max_emb_jack = UMIDI_EMB_JACK_MAX; } - for (n = 0; n < chan->max_cable; n++) { + for (n = 0; n < chan->max_emb_jack; n++) { sub = &chan->sub[n]; @@ -5719,9 +5735,8 @@ umidi_detach(device_t dev) struct umidi_chan *chan = &sc->sc_midi_chan; uint32_t n; - for (n = 0; n < UMIDI_CABLES_MAX; n++) { + for (n = 0; n < UMIDI_EMB_JACK_MAX; n++) usb_fifo_detach(&chan->sub[n].fifo); - } mtx_lock(&chan->mtx); diff --git a/sys/dev/sound/usb/uaudioreg.h b/sys/dev/sound/usb/uaudioreg.h index c2c1ad4b077f..637b5b1c0f23 100644 --- a/sys/dev/sound/usb/uaudioreg.h +++ b/sys/dev/sound/usb/uaudioreg.h @@ -119,6 +119,13 @@ struct usb_audio_streaming_endpoint_descriptor { uWord wLockDelay; } __packed; +struct usb_midi_streaming_endpoint_descriptor { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bNumEmbMIDIJack; +} __packed; + struct usb_audio_streaming_type1_descriptor { uByte bLength; uByte bDescriptorType; @@ -378,6 +385,7 @@ struct usb_audio_extension_unit_1 { #define MASTER_CHAN 0 +#define MS_GENERAL 1 #define AS_GENERAL 1 #define FORMAT_TYPE 2 #define FORMAT_SPECIFIC 3