Bug 118861

Summary: uinput doesn't register device node anymore if too many keys are set
Product: Other Reporter: Markus Rechberger (kontakt)
Component: OtherAssignee: other_other
Status: NEW ---    
Severity: normal CC: crow
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 4.4.11-2 Subsystem:
Regression: No Bisected commit-id:

Description Markus Rechberger 2016-05-24 21:21:35 UTC
here's a cheap example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <linux/uinput.h>

#define die(str, args...) do { \
        perror(str); \
        exit(EXIT_FAILURE); \
    } while(0)

int
main(void)
{
    int                    fd;
    struct uinput_user_dev uidev;
    struct input_event     ev;
    int                    dx, dy;
    int                    i;

    fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
    if(fd < 0)
        die("error: open");

                ioctl(fd, UI_SET_EVBIT, (void*)EV_KEY);
        ioctl(fd, UI_SET_EVBIT, (void*)EV_MSC);
        ioctl(fd, UI_SET_EVBIT, (void*)EV_REP);
        ioctl(fd, UI_SET_EVBIT, (void*)EV_REL);

    memset(&uidev, 0, sizeof(uidev));
    snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "Remote Control");
    uidev.id.bustype = BUS_USB;
    uidev.id.vendor  = 0x1;
    uidev.id.product = 0x1;
    uidev.id.version = 1;
        for (i=0; i < 248; i++) {
                if (i==240)
                        continue;
                ioctl(fd, UI_SET_KEYBIT, i);
        }
        for(i=0x160;i<=0x214;i++) {
                if (i>0x20b && i<0x210)
                        continue;
                if (i>0x1fa && i<0x200)
                        continue;
                if (i>0x1e4 && i<0x1f1)
                        continue;
                if (i>0x1c3 && i<0x1d0)
                        continue;
                if (i>0x1ba && i<0x1c0)
                        continue;
                ioctl(fd, UI_SET_KEYBIT, i);
        }

    if(write(fd, &uidev, sizeof(uidev)) < 0)
        die("error: write");

    if(ioctl(fd, UI_DEV_CREATE) < 0)
        die("error: ioctl");

    sleep(200);

    if(ioctl(fd, UI_DEV_DESTROY) < 0)
        die("error: ioctl");

    close(fd);

    return 0;
}




cat /proc/bus/input/devices
I: Bus=0003 Vendor=0001 Product=0001 Version=0001
N: Name="Sundtek Remote Control"
P: Phys=
S: Sysfs=/devices/virtual/input/input3
U: Uniq=
H: Handlers=sysrq rfkill kbd <----- eventN is missing!
B: PROP=0
B: EV=100017
B: KEY=1f0fff 7fe001f ffff000f 7ffffff ffffffff ffffffff 0 0 0 feffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe
B: REL=0
B: MSC=0

eventN is missing in the Handlers: section


if I modify the following loop:
        for(i=0x160;i<=0x214;i++) {
                if (i>0x20b && i<0x210)
                        continue;
                if (i>0x1fa && i<0x200)
                        continue;
                if (i>0x1e4 && i<0x1f1)
                        continue;
                if (i>0x1c3 && i<0x1d0)
                        continue;
                if (i>0x1ba && i<0x1c0)
                        continue;
                if (i>0x200)   <<<--------
                        continue;   <<<<------
                ioctl(fd, UI_SET_KEYBIT, i);
        }


this will create a node again (and if the previous version was started without this modification they will also suddenly get an event node in the proc input devices file:

I: Bus=0003 Vendor=0001 Product=0001 Version=0001
N: Name="Remote Control"
P: Phys=
S: Sysfs=/devices/virtual/input/input8
U: Uniq=
H: Handlers=sysrq rfkill kbd event1  <---- event1
B: PROP=0
B: EV=100017
B: KEY=1 7fe001f ffff000f 7ffffff ffffffff ffffffff 0 0 0 feffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe
B: REL=0
B: MSC=0

this event is related to /dev/input nodes (compared with regular input devices they don't even have a node id in sysfs (unless the userspace modification to handle less keys is made).


This behaviour has been different until 4.4.9 (according to a customer).


Tested on a Raspberry PI
Comment 1 Markus Rechberger 2016-05-25 01:48:41 UTC
It does not matter which keys we remove, we just have to remove some UI_SET_KEYBIT calls.

ioctl(fd, UI_SET_KEYBIT, i);