Skip to content

Commit

Permalink
Input: synaptics - add support for reporting x/y resolution
Browse files Browse the repository at this point in the history
Synaptics uses anisotropic coordinate system.  On some wide touchpads
vertical resolution can be twice as high as horizontal which causes
unequal sensitivity on x/y directions.  Add support for reading the
resolution with EVIOCGABS ioctl.

Signed-off-by: Tero Saarni <tero.saarni@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
  • Loading branch information
Tero Saarni authored and Dmitry Torokhov committed Jun 20, 2009
1 parent d7ed5d8 commit ec20a02
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 3 deletions.
12 changes: 9 additions & 3 deletions drivers/input/evdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,8 +626,11 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
abs.maximum = dev->absmax[t];
abs.fuzz = dev->absfuzz[t];
abs.flat = dev->absflat[t];
abs.resolution = dev->absres[t];

if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
if (copy_to_user(p, &abs, min_t(size_t,
_IOC_SIZE(cmd),
sizeof(struct input_absinfo))))
return -EFAULT;

return 0;
Expand All @@ -654,8 +657,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,

t = _IOC_NR(cmd) & ABS_MAX;

if (copy_from_user(&abs, p,
sizeof(struct input_absinfo)))
if (copy_from_user(&abs, p, min_t(size_t,
_IOC_SIZE(cmd),
sizeof(struct input_absinfo))))
return -EFAULT;

/*
Expand All @@ -670,6 +674,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
dev->absmax[t] = abs.maximum;
dev->absfuzz[t] = abs.fuzz;
dev->absflat[t] = abs.flat;
dev->absres[t] = _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ?
0 : abs.resolution;

spin_unlock_irq(&dev->event_lock);

Expand Down
28 changes: 28 additions & 0 deletions drivers/input/mouse/synaptics.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,29 @@ static int synaptics_identify(struct psmouse *psmouse)
return -1;
}

/*
* Read touchpad resolution
* Resolution is left zero if touchpad does not support the query
*/
static int synaptics_resolution(struct psmouse *psmouse)
{
struct synaptics_data *priv = psmouse->private;
unsigned char res[3];

if (SYN_ID_MAJOR(priv->identity) < 4)
return 0;

if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res))
return 0;

if ((res[0] != 0) && (res[1] & 0x80) && (res[2] != 0)) {
priv->x_res = res[0]; /* x resolution in units/mm */
priv->y_res = res[2]; /* y resolution in units/mm */
}

return 0;
}

static int synaptics_query_hardware(struct psmouse *psmouse)
{
if (synaptics_identify(psmouse))
Expand All @@ -188,6 +211,8 @@ static int synaptics_query_hardware(struct psmouse *psmouse)
return -1;
if (synaptics_capability(psmouse))
return -1;
if (synaptics_resolution(psmouse))
return -1;

return 0;
}
Expand Down Expand Up @@ -563,6 +588,9 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
clear_bit(EV_REL, dev->evbit);
clear_bit(REL_X, dev->relbit);
clear_bit(REL_Y, dev->relbit);

dev->absres[ABS_X] = priv->x_res;
dev->absres[ABS_Y] = priv->y_res;
}

static void synaptics_disconnect(struct psmouse *psmouse)
Expand Down
2 changes: 2 additions & 0 deletions drivers/input/mouse/synaptics.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ struct synaptics_data {
unsigned long int capabilities; /* Capabilities */
unsigned long int ext_cap; /* Extended Capabilities */
unsigned long int identity; /* Identification */
int x_res; /* X resolution in units/mm */
int y_res; /* Y resolution in units/mm */

unsigned char pkt_type; /* packet type - old, new, etc */
unsigned char mode; /* current mode byte */
Expand Down
2 changes: 2 additions & 0 deletions include/linux/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ struct input_absinfo {
__s32 maximum;
__s32 fuzz;
__s32 flat;
__s32 resolution;
};

#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
Expand Down Expand Up @@ -1109,6 +1110,7 @@ struct input_dev {
int absmin[ABS_MAX + 1];
int absfuzz[ABS_MAX + 1];
int absflat[ABS_MAX + 1];
int absres[ABS_MAX + 1];

int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
Expand Down

0 comments on commit ec20a02

Please sign in to comment.