[libhid-discuss] Polling interrupt endpoint

Rene vanallesennogwat at onsnet.nu
Wed Jul 7 12:10:03 UTC 2010


Peter Stuge wrote:
> Hi Rene,
>   

Hi Peter,

First of all, thank you very much for replying! Second, sorry that I did 
not reply sooner, this was most certainly not due to a lack of interest.

You have already given me quite some enlightment. I am very new to all 
of this and usb is not an easy matter, it is not just the protocol one 
has to learn but also the practical aspects of implenting stuff both on 
device and host side. There is a lot of theoretical information on the 
web, and there is a lot of stuff that can be helpfull when it comes to 
implementation but how exactly to use all of this is sometimes difficult.

> Rene wrote:
>   
>> an interrupt ep has a polling time. AFAI understand it, this is used
>> for calculating the required bandwidth (along with the ep size, this
>> is done by driver code that is on a lower level in the usb stack)
>> and off course for setting the polling time. However, when I "steal"
>> the device from the kernel hid driver, do I have to see to it that
>> this polling time is respected?
>>     
>
> No, not in general. However, it depends on how the device is abusing
> HID in order to use USB. (It's an extremely bad idea to use HID for
> devices that should not use the kernel HID driver. It's like driving
> a tractor on the side walk, when there is a street right next to it.)
>   


To be honest, I really don't know whether I am abusing HID or not. The 
fact that I chose HID is because for the Atmel mcu I am using there is a 
generic HID-implementation in LUFA (the usb-framework that is available 
for these mcus as foss) that I understand by now and can very easily 
tailor to my needs and on the host side I came across libhid and the 
sample app that is delivered with it and with those two, I can achieve 
what I want. The two int eps are exactly what I need so I thought a hid 
would be the easiest thing to use. And the function of the device, input 
through buttons and output through a display are quite fitting to 
"interfacing with a human".

My knowledge and experience are still too limited to judge if this was 
the right choice, I would very much appreciate your opinion and - if you 
think there is a better way for me to achieve my goals (which are 
described below) - suggestions about the way I should choose (I always 
appreciate pointers to usefull and practical places as well off course).

On a side note: Later on, the device will have to be usable from Windows 
as well.



> The poll time is not so much a requirement for the USB driver (your
> program) but for the USB host controller chip and the USB system
> software (the kernel USB stack, always used, even if you detach the
> HID kernel driver).
>
> If the device has data available for you with this interval, and if
> you do not want to lose any data, *then* you need to make sure to
> read from the device using libhid frequently enough that the lower
> level USB software and hardware will consistently perform a transfer
> on every opportunity.
>
>   


Aha, that is very clear. 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).

>   
>> Esp. for reading this is important.
>>     
>
> I hope it's clearer from the above. 


Yes, it most certainly is, thanks.


> Basically we can't say if it is
> important or not, that depends on your particular device and the
> assumptions made by the firmware engineers.
>   


The firmware "engineer" is myself as well ;-). I should have given more 
detail in my first post.

The device (an Amtel AVR mcu running LUFA) has some buttons that can be 
pressed and a display (but in a future edition it might have values from 
a rotary encoder or from the ADC as well), the host side application 
should and will (because I will write it) know how to interpret the 
data. The device sends data only if something has changed. The display 
does not need constant refreshing. When I want it to display something 
else, 1 KB of raw data has to be send to it as quickly as possible (in 8 
byte chunks which is the maximum the ep of the mcu can handle)(and I 
made a mistake about the polling time: the OUT EP polling time will be 1 
ms).


>
>   
>> For writing (updating the readings on a display) I can just send
>> a package whenever there is something to be sent, being carefull to
>> respect the polling time.
>>     
>
> You can send any time. The lower level USB software and hardware will
> handle scheduling for you.
>
>   

I understand that now, I was very confused about that and obviously my 
hypothesis was wrong.

>   
>> Another question is how pressing a button on the usb device might
>> wake up the pc if it is suspended. AFAI can see, this is not possible.
>>     
>
> So the device has buttons - does it identify itself as a HID
> keyboard?

No, it doesn't. It is a vendor specific device. 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). 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.

>  If so, then I would strongly recommend interfacing with the
> kernel input layer instead of trying to speak directly with the USB
> device.
>
> That said - remote resume is possible over USB, what is your question
> again? While the PC is suspended, USB still has power. Not a lot, but
> some.
>   


I know, my problem was that I thought that the user space program would 
be responsible for the polling once the device was "stolen" from the 
kernel. In that case, when the pc would put itself to sleep, there would 
be no more polling (because my user space program would be sleeping) and 
so the system would never know that there was an interrupt from the usb 
device. 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.


>
>   
>> My last question is about the fact that there are two things taking place. 
>> The display part (the display is on the device) of my program is reading 
>> from a fifo, I could do that with a blocking read or with select with a 
>> time-out, the last option allows me to poll the in ep at a regular interval 
>> where the first one doesn't. The in ep needs to be read every 50 ms and 
>> then something has to be put into another fifo. What would be the most 
>> elegant solution to achieve this?
>>     
>
> It also depends on how the device wants to be read. 


When something changes at the device side (button pressed or released) 
it will put data (the current state of the buttons) in the IN EP that 
should be read with a maximum latency of 50 ms. The rest of the time it 
will return NAK.

Then the data has to be put in a fifo (at least that is my plan at the 
moment) and the application interested in it can read that using the 
select function. 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.

> If you were using
> libusb then one option would be to have two threads, or to use async
> USB transfers. I'm not sure you can, with libhid. (Though, if you're
> using libhid on top of libusb-compat-0.1 on top of libusb-1.0, then
> it would probably be fine anyway.)
>   


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.

>
>   
>> Another option would be to have a select with just a timeout, when it times 
>> out (10ms) it polls the in ep every fifth time (polling time for the out ep 
>> is 10 ms, for in ep 50 ms)
>>     
>
> Please don't mix these timings. Any timeout involved in userspace
> calls into the kernel have no guaranteed latency and can always be
> longer than the specified time, while the polling time is an
> absolutely strict upper limit for the hardware. The polling is done
> in the host controller hardware.
>
>
>   


I mixed things up a bit. I was thinking about minimum latency so the 
device would not be asked for data too quickly but off course we're 
talking about _maximum_ latency. I know that can't be guaranteed in user 
space. Sorry for the confusion (like I said, many aspects from this 
project are new to me).


>> I am not only new to usb and libhid but also rather new to Linux and
>> would very much like to hear Your opinions about this or perhaps You
>> have a completely different idea about how I would best design this.
>>     
>
> Please say more about the process of reading data from the device.
>   


I hope the things I wrote above are sufficient.

I really appreciate your help.

Yours sincerely,
Rene



More information about the libhid-discuss mailing list