Commit 4ea686bc authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Vojtech Pavlik

Input: mousedev - better multiplex absolute and relative devices;

       cleanups
parent c13036e5
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Input driver to ExplorerPS/2 device driver module. * Input driver to ExplorerPS/2 device driver module.
* *
* Copyright (c) 1999-2002 Vojtech Pavlik * Copyright (c) 1999-2002 Vojtech Pavlik
* Copyright (c) 2004 Dmitry Torokhov
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published by * it under the terms of the GNU General Public License version 2 as published by
...@@ -47,15 +48,24 @@ static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y; ...@@ -47,15 +48,24 @@ static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
module_param(yres, uint, 0); module_param(yres, uint, 0);
MODULE_PARM_DESC(yres, "Vertical screen resolution"); MODULE_PARM_DESC(yres, "Vertical screen resolution");
struct mousedev_motion {
int dx, dy, dz;
};
struct mousedev { struct mousedev {
int exist; int exist;
int open; int open;
int minor; int minor;
int misc;
char name[16]; char name[16];
wait_queue_head_t wait; wait_queue_head_t wait;
struct list_head list; struct list_head list;
struct input_handle handle; struct input_handle handle;
struct mousedev_motion packet;
unsigned long buttons;
unsigned int pkt_count;
int old_x[4], old_y[4];
unsigned int touch;
}; };
struct mousedev_list { struct mousedev_list {
...@@ -63,13 +73,10 @@ struct mousedev_list { ...@@ -63,13 +73,10 @@ struct mousedev_list {
struct mousedev *mousedev; struct mousedev *mousedev;
struct list_head node; struct list_head node;
int dx, dy, dz; int dx, dy, dz;
int old_x[4], old_y[4];
unsigned long buttons; unsigned long buttons;
signed char ps2[6]; signed char ps2[6];
unsigned char ready, buffer, bufsiz; unsigned char ready, buffer, bufsiz;
unsigned char mode, imexseq, impsseq; unsigned char mode, imexseq, impsseq;
unsigned int pkt_count;
unsigned char touch;
}; };
#define MOUSEDEV_SEQ_LEN 6 #define MOUSEDEV_SEQ_LEN 6
...@@ -82,135 +89,157 @@ static struct input_handler mousedev_handler; ...@@ -82,135 +89,157 @@ static struct input_handler mousedev_handler;
static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
static struct mousedev mousedev_mix; static struct mousedev mousedev_mix;
#define fx(i) (list->old_x[(list->pkt_count - (i)) & 03]) #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
#define fy(i) (list->old_y[(list->pkt_count - (i)) & 03]) #define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
static void mousedev_abs_event(struct input_handle *handle, struct mousedev_list *list, unsigned int code, int value) static void mousedev_touchpad_event(struct mousedev *mousedev, unsigned int code, int value)
{ {
int size; if (mousedev->touch) {
int touchpad; switch (code) {
case ABS_X:
fx(0) = value;
if (mousedev->pkt_count >= 2)
mousedev->packet.dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) / 8;
break;
/* Ignore joysticks */ case ABS_Y:
if (test_bit(BTN_TRIGGER, handle->dev->keybit)) fy(0) = value;
return; if (mousedev->pkt_count >= 2)
mousedev->packet.dy = -((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) / 8;
break;
}
}
}
touchpad = test_bit(BTN_TOOL_FINGER, handle->dev->keybit); static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value)
{
int size;
switch (code) { switch (code) {
case ABS_X: case ABS_X:
if (touchpad) { size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
if (list->touch) { if (size == 0) size = xres;
fx(0) = value; mousedev->packet.dx = (value * xres - mousedev->old_x[0]) / size;
if (list->pkt_count >= 2) mousedev->old_x[0] = mousedev->packet.dx * size;
list->dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) / 8;
}
} else {
size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
if (size == 0) size = xres;
list->dx += (value * xres - list->old_x[0]) / size;
list->old_x[0] += list->dx * size;
}
break; break;
case ABS_Y: case ABS_Y:
if (touchpad) { size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
if (list->touch) { if (size == 0) size = yres;
fy(0) = value; mousedev->packet.dy = (value * yres - mousedev->old_y[0]) / size;
if (list->pkt_count >= 2) mousedev->old_y[0] = mousedev->packet.dy * size;
list->dy = -((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) / 8;
}
} else {
size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
if (size == 0) size = yres;
list->dy -= (value * yres - list->old_y[0]) / size;
list->old_y[0] -= list->dy * size;
}
break; break;
} }
} }
static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) static void mousedev_rel_event(struct mousedev *mousedev, unsigned int code, int value)
{
switch (code) {
case REL_X: mousedev->packet.dx += value; break;
case REL_Y: mousedev->packet.dy -= value; break;
case REL_WHEEL: mousedev->packet.dz -= value; break;
}
}
static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int value)
{
int index;
switch (code) {
case BTN_TOUCH:
case BTN_0:
case BTN_FORWARD:
case BTN_LEFT: index = 0; break;
case BTN_STYLUS:
case BTN_1:
case BTN_RIGHT: index = 1; break;
case BTN_2:
case BTN_STYLUS2:
case BTN_MIDDLE: index = 2; break;
case BTN_3:
case BTN_BACK:
case BTN_SIDE: index = 3; break;
case BTN_4:
case BTN_EXTRA: index = 4; break;
default: return;
}
if (value) {
set_bit(index, &mousedev->buttons);
set_bit(index, &mousedev_mix.buttons);
} else {
clear_bit(index, &mousedev->buttons);
clear_bit(index, &mousedev_mix.buttons);
}
}
static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_motion *packet)
{ {
struct mousedev *mousedevs[3] = { handle->private, &mousedev_mix, NULL };
struct mousedev **mousedev = mousedevs;
struct mousedev_list *list; struct mousedev_list *list;
int index, wake;
list_for_each_entry(list, &mousedev->list, node) {
while (*mousedev) { list->dx += packet->dx;
list->dy += packet->dy;
wake = 0; list->dz += packet->dz;
list->buttons = mousedev->buttons;
list_for_each_entry(list, &(*mousedev)->list, node) list->ready = 1;
switch (type) { kill_fasync(&list->fasync, SIGIO, POLL_IN);
case EV_ABS: }
mousedev_abs_event(handle, list, code, value);
break; wake_up_interruptible(&mousedev->wait);
}
case EV_REL:
switch (code) { static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
case REL_X: list->dx += value; break; {
case REL_Y: list->dy -= value; break; struct mousedev *mousedev = handle->private;
case REL_WHEEL: if (list->mode) list->dz -= value; break;
} switch (type) {
break; case EV_ABS:
/* Ignore joysticks */
case EV_KEY: if (test_bit(BTN_TRIGGER, handle->dev->keybit))
if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) { return;
/* Handle touchpad data */
list->touch = value; if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
if (!list->touch) mousedev_touchpad_event(mousedev, code, value);
list->pkt_count = 0; else
break; mousedev_abs_event(handle->dev, mousedev, code, value);
}
break;
switch (code) {
case BTN_TOUCH: case EV_REL:
case BTN_0: mousedev_rel_event(mousedev, code, value);
case BTN_FORWARD: break;
case BTN_LEFT: index = 0; break;
case BTN_4: case EV_KEY:
case BTN_EXTRA: if (list->mode == 2) { index = 4; break; } if (value != 2) {
case BTN_STYLUS: if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) {
case BTN_1: /* Handle touchpad data */
case BTN_RIGHT: index = 1; break; mousedev->touch = value;
case BTN_3: if (!mousedev->touch)
case BTN_BACK: mousedev->pkt_count = 0;
case BTN_SIDE: if (list->mode == 2) { index = 3; break; } }
case BTN_2: else
case BTN_STYLUS2: mousedev_key_event(mousedev, code, value);
case BTN_MIDDLE: index = 2; break;
default: return;
}
switch (value) {
case 0: clear_bit(index, &list->buttons); break;
case 1: set_bit(index, &list->buttons); break;
case 2: return;
}
break;
case EV_SYN:
switch (code) {
case SYN_REPORT:
if (list->touch) {
list->pkt_count++;
/* Input system eats duplicate events,
* but we need all of them to do correct
* averaging so apply present one forward
*/
fx(0) = fx(1);
fy(0) = fy(1);
}
list->ready = 1;
kill_fasync(&list->fasync, SIGIO, POLL_IN);
wake = 1;
break;
}
} }
break;
case EV_SYN:
if (code == SYN_REPORT) {
if (mousedev->touch) {
mousedev->pkt_count++;
/* Input system eats duplicate events, but we need all of them
* to do correct averaging so apply present one forward
*/
fx(0) = fx(1);
fy(0) = fy(1);
}
if (wake) mousedev_notify_readers(mousedev, &mousedev->packet);
wake_up_interruptible(&((*mousedev)->wait)); mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
mousedev++; memset(&mousedev->packet, 0, sizeof(struct mousedev_motion));
}
break;
} }
} }
...@@ -326,6 +355,8 @@ static void mousedev_packet(struct mousedev_list *list, unsigned char off) ...@@ -326,6 +355,8 @@ static void mousedev_packet(struct mousedev_list *list, unsigned char off)
list->dz -= list->ps2[off + 3]; list->dz -= list->ps2[off + 3];
list->ps2[off + 3] = (list->ps2[off + 3] & 0x0f) | ((list->buttons & 0x18) << 1); list->ps2[off + 3] = (list->ps2[off + 3] & 0x0f) | ((list->buttons & 0x18) << 1);
list->bufsiz++; list->bufsiz++;
} else {
list->ps2[off] |= ((list->buttons & 0x10) >> 3) | ((list->buttons & 0x08) >> 1);
} }
if (list->mode == 1) { if (list->mode == 1) {
...@@ -553,6 +584,7 @@ static struct input_handler mousedev_handler = { ...@@ -553,6 +584,7 @@ static struct input_handler mousedev_handler = {
static struct miscdevice psaux_mouse = { static struct miscdevice psaux_mouse = {
PSMOUSE_MINOR, "psaux", &mousedev_fops PSMOUSE_MINOR, "psaux", &mousedev_fops
}; };
static int psaux_registered;
#endif #endif
static int __init mousedev_init(void) static int __init mousedev_init(void)
...@@ -572,7 +604,7 @@ static int __init mousedev_init(void) ...@@ -572,7 +604,7 @@ static int __init mousedev_init(void)
NULL, "mice"); NULL, "mice");
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
if (!(mousedev_mix.misc = !misc_register(&psaux_mouse))) if (!(psaux_registered = !misc_register(&psaux_mouse)))
printk(KERN_WARNING "mice: could not misc_register the device\n"); printk(KERN_WARNING "mice: could not misc_register the device\n");
#endif #endif
...@@ -584,7 +616,7 @@ static int __init mousedev_init(void) ...@@ -584,7 +616,7 @@ static int __init mousedev_init(void)
static void __exit mousedev_exit(void) static void __exit mousedev_exit(void)
{ {
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
if (mousedev_mix.misc) if (psaux_registered)
misc_deregister(&psaux_mouse); misc_deregister(&psaux_mouse);
#endif #endif
devfs_remove("input/mice"); devfs_remove("input/mice");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment