[gpm] [PATCH 14/18] evdev-2.6-update.patch

Dmitry Torokhov dtor_core@ameritech.net
Tue Aug 10 09:00:36 CEST 2004


===================================================================


ChangeSet@1.18, 2004-08-10 00:53:37-05:00, dtor_core@ameritech.net
  Update evdev protocol to support kernels >= 2.6.0-test.
  Do not use Oops in evdev in case of crazy input parameters.
  Use "get ID" IOCTL to detect Synaptics hardware.


 configure.ac                |    1 
 src/evdev.c                 |  402 +++++++++++++++++++++++++++++---------------
 src/headers/input-defines.h |   81 ++++++++
 3 files changed, 347 insertions(+), 137 deletions(-)


===================================================================



diff -Nru a/configure.ac b/configure.ac
--- a/configure.ac	2004-08-10 01:18:01 -05:00
+++ b/configure.ac	2004-08-10 01:18:01 -05:00
@@ -86,6 +86,7 @@
 if test ${ac_cv_header_linux_input_h} = yes ; then
         EVDEV_SRCS=evdev.c ;
         AC_CHECK_TYPE(struct input_absinfo,AC_DEFINE_UNQUOTED(HAVE_INPUT_ABSINFO, 1, [define if struct input_absinfo defined in linux/input.h]),,[#include <linux/input.h>])
+        AC_CHECK_TYPE(struct input_id,AC_DEFINE_UNQUOTED(HAVE_INPUT_ID, 1, [define if struct input_id defined in linux/input.h]),,[#include <linux/input.h>])
 fi
 
 ITZ_CHECK_TYPE(__u32,linux/types.h)
diff -Nru a/src/evdev.c b/src/evdev.c
--- a/src/evdev.c	2004-08-10 01:18:01 -05:00
+++ b/src/evdev.c	2004-08-10 01:18:01 -05:00
@@ -29,6 +29,7 @@
 #include <sys/time.h>
 
 #include <linux/input.h>
+#include "headers/input-defines.h" /* misisng bits in case <linux/input.h> is old */ 
 
 #include "headers/gpm.h"
 #include "headers/gpmInt.h"
@@ -36,29 +37,8 @@
 #include "headers/message.h"
 #include "headers/optparser.h"
 
-#ifndef MSC_GESTURE
-#define MSC_GESTURE     2
-#endif
-
-#ifndef EV_SYNC
-#define EV_SYNC         0
-#endif
-
-#ifndef SYN_REPORT
-#define SYN_REPORT      0
-#endif
-
-#ifndef HAVE_INPUT_ABSINFO
-struct input_absinfo {
-   int value;
-   int minimum;
-   int maximum;
-   int fuzz;
-   int flat;
-};
-#endif
-
 enum evdev_type {
+   EVDEV_UNKNOWN,
    EVDEV_RELATIVE,
    EVDEV_ABSOLUTE,
    EVDEV_TOUCHPAD,
@@ -96,19 +76,21 @@
    int wdx, wdy;
    int abs_x, abs_y;
    int buttons;
+   int touch;  /* dumb touchpad report touch events, smart ones - pressure */
    int pressure;
    int w;
+   int finger_count;
    int synced;
 };
 
 struct touch_data {
-   enum touch_type type;
-   enum gesture_type gesture;
-   int finger_count;
+   int touching;
    int x, y;
+   int finger_count;
    int buttons;
    int clicks;
    struct timeval start;
+   enum gesture_type gesture;
 };
 
 struct event_device {
@@ -127,6 +109,9 @@
    int touch_high, touch_low;
    int tap_time, tap_move;
    int y_inverted;
+
+   enum touch_type (*detect_touch)(struct event_device *evdev);
+   void (*update_finger_count)(struct event_device *evdev);
 };
 
 struct evdev_capabilities {
@@ -186,6 +171,10 @@
             case ABS_PRESSURE:
                data->pressure = event->value;
                break;
+
+            case ABS_TOOL_WIDTH:
+               data->w = event->value;
+               break;
          }
          break;
 
@@ -201,21 +190,39 @@
       case EV_KEY:
          switch(event->code) {
             case BTN_0:
-            case BTN_TOUCH:
             case BTN_LEFT:
                toggle_btn(GPM_B_LEFT, event->value);
                break;
+
             case BTN_2:
             case BTN_STYLUS2:
             case BTN_SIDE:
             case BTN_MIDDLE:
                toggle_btn(GPM_B_MIDDLE, event->value);
                break;
+
             case BTN_STYLUS:
             case BTN_1:
             case BTN_RIGHT:
                toggle_btn(GPM_B_RIGHT, event->value);
                break;
+
+            case BTN_TOUCH:
+               data->touch = event->value ? 1 : 0;
+               break;
+
+            case BTN_TOOL_FINGER:
+               if (event->value) data->finger_count = 1;
+               break;
+
+            case BTN_TOOL_DOUBLETAP:
+               if (event->value) data->finger_count = 2;
+               break;
+
+            case BTN_TOOL_TRIPLETAP:
+               if (event->value) data->finger_count = 3;
+               break;
+
          }
          break;
 
@@ -234,7 +241,7 @@
    struct event_data *pkt = &evdev->pkt;
 
    state->dx = state->dy = 0;
-   if (evdev->touch.type == TOUCH_FINGERS) {
+   if (evdev->touch.touching) {
       fx(0) = pkt->abs_x;
       fy(0) = pkt->abs_y;
       if (evdev->pkt_count >= 2 &&
@@ -248,9 +255,14 @@
    }
 }
 
-static enum touch_type tp_detect_touch(struct event_device *evdev)
+static enum touch_type dumb_tp_detect_touch(struct event_device *evdev)
 {
-   if (evdev->touch.type == TOUCH_FINGERS)
+   return evdev->pkt.touch ? TOUCH_FINGERS : TOUCH_NONE;
+}
+
+static enum touch_type smart_tp_detect_touch(struct event_device *evdev)
+{
+   if (evdev->touch.touching)
       return evdev->pkt.pressure > evdev->touch_low ? TOUCH_FINGERS : TOUCH_NONE;
    else
       return evdev->pkt.pressure > evdev->touch_high ? TOUCH_FINGERS : TOUCH_NONE;
@@ -262,19 +274,21 @@
    enum touch_type type = TOUCH_NONE;
 
    if (pkt->pressure > 200 || pkt->w > 10)
-      return TOUCH_PALM; /* palm */
+      return TOUCH_PALM;
 
    if (pkt->abs_x == 0)
       evdev->avg_w = 0;
    else
       evdev->avg_w = (pkt->w - evdev->avg_w + 1) / 2;
 
-   if (evdev->touch.type == TOUCH_FINGERS)
+   if (evdev->touch.touching) {
       type = pkt->pressure > evdev->touch_low ? TOUCH_FINGERS : TOUCH_NONE;
-   else if (pkt->pressure > evdev->touch_high) {
+   } else if (pkt->pressure > evdev->touch_high) {
       int safe_w = max(pkt->w, evdev->avg_w);
 
-      if (pkt->w < 2)
+      if (pkt->finger_count > 1)
+         type = TOUCH_FINGERS;
+      else if (pkt->w < 2)
          type = TOUCH_FINGERS;                  /* more than one finger -> not a palm */
       else if (safe_w < 6 && evdev->prev_pressure < evdev->touch_high)
          type = TOUCH_FINGERS;                  /* thin finger, distinct touch -> not a palm */
@@ -301,9 +315,9 @@
    else if (x < evdev->left_edge)
       edge |= LEFT_EDGE;
 
-   if (y > evdev->top_edge)
+   if (y < evdev->top_edge)
       edge |= TOP_EDGE;
-   else if (y < evdev->bottom_edge)
+   else if (y > evdev->bottom_edge)
       edge |= BOTTOM_EDGE;
 
    return edge;
@@ -319,17 +333,16 @@
 
 static int tp_detect_tap(struct event_device *evdev)
 {
-   return evdev->touch.finger_count > 0 ||
-          (!tp_touch_expired(evdev) &&
-           abs(evdev->pkt.abs_x - evdev->touch.x) < evdev->tap_move &&
-           abs(evdev->pkt.abs_y - evdev->touch.y) < evdev->tap_move);
+   return !tp_touch_expired(evdev) &&
+          (evdev->touch.finger_count > 1 ||
+           (abs(evdev->pkt.abs_x - evdev->touch.x) < evdev->tap_move &&
+            abs(evdev->pkt.abs_y - evdev->touch.y) < evdev->tap_move));
 }
 
 static int tp_tap_to_buttons(struct event_device *evdev)
 {
    enum edge_type edge;
-
-   if (!evdev->touch.finger_count) {
+   if (evdev->touch.finger_count < 2) {
       edge = tp_detect_edges(evdev, evdev->pkt.abs_x, evdev->pkt.abs_y);
       switch (edge) {
          case RIGHT_TOP_EDGE:
@@ -354,18 +367,17 @@
    }
 }
 
-static void tp_detect_gesture(struct event_device *evdev, int timed_out, struct Gpm_Event *state)
+static void tp_detect_gesture(struct event_device *evdev, int timed_out, enum touch_type touch_type)
 {
    struct touch_data *touch = &evdev->touch;
-   int was_touching = touch->type == TOUCH_FINGERS;
+   int was_touching = touch->touching;
 
-   touch->type = timed_out ?
-                     TOUCH_NONE : (evdev->type == EVDEV_SYNAPTICS ?
-                                   syn_detect_touch(evdev) : tp_detect_touch(evdev));
+   touch->touching = touch_type == TOUCH_FINGERS;
 
-   if (touch->type == TOUCH_FINGERS) {
+   if (touch->touching) {
       if (!was_touching) {
          GET_TIME(touch->start);
+         touch->finger_count = 0;
          if (touch->gesture == GESTURE_TAP_PENDING) {
             touch->gesture = GESTURE_DRAG_PENDING;
          } else {
@@ -376,9 +388,9 @@
       } else if (touch->gesture == GESTURE_DRAG_PENDING && tp_touch_expired(evdev)) {
          touch->gesture = GESTURE_DRAG;
       }
-   } else if (touch->type == TOUCH_NONE) {
+   } else {
       if (was_touching) {
-         if (tp_detect_tap(evdev)) {
+        if (tp_detect_tap(evdev)) {
             if (touch->gesture == GESTURE_DRAG_PENDING) {
                touch->gesture = GESTURE_DOUBLE_TAP;
                touch->clicks = 4;
@@ -402,18 +414,74 @@
    }
 }
 
+static int tp_process_gesture(struct event_device *evdev, struct Gpm_Event *state)
+{
+   int next_timeout = -1;
+
+   switch(evdev->touch.gesture) {
+      case GESTURE_DOUBLE_TAP:
+      case GESTURE_TAP:
+         if (--evdev->touch.clicks == 0)
+            evdev->touch.gesture = GESTURE_NONE;
+         else
+            next_timeout = 0;
+
+         if (evdev->touch.clicks % 2)
+            state->buttons |= evdev->touch.buttons;
+         else
+            state->buttons &= ~evdev->touch.buttons;
+         break;
+
+      case GESTURE_DRAG:
+         state->buttons |= evdev->touch.buttons;
+         break;
+
+      case GESTURE_DRAG_PENDING:
+      case GESTURE_TAP_PENDING:
+         next_timeout = evdev->tap_time;
+         break;
+
+      default:
+         break;
+   }
+   return next_timeout;
+}
+
+static void tp_update_finger_count(struct event_device *evdev)
+{
+   evdev->touch.finger_count = max(evdev->pkt.finger_count, evdev->touch.finger_count);
+}
+
+static void syn_update_finger_count(struct event_device *evdev)
+{
+   if (evdev->pkt.w == 1)
+      evdev->touch.finger_count = 3;
+   else if (evdev->pkt.w == 0 && evdev->touch.finger_count != 3)
+      evdev->touch.finger_count = 2;
+   else
+      evdev->touch.finger_count = 1;
+}
+
 static int compose_gpm_event(struct event_device *evdev, int timed_out, Gpm_Event *state)
 {
    struct event_data *pkt = &evdev->pkt;
+   enum touch_type touch_type;
    int next_timeout = -1;
 
-	state->buttons = pkt->buttons;
-   state->wdx = pkt->wdx; state->wdy = pkt->wdy;
+	if (!timed_out) {
+      state->buttons = pkt->buttons;
+      state->wdx = pkt->wdx; state->wdy = pkt->wdy;
+   }
 
    switch (evdev->type) {
       case EVDEV_RELATIVE:
-         if (!timed_out)
+         if (!timed_out) {
             state->dx = pkt->dx; state->dy = pkt->dy;
+            if (evdev->pkt.touch)
+               state->buttons |=  GPM_B_LEFT;
+            else
+               state->buttons &= ~GPM_B_LEFT;
+         }
          break;
 
       case EVDEV_ABSOLUTE:
@@ -423,61 +491,45 @@
             else if (pkt->abs_x > evdev->right_edge)
                pkt->abs_x = evdev->right_edge;
 
-            if (pkt->abs_y < evdev->bottom_edge)
+            if (pkt->abs_y > evdev->bottom_edge)
                pkt->abs_y = evdev->bottom_edge;
-            else if (pkt->abs_y > evdev->top_edge)
+            else if (pkt->abs_y < evdev->top_edge)
                pkt->abs_y = evdev->top_edge;
 
             state->x = (pkt->abs_x - evdev->left_edge) *
                         console.max_x / (evdev->right_edge - evdev->left_edge);
-            state->y = (pkt->abs_y - evdev->bottom_edge) *
-                        console.max_y / (evdev->top_edge - evdev->bottom_edge);
+            state->y = (pkt->abs_y - evdev->top_edge) *
+                        console.max_y / (evdev->bottom_edge - evdev->top_edge);
 
             if (evdev->y_inverted) state->y = console.max_y - state->y;
+
+            if (evdev->pkt.touch)
+               state->buttons |=  GPM_B_LEFT;
+            else
+               state->buttons &= ~GPM_B_LEFT;
          }
          break;
 
       case EVDEV_TOUCHPAD:
       case EVDEV_SYNAPTICS:
-         tp_detect_gesture(evdev, timed_out, state);
-         tp_figure_deltas(evdev, state);
+         touch_type = timed_out ? TOUCH_NONE : evdev->detect_touch(evdev);
 
-         if (evdev->type == EVDEV_SYNAPTICS &&
-             evdev->touch.type == TOUCH_FINGERS &&
-             !tp_touch_expired(evdev)) {
-            if (evdev->pkt.w == 0 && evdev->touch.finger_count == 0)
-               evdev->touch.finger_count = 2;
-            if (evdev->pkt.w == 1)
-               evdev->touch.finger_count = 3;
-         } else
-            evdev->touch.finger_count = 0;
-
-         switch(evdev->touch.gesture) {
-            case GESTURE_DOUBLE_TAP:
-            case GESTURE_TAP:
-               if (evdev->touch.clicks <= 0) {
-                  evdev->touch.gesture = GESTURE_NONE;
-               } else {
-                  if (--evdev->touch.clicks % 2)
-                     state->buttons |= evdev->touch.buttons;
-                  else
-                     state->buttons &= ~evdev->touch.buttons;
-                  next_timeout = 0;
-               }
-               break;
-           case GESTURE_DRAG:
-               state->buttons |= evdev->touch.buttons;
-               break;
-            case GESTURE_DRAG_PENDING:
-               next_timeout = evdev->tap_time;
-               break;
-            case GESTURE_TAP_PENDING:
-               next_timeout = evdev->tap_time;
-               break;
-            default:
-               break;
+         if (touch_type != TOUCH_PALM) {
+            tp_detect_gesture(evdev, timed_out, touch_type);
+
+            if (evdev->touch.touching && !tp_touch_expired(evdev))
+               evdev->update_finger_count(evdev);
+
+            if (evdev->touch.finger_count < 2)
+               tp_figure_deltas(evdev, state);
+
+            next_timeout = tp_process_gesture(evdev, state);
          }
+         break;
 
+      default:
+         /* should not happen */
+         gpm_report(GPM_PR_OOPS, "Bad evdev type %d", evdev->type);
          break;
    }
 
@@ -498,6 +550,9 @@
 
    if (timed_out || evdev->pkt.synced || evdev->dont_sync) {
       dev->timeout = compose_gpm_event(evdev, timed_out, state);
+      evdev->pkt.dx = evdev->pkt.dy = 0;
+      evdev->pkt.wdx = evdev->pkt.wdy = 0;
+      evdev->pkt.finger_count = 0;
       evdev->pkt.synced = 0;
       return 0;
    }
@@ -508,55 +563,96 @@
 
 /* ------------- evdev initialization routines ---------------------*/
 
-static void evdev_get_capabilities(int fd, struct evdev_capabilities *caps)
+static int evdev_get_id(int fd, struct input_id *id)
+{
+   if (ioctl(fd, EVIOCGID, id) < 0) {
+      gpm_report(GPM_PR_ERR, "evdev: cannot query device identification");
+      return -1;
+   }
+   return 0;
+}
+
+static int evdev_get_capabilities(int fd, struct evdev_capabilities *caps)
 {
    memset(caps, 0, sizeof(*caps));
+
    if (ioctl(fd, EVIOCGBIT(0, EV_MAX), caps->evbits) < 0) {
-      gpm_report(GPM_PR_OOPS, "evdev: cannot query device capabilities");
+      gpm_report(GPM_PR_ERR, "evdev: cannot query device capabilities");
+      return -1;
    }
 
    if (test_bit(EV_ABS, caps->evbits) &&
        ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(caps->absbits)), caps->absbits) < 0) {
-      gpm_report(GPM_PR_OOPS, "evdev: cannot query ABS device capabilities");
+      gpm_report(GPM_PR_ERR, "evdev: cannot query ABS device capabilities");
+      return -1;
    }
 
    if (test_bit(EV_KEY, caps->evbits) &&
        ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(caps->keybits)), caps->keybits) < 0) {
-      gpm_report(GPM_PR_OOPS, "evdev: cannot query KEY device capabilities");
+      gpm_report(GPM_PR_ERR, "evdev: cannot query KEY device capabilities");
+      return -1;
    }
 
    if (test_bit(EV_MSC, caps->evbits) &&
        ioctl(fd, EVIOCGBIT(EV_MSC, sizeof(caps->mscbits)), caps->mscbits) < 0) {
-      /* dont complain as 2.4 kernels didnt have it
-      gpm_report(GPM_PR_OOPS, "evdev: cannot query MSC device capabilities");
+      /* don't complain as 2.4 kernels didnt have it
+      gpm_report(GPM_PR_ERR, "evdev: cannot query MSC device capabilities");
+      return -1;
       */
    }
+   return 0;
 }
 
-static void evdev_query_axis(int fd, int axis, int *axis_min, int *axis_max)
+static int evdev_query_axis(int fd, int axis, int *axis_min, int *axis_max)
 {
    struct input_absinfo axis_info;
 
-   if (ioctl(fd, EVIOCGABS(axis), &axis_info) == 0) {
-      *axis_min = axis_info.minimum;
-      *axis_max = axis_info.maximum;
-   } else
+   if (ioctl(fd, EVIOCGABS(axis), &axis_info) == -1) {
       gpm_report(GPM_PR_ERR, "evdev: could not query axis data");
+      return -1;
+   }
+
+   *axis_min = axis_info.minimum;
+   *axis_max = axis_info.maximum;
+   return 0;
 }
 
-static enum evdev_type evdev_guess_type(struct evdev_capabilities *caps)
+static int evdev_get_limits(int fd, struct event_device *evdev,
+                            struct evdev_capabilities *caps)
+{
+   if (test_bit(ABS_X, caps->absbits) &&
+         evdev_query_axis(fd, ABS_X, &evdev->left_edge, &evdev->right_edge) < 0)
+      return -1;
+
+   if (test_bit(ABS_Y, caps->absbits) &&
+         evdev_query_axis(fd, ABS_Y, &evdev->top_edge, &evdev->bottom_edge) < 0)
+      return -1;
+
+   return 0;
+}
+
+static int is_synaptics(struct input_id *id)
+{
+   return id->bustype == BUS_I8042 && id->vendor == 0x0002 && id->product == PSMOUSE_SYNAPTICS;
+}
+
+static enum evdev_type evdev_guess_type(struct input_id *id, struct evdev_capabilities *caps)
 {
    if (test_bit(EV_ABS, caps->evbits)) {
-      if (caps->keybits[BTN_DIGI / 8] || !test_bit(ABS_PRESSURE, caps->absbits))
-         return EVDEV_ABSOLUTE;
+      if (is_synaptics(id))
+         return EVDEV_SYNAPTICS;
+
+      if (test_bit(BTN_TOUCH, caps->keybits) && caps->keybits[BTN_MOUSE / 8])
+         return EVDEV_TOUCHPAD;
 
-      return test_bit(EV_MSC, caps->evbits) && test_bit(MSC_GESTURE, caps->mscbits) ?
-             EVDEV_SYNAPTICS : EVDEV_TOUCHPAD;
+      return EVDEV_ABSOLUTE;
    }
 
-   if (!test_bit(EV_REL, caps->evbits))
-      gpm_report(GPM_PR_OOPS,
+   if (!test_bit(EV_REL, caps->evbits)) {
+      gpm_report(GPM_PR_ERR,
                  "evdev: device does not report neither absolute nor relative coordinates");
+      return EVDEV_UNKNOWN;
+   }
 
    return EVDEV_RELATIVE;
 }
@@ -572,8 +668,8 @@
    } else if (!strcmp(type, "synaptics")) {
       return EVDEV_SYNAPTICS;
    } else {
-      gpm_report(GPM_PR_OOPS, "evdev: unknown type '%s'", type);
-      return 0;  /* won't happen as gpm_report(OOPS) does not return */
+      gpm_report(GPM_PR_ERR, "evdev: unknown type '%s'", type);
+      return EVDEV_UNKNOWN;
    }
 }
 
@@ -588,7 +684,7 @@
 // -o type=(auto|synaptics|touchpad|relative|absolute),y_inverted,
 //    left=1234,right=1234,top=1234,bottom=1234,
 //    touch_high=30,touch_low=25,tap_time=30,tap_move=100
-static void evdev_apply_options(struct event_device *evdev, char *optstring)
+static int evdev_apply_options(struct event_device *evdev, char *optstring)
 {
    char *type = "auto";
    struct option_helper optinfo[] = {
@@ -606,7 +702,7 @@
    };
 
    if (parse_options("evdev", optstring, ',', optinfo) < 0)
-      gpm_report(GPM_PR_OOPS, "evdev: failed to parse option string");
+      return -1;
 
    if (strcmp(type, "auto"))
       evdev->type = evdev_str_to_type(type);
@@ -636,11 +732,16 @@
       case EVDEV_SYNAPTICS:
          warn_if_present(optinfo, "y_inverted", type);
          break;
+
+      default:
+         return -1;
    }
+   return 0;
 }
 
 int I_evdev(struct micedev *dev, struct miceopt *opts, Gpm_Type *type)
 {
+   struct input_id id;
    struct evdev_capabilities caps;
    struct event_device *evdev;
 
@@ -650,33 +751,37 @@
 
       memset(evdev, 0, sizeof(*evdev));
 
-      evdev_get_capabilities(dev->fd, &caps);
-      evdev->type = evdev_guess_type(&caps);
+      if (evdev_get_id(dev->fd, &id))
+         goto init_fail;
+
+      if (evdev_get_capabilities(dev->fd, &caps))
+         goto init_fail;
+
+      evdev->type = evdev_guess_type(&id, &caps);
 
       /* load default values - suitable for my synaptics ;P */
       evdev->left_edge = 1900;
-      evdev->right_edge = 5400;
-      evdev->top_edge = 3900;
-      evdev->bottom_edge = 1800;
+      evdev->right_edge = 5300;
+      evdev->top_edge = 2000;
+      evdev->bottom_edge = 3900;
       evdev->tap_time = 180;
       evdev->tap_move = 220;
       evdev->touch_high = 30;
       evdev->touch_low = 25;
 
-      if (evdev->type == EVDEV_ABSOLUTE) {
-         if (test_bit(ABS_X, caps.absbits))
-            evdev_query_axis(dev->fd, ABS_X, &evdev->left_edge, &evdev->right_edge);
-         if (test_bit(ABS_Y, caps.absbits))
-            evdev_query_axis(dev->fd, ABS_Y, &evdev->bottom_edge, &evdev->top_edge);
-      }
+      if (evdev->type == EVDEV_ABSOLUTE && evdev_get_limits(dev->fd, evdev, &caps) < 0)
+         goto init_fail;
 
-      evdev_apply_options(evdev, opts->text);
+      if (evdev_apply_options(evdev, opts->text) < 0)
+         goto init_fail;
 
       if (!test_bit(EV_SYNC, caps.evbits)) {
          evdev->dont_sync = 1;
-         if (evdev->type == EVDEV_TOUCHPAD || evdev->type == EVDEV_SYNAPTICS)
-            gpm_report(GPM_PR_OOPS,
+         if (evdev->type == EVDEV_TOUCHPAD || evdev->type == EVDEV_SYNAPTICS) {
+            gpm_report(GPM_PR_ERR,
                        "evdev: The running kernel lacks EV_SYNC support which is required for touchpad/synaptics mode");
+            goto init_fail;
+         }
       }
 
       switch (evdev->type) {
@@ -688,10 +793,14 @@
 
          case EVDEV_ABSOLUTE:
             gpm_report(GPM_PR_INFO, "evdev: selected Absolute mode");
-            if (evdev->right_edge <= evdev->left_edge)
-               gpm_report(GPM_PR_OOPS, "evdev: right edge value should be gerater then left");
-            if (evdev->top_edge <= evdev->bottom_edge)
-               gpm_report(GPM_PR_OOPS, "evdev: top edge value should be gerater then bottom");
+            if (evdev->right_edge <= evdev->left_edge) {
+               gpm_report(GPM_PR_ERR, "evdev: right edge value should be gerater than left");
+               goto init_fail;
+            }
+            if (evdev->bottom_edge <= evdev->top_edge) {
+               gpm_report(GPM_PR_ERR, "evdev: bottom edge value should be gerater than top");
+               goto init_fail;
+            }
             if (!test_bit(EV_ABS, caps.evbits))
                gpm_report(GPM_PR_WARN, "evdev: selected absolute mode but device does not report any absolute events");
             opts->absolute = 1;
@@ -701,23 +810,42 @@
             gpm_report(GPM_PR_INFO, "evdev: selected Touchpad mode");
             if (!test_bit(EV_ABS, caps.evbits))
                gpm_report(GPM_PR_WARN, "evdev: selected touchpad mode but device does not report any absolute events");
-            if (!test_bit(ABS_PRESSURE, caps.absbits))
-               gpm_report(GPM_PR_WARN, "evdev: selected touchpad mode but device does not report pressure");
+            if (test_bit(ABS_PRESSURE, caps.absbits))
+               evdev->detect_touch = smart_tp_detect_touch;
+            else if (test_bit(BTN_TOUCH, caps.keybits))
+               evdev->detect_touch = dumb_tp_detect_touch;
+            else
+               gpm_report(GPM_PR_WARN, "evdev: selected touchpad mode but device does not report pressure not touch events");
+            evdev->update_finger_count = tp_update_finger_count;
             break;
 
          case EVDEV_SYNAPTICS:
             gpm_report(GPM_PR_INFO, "evdev: selected Synaptics mode");
+            if (!is_synaptics(&id))
+               gpm_report(GPM_PR_WARN, "evdev: idevice isn't identified as Synaptics");
             if (!test_bit(EV_ABS, caps.evbits))
                gpm_report(GPM_PR_WARN, "evdev: selected synaptics mode but device does not report any absolute events");
             if (!test_bit(ABS_PRESSURE, caps.absbits))
                gpm_report(GPM_PR_WARN, "evdev: selected synaptics mode but device does not report pressure");
-            if (!test_bit(EV_MSC, caps.evbits) || !test_bit(MSC_GESTURE, caps.mscbits))
-               gpm_report(GPM_PR_WARN, "evdev: selected synaptics mode but device does not report gesture events");
-            evdev->y_inverted = 1;     /* Synaptics always has Y inverted */
+            if (test_bit(EV_MSC, caps.evbits) && test_bit(MSC_GESTURE, caps.mscbits)) {
+               /* this is compatibility mode with pre 2.6-test6 kernels */
+               evdev->update_finger_count = syn_update_finger_count;
+               evdev->y_inverted = 1;
+            } else {
+               evdev->update_finger_count = tp_update_finger_count;
+            }
+            evdev->detect_touch = syn_detect_touch;
+            break;
+
+         default:
             break;
       }
    }
 
    return 0;
+
+init_fail:
+   free(dev->private);
+   return -1;
 }
 
diff -Nru a/src/headers/input-defines.h b/src/headers/input-defines.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/src/headers/input-defines.h	2004-08-10 01:18:01 -05:00
@@ -0,0 +1,81 @@
+/*
+ * input-defines.h - complements <linux/input.h> adding missing bits
+ *
+ * Copyright (C) 2003        Dmitry Torokhov <dtor@mail.ru>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ ********/
+#ifndef __GPM_INPUT_DEFINES_H
+#define __GPM_INPUT_DEFINES_H
+
+#include <linux/input.h>
+#include "headers/config.h"
+
+#ifndef ABS_TOOL_WIDTH
+#define ABS_TOOL_WIDTH        0x1c
+#endif
+
+#ifndef BTN_TOOL_FINGER
+#define BTN_TOOL_FINGER       0x145
+#endif
+
+#ifndef BTN_TOUCH
+#define BTN_TOUCH             0x14a
+#endif
+
+#ifndef BTN_TOOL_DOUBLETAP
+#define BTN_TOOL_DOUBLETAP    0x14d
+#endif
+
+#ifndef BTN_TOOL_TRIPLETAP
+#define BTN_TOOL_TRIPLETAP    0x14e
+#endif
+
+#ifndef MSC_GESTURE
+#define MSC_GESTURE           2
+#endif
+
+#ifndef EV_SYNC
+#define EV_SYNC               0
+#endif
+
+#ifndef SYN_REPORT
+#define SYN_REPORT            0
+#endif
+
+#ifndef PSMOUSE_SYNAPTICS
+#define PSMOUSE_SYNAPTICS     7
+#endif
+
+#ifndef HAVE_INPUT_ID
+struct input_id {
+   unsigned short bustype;
+   unsigned short vendor;
+   unsigned short product;
+   unsigned short version;
+};
+#endif
+
+#ifndef HAVE_INPUT_ABSINFO
+struct input_absinfo {
+   int value;
+   int minimum;
+   int maximum;
+   int fuzz;
+   int flat;
+};
+#endif
+
+#endif


More information about the gpm mailing list