Given the discussion on INTR-OUT transfers, I thought it'd
be useful to write out my current thoughts on how we should
resolve this ... since it involves driver API changes as well as
changes to each of the host controller drivers.

Here's a quick writeup, including rationale and some sketches
of API updates (for 2.5).  Comments?

- Dave



GOAL:  support INTR-OUT and INTR-IN transfers with
one API model which could also be used for a device
controller API using an URB-like model.


CURRENT MODEL:  all interrupt transfers are specified
with using an URB with transfer_buffer_length set to a
fixed packet size, and a fixed polling interval.  Also,
current host controller drivers say only one interrupt URB
(usually of at most maxpacketsize) may be queued.

One notable problem with that model relates to the fixed
transfer buffer length.  When writing data, the length may
need to vary:  different HID reports may have different
sizes, as one example.  The current model only allows
sizes to vary for reading data, by enabling short packets.

A related problem is that when data is not available,
there's no way to say "don't write data during this
period, but I may have some later."


COMPARISON:  most device hardware makes each
transfer be individually enabled and sized.  Interrupts
on completion can be used to enable/size the next
transfer.

Some (like the EZ-USB FX2) have options such as single,
double, triple, and even quad buffering (helps when doing
highspeed transfers with slowish and/or busy CPUs).  Such
functionality is not available today for Linux-USB.


API CHANGE #1:  Let INTR completion handlers change
the transfer_buffer_length.  A value of "-1" (it's not
a size_t!!) would mean "don't transfer anything".  Any
other value, up to the maximum allowed by the endpoint
descriptor (which is what would control the bandwidth
allocation by the HCD), would be legal.

Today, this would mostly be used for INTR-OUT (or
host-writes-to-device).  For a device side API it
would be used regularly on INTR-IN transfers (or
device-writes-to-host).

This could either be done (a) with a special API
function, like

    usb_modify_transfer (struct urb *urb, int size)

or (b) by just modifying the HCDs to use the current
transfer_buffer_length when re-enabling the transfer
after a completion callback finished.

I'd prefer (a) since it lets "too big" be reported to
drivers.  Doing that cleanly would also mean adding
a new core-to-HCD call, which I'd rather avoid ... though
it would let unmodified HCDs cause error reports.
(There are enough HCDs outside drivers/usb that I
start to worry about seemingly "transparent" API
changes.)  It would also provide a clear way to
re-enable transfers outside a completion handler,
once transfer_buffer_length is set to "-1"; and it's
a more direct analogue of how device hardware
works.


API CHANGE #2 (much less thought out):  Support
multi-buffering.  Two options come to mind:

1) Let INTR transfers to a given endpoint be
   queued.  At end of queue, the bandwidth
   is reclaimed.  This is basically the same
   model as bulk transfers ... single buffered
   drivers might make completion handlers
   (re)submit the just-completed URB.

   HCDs wouldn't prune a QH/ED from the
   periodic schedule until nothing's queued
   (no TDs in their lists).  And existing code
   for bulk queuing would be reused.

2) Use urb->next and insist that interrupt URBs
   be linked in rings, like ISO.  Single buffered
   drivers would have urb->next == urb.

Both of those seem like they'd be incompatible
changes to the transfer model.  All drivers would
need to change, unless this were added as some
kind of second interrupt transfer mode (yeech).

API change #2 may get rid of any need for #1...

Note that (1) gives a very simple answer for
the question of "one shot" transfers, or ones
like writing N bytes of data (N > maxpacket).

Of those, I tend to prefer (1) although the model
for bandwidth allocation needs to be looked at.

For example, what about when urb->interval is
not the same in the different URBs?  (Error!)
And what to do when the driver wants to keep
its bandwidth allocation but not issue a transfer
just now?

I don't much like (2) because I've never liked
the weak error reporting model inherent in
the urb->next submission path.  It also doesn't
match the hardware's queuing model as well;
all the HCs treat interrupt transfers pretty much
like bulk ones that happen to live in the periodic
schedule ... I'd rather see interrupt transfers
look much more like bulk ones.



_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to