USB MIDI patch for FreeBSD 8/9

Raoul M�g�las rmgls at free.fr
Thu Feb 17 22:55:37 UTC 2011


On Thu, 17 Feb 2011 22:54:35 +0100
Hans Petter Selasky <hselasky at c2i.net> wrote:

> On Thursday 17 February 2011 22:12:16 Raoul M=EF=BF=BDg=EF=BF=BDlas wrote:
> > on Thu, 17 Feb 2011 11:18:40 +0100
> > Hans Petter Selasky <hselasky at c2i.net> wrote:

>>    ...

> > > cd /usr/src/sys/dev/sound/usb/
> > > cat umidi_patch_001.txt | patch
> > >=20
> > > A short summary of what the changes are about:
> > >=20
> > > - Make the USB MIDI driver more OSS compliant by implementing the
> > > correct data format for the /dev/umidiX.Y character devices. Also
> > > implement some missing OSS MIDI ioctls.
> > > - Use the USB stack's builtin clear-stall feature.
> > > - Wrap some long lines.
> > > - Use memcpy() instead of bcopy().
> > >=20
> > > --HPS
> > >
> > Some demo tunes:
> >=20
> > fluidsynth + zynaddsubfx + audacity + midipp:
> >=20
> > http://www.selasky.org/hans_petter/synth_test_new.mp3
> >=20
> > zynaddsubfx + midipp:
> >=20
> > http://www.selasky.org/hans_petter/synth_test.mp3
> >=20
> > --HPS
> >=20
> > --Boundary-00=3D_AYPXNgVCRizMd8n
> > Content-Type: text/plain;
> >=20
> >   charset=3D"us-ascii";
> >   name=3D"umidi_patch_001.txt"
> >=20
> > Content-Transfer-Encoding: 7bit
> > Content-Disposition: inline;
> >=20
> > 	filename=3D"umidi_patch_001.txt"
> >=20
> > =3D=3D=3D uaudio.c
> > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> > --- uaudio.c	(revision 218769)
> > +++ uaudio.c	(local)
> > @@ -191,10 +191,15 @@
> >=20
> >  	uint8_t	iface_alt_index;
> > =20
> >  };
> >=20
> > -#define	UMIDI_N_TRANSFER    4		/* units */
> >=20
> >  #define	UMIDI_CABLES_MAX   16		/* units */
> >  #define	UMIDI_BULK_SIZE  1024		/* bytes */
> >=20
> > +enum {
> > +	UMIDI_TX_TRANSFER,
> > +	UMIDI_RX_TRANSFER,
> > +	UMIDI_N_TRANSFER,
> > +};
> > +
> >=20
> >  struct umidi_sub_chan {
> > =20
> >  	struct usb_fifo_sc fifo;
> >  	uint8_t *temp_cmd;
> >=20
> > @@ -224,10 +229,6 @@
> >=20
> >  	uint8_t	iface_index;
> >  	uint8_t	iface_alt_index;
> >=20
> > -	uint8_t	flags;
> > -#define	UMIDI_FLAG_READ_STALL  0x01
> > -#define	UMIDI_FLAG_WRITE_STALL 0x02
> > -
> >=20
> >  	uint8_t	read_open_refcount;
> >  	uint8_t	write_open_refcount;
> >=20
> > @@ -336,9 +337,7 @@
> >=20
> >  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;
> >=20
> > -static usb_callback_t umidi_read_clear_stall_callback;
> >=20
> >  static usb_callback_t umidi_bulk_read_callback;
> >=20
> > -static usb_callback_t umidi_write_clear_stall_callback;
> >=20
> >  static usb_callback_t umidi_bulk_write_callback;
> > =20
> >  static void	uaudio_chan_fill_info_sub(struct uaudio_softc *,
> >=20
> > @@ -493,7 +492,7 @@
> >=20
> >  static const struct usb_config
> > =20
> >  	umidi_config[UMIDI_N_TRANSFER] =3D {
> >=20
> > -	[0] =3D {
> > +	[UMIDI_TX_TRANSFER] =3D {
> >=20
> >  		.type =3D UE_BULK,
> >  		.endpoint =3D UE_ADDR_ANY,
> >  		.direction =3D UE_DIR_OUT,
> >=20
> > @@ -502,7 +501,7 @@
> >=20
> >  		.callback =3D &umidi_bulk_write_callback,
> >  =09
> >  	},
> >=20
> > -	[1] =3D {
> > +	[UMIDI_RX_TRANSFER] =3D {
> >=20
> >  		.type =3D UE_BULK,
> >  		.endpoint =3D UE_ADDR_ANY,
> >  		.direction =3D UE_DIR_IN,
> >=20
> > @@ -510,26 +509,6 @@
> >=20
> >  		.flags =3D {.pipe_bof =3D 1,.short_xfer_ok =3D 1,.proxy_buffer =3D 1=
,},
> >  		.callback =3D &umidi_bulk_read_callback,
> >  =09
> >  	},
> >=20
> > -
> > -	[2] =3D {
> > -		.type =3D UE_CONTROL,
> > -		.endpoint =3D 0x00,	/* Control pipe */
> > -		.direction =3D UE_DIR_ANY,
> > -		.bufsize =3D sizeof(struct usb_device_request),
> > -		.callback =3D &umidi_write_clear_stall_callback,
> > -		.timeout =3D 1000,	/* 1 second */
> > -		.interval =3D 50,	/* 50ms */
> > -	},
> > -
> > -	[3] =3D {
> > -		.type =3D UE_CONTROL,
> > -		.endpoint =3D 0x00,	/* Control pipe */
> > -		.direction =3D UE_DIR_ANY,
> > -		.bufsize =3D sizeof(struct usb_device_request),
> > -		.callback =3D &umidi_read_clear_stall_callback,
> > -		.timeout =3D 1000,	/* 1 second */
> > -		.interval =3D 50,	/* 50ms */
> > -	},
> >=20
> >  };
> > =20
> >  static devclass_t uaudio_devclass;
> >=20
> > @@ -1577,10 +1556,10 @@
> >=20
> >  uaudio_mixer_add_ctl_sub(struct uaudio_softc *sc, struct
> >  uaudio_mixer_node *mc) {
> > =20
> >  	struct uaudio_mixer_node *p_mc_new =3D
> >=20
> > -	malloc(sizeof(*p_mc_new), M_USBDEV, M_WAITOK);
> > +	    malloc(sizeof(*p_mc_new), M_USBDEV, M_WAITOK);
> >=20
> > -	if (p_mc_new) {
> > -		bcopy(mc, p_mc_new, sizeof(*p_mc_new));
> > +	if (p_mc_new !=3D NULL) {
> > +		memcpy(p_mc_new, mc, sizeof(*p_mc_new));
> >=20
> >  		p_mc_new->next =3D sc->sc_mixer_root;
> >  		sc->sc_mixer_root =3D p_mc_new;
> >  		sc->sc_mixer_count++;
> >=20
> > @@ -1722,7 +1701,7 @@
> >=20
> >  	DPRINTFN(3, "ichs=3D%d ochs=3D%d\n", ichs, ochs);
> >=20
> > -	bzero(&mix, sizeof(mix));
> > +	memset(&mix, 0, sizeof(mix));
> >=20
> >  	mix.wIndex =3D MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no);
> >  	uaudio_mixer_determine_class(&iot[id], &mix);
> >=20
> > @@ -1782,7 +1761,7 @@
> >=20
> >  	if (d->bNrInPins =3D=3D 0) {
> >  =09
> >  		return;
> >  =09
> >  	}
> >=20
> > -	bzero(&mix, sizeof(mix));
> > +	memset(&mix, 0, sizeof(mix));
> >=20
> >  	mix.wIndex =3D MAKE_WORD(d->bUnitId, sc->sc_mixer_iface_no);
> >  	mix.wValue[0] =3D MAKE_WORD(0, 0);
> >=20
> > @@ -1852,7 +1831,7 @@
> >=20
> >  	if (d->bControlSize =3D=3D 0) {
> >  =09
> >  		return;
> >  =09
> >  	}
> >=20
> > -	bzero(&mix, sizeof(mix));
> > +	memset(&mix, 0, sizeof(mix));
> >=20
> >  	nchan =3D (d->bLength - 7) / d->bControlSize;
> >  	mmask =3D uaudio_mixer_feature_get_bmaControls(d, 0);
> >=20
> > @@ -1986,7 +1965,7 @@
> >=20
> >  		DPRINTF("no mode select\n");
> >  		return;
> >  =09
> >  	}
> >=20
> > -	bzero(&mix, sizeof(mix));
> > +	memset(&mix, 0, sizeof(mix));
> >=20
> >  	mix.wIndex =3D MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no);
> >  	mix.nchan =3D 1;
> >=20
> > @@ -2012,7 +1991,7 @@
> >=20
> >  	struct uaudio_mixer_node mix;
> >  	uint16_t ptype;
> >=20
> > -	bzero(&mix, sizeof(mix));
> > +	memset(&mix, 0, sizeof(mix));
> >=20
> >  	ptype =3D UGETW(d0->wProcessType);
> >=20
> > @@ -2067,7 +2046,7 @@
> >=20
> >  	}
> >  	if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
> >=20
> > -		bzero(&mix, sizeof(mix));
> > +		memset(&mix, 0, sizeof(mix));
> >=20
> >  		mix.wIndex =3D MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no);
> >  		mix.nchan =3D 1;
> >=20
> > @@ -2294,7 +2273,7 @@
> >=20
> >  	}
> > =20
> >  error:
> >  	DPRINTF("bad data\n");
> >=20
> > -	bzero(&r, sizeof(r));
> > +	memset(&r, 0, sizeof(r));
> >=20
> >  done:
> >  	return (r);
> > =20
> >  }
> >=20
> > @@ -3284,25 +3263,12 @@
> >=20
> >   *=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> >   =3D=3D*/
> > =20
> >  static void
> >=20
> > -umidi_read_clear_stall_callback(struct usb_xfer *xfer, usb_error_t
> > error) -{
> > -	struct umidi_chan *chan =3D usbd_xfer_softc(xfer);
> > -	struct usb_xfer *xfer_other =3D chan->xfer[1];
> > -
> > -	if (usbd_clear_stall_callback(xfer, xfer_other)) {
> > -		DPRINTF("stall cleared\n");
> > -		chan->flags &=3D ~UMIDI_FLAG_READ_STALL;
> > -		usbd_transfer_start(xfer_other);
> > -	}
> > -}
> > -
> > -static void
> >=20
> >  umidi_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
> >  {
> > =20
> >  	struct umidi_chan *chan =3D usbd_xfer_softc(xfer);
> >  	struct umidi_sub_chan *sub;
> >  	struct usb_page_cache *pc;
> >=20
> > -	uint8_t buf[1];
> > +	uint8_t buf[5];
> >=20
> >  	uint8_t cmd_len;
> >  	uint8_t cn;
> >  	uint16_t pos;
> >=20
> > @@ -3320,60 +3286,66 @@
> >=20
> >  		while (actlen >=3D 4) {
> >=20
> > -			usbd_copy_out(pc, pos, buf, 1);
> > -
> > -			cmd_len =3D umidi_cmd_to_len[buf[0] & 0xF];	/* command length=20
*/
> > -			cn =3D buf[0] >> 4;	/* cable number */
> > +			/* copy out the MIDI data */
> > +			usbd_copy_out(pc, pos, buf, 4);
> > +			/* command length */
> > +			cmd_len =3D umidi_cmd_to_len[buf[0] & 0xF];
> > +			/* cable number */
> > +			cn =3D buf[0] >> 4;
> > +			/*
> > +			 * Lookup sub-channel. The index is range
> > +			 * checked below.
> > +			 */
> >=20
> >  			sub =3D &chan->sub[cn];
> >=20
> > -			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 */
> > -			}
> > +			if ((cmd_len !=3D 0) &&
> > +			    (cn < chan->max_cable) &&
> > +			    (sub->read_open !=3D 0)) {
> >=20
> > +				/* re-pack into a 4-byte array */
> > +				/* zero unused bytes */
> > +				if (cmd_len =3D=3D 1) {
> > +					buf[2] =3D 0;
> > +					buf[3] =3D 0;
> > +					buf[4] =3D 0;
> > +				} else if (cmd_len =3D=3D 2) {
> > +					buf[3] =3D 0;
> > +					buf[4] =3D 0;
> > +				} else {
> > +					buf[4] =3D 0;
> > +				}
> > +
> > +				/*
> > +				 * Send data in 4-byte chunks to the
> > +				 * application:
> > +				 */
> > +				usb_fifo_put_data_linear(
> > +				    sub->fifo.fp[USB_FIFO_RX],
> > +				    buf + 1, 4, 1);
> > +			}
> >=20
> >  			actlen -=3D 4;
> >  			pos +=3D 4;
> >  	=09
> >  		}
> >  =09
> >  	case USB_ST_SETUP:
> >  		DPRINTF("start\n");
> >=20
> > -
> > -		if (chan->flags & UMIDI_FLAG_READ_STALL) {
> > -			usbd_transfer_start(chan->xfer[3]);
> > -			return;
> > -		}
> >=20
> > +tr_setup:
> >  		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
> >  		usbd_transfer_submit(xfer);
> >=20
> > -		return;
> > +		break;
> >=20
> >  	default:
> >  		DPRINTF("error=3D%s\n", usbd_errstr(error));
> >  	=09
> >  		if (error !=3D USB_ERR_CANCELLED) {
> >  	=09
> >  			/* try to clear stall first */
> >=20
> > -			chan->flags |=3D UMIDI_FLAG_READ_STALL;
> > -			usbd_transfer_start(chan->xfer[3]);
> > +			usbd_xfer_set_stall(xfer);
> > +			goto tr_setup;
> >=20
> >  		}
> >=20
> > -		return;
> > -
> > +		break;
> >=20
> >  	}
> > =20
> >  }
> >=20
> > -static void
> > -umidi_write_clear_stall_callback(struct usb_xfer *xfer, usb_error_t
> > error) -{
> > -	struct umidi_chan *chan =3D usbd_xfer_softc(xfer);
> > -	struct usb_xfer *xfer_other =3D chan->xfer[0];
> > -
> > -	if (usbd_clear_stall_callback(xfer, xfer_other)) {
> > -		DPRINTF("stall cleared\n");
> > -		chan->flags &=3D ~UMIDI_FLAG_WRITE_STALL;
> > -		usbd_transfer_start(xfer_other);
> > -	}
> > -}
> > -
> >=20
> >  /*
> > =20
> >   * The following statemachine, that converts MIDI commands to
> >   * USB MIDI packets, derives from Linux's usbmidi.c, which
> >=20
> > @@ -3502,6 +3474,8 @@
> >=20
> >  			sub->temp_cmd =3D sub->temp_1;
> >  			sub->state =3D UMIDI_ST_SYSEX_0;
> >  			return (1);
> >=20
> > +		default:
> > +			break;
> >=20
> >  		}
> >  =09
> >  	}
> >  	return (0);
> >=20
> > @@ -3527,13 +3501,9 @@
> >=20
> >  		DPRINTF("actlen=3D%d bytes\n", len);
> >  =09
> >  	case USB_ST_SETUP:
> > -
> >=20
> > +tr_setup:
> >  		DPRINTF("start\n");
> >=20
> > -		if (chan->flags & UMIDI_FLAG_WRITE_STALL) {
> > -			usbd_transfer_start(chan->xfer[2]);
> > -			return;
> > -		}
> >=20
> >  		total_length =3D 0;	/* reset */
> >  		start_cable =3D chan->curr_cable;
> >  		tr_any =3D 0;
> >=20
> > @@ -3593,7 +3563,7 @@
> >=20
> >  			usbd_xfer_set_frame_len(xfer, 0, total_length);
> >  			usbd_transfer_submit(xfer);
> >  	=09
> >  		}
> >=20
> > -		return;
> > +		break;
> >=20
> >  	default:			/* Error */
> >=20
> > @@ -3601,11 +3571,10 @@
> >=20
> >  		if (error !=3D USB_ERR_CANCELLED) {
> >  	=09
> >  			/* try to clear stall first */
> >=20
> > -			chan->flags |=3D UMIDI_FLAG_WRITE_STALL;
> > -			usbd_transfer_start(chan->xfer[2]);
> > +			usbd_xfer_set_stall(xfer);
> > +			goto tr_setup;
> >=20
> >  		}
> >=20
> > -		return;
> > -
> > +		break;
> >=20
> >  	}
> > =20
> >  }
> >=20
> > @@ -3635,7 +3604,7 @@
> >=20
> >  {
> > =20
> >  	struct umidi_chan *chan =3D usb_fifo_softc(fifo);
> >=20
> > -	usbd_transfer_start(chan->xfer[1]);
> > +	usbd_transfer_start(chan->xfer[UMIDI_RX_TRANSFER]);
> >=20
> >  }
> > =20
> >  static void
> >=20
> > @@ -3662,7 +3631,7 @@
> >=20
> >  {
> > =20
> >  	struct umidi_chan *chan =3D usb_fifo_softc(fifo);
> >=20
> > -	usbd_transfer_start(chan->xfer[0]);
> > +	usbd_transfer_start(chan->xfer[UMIDI_TX_TRANSFER]);
> >=20
> >  }
> > =20
> >  static void
> >=20
> > @@ -3677,8 +3646,7 @@
> >=20
> >  	if (--(chan->write_open_refcount) =3D=3D 0) {
> >  =09
> >  		DPRINTF("(stopping write transfer)\n");
> >=20
> > -		usbd_transfer_stop(chan->xfer[2]);
> > -		usbd_transfer_stop(chan->xfer[0]);
> > +		usbd_transfer_stop(chan->xfer[UMIDI_TX_TRANSFER]);
> >=20
> >  	}
> > =20
> >  }
> >=20
> > @@ -3703,7 +3671,7 @@
> >=20
> >  		}
> >  		/* clear stall first */
> >  		mtx_lock(&chan->mtx);
> >=20
> > -		chan->flags |=3D UMIDI_FLAG_WRITE_STALL;
> > +		usbd_xfer_set_stall(chan->xfer[UMIDI_TX_TRANSFER]);
> >=20
> >  		chan->write_open_refcount++;
> >  		sub->write_open =3D 1;
> >=20
> > @@ -3769,7 +3737,8 @@
> >=20
> >  		DPRINTF("setting of alternate index failed!\n");
> >  		goto detach;
> >  =09
> >  	}
> >=20
> > -	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);
> >=20
> >  	error =3D usbd_transfer_setup(uaa->device, &chan->iface_index,
> >  =09
> >  	    chan->xfer, umidi_config, UMIDI_N_TRANSFER,
> >=20
> > @@ -3799,13 +3768,15 @@
> >=20
> >  	mtx_lock(&chan->mtx);
> >  =09
> >  	/* clear stall first */
> >=20
> > -	chan->flags |=3D UMIDI_FLAG_READ_STALL;
> > +	usbd_xfer_set_stall(chan->xfer[UMIDI_RX_TRANSFER]);
> >=20
> >  	/*
> >=20
> > -	 * NOTE: at least one device will not work properly unless
> > -	 * the BULK pipe is open all the time.
> > +	 * 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.
> >=20
> >  	 */
> >=20
> > -	usbd_transfer_start(chan->xfer[1]);
> > +	usbd_transfer_start(chan->xfer[UMIDI_RX_TRANSFER]);
> >=20
> >  	mtx_unlock(&chan->mtx);
> >=20
> > @@ -3828,8 +3799,7 @@
> >=20
> >  	mtx_lock(&chan->mtx);
> >=20
> > -	usbd_transfer_stop(chan->xfer[3]);
> > -	usbd_transfer_stop(chan->xfer[1]);
> > +	usbd_transfer_stop(chan->xfer[UMIDI_RX_TRANSFER]);
> >=20
> >  	mtx_unlock(&chan->mtx);
>=20
> Hi Hans Peter,
>=20
> On my laptop The first patch coredump, but not the second.
> without the patch, my little soft runs fine,
> i.e. using the mutexes part of code from ssynth.
> With the second patch:
> in the same conditions of testing, all notes stick, and make some jam.
> It seems that the performances are degraded here.
> what i do is simple:
> the master keyboard sends the notes, the soft does some transformations a=
nd
> resends the notes to the two modules.
>=20
> Do you need something else?
> feel free to ask, of course.

> Could you try this third patch?

=.-HPS

Oh! this one works perfectly for me. thanks.

Raoul

--Boundary-00=_bkZXNBbphpH84ED
Content-Type: text/plain;
  charset="iso-8859-15";
  name="umidi_patch_003.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
	filename="umidi_patch_003.txt"

=== uaudio.c
==================================================================
--- uaudio.c	(revision 218769)
+++ uaudio.c	(local)
@@ -191,10 +191,15 @@
 	uint8_t	iface_alt_index;
 };
 
-#define	UMIDI_N_TRANSFER    4		/* units */
 #define	UMIDI_CABLES_MAX   16		/* units */
 #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;
@@ -224,10 +229,6 @@
 	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;
 
@@ -336,9 +337,7 @@
 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 *,
@@ -493,7 +492,7 @@
 
 static const struct usb_config
 	umidi_config[UMIDI_N_TRANSFER] = {
-	[0] = {
+	[UMIDI_TX_TRANSFER] = {
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
@@ -502,7 +501,7 @@
 		.callback = &umidi_bulk_write_callback,
 	},
 
-	[1] = {
+	[UMIDI_RX_TRANSFER] = {
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
@@ -510,26 +509,6 @@
 		.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;
@@ -1577,10 +1556,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) {
-		bcopy(mc, p_mc_new, sizeof(*p_mc_new));
+	if (p_mc_new != NULL) {
+		memcpy(p_mc_new, mc, sizeof(*p_mc_new));
 		p_mc_new->next = sc->sc_mixer_root;
 		sc->sc_mixer_root = p_mc_new;
 		sc->sc_mixer_count++;
@@ -1722,7 +1701,7 @@
 
 	DPRINTFN(3, "ichs=%d ochs=%d\n", ichs, ochs);
 
-	bzero(&mix, sizeof(mix));
+	memset(&mix, 0, sizeof(mix));
 
 	mix.wIndex = MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no);
 	uaudio_mixer_determine_class(&iot[id], &mix);
@@ -1782,7 +1761,7 @@
 	if (d->bNrInPins == 0) {
 		return;
 	}
-	bzero(&mix, sizeof(mix));
+	memset(&mix, 0, sizeof(mix));
 
 	mix.wIndex = MAKE_WORD(d->bUnitId, sc->sc_mixer_iface_no);
 	mix.wValue[0] = MAKE_WORD(0, 0);
@@ -1852,7 +1831,7 @@
 	if (d->bControlSize == 0) {
 		return;
 	}
-	bzero(&mix, sizeof(mix));
+	memset(&mix, 0, sizeof(mix));
 
 	nchan = (d->bLength - 7) / d->bControlSize;
 	mmask = uaudio_mixer_feature_get_bmaControls(d, 0);
@@ -1986,7 +1965,7 @@
 		DPRINTF("no mode select\n");
 		return;
 	}
-	bzero(&mix, sizeof(mix));
+	memset(&mix, 0, sizeof(mix));
 
 	mix.wIndex = MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no);
 	mix.nchan = 1;
@@ -2012,7 +1991,7 @@
 	struct uaudio_mixer_node mix;
 	uint16_t ptype;
 
-	bzero(&mix, sizeof(mix));
+	memset(&mix, 0, sizeof(mix));
 
 	ptype = UGETW(d0->wProcessType);
 
@@ -2067,7 +2046,7 @@
 	}
 	if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
 
-		bzero(&mix, sizeof(mix));
+		memset(&mix, 0, sizeof(mix));
 
 		mix.wIndex = MAKE_WORD(d0->bUnitId, sc->sc_mixer_iface_no);
 		mix.nchan = 1;
@@ -2294,7 +2273,7 @@
 	}
 error:
 	DPRINTF("bad data\n");
-	bzero(&r, sizeof(r));
+	memset(&r, 0, sizeof(r));
 done:
 	return (r);
 }
@@ -3284,25 +3263,12 @@
  *========================================================================*/
 
 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[1];
+	uint8_t buf[4];
 	uint8_t cmd_len;
 	uint8_t cn;
 	uint16_t pos;
@@ -3320,60 +3286,50 @@
 
 		while (actlen >= 4) {
 
-			usbd_copy_out(pc, pos, buf, 1);
-
-			cmd_len = umidi_cmd_to_len[buf[0] & 0xF];	/* command length */
-			cn = buf[0] >> 4;	/* cable number */
+			/* 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.
+			 */
 			sub = &chan->sub[cn];
 
-			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 */
-			}
+			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);
+			}
 			actlen -= 4;
 			pos += 4;
 		}
 
 	case USB_ST_SETUP:
 		DPRINTF("start\n");
-
-		if (chan->flags & UMIDI_FLAG_READ_STALL) {
-			usbd_transfer_start(chan->xfer[3]);
-			return;
-		}
+tr_setup:
 		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
 		usbd_transfer_submit(xfer);
-		return;
+		break;
 
 	default:
 		DPRINTF("error=%s\n", usbd_errstr(error));
 
 		if (error != USB_ERR_CANCELLED) {
 			/* try to clear stall first */
-			chan->flags |= UMIDI_FLAG_READ_STALL;
-			usbd_transfer_start(chan->xfer[3]);
+			usbd_xfer_set_stall(xfer);
+			goto tr_setup;
 		}
-		return;
-
+		break;
 	}
 }
 
-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
@@ -3502,6 +3458,8 @@
 			sub->temp_cmd = sub->temp_1;
 			sub->state = UMIDI_ST_SYSEX_0;
 			return (1);
+		default:
+			break;
 		}
 	}
 	return (0);
@@ -3527,13 +3485,9 @@
 		DPRINTF("actlen=%d bytes\n", len);
 
 	case USB_ST_SETUP:
-
+tr_setup:
 		DPRINTF("start\n");
 
-		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;
@@ -3593,7 +3547,7 @@
 			usbd_xfer_set_frame_len(xfer, 0, total_length);
 			usbd_transfer_submit(xfer);
 		}
-		return;
+		break;
 
 	default:			/* Error */
 
@@ -3601,11 +3555,10 @@
 
 		if (error != USB_ERR_CANCELLED) {
 			/* try to clear stall first */
-			chan->flags |= UMIDI_FLAG_WRITE_STALL;
-			usbd_transfer_start(chan->xfer[2]);
+			usbd_xfer_set_stall(xfer);
+			goto tr_setup;
 		}
-		return;
-
+		break;
 	}
 }
 
@@ -3635,7 +3588,7 @@
 {
 	struct umidi_chan *chan = usb_fifo_softc(fifo);
 
-	usbd_transfer_start(chan->xfer[1]);
+	usbd_transfer_start(chan->xfer[UMIDI_RX_TRANSFER]);
 }
 
 static void
@@ -3662,7 +3615,7 @@
 {
 	struct umidi_chan *chan = usb_fifo_softc(fifo);
 
-	usbd_transfer_start(chan->xfer[0]);
+	usbd_transfer_start(chan->xfer[UMIDI_TX_TRANSFER]);
 }
 
 static void
@@ -3677,8 +3630,7 @@
 
 	if (--(chan->write_open_refcount) == 0) {
 		DPRINTF("(stopping write transfer)\n");
-		usbd_transfer_stop(chan->xfer[2]);
-		usbd_transfer_stop(chan->xfer[0]);
+		usbd_transfer_stop(chan->xfer[UMIDI_TX_TRANSFER]);
 	}
 }
 
@@ -3703,7 +3655,7 @@
 		}
 		/* clear stall first */
 		mtx_lock(&chan->mtx);
-		chan->flags |= UMIDI_FLAG_WRITE_STALL;
+		usbd_xfer_set_stall(chan->xfer[UMIDI_TX_TRANSFER]);
 		chan->write_open_refcount++;
 		sub->write_open = 1;
 
@@ -3769,7 +3721,8 @@
 		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,
@@ -3799,13 +3752,15 @@
 	mtx_lock(&chan->mtx);
 
 	/* clear stall first */
-	chan->flags |= UMIDI_FLAG_READ_STALL;
+	usbd_xfer_set_stall(chan->xfer[UMIDI_RX_TRANSFER]);
 
 	/*
-	 * NOTE: at least one device will not work properly unless
-	 * the BULK pipe is open all the time.
+	 * 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.
 	 */
-	usbd_transfer_start(chan->xfer[1]);
+	usbd_transfer_start(chan->xfer[UMIDI_RX_TRANSFER]);
 
 	mtx_unlock(&chan->mtx);
 
@@ -3828,8 +3783,7 @@
 
 	mtx_lock(&chan->mtx);
 
-	usbd_transfer_stop(chan->xfer[3]);
-	usbd_transfer_stop(chan->xfer[1]);
+	usbd_transfer_stop(chan->xfer[UMIDI_RX_TRANSFER]);
 
 	mtx_unlock(&chan->mtx);
 

--Boundary-00=_bkZXNBbphpH84ED--


More information about the freebsd-multimedia mailing list