[PATCH 1/3] ALSA USB MIDI: Fix port starvation

Andreas Steinmetz ast at domdv.de
Mon Mar 16 14:31:15 CET 2020


On Mon, 2020-03-16 at 13:03 +0100, Clemens Ladisch wrote:
> Andreas Steinmetz wrote:
> > the snd_usbmidi_transmit_byte helper had to be converted to
> > return output notification to allow for the 'repeat' shortcut.
> 
> Why not simply handle one MIDI byte per port in each iteration?  It
> could be argued that single-byte MIDI commands are likely to be real-
> time messages and deserve to go first.
> 

Actually the patch does exactly this. As soon as the helper signals
that a message is complete the next port is processed. The "repeat"
loop is just necessary to get a complete class compliant message for
transfer as the helper processes one byte at a time.
The range optimization is there to prevent O(2) performance cost if
possible.

> > Current multi port MIDI interfaces do
> > typically have 2^n output ports and 2^x as wMaxPacketSize where
> > x>n.
> 
> The USB specification requires bulk endpoints to have a
> wMaxPacketSize
> value of 8/16/32/64 for full speed, or exactly 512 for high speed.
> 
> > For the patch to properly work the wMaxPacketSize of the device
> > must be
> > large enough to allow for at least one MIDI event per port in a
> > URB.
> 
> There are devices that handle only the first four bytes of a received
> packet (because Windows used to send only small packets), and one of
> them, the ESI M4U, actually has more than one port.
> 

Again no problem as the patch is designed to prefer quirks over user
settings to prevent malfunctioning devices. Quirk processing and thus
size restrictions are processed after user selection.

> My original idea for that FIXME was to use round robin until the
> packet
> is filled (or all ports are empty), and to store the next port index
> (where to start for the next packet) in the endpoint.  This would be
> able to distribute the balancing over multiple packets.
> 

The problem with "round robin until the packet is filled" is that in
case of a large wMaxPacketSize there's then a huge latency.
I just got for further internal testing an USB3 8x8 interface that uses
a wMaxPacketSize of 512.
In such a case a port doing a sysex transfer will delay another port
then sending a realtime message by a minimum of 123ms per queued URB.
Make that 7 URBs and you have a sysex queue of 860ms until the realtime
message can be transmitted.
> 
> Regards,
> Clemens
-- 
Andreas Steinmetz



More information about the Alsa-devel mailing list