diff options
Diffstat (limited to 'drivers/input/mouse/appletouch.c')
-rw-r--r-- | drivers/input/mouse/appletouch.c | 299 |
1 files changed, 222 insertions, 77 deletions
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 1f41ae94f26b..079816e6b23b 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
@@ -136,12 +136,28 @@ MODULE_DEVICE_TABLE(usb, atp_table); | |||
136 | #define ATP_GEYSER_MODE_REQUEST_INDEX 0 | 136 | #define ATP_GEYSER_MODE_REQUEST_INDEX 0 |
137 | #define ATP_GEYSER_MODE_VENDOR_VALUE 0x04 | 137 | #define ATP_GEYSER_MODE_VENDOR_VALUE 0x04 |
138 | 138 | ||
139 | /** | ||
140 | * enum atp_status_bits - status bit meanings | ||
141 | * | ||
142 | * These constants represent the meaning of the status bits. | ||
143 | * (only Geyser 3/4) | ||
144 | * | ||
145 | * @ATP_STATUS_BUTTON: The button was pressed | ||
146 | * @ATP_STATUS_BASE_UPDATE: Update of the base values (untouched pad) | ||
147 | * @ATP_STATUS_FROM_RESET: Reset previously performed | ||
148 | */ | ||
149 | enum atp_status_bits { | ||
150 | ATP_STATUS_BUTTON = BIT(0), | ||
151 | ATP_STATUS_BASE_UPDATE = BIT(2), | ||
152 | ATP_STATUS_FROM_RESET = BIT(4), | ||
153 | }; | ||
154 | |||
139 | /* Structure to hold all of our device specific stuff */ | 155 | /* Structure to hold all of our device specific stuff */ |
140 | struct atp { | 156 | struct atp { |
141 | char phys[64]; | 157 | char phys[64]; |
142 | struct usb_device *udev; /* usb device */ | 158 | struct usb_device *udev; /* usb device */ |
143 | struct urb *urb; /* usb request block */ | 159 | struct urb *urb; /* usb request block */ |
144 | signed char *data; /* transferred data */ | 160 | u8 *data; /* transferred data */ |
145 | struct input_dev *input; /* input dev */ | 161 | struct input_dev *input; /* input dev */ |
146 | enum atp_touchpad_type type; /* type of touchpad */ | 162 | enum atp_touchpad_type type; /* type of touchpad */ |
147 | bool open; | 163 | bool open; |
@@ -251,8 +267,6 @@ static void atp_reinit(struct work_struct *work) | |||
251 | int retval; | 267 | int retval; |
252 | 268 | ||
253 | dprintk("appletouch: putting appletouch to sleep (reinit)\n"); | 269 | dprintk("appletouch: putting appletouch to sleep (reinit)\n"); |
254 | dev->idlecount = 0; | ||
255 | |||
256 | atp_geyser_init(udev); | 270 | atp_geyser_init(udev); |
257 | 271 | ||
258 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); | 272 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); |
@@ -327,11 +341,14 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers) | |||
327 | input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2); | 341 | input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2); |
328 | } | 342 | } |
329 | 343 | ||
330 | static void atp_complete(struct urb *urb) | 344 | /* Check URB status and for correct length of data package */ |
345 | |||
346 | #define ATP_URB_STATUS_SUCCESS 0 | ||
347 | #define ATP_URB_STATUS_ERROR 1 | ||
348 | #define ATP_URB_STATUS_ERROR_FATAL 2 | ||
349 | |||
350 | static int atp_status_check(struct urb *urb) | ||
331 | { | 351 | { |
332 | int x, y, x_z, y_z, x_f, y_f; | ||
333 | int retval, i, j; | ||
334 | int key; | ||
335 | struct atp *dev = urb->context; | 352 | struct atp *dev = urb->context; |
336 | 353 | ||
337 | switch (urb->status) { | 354 | switch (urb->status) { |
@@ -351,11 +368,12 @@ static void atp_complete(struct urb *urb) | |||
351 | /* This urb is terminated, clean up */ | 368 | /* This urb is terminated, clean up */ |
352 | dbg("atp_complete: urb shutting down with status: %d", | 369 | dbg("atp_complete: urb shutting down with status: %d", |
353 | urb->status); | 370 | urb->status); |
354 | return; | 371 | return ATP_URB_STATUS_ERROR_FATAL; |
372 | |||
355 | default: | 373 | default: |
356 | dbg("atp_complete: nonzero urb status received: %d", | 374 | dbg("atp_complete: nonzero urb status received: %d", |
357 | urb->status); | 375 | urb->status); |
358 | goto exit; | 376 | return ATP_URB_STATUS_ERROR; |
359 | } | 377 | } |
360 | 378 | ||
361 | /* drop incomplete datasets */ | 379 | /* drop incomplete datasets */ |
@@ -363,30 +381,33 @@ static void atp_complete(struct urb *urb) | |||
363 | dprintk("appletouch: incomplete data package" | 381 | dprintk("appletouch: incomplete data package" |
364 | " (first byte: %d, length: %d).\n", | 382 | " (first byte: %d, length: %d).\n", |
365 | dev->data[0], dev->urb->actual_length); | 383 | dev->data[0], dev->urb->actual_length); |
366 | goto exit; | 384 | return ATP_URB_STATUS_ERROR; |
367 | } | 385 | } |
368 | 386 | ||
369 | /* reorder the sensors values */ | 387 | return ATP_URB_STATUS_SUCCESS; |
370 | if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) { | 388 | } |
371 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); | ||
372 | 389 | ||
373 | /* | 390 | /* |
374 | * The values are laid out like this: | 391 | * USB interrupt callback functions |
375 | * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... | 392 | */ |
376 | * '-' is an unused value. | ||
377 | */ | ||
378 | 393 | ||
379 | /* read X values */ | 394 | /* Interrupt function for older touchpads: FOUNTAIN/GEYSER1/GEYSER2 */ |
380 | for (i = 0, j = 19; i < 20; i += 2, j += 3) { | 395 | |
381 | dev->xy_cur[i] = dev->data[j + 1]; | 396 | static void atp_complete_geyser_1_2(struct urb *urb) |
382 | dev->xy_cur[i + 1] = dev->data[j + 2]; | 397 | { |
383 | } | 398 | int x, y, x_z, y_z, x_f, y_f; |
384 | /* read Y values */ | 399 | int retval, i, j; |
385 | for (i = 0, j = 1; i < 9; i += 2, j += 3) { | 400 | int key; |
386 | dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; | 401 | struct atp *dev = urb->context; |
387 | dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; | 402 | int status = atp_status_check(urb); |
388 | } | 403 | |
389 | } else if (dev->type == ATP_GEYSER2) { | 404 | if (status == ATP_URB_STATUS_ERROR_FATAL) |
405 | return; | ||
406 | else if (status == ATP_URB_STATUS_ERROR) | ||
407 | goto exit; | ||
408 | |||
409 | /* reorder the sensors values */ | ||
410 | if (dev->type == ATP_GEYSER2) { | ||
390 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); | 411 | memset(dev->xy_cur, 0, sizeof(dev->xy_cur)); |
391 | 412 | ||
392 | /* | 413 | /* |
@@ -427,34 +448,40 @@ static void atp_complete(struct urb *urb) | |||
427 | /* first sample */ | 448 | /* first sample */ |
428 | dev->valid = true; | 449 | dev->valid = true; |
429 | dev->x_old = dev->y_old = -1; | 450 | dev->x_old = dev->y_old = -1; |
451 | |||
452 | /* Store first sample */ | ||
430 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | 453 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); |
431 | 454 | ||
432 | if (dev->size_detect_done || | 455 | /* Perform size detection, if not done already */ |
433 | dev->type == ATP_GEYSER3) /* No 17" Macbooks (yet) */ | 456 | if (!dev->size_detect_done) { |
434 | goto exit; | 457 | |
458 | /* 17" Powerbooks have extra X sensors */ | ||
459 | for (i = (dev->type == ATP_GEYSER2 ? 15 : 16); | ||
460 | i < ATP_XSENSORS; i++) { | ||
461 | if (!dev->xy_cur[i]) | ||
462 | continue; | ||
463 | |||
464 | printk(KERN_INFO | ||
465 | "appletouch: 17\" model detected.\n"); | ||
466 | |||
467 | if (dev->type == ATP_GEYSER2) | ||
468 | input_set_abs_params(dev->input, ABS_X, | ||
469 | 0, | ||
470 | (20 - 1) * | ||
471 | ATP_XFACT - 1, | ||
472 | ATP_FUZZ, 0); | ||
473 | else | ||
474 | input_set_abs_params(dev->input, ABS_X, | ||
475 | 0, | ||
476 | (26 - 1) * | ||
477 | ATP_XFACT - 1, | ||
478 | ATP_FUZZ, 0); | ||
479 | break; | ||
480 | } | ||
435 | 481 | ||
436 | /* 17" Powerbooks have extra X sensors */ | 482 | dev->size_detect_done = 1; |
437 | for (i = (dev->type == ATP_GEYSER2 ? 15 : 16); | 483 | goto exit; |
438 | i < ATP_XSENSORS; i++) { | ||
439 | if (!dev->xy_cur[i]) | ||
440 | continue; | ||
441 | |||
442 | printk(KERN_INFO "appletouch: 17\" model detected.\n"); | ||
443 | if (dev->type == ATP_GEYSER2) | ||
444 | input_set_abs_params(dev->input, ABS_X, 0, | ||
445 | (20 - 1) * | ||
446 | ATP_XFACT - 1, | ||
447 | ATP_FUZZ, 0); | ||
448 | else | ||
449 | input_set_abs_params(dev->input, ABS_X, 0, | ||
450 | (ATP_XSENSORS - 1) * | ||
451 | ATP_XFACT - 1, | ||
452 | ATP_FUZZ, 0); | ||
453 | break; | ||
454 | } | 484 | } |
455 | |||
456 | dev->size_detect_done = 1; | ||
457 | goto exit; | ||
458 | } | 485 | } |
459 | 486 | ||
460 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { | 487 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { |
@@ -475,7 +502,118 @@ static void atp_complete(struct urb *urb) | |||
475 | ATP_XFACT, &x_z, &x_f); | 502 | ATP_XFACT, &x_z, &x_f); |
476 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, | 503 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, |
477 | ATP_YFACT, &y_z, &y_f); | 504 | ATP_YFACT, &y_z, &y_f); |
478 | key = dev->data[dev->datalen - 1] & 1; | 505 | key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON; |
506 | |||
507 | if (x && y) { | ||
508 | if (dev->x_old != -1) { | ||
509 | x = (dev->x_old * 3 + x) >> 2; | ||
510 | y = (dev->y_old * 3 + y) >> 2; | ||
511 | dev->x_old = x; | ||
512 | dev->y_old = y; | ||
513 | |||
514 | if (debug > 1) | ||
515 | printk(KERN_DEBUG "appletouch: " | ||
516 | "X: %3d Y: %3d Xz: %3d Yz: %3d\n", | ||
517 | x, y, x_z, y_z); | ||
518 | |||
519 | input_report_key(dev->input, BTN_TOUCH, 1); | ||
520 | input_report_abs(dev->input, ABS_X, x); | ||
521 | input_report_abs(dev->input, ABS_Y, y); | ||
522 | input_report_abs(dev->input, ABS_PRESSURE, | ||
523 | min(ATP_PRESSURE, x_z + y_z)); | ||
524 | atp_report_fingers(dev->input, max(x_f, y_f)); | ||
525 | } | ||
526 | dev->x_old = x; | ||
527 | dev->y_old = y; | ||
528 | |||
529 | } else if (!x && !y) { | ||
530 | |||
531 | dev->x_old = dev->y_old = -1; | ||
532 | input_report_key(dev->input, BTN_TOUCH, 0); | ||
533 | input_report_abs(dev->input, ABS_PRESSURE, 0); | ||
534 | atp_report_fingers(dev->input, 0); | ||
535 | |||
536 | /* reset the accumulator on release */ | ||
537 | memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); | ||
538 | } | ||
539 | |||
540 | input_report_key(dev->input, BTN_LEFT, key); | ||
541 | input_sync(dev->input); | ||
542 | |||
543 | exit: | ||
544 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); | ||
545 | if (retval) | ||
546 | err("atp_complete: usb_submit_urb failed with result %d", | ||
547 | retval); | ||
548 | } | ||
549 | |||
550 | /* Interrupt function for older touchpads: GEYSER3/GEYSER4 */ | ||
551 | |||
552 | static void atp_complete_geyser_3_4(struct urb *urb) | ||
553 | { | ||
554 | int x, y, x_z, y_z, x_f, y_f; | ||
555 | int retval, i, j; | ||
556 | int key; | ||
557 | struct atp *dev = urb->context; | ||
558 | int status = atp_status_check(urb); | ||
559 | |||
560 | if (status == ATP_URB_STATUS_ERROR_FATAL) | ||
561 | return; | ||
562 | else if (status == ATP_URB_STATUS_ERROR) | ||
563 | goto exit; | ||
564 | |||
565 | /* Reorder the sensors values: | ||
566 | * | ||
567 | * The values are laid out like this: | ||
568 | * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ... | ||
569 | * '-' is an unused value. | ||
570 | */ | ||
571 | |||
572 | /* read X values */ | ||
573 | for (i = 0, j = 19; i < 20; i += 2, j += 3) { | ||
574 | dev->xy_cur[i] = dev->data[j + 1]; | ||
575 | dev->xy_cur[i + 1] = dev->data[j + 2]; | ||
576 | } | ||
577 | /* read Y values */ | ||
578 | for (i = 0, j = 1; i < 9; i += 2, j += 3) { | ||
579 | dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1]; | ||
580 | dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2]; | ||
581 | } | ||
582 | |||
583 | dbg_dump("sample", dev->xy_cur); | ||
584 | |||
585 | /* Just update the base values (i.e. touchpad in untouched state) */ | ||
586 | if (dev->data[dev->datalen - 1] & ATP_STATUS_BASE_UPDATE) { | ||
587 | |||
588 | dprintk(KERN_DEBUG "appletouch: updated base values\n"); | ||
589 | |||
590 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | ||
591 | goto exit; | ||
592 | } | ||
593 | |||
594 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { | ||
595 | /* calculate the change */ | ||
596 | dev->xy_acc[i] = dev->xy_cur[i] - dev->xy_old[i]; | ||
597 | |||
598 | /* this is a round-robin value, so couple with that */ | ||
599 | if (dev->xy_acc[i] > 127) | ||
600 | dev->xy_acc[i] -= 256; | ||
601 | |||
602 | if (dev->xy_acc[i] < -127) | ||
603 | dev->xy_acc[i] += 256; | ||
604 | |||
605 | /* prevent down drifting */ | ||
606 | if (dev->xy_acc[i] < 0) | ||
607 | dev->xy_acc[i] = 0; | ||
608 | } | ||
609 | |||
610 | dbg_dump("accumulator", dev->xy_acc); | ||
611 | |||
612 | x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, | ||
613 | ATP_XFACT, &x_z, &x_f); | ||
614 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, | ||
615 | ATP_YFACT, &y_z, &y_f); | ||
616 | key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON; | ||
479 | 617 | ||
480 | if (x && y) { | 618 | if (x && y) { |
481 | if (dev->x_old != -1) { | 619 | if (dev->x_old != -1) { |
@@ -514,28 +652,27 @@ static void atp_complete(struct urb *urb) | |||
514 | input_sync(dev->input); | 652 | input_sync(dev->input); |
515 | 653 | ||
516 | /* | 654 | /* |
517 | * Many Geysers will continue to send packets continually after | 655 | * Geysers 3/4 will continue to send packets continually after |
518 | * the first touch unless reinitialised. Do so if it's been | 656 | * the first touch unless reinitialised. Do so if it's been |
519 | * idle for a while in order to avoid waking the kernel up | 657 | * idle for a while in order to avoid waking the kernel up |
520 | * several hundred times a second. Re-initialization does not | 658 | * several hundred times a second. |
521 | * work on Fountain touchpads. | ||
522 | */ | 659 | */ |
523 | if (dev->type != ATP_FOUNTAIN) { | 660 | |
524 | /* | 661 | /* |
525 | * Button must not be pressed when entering suspend, | 662 | * Button must not be pressed when entering suspend, |
526 | * otherwise we will never release the button. | 663 | * otherwise we will never release the button. |
527 | */ | 664 | */ |
528 | if (!x && !y && !key) { | 665 | if (!x && !y && !key) { |
529 | dev->idlecount++; | 666 | dev->idlecount++; |
530 | if (dev->idlecount == 10) { | 667 | if (dev->idlecount == 10) { |
531 | dev->valid = false; | 668 | dev->x_old = dev->y_old = -1; |
532 | schedule_work(&dev->work); | ||
533 | /* Don't resubmit urb here, wait for reinit */ | ||
534 | return; | ||
535 | } | ||
536 | } else | ||
537 | dev->idlecount = 0; | 669 | dev->idlecount = 0; |
538 | } | 670 | schedule_work(&dev->work); |
671 | /* Don't resubmit urb here, wait for reinit */ | ||
672 | return; | ||
673 | } | ||
674 | } else | ||
675 | dev->idlecount = 0; | ||
539 | 676 | ||
540 | exit: | 677 | exit: |
541 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); | 678 | retval = usb_submit_urb(dev->urb, GFP_ATOMIC); |
@@ -632,9 +769,19 @@ static int atp_probe(struct usb_interface *iface, | |||
632 | if (!dev->data) | 769 | if (!dev->data) |
633 | goto err_free_urb; | 770 | goto err_free_urb; |
634 | 771 | ||
635 | usb_fill_int_urb(dev->urb, udev, | 772 | /* Select the USB complete (callback) function */ |
636 | usb_rcvintpipe(udev, int_in_endpointAddr), | 773 | if (dev->type == ATP_FOUNTAIN || |
637 | dev->data, dev->datalen, atp_complete, dev, 1); | 774 | dev->type == ATP_GEYSER1 || |
775 | dev->type == ATP_GEYSER2) | ||
776 | usb_fill_int_urb(dev->urb, udev, | ||
777 | usb_rcvintpipe(udev, int_in_endpointAddr), | ||
778 | dev->data, dev->datalen, | ||
779 | atp_complete_geyser_1_2, dev, 1); | ||
780 | else | ||
781 | usb_fill_int_urb(dev->urb, udev, | ||
782 | usb_rcvintpipe(udev, int_in_endpointAddr), | ||
783 | dev->data, dev->datalen, | ||
784 | atp_complete_geyser_3_4, dev, 1); | ||
638 | 785 | ||
639 | error = atp_handle_geyser(dev); | 786 | error = atp_handle_geyser(dev); |
640 | if (error) | 787 | if (error) |
@@ -751,8 +898,6 @@ static int atp_suspend(struct usb_interface *iface, pm_message_t message) | |||
751 | struct atp *dev = usb_get_intfdata(iface); | 898 | struct atp *dev = usb_get_intfdata(iface); |
752 | 899 | ||
753 | usb_kill_urb(dev->urb); | 900 | usb_kill_urb(dev->urb); |
754 | dev->valid = false; | ||
755 | |||
756 | return 0; | 901 | return 0; |
757 | } | 902 | } |
758 | 903 | ||