【问题标题】:In android how to find what /dev/input/event* is used for touchscreen using c function在android中如何使用c函数查找/dev/input/event*用于触摸屏
【发布时间】:2021-03-09 05:24:28
【问题描述】:

我正在尝试读取触摸屏事件,在我的设备中 /dev/input/event4 用于触摸屏,而在其他手机中,event7 用于触摸屏。

我正在寻找可以帮助我的 c 函数 找到那个触摸屏事件。

【问题讨论】:

    标签: android c linux touch-event


    【解决方案1】:

    每个输入事件设备在/sys/class/input/ 伪文件层次结构中都有对应的条目。 (更多细节参见Linux内核文档中的Linux Input Subsystem userspace API。)例如,event7对应的设备名称在/sys/class/input/event7/device/name中。

    当您打开事件字符设备(/dev/input/event7)时,您可以使用 EVIOCGBIT(type, bits) ioctl 来检查设备可以产生哪种事件。触摸板会产生 EV_ABS 事件 ABS_X 和 ABS_Y,以及 EV_KEY 事件 BTN_TOUCH。

    因此,如果你 glob /dev/input/event*,依次打开每个设备,并检查它们是否报告了上述三个事件,你很可能会找到你要查找的设备。例如:

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

    使用例如编译gcc -Wall -Wextra -O2 example.c -o example,并以root权限运行,它会列出它认为是触摸屏的输入事件设备的路径。

    【讨论】:

      【解决方案2】:

      完整代码的答案可能很困难,因为这是一项漫长/繁重的工作。 我会为您指明正确的方向:

      • 读取“输入事件代码”:https://www.kernel.org/doc/html/v4.14/input/event-codes.html
      • 那么你必须列出所有 /dev/input/* 文件
      • 使用 "fd = open("/dev/input/xxxxx", O_RDONLY);" 打开它们中的每一个
      • 调用“ioctl(fd, EVIOCGBIT(EV_REL, sizeof(maskbit)), maskbit)”(调用这个改变“EV_REL”与其他“输入事件代码”
      • 通过搜索一些只有触摸屏具有的特定值来分析“maskbit”

      一个可能的例子可以在这里找到:https://android.googlesource.com/device/generic/brillo/+/d1917142dc905d808519023d80a664c066104600/examples/keyboard/keyboard_example.cpp,作者在其中寻找支持“KEY_B”事件代码的输入。

      触摸屏应该有:

      • 对于 EV_ABS
        • ABS_X
        • ABS_Y
        • ABS_MT_SLOT
        • ABS_MT_POSITION_X
        • ABS_MT_POSITION_Y
        • ABS_MT_TRACKING_ID

      如果输入具有所有这些位,则它是触摸屏(参考:https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt

      【讨论】:

        猜你喜欢
        • 2016-07-20
        • 2013-09-10
        • 1970-01-01
        • 1970-01-01
        • 2015-02-14
        • 2011-06-30
        • 2014-09-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多