【问题标题】:How to get Coordinates of Touchscreen Rawdata using Linux如何使用 Linux 获取触摸屏原始数据的坐标
【发布时间】:2015-03-03 20:16:51
【问题描述】:

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

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

cat /dev/input/event2 | hexdump

evtest

你得到的十六进制代码似乎无处记录......

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

内核有没有办法实时为我提供所需的信息?

作为一种解决方法,是否有 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, 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 无法解码这些十六进制代码,我们应该查找此触摸屏的驱动程序代码,它应该会提供有关这些数字的一些线索。
  • evtest 可以以某种方式解码,但我根本不明白。设备是多点触控的,但如果它像单点触控一样工作,它将适合这种情况。代码或终端无关紧要。
  • 我们需要知道您的触摸屏型号(如果您能告诉我们触摸屏控制器的型号就更好了)。此外,还不清楚您是否设法让它在 Linux 中工作(因此当您触摸此触摸屏时,您的光标会移动)。我想说这是你需要做的第一件事——找到并安装适用于这个触摸屏的驱动程序,然后让它工作。
  • 实际上它在Linux kernel documentation 中有很好的记录:) 另请参阅this answer on SO 以获得更紧凑的版本。

标签: linux linux-kernel driver touchscreen raw-input


【解决方案1】:

基于控制台的解决方案

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

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

     type 3 (EV_ABS), code 0 (ABS_X), value 10306
     type 3 (EV_ABS), code 1 (ABS_Y), value 30625
    
  2. 如果需要多点触控坐标:

    • ABS_MT_SLOT代表手指数
    • ABS_MT_POSITION_XABS_MT_POSITION_Y -- 坐标

    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
    

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

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

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

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

【讨论】:

  • 您好,我可以使用您的 c 代码在 Android 应用程序中注入触摸事件吗?另外,是否可以在android中使用getruntime.exe(“some linux command to injection event”)?
  • @Dania 我的代码只适合阅读事件。如果您需要执行触摸事件,请参阅thisthisthis
  • 非常感谢您的回复,但我需要一些 linux 命令,因为我的应用程序需要在整个系统中注入事件,我检查了链接,它们仅在应用程序的上下文中进行.我想我可以通过在/dev/input/eventX 中注入一个事件来做到这一点,我找到了关于这个yhcting.wordpress.com/2010/11/29/… 的链接,但我不确定语法,是/dev/input/eventX ABS_X 值和/ dev/input/eventX ABS_Y 值?谢谢。
  • @Dania 如果您需要 Linux 命令来模拟输入事件,请查看xdotool。或者你可以试试uinput驱动,但我怀疑有没有一个命令行工具。
  • 谢谢山姆,我会检查的。
【解决方案2】:

你得到的十六进制代码似乎无处记录......

这是由设备本身记录的,这是hid-multitouch 驱动程序如何解释它接收到的 USB 数据。

您可以使用以下命令查找信息:

$ lsusb              # determine the bus & device numbers
...
Bus 001 Device 067: ID 1aad:000f KeeTouch
...

$ sudo usbhid-dump -a 1:67 -e d
001:067:002:DESCRIPTOR         1615651625.434241
 05 0D 09 04 A1 01 85 03 09 22 09 00 15 00 26 FF
 00 75 08 95 09 81 02 A1 00 05 0D 09 51 15 00 26
 FF 00 75 08 95 01 81 02 05 0D 09 42 15 00 25 01
 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05
 81 03 05 01 09 30 26 FF 7F 55 00 65 00 35 00 46
 00 00 75 10 95 01 81 02 09 31 35 00 46 00 00 81
 02 05 0D 09 48 15 00 26 FF 7F 75 10 95 01 81 02
 09 49 15 00 26 FF 7F 75 10 95 01 81 02 C0 A1 00
 05 0D 09 51 15 00 26 FF 00 75 08 95 01 81 02 05
 0D 09 42 15 00 25 01 75 01 95 01 81 02 09 32 81
 02 09 47 81 02 95 05 81 03 05 01 09 30 26 FF 7F
 55 00 65 00 35 00 46 00 00 75 10 95 01 81 02 09
 31 35 00 46 00 00 81 02 05 0D 09 48 15 00 26 FF
 7F 75 10 95 01 81 02 09 49 15 00 26 FF 7F 75 10
 95 01 81 02 C0 A1 00 05 0D 09 51 15 00 26 FF 00
 75 08 95 01 81 02 05 0D 09 42 15 00 25 01 75 01
 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03
 05 01 09 30 26 FF 7F 55 00 65 00 35 00 46 00 00
 75 10 95 01 81 02 09 31 35 00 46 00 00 81 02 05
 0D 09 48 15 00 26 FF 7F 75 10 95 01 81 02 09 49
 15 00 26 FF 7F 75 10 95 01 81 02 C0 A1 00 05 0D
 09 51 15 00 26 FF 00 75 08 95 01 81 02 05 0D 09
 42 15 00 25 01 75 01 95 01 81 02 09 32 81 02 09
 47 81 02 95 05 81 03 05 01 09 30 26 FF 7F 55 00
 65 00 35 00 46 00 00 75 10 95 01 81 02 09 31 35
 00 46 00 00 81 02 05 0D 09 48 15 00 26 FF 7F 75
 10 95 01 81 02 09 49 15 00 26 FF 7F 75 10 95 01
 81 02 C0 A1 00 05 0D 09 51 15 00 26 FF 00 75 08
 95 01 81 02 05 0D 09 42 15 00 25 01 75 01 95 01
 81 02 09 32 81 02 09 47 81 02 95 05 81 03 05 01
 09 30 26 FF 7F 55 00 65 00 35 00 46 00 00 75 10
 95 01 81 02 09 31 35 00 46 00 00 81 02 05 0D 09
 48 15 00 26 FF 7F 75 10 95 01 81 02 09 49 15 00
 26 FF 7F 75 10 95 01 81 02 C0 A1 00 05 0D 09 54
 15 00 25 1F 75 08 95 01 81 02 C0 09 55 85 FD 15
 00 26 FF 00 75 08 95 01 B1 02 C0 05 0D 09 0E A1
 01 85 FC 09 52 09 53 15 00 26 FF 00 75 08 95 02
 B1 02 C0

001:067:001:DESCRIPTOR         1615651625.436655
 05 01 09 02 A1 01 85 02 09 01 A1 00 06 00 FF 09
 00 15 00 26 FF 00 75 08 95 09 81 02 05 01 09 30
 09 31 15 00 26 FF 7F 75 10 95 02 81 02 05 09 19
 01 29 08 15 00 25 01 95 08 75 01 81 02 C0 C0

001:067:000:DESCRIPTOR         1615651625.437001
 06 00 FF 09 00 A1 01 09 00 85 01 A1 00 09 00 15
 00 26 FF 00 35 00 46 FF 00 75 08 95 3F 81 02 C0
 09 02 85 FE A1 00 09 06 15 00 26 FF 00 35 00 46
 FF 00 75 08 95 3F B1 02 C0 C0

我使用lsusb 命令确定总线和设备编号并将其传递给usbhid-dump 命令。您可以使用不带这些数字的转储命令,但随后您将获得所有设备的列表。在大多数情况下,可能不是您想要的。

其中的代码由内核中的hid_parser() 命令解释。只有某些设备可能无法正确识别,而这正是您需要此信息的时候。

如何解释该数据由 USB 联盟定义。目前是1.11版本,对于hid类型的设备可以找到on this page

这主要包括键盘、鼠标、触摸屏、触摸板、操纵杆,尽管其他一些类型的设备也支持此功能(电源按钮、显示器上的各种按钮等)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-29
    • 2011-03-28
    • 1970-01-01
    相关资源
    最近更新 更多