aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2012-09-15 10:40:04 -0400
committerHenrik Rydberg <rydberg@euromail.se>2012-09-19 13:50:22 -0400
commit51c80b74002f86477d691ed7c8ac479dcfa6271c (patch)
treec318aa1bd6312c7338c9f560f79eb397bd8db6cc
parent0e7269669d4cd14a49b4e5c708b8be0ba11504f7 (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.c73
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
465static void report_finger_data(struct input_dev *input, 460static 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
485static void report_synaptics_data(struct input_dev *input, 481static 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) {