Logitech HD Webcam Pro c910 && snd_uaudio does not work
Matthias Apitz
guru at unixarea.de
Thu May 17 06:46:37 UTC 2012
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: <USB audio> 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 <guru at unixarea.de> - 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
-------------- next part --------------
Index: uaudio.c
===================================================================
--- uaudio.c (revisi?226986)
+++ uaudio.c (copia de trabajo)
@@ -53,6 +53,7 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
+#include <sys/linker_set.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -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);
More information about the freebsd-multimedia
mailing list