How to Get Coordinates of Touchscreen Rawdata Using Linux

How to get Coordinates of Touchscreen Rawdata using Linux

Console-based solution

You can obtain parsed coordinates using evtest tool.

  1. If you only need single-touch coordinates: look for ABS_X and ABS_Y fields:

     type 3 (EV_ABS), code 0 (ABS_X), value 10306
    type 3 (EV_ABS), code 1 (ABS_Y), value 30625
  2. If you need multi-touch coordinates:

    • ABS_MT_SLOT represents number of finger
    • ABS_MT_POSITION_X and ABS_MT_POSITION_Y -- coordinates

    Finger #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

    Finger #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

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...\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;
}

Coordinates units

First of all you need to know next things:

  • where is coordinates origin point (i.e. [x=0;y=0])
  • which units your device is using for representing coordinates

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

This is the driver for your device.

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

Get coordinates from USB 2.0 TouchScreen Monitor under ubuntu.

in general you can get the coordinates using the evtest tool, that reads input events i.e. in /dev/input/event see How to get Coordinates of Touchscreen Rawdata using Linux <- very good answer

Despite this other ways to get the data depend on your touchscreen (reading/writing /dev/ttySx ,...). Touch screens are in general implemented as USB HID devices or emulating a serial connection
(https://wiki.ubuntu.com/Touchscreen)

Checking for touchscreen connectivity

When encountering a new device, the first order of business is to
determine how the touchscreen is connected to your computer. If the
touchscreen produces no events out of the box, check to see if it's an
USB device or not:

lsusb

USB connection

Check the output for any reference to a touchscreen. If your
touchscreen has an USB interface, and it isn't working, then you may
need to blacklist the usbtouchscreen driver for it to work:

sudo modprobe -r usbtouchscreen

If your touchscreen begins to produce events, then you can permanently
blacklist the usbtouchscreen driver:

echo "blacklist usbtouchscreen" | sudo tee -a
/etc/modprobe.d/blacklist.conf

Some touchscreens might already have good or perfect calibrations,
otherwise you'll need to continue to the calibration section.

Serial connection

If there is no reference to a touchscreen device in your lsusb output,
the connection is most likely through one of your serial ports. The
actual IRQ mapping varies between manufacturers. In the case of
Itronix devices, the default is /dev/ttyS3. A simple way to check for
connections is to check each one for events:

screen /dev/ttyS0

Touch anywhere on your screen to check for any character output. If
nothing happens, quit screen by pressing Ctrl+A and then the \ key
to quit. Continue with /dev/ttyS1, etc. until you get a response. Once
you've determined the device, we can try a few different drivers. In
the case of Itronix (and most other devices using the Touchkit
driver), the correct driver is touchit213.

sudo inputattach --touchit213 /dev/ttyS3

Will work for most touchkit screens. The calibration or one or more
axes may be swapped, but if the calibration is approximate then it's
probably the correct driver. Press Ctrl+C to try a new mode.
inputattach supports any of the following modes, which includes
external touchscreens which may attach through a physical serial port:

  • --h3600ts -ipaq Ipaq h3600 touchscreend
  • --elotouch -elo ELO touchscreen, 10-byte mode
  • --elo4002 -elo6b ELO touchscreen, 6-byte mode
  • --elo271-140 -elo4b ELO touchscreen, 4-byte mode
  • --elo261-280 -elo3b ELO Touchscreen, 3-byte mode
  • --mtouch -mtouch MicroTouch (3M) touchscreen
  • --touchit213 -t213 Sahara Touch-iT213 Tablet PC
  • --touchright -tr Touchright serial touchscreen
  • --touchwin -tw Touchwindow serial touchscreen
  • --penmount -pm Penmount touchscreen
  • --fujitsu -fjt Fujitsu serial touchscreen

If your device is built into a laptop, you'll have the best luck with
the mtouch, touchright, touchwin, or touchit213 drivers. Likewise,
non-Elo external touchscreens will most likely use touchit213. If your
device is a tablet with stylus-only input, fujitsu is a popular maker
of embedded tablet devices.

To attach the touchscreen at startup, edit your /etc/rc.local to look
like the following:

/usr/bin/inputattach --daemon --always -t213 /dev/ttyS3 exit 0

Replace -t213 with your appropriate driver and /dev/ttyS3 with the
correct device.

Again, don't worry if the calibration isn't perfect, or if an axis is
inverted or reversed - this will be addressed in the calibration
section.

https://wiki.ubuntu.com/Touchscreen

How to read hardware-level event information from touchscreen?

I went ahead and tested the monitor with a laptop that had Linux kernel 4.4.0, and it worked right away, so it seems that it's definitely the kernel. I don't know if there are any touchscreens that WILL work with kernel 2.6.32, but the ones based on the Quanta display definitely don't work.



Related Topics



Leave a reply



Submit