Subject: Re: USB control endpoint stalled
To: Edgar =?iso-8859-1?Q?Fu=DF?= <Edgar.Fuss@bn2.maus.net>
From: Terry Moore <tmm@mcci.com>
List: tech-kern
Date: 03/15/2007 17:00:39
At 11:27 AM 3/15/2007 +0100, Edgar Fu=DF wrote:
>Thanks very much for your detailed reply.
>
>I'm trying to talk to a Masterguard UPS via USB.
>The problem is that the most helpful people at Masterguard didn't build
>the USB interface themselves, but outsourced that and only got a M$ Win
>driver. However, they, helpful as they are, supplied me with a trace of
>the driver talking to the UPS. The interesting part of it reads as follows:
>
>Vendor-Specific Request (DOWN)
>Destination: Endpoint, Index 0
>Reserved Bits: 9
>Request: 0xd
>Value: 0x0
>Send 0x3 bytes to the device
>
>I deduced from this that I had to send a vendor-specific request #0x0d
>to the control endpoint. I can't make sense of the "reserved bits".
>
> > The device can return a STALL handshake to indicate an error.
>Do I read this correctly as that the device actively generates this
>"STALL" condition and it's not something like a timeout or protocol
>violation?

Correct.


> > Because the type is 0x42, this is a
> > "host-to-device, vendor-specific request directed
> > at an endpoint", where the endpoint is specified
> > by the low 8 bits of wIndex.  The request code is 0x0D.
>Good. That looks exactly like what I intended to do.
>
> > This request fails.
>Where "fails" means that the UPS actively answers that it cannot
>handle the request?

Yes.


> > Since this is a vendor request, it's seems likely that you're running
> > software that doesn't actually know how to talk to your device.
>As mentioned, the software is of my own making.
>However, most of the time, it works. But sometimes something (where I
>can't tell being that the USB stack, the UPS or whatever) seems to get
>stuck and the only known ways to get it work again is either to wait
>something in he order of ten minutes or re-plug the USB cable.
>I've also no idea what leads to the "stuck" state.

Probably the UPS itself gets stuck.  I suppose=20
it's also possible that it's a data-toggle=20
error.  I don't know whether ugen will let you=20
send a "port reset" easily -- that is equivalent=20
to unplug/replug and probably will clear the problem.


> > this sends the setup.
>Where "setup" is USB speak meaning aproximately what "CDB" would be
>in SCSI?

Yes.


> > >TD(0xffff80004dc4d6c0) at 082b46c0:
> > >f3ec0000<R,OUT,TOG1,SETTOGGLE> delay=3D7 ec=3D0 cc=3D15
> > >cbp=3D0x07b9dec0 nexttd=3D0x082b4710 be=3D0x07b9dec2
> >
> > this sends the two bytes of data
>TWO bytes? That would exactly explain the problem as I have to send
>THREE bytes. Where do you read from that I'm erroneously sending only two?

I am sorry, I was in too much of a hurry.  You are right, according to this:

>>ohci_device_control type=3D0x42, request=3D0x0d,=20
>>wValue=3D0x0000, wIndex=3D0x0000 len=3D3, addr=3D2, endpt=3D0

you are in fact trying to send three bytes of data.


> > This usually means that your device doesn't understand the request.
>Hm. Now I have to find out why it sometimes does and sometimes does not
>understand the same request?
>
>Can there be anny issue with timing? Like the NetBSD USB stack overrunning
>the "well, it works with Window$"-type device. Any knobs to turn?

I don't know of any -- I work with USB all the=20
time, and I use NetBSD all the time, but I don't use USB with NetBSD very=
 much.

> > Your driver, or the stack issues this.
>Must be the stack.
>
> > It also seems to complete without errors, which
> > means the device is NOT stuck in the STALL state.
>OK, that's a most valuable thing for me to know.
>
>If your analysis that I'm only sending two instead of three bytes
>is correct I'll have to find out what makes that happen.

I'm sorry to have confused you on this.  In the=20
error case you are indeed sending three bytes.

>Could you be so kind as to double-check that?
>And instruct me how I can extract that information from the trace?

Look for lines like this:
>>ohci_device_control type=3D0x42, request=3D0x0d,=20
>>wValue=3D0x0000, wIndex=3D0x0000 len=3D3, addr=3D2, endpt=3D0


> > Then the app gives up and closes ugen:
>OK.
>
> > Then the app reopens.
>Well, that's actually the operator (e.g. me) re-starting gdb.
>Seems like I sent to large an excerpt of the syslog trace.

OK.

> > The app does the same thing over and over?
>No. It won't close and re-open ugen. It either retries sending the
>command after a delay or gives up, closes ugen and returns an error.

When you restart the app in this state, does it always fail?

> > Seems like the app is the problem, not the device.
>Maybe yes. If it would only either work all the time or fail all the time.
>Indeed, yesterday, I was happy that it consistently failed while I was
>trying to produce the trace.

Indeed.

>Two remaining questions:
>
>1. Can anyone make any sense of the "reserved bits" mentioned in the trace
>they provided me? From the relevant parts of the USB spec I read, I could
>not find any field of at least five bits that could hold a value of 9
>and be called "reserved"

It is puzzling.  The bmReqType field has 1 bit of=20
direction, 2 bits of type, and 5 bits of=20
"destination".  There are 4 defined values for=20
the 5-bit destination field: 0,1,2,3.  It's=20
possible that they meant that you should set this=20
field to 9, which would result in bmReqType =3D=3D=20
0x49, not 0x42.  But that seems to contradict=20
what they're saying in their instructions.

A bus trace is the only good way to find out what=20
they're really doing, and to confirm that the=20
NetBSD stack is really doing the right thing.

>2. With the NetBSD stack, is there any way to do something like a USB=
 reset,
>e.g. something in software close to walk down to the server room and
>phyically re-plug the cable?

Unfortunately, there doesn't seem to be, but I'm=20
only looking at the 3.1 manpages.  Basically,=20
something like the Windows "Cycle Port" operation=20
is needed, but I'm not sure the NetBSD stack provides that.

>Thanks again a lot for your most detailed reply.

Sorry for the confusion about length,
--Terry=20