diff options
| author | Henrik Rydberg <rydberg@euromail.se> | 2012-09-15 10:40:04 -0400 |
|---|---|---|
| committer | Henrik Rydberg <rydberg@euromail.se> | 2012-09-19 13:50:22 -0400 |
| commit | 51c80b74002f86477d691ed7c8ac479dcfa6271c (patch) | |
| tree | c318aa1bd6312c7338c9f560f79eb397bd8db6cc | |
| parent | 0e7269669d4cd14a49b4e5c708b8be0ba11504f7 (diff) | |
Input: bcm5974 - Convert to MT-B
Use of the in-kernel tracking code to convert the driver to MT-B.
With ten fingers on the pad, the in-kernel tracking adds approximately
25 us to the maximum irqsoff latency. Under normal workloads, however,
the tracking has no measurable effect.
Tested-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
| -rw-r--r-- | drivers/input/mouse/bcm5974.c | 73 |
1 files changed, 28 insertions, 45 deletions
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index e8cfb3864181..3a78f235fa3e 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <linux/usb/input.h> | 40 | #include <linux/usb/input.h> |
| 41 | #include <linux/hid.h> | 41 | #include <linux/hid.h> |
| 42 | #include <linux/mutex.h> | 42 | #include <linux/mutex.h> |
| 43 | #include <linux/input/mt.h> | ||
| 43 | 44 | ||
| 44 | #define USB_VENDOR_ID_APPLE 0x05ac | 45 | #define USB_VENDOR_ID_APPLE 0x05ac |
| 45 | 46 | ||
| @@ -235,11 +236,14 @@ struct bcm5974 { | |||
| 235 | struct bt_data *bt_data; /* button transferred data */ | 236 | struct bt_data *bt_data; /* button transferred data */ |
| 236 | struct urb *tp_urb; /* trackpad usb request block */ | 237 | struct urb *tp_urb; /* trackpad usb request block */ |
| 237 | u8 *tp_data; /* trackpad transferred data */ | 238 | u8 *tp_data; /* trackpad transferred data */ |
| 239 | const struct tp_finger *index[MAX_FINGERS]; /* finger index data */ | ||
| 240 | struct input_mt_pos pos[MAX_FINGERS]; /* position array */ | ||
| 241 | int slots[MAX_FINGERS]; /* slot assignments */ | ||
| 238 | }; | 242 | }; |
| 239 | 243 | ||
| 240 | /* logical signal quality */ | 244 | /* logical signal quality */ |
| 241 | #define SN_PRESSURE 45 /* pressure signal-to-noise ratio */ | 245 | #define SN_PRESSURE 45 /* pressure signal-to-noise ratio */ |
| 242 | #define SN_WIDTH 100 /* width signal-to-noise ratio */ | 246 | #define SN_WIDTH 25 /* width signal-to-noise ratio */ |
| 243 | #define SN_COORD 250 /* coordinate signal-to-noise ratio */ | 247 | #define SN_COORD 250 /* coordinate signal-to-noise ratio */ |
| 244 | #define SN_ORIENT 10 /* orientation signal-to-noise ratio */ | 248 | #define SN_ORIENT 10 /* orientation signal-to-noise ratio */ |
| 245 | 249 | ||
| @@ -414,10 +418,6 @@ static void setup_events_to_report(struct input_dev *input_dev, | |||
| 414 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 256, 5, 0); | 418 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 256, 5, 0); |
| 415 | input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 16, 0, 0); | 419 | input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 16, 0, 0); |
| 416 | 420 | ||
| 417 | /* pointer emulation */ | ||
| 418 | set_abs(input_dev, ABS_X, &cfg->x); | ||
| 419 | set_abs(input_dev, ABS_Y, &cfg->y); | ||
| 420 | |||
| 421 | /* finger touch area */ | 421 | /* finger touch area */ |
| 422 | set_abs(input_dev, ABS_MT_TOUCH_MAJOR, &cfg->w); | 422 | set_abs(input_dev, ABS_MT_TOUCH_MAJOR, &cfg->w); |
| 423 | set_abs(input_dev, ABS_MT_TOUCH_MINOR, &cfg->w); | 423 | set_abs(input_dev, ABS_MT_TOUCH_MINOR, &cfg->w); |
| @@ -431,18 +431,13 @@ static void setup_events_to_report(struct input_dev *input_dev, | |||
| 431 | set_abs(input_dev, ABS_MT_POSITION_Y, &cfg->y); | 431 | set_abs(input_dev, ABS_MT_POSITION_Y, &cfg->y); |
| 432 | 432 | ||
| 433 | __set_bit(EV_KEY, input_dev->evbit); | 433 | __set_bit(EV_KEY, input_dev->evbit); |
| 434 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
| 435 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
| 436 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
| 437 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | ||
| 438 | __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); | ||
| 439 | __set_bit(BTN_LEFT, input_dev->keybit); | 434 | __set_bit(BTN_LEFT, input_dev->keybit); |
| 440 | 435 | ||
| 441 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | ||
| 442 | if (cfg->caps & HAS_INTEGRATED_BUTTON) | 436 | if (cfg->caps & HAS_INTEGRATED_BUTTON) |
| 443 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); | 437 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); |
| 444 | 438 | ||
| 445 | input_set_events_per_packet(input_dev, 60); | 439 | input_mt_init_slots(input_dev, MAX_FINGERS, |
| 440 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK); | ||
| 446 | } | 441 | } |
| 447 | 442 | ||
| 448 | /* report button data as logical button state */ | 443 | /* report button data as logical button state */ |
| @@ -462,10 +457,13 @@ static int report_bt_state(struct bcm5974 *dev, int size) | |||
| 462 | return 0; | 457 | return 0; |
| 463 | } | 458 | } |
| 464 | 459 | ||
| 465 | static void report_finger_data(struct input_dev *input, | 460 | static void report_finger_data(struct input_dev *input, int slot, |
| 466 | const struct bcm5974_config *cfg, | 461 | const struct input_mt_pos *pos, |
| 467 | const struct tp_finger *f) | 462 | const struct tp_finger *f) |
| 468 | { | 463 | { |
| 464 | input_mt_slot(input, slot); | ||
| 465 | input_mt_report_slot_state(input, MT_TOOL_FINGER, true); | ||
| 466 | |||
| 469 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, | 467 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, |
| 470 | raw2int(f->touch_major) << 1); | 468 | raw2int(f->touch_major) << 1); |
| 471 | input_report_abs(input, ABS_MT_TOUCH_MINOR, | 469 | input_report_abs(input, ABS_MT_TOUCH_MINOR, |
| @@ -476,10 +474,8 @@ static void report_finger_data(struct input_dev *input, | |||
| 476 | raw2int(f->tool_minor) << 1); | 474 | raw2int(f->tool_minor) << 1); |
| 477 | input_report_abs(input, ABS_MT_ORIENTATION, | 475 | input_report_abs(input, ABS_MT_ORIENTATION, |
| 478 | MAX_FINGER_ORIENTATION - raw2int(f->orientation)); | 476 | MAX_FINGER_ORIENTATION - raw2int(f->orientation)); |
| 479 | input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x)); | 477 | input_report_abs(input, ABS_MT_POSITION_X, pos->x); |
| 480 | input_report_abs(input, ABS_MT_POSITION_Y, | 478 | input_report_abs(input, ABS_MT_POSITION_Y, pos->y); |
| 481 | cfg->y.min + cfg->y.max - raw2int(f->abs_y)); | ||
| 482 | input_mt_sync(input); | ||
| 483 | } | 479 | } |
| 484 | 480 | ||
| 485 | static void report_synaptics_data(struct input_dev *input, | 481 | static void report_synaptics_data(struct input_dev *input, |
| @@ -507,8 +503,7 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
| 507 | const struct bcm5974_config *c = &dev->cfg; | 503 | const struct bcm5974_config *c = &dev->cfg; |
| 508 | const struct tp_finger *f; | 504 | const struct tp_finger *f; |
| 509 | struct input_dev *input = dev->input; | 505 | struct input_dev *input = dev->input; |
| 510 | int raw_n, i; | 506 | int raw_n, i, n = 0; |
| 511 | int abs_x = 0, abs_y = 0, n = 0; | ||
| 512 | 507 | ||
| 513 | if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) | 508 | if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) |
| 514 | return -EIO; | 509 | return -EIO; |
| @@ -517,35 +512,23 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
| 517 | f = (const struct tp_finger *)(dev->tp_data + c->tp_offset); | 512 | f = (const struct tp_finger *)(dev->tp_data + c->tp_offset); |
| 518 | raw_n = (size - c->tp_offset) / SIZEOF_FINGER; | 513 | raw_n = (size - c->tp_offset) / SIZEOF_FINGER; |
| 519 | 514 | ||
| 520 | /* always track the first finger; when detached, start over */ | 515 | for (i = 0; i < raw_n; i++) { |
| 521 | if (raw_n) { | 516 | if (raw2int(f[i].touch_major) == 0) |
| 522 | 517 | continue; | |
| 523 | /* report raw trackpad data */ | 518 | dev->pos[n].x = raw2int(f[i].abs_x); |
| 524 | for (i = 0; i < raw_n; i++) | 519 | dev->pos[n].y = c->y.min + c->y.max - raw2int(f[i].abs_y); |
| 525 | report_finger_data(input, c, &f[i]); | 520 | dev->index[n++] = &f[i]; |
| 526 | |||
| 527 | /* while tracking finger still valid, count all fingers */ | ||
| 528 | if (raw2int(f->touch_major) > 0 && raw2int(f->origin)) { | ||
| 529 | abs_x = raw2int(f->abs_x); | ||
| 530 | abs_y = c->y.min + c->y.max - raw2int(f->abs_y); | ||
| 531 | for (i = 0; i < raw_n; i++) | ||
| 532 | if (raw2int(f[i].touch_major) > 0) | ||
| 533 | n++; | ||
| 534 | } | ||
| 535 | } | 521 | } |
| 536 | 522 | ||
| 537 | input_report_key(input, BTN_TOUCH, n > 0); | 523 | input_mt_assign_slots(input, dev->slots, dev->pos, n); |
| 538 | input_report_key(input, BTN_TOOL_FINGER, n == 1); | ||
| 539 | input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2); | ||
| 540 | input_report_key(input, BTN_TOOL_TRIPLETAP, n == 3); | ||
| 541 | input_report_key(input, BTN_TOOL_QUADTAP, n > 3); | ||
| 542 | 524 | ||
| 543 | report_synaptics_data(input, c, f, raw_n); | 525 | for (i = 0; i < n; i++) |
| 526 | report_finger_data(input, dev->slots[i], | ||
| 527 | &dev->pos[i], dev->index[i]); | ||
| 544 | 528 | ||
| 545 | if (n > 0) { | 529 | input_mt_sync_frame(input); |
| 546 | input_report_abs(input, ABS_X, abs_x); | 530 | |
| 547 | input_report_abs(input, ABS_Y, abs_y); | 531 | report_synaptics_data(input, c, f, raw_n); |
| 548 | } | ||
| 549 | 532 | ||
| 550 | /* type 2 reports button events via ibt only */ | 533 | /* type 2 reports button events via ibt only */ |
| 551 | if (c->tp_type == TYPE2) { | 534 | if (c->tp_type == TYPE2) { |
