aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/evdev.c12
-rw-r--r--drivers/input/mouse/synaptics.c28
-rw-r--r--drivers/input/mouse/synaptics.h2
-rw-r--r--include/linux/input.h2
4 files changed, 41 insertions, 3 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index c238116400b3..114efd8dc8f5 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 f3e4f7b0240d..19984bf06cad 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 02aa4cf7bc77..302382151752 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 */
diff --git a/include/linux/input.h b/include/linux/input.h
index 6fed4f6a9c9e..8b3bc3e0d146 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -53,6 +53,7 @@ struct input_absinfo {
53 __s32 maximum; 53 __s32 maximum;
54 __s32 fuzz; 54 __s32 fuzz;
55 __s32 flat; 55 __s32 flat;
56 __s32 resolution;
56}; 57};
57 58
58#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */ 59#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
@@ -1109,6 +1110,7 @@ struct input_dev {
1109 int absmin[ABS_MAX + 1]; 1110 int absmin[ABS_MAX + 1];
1110 int absfuzz[ABS_MAX + 1]; 1111 int absfuzz[ABS_MAX + 1];
1111 int absflat[ABS_MAX + 1]; 1112 int absflat[ABS_MAX + 1];
1113 int absres[ABS_MAX + 1];
1112 1114
1113 int (*open)(struct input_dev *dev); 1115 int (*open)(struct input_dev *dev);
1114 void (*close)(struct input_dev *dev); 1116 void (*close)(struct input_dev *dev);