Hi,

I'm working on a device driver which uses interrupt mode transfers in 
both directions.  The reception side is working happily, but I'm 
having some problems with the transmission side.  My understanding is 
that the following pseudo-code is how I should attempt to use the USB 
system (main setup of endpoints etc omited for clarity).  Tx interval 
is set to zero for one-shot mode (although it makes no difference if 
I set to the interval value from the endpoint).

driver_write()
{
  ...
   if (tx_urb->status == -EINPROGRESS)
   {
     wait(tx_sem); /*  hit by reception of -ECONNRESET in tx_completion */
   }
   FILL_INT_URB(tx_urb, some data, tx_completion, etc.)
   usb_submit_urb(tgx_urb)
...
}

tx_completion(urb)
{
   if (urb->status == -ECONNRESET)
   {
    wake_up(tx_sem);
     return;
   }

   if (more data to transmit)
   {
     FILL_INT_URB(tx_urb, more data, etc.); /* HCD will resubmit this */
   }
   else
   {
#ifdef  EVIL_HACK_NO_94
     urb->status = -EINPROGRESS; /* Bodge - see b) below */
#endif
     urb->transfer_flags |= USB_ASYNC_UNLINK;
     usb_unlink_urb(urb);
   }
}

My main question is whether this approach is correct?

Whilst attempting to debug this on my system (Apple Titanium G4 
PowerBook - uses OHCI controller usb-ohci.c) I have observed the 
following interesting 'features' of the OHCI driver:

a) Unlike the documentation & usb-uhci.c, it only generates unlink 
completion events for asynchronous unlinks (-ECONNRESET) but not for 
synchronous unlinks (should be -ENOENT?).  This appears to be a 
straight inconsistency between the implementations and is easily 
fixed.

b) Calling usb_unlink_urb() from a completion routine does NOTHING 
because urb->status has been set to zero for the completion routine, 
and sohci_unlink_urb() returns immediately (with no error) if 
urb->status is not -EINPROGRESS.

c) Having worked around b) by setting urb->status to -EINPROGRESS 
before calling usb_unlink_urb, I never receive a completion with 
status -ECONNRESET.  After instrumenting usb-ohci.c I know that the 
unlink correctly marks the URB for unlinking and enables the start 
frame interrupt.  The start frame interrupt does occur and does 
invoke the routine dl_del_list() for processing of the unlink, but it 
does not invoke dl_del_urb() on my (being) unlinked URB. Having dealt 
with the list, the start frame interrupt is disabled as no further 
worked is deemed necessary.  At this point I am at the limit of my 
current knowledge....a few simple attempts at tweaking have generally 
resulted in a reboot being required :(

The observed behaviour is that my first transmission works, then my 
second transmission waits forever for the URB to become unlinked.

I am currently attempting to be able to try this on a UHCI based 
system for comparison, and reading the OHCI spec for enlightenment, 
but would be grateful for any suggestions (or patches for usb-ohci.c) 
to try.

Regards

Stu
-- 
The Janitorium <http://www.janitorium.co.uk/>

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

Reply via email to