Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 29 Dec 2004 08:12:19 +1100
From:      John Birrell <jb@cimlogic.com.au>
To:        ticso@cicely.de
Cc:        Julian Elischer <julian@elischer.org>
Subject:   Re: USB problems
Message-ID:  <20041228211219.GE61668@freebsd3.cimlogic.com.au>
In-Reply-To: <20041228202832.GN81585@cicely12.cicely.de>
References:  <20041228010938.GA39686@freebsd3.cimlogic.com.au> <41D0C63F.3000702@elischer.org> <20041228025836.GA53223@freebsd3.cimlogic.com.au> <20041228152212.GM81585@cicely12.cicely.de> <20041228195436.GA61668@freebsd3.cimlogic.com.au> <20041228202832.GN81585@cicely12.cicely.de>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, Dec 28, 2004 at 09:28:33PM +0100, Bernd Walter wrote:
> Well, getting a stall on control endpoint is an error, but getting an
> error on string descriptors shouldn't stop further processing.

Windows obviously begs to differ. This reference design comes from the
Singapore lab of Philips which I believe also contains the engineers
who contributed to the USB specification.

The firmware code looks like it was written by an inexperienced hardware
engineer. It is only provided as an example by Philips. They intend you
to write your own when you build your own board. I will do that when I
get the ability to burn 8051 code. In the meantime, I want FreeBSD's
USB implementation to function as well as Windows. That means coming
up with an implementation that tolerates the control endpoint being
stalled.

> > The string descriptors are returned normally by the device, except for the
> > fact that it sets the stall bit on the control endpoint.
> 
> Here is the device broken, unless FreeBSD's request is not correct.

Windows can talk to it though, so at least it's possible to get around
aspects of the device which, I agree, are probably broken.

The thing that nags me, though, is that this is a 'reference design' and
that means that any company choosing to build an MPEG2 encoder based
on Philips' SAA7114, SAA6752 and ISP1581 is going to start with this
firmware code and build a product that probably has the same behaviour.
Philips only offer support to companies who are planning to by large
numbers of chips. That means I'm on my own here. I can't communicate
with their engineers in Singapore. I've tried - they won't respond.

> The device shouldn't stall on requesting partial descriptors.
> IIRC FreeBSD changed the way how descriptors are fetched normaly in
> that it doesn't trust the size fields anymore and asks for more data
> than required.

It also shouldn't stall getting the configuration. Or getting status.
But it is coded to do that.

> > The FreeBSD code *never* takes into account that the control endpoint
> > stall will be cleared with the next setup packet.
> 
> Maybe the host controller needs any kind of unstall mimic, but not the
> device.
> The question is more what happens with further requests after that
> error.

Further requests start with a setup packet, so the stall is cleared when
that is received. The problem is that FreeBSD gives up on talking to the
device because it treats the stall condition as an error. It isn't
even possible for FreeBSD to get past the device initialisation because
the first 8 bytes of the device descriptor are returned with the stall
bit set. At that point, FreeBSD barfs.

> > I think that a control endpoint transfer should not return USBD_STALLED
> > to the caller unless the length received is less than that requested
> > and ~SHORT_TRANSER_OK. A stall on the control endpoint should only be an
> > error if the controller has a problem with the protocol (i.e. it is
> > a protocol stall, not a device stall);
> 
> I had something like this localy running (cut & paste'd):
> Index: usbdi.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/dev/usb/usbdi.c,v
> retrieving revision 1.76
> diff -u -r1.76 usbdi.c
> --- usbdi.c     26 May 2002 22:00:06 -0000      1.76
> +++ usbdi.c     15 Jun 2003 21:32:34 -0000
> @@ -931,8 +931,17 @@
>  usbd_do_request_flags(usbd_device_handle dev, usb_device_request_t *req,
>                       void *data, u_int16_t flags, int *actlen, u_int32_t timo)
>  {
> -       return (usbd_do_request_flags_pipe(dev, dev->default_pipe, req,
> -                                          data, flags, actlen, timo));
> +       int actlen2;
> +       usbd_status ret;
> +
> +       ret = usbd_do_request_flags_pipe(dev, dev->default_pipe, req,
> +                                          data, flags, &actlen2, timo);
> +       if (actlen != NULL)
> +               *actlen = actlen2;
> +       if (ret == USBD_STALLED && actlen2 == UGETW(req->wLength)) {
> +               ret = USBD_NORMAL_COMPLETION;
> +       }
> +       return (ret);
>  }
>  
>  usbd_status
> 
> But it's wrong.
> You just don't know if the received data is correct when receiving
> a stall - especially for requests without data.
> This is something to hand up to the driver which might have a clue
> about a specific device brokenness.

A problem with FreeBSD's code is that some of the places where the driver
*could* interpret the stall condition differently and actually handled
in common routines that are hard-coded to treat the stall as an error.

Take the configuration descriptor as an example. The FreeBSD code tries
to get the first 9 bytes to discover the wTotalLength, then it goes and
gets the full descriptor (including interfaces and endpoints). In the
case of this rogue device, the get of the first 9 bytes results in a
stall. FreeBSD's code then fails the entire configuration descriptor
get and it isn't possible for a driver to configure the device.

-- 
John Birrell



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20041228211219.GE61668>