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