--- linux-2.5.59/drivers/input/mousedev.c 2003-01-17 03:22:43.000000000 +0100 +++ linux-2.5.59_jlt/drivers/input/mousedev.c 2003-02-02 14:27:36.000000000 +0100 @@ -36,6 +36,12 @@ #ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_Y #define CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768 #endif +#ifndef CONFIG_INPUT_MOUSEDEV_TAPFRACT +#define CONFIG_INPUT_MOUSEDEV_TAPFRACT 12 +#endif +#ifndef CONFIG_INPUT_MOUSEDEV_DRAGFRACT +#define CONFIG_INPUT_MOUSEDEV_DRAGFRACT 8 +#endif struct mousedev { int exist; @@ -53,7 +59,9 @@ struct fasync_struct *fasync; struct mousedev *mousedev; struct list_head node; - int dx, dy, dz, oldx, oldy; + int dx, dy, dz, oldx, oldy, touchx, touchy; + char touched, tapped; + unsigned long tstamp; signed char ps2[6]; unsigned long buttons; unsigned char ready, buffer, bufsiz; @@ -62,6 +70,13 @@ #define MOUSEDEV_SEQ_LEN 6 +#define TAPSTATE_NONE 0 +#define TAPSTATE_TAPPED 1 +#define TAPSTATE_DRAGORDOUBLE 2 +#define TAPSTATE_DRAG 3 +#define TAPSTATE_DOUBLE 4 +#define TAPSTATE_DOUBLE2 5 + static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 }; static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; @@ -72,6 +87,43 @@ static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X; static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y; +static int taptimeout = HZ/CONFIG_INPUT_MOUSEDEV_TAPFRACT; +static int dragtimeout = HZ/CONFIG_INPUT_MOUSEDEV_DRAGFRACT; + +static inline void mousedev_touch(struct mousedev_list *list) +{ + list->touched = 1; + + if (list->tapped == TAPSTATE_TAPPED) + /* drag or double tap */ + list->tapped++; + + list->tstamp = jiffies; + list->touchx = list->oldx; + list->touchy = list->oldy; +} + +static inline void mousedev_touch_release(struct input_handle *handle, struct mousedev_list *list) +{ + list->touched = 0; + + if (((list->tapped == 0) || (list->tapped == TAPSTATE_DRAGORDOUBLE)) && + (!time_after(jiffies, list->tstamp + taptimeout)) && + (abs(list->oldx - list->touchx) < (handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X]) * xres / 40) && + (abs(list->oldy - list->touchy) < (handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y]) * yres / 40)) { + if (list->tapped == TAPSTATE_DRAGORDOUBLE) + /* double */ + list->tapped += 2; + else + list->tapped++; + + list->dx = 0; + list->dy = 0; + } else + list->tapped = TAPSTATE_NONE; + + list->tstamp = jiffies; +} static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { @@ -99,6 +151,8 @@ list->dx += value - list->oldx; list->oldx += list->dx; } + if (!list->touched || (list->tapped == 1)) + list->dx = 0; break; case ABS_Y: @@ -110,6 +164,16 @@ list->dy -= value - list->oldy; list->oldy -= list->dy; } + if (!list->touched || (list->tapped == 1)) + list->dy = 0; + break; + + case ABS_PRESSURE: + if (!list->touched) { + if (value > 30) + mousedev_touch(list); + } else if (value < 25) + mousedev_touch_release(handle, list); break; } break; @@ -235,6 +299,8 @@ memset(list, 0, sizeof(struct mousedev_list)); list->mousedev = mousedev_table[i]; + list->touched = 1; + list->tapped = 0; list_add_tail(&list->node, &mousedev_table[i]->list); file->private_data = list; @@ -255,28 +321,70 @@ static void mousedev_packet(struct mousedev_list *list, unsigned char off) { - list->ps2[off] = 0x08 | ((list->dx < 0) << 4) | ((list->dy < 0) << 5) | (list->buttons & 0x07); - list->ps2[off + 1] = (list->dx > 127 ? 127 : (list->dx < -127 ? -127 : list->dx)); - list->ps2[off + 2] = (list->dy > 127 ? 127 : (list->dy < -127 ? -127 : list->dy)); - list->dx -= list->ps2[off + 1]; - list->dy -= list->ps2[off + 2]; - list->bufsiz = off + 3; - - if (list->mode == 2) { - list->ps2[off + 3] = (list->dz > 7 ? 7 : (list->dz < -7 ? -7 : list->dz)); - list->dz -= list->ps2[off + 3]; - list->ps2[off + 3] = (list->ps2[off + 3] & 0x0f) | ((list->buttons & 0x18) << 1); - list->bufsiz++; - } - - if (list->mode == 1) { - list->ps2[off + 3] = (list->dz > 127 ? 127 : (list->dz < -127 ? -127 : list->dz)); - list->dz -= list->ps2[off + 3]; - list->bufsiz++; + /* Dont move during taps. But accumulate dx, dy etc. - we might drag. */ + if (!list->tapped || (list->tapped == TAPSTATE_DRAG)) { + list->ps2[off] = 0x08 | ((list->dx < 0) << 4) | ((list->dy < 0) << 5) | (list->buttons & 0x07); + list->ps2[off + 1] = (list->dx > 127 ? 127 : (list->dx < -127 ? -127 : list->dx)); + list->ps2[off + 2] = (list->dy > 127 ? 127 : (list->dy < -127 ? -127 : list->dy)); + list->dx -= list->ps2[off + 1]; + list->dy -= list->ps2[off + 2]; + list->bufsiz = off + 3; + + if (list->mode == 2) { + list->ps2[off + 3] = (list->dz > 7 ? 7 : (list->dz < -7 ? -7 : list->dz)); + list->dz -= list->ps2[off + 3]; + list->ps2[off + 3] = (list->ps2[off + 3] & 0x0f) | ((list->buttons & 0x18) << 1); + list->bufsiz++; + } + + if (list->mode == 1) { + list->ps2[off + 3] = (list->dz > 127 ? 127 : (list->dz < -127 ? -127 : list->dz)); + list->dz -= list->ps2[off + 3]; + list->bufsiz++; + } + } else { + list->ps2[off] = 0x08 | (list->buttons & 0x07); + list->ps2[off + 1] = 0; + list->ps2[off + 2] = 0; + list->bufsiz = off + 3; + + if (list->mode == 2) { + list->ps2[off + 3] = (list->buttons & 0x18) << 1; + list->bufsiz++; + } } if (!list->dx && !list->dy && (!list->mode || !list->dz)) list->ready = 0; list->buffer = list->bufsiz; + + switch (list->tapped) { + case TAPSTATE_TAPPED: + /* tap -> press and hold until we know if it is a drag */ + if (!time_after(jiffies, list->tstamp + dragtimeout)) + list->ps2[off] |= 0x01; + else + list->tapped = TAPSTATE_NONE; + break; + case TAPSTATE_DRAGORDOUBLE: + /* drag or doubletap -> hold button */ + list->ps2[off] |= 0x01; + if (time_after(jiffies, list->tstamp + taptimeout)) + list->tapped++; + break; + case TAPSTATE_DRAG: + /* drag -> hold button */ + list->ps2[off] |= 0x01; + break; + case TAPSTATE_DOUBLE: + /* double tap (part 1) -> release button */ + list->tapped++; + break; + case TAPSTATE_DOUBLE2: + /* double tap (part 2) -> click button */ + list->ps2[off] |= 0x01; + list->tapped = TAPSTATE_NONE; + break; + } }