From owner-freebsd-multimedia@FreeBSD.ORG Thu May 17 06:46:37 2012 Return-Path: Delivered-To: freebsd-multimedia@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 61C37106566B for ; Thu, 17 May 2012 06:46:37 +0000 (UTC) (envelope-from guru@unixarea.de) Received: from ms16-1.1blu.de (ms16-1.1blu.de [89.202.0.34]) by mx1.freebsd.org (Postfix) with ESMTP id 9C7428FC12 for ; Thu, 17 May 2012 06:46:36 +0000 (UTC) Received: from [88.217.85.60] (helo=localhost.my.domain) by ms16-1.1blu.de with esmtpsa (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1SUuTr-0002hw-6F for freebsd-multimedia@freebsd.org; Thu, 17 May 2012 08:46:35 +0200 Received: from localhost.my.domain (localhost [127.0.0.1]) by localhost.my.domain (8.14.4/8.14.3) with ESMTP id q4H6kXUt002714 for ; Thu, 17 May 2012 08:46:33 +0200 (CEST) (envelope-from guru@unixarea.de) Received: (from guru@localhost) by localhost.my.domain (8.14.4/8.14.3/Submit) id q4H6kXNf002713 for freebsd-multimedia@freebsd.org; Thu, 17 May 2012 08:46:33 +0200 (CEST) (envelope-from guru@unixarea.de) X-Authentication-Warning: localhost.my.domain: guru set sender to guru@unixarea.de using -f Date: Thu, 17 May 2012 08:46:32 +0200 From: Matthias Apitz To: freebsd-multimedia@freebsd.org Message-ID: <20120517064632.GA2670@tinyCurrent> References: <20120513155939.GA4313@tinyCurrent> <201205131911.18787.hselasky@c2i.net> <20120514051026.GA2711@tinyCurrent> <201205141721.25641.hselasky@c2i.net> <20120516160807.GA2246@tinyCurrent> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="3V7upXqbjpZ4EhLz" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20120516160807.GA2246@tinyCurrent> X-Operating-System: FreeBSD 9.0-CURRENT r214444 (i386) User-Agent: Mutt/1.5.21 (2010-09-15) X-Con-Id: 51246 X-Con-U: 0-guru X-Originating-IP: 88.217.85.60 Subject: Re: Logitech HD Webcam Pro c910 && snd_uaudio does not work X-BeenThere: freebsd-multimedia@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Matthias Apitz List-Id: Multimedia discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 May 2012 06:46:37 -0000 --3V7upXqbjpZ4EhLz Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit El día Wednesday, May 16, 2012 a las 06:08:07PM +0200, Matthias Apitz escribió: > This gives the following messages: > > on plug-in: > > May 16 18:00:36 tinyCurrent kernel: pcm1: on uaudio0 > May 16 18:00:36 tinyCurrent kernel: uaudio_attach_sub: emulating master volume > May 16 18:00:36 tinyCurrent kernel: uaudio_mixer_init_sub: > May 16 18:00:36 tinyCurrent kernel: uaudio_mixer_bsd2value: type=0x002 val=-18176 min=-18176 max=-4864 val=-18176 > May 16 18:00:36 tinyCurrent kernel: uaudio_mixer_write_cfg_callback: > May 16 18:00:36 tinyCurrent kernel: uaudio_mixer_write_cfg_callback: > May 16 18:00:36 tinyCurrent kernel: uaudio_chan_init: endpoint=0x86, > speed=32000, iface=1 alt=3 > May 16 18:00:36 tinyCurrent kernel: uaudio_chan_init: fps=1000 sample_rem=0 > May 16 18:00:36 tinyCurrent root: /usr/local/etc/rc.d/webcamd: WARNING: failed to start webcamd > May 16 18:00:36 tinyCurrent root: Unknown USB device: vendor 0x046d product 0x0821 bus uhub4 > May 16 18:00:37 tinyCurrent last message repeated 2 times > > (now started in another window dd if=/dev/dsp1.0 of=/tmp/snd) > > > May 16 18:02:08 tinyCurrent kernel: uaudio_chan_record_callback: transferred 0 bytes > May 16 18:02:13 tinyCurrent last message repeated 623 times > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > May 16 18:02:13 tinyCurrent kernel: pcm1: chn_read(): pcm1:virtual:dsp1.vr0: record interrupt timeout, channel dead I have had a look into the kernel sources... the message 'uaudio_chan_record_callback: transferred 0 bytes' comes from /usr/src.r214444/sys/dev/sound/usb/uaudio.c and if I svn diff this with the kernel r226986 where the micro of the cam is working # svn diff -r226986 uaudio.c > /tmp/uaudio.c-r214444-r226986 there are substantial changes in the source (diff attached); I think I should just update this laptop to a more recent version.... matthias -- Matthias Apitz t +49-89-61308 351 - f +49-89-61308 399 - m +49-170-4527211 e - w http://www.unixarea.de/ UNIX since V7 on PDP-11 | UNIX on mainframe since ESER 1055 (IBM /370) UNIX on x86 since SVR4.2 UnixWare 2.1.2 | FreeBSD since 2.2.5 --3V7upXqbjpZ4EhLz Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="uaudio.c-r214444-r226986" Content-Transfer-Encoding: 8bit Index: uaudio.c =================================================================== --- uaudio.c (revisión: 226986) +++ uaudio.c (copia de trabajo) @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -191,16 +192,10 @@ uint8_t iface_alt_index; }; +#define UMIDI_N_TRANSFER 4 /* units */ #define UMIDI_CABLES_MAX 16 /* units */ -#define UMIDI_TX_FRAMES 256 /* units */ -#define UMIDI_TX_BUFFER (UMIDI_TX_FRAMES * 4) /* bytes */ +#define UMIDI_BULK_SIZE 1024 /* bytes */ -enum { - UMIDI_TX_TRANSFER, - UMIDI_RX_TRANSFER, - UMIDI_N_TRANSFER, -}; - struct umidi_sub_chan { struct usb_fifo_sc fifo; uint8_t *temp_cmd; @@ -230,13 +225,16 @@ uint8_t iface_index; uint8_t iface_alt_index; + uint8_t flags; +#define UMIDI_FLAG_READ_STALL 0x01 +#define UMIDI_FLAG_WRITE_STALL 0x02 + uint8_t read_open_refcount; uint8_t write_open_refcount; uint8_t curr_cable; uint8_t max_cable; uint8_t valid; - uint8_t single_command; }; struct uaudio_softc { @@ -267,7 +265,6 @@ uint8_t sc_uq_au_inp_async:1; uint8_t sc_uq_au_no_xu:1; uint8_t sc_uq_bad_adc:1; - uint8_t sc_uq_au_vendor_class:1; }; struct uaudio_search_result { @@ -340,7 +337,9 @@ static usb_callback_t uaudio_chan_play_callback; static usb_callback_t uaudio_chan_record_callback; static usb_callback_t uaudio_mixer_write_cfg_callback; +static usb_callback_t umidi_read_clear_stall_callback; static usb_callback_t umidi_bulk_read_callback; +static usb_callback_t umidi_write_clear_stall_callback; static usb_callback_t umidi_bulk_write_callback; static void uaudio_chan_fill_info_sub(struct uaudio_softc *, @@ -404,8 +403,8 @@ static int umidi_ioctl(struct usb_fifo *, u_long cmd, void *, int); static void umidi_close(struct usb_fifo *, int); static void umidi_init(device_t dev); -static int umidi_probe(device_t dev); -static int umidi_detach(device_t dev); +static int32_t umidi_probe(device_t dev); +static int32_t umidi_detach(device_t dev); #ifdef USB_DEBUG static void uaudio_chan_dump_ep_desc( @@ -495,22 +494,43 @@ static const struct usb_config umidi_config[UMIDI_N_TRANSFER] = { - [UMIDI_TX_TRANSFER] = { + [0] = { .type = UE_BULK, .endpoint = UE_ADDR_ANY, .direction = UE_DIR_OUT, - .bufsize = UMIDI_TX_BUFFER, + .bufsize = UMIDI_BULK_SIZE, + .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, .callback = &umidi_bulk_write_callback, }, - [UMIDI_RX_TRANSFER] = { + [1] = { .type = UE_BULK, .endpoint = UE_ADDR_ANY, .direction = UE_DIR_IN, .bufsize = 4, /* bytes */ - .flags = {.short_xfer_ok = 1,.proxy_buffer = 1,}, + .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,}, .callback = &umidi_bulk_read_callback, }, + + [2] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .bufsize = sizeof(struct usb_device_request), + .callback = &umidi_write_clear_stall_callback, + .timeout = 1000, /* 1 second */ + .interval = 50, /* 50ms */ + }, + + [3] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = UE_DIR_ANY, + .bufsize = sizeof(struct usb_device_request), + .callback = &umidi_read_clear_stall_callback, + .timeout = 1000, /* 1 second */ + .interval = 50, /* 50ms */ + }, }; static devclass_t uaudio_devclass; @@ -532,15 +552,6 @@ .size = sizeof(struct uaudio_softc), }; -static const STRUCT_USB_HOST_ID __used uaudio_devs[] = { - /* Generic USB audio class match */ - {USB_IFACE_CLASS(UICLASS_AUDIO), - USB_IFACE_SUBCLASS(UISUBCLASS_AUDIOCONTROL),}, - /* Generic USB MIDI class match */ - {USB_IFACE_CLASS(UICLASS_AUDIO), - USB_IFACE_SUBCLASS(UISUBCLASS_MIDISTREAM),}, -}; - static int uaudio_probe(device_t dev) { @@ -549,29 +560,24 @@ if (uaa->usb_mode != USB_MODE_HOST) return (ENXIO); - /* lookup non-standard device */ + if (uaa->use_generic == 0) + return (ENXIO); - if (uaa->info.bInterfaceClass != UICLASS_AUDIO) { - if (usb_test_quirk(uaa, UQ_AU_VENDOR_CLASS) == 0) - return (ENXIO); - } + /* trigger on the control interface */ - /* check for AUDIO control interface */ - - if (uaa->info.bInterfaceSubClass == UISUBCLASS_AUDIOCONTROL) { + if ((uaa->info.bInterfaceClass == UICLASS_AUDIO) && + (uaa->info.bInterfaceSubClass == UISUBCLASS_AUDIOCONTROL)) { if (usb_test_quirk(uaa, UQ_BAD_AUDIO)) return (ENXIO); else - return (BUS_PROBE_GENERIC); + return (0); } /* check for MIDI stream */ - if (uaa->info.bInterfaceSubClass == UISUBCLASS_MIDISTREAM) { - if (usb_test_quirk(uaa, UQ_BAD_MIDI)) - return (ENXIO); - else - return (BUS_PROBE_GENERIC); + if ((uaa->info.bInterfaceClass == UICLASS_AUDIO) && + (uaa->info.bInterfaceSubClass == UISUBCLASS_MIDISTREAM)) { + return (0); } return (ENXIO); } @@ -602,9 +608,6 @@ if (usb_test_quirk(uaa, UQ_BAD_ADC)) sc->sc_uq_bad_adc = 1; - if (usb_test_quirk(uaa, UQ_AU_VENDOR_CLASS)) - sc->sc_uq_au_vendor_class = 1; - umidi_init(dev); device_set_usb_desc(dev); @@ -796,47 +799,7 @@ #endif -/* - * The following is a workaround for broken no-name USB audio devices - * sold by dealextreme called "3D sound". The problem is that the - * manufacturer computed wMaxPacketSize is too small to hold the - * actual data sent. In other words the device sometimes sends more - * data than it actually reports it can send in a single isochronous - * packet. - */ static void -uaudio_record_fix_fs(usb_endpoint_descriptor_audio_t *ep, - uint32_t xps, uint32_t add) -{ - uint32_t mps; - - mps = UGETW(ep->wMaxPacketSize); - - /* - * If the device indicates it can send more data than what the - * sample rate indicates, we apply the workaround. - */ - if (mps > xps) { - - /* allow additional data */ - xps += add; - - /* check against the maximum USB 1.x length */ - if (xps > 1023) - xps = 1023; - - /* check if we should do an update */ - if (mps < xps) { - /* simply update the wMaxPacketSize field */ - USETW(ep->wMaxPacketSize, xps); - DPRINTF("Workaround: Updated wMaxPacketSize " - "from %d to %d bytes.\n", - (int)mps, (int)xps); - } - } -} - -static void uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb_device *udev, uint32_t rate, uint8_t channels, uint8_t bit_resolution) { @@ -844,7 +807,7 @@ const struct usb_audio_streaming_interface_descriptor *asid = NULL; const struct usb_audio_streaming_type1_descriptor *asf1d = NULL; const struct usb_audio_streaming_endpoint_descriptor *sed = NULL; - usb_endpoint_descriptor_audio_t *ed1 = NULL; + const usb_endpoint_descriptor_audio_t *ed1 = NULL; const usb_endpoint_descriptor_audio_t *ed2 = NULL; struct usb_config_descriptor *cd = usbd_get_config_descriptor(udev); struct usb_interface_descriptor *id; @@ -859,7 +822,6 @@ uint8_t bBitResolution; uint8_t x; uint8_t audio_if = 0; - uint8_t uma_if_class; while ((desc = usb_desc_foreach(cd, desc))) { @@ -877,22 +839,19 @@ alt_index++; } - uma_if_class = - ((id->bInterfaceClass == UICLASS_AUDIO) || - ((id->bInterfaceClass == UICLASS_VENDOR) && - (sc->sc_uq_au_vendor_class != 0))); - - if ((uma_if_class != 0) && (id->bInterfaceSubClass == UISUBCLASS_AUDIOSTREAM)) { + if ((id->bInterfaceClass == UICLASS_AUDIO) && + (id->bInterfaceSubClass == UISUBCLASS_AUDIOSTREAM)) { audio_if = 1; } else { audio_if = 0; } - if ((uma_if_class != 0) && + if ((id->bInterfaceClass == UICLASS_AUDIO) && (id->bInterfaceSubClass == UISUBCLASS_MIDISTREAM)) { /* * XXX could allow multiple MIDI interfaces + * XXX */ if ((sc->sc_midi_chan.valid == 0) && @@ -927,8 +886,8 @@ continue; } if (asf1d->bLength < (sizeof(*asf1d) + - ((asf1d->bSamFreqType == 0) ? 6 : - (asf1d->bSamFreqType * 3)))) { + (asf1d->bSamFreqType == 0) ? 6 : + (asf1d->bSamFreqType * 3))) { DPRINTFN(11, "'asf1d' descriptor is too short\n"); asf1d = NULL; continue; @@ -1046,13 +1005,6 @@ UAUDIO_MAX_CHAN(chan->p_asf1d->bNrChannels) * chan->p_asf1d->bBitResolution) / 8); - if (ep_dir == UE_DIR_IN && - usbd_get_speed(udev) == USB_SPEED_FULL) { - uaudio_record_fix_fs(ed1, - chan->sample_size * (rate / 1000), - chan->sample_size * (rate / 4000)); - } - if (sc->sc_sndstat_valid) { sbuf_printf(&sc->sc_sndstat, "\n\t" "mode %d.%d:(%s) %dch, %d/%dbit, %s, %dHz", @@ -1410,14 +1362,14 @@ usbd_errstr(err)); goto error; } - usbd_set_parent_iface(sc->sc_udev, iface_index, - sc->sc_mixer_iface_index); + usbd_set_parent_iface(sc->sc_udev, iface_index, sc->sc_mixer_iface_index); /* - * Only set the sample rate if the channel reports that it - * supports the frequency control. + * If just one sampling rate is supported, + * no need to call "uaudio_set_speed()". + * Roland SD-90 freezes by a SAMPLING_FREQ_CONTROL request. */ - if (ch->p_sed->bmAttributes & UA_SED_FREQ_CONTROL) { + if (ch->p_asf1d->bSamFreqType != 1) { if (uaudio_set_speed(sc->sc_udev, endpoint, ch->sample_rate)) { /* * If the endpoint is adaptive setting the speed may @@ -1626,10 +1578,10 @@ uaudio_mixer_add_ctl_sub(struct uaudio_softc *sc, struct uaudio_mixer_node *mc) { struct uaudio_mixer_node *p_mc_new = - malloc(sizeof(*p_mc_new), M_USBDEV, M_WAITOK); + malloc(sizeof(*p_mc_new), M_USBDEV, M_WAITOK); - if (p_mc_new != NULL) { - memcpy(p_mc_new, mc, sizeof(*p_mc_new)); + if (p_mc_new) { + bcopy(mc, p_mc_new, sizeof(*p_mc_new)); p_mc_new->next = sc->sc_mixer_root; sc->sc_mixer_root = p_mc_new; sc->sc_mixer_count++; @@ -1771,7 +1723,7 @@ DPRINTFN(3, "ichs=%d ochs=%d\n", ichs, ochs); - memset(&mix, 0, sizeof(mix)); + bzero(&mix, sizeof(mix)); mix.wIndex = MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no); uaudio_mixer_determine_class(&iot[id], &mix); @@ -1831,7 +1783,7 @@ if (d->bNrInPins == 0) { return; } - memset(&mix, 0, sizeof(mix)); + bzero(&mix, sizeof(mix)); mix.wIndex = MAKE_WORD(d->bUnitId, sc->sc_mixer_iface_no); mix.wValue[0] = MAKE_WORD(0, 0); @@ -1901,7 +1853,7 @@ if (d->bControlSize == 0) { return; } - memset(&mix, 0, sizeof(mix)); + bzero(&mix, sizeof(mix)); nchan = (d->bLength - 7) / d->bControlSize; mmask = uaudio_mixer_feature_get_bmaControls(d, 0); @@ -2035,7 +1987,7 @@ DPRINTF("no mode select\n"); return; } - memset(&mix, 0, sizeof(mix)); + bzero(&mix, sizeof(mix)); mix.wIndex = MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no); mix.nchan = 1; @@ -2061,7 +2013,7 @@ struct uaudio_mixer_node mix; uint16_t ptype; - memset(&mix, 0, sizeof(mix)); + bzero(&mix, sizeof(mix)); ptype = UGETW(d0->wProcessType); @@ -2116,7 +2068,7 @@ } if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) { - memset(&mix, 0, sizeof(mix)); + bzero(&mix, sizeof(mix)); mix.wIndex = MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no); mix.nchan = 1; @@ -2343,7 +2295,7 @@ } error: DPRINTF("bad data\n"); - memset(&r, 0, sizeof(r)); + bzero(&r, sizeof(r)); done: return (r); } @@ -3333,12 +3285,25 @@ *========================================================================*/ static void +umidi_read_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error) +{ + struct umidi_chan *chan = usbd_xfer_softc(xfer); + struct usb_xfer *xfer_other = chan->xfer[1]; + + if (usbd_clear_stall_callback(xfer, xfer_other)) { + DPRINTF("stall cleared\n"); + chan->flags &= ~UMIDI_FLAG_READ_STALL; + usbd_transfer_start(xfer_other); + } +} + +static void umidi_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) { struct umidi_chan *chan = usbd_xfer_softc(xfer); struct umidi_sub_chan *sub; struct usb_page_cache *pc; - uint8_t buf[4]; + uint8_t buf[1]; uint8_t cmd_len; uint8_t cn; uint16_t pos; @@ -3356,50 +3321,60 @@ while (actlen >= 4) { - /* copy out the MIDI data */ - usbd_copy_out(pc, pos, buf, 4); - /* command length */ - cmd_len = umidi_cmd_to_len[buf[0] & 0xF]; - /* cable number */ - cn = buf[0] >> 4; - /* - * Lookup sub-channel. The index is range - * checked below. - */ + usbd_copy_out(pc, pos, buf, 1); + + cmd_len = umidi_cmd_to_len[buf[0] & 0xF]; /* command length */ + cn = buf[0] >> 4; /* cable number */ sub = &chan->sub[cn]; - if ((cmd_len != 0) && - (cn < chan->max_cable) && - (sub->read_open != 0)) { - - /* Send data to the application */ - usb_fifo_put_data_linear( - sub->fifo.fp[USB_FIFO_RX], - buf + 1, cmd_len, 1); + if (cmd_len && (cn < chan->max_cable) && sub->read_open) { + usb_fifo_put_data(sub->fifo.fp[USB_FIFO_RX], pc, + pos + 1, cmd_len, 1); + } else { + /* ignore the command */ } + actlen -= 4; pos += 4; } case USB_ST_SETUP: DPRINTF("start\n"); -tr_setup: + + if (chan->flags & UMIDI_FLAG_READ_STALL) { + usbd_transfer_start(chan->xfer[3]); + return; + } usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); usbd_transfer_submit(xfer); - break; + return; default: DPRINTF("error=%s\n", usbd_errstr(error)); if (error != USB_ERR_CANCELLED) { /* try to clear stall first */ - usbd_xfer_set_stall(xfer); - goto tr_setup; + chan->flags |= UMIDI_FLAG_READ_STALL; + usbd_transfer_start(chan->xfer[3]); } - break; + return; + } } +static void +umidi_write_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error) +{ + struct umidi_chan *chan = usbd_xfer_softc(xfer); + struct usb_xfer *xfer_other = chan->xfer[0]; + + if (usbd_clear_stall_callback(xfer, xfer_other)) { + DPRINTF("stall cleared\n"); + chan->flags &= ~UMIDI_FLAG_WRITE_STALL; + usbd_transfer_start(xfer_other); + } +} + /* * The following statemachine, that converts MIDI commands to * USB MIDI packets, derives from Linux's usbmidi.c, which @@ -3528,8 +3503,6 @@ sub->temp_cmd = sub->temp_1; sub->state = UMIDI_ST_SYSEX_0; return (1); - default: - break; } } return (0); @@ -3542,7 +3515,7 @@ struct umidi_sub_chan *sub; struct usb_page_cache *pc; uint32_t actlen; - uint16_t nframes; + uint16_t total_length; uint8_t buf; uint8_t start_cable; uint8_t tr_any; @@ -3550,19 +3523,19 @@ usbd_xfer_status(xfer, &len, NULL, NULL, NULL); - /* - * NOTE: Some MIDI devices only accept 4 bytes of data per - * short terminated USB transfer. - */ switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: DPRINTF("actlen=%d bytes\n", len); case USB_ST_SETUP: -tr_setup: + DPRINTF("start\n"); - nframes = 0; /* reset */ + if (chan->flags & UMIDI_FLAG_WRITE_STALL) { + usbd_transfer_start(chan->xfer[2]); + return; + } + total_length = 0; /* reset */ start_cable = chan->curr_cable; tr_any = 0; pc = usbd_xfer_get_frame(xfer, 0); @@ -3574,53 +3547,54 @@ sub = &chan->sub[chan->curr_cable]; if (sub->write_open) { - usb_fifo_get_data_linear(sub->fifo.fp[USB_FIFO_TX], - &buf, 1, &actlen, 0); + usb_fifo_get_data(sub->fifo.fp[USB_FIFO_TX], + pc, total_length, 1, &actlen, 0); } else { actlen = 0; } if (actlen) { + usbd_copy_out(pc, total_length, &buf, 1); tr_any = 1; - DPRINTF("byte=0x%02x from FIFO %u\n", buf, - (unsigned int)chan->curr_cable); + DPRINTF("byte=0x%02x\n", buf); if (umidi_convert_to_usb(sub, chan->curr_cable, buf)) { - DPRINTF("sub=0x%02x 0x%02x 0x%02x 0x%02x\n", + DPRINTF("sub= %02x %02x %02x %02x\n", sub->temp_cmd[0], sub->temp_cmd[1], sub->temp_cmd[2], sub->temp_cmd[3]); - usbd_copy_in(pc, nframes * 4, sub->temp_cmd, 4); + usbd_copy_in(pc, total_length, + sub->temp_cmd, 4); - nframes++; + total_length += 4; - if ((nframes >= UMIDI_TX_FRAMES) || (chan->single_command != 0)) + if (total_length >= UMIDI_BULK_SIZE) { break; + } } else { continue; } } - chan->curr_cable++; - if (chan->curr_cable >= chan->max_cable) + if (chan->curr_cable >= chan->max_cable) { chan->curr_cable = 0; - + } if (chan->curr_cable == start_cable) { - if (tr_any == 0) + if (tr_any == 0) { break; + } tr_any = 0; } } - if (nframes != 0) { - DPRINTF("Transferring %d frames\n", (int)nframes); - usbd_xfer_set_frame_len(xfer, 0, 4 * nframes); + if (total_length) { + usbd_xfer_set_frame_len(xfer, 0, total_length); usbd_transfer_submit(xfer); } - break; + return; default: /* Error */ @@ -3628,10 +3602,11 @@ if (error != USB_ERR_CANCELLED) { /* try to clear stall first */ - usbd_xfer_set_stall(xfer); - goto tr_setup; + chan->flags |= UMIDI_FLAG_WRITE_STALL; + usbd_transfer_start(chan->xfer[2]); } - break; + return; + } } @@ -3661,7 +3636,7 @@ { struct umidi_chan *chan = usb_fifo_softc(fifo); - usbd_transfer_start(chan->xfer[UMIDI_RX_TRANSFER]); + usbd_transfer_start(chan->xfer[1]); } static void @@ -3688,7 +3663,7 @@ { struct umidi_chan *chan = usb_fifo_softc(fifo); - usbd_transfer_start(chan->xfer[UMIDI_TX_TRANSFER]); + usbd_transfer_start(chan->xfer[0]); } static void @@ -3703,7 +3678,8 @@ if (--(chan->write_open_refcount) == 0) { DPRINTF("(stopping write transfer)\n"); - usbd_transfer_stop(chan->xfer[UMIDI_TX_TRANSFER]); + usbd_transfer_stop(chan->xfer[2]); + usbd_transfer_stop(chan->xfer[0]); } } @@ -3728,7 +3704,7 @@ } /* clear stall first */ mtx_lock(&chan->mtx); - usbd_xfer_set_stall(chan->xfer[UMIDI_TX_TRANSFER]); + chan->flags |= UMIDI_FLAG_WRITE_STALL; chan->write_open_refcount++; sub->write_open = 1; @@ -3778,7 +3754,7 @@ .basename[0] = "umidi", }; -static int +static int32_t umidi_probe(device_t dev) { struct uaudio_softc *sc = device_get_softc(dev); @@ -3789,16 +3765,12 @@ int error; uint32_t n; - if (usb_test_quirk(uaa, UQ_SINGLE_CMD_MIDI)) - chan->single_command = 1; - if (usbd_set_alt_interface_index(sc->sc_udev, chan->iface_index, chan->iface_alt_index)) { DPRINTF("setting of alternate index failed!\n"); goto detach; } - usbd_set_parent_iface(sc->sc_udev, chan->iface_index, - sc->sc_mixer_iface_index); + usbd_set_parent_iface(sc->sc_udev, chan->iface_index, sc->sc_mixer_iface_index); error = usbd_transfer_setup(uaa->device, &chan->iface_index, chan->xfer, umidi_config, UMIDI_N_TRANSFER, @@ -3828,15 +3800,13 @@ mtx_lock(&chan->mtx); /* clear stall first */ - usbd_xfer_set_stall(chan->xfer[UMIDI_RX_TRANSFER]); + chan->flags |= UMIDI_FLAG_READ_STALL; /* - * NOTE: At least one device will not work properly unless the - * BULK IN pipe is open all the time. This might have to do - * about that the internal queues of the device overflow if we - * don't read them regularly. + * NOTE: at least one device will not work properly unless + * the BULK pipe is open all the time. */ - usbd_transfer_start(chan->xfer[UMIDI_RX_TRANSFER]); + usbd_transfer_start(chan->xfer[1]); mtx_unlock(&chan->mtx); @@ -3846,7 +3816,7 @@ return (ENXIO); /* failure */ } -static int +static int32_t umidi_detach(device_t dev) { struct uaudio_softc *sc = device_get_softc(dev); @@ -3859,7 +3829,8 @@ mtx_lock(&chan->mtx); - usbd_transfer_stop(chan->xfer[UMIDI_RX_TRANSFER]); + usbd_transfer_stop(chan->xfer[3]); + usbd_transfer_stop(chan->xfer[1]); mtx_unlock(&chan->mtx); --3V7upXqbjpZ4EhLz--