aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-ntrig.c
diff options
context:
space:
mode:
authorRafi Rubin <rafi@seas.upenn.edu>2010-02-12 21:13:05 -0500
committerJiri Kosina <jkosina@suse.cz>2010-02-16 07:54:23 -0500
commitdbf2b17de505d390b5ecf5b5944fc0c88f6d66fe (patch)
tree26da975937205a3939557cac0cffc735450eb058 /drivers/hid/hid-ntrig.c
parentb0549cf1a35a92edf053d94066e60fb0ed02bb71 (diff)
HID: hid-ntrig: multitouch cleanup and fix
This cleans up the identification of multitouch groups and enables the end of group sync. Taps are now explicitly handled to adjust for the changes in the event stream in multitouch mode. Added triple and quad tap for the benefit of tools that recognize different tap types but do not have full multi touch support. This cleans up the behavior particularly for the latest firmware, which didn't work particularly well with the older version of the driver. In this form, when multitouch is active, both mt and st events will come out of the "N-Trig MultiTouch" device. And when its not st events will come out of "N-Trig Touchscreen". Signed-off-by: Rafi Rubin <rafi@seas.upenn.edu> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-ntrig.c')
-rw-r--r--drivers/hid/hid-ntrig.c116
1 files changed, 94 insertions, 22 deletions
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index 1bda3a4bd71f..f6f882da6267 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -25,8 +25,16 @@
25 EV_KEY, (c)) 25 EV_KEY, (c))
26 26
27struct ntrig_data { 27struct ntrig_data {
28 __s32 x, y, id, w, h; 28 /* Incoming raw values for a single contact */
29 bool reading_a_point, found_contact_id; 29 __u16 x, y, w, h;
30 __u16 id;
31 __u8 confidence;
32
33 bool reading_mt;
34 __u8 first_contact_confidence;
35
36 __u8 mt_footer[4];
37 __u8 mt_foot_count;
30}; 38};
31 39
32/* 40/*
@@ -39,8 +47,8 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
39 struct hid_field *field, struct hid_usage *usage, 47 struct hid_field *field, struct hid_usage *usage,
40 unsigned long **bit, int *max) 48 unsigned long **bit, int *max)
41{ 49{
42 /* No special mappings needed for the pen */ 50 /* No special mappings needed for the pen and single touch */
43 if (field->application == HID_DG_PEN) 51 if (field->physical)
44 return 0; 52 return 0;
45 53
46 switch (usage->hid & HID_USAGE_PAGE) { 54 switch (usage->hid & HID_USAGE_PAGE) {
@@ -66,18 +74,12 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
66 case HID_UP_DIGITIZER: 74 case HID_UP_DIGITIZER:
67 switch (usage->hid) { 75 switch (usage->hid) {
68 /* we do not want to map these for now */ 76 /* we do not want to map these for now */
69 case HID_DG_CONTACTID: /* value is useless */ 77 case HID_DG_CONTACTID: /* Not trustworthy, squelch for now */
70 case HID_DG_INPUTMODE: 78 case HID_DG_INPUTMODE:
71 case HID_DG_DEVICEINDEX: 79 case HID_DG_DEVICEINDEX:
72 case HID_DG_CONTACTCOUNT:
73 case HID_DG_CONTACTMAX: 80 case HID_DG_CONTACTMAX:
74 return -1; 81 return -1;
75 82
76 /* original mapping by Rafi Rubin */
77 case HID_DG_CONFIDENCE:
78 nt_map_key_clear(BTN_TOOL_DOUBLETAP);
79 return 1;
80
81 /* width/height mapped on TouchMajor/TouchMinor/Orientation */ 83 /* width/height mapped on TouchMajor/TouchMinor/Orientation */
82 case HID_DG_WIDTH: 84 case HID_DG_WIDTH:
83 hid_map_usage(hi, usage, bit, max, 85 hid_map_usage(hi, usage, bit, max,
@@ -104,8 +106,8 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
104 struct hid_field *field, struct hid_usage *usage, 106 struct hid_field *field, struct hid_usage *usage,
105 unsigned long **bit, int *max) 107 unsigned long **bit, int *max)
106{ 108{
107 /* No special mappings needed for the pen */ 109 /* No special mappings needed for the pen and single touch */
108 if (field->application == HID_DG_PEN) 110 if (field->physical)
109 return 0; 111 return 0;
110 112
111 if (usage->type == EV_KEY || usage->type == EV_REL 113 if (usage->type == EV_KEY || usage->type == EV_REL
@@ -133,17 +135,24 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
133 135
134 if (hid->claimed & HID_CLAIMED_INPUT) { 136 if (hid->claimed & HID_CLAIMED_INPUT) {
135 switch (usage->hid) { 137 switch (usage->hid) {
138 case 0xff000001:
139 /* Tag indicating the start of a multitouch group */
140 nd->reading_mt = 1;
141 nd->first_contact_confidence = 0;
142 break;
143 case HID_DG_CONFIDENCE:
144 nd->confidence = value;
145 break;
136 case HID_GD_X: 146 case HID_GD_X:
137 nd->x = value; 147 nd->x = value;
138 nd->reading_a_point = 1; 148 /* Clear the contact footer */
149 nd->mt_foot_count = 0;
139 break; 150 break;
140 case HID_GD_Y: 151 case HID_GD_Y:
141 nd->y = value; 152 nd->y = value;
142 break; 153 break;
143 case HID_DG_CONTACTID: 154 case HID_DG_CONTACTID:
144 nd->id = value; 155 nd->id = value;
145 /* we receive this only when in multitouch mode */
146 nd->found_contact_id = 1;
147 break; 156 break;
148 case HID_DG_WIDTH: 157 case HID_DG_WIDTH:
149 nd->w = value; 158 nd->w = value;
@@ -155,7 +164,7 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
155 * report received in a finger event. We want 164 * report received in a finger event. We want
156 * to emit a normal (X, Y) position 165 * to emit a normal (X, Y) position
157 */ 166 */
158 if (!nd->found_contact_id) { 167 if (!nd->reading_mt) {
159 input_event(input, EV_ABS, ABS_X, nd->x); 168 input_event(input, EV_ABS, ABS_X, nd->x);
160 input_event(input, EV_ABS, ABS_Y, nd->y); 169 input_event(input, EV_ABS, ABS_Y, nd->y);
161 } 170 }
@@ -167,10 +176,34 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
167 * this usage tells if the contact point is real 176 * this usage tells if the contact point is real
168 * or a placeholder 177 * or a placeholder
169 */ 178 */
170 if (!nd->reading_a_point || value != 1) 179
180 /* Shouldn't get more than 4 footer packets, so skip */
181 if (nd->mt_foot_count >= 4)
182 break;
183
184 nd->mt_footer[nd->mt_foot_count++] = value;
185
186 /* if the footer isn't complete break */
187 if (nd->mt_foot_count != 4)
188 break;
189
190 /* Pen activity signal, trigger end of touch. */
191 if (nd->mt_footer[2]) {
192 nd->confidence = 0;
193 break;
194 }
195
196 /* If the contact was invalid */
197 if (!(nd->confidence && nd->mt_footer[0])
198 || nd->w <= 250
199 || nd->h <= 190) {
200 nd->confidence = 0;
171 break; 201 break;
202 }
203
172 /* emit a normal (X, Y) for the first point only */ 204 /* emit a normal (X, Y) for the first point only */
173 if (nd->id == 0) { 205 if (nd->id == 0) {
206 nd->first_contact_confidence = nd->confidence;
174 input_event(input, EV_ABS, ABS_X, nd->x); 207 input_event(input, EV_ABS, ABS_X, nd->x);
175 input_event(input, EV_ABS, ABS_Y, nd->y); 208 input_event(input, EV_ABS, ABS_Y, nd->y);
176 } 209 }
@@ -192,8 +225,39 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
192 ABS_MT_TOUCH_MINOR, nd->w); 225 ABS_MT_TOUCH_MINOR, nd->w);
193 } 226 }
194 input_mt_sync(field->hidinput->input); 227 input_mt_sync(field->hidinput->input);
195 nd->reading_a_point = 0; 228 break;
196 nd->found_contact_id = 0; 229
230 case HID_DG_CONTACTCOUNT: /* End of a multitouch group */
231 if (!nd->reading_mt)
232 break;
233
234 nd->reading_mt = 0;
235
236 if (nd->first_contact_confidence) {
237 switch (value) {
238 case 0: /* for single touch devices */
239 case 1:
240 input_report_key(input,
241 BTN_TOOL_DOUBLETAP, 1);
242 break;
243 case 2:
244 input_report_key(input,
245 BTN_TOOL_TRIPLETAP, 1);
246 break;
247 case 3:
248 default:
249 input_report_key(input,
250 BTN_TOOL_QUADTAP, 1);
251 }
252 input_report_key(input, BTN_TOUCH, 1);
253 } else {
254 input_report_key(input,
255 BTN_TOOL_DOUBLETAP, 0);
256 input_report_key(input,
257 BTN_TOOL_TRIPLETAP, 0);
258 input_report_key(input,
259 BTN_TOOL_QUADTAP, 0);
260 }
197 break; 261 break;
198 262
199 default: 263 default:
@@ -224,8 +288,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
224 dev_err(&hdev->dev, "cannot allocate N-Trig data\n"); 288 dev_err(&hdev->dev, "cannot allocate N-Trig data\n");
225 return -ENOMEM; 289 return -ENOMEM;
226 } 290 }
227 nd->reading_a_point = 0; 291
228 nd->found_contact_id = 0; 292 nd->reading_mt = 0;
229 hid_set_drvdata(hdev, nd); 293 hid_set_drvdata(hdev, nd);
230 294
231 ret = hid_parse(hdev); 295 ret = hid_parse(hdev);
@@ -248,6 +312,14 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
248 input->name = "N-Trig Pen"; 312 input->name = "N-Trig Pen";
249 break; 313 break;
250 case HID_DG_TOUCHSCREEN: 314 case HID_DG_TOUCHSCREEN:
315 __clear_bit(BTN_TOOL_PEN, input->keybit);
316 /*
317 * A little something special to enable
318 * two and three finger taps.
319 */
320 __set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
321 __set_bit(BTN_TOOL_TRIPLETAP, input->keybit);
322 __set_bit(BTN_TOOL_QUADTAP, input->keybit);
251 /* 323 /*
252 * The physical touchscreen (single touch) 324 * The physical touchscreen (single touch)
253 * input has a value for physical, whereas 325 * input has a value for physical, whereas