diff options
author | Sven Anders <anders@anduras.de> | 2008-08-08 16:31:33 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2008-08-08 16:44:28 -0400 |
commit | 82a196f481661170b4982dc7e68a12e9253309d0 (patch) | |
tree | 26b047fe68743247162b4b0401ab8740960328be /drivers | |
parent | d83d213d9fda671dfd84ea81182742f9e329a6b4 (diff) |
Input: appletouch - handle geyser 3/4 status bits
Implement support for status bits on Geyser 3/4.
Signed-off-by: Sven Anders <anders@anduras.de>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/mouse/appletouch.c | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 36ebe5c25ee3..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); |
@@ -488,7 +502,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
488 | ATP_XFACT, &x_z, &x_f); | 502 | ATP_XFACT, &x_z, &x_f); |
489 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, | 503 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, |
490 | ATP_YFACT, &y_z, &y_f); | 504 | ATP_YFACT, &y_z, &y_f); |
491 | key = dev->data[dev->datalen - 1] & 1; | 505 | key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON; |
492 | 506 | ||
493 | if (x && y) { | 507 | if (x && y) { |
494 | if (dev->x_old != -1) { | 508 | if (dev->x_old != -1) { |
@@ -568,34 +582,38 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
568 | 582 | ||
569 | dbg_dump("sample", dev->xy_cur); | 583 | dbg_dump("sample", dev->xy_cur); |
570 | 584 | ||
571 | if (!dev->valid) { | 585 | /* Just update the base values (i.e. touchpad in untouched state) */ |
572 | /* first sample */ | 586 | if (dev->data[dev->datalen - 1] & ATP_STATUS_BASE_UPDATE) { |
573 | dev->valid = true; | ||
574 | dev->x_old = dev->y_old = -1; | ||
575 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | ||
576 | 587 | ||
588 | dprintk(KERN_DEBUG "appletouch: updated base values\n"); | ||
589 | |||
590 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | ||
577 | goto exit; | 591 | goto exit; |
578 | } | 592 | } |
579 | 593 | ||
580 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { | 594 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { |
581 | /* accumulate the change */ | 595 | /* calculate the change */ |
582 | signed char change = dev->xy_old[i] - dev->xy_cur[i]; | 596 | dev->xy_acc[i] = dev->xy_cur[i] - dev->xy_old[i]; |
583 | dev->xy_acc[i] -= change; | 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; | ||
584 | 604 | ||
585 | /* prevent down drifting */ | 605 | /* prevent down drifting */ |
586 | if (dev->xy_acc[i] < 0) | 606 | if (dev->xy_acc[i] < 0) |
587 | dev->xy_acc[i] = 0; | 607 | dev->xy_acc[i] = 0; |
588 | } | 608 | } |
589 | 609 | ||
590 | memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); | ||
591 | |||
592 | dbg_dump("accumulator", dev->xy_acc); | 610 | dbg_dump("accumulator", dev->xy_acc); |
593 | 611 | ||
594 | x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, | 612 | x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS, |
595 | ATP_XFACT, &x_z, &x_f); | 613 | ATP_XFACT, &x_z, &x_f); |
596 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, | 614 | y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, |
597 | ATP_YFACT, &y_z, &y_f); | 615 | ATP_YFACT, &y_z, &y_f); |
598 | key = dev->data[dev->datalen - 1] & 1; | 616 | key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON; |
599 | 617 | ||
600 | if (x && y) { | 618 | if (x && y) { |
601 | if (dev->x_old != -1) { | 619 | if (dev->x_old != -1) { |
@@ -647,7 +665,8 @@ static void atp_complete_geyser_3_4(struct urb *urb) | |||
647 | if (!x && !y && !key) { | 665 | if (!x && !y && !key) { |
648 | dev->idlecount++; | 666 | dev->idlecount++; |
649 | if (dev->idlecount == 10) { | 667 | if (dev->idlecount == 10) { |
650 | dev->valid = false; | 668 | dev->x_old = dev->y_old = -1; |
669 | dev->idlecount = 0; | ||
651 | schedule_work(&dev->work); | 670 | schedule_work(&dev->work); |
652 | /* Don't resubmit urb here, wait for reinit */ | 671 | /* Don't resubmit urb here, wait for reinit */ |
653 | return; | 672 | return; |
@@ -879,8 +898,6 @@ static int atp_suspend(struct usb_interface *iface, pm_message_t message) | |||
879 | struct atp *dev = usb_get_intfdata(iface); | 898 | struct atp *dev = usb_get_intfdata(iface); |
880 | 899 | ||
881 | usb_kill_urb(dev->urb); | 900 | usb_kill_urb(dev->urb); |
882 | dev->valid = false; | ||
883 | |||
884 | return 0; | 901 | return 0; |
885 | } | 902 | } |
886 | 903 | ||