[libhid-discuss] Polling interrupt endpoint

Rene vanallesennogwat at onsnet.nu
Mon Jul 12 15:10:59 UTC 2010


Hi Peter,

Thanks again for your help and patience...

>   
> Ok. It's easy to fall into the HID trap because there is a lot of
> information and code examples for HID, and because it is trivial to
> use on Windows. (Those two are likely related.) In contrast, doing
> almost anything else with USB on Windows is an absolute nightmare.
>
> I suggest that you make your device use the vendor specific device
> class 0xff instead of having it use the HID class.
>   

Yes, I am going to try that. At the moment, the device is working the
way I want it to (well, the display part is working, the i/o not yet),
now I am going to try to rework both firmware and host software to get
out the HID stuff and replace it with non-HID code.

I nosed around in libhid and saw that e.g. an interrupt ep there just
calls the interrupt read from usblib. I don't expect much troubles. I am
starting to get used a bit to the way libs are documented. For a
beginner, what is generated in these doxygenpages is not always
sufficient to get started with...

>   
>> On a side note: Later on, the device will have to be usable from
>> Windows as well.
>>     
>
> No problem. There are two solutions at the moment, either you program
> for the libusb-0.1 API, or you program for the libusb-1.0 API.
>
> libusb-0.1 is no longer maintained, but might still be an option if
> Windows support in the short term is neccessary.
>
> In the former case you would install the libusb0.sys signed kernel
> driver written by the libusb-win32 project (a fork from libusb-0.1,
> providing the libusb-0.1 API with some extensions on Windows) to
> handle your device on Windows, then everything works nicely.
>   


I am confident that I'll be able to work things out that way. But first
I am going to concentrate on Linux.

By the way, I think for Windows I might use "windows backend", I saw
that it should be working quite well by now.

> In Linux and Mac OS you need only ensure that the user has access to
> the vendor specific device. HID requires root access (reboot on Mac!).
>
> You can still use the interrupt endpoints of course. But you can
> completely cut away all the overhead introduced by the device
> announcing that it's a HID class device, and then needing to work
> with/around the kernel HID driver in every operating system.
>   

Yes, I understand that that is much better. There is no advantage in
using my device as a HID. It was just the easiest way to get it going at
the moment I was looking around at the web. And almost all of the
examples and tutorials concentrate on creating usb devices from a
certain defined class, hid or audio or so. But there is not much to be
found that shows one how to build a vendor defined class usb device and
driver on the pc.

>
>   
>> What would happen if I fail to read often enough apart from missing
>> data? Would some fifo or so get full and would the lower level
>> parts stop polling eventually? Suppose not a single program reads the 
>> mouse but I keep on moving the mouse (rather useless, I know, but 
>> theoretically speaking).
>>     
>
> This is entirely device specific, or firmware specific if you will.
>
> If no program on the host ever reads, then then host will never
> initiate any communication with the device. The device is only given
> opportunity to send data on the bus when an application wants to
> read.
>
> The device could of course have a FIFO that gets full and makes the
> device go into a state where it will no longer respond to reads from
> an application, but that would be one very broken device.
>   


That was a misunderstanding as well, I thought that polling was taking
place all the time. That if one set a polling interval of say 10 ms,
every 10 ms, the device would be read, no matter what. In that case
somewhere in the host something would get full at some moment. But now
that you wrote that a device is only being read when a program wants to
read from that device, it all makes much more sense. After all, it would
be rather useless to be polling a device if nothing is being done with
the data.


>   
>> The firmware "engineer" is myself as well ;-).
>>     
>
> This is good. :)
>   

Well, in fact it is only as good as I am as a usb-programmer, which at
the moment is not that good yet ;-) (no, I am not fishing for a
compliment, you already gave me one but what I wrote here is just the
way it is - I don't feel bad about it). But I am very happy that my
device is already working, that gives a lot of confidence. Learning usb
is quite frustrating, all the time one wants to start coding but really
a lot of reading, re-reading and re-re-reading is required, as well as
processing in the brain before one really gets a grasp. At least, that
is how it worked for me. Fortunately I am now in the phase where I can
do active experimenting, and I appreciate it very much that you
corrected several misunderstandings I had in my head.

> HID and vendor specific are orthogonal and mutually exclusive.
>
>
>   

You are right. What I meant was vendor specific usage, so not one of the
standard HIDs like a keyboard or a mouse where the report items have
some meaning to the os.

>   
>
>> If I understand it correctly, if something is a keyboard device,
>> it's keys are "parallel" to the keys on a normal keyboard. So if a
>> button on the device were pressed and someone had his word
>> processor on the foreground, something would happen in that program
>> (e.g. an "a" was entered or so)(depending on the report descriptor
>> in the device).
>>     
>
> Yep, it is when this behavior is a feature that the USB HID class
> should be used for a device.
>   

And it is not the behaviour I am looking for so a HID is obviously not
the right choice, I understand now why.

>   
>> My project is for making an embedded device whiches keys have to be
>> completely separate and are only relevant to one certain host side
>> application.
>>     
>
> Since it is a human interface, a case could be made to use the HID
> class, but because you never want to deal with the OS HID driver I
> would strongly recommend a vendor speciic device class instead.
>   

Yes, I am going to take that road from now.

>   
>>> remote resume is possible over USB, what is your question again?
>>>       
> ..
>   
>> Now I have understood that this polling goes on because it still
>> happens in the controller and that way an interrupt can be detected
>> and wake up the pc again.
>>     
>
> Almost right, there is no polling in suspend, wake-up signalling is
> initiated by the device. This is a special case indeed.
>
>   

I looked it up after reading this. I did not know that yet. But it turns
out that LUFA even supports that. Quite a guy who wrote that framework!

> Unfortunately it's not possible to program USB portably using
> select(). The best you can get so far is libusb-1.0, which provides
> both a synchronous and an asynchronous API for USB programming.
>   


I already had been reading a bit in the api documentation and had found
the descriptions of those two.

But the select part of my driver would not be about usb but it would be
the other side of the driver, the fifo. I might use a message queue for
it as well, am not sure yet. Anyway in Linux I want there to be a fifo
somewhere or a message queue in which the program that should write
something on the display can just write some special sort of bitmap
structure (which I will provide in a header file) by means of calling a
fuction which does the actual writing for the programmer, and I want the
driver to read this fifo or queue with select. In Windows I'll take
another road, but in Linux this driver would be a process that is
running and monitoring its input and sending the data, after some
processing (simple protocol to the device) to the endpoint.


> libusb-1.0 has known behavior (and one or two known bugs that are
> being fixed) when used in threaded applications, while libusb-0.1
> does not fit well into such an environment at all. Using libusb-1.0
> in async mode you get callbacks on completed transfers.
>
> In order to meet the 50ms system response time requirement I would
> make sure to have multiple outstanding requests at all times, for
> when many events follow each other.
>   


Suppose I would not use async mode but sync. Is it correct if I would
implement it this way:

(pseudocode)

while (1)
{
    usb_interrupt_read(timeout parameter = 1 second or so, more than 50
ms I mean);
    do something with received data;
}

Am I correct that this piece of code will automatically only take place
every 50 ms if that value is in the endpoint descriptor?

I know that this way I can not achieve what I want, after all I need to
write to another endpoint as well, but this is just theoreticaclly
speaking.

>
>   
>> But that means that for the rest the application would come to a 
>> halt (off course I can use the timeout of select).
>>
>> I think using a fork would be the simplest solution for the user
>> space driver.
>>     
>
> The only way to program USB portably is with libusb and threads,
> which means that libusb-1.0 should really be your choice since 0.1
> doesn't have very well defined behavior in threaded apps.
>
>
>   
>>> using libhid on top of libusb-compat-0.1 on top of libusb-1.0,
>>>       
>> I really don't know whether I am using this compatibility layer or not
>> (I did read about it on the libusb website). I am using Xubuntu 9.04
>> and when I look in the package manager, originally only libusb-0.1
>> was installed. I then installed libusb-1.0 as well. And it works.
>> However, how this works "under water", I don't know and I have no
>> idea how to find it out.
>>     
>
> libusb-0.1 and libusb-1.0 are not mutually exclusive. They are two
> distinct APIs and ABIs, which can be said to solve the same problem
> but in different ways. Thus it's fine to have both installed at the
> same time. Apps using the 0.1 API will use the old library, apps
> using the 1.0 API will use the new library.
>
> libusb-compat-0.1 is a wrapper that provides the 0.1 API by using
> the libusb-1.0 API. This has the benefit of increased performance and
> deterministic threading behavior, without requiring app rewrite to
> the new API, but really, the right thing to do is to use the new API
> instead.
>   

I see, and this all functions without me having to do anything? I mean,
if one has a system with only libusb-1.0 on it and one runs a program
written for libusb-0.1, I don't have to do anything, this layer will do
the translation automatically? It is also integrated in libusb-1.0 and
not something that has to be installed seperately?


>> Sorry for the confusion (like I said, many aspects from this
>> project are new to me).
>>     
> That's ok. I think you have a good understand of the important bits
> already in a pretty short time. Well done!
>   


That sounds very encouraging, thanks!

>> I hope the things I wrote above are sufficient.
>>     
>
> I think so. I hope my advice is helpful.
>   

It most certainly is. Not only have you given me some precious tips, you
have also pointed me at several things I thought I understood but where
my understanding was wrong. Many things make more sense to me now.

Yours sincerely,
Rene




More information about the libhid-discuss mailing list