Commit d4032a97 authored by Peter Osterlund's avatar Peter Osterlund Committed by Linus Torvalds

input: Tidy up events reported by a Synaptics pad, add touchpad

       support to mousedev.
parent 9f5bbac5
...@@ -28,6 +28,16 @@ ...@@ -28,6 +28,16 @@
#include "psmouse.h" #include "psmouse.h"
#include "synaptics.h" #include "synaptics.h"
/*
* The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
* section 2.3.2, which says that they should be valid regardless of the
* actual size of the sensor.
*/
#define XMIN_NOMINAL 1472
#define XMAX_NOMINAL 5472
#define YMIN_NOMINAL 1408
#define YMAX_NOMINAL 4448
/***************************************************************************** /*****************************************************************************
* Synaptics communications functions * Synaptics communications functions
****************************************************************************/ ****************************************************************************/
...@@ -316,20 +326,17 @@ static inline void set_abs_params(struct input_dev *dev, int axis, int min, int ...@@ -316,20 +326,17 @@ static inline void set_abs_params(struct input_dev *dev, int axis, int min, int
static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
{ {
/*
* The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
* which says that they should be valid regardless of the actual size of
* the sensor.
*/
set_bit(EV_ABS, dev->evbit); set_bit(EV_ABS, dev->evbit);
set_abs_params(dev, ABS_X, 1472, 5472, 0, 0); set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0);
set_abs_params(dev, ABS_Y, 1408, 4448, 0, 0); set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0);
set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
set_bit(ABS_TOOL_WIDTH, dev->absbit);
set_bit(EV_MSC, dev->evbit);
set_bit(MSC_GESTURE, dev->mscbit);
set_bit(EV_KEY, dev->evbit); set_bit(EV_KEY, dev->evbit);
set_bit(BTN_TOOL_FINGER, dev->keybit);
set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
set_bit(BTN_LEFT, dev->keybit); set_bit(BTN_LEFT, dev->keybit);
set_bit(BTN_RIGHT, dev->keybit); set_bit(BTN_RIGHT, dev->keybit);
set_bit(BTN_FORWARD, dev->keybit); set_bit(BTN_FORWARD, dev->keybit);
...@@ -489,42 +496,49 @@ static void synaptics_process_packet(struct psmouse *psmouse) ...@@ -489,42 +496,49 @@ static void synaptics_process_packet(struct psmouse *psmouse)
struct input_dev *dev = &psmouse->dev; struct input_dev *dev = &psmouse->dev;
struct synaptics_data *priv = psmouse->private; struct synaptics_data *priv = psmouse->private;
struct synaptics_hw_state hw; struct synaptics_hw_state hw;
int num_fingers;
int finger_width;
synaptics_parse_hw_state(psmouse->packet, priv, &hw); synaptics_parse_hw_state(psmouse->packet, priv, &hw);
if (hw.z > 0) { if (hw.z > 0) {
int w_ok = 0; num_fingers = 1;
/* finger_width = 5;
* Use capability bits to decide if the w value is valid.
* If not, set it to 5, which corresponds to a finger of
* normal width.
*/
if (SYN_CAP_EXTENDED(priv->capabilities)) { if (SYN_CAP_EXTENDED(priv->capabilities)) {
switch (hw.w) { switch (hw.w) {
case 0 ... 1: case 0 ... 1:
w_ok = SYN_CAP_MULTIFINGER(priv->capabilities); if (SYN_CAP_MULTIFINGER(priv->capabilities))
num_fingers = hw.w + 2;
break; break;
case 2: case 2:
w_ok = SYN_MODEL_PEN(priv->model_id); if (SYN_MODEL_PEN(priv->model_id))
; /* Nothing, treat a pen as a single finger */
break; break;
case 4 ... 15: case 4 ... 15:
w_ok = SYN_CAP_PALMDETECT(priv->capabilities); if (SYN_CAP_PALMDETECT(priv->capabilities))
finger_width = hw.w;
break; break;
} }
} }
if (!w_ok) } else {
hw.w = 5; num_fingers = 0;
finger_width = 0;
} }
/* Post events */ /* Post events */
input_report_abs(dev, ABS_X, hw.x); if (hw.z > 0) {
input_report_abs(dev, ABS_Y, hw.y); input_report_abs(dev, ABS_X, hw.x);
if (SYN_MODEL_ROT180(priv->model_id))
input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y);
else
input_report_abs(dev, ABS_Y, hw.y);
}
input_report_abs(dev, ABS_PRESSURE, hw.z); input_report_abs(dev, ABS_PRESSURE, hw.z);
if (hw.w != priv->old_w) { input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
input_event(dev, EV_MSC, MSC_GESTURE, hw.w); input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
priv->old_w = hw.w; input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
} input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
input_report_key(dev, BTN_LEFT, hw.left); input_report_key(dev, BTN_LEFT, hw.left);
input_report_key(dev, BTN_RIGHT, hw.right); input_report_key(dev, BTN_RIGHT, hw.right);
......
...@@ -58,6 +58,7 @@ struct mousedev_list { ...@@ -58,6 +58,7 @@ struct mousedev_list {
unsigned long buttons; unsigned long buttons;
unsigned char ready, buffer, bufsiz; unsigned char ready, buffer, bufsiz;
unsigned char mode, imexseq, impsseq; unsigned char mode, imexseq, impsseq;
int finger;
}; };
#define MOUSEDEV_SEQ_LEN 6 #define MOUSEDEV_SEQ_LEN 6
...@@ -73,12 +74,77 @@ static struct mousedev mousedev_mix; ...@@ -73,12 +74,77 @@ static struct mousedev mousedev_mix;
static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X; static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y; static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
static void mousedev_abs_event(struct input_handle *handle, struct mousedev_list *list, unsigned int code, int value)
{
int size;
/* Ignore joysticks */
if (test_bit(BTN_TRIGGER, handle->dev->keybit))
return;
/* Handle touchpad data */
if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit) &&
test_bit(ABS_PRESSURE, handle->dev->absbit) &&
test_bit(ABS_TOOL_WIDTH, handle->dev->absbit)) {
switch (code) {
case ABS_PRESSURE:
if (!list->finger) {
if (value > 30)
list->finger = 1;
} else {
if (value < 25)
list->finger = 0;
else if (list->finger < 3)
list->finger++;
}
break;
case ABS_X:
if (list->finger >= 3) {
list->dx += (value - list->oldx) / 8;
}
list->oldx = value;
break;
case ABS_Y:
if (list->finger >= 3) {
list->dy -= (value - list->oldy) / 8;
}
list->oldy = value;
break;
}
return;
}
/* Handle tablet like devices */
switch (code) {
case ABS_X:
size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
if (size != 0) {
list->dx += (value * xres - list->oldx) / size;
list->oldx += list->dx * size;
} else {
list->dx += value - list->oldx;
list->oldx += list->dx;
}
break;
case ABS_Y:
size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
if (size != 0) {
list->dy -= (value * yres - list->oldy) / size;
list->oldy -= list->dy * size;
} else {
list->dy -= value - list->oldy;
list->oldy -= list->dy;
}
break;
}
}
static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{ {
struct mousedev *mousedevs[3] = { handle->private, &mousedev_mix, NULL }; struct mousedev *mousedevs[3] = { handle->private, &mousedev_mix, NULL };
struct mousedev **mousedev = mousedevs; struct mousedev **mousedev = mousedevs;
struct mousedev_list *list; struct mousedev_list *list;
int index, size, wake; int index, wake;
while (*mousedev) { while (*mousedev) {
...@@ -87,31 +153,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig ...@@ -87,31 +153,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
list_for_each_entry(list, &(*mousedev)->list, node) list_for_each_entry(list, &(*mousedev)->list, node)
switch (type) { switch (type) {
case EV_ABS: case EV_ABS:
if (test_bit(BTN_TRIGGER, handle->dev->keybit)) mousedev_abs_event(handle, list, code, value);
break;
switch (code) {
case ABS_X:
size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
if (size != 0) {
list->dx += (value * xres - list->oldx) / size;
list->oldx += list->dx * size;
} else {
list->dx += value - list->oldx;
list->oldx += list->dx;
}
break;
case ABS_Y:
size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
if (size != 0) {
list->dy -= (value * yres - list->oldy) / size;
list->oldy -= list->dy * size;
} else {
list->dy -= value - list->oldy;
list->oldy -= list->dy;
}
break;
}
break; break;
case EV_REL: case EV_REL:
...@@ -472,6 +514,12 @@ static struct input_device_id mousedev_ids[] = { ...@@ -472,6 +514,12 @@ static struct input_device_id mousedev_ids[] = {
.keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) }, .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
.absbit = { BIT(ABS_X) | BIT(ABS_Y) }, .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
}, /* A tablet like device, at least touch detection, two absolute axes */ }, /* A tablet like device, at least touch detection, two absolute axes */
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
.evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
.keybit = { [LONG(BTN_TOOL_FINGER)] = BIT(BTN_TOOL_FINGER) },
.absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) },
}, /* A touchpad */
{ }, /* Terminating entry */ { }, /* Terminating entry */
}; };
......
...@@ -404,6 +404,8 @@ struct input_absinfo { ...@@ -404,6 +404,8 @@ struct input_absinfo {
#define BTN_TOUCH 0x14a #define BTN_TOUCH 0x14a
#define BTN_STYLUS 0x14b #define BTN_STYLUS 0x14b
#define BTN_STYLUS2 0x14c #define BTN_STYLUS2 0x14c
#define BTN_TOOL_DOUBLETAP 0x14d
#define BTN_TOOL_TRIPLETAP 0x14e
#define BTN_WHEEL 0x150 #define BTN_WHEEL 0x150
#define BTN_GEAR_DOWN 0x150 #define BTN_GEAR_DOWN 0x150
...@@ -521,6 +523,7 @@ struct input_absinfo { ...@@ -521,6 +523,7 @@ struct input_absinfo {
#define ABS_DISTANCE 0x19 #define ABS_DISTANCE 0x19
#define ABS_TILT_X 0x1a #define ABS_TILT_X 0x1a
#define ABS_TILT_Y 0x1b #define ABS_TILT_Y 0x1b
#define ABS_TOOL_WIDTH 0x1c
#define ABS_VOLUME 0x20 #define ABS_VOLUME 0x20
#define ABS_MISC 0x28 #define ABS_MISC 0x28
#define ABS_MAX 0x3f #define ABS_MAX 0x3f
......
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