aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-3m-pct.c
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-09-21 16:12:12 -0400
committerJiri Kosina <jkosina@suse.cz>2010-09-21 17:22:34 -0400
commit1f01a1fe167f588c8b6b449fde2f5427ca940423 (patch)
treeda2eaa5f1fdf7a7da0c4347de052dbd8bf2ee72f /drivers/hid/hid-3m-pct.c
parent46c4ba012c9e70b26e4c2072245e3922cca3ef31 (diff)
HID: 3m: Convert to MT slots
The Microtouch controller is capable of doing finger tracking on up to 60 fingers. To reduce bandwidth and cpu usage, convert the driver to use the MT slots protocol. On Stephane's suggestion, also insert the additional copyright lines. Signed-off-by: Henrik Rydberg <rydberg@euromail.se> Acked-by: Stephane Chatty <chatty@enac.fr> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-3m-pct.c')
-rw-r--r--drivers/hid/hid-3m-pct.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c
index d2fda7848f59..3c380e1c5b60 100644
--- a/drivers/hid/hid-3m-pct.c
+++ b/drivers/hid/hid-3m-pct.c
@@ -2,6 +2,8 @@
2 * HID driver for 3M PCT multitouch panels 2 * HID driver for 3M PCT multitouch panels
3 * 3 *
4 * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> 4 * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
5 * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
6 * Copyright (c) 2010 Canonical, Ltd.
5 * 7 *
6 */ 8 */
7 9
@@ -25,16 +27,24 @@ MODULE_LICENSE("GPL");
25#include "hid-ids.h" 27#include "hid-ids.h"
26 28
27#define MAX_SLOTS 60 29#define MAX_SLOTS 60
28#define MAX_TRKID 59 30#define MAX_TRKID USHRT_MAX
31#define MAX_EVENTS 360
32
33/* estimated signal-to-noise ratios */
34#define SN_MOVE 2048
35#define SN_WIDTH 128
29 36
30struct mmm_finger { 37struct mmm_finger {
31 __s32 x, y, w, h; 38 __s32 x, y, w, h;
39 __u16 id;
32 __u8 rank; 40 __u8 rank;
41 bool prev_touch;
33 bool touch, valid; 42 bool touch, valid;
34}; 43};
35 44
36struct mmm_data { 45struct mmm_data {
37 struct mmm_finger f[MAX_SLOTS]; 46 struct mmm_finger f[MAX_SLOTS];
47 __u16 id;
38 __u8 curid, num; 48 __u8 curid, num;
39 __u8 nexp, nreal; 49 __u8 nexp, nreal;
40 bool touch, valid; 50 bool touch, valid;
@@ -44,6 +54,10 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
44 struct hid_field *field, struct hid_usage *usage, 54 struct hid_field *field, struct hid_usage *usage,
45 unsigned long **bit, int *max) 55 unsigned long **bit, int *max)
46{ 56{
57 int f1 = field->logical_minimum;
58 int f2 = field->logical_maximum;
59 int df = f2 - f1;
60
47 switch (usage->hid & HID_USAGE_PAGE) { 61 switch (usage->hid & HID_USAGE_PAGE) {
48 62
49 case HID_UP_BUTTON: 63 case HID_UP_BUTTON:
@@ -54,18 +68,20 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
54 case HID_GD_X: 68 case HID_GD_X:
55 hid_map_usage(hi, usage, bit, max, 69 hid_map_usage(hi, usage, bit, max,
56 EV_ABS, ABS_MT_POSITION_X); 70 EV_ABS, ABS_MT_POSITION_X);
71 input_set_abs_params(hi->input, ABS_MT_POSITION_X,
72 f1, f2, df / SN_MOVE, 0);
57 /* touchscreen emulation */ 73 /* touchscreen emulation */
58 input_set_abs_params(hi->input, ABS_X, 74 input_set_abs_params(hi->input, ABS_X,
59 field->logical_minimum, 75 f1, f2, df / SN_MOVE, 0);
60 field->logical_maximum, 0, 0);
61 return 1; 76 return 1;
62 case HID_GD_Y: 77 case HID_GD_Y:
63 hid_map_usage(hi, usage, bit, max, 78 hid_map_usage(hi, usage, bit, max,
64 EV_ABS, ABS_MT_POSITION_Y); 79 EV_ABS, ABS_MT_POSITION_Y);
80 input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
81 f1, f2, df / SN_MOVE, 0);
65 /* touchscreen emulation */ 82 /* touchscreen emulation */
66 input_set_abs_params(hi->input, ABS_Y, 83 input_set_abs_params(hi->input, ABS_Y,
67 field->logical_minimum, 84 f1, f2, df / SN_MOVE, 0);
68 field->logical_maximum, 0, 0);
69 return 1; 85 return 1;
70 } 86 }
71 return 0; 87 return 0;
@@ -85,14 +101,19 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
85 case HID_DG_TIPSWITCH: 101 case HID_DG_TIPSWITCH:
86 /* touchscreen emulation */ 102 /* touchscreen emulation */
87 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); 103 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
104 input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
88 return 1; 105 return 1;
89 case HID_DG_WIDTH: 106 case HID_DG_WIDTH:
90 hid_map_usage(hi, usage, bit, max, 107 hid_map_usage(hi, usage, bit, max,
91 EV_ABS, ABS_MT_TOUCH_MAJOR); 108 EV_ABS, ABS_MT_TOUCH_MAJOR);
109 input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR,
110 f1, f2, df / SN_WIDTH, 0);
92 return 1; 111 return 1;
93 case HID_DG_HEIGHT: 112 case HID_DG_HEIGHT:
94 hid_map_usage(hi, usage, bit, max, 113 hid_map_usage(hi, usage, bit, max,
95 EV_ABS, ABS_MT_TOUCH_MINOR); 114 EV_ABS, ABS_MT_TOUCH_MINOR);
115 input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR,
116 f1, f2, df / SN_WIDTH, 0);
96 input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 117 input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
97 0, 1, 0, 0); 118 0, 1, 0, 0);
98 return 1; 119 return 1;
@@ -100,6 +121,11 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
100 field->logical_maximum = MAX_TRKID; 121 field->logical_maximum = MAX_TRKID;
101 hid_map_usage(hi, usage, bit, max, 122 hid_map_usage(hi, usage, bit, max,
102 EV_ABS, ABS_MT_TRACKING_ID); 123 EV_ABS, ABS_MT_TRACKING_ID);
124 input_set_abs_params(hi->input, ABS_MT_TRACKING_ID,
125 0, MAX_TRKID, 0, 0);
126 if (!hi->input->mt)
127 input_mt_create_slots(hi->input, MAX_SLOTS);
128 input_set_events_per_packet(hi->input, MAX_EVENTS);
103 return 1; 129 return 1;
104 } 130 }
105 /* let hid-input decide for the others */ 131 /* let hid-input decide for the others */
@@ -117,10 +143,10 @@ static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi,
117 struct hid_field *field, struct hid_usage *usage, 143 struct hid_field *field, struct hid_usage *usage,
118 unsigned long **bit, int *max) 144 unsigned long **bit, int *max)
119{ 145{
146 /* tell hid-input to skip setup of these event types */
120 if (usage->type == EV_KEY || usage->type == EV_ABS) 147 if (usage->type == EV_KEY || usage->type == EV_ABS)
121 clear_bit(usage->code, *bit); 148 set_bit(usage->type, hi->input->evbit);
122 149 return -1;
123 return 0;
124} 150}
125 151
126/* 152/*
@@ -141,10 +167,15 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
141 struct mmm_finger *f = &md->f[i]; 167 struct mmm_finger *f = &md->f[i];
142 if (!f->valid) { 168 if (!f->valid) {
143 /* this finger is just placeholder data, ignore */ 169 /* this finger is just placeholder data, ignore */
144 } else if (f->touch) { 170 continue;
171 }
172 input_mt_slot(input, i);
173 if (f->touch) {
145 /* this finger is on the screen */ 174 /* this finger is on the screen */
146 int wide = (f->w > f->h); 175 int wide = (f->w > f->h);
147 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, i); 176 if (!f->prev_touch)
177 f->id = md->id++;
178 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id);
148 input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); 179 input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
149 input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); 180 input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
150 input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); 181 input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
@@ -152,7 +183,6 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
152 wide ? f->w : f->h); 183 wide ? f->w : f->h);
153 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, 184 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR,
154 wide ? f->h : f->w); 185 wide ? f->h : f->w);
155 input_mt_sync(input);
156 /* 186 /*
157 * touchscreen emulation: maintain the age rank 187 * touchscreen emulation: maintain the age rank
158 * of this finger, decide if we have a press 188 * of this finger, decide if we have a press
@@ -181,7 +211,9 @@ static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
181 --(md->num); 211 --(md->num);
182 if (md->num == 0) 212 if (md->num == 0)
183 released = true; 213 released = true;
214 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1);
184 } 215 }
216 f->prev_touch = f->touch;
185 f->valid = 0; 217 f->valid = 0;
186 } 218 }
187 219