[gpm] [PATCH 12/18] evdev-support.patch
Dmitry Torokhov
dtor_core@ameritech.net
Tue Aug 10 08:58:34 CEST 2004
===================================================================
ChangeSet@1.16, 2004-08-10 00:53:28-05:00, dtor_core@ameritech.net
Extended support for event devices.
Use ioctls to retrieve device capabilities and select best mode.
configure.ac | 6
src/Makefile.in | 7
src/evdev.c | 643 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/mice.c | 24 --
4 files changed, 657 insertions(+), 23 deletions(-)
===================================================================
diff -Nru a/configure.ac b/configure.ac
--- a/configure.ac 2004-08-10 01:18:00 -05:00
+++ b/configure.ac 2004-08-10 01:18:00 -05:00
@@ -82,6 +82,11 @@
CURSES_OBJS=lib/libcurses.o ; fi ;;
esac
+EVDEV_SRCS=
+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>])
+fi
ITZ_CHECK_TYPE(__u32,linux/types.h)
if test ${itz_cv_type___u32} = yes || test ${ac_cv_type___u32} = yes ; then
@@ -166,6 +171,7 @@
AC_SUBST(PICFLAGS)
AC_SUBST(SOLDFLAGS)
AC_SUBST(CURSES_OBJS)
+AC_SUBST(EVDEV_SRCS)
AC_SUBST(SHARED_LIBS)
AC_SUBST(LIBM)
AC_SUBST(lispdir)
diff -Nru a/src/Makefile.in b/src/Makefile.in
--- a/src/Makefile.in 2004-08-10 01:18:00 -05:00
+++ b/src/Makefile.in 2004-08-10 01:18:00 -05:00
@@ -12,9 +12,10 @@
include $(top_builddir)/Makefile.include
# Main portion: regular build rules
+MICESRC = mice.c twiddler.c synaptics.c @EVDEV_SRCS@
-GSRC = main.c gpm.c gpn.c mice.c special.c twiddler.c synaptics.c \
- startup.c server_tools.c console.c client.c optparser.c
+GSRC = main.c gpm.c gpn.c special.c startup.c server_tools.c console.c \
+ client.c optparser.c $(MICESRC)
GOBJ = $(GSRC:.c=.o) report.o tools.o
@@ -153,7 +154,7 @@
$(CC) -I. @CPPFLAGS@ $(CPPFLAGS) @CFLAGS@ $(CFLAGS) -c -o $@.o $<
$(CC) @LDFLAGS@ $(LDFLAGS) -o $@ $@.o @LIBS@ $(LIBS) lib/libgpm.a
-prog/mouse-test: mice.o twiddler.o synaptics.o console.o optparser.o
+prog/mouse-test: $(MICESRC:.c=.o) console.o optparser.o
$(PROG): @SHLIB@ lib/libgpm.a
diff -Nru a/src/evdev.c b/src/evdev.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/src/evdev.c 2004-08-10 01:18:00 -05:00
@@ -0,0 +1,643 @@
+/*
+ * evdev.c - support for event input devices in linux 2.4 & 2.6
+ *
+ * Copyright (C) 2003 Dmitry Torokhov <dtor@mail.ru>
+ * Based on XFree86 driver by Stefan Gmeiner & Peter Osterlund
+ *
+ * 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.
+ ********/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <sys/select.h>
+#include <sys/time.h>
+
+#include <linux/input.h>
+
+#include "headers/gpm.h"
+#include "headers/gpmInt.h"
+#include "headers/console.h"
+#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_RELATIVE,
+ EVDEV_ABSOLUTE,
+ EVDEV_TOUCHPAD,
+ EVDEV_SYNAPTICS
+};
+
+enum touch_type {
+ TOUCH_NONE,
+ TOUCH_FINGERS,
+ TOUCH_PALM
+};
+
+enum edge_type {
+ BOTTOM_EDGE = 1,
+ TOP_EDGE = 2,
+ LEFT_EDGE = 4,
+ RIGHT_EDGE = 8,
+ LEFT_BOTTOM_EDGE = BOTTOM_EDGE | LEFT_EDGE,
+ RIGHT_BOTTOM_EDGE = BOTTOM_EDGE | RIGHT_EDGE,
+ RIGHT_TOP_EDGE = TOP_EDGE | RIGHT_EDGE,
+ LEFT_TOP_EDGE = TOP_EDGE | LEFT_EDGE
+};
+
+struct event_data {
+ int dx, dy;
+ int wdx, wdy;
+ int abs_x, abs_y;
+ int buttons;
+ int pressure;
+ int w;
+ int synced;
+};
+
+struct touch_data {
+ enum touch_type type;
+ int finger_count;
+ int x, y;
+ int buttons;
+ struct timeval start;
+};
+
+struct event_device {
+ enum evdev_type type;
+ int dont_sync;
+
+ struct event_data pkt;
+ int pkt_count;
+
+ int prev_x[4], prev_y[4];
+ int prev_pressure, avg_w;
+ struct touch_data touch;
+
+ int left_edge, right_edge;
+ int top_edge, bottom_edge;
+ int touch_high, touch_low;
+ int tap_time, tap_move;
+ int y_inverted;
+};
+
+struct evdev_capabilities {
+ unsigned char evbits[EV_MAX/8 + 1];
+ unsigned char keybits[KEY_MAX/8 + 1];
+ unsigned char absbits[ABS_MAX/8 + 1];
+ unsigned char mscbits[MSC_MAX/8 + 1];
+};
+
+#ifndef max
+#define max(a,b) ((a)>(b) ? (a) : (b))
+#endif
+
+#define fx(i) (evdev->prev_x[(evdev->pkt_count - (i)) & 03])
+#define fy(i) (evdev->prev_y[(evdev->pkt_count - (i)) & 03])
+
+#define toggle_btn(btn, val) do { if (val) data->buttons |= (btn);\
+ else data->buttons &= ~(btn);\
+ } while (0)
+#define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL))
+#define DIF_TIME(t1,t2) ((t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec) / 1000)
+
+#define test_bit(bit, array) (array[bit / 8] & (1 << (bit % 8)))
+
+/* ------------- evdev protocol handling routines ---------------------*/
+
+static void parse_input_event(struct input_event *event, struct event_data *data)
+{
+ switch (event->type) {
+ case EV_REL:
+ switch (event->code) {
+ case REL_X:
+ data->dx = (signed char)event->value;
+ break;
+ case REL_Y:
+ data->dy = (signed char)event->value;
+ break;
+ case REL_WHEEL:
+ data->wdy += event->value;
+ break;
+ case REL_HWHEEL:
+ data->wdx += event->value;
+ break;
+ }
+ break;
+
+ case EV_ABS:
+ switch (event->code) {
+ case ABS_X:
+ data->abs_x = event->value;
+ break;
+
+ case ABS_Y:
+ data->abs_y = event->value;
+ break;
+
+ case ABS_PRESSURE:
+ data->pressure = event->value;
+ break;
+ }
+ break;
+
+ case EV_MSC:
+ switch (event->code) {
+ case MSC_GESTURE:
+ data->w = event->value;
+ break;
+ }
+ break;
+
+
+ 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;
+ }
+ break;
+
+ case EV_SYNC:
+ switch(event->code) {
+ case SYN_REPORT:
+ data->synced = 1;
+ break;
+ }
+ break;
+ }
+}
+
+static void tp_figure_deltas(struct event_device *evdev, struct Gpm_Event *state)
+{
+ struct event_data *pkt = &evdev->pkt;
+
+ if (evdev->touch.type == TOUCH_FINGERS) {
+ fx(0) = pkt->abs_x;
+ fy(0) = pkt->abs_y;
+ if (evdev->pkt_count >= 2) {
+ state->dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) / 8; //SYN_REL_DECEL_FACTOR;
+ state->dy = ((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) / 8; //SYN_REL_DECEL_FACTOR;
+ }
+ evdev->pkt_count++;
+ } else {
+ state->dx = state->dy = 0;
+ evdev->pkt_count = 0;
+ }
+}
+
+static enum touch_type tp_detect_touch(struct event_device *evdev)
+{
+ if (evdev->touch.type == TOUCH_FINGERS)
+ return evdev->pkt.pressure > evdev->touch_low ? TOUCH_FINGERS : TOUCH_NONE;
+ else
+ return evdev->pkt.pressure > evdev->touch_high ? TOUCH_FINGERS : TOUCH_NONE;
+}
+
+static enum touch_type syn_detect_touch(struct event_device *evdev)
+{
+ struct event_data *pkt = &evdev->pkt;
+ enum touch_type type = TOUCH_NONE;
+
+ if (pkt->pressure > 200 || pkt->w > 10)
+ return TOUCH_PALM; /* 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)
+ type = pkt->pressure > evdev->touch_low ? TOUCH_FINGERS : TOUCH_NONE;
+ else if (pkt->pressure > evdev->touch_high) {
+ int safe_w = max(pkt->w, evdev->avg_w);
+
+ 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 */
+ else if (safe_w < 7 && evdev->prev_pressure < evdev->touch_high / 2)
+ type = TOUCH_FINGERS; /* thin finger, distinct touch -> not a palm */
+ else if (pkt->pressure > evdev->prev_pressure + 1)
+ type = TOUCH_NONE; /* pressure not stable, may be a palm */
+ else if (pkt->pressure < evdev->prev_pressure - 5)
+ type = TOUCH_NONE; /* pressure not stable, may be a palm */
+ else
+ type = TOUCH_FINGERS;
+ }
+
+ evdev->prev_pressure = pkt->pressure;
+ return type;
+}
+
+static enum edge_type tp_detect_edges(struct event_device *evdev, int x, int y)
+{
+ enum edge_type edge = 0;
+
+ if (x > evdev->right_edge)
+ edge |= RIGHT_EDGE;
+ else if (x < evdev->left_edge)
+ edge |= LEFT_EDGE;
+
+ if (y > evdev->top_edge)
+ edge |= TOP_EDGE;
+ else if (y < evdev->bottom_edge)
+ edge |= BOTTOM_EDGE;
+
+ return edge;
+}
+
+static int tp_touch_expired(struct event_device *evdev)
+{
+ struct timeval now;
+
+ GET_TIME(now);
+ return DIF_TIME(evdev->touch.start, now) > evdev->tap_time;
+}
+
+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);
+}
+
+static int tp_process_tap(struct event_device *evdev, struct Gpm_Event *state)
+{
+ struct touch_data *touch = &evdev->touch;
+ int was_touching = touch->type == TOUCH_FINGERS;
+ enum edge_type edge;
+
+ touch->type = evdev->type == EVDEV_SYNAPTICS ?
+ syn_detect_touch(evdev) : tp_detect_touch(evdev);
+ if (touch->type != TOUCH_PALM) {
+ if (touch->type == TOUCH_FINGERS && !was_touching) {
+ GET_TIME(touch->start);
+ touch->x = evdev->pkt.abs_x;
+ touch->y = evdev->pkt.abs_y;
+ touch->buttons = 0;
+ } else if (was_touching && touch->type == TOUCH_NONE) {
+ if (tp_detect_tap(evdev)) {
+ edge = tp_detect_edges(evdev, evdev->pkt.abs_x, evdev->pkt.abs_y);
+ if (!touch->finger_count) {
+ switch (edge) {
+ case RIGHT_TOP_EDGE:
+ touch->buttons |= GPM_B_MIDDLE;
+ break;
+ case RIGHT_BOTTOM_EDGE:
+ touch->buttons |= GPM_B_RIGHT;
+ break;
+ default:
+ touch->buttons |= GPM_B_LEFT;
+ break;
+ }
+ } else {
+ switch (touch->finger_count) {
+ case 2:
+ touch->buttons |= GPM_B_MIDDLE;
+ break;
+ case 3:
+ touch->buttons |= GPM_B_RIGHT;
+ break;
+ default:
+ touch->buttons |= GPM_B_LEFT;
+ break;
+ }
+ }
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static void compose_gpm_event(struct event_device *evdev, Gpm_Event *state)
+{
+ struct event_data *pkt = &evdev->pkt;
+
+ state->buttons = pkt->buttons;
+ state->wdx = pkt->wdx; state->wdy = pkt->wdy;
+
+ switch (evdev->type) {
+ case EVDEV_RELATIVE:
+ state->dx = pkt->dx; state->dy = pkt->dy;
+ break;
+
+ case EVDEV_ABSOLUTE:
+ if (pkt->abs_x < evdev->left_edge)
+ pkt->abs_x = evdev->left_edge;
+ else if (pkt->abs_x > evdev->right_edge)
+ pkt->abs_x = evdev->right_edge;
+ if (pkt->abs_y < evdev->bottom_edge)
+ pkt->abs_y = evdev->bottom_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);
+ if (evdev->y_inverted) state->y = console.max_y - state->y;
+ break;
+
+ case EVDEV_TOUCHPAD:
+ case EVDEV_SYNAPTICS:
+ if (tp_process_tap(evdev, state))
+ state->buttons |= evdev->touch.buttons;
+
+ 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;
+
+ tp_figure_deltas(evdev, state);
+ break;
+ }
+ if (evdev->y_inverted) state->dy = -state->dy;
+}
+
+int M_evdev(struct micedev *dev, struct miceopt *opts,
+ unsigned char *data, struct Gpm_Event *state)
+{
+ struct event_device *evdev = dev->private;
+ struct input_event *event = (struct input_event *)data;
+
+ parse_input_event(event, &evdev->pkt);
+ if (evdev->pkt.synced || evdev->dont_sync) {
+ compose_gpm_event(evdev, state);
+ evdev->pkt.synced = 0;
+ return 0;
+ }
+ return -1;
+}
+
+/* ------------- evdev initialization routines ---------------------*/
+
+static void 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");
+ }
+
+ 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");
+ }
+
+ 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");
+ }
+
+ 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");
+ */
+ }
+}
+
+static void 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
+ gpm_report(GPM_PR_ERR, "evdev: could not query axis data");
+}
+
+static enum evdev_type evdev_guess_type(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;
+
+ return test_bit(EV_MSC, caps->evbits) && test_bit(MSC_GESTURE, caps->mscbits) ?
+ EVDEV_SYNAPTICS : EVDEV_TOUCHPAD;
+ }
+
+ if (!test_bit(EV_REL, caps->evbits))
+ gpm_report(GPM_PR_OOPS,
+ "evdev: device does not report neither absolute nor relative coordinates");
+
+ return EVDEV_RELATIVE;
+}
+
+static enum evdev_type evdev_str_to_type(const char *type)
+{
+ if (!strcmp(type, "relative")) {
+ return EVDEV_RELATIVE;
+ } else if (!strcmp(type, "absolute")) {
+ return EVDEV_ABSOLUTE;
+ } else if (!strcmp(type, "touchpad")) {
+ return EVDEV_TOUCHPAD;
+ } 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 */
+ }
+}
+
+static void warn_if_present(struct option_helper *optinfo, const char *name, const char *type)
+{
+ if (is_option_present(optinfo, name))
+ gpm_report(GPM_PR_WARN,
+ "evdev: option '%s' is not valud for type '%s', ignored",
+ name, type);
+}
+
+// -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)
+{
+ char *type = "auto";
+ struct option_helper optinfo[] = {
+ { "type", OPT_STRING, u: { sptr: &type } },
+ { "y_inverted", OPT_BOOL, u: { iptr: &evdev->y_inverted }, value: 1 },
+ { "left", OPT_INT, u: { iptr: &evdev->left_edge } },
+ { "right", OPT_INT, u: { iptr: &evdev->right_edge } },
+ { "top", OPT_INT, u: { iptr: &evdev->top_edge } },
+ { "bottom", OPT_INT, u: { iptr: &evdev->bottom_edge } },
+ { "touch_high", OPT_INT, u: { iptr: &evdev->touch_high } },
+ { "touch_low", OPT_INT, u: { iptr: &evdev->touch_low } },
+ { "tap_time", OPT_INT, u: { iptr: &evdev->tap_time } },
+ { "tap_move", OPT_INT, u: { iptr: &evdev->tap_move } },
+ { "", OPT_END }
+ };
+
+ if (parse_options("evdev", optstring, ',', optinfo) < 0)
+ gpm_report(GPM_PR_OOPS, "evdev: failed to parse option string");
+
+ if (strcmp(type, "auto"))
+ evdev->type = evdev_str_to_type(type);
+
+ switch (evdev->type) {
+ case EVDEV_RELATIVE:
+ warn_if_present(optinfo, "left", type);
+ warn_if_present(optinfo, "right", type);
+ warn_if_present(optinfo, "top", type);
+ warn_if_present(optinfo, "bottom", type);
+ warn_if_present(optinfo, "tap_move", type);
+ warn_if_present(optinfo, "tap_time", type);
+ warn_if_present(optinfo, "touch_high", type);
+ warn_if_present(optinfo, "touch_low", type);
+ break;
+
+ case EVDEV_ABSOLUTE:
+ warn_if_present(optinfo, "tap_move", type);
+ warn_if_present(optinfo, "tap_time", type);
+ warn_if_present(optinfo, "touch_high", type);
+ warn_if_present(optinfo, "touch_low", type);
+ break;
+
+ case EVDEV_TOUCHPAD:
+ break;
+
+ case EVDEV_SYNAPTICS:
+ warn_if_present(optinfo, "y_inverted", type);
+ break;
+ }
+}
+
+int I_evdev(struct micedev *dev, struct miceopt *opts, Gpm_Type *type)
+{
+ struct evdev_capabilities caps;
+ struct event_device *evdev;
+
+ if (!dev->private) { /* called first time, not re-init */
+ if (!(dev->private = evdev = malloc(sizeof(*evdev))))
+ gpm_report(GPM_PR_OOPS, "Can't allocate memory for event device");
+
+ memset(evdev, 0, sizeof(*evdev));
+
+ evdev_get_capabilities(dev->fd, &caps);
+ evdev->type = evdev_guess_type(&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->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);
+ }
+
+ evdev_apply_options(evdev, opts->text);
+
+ 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,
+ "evdev: The running kernel lacks EV_SYNC support which is required for touchpad/synaptics mode");
+ }
+
+ switch (evdev->type) {
+ case EVDEV_RELATIVE:
+ gpm_report(GPM_PR_INFO, "evdev: selected Relative mode");
+ if (!test_bit(EV_REL, caps.evbits))
+ gpm_report(GPM_PR_WARN, "evdev: selected relative mode but device does not report any relative events");
+ break;
+
+ 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 (!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;
+ break;
+
+ case EVDEV_TOUCHPAD:
+ 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");
+ break;
+
+ case EVDEV_SYNAPTICS:
+ gpm_report(GPM_PR_INFO, "evdev: selected Synaptics mode");
+ 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 */
+ break;
+ }
+ }
+
+ return 0;
+}
+
diff -Nru a/src/mice.c b/src/mice.c
--- a/src/mice.c 2004-08-10 01:18:00 -05:00
+++ b/src/mice.c 2004-08-10 01:18:00 -05:00
@@ -134,25 +134,9 @@
/*========================================================================*/
#ifdef HAVE_LINUX_INPUT_H
-static int M_evdev(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state)
-{
- struct input_event thisevent;
- (void) memcpy (&thisevent, data, sizeof (struct input_event));
- if (thisevent.type == EV_REL) {
- if (thisevent.code == REL_X)
- state->dx = (signed char) thisevent.value;
- else if (thisevent.code == REL_Y)
- state->dy = (signed char) thisevent.value;
- } else if (thisevent.type == EV_KEY) {
- switch(thisevent.code) {
- case BTN_LEFT: state->buttons ^= GPM_B_LEFT; break;
- case BTN_MIDDLE: state->buttons ^= GPM_B_MIDDLE; break;
- case BTN_RIGHT: state->buttons ^= GPM_B_RIGHT; break;
- case BTN_SIDE: state->buttons ^= GPM_B_MIDDLE; break;
- }
- }
- return 0;
-}
+/* defined in evdev.c */
+extern int M_evdev(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state);
+extern int I_evdev(struct micedev *dev, struct miceopt *opt, Gpm_Type *type);
#endif /* HAVE_LINUX_INPUT_H */
static int M_ms(struct micedev *dev, struct miceopt *opt, unsigned char *data, Gpm_Event *state)
@@ -2129,7 +2113,7 @@
{0x80, 0x80, 0x80, 0x00}, 6, 6, 0, 0, 0},
#ifdef HAVE_LINUX_INPUT_H
{"evdev", "Linux Event Device",
- "", M_evdev, I_empty, STD_FLG,
+ "", M_evdev, I_evdev, STD_FLG,
{0x00, 0x00, 0x00, 0x00} , 16, 16, 0, 0, NULL},
#endif /* HAVE_LINUX_INPUT_H */
{"exps2", "IntelliMouse Explorer (ps2) - 3 buttons, wheel unused",
More information about the gpm
mailing list