'In android how to find what /dev/input/event* is used for touchscreen using c function

I am trying to read touchscreen event, in my device /dev/input/event4 is used for touchscreen, while in some other phone, event7 is used for touchscreen.

I am looking for a c function that can help me to find that touchscreen event.



Solution 1:[1]

Each input event device has a corresponding entry in the /sys/class/input/ pseudo-file hierarchy. (See Linux Input Subsystem userspace API in the Linux kernel documentation for further details.) For example, the name of the device corresponding to event7 is in /sys/class/input/event7/device/name.

When you open the event character device (/dev/input/event7), you can use the EVIOCGBIT(type, bits) ioctl to check which kind of events the device can produce. Touchpads will produce EV_ABS events ABS_X and ABS_Y, and EV_KEY event BTN_TOUCH.

Therefore, if you glob /dev/input/event*, open each device in turn, and check if they report the abovementioned three events, you are likely to find the device you look for. For example:

#define  _POSIX_C_SOURCE  200809L
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <linux/input.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <glob.h>
#include <errno.h>
#include <stdio.h>

#ifndef  ULONG_BITS
#define  ULONG_BITS   (CHAR_BIT * sizeof (unsigned long))
#endif

static inline int  has_bit(const unsigned long  data[], const size_t  bit)
{
    return !!(data[bit / ULONG_BITS] & (1uL << (bit % ULONG_BITS)));
}

char *touchscreen_event_device(size_t skip)
{
    glob_t  files;
    int     result;

    result = glob("/dev/input/event*", 0, NULL, &files);
    if (result) {
        if (result == GLOB_NOSPACE) {
            errno = ENOMEM;
            return NULL;
        } else
        if (result == GLOB_NOMATCH) {
            errno = ENOENT;
            return NULL;
        } else {
            errno = EACCES;
            return NULL;
        }
    }

    for (size_t  i = 0;  i < files.gl_pathc;  i++) {
        int  fd = open(files.gl_pathv[i], O_RDONLY);
        if (fd != -1) {
            unsigned long  absbits[1 + ABS_MAX / ULONG_BITS] = { 0 };
            unsigned long  keybits[1 + KEY_MAX / ULONG_BITS] = { 0 };
            if (ioctl(fd, EVIOCGBIT(EV_ABS, ABS_MAX+1), &absbits) != -1 &&
                ioctl(fd, EVIOCGBIT(EV_KEY, KEY_MAX+1), &keybits) != -1) {
                if (has_bit(absbits, ABS_X) &&
                    has_bit(absbits, ABS_Y) &&
                    has_bit(keybits, BTN_TOUCH)) {
                    /* Device reports ABS_X, ABS_Y and BTN_TOUCH,
                       and therefore is a touchpad device. */
                    if (!skip) {
                        char *devpath = strdup(files.gl_pathv[i]);
                        close(fd);
                        globfree(&files);
                        if (!devpath)
                            errno = ENOMEM;
                        return devpath;
                    } else {
                        skip--;
                    }
                }
            }
            close(fd);
        }
    }
    globfree(&files);

    errno = ENOENT;
    return NULL;
}

int main(void)
{
    size_t  i = 0;

    while (1) {
        char *devpath = touchscreen_event_device(i);
        if (!devpath) {
            if (i)
                break;
            fprintf(stderr, "No touchscreen input event devices found: %s.\n", strerror(errno));
            return EXIT_FAILURE;
        }
        printf("Found touchscreen input event device '%s'\n", devpath);
        free(devpath);
        i++;
    }

    return EXIT_SUCCESS;
}

Compile using e.g. gcc -Wall -Wextra -O2 example.c -o example, and run with root privileges, and it will list the paths to the input event devices it believes are touch screens.

Solution 2:[2]

An answer for a complete code could be difficult because it's a long/heavy work. I'll point you in right directions:

  • read "Input Event Codes": https://www.kernel.org/doc/html/v4.14/input/event-codes.html
  • then you have to list all /dev/input/* files
  • open each of them using "fd = open("/dev/input/xxxxx", O_RDONLY);"
  • call "ioctl(fd, EVIOCGBIT(EV_REL, sizeof(maskbit)), maskbit)" (calling this changing "EV_REL" with others "Input Event Codes"
  • analize "maskbit" by searching for some specific Values that only Touchscreen has

A possibile example could find here: https://android.googlesource.com/device/generic/brillo/+/d1917142dc905d808519023d80a664c066104600/examples/keyboard/keyboard_example.cpp in which the author looking for an Input that supports "KEY_B" Event Code.

Touchscreens should have:

  • for EV_ABS:
    • ABS_X
    • ABS_Y
    • ABS_MT_SLOT
    • ABS_MT_POSITION_X
    • ABS_MT_POSITION_Y
    • ABS_MT_TRACKING_ID

If the Input has all these Bit it is a Touchscreen (reference: https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt)

Solution 3:[3]

adb shell dumpsys input - this will show the list of all event nodes with the details that you are looking for

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Glärbo
Solution 2 emandt
Solution 3 sanandane-codeguru