I thought the first suggestion here made the most sense, allowing you to change the size of the URB buffer.
I agree that a new function is the best way to do this (as opposed to allowing people to change the size themselves directly in the urb and picking up the change on resubmission) for the following reasons. i. it's encapsulated. It allows drivers to do whatever they want at URB submission (like creating internal structures and buffers/TDs) and tells them specifically you want to make a change. They can schedule that change in whatever way suits them. ii. It adheres to the idea that an URB, once submitted, is not yours to play with except via defined calls into the API. ii. It allows much better error reporting. For instance the changing of this value while the URB is still in progress could return an EINPROGRESS status code. You can, as David points out, also return illegal size errors. One point which comes to mind is that you lose knowledge of the actual size of buffer originally allocated. Currently, anyone making an URB can alloc() the memory and store the size in the URB and doesn't need to remember how big it was actually allocated. People will need to be careful to remember the actual size of their buffers when they are requesting the size grows again after shrinking it. You also need to think about what a '-1' urb means. Will you still 'schedule' it even though it will trivially return each time, or would you stop scheduling it? I think you should do the former so that driver writers get continual callbacks even for null transfer urbs, that should simplify the logic of when to call the 'modify' routine. If we're doing this, is it worth also allowing the buffer pointer to be changed, ie make the call more like usb_modify_transfer( struct urb *urb, int size, void *buffer); This would make the reading and writing of data buffers more than one packet long quite easy. (eg for writing 100 bytes which have already been transferred to kernel memory you could submit the urb with a count of 64, then, in the completion handler, change the size to 36 and increment buffer by 64 instead of having to copy each packet of data going out into the one, 64 byte, urb buffer). I think that might help readers and writers. Finally just a couple of notes about INTR-OUT transfers in general. I just read through the UHCI and OHCI specs (it's why I've been sleeping so much recently!) and they really seem to treat interrupt transfers as device->host only. That actually makes a lot of sense to me; you, the host, are required to poll the device for incoming data because USB is a scheduled protocol; hence the INTR-IN transfer. However, for outgoing data, you do know how much data you have and don't really need this continual callback. You could use a bulk URB and resubmit it in the callback routine, or just set up a string of URBs and let them go. (question - are callback routines mandatory and, if you don't have them, who frees the urb?). The only things you lose here are the priority handling of the interrupt urb and I suppose some devices may not be able to handle data coming at them too fast, hence you would want to schedule the urbs and I think you can't currently schedule bulk urbs, even to the extent of 'not before frame x please'. That might be a nice thing to add for bulk, if the start_frame is set, the urb is not tried until that frame arrives. Do people think that is a good enhancement? So in general it seems to me that we can fix the INTR_OUT to be more sensible and more the analog of the INTR_IN (which has implicit buffer length changes because of the short packet flag) but people may want to think more about using bulk for transfers of known-length data to devices. Roland At 15:46 Wednesday, David Brownell wrote: >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 _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel