Bug 1048 - hiddev_events missing when reading from /dev/hiddev0
Summary: hiddev_events missing when reading from /dev/hiddev0
Status: RESOLVED CODE_FIX
Alias: None
Product: Other
Classification: Unclassified
Component: Modules (show other bugs)
Hardware: i386 Linux
: P2 normal
Assignee: Bugme Janitors Team
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-08-05 16:55 UTC by Eric Penner
Modified: 2005-06-02 05:17 UTC (History)
0 users

See Also:
Kernel Version: Any with hiddev (2.4.16 , 2.5 etc.)
Subsystem:
Regression: ---
Bisected commit-id:


Attachments

Description Eric Penner 2003-08-05 16:55:26 UTC
Distribution:          All (anything with hiddev)
Hardware Environment:  Absolute positioning USB device using hiddev
Software Environment:  All
Problem Description:

In trying to use a hiddev usb device in linux, we found the following bug. It
causes hiddev_events to be missing when reading from the device (eg.
/dev/hiddev0).  All that is required is that any value in a field be the same as
it was the last time it was read from the device. 

After they are eaten by the kernel, there is no way to get these missing events
from user-space. Since it is not known which events are missing, it is
impossible to reconstruct what is actually coming from the device. 

This renders hiddev useless for many devices. 

Anyway, I would like to know where else I should post this or where I can post a
patch that fixes the problem for a future release. 

hid-core.c : 

static void hid_input_field(struct hid_device *hid, struct hid_field *field,
__u8 *data) 
{ 
... 
        for (n = 0; n < count; n++) { 

                if (HID_MAIN_ITEM_VARIABLE & field->flags) { 

                        if (field->flags & HID_MAIN_ITEM_RELATIVE) { 
                                if (!value[n]) continue; 
                        } else { 
                                if (value[n] == field->value[n]) continue;//BUG! 
                        } 
                        hid_process_event(hid, field, &field->usage[n],
value[n]);    //Never gets called !!!! no hiddev_event on /dev/hiddev0
                        continue; 
                } 
        } 
... 
} 


Steps to reproduce:

Pretty much use any hiddev device that uses absolute positioning. Even if the
device is relative, I don't think the kernel should be eating events like it is
above. One has to expect a certain order of hiddev_events when reading from
/dev/hiddevX in order to determine what they mean.  When the kernel eats a few
of them up they become meaningless.

Fix:

Remove the following code:

if (field->flags & HID_MAIN_ITEM_RELATIVE) { 
    if (!value[n]) continue; 
} else { 
    if (value[n] == field->value[n]) continue;
}
Comment 1 Boris Shingarov 2004-06-01 06:01:25 UTC
This bug also stops CRYPTOCard initializers from working.
Is there any particular reason why this report caching is needed?
Comment 2 Vojtech Pavlik 2005-06-02 05:17:24 UTC
The HID protocol is supposed to be stateless (describing only the current
state of the device) and thus duplicate VARIABLE reports
are, according to the specification, carrying no information and the kernel
is allowed to filter them out.

However, many devices abuse the HID protocol for non-human-input uses, and also
abuse the reports as a generic data transport channel.

Since the filtering isn't strictly needed in the kernel (it only saves some CPU
cycles in processing the events) and it breaks these out-of-spec devices, I
removed it in 2.6.12-pre.

Consider the bug fixed.

Note You need to log in before you can comment on or make changes to this bug.