aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-ntrig.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-ntrig.c')
-rw-r--r--drivers/hid/hid-ntrig.c220
1 files changed, 211 insertions, 9 deletions
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index 4777bbfa1cc2..227d01527c6a 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -24,6 +24,13 @@
24 24
25#define NTRIG_DUPLICATE_USAGES 0x001 25#define NTRIG_DUPLICATE_USAGES 0x001
26 26
27static unsigned int min_width;
28static unsigned int min_height;
29static unsigned int activate_slack = 1;
30static unsigned int deactivate_slack = 4;
31static unsigned int activation_width = 64;
32static unsigned int activation_height = 32;
33
27struct ntrig_data { 34struct ntrig_data {
28 /* Incoming raw values for a single contact */ 35 /* Incoming raw values for a single contact */
29 __u16 x, y, w, h; 36 __u16 x, y, w, h;
@@ -37,6 +44,28 @@ struct ntrig_data {
37 44
38 __u8 mt_footer[4]; 45 __u8 mt_footer[4];
39 __u8 mt_foot_count; 46 __u8 mt_foot_count;
47
48 /* The current activation state. */
49 __s8 act_state;
50
51 /* Empty frames to ignore before recognizing the end of activity */
52 __s8 deactivate_slack;
53
54 /* Frames to ignore before acknowledging the start of activity */
55 __s8 activate_slack;
56
57 /* Minimum size contact to accept */
58 __u16 min_width;
59 __u16 min_height;
60
61 /* Threshold to override activation slack */
62 __u16 activation_width;
63 __u16 activation_height;
64
65 __u16 sensor_logical_width;
66 __u16 sensor_logical_height;
67 __u16 sensor_physical_width;
68 __u16 sensor_physical_height;
40}; 69};
41 70
42/* 71/*
@@ -49,6 +78,8 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
49 struct hid_field *field, struct hid_usage *usage, 78 struct hid_field *field, struct hid_usage *usage,
50 unsigned long **bit, int *max) 79 unsigned long **bit, int *max)
51{ 80{
81 struct ntrig_data *nd = hid_get_drvdata(hdev);
82
52 /* No special mappings needed for the pen and single touch */ 83 /* No special mappings needed for the pen and single touch */
53 if (field->physical) 84 if (field->physical)
54 return 0; 85 return 0;
@@ -62,6 +93,21 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
62 input_set_abs_params(hi->input, ABS_X, 93 input_set_abs_params(hi->input, ABS_X,
63 field->logical_minimum, 94 field->logical_minimum,
64 field->logical_maximum, 0, 0); 95 field->logical_maximum, 0, 0);
96
97 if (!nd->sensor_logical_width) {
98 nd->sensor_logical_width =
99 field->logical_maximum -
100 field->logical_minimum;
101 nd->sensor_physical_width =
102 field->physical_maximum -
103 field->physical_minimum;
104 nd->activation_width = activation_width *
105 nd->sensor_logical_width /
106 nd->sensor_physical_width;
107 nd->min_width = min_width *
108 nd->sensor_logical_width /
109 nd->sensor_physical_width;
110 }
65 return 1; 111 return 1;
66 case HID_GD_Y: 112 case HID_GD_Y:
67 hid_map_usage(hi, usage, bit, max, 113 hid_map_usage(hi, usage, bit, max,
@@ -69,6 +115,21 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
69 input_set_abs_params(hi->input, ABS_Y, 115 input_set_abs_params(hi->input, ABS_Y,
70 field->logical_minimum, 116 field->logical_minimum,
71 field->logical_maximum, 0, 0); 117 field->logical_maximum, 0, 0);
118
119 if (!nd->sensor_logical_height) {
120 nd->sensor_logical_height =
121 field->logical_maximum -
122 field->logical_minimum;
123 nd->sensor_physical_height =
124 field->physical_maximum -
125 field->physical_minimum;
126 nd->activation_height = activation_height *
127 nd->sensor_logical_height /
128 nd->sensor_physical_height;
129 nd->min_height = min_height *
130 nd->sensor_logical_height /
131 nd->sensor_physical_height;
132 }
72 return 1; 133 return 1;
73 } 134 }
74 return 0; 135 return 0;
@@ -201,20 +262,68 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
201 if (nd->mt_foot_count != 4) 262 if (nd->mt_foot_count != 4)
202 break; 263 break;
203 264
204 /* Pen activity signal, trigger end of touch. */ 265 /* Pen activity signal. */
205 if (nd->mt_footer[2]) { 266 if (nd->mt_footer[2]) {
267 /*
268 * When the pen deactivates touch, we see a
269 * bogus frame with ContactCount > 0.
270 * We can
271 * save a bit of work by ensuring act_state < 0
272 * even if deactivation slack is turned off.
273 */
274 nd->act_state = deactivate_slack - 1;
206 nd->confidence = 0; 275 nd->confidence = 0;
207 break; 276 break;
208 } 277 }
209 278
210 /* If the contact was invalid */ 279 /*
211 if (!(nd->confidence && nd->mt_footer[0]) 280 * The first footer value indicates the presence of a
212 || nd->w <= 250 281 * finger.
213 || nd->h <= 190) { 282 */
214 nd->confidence = 0; 283 if (nd->mt_footer[0]) {
284 /*
285 * We do not want to process contacts under
286 * the size threshold, but do not want to
287 * ignore them for activation state
288 */
289 if (nd->w < nd->min_width ||
290 nd->h < nd->min_height)
291 nd->confidence = 0;
292 } else
215 break; 293 break;
294
295 if (nd->act_state > 0) {
296 /*
297 * Contact meets the activation size threshold
298 */
299 if (nd->w >= nd->activation_width &&
300 nd->h >= nd->activation_height) {
301 if (nd->id)
302 /*
303 * first contact, activate now
304 */
305 nd->act_state = 0;
306 else {
307 /*
308 * avoid corrupting this frame
309 * but ensure next frame will
310 * be active
311 */
312 nd->act_state = 1;
313 break;
314 }
315 } else
316 /*
317 * Defer adjusting the activation state
318 * until the end of the frame.
319 */
320 break;
216 } 321 }
217 322
323 /* Discarding this contact */
324 if (!nd->confidence)
325 break;
326
218 /* emit a normal (X, Y) for the first point only */ 327 /* emit a normal (X, Y) for the first point only */
219 if (nd->id == 0) { 328 if (nd->id == 0) {
220 /* 329 /*
@@ -227,8 +336,15 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
227 input_event(input, EV_ABS, ABS_X, nd->x); 336 input_event(input, EV_ABS, ABS_X, nd->x);
228 input_event(input, EV_ABS, ABS_Y, nd->y); 337 input_event(input, EV_ABS, ABS_Y, nd->y);
229 } 338 }
339
340 /* Emit MT events */
230 input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x); 341 input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x);
231 input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y); 342 input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y);
343
344 /*
345 * Translate from height and width to size
346 * and orientation.
347 */
232 if (nd->w > nd->h) { 348 if (nd->w > nd->h) {
233 input_event(input, EV_ABS, 349 input_event(input, EV_ABS,
234 ABS_MT_ORIENTATION, 1); 350 ABS_MT_ORIENTATION, 1);
@@ -248,12 +364,88 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
248 break; 364 break;
249 365
250 case HID_DG_CONTACTCOUNT: /* End of a multitouch group */ 366 case HID_DG_CONTACTCOUNT: /* End of a multitouch group */
251 if (!nd->reading_mt) 367 if (!nd->reading_mt) /* Just to be sure */
252 break; 368 break;
253 369
254 nd->reading_mt = 0; 370 nd->reading_mt = 0;
255 371
256 if (nd->first_contact_touch) { 372
373 /*
374 * Activation state machine logic:
375 *
376 * Fundamental states:
377 * state > 0: Inactive
378 * state <= 0: Active
379 * state < -deactivate_slack:
380 * Pen termination of touch
381 *
382 * Specific values of interest
383 * state == activate_slack
384 * no valid input since the last reset
385 *
386 * state == 0
387 * general operational state
388 *
389 * state == -deactivate_slack
390 * read sufficient empty frames to accept
391 * the end of input and reset
392 */
393
394 if (nd->act_state > 0) { /* Currently inactive */
395 if (value)
396 /*
397 * Consider each live contact as
398 * evidence of intentional activity.
399 */
400 nd->act_state = (nd->act_state > value)
401 ? nd->act_state - value
402 : 0;
403 else
404 /*
405 * Empty frame before we hit the
406 * activity threshold, reset.
407 */
408 nd->act_state = nd->activate_slack;
409
410 /*
411 * Entered this block inactive and no
412 * coordinates sent this frame, so hold off
413 * on button state.
414 */
415 break;
416 } else { /* Currently active */
417 if (value && nd->act_state >=
418 nd->deactivate_slack)
419 /*
420 * Live point: clear accumulated
421 * deactivation count.
422 */
423 nd->act_state = 0;
424 else if (nd->act_state <= nd->deactivate_slack)
425 /*
426 * We've consumed the deactivation
427 * slack, time to deactivate and reset.
428 */
429 nd->act_state =
430 nd->activate_slack;
431 else { /* Move towards deactivation */
432 nd->act_state--;
433 break;
434 }
435 }
436
437 if (nd->first_contact_touch && nd->act_state <= 0) {
438 /*
439 * Check to see if we're ready to start
440 * emitting touch events.
441 *
442 * Note: activation slack will decrease over
443 * the course of the frame, and it will be
444 * inconsistent from the start to the end of
445 * the frame. However if the frame starts
446 * with slack, first_contact_touch will still
447 * be 0 and we will not get to this point.
448 */
257 input_report_key(input, BTN_TOOL_DOUBLETAP, 1); 449 input_report_key(input, BTN_TOOL_DOUBLETAP, 1);
258 input_report_key(input, BTN_TOUCH, 1); 450 input_report_key(input, BTN_TOUCH, 1);
259 } else { 451 } else {
@@ -263,7 +455,7 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
263 break; 455 break;
264 456
265 default: 457 default:
266 /* fallback to the generic hidinput handling */ 458 /* fall-back to the generic hidinput handling */
267 return 0; 459 return 0;
268 } 460 }
269 } 461 }
@@ -293,6 +485,16 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
293 } 485 }
294 486
295 nd->reading_mt = 0; 487 nd->reading_mt = 0;
488 nd->min_width = 0;
489 nd->min_height = 0;
490 nd->activate_slack = activate_slack;
491 nd->act_state = activate_slack;
492 nd->deactivate_slack = -deactivate_slack;
493 nd->sensor_logical_width = 0;
494 nd->sensor_logical_height = 0;
495 nd->sensor_physical_width = 0;
496 nd->sensor_physical_height = 0;
497
296 hid_set_drvdata(hdev, nd); 498 hid_set_drvdata(hdev, nd);
297 499
298 ret = hid_parse(hdev); 500 ret = hid_parse(hdev);