加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

如何使用Linux获取Touchscreen Rawdata的坐标

发布时间:2020-12-14 02:18:45 所属栏目:Linux 来源:网络整理
导读:我们有一个3米的微触摸显示屏.它通过usb连接到我的debian系统,并被识别为人机界面(hid).我正在尝试访问并推送实时信息…如果它被触及我想知道哪里(x,y)并通过netcat管道到另一台主机. 不幸的是,我只能使用原始数据 cat /dev/input/event2 | hexdump 要么 evt
我们有一个3米的微触摸显示屏.它通过usb连接到我的debian系统,并被识别为人机界面(hid).我正在尝试访问并推送实时信息…如果它被触及我想知道哪里(x,y)并通过netcat管道到另一台主机.

不幸的是,我只能使用原始数据

cat /dev/input/event2 | hexdump

要么
evtest

你得到的hexcode似乎没有记录……

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

有没有办法让内核能够实时提供我想要的信息?
作为一个解决方案,可能有一个X-Server可以告诉我的解决方案?触摸屏的行为类似于X中的鼠标.我实际上已经尝试通过xlib获取鼠标的x,y位置.但它太慢了,无法告诉我是否有人在接触……

提前致谢!

evtest样本输出:

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

解决方法

基于控制台的解决方案

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

>如果您只需要单点触控坐标:查找ABS_X和ABS_Y字段:

type 3 (EV_ABS),value 10306
type 3 (EV_ABS),value 30625

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

> ABS_MT_SLOT表示手指的数量
> ABS_MT_POSITION_X和ABS_MT_POSITION_Y – 坐标

手指#0:

type 3 (EV_ABS),value 0
type 3 (EV_ABS),value 10318
type 3 (EV_ABS),value 30609

手指#1:

type 3 (EV_ABS),value 1
type 3 (EV_ABS),value 20301
type 3 (EV_ABS),value 24161

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

#!/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应用程序.获得的二进制数据可以很容易地解释,参见kernel documentation中的第5节.
您可以使用select()系统调用等待下一个数据部分.

#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...n");
        return EXIT_SUCCESS;
    }

    /* Open Device */
    fd = open(EVENT_DEVICE,O_RDONLY);
    if (fd == -1) {
        fprintf(stderr,"%s is not a vaild devicen",EVENT_DEVICE);
        return EXIT_FAILURE;
    }

    /* Print Device Name */
    ioctl(fd,EVIOCGNAME(sizeof(name)),name);
    printf("Reading from:n");
    printf("device file = %sn",EVENT_DEVICE);
    printf("device name = %sn",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 readingn");
            goto err;
        }

        if (ev.type == EVENT_TYPE && (ev.code == EVENT_CODE_X
                      || ev.code == EVENT_CODE_Y)) {
            /* TODO: convert value to pixels */
            printf("%s = %dn",ev.code == EVENT_CODE_X ? "X" : "Y",ev.value);
        }
    }

    return EXIT_SUCCESS;

err:
    close(fd);
    return EXIT_FAILURE;
}

坐标单位

首先,您需要了解下一步:

>其中是坐标原点(即[x = 0; y = 0])
>您的设备用于表示坐标的单位

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

This是您设备的驱动程序.

因此,您似乎需要将您的轴值从evtest除以65535并将其乘以设备的宽度或高度(以像素为单位).例如,如果X = 30000,并且LCD面板的宽度为1080像素,则需要执行以下操作:

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读