Difference between revisions of "Uinput"

From Ilianko
Line 1: Line 1:
 
<!--Getting started with uinput: the user level input subsystem -->
 
<!--Getting started with uinput: the user level input subsystem -->
 +
 +
==uinput==
 
Вход от потрeбителско ниво
 
Вход от потрeбителско ниво
  
Line 6: Line 8:
 
In this document, we will see how to create a such input device and how it can be used. -->
 
In this document, we will see how to create a such input device and how it can be used. -->
  
uinput е модул за linux ядрото, който позволява управление на системата за входни данни от приложения работещи на потребителско ниво. Модулът uinput създава виртуално входно устройство.  
+
Uinput е модул за linux ядрото, който позволява управление на системата за входни данни от приложения работещи на потребителско ниво. Модулът uinput създава виртуално входно устройство.  
  
  
1. Създаване на входно устройство.
+
===Създаване на входно устройство===
  
 
След инсталиране на модула uinput (чрез modprobe или insmod) се създава устройство от буквен тип с име /dev/input/uinput (или /dev/uinput). Това устройство представлява интерфейса между риложението и системата за входни данни на ядрото.
 
След инсталиране на модула uinput (чрез modprobe или insmod) се създава устройство от буквен тип с име /dev/input/uinput (или /dev/uinput). Това устройство представлява интерфейса между риложението и системата за входни данни на ядрото.
Line 48: Line 50:
 
Now some basic features have been enabled, we need to finish the configuration by using the struct uinput_user_dev from linux/uinput.h. This structure is defined as:
 
Now some basic features have been enabled, we need to finish the configuration by using the struct uinput_user_dev from linux/uinput.h. This structure is defined as:
  
/usr/include/linux/uinput.h
+
/usr/include/linux/uinput.h
#define UINPUT_MAX_NAME_SIZE    80
+
#define UINPUT_MAX_NAME_SIZE    80
struct uinput_user_dev {
+
struct uinput_user_dev {
 
     char name[UINPUT_MAX_NAME_SIZE];
 
     char name[UINPUT_MAX_NAME_SIZE];
 
     struct input_id id;
 
     struct input_id id;
Line 58: Line 60:
 
         int absfuzz[ABS_MAX + 1];
 
         int absfuzz[ABS_MAX + 1];
 
         int absflat[ABS_MAX + 1];
 
         int absflat[ABS_MAX + 1];
};
+
};
 +
 
 
The most important fields are:
 
The most important fields are:
 +
*name is the given name to the input device we will create,
 +
*id is a linux internal structure that describes the device bustype, vendor id, product id and version,
 +
*absmin and absmax are integer array that defines mininal and maximal values for an absolute axis (i.e *absmin[ABS_X] = 0, absmax[ABS_X] = 1024 for the X axis on a touchscreen device).
  
name is the given name to the input device we will create,
 
id is a linux internal structure that describes the device bustype, vendor id, product id and version,
 
absmin and absmax are integer array that defines mininal and maximal values for an absolute axis (i.e absmin[ABS_X] = 0, absmax[ABS_X] = 1024 for the X axis on a touchscreen device).
 
 
Now, we can fill this structure with appropriate values:
 
Now, we can fill this structure with appropriate values:
 +
struct uinput_user_dev uidev;
 +
memset(&uidev, 0, sizeof(uidev));
 +
 +
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-sample");
 +
uidev.id.bustype = BUS_USB;
 +
uidev.id.vendor  = 0x1234;
 +
uidev.id.product = 0xfedc;
 +
uidev.id.version = 1;
  
struct uinput_user_dev uidev;
+
Then, we write this structure in the uinput file descriptor.
  
memset(&uidev, 0, sizeof(uidev));
+
ret = write(fd, &uidev, sizeof(uidev));
  
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-sample");
+
Last step is to request the creation of the device via the UI_DEV_CREATE ioctl request on the file descriptor:
uidev.id.bustype = BUS_USB;
 
uidev.id.vendor  = 0x1234;
 
uidev.id.product = 0xfedc;
 
uidev.id.version = 1;
 
Then, we write this structure in the uinput file descriptor.
 
  
ret = write(fd, &uidev, sizeof(uidev));
+
ret = ioctl(fd, UI_DEV_CREATE);
Last step is to request the creation of the device via the UI_DEV_CREATE ioctl request on the file descriptor:
 
  
ret = ioctl(fd, UI_DEV_CREATE);
 
 
Now, the file descriptor fd represents the end-point file descriptor of the new input device.
 
Now, the file descriptor fd represents the end-point file descriptor of the new input device.
  
2. Injecting events in the input subsystem
+
===Injecting events in the input subsystem===
  
 
The following block code injects a key press event in the input subsystem. The input_event structure contains 3 important fields:
 
The following block code injects a key press event in the input subsystem. The input_event structure contains 3 important fields:
 +
*type: is an event type (EV_KEY, EV_ABS, EV_REL, ...),
 +
*code: could be either a key code when using EV_KEY, or an axis for EV_ABS and EV_REL,
 +
*value: may be 1 (press) or 0 (release) for EV_KEY, or any values for others (positive integer for EV_ABS, signed integer for EV_REL, etc…).
  
type: is an event type (EV_KEY, EV_ABS, EV_REL, ...),
 
code: could be either a key code when using EV_KEY, or an axis for EV_ABS and EV_REL,
 
value: may be 1 (press) or 0 (release) for EV_KEY, or any values for others (positive integer for EV_ABS, signed integer for EV_REL, etc…).
 
 
To inject a press event on the 'd' key:
 
To inject a press event on the 'd' key:
 +
struct input_event ev;
 +
memset(&ev, 0, sizeof(ev));
 +
ev.type = EV_KEY;
 +
ev.code = KEY_D;
 +
ev.value = 1;
 +
ret = write(fd, &ev, sizeof(ev));
 +
===Destroying an input device===
 +
ret = ioctl(fd, UI_DEV_DESTROY);
  
struct input_event ev;
+
===Handling absolute axis events===
 
 
memset(&ev, 0, sizeof(ev));
 
 
 
ev.type = EV_KEY;
 
ev.code = KEY_D;
 
ev.value = 1;
 
 
 
ret = write(fd, &ev, sizeof(ev));
 
3. Destroying an input device
 
 
 
ret = ioctl(fd, UI_DEV_DESTROY);
 
4. Handling absolute axis events
 
  
 
If we want to inject absolute events, we first need to activate EV_ABS event and the desired axes support with ioctl requests. The following ioctl requests enable X and Y absolute axes:
 
If we want to inject absolute events, we first need to activate EV_ABS event and the desired axes support with ioctl requests. The following ioctl requests enable X and Y absolute axes:
  
ret = ioctl(fd, UI_SET_EVBIT, EV_ABS);
+
ret = ioctl(fd, UI_SET_EVBIT, EV_ABS);
...
+
...
 +
ret = ioctl(fd, UI_SET_ABSBIT, ABS_X);
 +
...
 +
ret = ioctl(fd, UI_SET_ABSBIT, ABS_Y);
  
ret = ioctl(fd, UI_SET_ABSBIT, ABS_X);
 
...
 
ret = ioctl(fd, UI_SET_ABSBIT, ABS_Y);
 
 
Then we need to defined a range of values for each axis with absmin and absmax fields from the uinput_user_dev structure:
 
Then we need to defined a range of values for each axis with absmin and absmax fields from the uinput_user_dev structure:
  
uidev.absmin[ABS_X] = 0;
+
uidev.absmin[ABS_X] = 0;
uidev.absmax[ABS_X] = 1023;
+
uidev.absmax[ABS_X] = 1023;
 +
 
 
Event injection follows the same method as for any other events.
 
Event injection follows the same method as for any other events.
 
+
struct input_event ev[2];
struct input_event ev[2];
+
memset(ev, 0, sizeof(ev));
 
+
ev[0].type = EV_ABS;
memset(ev, 0, sizeof(ev));
+
ev[0].code = ABS_X;
 
+
ev[0].value = 1023;
ev[0].type = EV_ABS;
+
ev[1].type = EV_ABS;
ev[0].code = ABS_X;
+
ev[1].code = ABS_Y;
ev[0].value = 1023;
+
ev[1].value = 767;
ev[1].type = EV_ABS;
+
ret = write(fd, ev, sizeof(ev));
ev[1].code = ABS_Y;
 
ev[1].value = 767;
 
 
 
ret = write(fd, ev, sizeof(ev));
 
  
 
== Виртуална мишка ==
 
== Виртуална мишка ==

Revision as of 00:17, 26 March 2013


uinput

Вход от потрeбителско ниво


Uinput е модул за linux ядрото, който позволява управление на системата за входни данни от приложения работещи на потребителско ниво. Модулът uinput създава виртуално входно устройство.


Създаване на входно устройство

След инсталиране на модула uinput (чрез modprobe или insmod) се създава устройство от буквен тип с име /dev/input/uinput (или /dev/uinput). Това устройство представлява интерфейса между риложението и системата за входни данни на ядрото.

За да се използва uinput, то устройство трябва трябва да се отвори само за запис и неблокиращ режим.

#include <linux/input.h>
#include <linux/uinput.h>
...

int fd;

fd = open("/dev/input/uinput", O_WRONLY | O_NONBLOCK);
if(fd < 0) {
   ...
   exit(EXIT_FAILURE);
}

След като е отворено устройството трябва да се конфигурира. Първо трябва да се инициализират типовете входни събития, които ще се ползват. Типовете събития са дефинирани в /usr/include/linux/input.h:

...

#define EV_KEY          0x01
#define EV_REL          0x02
#define EV_ABS          0x03
...
  • EV_KEY събитие за натиснат или отпуснат бутон от клавиатурата,
  • EV_REL събитие за относително отместване (such as mouse movements),
  • EV_ABS събитие за абсолютно отместване (such as touchscreen movements),

Активиране на събития чрез ioctl. Следните редове активират събития натискане/отпускане на бутон и синхронизация.

ret = ioctl(fd, UI_SET_EVBIT, EV_KEY);
ret = ioctl(fd, UI_SET_EVBIT, EV_SYN);

При активиране на ЕV_KEY събитие, трябва да се опишат и възможните бутони, които ще бъдат изпращани. За 'd' се дефинира по следния начин:

ret = ioctl(fd, UI_SET_KEYBIT, KEY_D);

Now some basic features have been enabled, we need to finish the configuration by using the struct uinput_user_dev from linux/uinput.h. This structure is defined as:

/usr/include/linux/uinput.h
#define UINPUT_MAX_NAME_SIZE    80
struct uinput_user_dev {
   char name[UINPUT_MAX_NAME_SIZE];
   struct input_id id;
       int ff_effects_max;
       int absmax[ABS_MAX + 1];
       int absmin[ABS_MAX + 1];
       int absfuzz[ABS_MAX + 1];
       int absflat[ABS_MAX + 1];
};

The most important fields are:

  • name is the given name to the input device we will create,
  • id is a linux internal structure that describes the device bustype, vendor id, product id and version,
  • absmin and absmax are integer array that defines mininal and maximal values for an absolute axis (i.e *absmin[ABS_X] = 0, absmax[ABS_X] = 1024 for the X axis on a touchscreen device).

Now, we can fill this structure with appropriate values:

struct uinput_user_dev uidev;
memset(&uidev, 0, sizeof(uidev));

snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-sample");
uidev.id.bustype = BUS_USB;
uidev.id.vendor  = 0x1234;
uidev.id.product = 0xfedc;
uidev.id.version = 1;

Then, we write this structure in the uinput file descriptor.

ret = write(fd, &uidev, sizeof(uidev));

Last step is to request the creation of the device via the UI_DEV_CREATE ioctl request on the file descriptor:

ret = ioctl(fd, UI_DEV_CREATE);

Now, the file descriptor fd represents the end-point file descriptor of the new input device.

Injecting events in the input subsystem

The following block code injects a key press event in the input subsystem. The input_event structure contains 3 important fields:

  • type: is an event type (EV_KEY, EV_ABS, EV_REL, ...),
  • code: could be either a key code when using EV_KEY, or an axis for EV_ABS and EV_REL,
  • value: may be 1 (press) or 0 (release) for EV_KEY, or any values for others (positive integer for EV_ABS, signed integer for EV_REL, etc…).

To inject a press event on the 'd' key:

struct input_event ev;
memset(&ev, 0, sizeof(ev));
ev.type = EV_KEY;
ev.code = KEY_D;
ev.value = 1;
ret = write(fd, &ev, sizeof(ev));

Destroying an input device

ret = ioctl(fd, UI_DEV_DESTROY);

Handling absolute axis events

If we want to inject absolute events, we first need to activate EV_ABS event and the desired axes support with ioctl requests. The following ioctl requests enable X and Y absolute axes:

ret = ioctl(fd, UI_SET_EVBIT, EV_ABS);
...
ret = ioctl(fd, UI_SET_ABSBIT, ABS_X);
...
ret = ioctl(fd, UI_SET_ABSBIT, ABS_Y);

Then we need to defined a range of values for each axis with absmin and absmax fields from the uinput_user_dev structure:

uidev.absmin[ABS_X] = 0;
uidev.absmax[ABS_X] = 1023;

Event injection follows the same method as for any other events.

struct input_event ev[2];
memset(ev, 0, sizeof(ev));
ev[0].type = EV_ABS;
ev[0].code = ABS_X;
ev[0].value = 1023;
ev[1].type = EV_ABS;
ev[1].code = ABS_Y;
ev[1].value = 767;
ret = write(fd, ev, sizeof(ev));

Виртуална мишка

#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>

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

    fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
        if(fd < 0) exit(0);
        
    ioctl(fd, UI_SET_EVBIT, EV_KEY);
    ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
    
    ioctl(fd, UI_SET_EVBIT, EV_REL);
    ioctl(fd, UI_SET_RELBIT, REL_X);
    ioctl(fd, UI_SET_RELBIT, REL_Y);
    
     

    memset(&uidev, 0, sizeof(uidev));
    snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-sample");
    uidev.id.bustype = BUS_USB;
    uidev.id.vendor  = 0x1;
    uidev.id.product = 0x1;
    uidev.id.version = 1;

    write(fd, &uidev, sizeof(uidev));
    ioctl(fd, UI_DEV_CREATE);

    sleep(3);

    dx = -100;
    dy = -10;
          
    memset(&ev, 0, sizeof(struct input_event));
    ev.type = EV_REL;
    ev.code = REL_X;
    ev.value = dx;
    write(fd, &ev, sizeof(struct input_event));
         
    memset(&ev, 0, sizeof(struct input_event));
    ev.type = EV_REL;
    ev.code = REL_Y;
    ev.value = dy;
    write(fd, &ev, sizeof(struct input_event));

    нулиране
    memset(&ev, 0, sizeof(struct input_event));
    ev.type = BTN_LEFT;
    ev.code = 0;
    ev.value = 0;
    write(fd, &ev, sizeof(struct input_event));

    ioctl(fd, UI_DEV_DESTROY);
    close(fd);
    return 0;
}
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main()
{
    int fd;
    struct input_event ev;

    fd = open("/dev/input/event3", O_RDONLY);
    if(fd < 0) {
        printf("error openning");
        return 1;
    }
    
    
    while (1)
    {
    read(fd, &ev, sizeof(struct input_event));

    if(ev.type == 1)
        printf("key %i state %i\n", ev.code, ev.value);

    }
}

chmod

~$ sudo chmod 777 /dev/input/event3
~$ sudo chmod 777 /dev/uinput


http://web.me.com/haroldsoh/tutorials/technical-skills/using-optical-mice-for-othe-2/