Blame touch.c

7e0df9
7e0df9
#include "touch.h"
7e0df9
7e0df9
7e0df9
#ifndef DIRECT_TOUCH
7e0df9
7e0df9
7e0df9
int touchInit(Touch *touch, App *app, const char *dev) { return 0; }
7e0df9
void touchDeinit(Touch *touch) { }
7e0df9
int touchGet(Touch *touch, int *x, int *y, int *p) { return 0; }
7e0df9
7e0df9
7e0df9
#else // DIRECT_TOUCH
7e0df9
7e0df9
7e0df9
#include <math.h></math.h>
7e0df9
#include <mtdev.h></mtdev.h>
7e0df9
#include <stdio.h></stdio.h>
7e0df9
#include <unistd.h></unistd.h>
7e0df9
#include <fcntl.h></fcntl.h>
7e0df9
7e0df9
7e0df9
7e0df9
static int touch_field_codes[TOUCH_FIELDS] =
7e0df9
  { ABS_MT_POSITION_X, ABS_MT_POSITION_Y, ABS_MT_PRESSURE };
7e0df9
7e0df9
7e0df9
int touchInit(Touch *touch, App *app, const char *dev) {
7e0df9
  if (!app || !dev) return 0;
7e0df9
  LOGDBG("touch: init");
7e0df9
7e0df9
  touch->fd = open(dev, O_RDONLY | O_NONBLOCK);
7e0df9
  if (touch->fd < 0)
7e0df9
    return LOGERR("touch: init: cannot open file: %s", dev);
7e0df9
7e0df9
  int ret = mtdev_open(&touch->dev, touch->fd);
7e0df9
  if (ret) {
7e0df9
    close(touch->fd);
7e0df9
    touch->fd = 0;
7e0df9
    return LOGERR("touch: init: cannot open device: %s", dev);
7e0df9
  }
7e0df9
7e0df9
  for(int i = 0; i < TOUCH_FIELDS; ++i) {
7e0df9
    int *f = touch->fields[i];
7e0df9
    f[0] = mtdev_get_abs_minimum(&touch->dev, touch_field_codes[i]);
7e0df9
    f[1] = mtdev_get_abs_maximum(&touch->dev, touch_field_codes[i]);
7e0df9
    if (f[0] >= f[1]) {
7e0df9
      mtdev_close(&touch->dev);
7e0df9
      close(touch->fd);
7e0df9
      return LOGERR("touch: init: cannot get field bounds for device: %s (field %d:%d)", dev, i, touch_field_codes[i]);
7e0df9
    }
7e0df9
    f[2] = 0;
7e0df9
    if (f[2] > f[1]) f[2] = f[1];
7e0df9
    if (f[2] < f[0]) f[2] = f[0];
7e0df9
  }
7e0df9
8603b4
  touch->app = app;
8603b4
  touch->slot = 0;
8603b4
  touch->id = -1;
8603b4
  touch->pressed = 0;
7e0df9
  return 1;
7e0df9
}
7e0df9
7e0df9
7e0df9
void touchDeinit(Touch *touch) {
7e0df9
  if (touch->app) {
7e0df9
    mtdev_close(&touch->dev);
7e0df9
    close(touch->fd);
7e0df9
  }
7e0df9
  touch->app = NULL;
7e0df9
}
7e0df9
7e0df9
7e0df9
int touchGet(Touch *touch, int *x, int *y, int *p) {
7e0df9
  if (!touch->app) return 0;
7e0df9
7e0df9
  struct input_event ev;
7e0df9
  while(mtdev_get(&touch->dev, touch->fd, &ev, 1) > 0) {
7e0df9
    if (ev.type == EV_SYN) {
7e0df9
      // return event
7e0df9
      double f[TOUCH_FIELDS];
7e0df9
      for(int i = 0; i < TOUCH_FIELDS; ++i) {
7e0df9
          int *tf = touch->fields[i];
7e0df9
          f[i] = (tf[2] - tf[0])/(double)(tf[1] - tf[0]);
7e0df9
      }
7e0df9
      double fx = f[0], fy = f[1], fp = f[2];
7e0df9
7e0df9
      App *app = touch->app;
7e0df9
      if (app->sr & RR_Rotate_90)
7e0df9
        { double v = fx; fx = fy; fy = 1-v; }
7e0df9
      if (app->sr & RR_Rotate_180)
7e0df9
        { fx = 1-fx; fy = 1-fy; }
7e0df9
      if (app->sr & RR_Rotate_270)
7e0df9
        { double v = fx; fx = 1-fy; fy = v; }
7e0df9
      if (app->sr & RR_Reflect_X)
7e0df9
        fx = 1-fx;
7e0df9
      if (app->sr & RR_Reflect_Y)
7e0df9
        fy = 1-fy;
7e0df9
7e0df9
      *x = (int)round(fx*app->sw - app->x);
7e0df9
      *y = (int)round(fy*app->sh - app->y);
7e0df9
      *p = touch->id >= 0 && fp > (touch->pressed ? TOUCH_THRESHOLD0 : TOUCH_THRESHOLD1);
7e0df9
      touch->pressed = *p;
7e0df9
      return 1;
7e0df9
    }
7e0df9
7e0df9
    if (ev.type != EV_ABS)
7e0df9
      continue; // ignore non ABS events
7e0df9
7e0df9
    if (ev.code == ABS_MT_SLOT)
7e0df9
      { touch->slot = ev.value; continue; }  // switch slot
7e0df9
    if (touch->slot != 0)
7e0df9
      continue;  // handle only first slot
7e0df9
7e0df9
    if (ev.code == ABS_MT_TRACKING_ID)
7e0df9
      { touch->id = ev.value; continue; } // set track id
7e0df9
7e0df9
    for(int i = 0; i < TOUCH_FIELDS; ++i)
7e0df9
      if (ev.code == touch_field_codes[i])
7e0df9
        touch->fields[i][2] = ev.value;
7e0df9
  }
7e0df9
7e0df9
  return 0;
7e0df9
}
7e0df9
7e0df9
7e0df9
#endif // DIRECT_TOUCH