Capturing Coordinate of Touch Screen in Linux

Home / Capturing Coordinate of Touch Screen in Linux

Linux is dominating embedded system. It is mainly because of broad support of processor, such as: ARM, MIPS, PowerPC, etc. For some gadget, touch screen is an extra feature, other must have it. Whatever the reason, Linux support it. The fundamental thing in programming a system with touch screen is how to get coordinate of point touched by user.

This article will discuss about how to capture coordinate of point in touch screen. When I write this article I use Castles Technology’s EDC. I won’t disclose internal of the system used, but I should tell you that our discussion could be applied to Linux in general.

Some Knowledge

As usual, before we start we need to know some basic knowledge.

Linux is unix-like operating system. Everything in Linux is a file, including device. They are all stored inside /dev. Your first SCSI disk should be recognized as /dev/sda. Your DVD ROM might be recognized as /dev/sr0 (or /dev/dvd, a symlink to it).

You might also learn that device is categorized mainly as character device and block device. A character device is a class of device which send data by amount of character at a time, while block device will give you a block of data (typically some bytes).

Now direct our focus toward /dev/input. This is the location where device files for our input devices located. By input devices we means mouse, keyboard, or perhaps touch screen. Good, now spot eventX file where X is a number. Well, the number of files is depends on how much input device you have.

So how can we pinpoint the device?

In desktop I can see the /dev/input/by-id or /dev/input/by-path and see to which device they are pointing at. However, we don’t always have this luxury.

ls -la /dev/input/by-id/
ls -la /dev/input/by-path/

Another quick way to figure it out is by inspecting /proc/bus/input/devices. Yet, this might be not the case for most device. Also we need to parse some unneeded information.

cat /proc/bus/input/devices

Next option is dumping the raw data from file. Again this is not always the case.

cat /dev/input/event0 | hexdump -c

Last option is writing a small program, open the device, and read it. This works for me and we will discuss it deeper later.

Preparation

I will leave the idea of “how you can connect to device” to you. I assume you have some way to write a program. We also need a way to direct I/O to device.

I also assume you can produce code for the device. Whether you have compiler inside, or just do cross compilation doesn’t matter.

Last, I assume you know our great programming language, C.

Capturing

This is the sample working code I use to enumerate the device, open it, and capture the coordinate.

#include <stdio.h>
#include <stdlib.h>

/* For open and read data */
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>

/* For directory listing */
#include <sys/stat.h>
#include <dirent.h>

/* Miscs */
#include <limits.h>
#include <string.h>

// We don't care it for now, let it be global.
DIR *dir = NULL;

/* Find first valid device which we can open */
int enum_and_open_dev()
{
    struct dirent *dirent;
    int fd;
    
    // Is it first time? Open it if yes.
    if (!dir)
        dir = opendir("/dev/input");

    if (dir)
    {
        while ((dirent = readdir(dir) != NULL)) {
            if (!memcmp(dirent->d_name, "event", 5)) {
                fd = open(dirent->d_name, O_RDONLY);
                if (fd == -1)
                    continue;   // Not a valid file

                return fd;   // file is opened
            }
        }
        closedir(dir);
        dir = NULL;
        return 0;
}

int get_dev_name(int fd)
{
    char buf[256] = "Unknown";

    /* Print Device Name */
    ioctl(fd, EVIOCGNAME(sizeof(buf)), buf);
    write(ofd, buf, strlen(buf));
}

int touch_screen_getxy(int fd)
{
    struct input_event ev;
    size_t ev_size = sizeof(struct input_event);
    size_t size;
    
    while (1) {
        size = read(fd, &ev, ev_size);
        if (size < ev_size) {
            write(ofd, "Error size when reading", 23);
            return -1;
        }
        
        if (ev.type == EV_ABS && 
            (ev.code == ABS_X || ev.code == ABS_Y))
        {
            sprintf(buf, "%s = %d\n", ev.code == ABS_X ? "X" : "Y", ev.value);
            write(ofd, buf, strlen(buf));
        }
    }
    return 0;
}

int test_()
{
   int fd;

   fd = enum_and_open_dev();
   if (fd == 0) {
      write(ofd, "No readable device found", 24);
      return -1;
   }

   get_dev_name(fd);
   touch_screen_getxy(fd);
}

Just a note, ofd is a file descriptor where will pipe to my host, in other words a debug means for me.

enum_and_open_dev() is a function to enumerate available file in /dev/input/ and trying to open it. In my sample code, I only use the first valid file descriptor. After I got it, I want to know it’s name and then the main dish: the coordinates.

Next?

Just a single point is not enough. What about two or three simultaneous touch (multitouch) ? Well, save it for later.

,

About Author

about author

xathrya

A man who is obsessed to low level technology.

Leave a Reply

Your email address will not be published. Required fields are marked *

Social media & sharing icons powered by UltimatelySocial