diff options
| -rw-r--r-- | drivers/hid/hid-ntrig.c | 220 |
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 | ||
| 27 | static unsigned int min_width; | ||
| 28 | static unsigned int min_height; | ||
| 29 | static unsigned int activate_slack = 1; | ||
| 30 | static unsigned int deactivate_slack = 4; | ||
| 31 | static unsigned int activation_width = 64; | ||
| 32 | static unsigned int activation_height = 32; | ||
| 33 | |||
| 27 | struct ntrig_data { | 34 | struct 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); |
