=================================================================== ChangeSet@xxxx, 2004-08-10 00:53:37-05:00, dtor_core@xxxxxxxxxxxxx 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@xxxxxxx> + * + * 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 _______________________________________________ gpm mailing list gpm@xxxxxxxxxxxxxx http://lists.linux.it/listinfo/gpm