Re: Question: Efficient IO to USB HID device with spurious zero byte IN packets

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 9 Feb 2010, Glen Harris wrote:

> Hi All,
> 
> I have currently developed a user-mode application that talks to a
> third-party USB device.  Existing software for the device is Windows
> only and proprietary.  My application works correctly, and it appears
> (from using a hardware USB analyser) that I am talking to the device
> correctly.  My concern is that the application 'feels' extremely
> inefficient, and I would like to know if anyone can suggest a more
> elegant approach.
> 
> The Device:
> The device is a USB powered HID device, but maybe not the most
> compliant device ever written (some missing descriptors etc).  It has
> two endpoints (excluding control) 0x81 interrupt in, and 0x02
> interrupt out.  I am only concerned with problems *reading* reports
> from the device.  The IN endpoint has a max packet size of 64 bytes.
> bInterval is 1 (i.e. 1 report every millisecond).  Although the device
> says it is a HID device, it is only using HID as a transport for
> opaque data (i.e. I am pretty sure it doesnt even have descriptors for
> the reports).

Have you tried running "lsusb -v" on it?  You might have to "rmmod 
usbhid" first to get all the descriptors.

> The Problem:
> The problem is that the device sends zero byte IN packets instead of
> NAKs.  In other words, when there is data to send, it will send a full
> 64 byte IN packet, and the rest of the time it will send a zero byte
> IN packet.  This means that the USB susbsystem feels obliged to tell
> my application that a zero byte packet was received.  I know why, in
> general, it has to treat any short packet like this, and I am not
> proposing to change this behaviour.  I see this behaviour with libusb
> and raw ioctls.
> 
> Current Approach:
> At the moment, when the application starts I submit N (say 20) IN USB
> IRPS.  As the device sends IN packets, they either have data or no
> data.  My application basically 'spins' by recycling the IRPs, and
> extracting any data that has arrived.  Like I say, it works, but it
> just feels ugly (not to mention uses CPU and keeps jumping from
> kernel<->userland).  I have the luxury of being able to treat this as
> an interesting problem and try to see if I can find an elegant
> solution, but I really need some help from people who know the Linux
> USB architecture.
> 
> What Wont Work:
> I dont think I can get high level HID reports because the device does
> not respond with all descriptors, and so dmesg shows
> [594015.753598] usbhid: timeout initializing reports
> [594015.755345] hiddev97hidraw0: USB HID v1.01 Device [XXX] on
> usb-0000:00:1d.0-2.2
> I could dig further into this, but I am fairly sure the actual
> firmware on the device is not compliant with the USB HID spec.
> 
> What I Want:
> I want a user mode application that can block in user space and read
> reports (64 bytes at a time) without having to worry about those
> spurious zero byte packets.  Ideally, I want to do this without making
> any kernel modifications.  Obviously, I cannot modify the firmware on
> the USB device, so I have to live with that 'as-is'.
> 
> Strategy 1:
> Is there any kind of flag that I have missed on the USB IRPS that
> would say 'by the way, just ignore a zero byte packet'.

There is no such flag.

> Strategy 2:
> Is there a different type of user-mode IO I should be using?

No.

> Strategy 3:
> What are the files /dev/usbdevX.Yep81 etc for?  Which driver creates
> them?  Do they provide any kind of interface for actually reading
> data, or are they signalling/control files.

I don't have files like that on my system.  However, if they are under 
/dev then they are created by udev, not by anything in the kernel.

My guess is that these files don't provide any interfaces at all -- not 
for reading/writing nor for signalling/control.  If anything they are 
placeholders, most likely intended for a vaporware version of usbfs.

> Strategy 4:
> What are the files /dev/usb/hiddevX etc for?  Which driver creates
> them?  Do they provide any kind of interface for actually reading
> data, or are they signalling/control files.

I don't know.  They might be useful for your purposes, but only if you 
can get the device working under usbhid.  It might not be as hard as 
you think -- a simple NOGET entry in the HID quirk table might be 
enough.

> Strategy 5:
> Is there any kind of a 'quirk' that I can set which tells the USB
> subsystem 'this particular device sends lots of zero byte packets that
> should be ignored completely'.

No.  In fact, the USB protocol does not allow systems to ignore 
zero-length packets.

> Strategy 6:
> Surely there has to be a 'nice' way of doing this?  Any ideas?

The only way to avoid lots of kernel/user transitions is to modify the 
kernel -- add some sort of quirk code or add a special driver.  But you 
said that you didn't want to change the kernel.

> Finally:
> If the answer is no to the above strategies, is there a consensus of
> whether this functionality (#1 or #5) makes sense to be added to the
> kernel.  I haven't done Linux kernel development before, but I would
> feel pretty confident tackling this if someone gave me a pointer in
> the right direction.

#1 or #5 would never be accepted, at least, not as you stated them.  
The closest you could come would be a flag meaning "Resubmit this 
request if the response hase length 0".  I doubt people would be in 
favor of adding such a flag just to support a brain-dead nonconformant 
device.  But others may have their own opinions...

The easiest approach is almost certainly to make the usbhid driver work
with the device somehow.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux