Overview
What is the Input Subsystem?
The input subsystem is the part of the Linux kernel that manages the various input devices (such as keyboards, mice, joysticks, tablets and a wide range of other devices) that a user uses to interact with the kernel, command line and graphical user interface.
This subsystem is included in the Linux kernel because these devices usually are accessed through special hardware interfaces (such as serial ports, PS/2 ports and the Universal Serial Bus), which are protected and managed by the kernel.
The kernel then exposes the user input in a consistent, device-independent way to user space through a range of defined APIs.
System Framework
Event-driven layer
Is responsible standard Interface and applications
Core layer
Provide the necessary event-driven layer and device driver layer function interface
Device driver layer
Responsible for communications with the underlying input devices and provide the events to upper layers.
Flow: low-level hardware –> drivers –> input core –> handler –> user space
Event-driven and core layer are common, we need to implement the device driver layer. Input device drivers will capture the hardware event information in a uniform format (struct input_event) and report to the core layer, then the core layer sorts the data, then escalated to the appropriate event-handling driver, and finally through the events layer to the user space, applications using /dev device node can get event information.
Unified format
Driver submit hardware event information using struct input_event, applications can also use this structure to obtain event information:
struct input_event {
struct timeval time; /Event generated time/
__u16type; /Type of event/
__u16code; /Event code/
__s32value; /Event value/
};
Event type, as defined in linux/input.h
# | Event code | Specifies |
0x00 | EV_SYN | Separate/synchronize other events (e.g. SYN_REPORT/SYN_MT_REPORT), or report events lost (SYN_DROPPED) |
0x01 | EV_KEY | Key press (KEY_*) or touch (BTN_TOUCH) |
0x02 | EV_REL | Relative changes to a property. Changes relayed through REL_[XYZ] values. |
0x03 | EV_ABS | Absolute coordinates for an event. Values are usually ABS_[XYZ], or ABS_MT for multi-touch |
0x04 | EV_MSC | Miscellaneous codes |
0x05 | EV_SW | Binary switches. E.g. SW_JACK_PHYSICAL_INSERT for headphone insertion |
0x11 | EV_LED | Used for device LEDs, if any |
0x12 | EV_SND | Used for sound devices |
0x14 | EV_REP | Used for auto-repeating events |
0x15 | EV_FF | Used for force-feedback capable devices (e.g. joysticks). An EVIOCSFF ioctl may be used to upload force feedback effects |
0x16 | EV_PWR | Reserved for power events. Largely unused |
0x17 | EV_FF_STATUS | Used for force-feedback capable devices. |
Event code, contains a wide variety of different event type code
EV_KEY KEY_1, KEY_2, KEY_3…
EV_REL REL_X, REL_Y, REL_Z…
EV_ABS ABS_X, ABS_Y, ABS_Z…
And so on….
Event value, generated by the input devices hardware, such as key device drivers will get hardware status using kernel gpio framework (Assuming active low), 0 if pressed, and 1 if released.
Realization of the input device driver
input_dev structure to describe an input device
struct input_dev{
/* Export the information into user space, in the sysfs can be seen*/
const char *name;
const char *phys;
const char *uniq;
struct input_id id;
…………………
unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; /Input device supports bitmaps/
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; /The event code key device supports bitmaps/
……
}
evbit, bitmap of types of events supported by the device (EV_KEY, EV_REL, etc.)
keybit, bitmap of keys/buttons this device has
Set the supported event types and event codes, which the input devices are capable of processing, usually we use set_bit() function to set rather than by direct assignment
Set supported event types (Support for key events)
set_bit(EV_KEY, input_dev->evbit);
Sets the event code support(Support press1)
set_bit(KEY_1, input_dev->keybit);
We can also directly call input_set_capability() to complete the assignment in a single step.
input_set_capability(input_dev,EV_KEY, KEY_1);
The kernel interface provides a set of functions for us to realize the input device driver
Allocation/Release of an input device:
struct input_dev* input_allocate_device(void)
void input_free_device(struct input_dev *dev)
input_allocate_device: After successful allocation will return a pointer to struct input_dev
Register and unregister input device
int input_register_device(struct input_dev*dev)
void input_unregister_device(struct input_dev*dev)
Registration function uses to input_dev register an input device in a core layer, cancellation is contrary. Parameter dev is input_allocate_device return value.
Report input events
Report key
void input_report_key(struct input_dev *dev, unsigned int code, int value)
Reports relative coordinates
void input_report_rel(struct input_dev *dev, unsigned int code, int value)
Report absolute coordinates
void input_report_abs(struct input_dev *dev, unsigned int code, int value)
Used to synchronize events to prevent data corruption
void input_sync(struct input_dev *dev)
Code:
Input Subsystem key-driven code, Hardware platform: s3c2440
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <asm/irq.h>
#include <asm/io.h>
#define DEV_NAME “KEY1”
#define BUTTON_IRQ IRQ_EINT8
Static struct input_dev *button_dev;
Static irqreturn_t button_interrupt (int irq, void *p)
{
/*get pin value <down 0, up 1> */
intval = s3c2410_gpio_getpin(S3C2410_GPG(0));
input_report_key(button_dev,KEY_1, val);
input_sync(button_dev);
return IRQ_RETVAL(IRQ_HANDLED);
}
Static int __init button_init(void)
{
Int err;
/* Interrupt registration*/
if(request_irq(BUTTON_IRQ, button_interrupt,
IRQ_TYPE_EDGE_BOTH,DEV_NAME, NULL)) {
printk(KERN_ERR “cannot allocate irq”);
return- EBUSY;
}
/*allocate input_dev */
button_dev= input_allocate_device();
if(button_dev == NULL) {
printk(KERN_ERR “notenough memory\n”);
err= – ENOMEM;
gotoerr_free_irq;
}
/Set the input device supported event types and event code/
set_bit(EV_KEY,button_dev->evbit);
set_bit(KEY_1,button_dev->keybit);
/*Registration of input devices into the core */
err= input_register_device(button_dev);
if(err) {
printk(KERN_ERR “failed to register device\n”);
goto err_free_dev;
}
printk(“initialized\n”);
return0;
err_free_dev:
input_free_device(button_dev);
err_free_irq:
free_irq(BUTTON_IRQ,NULL);
return err;
}
static void __exit button_exit(void)
{
input_unregister_device(button_dev);
input_free_device(button_dev);
free_irq(BUTTON_IRQ,NULL);
}
module_init(button_init);
module_exit(button_exit);
MODULE_LICENSE(“Dual BSD/GPL”);
In the next upcoming session, we shall further have in-depth analysis of Input Subsystem elements and understand how event handlers and linked with the input device driver in core layer.
Hi Dhruv , its a nice blog . Can u plz tell how does the application will interact with this driver. Probably a example code of Appl & Driver for the touch screen can give me a clear picture.
Thanks in advance
– Balaji
LikeLiked by 1 person
Thanks for your feedback balaji.
Request you to click on “Follow” button. so that you shall receive all the updates 🙂
LikeLike