aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTero Saarni <tero.saarni@gmail.com>2009-06-11 02:27:24 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-06-20 01:55:17 -0400
commitec20a022aa24fc63d3ab59584cb1e5aa9a21d46c (patch)
tree671086529e62fcb541fb03422010d1eeae09b00a /drivers
parentd7ed5d883c09c5474f842dcb148515dfaef2a567 (diff)
Input: synaptics - add support for reporting x/y resolution
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/evdev.c12
-rw-r--r--drivers/input/mouse/synaptics.c28
-rw-r--r--drivers/input/mouse/synaptics.h2
3 files changed, 39 insertions, 3 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index c238116400b..114efd8dc8f 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -626,8 +626,11 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
626 abs.maximum = dev->absmax[t]; 626 abs.maximum = dev->absmax[t];
627 abs.fuzz = dev->absfuzz[t]; 627 abs.fuzz = dev->absfuzz[t];
628 abs.flat = dev->absflat[t]; 628 abs.flat = dev->absflat[t];
629 abs.resolution = dev->absres[t];
629 630
630 if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) 631 if (copy_to_user(p, &abs, min_t(size_t,
632 _IOC_SIZE(cmd),
633 sizeof(struct input_absinfo))))
631 return -EFAULT; 634 return -EFAULT;
632 635
633 return 0; 636 return 0;
@@ -654,8 +657,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
654 657
655 t = _IOC_NR(cmd) & ABS_MAX; 658 t = _IOC_NR(cmd) & ABS_MAX;
656 659
657 if (copy_from_user(&abs, p, 660 if (copy_from_user(&abs, p, min_t(size_t,
658 sizeof(struct input_absinfo))) 661 _IOC_SIZE(cmd),
662 sizeof(struct input_absinfo))))
659 return -EFAULT; 663 return -EFAULT;
660 664
661 /* 665 /*
@@ -670,6 +674,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
670 dev->absmax[t] = abs.maximum; 674 dev->absmax[t] = abs.maximum;
671 dev->absfuzz[t] = abs.fuzz; 675 dev->absfuzz[t] = abs.fuzz;
672 dev->absflat[t] = abs.flat; 676 dev->absflat[t] = abs.flat;
677 dev->absres[t] = _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ?
678 0 : abs.resolution;
673 679
674 spin_unlock_irq(&dev->event_lock); 680 spin_unlock_irq(&dev->event_lock);
675 681
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index f3e4f7b0240..19984bf06ca 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -180,6 +180,29 @@ static int synaptics_identify(struct psmouse *psmouse)
180 return -1; 180 return -1;
181} 181}
182 182
183/*
184 * Read touchpad resolution
185 * Resolution is left zero if touchpad does not support the query
186 */
187static int synaptics_resolution(struct psmouse *psmouse)
188{
189 struct synaptics_data *priv = psmouse->private;
190 unsigned char res[3];
191
192 if (SYN_ID_MAJOR(priv->identity) < 4)
193 return 0;
194
195 if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res))
196 return 0;
197
198 if ((res[0] != 0) && (res[1] & 0x80) && (res[2] != 0)) {
199 priv->x_res = res[0]; /* x resolution in units/mm */
200 priv->y_res = res[2]; /* y resolution in units/mm */
201 }
202
203 return 0;
204}
205
183static int synaptics_query_hardware(struct psmouse *psmouse) 206static int synaptics_query_hardware(struct psmouse *psmouse)
184{ 207{
185 if (synaptics_identify(psmouse)) 208 if (synaptics_identify(psmouse))
@@ -188,6 +211,8 @@ static int synaptics_query_hardware(struct psmouse *psmouse)
188 return -1; 211 return -1;
189 if (synaptics_capability(psmouse)) 212 if (synaptics_capability(psmouse))
190 return -1; 213 return -1;
214 if (synaptics_resolution(psmouse))
215 return -1;
191 216
192 return 0; 217 return 0;
193} 218}
@@ -563,6 +588,9 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
563 clear_bit(EV_REL, dev->evbit); 588 clear_bit(EV_REL, dev->evbit);
564 clear_bit(REL_X, dev->relbit); 589 clear_bit(REL_X, dev->relbit);
565 clear_bit(REL_Y, dev->relbit); 590 clear_bit(REL_Y, dev->relbit);
591
592 dev->absres[ABS_X] = priv->x_res;
593 dev->absres[ABS_Y] = priv->y_res;
566} 594}
567 595
568static void synaptics_disconnect(struct psmouse *psmouse) 596static void synaptics_disconnect(struct psmouse *psmouse)
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 02aa4cf7bc7..30238215175 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -97,6 +97,8 @@ struct synaptics_data {
97 unsigned long int capabilities; /* Capabilities */ 97 unsigned long int capabilities; /* Capabilities */
98 unsigned long int ext_cap; /* Extended Capabilities */ 98 unsigned long int ext_cap; /* Extended Capabilities */
99 unsigned long int identity; /* Identification */ 99 unsigned long int identity; /* Identification */
100 int x_res; /* X resolution in units/mm */
101 int y_res; /* Y resolution in units/mm */
100 102
101 unsigned char pkt_type; /* packet type - old, new, etc */ 103 unsigned char pkt_type; /* packet type - old, new, etc */
102 unsigned char mode; /* current mode byte */ 104 unsigned char mode; /* current mode byte */