web-dev-qa-db-ja.com

Linuxを使用してタッチスクリーンのRawdataの座標を取得する方法

wieは3mのマイクロタッチディスプレイを備えています。それはusbを介して私のdebianシステムに接続され、ヒューマンインターフェイスとして認識されました(非表示)。リアルタイム情報にアクセスしてプッシュしようとしています...触れられたら、(x、y)を知り、それをnetcatを介して別のホストにパイプします。

残念ながら、私は生データを使用してのみ得ることができます

cat /dev/input/event2 | hexdump

またはevtest

あなたはどこにも文書化されていないように見える16進コードを取得します...

誰かがそれらの情報を取得する方法の手掛かりを持っていますか? 16進コードから抽出する方法が必要です。残念ながら、私は16進コードを解釈する方法がわかりません。文書化されているソースを見つけることができませんでした...

カーネルがこれらの必要な情報をリアルタイムで提供する方法はありますか?回避策として、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
11
uncle_iroh

コンソールベースのソリューション

解析された座標はevtestツールを使用して取得できます。

  1. シングルタッチ座標のみが必要な場合:_ABS_X_および_ABS_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_X_および_ABS_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]_)
  • デバイスが座標を表すために使用している単位

この情報は通常、デバイスのドライバーコードにあります。

これ は、デバイスのドライバーです。

したがって、軸の値をevtestから65535で割り、デバイスの幅または高さ(ピクセル単位)で乗算する必要があるようです。たとえば、X = 30000を取得し、LCDパネルの幅が1080ピクセルの場合、次のようにする必要があります。

_X = round((30000 / 65535) * 1080) = 494 pixels
_
29
Sam Protsenko