如何使用 Linux 获取触摸屏原始数据的坐标 [英] How to get Coordinates of Touchscreen Rawdata using Linux

查看:20
本文介绍了如何使用 Linux 获取触摸屏原始数据的坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个 3m 的微触摸显示屏.它通过 USB 连接到我的 Debian 系统并被识别为人机界面(隐藏).我正在尝试访问和推送实时信息......如果它被触及,我想知道 (x,y) 的位置并将其通过 netcat 管道传输到另一台主机.

We have a 3m microtouch display. It's connected to my Debian system via USB and recognized as human interface (hid). I am trying to access and push realtime information... if its getting touched I want to know where (x,y) and pipe it through netcat to another host.

不幸的是,我只能使用以下方法获取原始数据:

Unfortunately I am only able to get raw data using:

cat /dev/input/event2 | hexdump

evtest

你得到的十六进制代码似乎没有任何记录......

You get hexcode that seem nowhere documented...

有人知道如何获取这些信息吗?必须有一种方法可以从十六进制代码中提取它.不幸的是,我不知道如何解释十六进制代码.我找不到任何记录在案的来源...

Does anybody have a clue how to get that information? There must be a way to extract it from the hexcode. Unfortunately I have no idea how to interpret the hexcode. I couldn't find any source where its documented...

内核是否可以实时为我提供所需的信息?

Is there a way the Kernel could provide me those desired information in realtime?

作为一种解决方法,是否有 X-Server 可以告诉我的解决方案?触摸屏的行为就像 X 中的鼠标.实际上我已经尝试通过 xlib 获取鼠标的 x,y 位置.但是它太慢了,如果有人在触摸,它不会告诉我...

As a workaround, is there, maybe, a solution where the X-Server could tell me? The touchscreen behaves like a mouse in X. I actually already tried to get x,y-position of the mouse via xlib. But it was too slow and wouldn't tell me if somebody is touching or not...

evtest 示例输出:

Event: time 1425319271.595631, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 51
Event: time 1425319271.595631, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 10304
Event: time 1425319271.595631, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 30629
Event: time 1425319271.595631, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 893
Event: time 1425319271.595631, type 3 (EV_ABS), code 49 (ABS_MT_TOUCH_MINOR), value 414
Event: time 1425319271.595631, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1425319271.595631, type 3 (EV_ABS), code 0 (ABS_X), value 10304
Event: time 1425319271.595631, type 3 (EV_ABS), code 1 (ABS_Y), value 30629
Event: time 1425319271.595631, -------------- SYN_REPORT ------------
Event: time 1425319271.601632, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 10306
Event: time 1425319271.601632, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 30625
Event: time 1425319271.601632, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 962
Event: time 1425319271.601632, type 3 (EV_ABS), code 49 (ABS_MT_TOUCH_MINOR), value 421
Event: time 1425319271.601632, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 1
Event: time 1425319271.601632, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 52
Event: time 1425319271.601632, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 15416
Event: time 1425319271.601632, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 24159
Event: time 1425319271.601632, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 649
Event: time 1425319271.601632, type 3 (EV_ABS), code 49 (ABS_MT_TOUCH_MINOR), value 354
Event: time 1425319271.601632, type 3 (EV_ABS), code 0 (ABS_X), value 10306
Event: time 1425319271.601632, type 3 (EV_ABS), code 1 (ABS_Y), value 30625
Event: time 1425319271.601632, -------------- SYN_REPORT ------------
Event: time 1425319271.606626, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 0
Event: time 1425319271.606626, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 10318
Event: time 1425319271.606626, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 30609
Event: time 1425319271.606626, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 1014
Event: time 1425319271.606626, type 3 (EV_ABS), code 49 (ABS_MT_TOUCH_MINOR), value 426
Event: time 1425319271.606626, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 1
Event: time 1425319271.606626, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 24161
Event: time 1425319271.606626, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 681
Event: time 1425319271.606626, type 3 (EV_ABS), code 49 (ABS_MT_TOUCH_MINOR), value 376
Event: time 1425319271.606626, type 3 (EV_ABS), code 0 (ABS_X), value 10318
Event: time 1425319271.606626, type 3 (EV_ABS), code 1 (ABS_Y), value 30609
Event: time 1425319271.606626, -------------- SYN_REPORT ------------
Event: time 1425319271.611629, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 0
Event: time 1425319271.611629, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 10320
Event: time 1425319271.611629, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 30605
Event: time 1425319271.611629, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 1053
Event: time 1425319271.611629, type 3 (EV_ABS), code 49 (ABS_MT_TOUCH_MINOR), value 430
Event: time 1425319271.611629, type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 1
Event: time 1425319271.611629, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 705
Event: time 1425319271.611629, type 3 (EV_ABS), code 49 (ABS_MT_TOUCH_MINOR), value 392
Event: time 1425319271.611629, type 3 (EV_ABS), code 0 (ABS_X), value 10320
Event: time 1425319271.611629, type 3 (EV_ABS), code 1 (ABS_Y), value 30605

推荐答案

基于控制台的解决方案

您可以使用 evtest 工具获取解析后的坐标.

Console-based solution

You can obtain parsed coordinates using evtest tool.

  1. 如果您只需要单点触摸坐标:查找ABS_XABS_Y 字段:

 type 3 (EV_ABS), code 0 (ABS_X), value 10306
 type 3 (EV_ABS), code 1 (ABS_Y), value 30625

  • 如果您需要多点触控坐标:

  • If you need multi-touch coordinates:

    • ABS_MT_SLOT 代表手指数
    • ABS_MT_POSITION_XABS_MT_POSITION_Y -- 坐标
    • ABS_MT_SLOT represents number of finger
    • ABS_MT_POSITION_X and ABS_MT_POSITION_Y -- coordinates

    手指 #0:

     type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 0
     type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 10318
     type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 30609
    

    手指 #1:

     type 3 (EV_ABS), code 47 (ABS_MT_SLOT), value 1
     type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 20301
     type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 24161
    

  • 例如,如果您需要通过网络发送单点触摸坐标,您可以使用这样的脚本:

    For example, if you need to send single-touch coordinates via network, you can use script like this:

    #!/bin/sh
    
    # ---- Global variables ----
    
    input=/dev/input/event0
    code_prefix="ABS"
    code="${code_prefix}_[XY]"
    val_regex=".*(${code_prefix}_(.)), value ([-]?[0-9]+)"
    val_subst="1=2"
    
    # ---- Functions ----
    
    send_axis() {
        # 1. Convert axis value ($1) from device specific units
        # 2. Send this axis value via UDP packet
        echo $1
    }
    
    process_line() {  
        while read line; do
            axis=$(echo $line | grep "^Event:" | grep $code | 
                   sed "s/$val_regex/$val_subst/")
    
            if [ -n "$axis" ]; then
                send_axis $axis
            fi
        done
    }
    
    # ---- Entry point ----
    
    if [ $(id -u) -ne 0 ]; then
        echo "This script must be run from root" >&2
        exit 1
    fi
    
    evtest $input | process_line
    

    基于程序的解决方案

    您可以编写 C 应用程序来读取您的事件文件.获得的二进制数据可以很容易地解释,请参阅内核文档中的第 5 节.您可以使用 select() 系统调用等待下一个数据部分.

    Program-based solution

    You can write C application that will read your event file. Obtained binary data can be easily interpreted, see section 5 in kernel documentation. You can wait for next data portion using select() syscall.

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <linux/input.h>
    
    #define EVENT_DEVICE    "/dev/input/event2"
    #define EVENT_TYPE      EV_ABS
    #define EVENT_CODE_X    ABS_X
    #define EVENT_CODE_Y    ABS_Y
    
    /* TODO: Close fd on SIGINT (Ctrl-C), if it's open */
       
    int main(int argc, char *argv[])
    {
        struct input_event ev;
        int fd;
        char name[256] = "Unknown";
    
        if ((getuid()) != 0) {
            fprintf(stderr, "You are not root! This may not work...
    ");
            return EXIT_SUCCESS;
        }
    
        /* Open Device */
        fd = open(EVENT_DEVICE, O_RDONLY);
        if (fd == -1) {
            fprintf(stderr, "%s is not a vaild device
    ", EVENT_DEVICE);
            return EXIT_FAILURE;
        }
    
        /* Print Device Name */
        ioctl(fd, EVIOCGNAME(sizeof(name)), name);
        printf("Reading from:
    ");
        printf("device file = %s
    ", EVENT_DEVICE);
        printf("device name = %s
    ", name);
    
        for (;;) {
            const size_t ev_size = sizeof(struct input_event);
            ssize_t size;
    
            /* TODO: use select() */
    
            size = read(fd, &ev, ev_size);
            if (size < ev_size) {
                fprintf(stderr, "Error size when reading
    ");
                goto err;
            }
    
            if (ev.type == EVENT_TYPE && (ev.code == EVENT_CODE_X
                          || ev.code == EVENT_CODE_Y)) {
                /* TODO: convert value to pixels */
                printf("%s = %d
    ", ev.code == EVENT_CODE_X ? "X" : "Y",
                        ev.value);
            }
        }
    
        return EXIT_SUCCESS;
    
    err:
        close(fd);
        return EXIT_FAILURE;
    }
    

    坐标单位

    首先你需要知道接下来的事情:

    Coordinates units

    First of all you need to know next things:

    • 坐标原点在哪里(即[x=0;y=0])
    • 您的设备用于表示坐标的单位

    此信息通常可以在您设备的驱动程序代码中找到.

    This information usually can be found in driver code for your device.

    这个是您的驱动程序设备.

    因此,您似乎需要将 evtest 中的轴值除以 65535,然后乘以设备的宽度或高度(以像素为单位).例如,如果你得到 X=30000,你的 LCD 面板的宽度是 1080 像素,你需要这样做:

    So it seems like you need to divide your axis value from evtest by 65535 and multiply it by width or height of device (in pixels). For example, if you get X=30000, and width of your LCD panel is 1080 pixels, you need to do:

    X = round((30000 / 65535) * 1080) = 494 pixels
    

    这篇关于如何使用 Linux 获取触摸屏原始数据的坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆