[haiku-development] Re: Am I misunderstanding USB queue_bulk?

  • From: pete.goodeve@xxxxxxxxxxxx
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Sun, 6 Sep 2009 22:48:06 -0700

On Mon, Sep 07, 2009 at 03:53:12AM +0000, Michael Lotz wrote:
> Hi Pete
> 
> > The main one was in getting the write function to work.  The midi 
> > driver
> > seems to cleanly pass an event at a time, which nicely fits in a USB
> > midi packet -- *unless* it is a SysEx sequence, which can take many
> > packets to transmit.  So I thought I'd be efficient, and set up a
> > rotating pool of packet-sized buffers that I'd fill and pass on to
> > the USB driver with queue_bulk(...) as fast as they were filled.
> > (A semaphore primed with the number of buffers is used to prevent
> > overflow.)
> 
> You do not need to split up anything. In fact you shouldn't. The packet 
> size of the endpoint is purely informational for you. The stack (or the 
> host controller depending on the model) will do the splitting up. You 
> hand in the whole buffer with all the payload data you need to send.
I don't believe this is quite correct in the case of USB-MIDI.  All MIDI
is passed to and from the device in 4-byte packets, only the last three
of which are the MIDI data.  The first byte of each packet has to be
added (it isn't in the buffer passed from the MIDI driver) to identify
the contents.  So at the very least I have to build a new data buffer
contailing a sequence of full packets.

Are you saying, though, that I can build that buffer essentially as large
as I like, distinct from the 'maximum packet size' (64 bytes) of the device
hardware itself?  I had already found that the receiving side can get many
4-byte packets packed into a single return buffer, but this is always less
than the 64 limit (possibly because I put that limit in the device_info
structure?!).  I was about to try packing the output side as well, so I'll
go ahead and do that (though large SysExs will always have to be split).

> 
> > I've made it work by changing the semaphore to only allow one packet
> > to get sent until the callback is invoked, but this seems wrong from
> > the concept of a 'queue'. [And SLOW!]  Or, as I say, am I 
> > misunderstanding?
> 
> It is not actually a queue. It simply means that the function is async. 
> Transmission is queued and the function returns. You must only queue 
> one transfer at a time. For receiving this cannot work differently due 
> to the data toggle that you only know after an incoming transfer has 
> passed. For sending it would be possible to calculate the toggle up 
> front and allow multiple transfers. This is not currently supported 
> however. This means one buffer at the time for now. Since you do not 
> need to split up your buffer and can pass in the whole payload data you 
> want, this is in practice usually not a problem.
> 
Ah, so it is a bit of a misnomer...  I assumed it would be a fifo.
If I can pack the buffer, as you say it's not a real problem.

Thanks,
                -- Pete --


Other related posts: