summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2008-10-08 23:39:23 +0200
committerHenrik Rydberg <rydberg@euromail.se>2008-10-08 23:39:23 +0200
commit262c292d2d4241301476dbbefffe0b1ff827f2b2 (patch)
tree7f8eddcf6e47f23fce15179df9c46a1df9f7b0bd
parent6e62e2ecb58e6a1982b22b4e9c948483ac70ba34 (diff)
parentaa2d0bf085f624ad24deb0357d4fe935225ccd18 (diff)
Merge branch 'master' into detour
-rw-r--r--CHANGES174
-rw-r--r--INSTALL4
-rw-r--r--Makefile2
-rw-r--r--bcm5974-dkms-mkdeb/debian/README.Debian23
-rw-r--r--bcm5974-dkms-mkdeb/debian/changelog3
-rw-r--r--bcm5974-dkms-mkdeb/debian/control5
-rw-r--r--bcm5974-dkms-mkdeb/debian/copyright41
-rw-r--r--bcm5974-dkms-mkdeb/debian/dirs1
-rw-r--r--bcm5974.c667
-rw-r--r--dkms.conf3
-rwxr-xr-xscripts/bcm5974-diagnostics11
-rwxr-xr-xscripts/bcm5974-post-install20
-rwxr-xr-xscripts/bcm5974-pre-install42
13 files changed, 649 insertions, 347 deletions
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..2850cef
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,174 @@
1bcm5974 (0.65) unstable; urgency=low
2
3 * Switch back to normal mode when closing
4
5 -- Henrik Rydberg <rydberg@euromail.se> Sun, 14 Sep 2008 16:06:42 +0200
6
7bcm5974 (0.64) unstable; urgency=low
8
9 * Finger counting improved further
10
11 -- Henrik Rydberg <rydberg@euromail.se> Wed, 03 Sep 2008 21:58:38 +0200
12
13bcm5974 (0.63) unstable; urgency=low
14
15 * Finger pressure hysteresis added
16
17 -- Henrik Rydberg <rydberg@euromail.se> Wed, 03 Sep 2008 13:26:29 +0200
18
19bcm5974 (0.62) unstable; urgency=low
20
21 * Compatibility mode reverted
22 * BTN_TOUCH event added for mousedev
23
24 -- Henrik Rydberg <rydberg@euromail.se> Tue, 02 Sep 2008 20:46:51 +0200
25
26bcm5974 (0.61) unstable; urgency=low
27
28 * Smoother motion in mouse interface
29
30 -- Henrik Rydberg <rydberg@euromail.se> Mon, 01 Sep 2008 21:01:24 +0200
31
32bcm5974 (0.60) unstable; urgency=low
33
34 * New default mouse driver mode
35 * Mouse configuration parameters
36
37 -- Henrik Rydberg <rydberg@euromail.se> Mon, 01 Sep 2008 18:38:21 +0200
38
39bcm5974 (0.59) unstable; urgency=low
40
41 * Cleanup patch from Dmitry Torokhov
42 * Auto-suspend patch from Dmitry Torokhov
43
44 -- Henrik Rydberg <rydberg@euromail.se> Fri, 25 Jul 2008 20:14:05 +0200
45
46bcm5974 (0.58) unstable; urgency=low
47
48 * Name changes; use usbhid definitions, rename atp to bcm5974
49 * Input syncing moved to report functions, event type setup broken out
50 * Traffic functions added for open/close and suspend/resume logic
51 * Open/close and suspend/resume transition logic corrected
52 * Open/close serialized with respect to suspend/resume
53
54 -- Henrik Rydberg <rydberg@euromail.se> Wed, 23 Jul 2008 02:20:10 +0200
55
56bcm5974 (0.57) unstable; urgency=low
57
58 * Keep reset_resume around
59 * Submitted to kernel.org
60
61 -- Henrik Rydberg <rydberg@euromail.se> Sat, 19 Jul 2008 01:42:52 +0200
62
63bcm5974 (0.56) unstable; urgency=low
64
65 * Leave device initialization to hid; use mode-switch only
66 * Mode switch moved to atp_open and simplified
67 * Corrected cleanup action in atp_open
68 * Simplified control package detection
69 * Removed reset_resume, pre_reset, post_reset; not needed
70
71 -- Henrik Rydberg <rydberg@euromail.se> Fri, 18 Jul 2008 02:42:52 +0200
72
73bcm5974 (0.55) unstable; urgency=low
74
75 * Package updates.
76 * Reverting GFP_ATOMIC for irq handlers.
77
78 -- Henrik Rydberg <rydberg@euromail.se> Wed, 09 Jul 2008 20:59:39 +0200
79
80bcm5974 (0.54) unstable; urgency=low
81
82 * And another one... finally got the bright idea to test it by
83 emulating the different product ids.
84
85 -- Henrik Rydberg <rydberg@euromail.se> Tue, 08 Jul 2008 20:59:39 +0200
86
87bcm5974 (0.53) unstable; urgency=low
88
89 * Another typo in the post-install script.
90
91 -- Henrik Rydberg <rydberg@euromail.se> Mon, 07 Jul 2008 20:59:39 +0200
92
93bcm5974 (0.52) unstable; urgency=low
94
95 * Typo in the post-install script.
96
97 -- Henrik Rydberg <rydberg@euromail.se> Mon, 07 Jul 2008 20:09:39 +0200
98
99bcm5974 (0.51) unstable; urgency=low
100
101 * Fine-tuned signal-to-noise ratio, smoother mouse motion.
102 * Interrupt code got minor simplifications.
103 * GFP_ATOMIC completetly removed.
104
105 -- Henrik Rydberg <rydberg@euromail.se> Mon, 07 Jul 2008 18:09:39 +0200
106
107bcm5974 (0.5) unstable; urgency=low
108
109 * Working palm detection
110 * Changes for kernel.org
111 * DKMS introduced.
112
113 -- Henrik Rydberg <rydberg@euromail.se> Sun, 06 Jul 2008 20:59:39 +0200
114
115bcm5974 (0.42) unstable; urgency=low
116
117 * First button click registered.
118 * Hooks pre/post-reset added.
119
120 -- Henrik Rydberg <rydberg@euromail.se> Tue, 01 Jul 2008 20:59:39 +0200
121
122bcm5974 (0.41) unstable; urgency=low
123
124 * The reset_resume kernel function added.
125
126 -- Henrik Rydberg <rydberg@euromail.se> Sun, 29 Jun 2008 20:59:39 +0200
127
128bcm5974 (0.4) unstable; urgency=low
129
130 * Both finger pressure and width reported.
131
132 -- Henrik Rydberg <rydberg@euromail.se> Sun, 29 Jun 2008 18:59:39 +0200
133
134bcm5974 (0.31) unstable; urgency=low
135
136 * Administrative changes for kernel.org.
137
138 -- Henrik Rydberg <rydberg@euromail.se> Fri, 27 Jun 2008 20:59:39 +0200
139
140bcm5974 (0.3) unstable; urgency=low
141
142 * Explicit device structure, use all packages.
143
144 -- Henrik Rydberg <rydberg@euromail.se> Fri, 27 Jun 2008 18:59:39 +0200
145
146bcm5974 (0.23) unstable; urgency=low
147
148 * Finger release not reported properly.
149
150 -- Henrik Rydberg <rydberg@euromail.se> Fri, 27 Jun 2008 17:59:39 +0200
151
152bcm5974 (0.22) unstable; urgency=low
153
154 * ABS coordinates more stable with synaptics.
155
156 -- Henrik Rydberg <rydberg@euromail.se> Thu, 26 Jun 2008 20:59:39 +0200
157
158bcm5974 (0.21) unstable; urgency=low
159
160 * Fixed the relative coordinate scaling.
161
162 -- Henrik Rydberg <rydberg@euromail.se> Wed, 25 Jun 2008 20:59:39 +0200
163
164bcm5974 (0.2) unstable; urgency=low
165
166 * Misinterpreted pressure input, noise reduction.
167
168 -- Henrik Rydberg <rydberg@euromail.se> Wed, 25 Jun 2008 20:59:39 +0200
169
170bcm5974 (0.1) unstable; urgency=low
171
172 * First version.
173
174 -- Henrik Rydberg <rydberg@euromail.se> Tue, 24 Jun 2008 20:59:39 +0200
diff --git a/INSTALL b/INSTALL
index 7c7e975..195fd05 100644
--- a/INSTALL
+++ b/INSTALL
@@ -9,7 +9,9 @@ Standing in the source directory, do:
9 9
103. sudo ./scripts/bcm5974-post-install 103. sudo ./scripts/bcm5974-post-install
11 11
124. reboot (only if bcm5974 never was used before) 124. sudo depmod -a
13
145. reboot (or reload the bcm5974 module if already installed)
13 15
14For trouble-shooting, try running 16For trouble-shooting, try running
15 17
diff --git a/Makefile b/Makefile
index 74335c8..6a04556 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
1# 1#
2# Makefile for USB Network drivers 2# Makefile for input/mouse drivers
3# 3#
4 4
5obj-m := bcm5974.o 5obj-m := bcm5974.o
diff --git a/bcm5974-dkms-mkdeb/debian/README.Debian b/bcm5974-dkms-mkdeb/debian/README.Debian
index 7a1b108..1f170f1 100644
--- a/bcm5974-dkms-mkdeb/debian/README.Debian
+++ b/bcm5974-dkms-mkdeb/debian/README.Debian
@@ -1,10 +1,23 @@
1MODULE_NAME DKMS module for Debian 1MODULE_NAME DKMS module for Debian
2 2
3This driver adds support for the multitouch trackpad on the new 3BCM5974: This driver adds support for the multitouch trackpad on the
4Apple Macbook Air and Macbook Pro Penryn laptops. It replaces the 4new Apple Macbook Air and Macbook Pro Penryn laptops. It replaces the
5appletouch driver on those computers, and integrates well with the 5appletouch driver on those computers, and integrates well with the
6synaptics driver of the Xorg system. 6synaptics driver of the Xorg system.
7 7
8This package was automatically generated by the DKMS system, 8Known to work on Macbook Air and Macbook Pro Penryn.
9for distribution on Debian based operating systems.
10 9
10* Install the debian package (uses dkms)
11
12* Reboot
13
14Post installation
15
16* Make sure your /etc/X11/xorg.conf settings are sane.
17
18* If experiencing problems with your xorg settings, try the
19 bcm5974-diagnostics script (dkms installs the source under /usr/src/).
20
21Enjoy!
22
23Henrik Rydberg <rydberg@euromail.se>
diff --git a/bcm5974-dkms-mkdeb/debian/changelog b/bcm5974-dkms-mkdeb/debian/changelog
index 029a7bc..3ea1523 100644
--- a/bcm5974-dkms-mkdeb/debian/changelog
+++ b/bcm5974-dkms-mkdeb/debian/changelog
@@ -1,6 +1,5 @@
1MODULE_NAME-dkms (MODULE_VERSION) unstable; urgency=low 1MODULE_NAME-dkms (MODULE_VERSION) unstable; urgency=low
2 2
3 * Automatically packaged by DKMS. 3 * Switch back to normal mode when closing
4 4
5 -- Henrik Rydberg <rydberg@euromail.se> DATE_STAMP 5 -- Henrik Rydberg <rydberg@euromail.se> DATE_STAMP
6
diff --git a/bcm5974-dkms-mkdeb/debian/control b/bcm5974-dkms-mkdeb/debian/control
index ad717e6..c5497bf 100644
--- a/bcm5974-dkms-mkdeb/debian/control
+++ b/bcm5974-dkms-mkdeb/debian/control
@@ -4,8 +4,13 @@ Priority: optional
4Maintainer: Henrik Rydberg <rydberg@euromail.se> 4Maintainer: Henrik Rydberg <rydberg@euromail.se>
5Build-Depends: debhelper (>= 5) 5Build-Depends: debhelper (>= 5)
6Standards-Version: 3.7.2 6Standards-Version: 3.7.2
7Homepage: http://web.comhem.se/rydberg/Bits/
7 8
8Package: MODULE_NAME-dkms 9Package: MODULE_NAME-dkms
9Architecture: all 10Architecture: all
10Depends: dkms (>= 1.95), bash (>> 1.99) 11Depends: dkms (>= 1.95), bash (>> 1.99)
11Description: Apple USB BCM5974 Multitouch trackpad support (DKMS) 12Description: Apple USB BCM5974 Multitouch trackpad support (DKMS)
13 This driver adds support for the multitouch trackpad on the new
14 Apple Macbook Air and Macbook Pro Penryn laptops. It replaces the
15 appletouch driver on those computers, and integrates well with the
16 synaptics driver of the Xorg system.
diff --git a/bcm5974-dkms-mkdeb/debian/copyright b/bcm5974-dkms-mkdeb/debian/copyright
index d690e83..e00b447 100644
--- a/bcm5974-dkms-mkdeb/debian/copyright
+++ b/bcm5974-dkms-mkdeb/debian/copyright
@@ -1,4 +1,41 @@
1GNU GENERAL PUBLIC LICENSE Version 2 1The bcm5974-dkms package was created using DKMS <dkms-devel@dell.com>
2 2
3See the LICENSE file of this distribution for details. 3Source URL: http://web.comhem.se/rydberg/Bits/
4 4
5Upstream Author: Henrik Rydberg <rydberg@euromail.se>
6
7Copyright:
8 Copyright (C) 2008 Henrik Rydberg (rydberg@euromail.se)
9
10 The USB initialization and package decoding was made by
11 Scott Shawcroft as part of the touchd user-space driver project:
12 Copyright (C) 2008 Scott Shawcroft (scott.shawcroft@gmail.com)
13
14 The BCM5974 driver is based on the appletouch driver:
15 Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
16 Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)
17 Copyright (C) 2005 Stelian Pop (stelian@popies.net)
18 Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
19 Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
20 Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
21 Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch)
22
23License:
24
25 This program is free software; you can redistribute it and/or modify
26 it under the terms of the GNU General Public License as published by
27 the Free Software Foundation; either version 2 of the License, or
28 (at your option) any later version.
29
30 This program is distributed in the hope that it will be useful,
31 but WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 GNU General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with this program; if not, write to the Free Software
37 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38
39Packaging:
40 Copyright (C) 2008 by Henrik Rydberg <rydberg@euromail.se>
41 released under GPL 2
diff --git a/bcm5974-dkms-mkdeb/debian/dirs b/bcm5974-dkms-mkdeb/debian/dirs
index 2b01d9a..b601f22 100644
--- a/bcm5974-dkms-mkdeb/debian/dirs
+++ b/bcm5974-dkms-mkdeb/debian/dirs
@@ -1,2 +1 @@
1usr/src usr/src
2etc/modprobe.d
diff --git a/bcm5974.c b/bcm5974.c
index a7f070f..bf6c59f 100644
--- a/bcm5974.c
+++ b/bcm5974.c
@@ -39,42 +39,43 @@
39#include <linux/module.h> 39#include <linux/module.h>
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 43
43#define APPLE_VENDOR_ID 0x05AC 44#define USB_VENDOR_ID_APPLE 0x05ac
44 45
45/* MacbookAir, aka wellspring */ 46/* MacbookAir, aka wellspring */
46#define ATP_WELLSPRING_ANSI 0x0223 47#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223
47#define ATP_WELLSPRING_ISO 0x0224 48#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224
48#define ATP_WELLSPRING_JIS 0x0225 49#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225
49/* MacbookProPenryn, aka wellspring2 */ 50/* MacbookProPenryn, aka wellspring2 */
50#define ATP_WELLSPRING2_ANSI 0x0230 51#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
51#define ATP_WELLSPRING2_ISO 0x0231 52#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
52#define ATP_WELLSPRING2_JIS 0x0232 53#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
53 54
54#define ATP_DEVICE(prod) { \ 55#define BCM5974_DEVICE(prod) { \
55 .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ 56 .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
56 USB_DEVICE_ID_MATCH_INT_CLASS | \ 57 USB_DEVICE_ID_MATCH_INT_CLASS | \
57 USB_DEVICE_ID_MATCH_INT_PROTOCOL), \ 58 USB_DEVICE_ID_MATCH_INT_PROTOCOL), \
58 .idVendor = APPLE_VENDOR_ID, \ 59 .idVendor = USB_VENDOR_ID_APPLE, \
59 .idProduct = (prod), \ 60 .idProduct = (prod), \
60 .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ 61 .bInterfaceClass = USB_INTERFACE_CLASS_HID, \
61 .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE \ 62 .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE \
62} 63}
63 64
64/* table of devices that work with this driver */ 65/* table of devices that work with this driver */
65static const struct usb_device_id atp_table [] = { 66static const struct usb_device_id bcm5974_table[] = {
66 /* MacbookAir1.1 */ 67 /* MacbookAir1.1 */
67 ATP_DEVICE(ATP_WELLSPRING_ANSI), 68 BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
68 ATP_DEVICE(ATP_WELLSPRING_ISO), 69 BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
69 ATP_DEVICE(ATP_WELLSPRING_JIS), 70 BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_JIS),
70 /* MacbookProPenryn */ 71 /* MacbookProPenryn */
71 ATP_DEVICE(ATP_WELLSPRING2_ANSI), 72 BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
72 ATP_DEVICE(ATP_WELLSPRING2_ISO), 73 BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
73 ATP_DEVICE(ATP_WELLSPRING2_JIS), 74 BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
74 /* Terminating entry */ 75 /* Terminating entry */
75 {} 76 {}
76}; 77};
77MODULE_DEVICE_TABLE(usb, atp_table); 78MODULE_DEVICE_TABLE(usb, bcm5974_table);
78 79
79MODULE_AUTHOR("Henrik Rydberg"); 80MODULE_AUTHOR("Henrik Rydberg");
80MODULE_DESCRIPTION("Apple USB BCM5974 multitouch driver"); 81MODULE_DESCRIPTION("Apple USB BCM5974 multitouch driver");
@@ -104,7 +105,7 @@ struct tp_header {
104 105
105/* trackpad finger structure */ 106/* trackpad finger structure */
106struct tp_finger { 107struct tp_finger {
107 __le16 origin; /* left/right origin? */ 108 __le16 origin; /* zero when switching track finger */
108 __le16 abs_x; /* absolute x coodinate */ 109 __le16 abs_x; /* absolute x coodinate */
109 __le16 abs_y; /* absolute y coodinate */ 110 __le16 abs_y; /* absolute y coodinate */
110 __le16 rel_x; /* relative x coodinate */ 111 __le16 rel_x; /* relative x coodinate */
@@ -125,50 +126,40 @@ struct tp_data {
125}; 126};
126 127
127/* device-specific parameters */ 128/* device-specific parameters */
128struct atp_params { 129struct bcm5974_param {
129 int dim; /* logical dimension */ 130 int dim; /* logical dimension */
131 int fuzz; /* logical noise value */
130 int devmin; /* device minimum reading */ 132 int devmin; /* device minimum reading */
131 int devmax; /* device maximum reading */ 133 int devmax; /* device maximum reading */
132}; 134};
133 135
134/* device-specific configuration */ 136/* device-specific configuration */
135struct atp_config { 137struct bcm5974_config {
136 int ansi, iso, jis; /* the product id of this device */ 138 int ansi, iso, jis; /* the product id of this device */
137 int bt_ep; /* the endpoint of the button interface */ 139 int bt_ep; /* the endpoint of the button interface */
138 int bt_datalen; /* data length of the button interface */ 140 int bt_datalen; /* data length of the button interface */
139 int tp_ep; /* the endpoint of the trackpad interface */ 141 int tp_ep; /* the endpoint of the trackpad interface */
140 int tp_datalen; /* data length of the trackpad interface */ 142 int tp_datalen; /* data length of the trackpad interface */
141 struct atp_params p; /* finger pressure limits */ 143 struct bcm5974_param p; /* finger pressure limits */
142 struct atp_params w; /* finger width limits */ 144 struct bcm5974_param w; /* finger width limits */
143 struct atp_params x; /* horizontal limits */ 145 struct bcm5974_param x; /* horizontal limits */
144 struct atp_params y; /* vertical limits */ 146 struct bcm5974_param y; /* vertical limits */
145};
146
147/* logical trackpad state */
148struct tp_state {
149 int pressure; /* finger pressure value */
150 int width; /* finger width value */
151 int abs_x; /* absolute x coordinate */
152 int abs_y; /* absolute y coordinate */
153 int fingers; /* number of fingers on trackpad */
154}; 147};
155 148
156/* logical device structure */ 149/* logical device structure */
157struct atp { 150struct bcm5974 {
158 char phys[64]; 151 char phys[64];
159 struct usb_device *udev; /* usb device */ 152 struct usb_device *udev; /* usb device */
153 struct usb_interface *intf; /* our interface */
160 struct input_dev *input; /* input dev */ 154 struct input_dev *input; /* input dev */
161 struct atp_config cfg; /* device configuration */ 155 struct bcm5974_config cfg; /* device configuration */
162 int open; /* >0: open, else closed */ 156 struct mutex pm_mutex; /* serialize access to open/suspend */
163 int suspended; /* >0: suspended, else open */ 157 int opened; /* 1: opened, 0: closed */
164 struct urb *bt_urb; /* button usb request block */ 158 struct urb *bt_urb; /* button usb request block */
165 struct bt_data *bt_data; /* button transferred data */ 159 struct bt_data *bt_data; /* button transferred data */
166 unsigned bt_prev_state; /* logical button previous state */
167 unsigned bt_state; /* logical button state */
168 struct urb *tp_urb; /* trackpad usb request block */ 160 struct urb *tp_urb; /* trackpad usb request block */
169 struct tp_data *tp_data; /* trackpad transferred data */ 161 struct tp_data *tp_data; /* trackpad transferred data */
170 struct tp_state tp_state; /* logical trackpad state */ 162 int fingers; /* number of fingers on trackpad */
171 unsigned tp_valid; /* trackpad sensors valid */
172}; 163};
173 164
174/* logical dimensions */ 165/* logical dimensions */
@@ -176,45 +167,54 @@ struct atp {
176#define DIM_WIDTH 16 /* maximum finger width */ 167#define DIM_WIDTH 16 /* maximum finger width */
177#define DIM_X 1280 /* maximum trackpad x value */ 168#define DIM_X 1280 /* maximum trackpad x value */
178#define DIM_Y 800 /* maximum trackpad y value */ 169#define DIM_Y 800 /* maximum trackpad y value */
179#define SNRATIO 50 /* signal to noise ratio */ 170
171/* logical signal quality */
172#define SN_PRESSURE 45 /* pressure signal-to-noise ratio */
173#define SN_WIDTH 100 /* width signal-to-noise ratio */
174#define SN_COORD 250 /* coordinate signal-to-noise ratio */
175
176/* pressure thresholds */
177#define PRESSURE_LOW (2 * DIM_PRESSURE / SN_PRESSURE)
178#define PRESSURE_HIGH (3 * PRESSURE_LOW)
180 179
181/* device constants */ 180/* device constants */
182static const struct atp_config atp_config_table[] = { 181static const struct bcm5974_config bcm5974_config_table[] = {
183 { 182 {
184 ATP_WELLSPRING_ANSI, 183 USB_DEVICE_ID_APPLE_WELLSPRING_ANSI,
185 ATP_WELLSPRING_ISO, 184 USB_DEVICE_ID_APPLE_WELLSPRING_ISO,
186 ATP_WELLSPRING_JIS, 185 USB_DEVICE_ID_APPLE_WELLSPRING_JIS,
187 0x84, sizeof(struct bt_data), 186 0x84, sizeof(struct bt_data),
188 0x81, sizeof(struct tp_data), 187 0x81, sizeof(struct tp_data),
189 { DIM_PRESSURE, 0, 256 }, 188 { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
190 { DIM_WIDTH, 0, 2048 }, 189 { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
191 { DIM_X, -4824, 5342 }, 190 { DIM_X, DIM_X / SN_COORD, -4824, 5342 },
192 { DIM_Y, -172, 5820 } 191 { DIM_Y, DIM_Y / SN_COORD, -172, 5820 }
193 }, 192 },
194 { 193 {
195 ATP_WELLSPRING2_ANSI, 194 USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI,
196 ATP_WELLSPRING2_ISO, 195 USB_DEVICE_ID_APPLE_WELLSPRING2_ISO,
197 ATP_WELLSPRING2_JIS, 196 USB_DEVICE_ID_APPLE_WELLSPRING2_JIS,
198 0x84, sizeof(struct bt_data), 197 0x84, sizeof(struct bt_data),
199 0x81, sizeof(struct tp_data), 198 0x81, sizeof(struct tp_data),
200 { DIM_PRESSURE, 0, 256 }, 199 { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
201 { DIM_WIDTH, 0, 2048 }, 200 { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
202 { DIM_X, -4824, 5342 }, 201 { DIM_X, DIM_X / SN_COORD, -4824, 4824 },
203 { DIM_Y, -172, 5820 } 202 { DIM_Y, DIM_Y / SN_COORD, -172, 4290 }
204 }, 203 },
205 {} 204 {}
206}; 205};
207 206
208/* return the device-specific configuration by device */ 207/* return the device-specific configuration by device */
209static const struct atp_config *atp_product_config(struct usb_device *udev) 208static const struct bcm5974_config *bcm5974_get_config(struct usb_device *udev)
210{ 209{
211 u16 id = le16_to_cpu(udev->descriptor.idProduct); 210 u16 id = le16_to_cpu(udev->descriptor.idProduct);
212 const struct atp_config *config; 211 const struct bcm5974_config *cfg;
213 for (config = atp_config_table; config->ansi; ++config) 212
214 if (config->ansi == id || config->iso == id || 213 for (cfg = bcm5974_config_table; cfg->ansi; ++cfg)
215 config->jis == id) 214 if (cfg->ansi == id || cfg->iso == id || cfg->jis == id)
216 return config; 215 return cfg;
217 return atp_config_table; 216
217 return bcm5974_config_table;
218} 218}
219 219
220/* convert 16-bit little endian to signed integer */ 220/* convert 16-bit little endian to signed integer */
@@ -224,142 +224,189 @@ static inline int raw2int(__le16 x)
224} 224}
225 225
226/* scale device data to logical dimensions (asserts devmin < devmax) */ 226/* scale device data to logical dimensions (asserts devmin < devmax) */
227static inline int int2scale(const struct atp_params *p, int x) 227static inline int int2scale(const struct bcm5974_param *p, int x)
228{ 228{
229 return x * p->dim / (p->devmax - p->devmin); 229 return x * p->dim / (p->devmax - p->devmin);
230} 230}
231 231
232/* all logical value ranges are [0,dim). */ 232/* all logical value ranges are [0,dim). */
233static inline int int2bound(const struct atp_params *p, int x) 233static inline int int2bound(const struct bcm5974_param *p, int x)
234{ 234{
235 int s = int2scale(p, x); 235 int s = int2scale(p, x);
236 return s < 0 ? 0 : s >= p->dim ? p->dim - 1 : s; 236
237 //return clamp_val(s, 0, p->dim - 1);
238 return s < 0 ? 0 : s >= p->dim ? p->dim - 1 : s;
237} 239}
238 240
239/* convert button data to logical button state */ 241/* setup which logical events to report */
240static int compute_bt_state(struct atp *dev, int size) 242static void setup_events_to_report(struct input_dev *input_dev,
243 const struct bcm5974_config *cfg)
244{
245 __set_bit(EV_ABS, input_dev->evbit);
246
247 input_set_abs_params(input_dev, ABS_PRESSURE,
248 0, cfg->p.dim, cfg->p.fuzz, 0);
249 input_set_abs_params(input_dev, ABS_TOOL_WIDTH,
250 0, cfg->w.dim, cfg->w.fuzz, 0);
251 input_set_abs_params(input_dev, ABS_X,
252 0, cfg->x.dim, cfg->x.fuzz, 0);
253 input_set_abs_params(input_dev, ABS_Y,
254 0, cfg->y.dim, cfg->y.fuzz, 0);
255
256 __set_bit(EV_KEY, input_dev->evbit);
257 __set_bit(BTN_TOUCH, input_dev->keybit);
258 __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
259 __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
260 __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
261 __set_bit(BTN_LEFT, input_dev->keybit);
262}
263
264/* report button data as logical button state */
265static int report_bt_state(struct bcm5974 *dev, int size)
241{ 266{
242 if (size != sizeof(struct bt_data)) 267 if (size != sizeof(struct bt_data))
243 return -EIO; 268 return -EIO;
244 269
245 dev->bt_prev_state = dev->bt_state; 270 input_report_key(dev->input, BTN_LEFT, dev->bt_data->button);
246 dev->bt_state = dev->bt_data->button; 271 input_sync(dev->input);
247 272
248 return 0; 273 return 0;
249} 274}
250 275
251/* convert trackpad data to logical trackpad state */ 276/* report trackpad data as logical trackpad state */
252static int compute_tp_state(struct atp *dev, int size) 277static int report_tp_state(struct bcm5974 *dev, int size)
253{ 278{
254 const struct atp_config *c = &dev->cfg; 279 const struct bcm5974_config *c = &dev->cfg;
255 const struct tp_finger *f = dev->tp_data->finger; 280 const struct tp_finger *f = dev->tp_data->finger;
281 struct input_dev *input = dev->input;
256 const int fingers = (size - 26) / 28; 282 const int fingers = (size - 26) / 28;
257 struct tp_state *s = &dev->tp_state; 283 int raw_p, raw_w, raw_x, raw_y;
284 int ptest = 0, origin = 0, nmin = 0, nmax = 0;
285 int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
258 286
259 if (size < 26 || (size - 26) % 28 != 0) 287 if (size < 26 || (size - 26) % 28 != 0)
260 return -EIO; 288 return -EIO;
261 289
262 if (!fingers) { 290 /* always track the first finger; when detached, start over */
263 s->pressure = 0; 291 if (fingers) {
264 s->fingers = 0; 292 raw_p = raw2int(f->force_major);
265 return 0; 293 raw_w = raw2int(f->size_major);
294 raw_x = raw2int(f->abs_x);
295 raw_y = raw2int(f->abs_y);
296
297 dprintk(9,
298 "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n",
299 raw_p, raw_w, raw_x, raw_y);
300
301 ptest = int2bound(&c->p, raw_p);
302 origin = raw2int(f->origin);
303 }
304
305 /* while tracking finger still valid, count all fingers */
306 if (ptest > PRESSURE_LOW && origin) {
307 abs_p = ptest;
308 abs_w = int2bound(&c->w, raw_w);
309 abs_x = int2bound(&c->x, raw_x - c->x.devmin);
310 abs_y = int2bound(&c->y, c->y.devmax - raw_y);
311 for (; f != dev->tp_data->finger + fingers; f++) {
312 ptest = int2bound(&c->p, raw2int(f->force_major));
313 if (ptest > PRESSURE_LOW)
314 nmax++;
315 if (ptest > PRESSURE_HIGH)
316 nmin++;
317 }
266 } 318 }
267 319
268 dprintk(9, "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d f: %d\n", 320 if (dev->fingers < nmin)
269 raw2int(f->force_major), raw2int(f->size_major), 321 dev->fingers = nmin;
270 raw2int(f->abs_x), raw2int(f->abs_y), fingers); 322 if (dev->fingers > nmax)
323 dev->fingers = nmax;
324
325 input_report_key(input, BTN_TOUCH, dev->fingers > 0);
326 input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1);
327 input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2);
328 input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2);
329
330 input_report_abs(input, ABS_PRESSURE, abs_p);
331 input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
332
333 if (abs_p) {
334 input_report_abs(input, ABS_X, abs_x);
335 input_report_abs(input, ABS_Y, abs_y);
336
337 dprintk(8,
338 "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
339 "nmin: %d nmax: %d n: %d\n",
340 abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers);
271 341
272 s->pressure = int2bound(&c->p, raw2int(f->force_major)); 342 }
273 s->width = int2bound(&c->w, raw2int(f->size_major)); 343
274 s->abs_x = int2bound(&c->x, raw2int(f->abs_x) - c->x.devmin); 344 input_sync(input);
275 s->abs_y = int2bound(&c->y, c->y.devmax - raw2int(f->abs_y));
276 s->fingers = s->pressure > 0 ? fingers : 0;
277 345
278 return 0; 346 return 0;
279} 347}
280 348
281/* Wellspring initialization constants */ 349/* Wellspring initialization constants */
282#define ATP_WELLSPRING_MODE_READ_REQUEST_ID 1 350#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1
283#define ATP_WELLSPRING_MODE_WRITE_REQUEST_ID 9 351#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9
284#define ATP_WELLSPRING_MODE_REQUEST_VALUE 0x300 352#define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300
285#define ATP_WELLSPRING_MODE_REQUEST_INDEX 0 353#define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0
286#define ATP_WELLSPRING_MODE_VENDOR_VALUE_1 0x01 354#define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01
287#define ATP_WELLSPRING_MODE_VENDOR_VALUE_2 0x05 355#define BCM5974_WELLSPRING_MODE_NORMAL_VALUE 0x08
288 356
289static int atp_wellspring_init(struct atp *dev) 357static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
290{ 358{
291 char *data = kmalloc(8, GFP_KERNEL); 359 char *data = kmalloc(8, GFP_KERNEL);
292 int error = 0, size; 360 int retval = 0, size;
293 361
294 if (!data) { 362 if (!data) {
295 err("bcm5974: out of memory"); 363 err("bcm5974: out of memory");
296 error = -ENOMEM; 364 retval = -ENOMEM;
297 goto error; 365 goto out;
298 }
299
300 /* reset button endpoint */
301 if (usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
302 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
303 0, dev->cfg.bt_ep, NULL, 0, 5000)) {
304 err("bcm5974: could not reset button endpoint");
305 error = -EIO;
306 goto error;
307 }
308
309 /* reset trackpad endpoint */
310 if (usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
311 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
312 0, dev->cfg.tp_ep, NULL, 0, 5000)) {
313 err("bcm5974: could not reset trackpad endpoint");
314 error = -EIO;
315 goto error;
316 } 366 }
317 367
318 /* read configuration */ 368 /* read configuration */
319 size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), 369 size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
320 ATP_WELLSPRING_MODE_READ_REQUEST_ID, 370 BCM5974_WELLSPRING_MODE_READ_REQUEST_ID,
321 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 371 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
322 ATP_WELLSPRING_MODE_REQUEST_VALUE, 372 BCM5974_WELLSPRING_MODE_REQUEST_VALUE,
323 ATP_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); 373 BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
324 374
325 if (size != 8) { 375 if (size != 8) {
326 err("bcm5974: could not read from device"); 376 err("bcm5974: could not read from device");
327 error = -EIO; 377 retval = -EIO;
328 goto error; 378 goto out;
329 } 379 }
330 380
331 /* apply the mode switch */ 381 /* apply the mode switch */
332 data[0] = ATP_WELLSPRING_MODE_VENDOR_VALUE_1; 382 data[0] = on ?
333 data[1] = ATP_WELLSPRING_MODE_VENDOR_VALUE_2; 383 BCM5974_WELLSPRING_MODE_VENDOR_VALUE :
384 BCM5974_WELLSPRING_MODE_NORMAL_VALUE;
334 385
335 /* write configuration */ 386 /* write configuration */
336 size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), 387 size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
337 ATP_WELLSPRING_MODE_WRITE_REQUEST_ID, 388 BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID,
338 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 389 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
339 ATP_WELLSPRING_MODE_REQUEST_VALUE, 390 BCM5974_WELLSPRING_MODE_REQUEST_VALUE,
340 ATP_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000); 391 BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
341 392
342 if (size != 8) { 393 if (size != 8) {
343 err("bcm5974: could not write to device"); 394 err("bcm5974: could not write to device");
344 error = -EIO; 395 retval = -EIO;
345 goto error; 396 goto out;
346 } 397 }
347 398
348 dev->tp_valid = 0; 399 dprintk(2, "bcm5974: switched to %s mode.\n",
349 400 on ? "wellspring" : "normal");
350 printk(KERN_INFO "bcm5974: Wellspring mode initialized.\n");
351 401
402 out:
352 kfree(data); 403 kfree(data);
353 return 0; 404 return retval;
354
355error:
356 kfree(data);
357 return error;
358} 405}
359 406
360static void irq_button(struct urb *urb) 407static void bcm5974_irq_button(struct urb *urb)
361{ 408{
362 struct atp *dev = urb->context; 409 struct bcm5974 *dev = urb->context;
363 int error; 410 int error;
364 411
365 switch (urb->status) { 412 switch (urb->status) {
@@ -376,17 +423,9 @@ static void irq_button(struct urb *urb)
376 goto exit; 423 goto exit;
377 } 424 }
378 425
379 if (compute_bt_state(dev, dev->bt_urb->actual_length)) { 426 if (report_bt_state(dev, dev->bt_urb->actual_length))
380 dprintk(1, "bcm5974: bad button package, length: %d)\n", 427 dprintk(1, "bcm5974: bad button package, length: %d\n",
381 dev->bt_urb->actual_length); 428 dev->bt_urb->actual_length);
382 goto exit;
383 }
384
385 /* only report button state changes */
386 if (dev->bt_state != dev->bt_prev_state) {
387 input_report_key(dev->input, BTN_LEFT, dev->bt_data->button);
388 input_sync(dev->input);
389 }
390 429
391exit: 430exit:
392 error = usb_submit_urb(dev->bt_urb, GFP_ATOMIC); 431 error = usb_submit_urb(dev->bt_urb, GFP_ATOMIC);
@@ -394,10 +433,9 @@ exit:
394 err("bcm5974: button urb failed: %d", error); 433 err("bcm5974: button urb failed: %d", error);
395} 434}
396 435
397static void irq_trackpad(struct urb *urb) 436static void bcm5974_irq_trackpad(struct urb *urb)
398{ 437{
399 struct atp *dev = urb->context; 438 struct bcm5974 *dev = urb->context;
400 struct tp_state *state = &dev->tp_state;
401 int error; 439 int error;
402 440
403 switch (urb->status) { 441 switch (urb->status) {
@@ -414,26 +452,13 @@ static void irq_trackpad(struct urb *urb)
414 goto exit; 452 goto exit;
415 } 453 }
416 454
417 /* first sample data ignored */ 455 /* control response ignored */
418 if (!dev->tp_valid) { 456 if (dev->tp_urb->actual_length == 2)
419 dev->tp_valid = 1;
420 goto exit; 457 goto exit;
421 }
422 458
423 if (compute_tp_state(dev, dev->tp_urb->actual_length)) { 459 if (report_tp_state(dev, dev->tp_urb->actual_length))
424 dprintk(1, "bcm5974: bad trackpad package, length: %d)\n", 460 dprintk(1, "bcm5974: bad trackpad package, length: %d\n",
425 dev->tp_urb->actual_length); 461 dev->tp_urb->actual_length);
426 goto exit;
427 }
428
429 input_report_abs(dev->input, ABS_PRESSURE, state->pressure);
430 input_report_abs(dev->input, ABS_TOOL_WIDTH, state->width);
431 input_report_abs(dev->input, ABS_X, state->abs_x);
432 input_report_abs(dev->input, ABS_Y, state->abs_y);
433 input_report_key(dev->input, BTN_TOOL_FINGER, state->fingers == 1);
434 input_report_key(dev->input, BTN_TOOL_DOUBLETAP, state->fingers == 2);
435 input_report_key(dev->input, BTN_TOOL_TRIPLETAP, state->fingers > 2);
436 input_sync(dev->input);
437 462
438exit: 463exit:
439 error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC); 464 error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC);
@@ -441,107 +466,184 @@ exit:
441 err("bcm5974: trackpad urb failed: %d", error); 466 err("bcm5974: trackpad urb failed: %d", error);
442} 467}
443 468
444static int atp_open(struct input_dev *input) 469/*
470 * The Wellspring trackpad, like many recent Apple trackpads, share
471 * the usb device with the keyboard. Since keyboards are usually
472 * handled by the HID system, the device ends up being handled by two
473 * modules. Setting up the device therefore becomes slightly
474 * complicated. To enable multitouch features, a mode switch is
475 * required, which is usually applied via the control interface of the
476 * device. It can be argued where this switch should take place. In
477 * some drivers, like appletouch, the switch is made during
478 * probe. However, the hid module may also alter the state of the
479 * device, resulting in trackpad malfunction under certain
480 * circumstances. To get around this problem, there is at least one
481 * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to
482 * recieve a reset_resume request rather than the normal resume.
483 * Since the implementation of reset_resume is equal to mode switch
484 * plus start_traffic, it seems easier to always do the switch when
485 * starting traffic on the device.
486 */
487static int bcm5974_start_traffic(struct bcm5974 *dev)
445{ 488{
446 struct atp *dev = input_get_drvdata(input); 489 if (bcm5974_wellspring_mode(dev, true)) {
447 490 dprintk(1, "bcm5974: mode switch failed\n");
448 if (!dev->open) { 491 goto error;
449 if (usb_submit_urb(dev->bt_urb, GFP_ATOMIC))
450 goto error;
451 if (usb_submit_urb(dev->tp_urb, GFP_ATOMIC))
452 goto err_free_bt_urb;
453 } 492 }
454 493
455 dev->open = 1; 494 if (usb_submit_urb(dev->bt_urb, GFP_KERNEL))
456 dev->suspended = 0; 495 goto error;
496
497 if (usb_submit_urb(dev->tp_urb, GFP_KERNEL))
498 goto err_kill_bt;
499
457 return 0; 500 return 0;
458 501
459err_free_bt_urb: 502err_kill_bt:
460 usb_free_urb(dev->bt_urb); 503 usb_kill_urb(dev->bt_urb);
461error: 504error:
462 return -EIO; 505 return -EIO;
463} 506}
464 507
465static void atp_close(struct input_dev *input) 508static void bcm5974_pause_traffic(struct bcm5974 *dev)
466{ 509{
467 struct atp *dev = input_get_drvdata(input);
468
469 usb_kill_urb(dev->tp_urb); 510 usb_kill_urb(dev->tp_urb);
470 usb_kill_urb(dev->bt_urb); 511 usb_kill_urb(dev->bt_urb);
512 bcm5974_wellspring_mode(dev, false);
513}
514
515/*
516 * The code below implements open/close and manual suspend/resume.
517 * All functions may be called in random order.
518 *
519 * Opening a suspended device fails with EACCES - permission denied.
520 *
521 * Failing a resume leaves the device resumed but closed.
522 */
523static int bcm5974_open(struct input_dev *input)
524{
525 struct bcm5974 *dev = input_get_drvdata(input);
526 int error;
527
528 error = usb_autopm_get_interface(dev->intf);
529 if (error)
530 return error;
471 531
472 dev->open = 0; 532 mutex_lock(&dev->pm_mutex);
473 dev->suspended = 0; 533
534 error = bcm5974_start_traffic(dev);
535 if (!error)
536 dev->opened = 1;
537
538 mutex_unlock(&dev->pm_mutex);
539
540 if (error)
541 usb_autopm_put_interface(dev->intf);
542
543 return error;
544}
545
546static void bcm5974_close(struct input_dev *input)
547{
548 struct bcm5974 *dev = input_get_drvdata(input);
549
550 mutex_lock(&dev->pm_mutex);
551
552 bcm5974_pause_traffic(dev);
553 dev->opened = 0;
554
555 mutex_unlock(&dev->pm_mutex);
556
557 usb_autopm_put_interface(dev->intf);
474} 558}
475 559
476static int atp_probe(struct usb_interface *iface, 560static int bcm5974_suspend(struct usb_interface *iface, pm_message_t message)
477 const struct usb_device_id *id) 561{
562 struct bcm5974 *dev = usb_get_intfdata(iface);
563
564 mutex_lock(&dev->pm_mutex);
565
566 if (dev->opened)
567 bcm5974_pause_traffic(dev);
568
569 mutex_unlock(&dev->pm_mutex);
570
571 return 0;
572}
573
574static int bcm5974_resume(struct usb_interface *iface)
575{
576 struct bcm5974 *dev = usb_get_intfdata(iface);
577 int error = 0;
578
579 mutex_lock(&dev->pm_mutex);
580
581 if (dev->opened)
582 error = bcm5974_start_traffic(dev);
583
584 mutex_unlock(&dev->pm_mutex);
585
586 return error;
587}
588
589static int bcm5974_probe(struct usb_interface *iface,
590 const struct usb_device_id *id)
478{ 591{
479 struct usb_device *udev = interface_to_usbdev(iface); 592 struct usb_device *udev = interface_to_usbdev(iface);
480 const struct atp_config *cfg; 593 const struct bcm5974_config *cfg;
481 struct atp *dev; 594 struct bcm5974 *dev;
482 struct input_dev *input_dev; 595 struct input_dev *input_dev;
483 int error = 0; 596 int error = -ENOMEM;
484 597
485 /* find the product index */ 598 /* find the product index */
486 cfg = atp_product_config(udev); 599 cfg = bcm5974_get_config(udev);
487 600
488 /* allocate memory for our device state and initialize it */ 601 /* allocate memory for our device state and initialize it */
489 dev = kzalloc(sizeof(struct atp), GFP_KERNEL); 602 dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL);
490 input_dev = input_allocate_device(); 603 input_dev = input_allocate_device();
491 if (!dev || !input_dev) { 604 if (!dev || !input_dev) {
492 err("bcm5974: out of memory"); 605 err("bcm5974: out of memory");
493 error = -ENOMEM;
494 goto err_free_devs; 606 goto err_free_devs;
495 } 607 }
496 608
497 dev->udev = udev; 609 dev->udev = udev;
610 dev->intf = iface;
498 dev->input = input_dev; 611 dev->input = input_dev;
499 dev->cfg = *cfg; 612 dev->cfg = *cfg;
613 mutex_init(&dev->pm_mutex);
500 614
501 /* switch to raw sensor mode */ 615 /* setup urbs */
502 if (atp_wellspring_init(dev)) {
503 error = -EIO;
504 goto err_free_devs;
505 }
506
507 dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL); 616 dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL);
508 if (!dev->bt_urb) { 617 if (!dev->bt_urb)
509 error = -ENOMEM;
510 goto err_free_devs; 618 goto err_free_devs;
511 }
512 619
513 dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL); 620 dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL);
514 if (!dev->tp_urb) { 621 if (!dev->tp_urb)
515 error = -ENOMEM;
516 goto err_free_bt_urb; 622 goto err_free_bt_urb;
517 }
518 623
519 dev->bt_data = usb_buffer_alloc(dev->udev, 624 dev->bt_data = usb_buffer_alloc(dev->udev,
520 dev->cfg.bt_datalen, GFP_KERNEL, 625 dev->cfg.bt_datalen, GFP_KERNEL,
521 &dev->bt_urb->transfer_dma); 626 &dev->bt_urb->transfer_dma);
522 if (!dev->bt_data) { 627 if (!dev->bt_data)
523 error = -ENOMEM;
524 goto err_free_urb; 628 goto err_free_urb;
525 }
526 629
527 dev->tp_data = usb_buffer_alloc(dev->udev, 630 dev->tp_data = usb_buffer_alloc(dev->udev,
528 dev->cfg.tp_datalen, GFP_KERNEL, 631 dev->cfg.tp_datalen, GFP_KERNEL,
529 &dev->tp_urb->transfer_dma); 632 &dev->tp_urb->transfer_dma);
530 if (!dev->tp_data) { 633 if (!dev->tp_data)
531 error = -ENOMEM;
532 goto err_free_bt_buffer; 634 goto err_free_bt_buffer;
533 }
534 635
535 usb_fill_int_urb(dev->bt_urb, udev, 636 usb_fill_int_urb(dev->bt_urb, udev,
536 usb_rcvintpipe(udev, cfg->bt_ep), 637 usb_rcvintpipe(udev, cfg->bt_ep),
537 dev->bt_data, dev->cfg.bt_datalen, 638 dev->bt_data, dev->cfg.bt_datalen,
538 irq_button, dev, 1); 639 bcm5974_irq_button, dev, 1);
539 640
540 usb_fill_int_urb(dev->tp_urb, udev, 641 usb_fill_int_urb(dev->tp_urb, udev,
541 usb_rcvintpipe(udev, cfg->tp_ep), 642 usb_rcvintpipe(udev, cfg->tp_ep),
542 dev->tp_data, dev->cfg.tp_datalen, 643 dev->tp_data, dev->cfg.tp_datalen,
543 irq_trackpad, dev, 1); 644 bcm5974_irq_trackpad, dev, 1);
544 645
646 /* create bcm5974 device */
545 usb_make_path(udev, dev->phys, sizeof(dev->phys)); 647 usb_make_path(udev, dev->phys, sizeof(dev->phys));
546 strlcat(dev->phys, "/input0", sizeof(dev->phys)); 648 strlcat(dev->phys, "/input0", sizeof(dev->phys));
547 649
@@ -552,24 +654,10 @@ static int atp_probe(struct usb_interface *iface,
552 654
553 input_set_drvdata(input_dev, dev); 655 input_set_drvdata(input_dev, dev);
554 656
555 input_dev->open = atp_open; 657 input_dev->open = bcm5974_open;
556 input_dev->close = atp_close; 658 input_dev->close = bcm5974_close;
557
558 set_bit(EV_ABS, input_dev->evbit);
559 input_set_abs_params(input_dev, ABS_PRESSURE,
560 0, cfg->p.dim, cfg->p.dim / SNRATIO, 0);
561 input_set_abs_params(input_dev, ABS_TOOL_WIDTH,
562 0, cfg->w.dim, cfg->w.dim / SNRATIO, 0);
563 input_set_abs_params(input_dev, ABS_X,
564 0, cfg->x.dim, cfg->x.dim / SNRATIO, 0);
565 input_set_abs_params(input_dev, ABS_Y,
566 0, cfg->y.dim, cfg->y.dim / SNRATIO, 0);
567 659
568 set_bit(EV_KEY, input_dev->evbit); 660 setup_events_to_report(input_dev, cfg);
569 set_bit(BTN_TOOL_FINGER, input_dev->keybit);
570 set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
571 set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
572 set_bit(BTN_LEFT, input_dev->keybit);
573 661
574 error = input_register_device(dev->input); 662 error = input_register_device(dev->input);
575 if (error) 663 if (error)
@@ -592,99 +680,48 @@ err_free_bt_urb:
592 usb_free_urb(dev->bt_urb); 680 usb_free_urb(dev->bt_urb);
593err_free_devs: 681err_free_devs:
594 usb_set_intfdata(iface, NULL); 682 usb_set_intfdata(iface, NULL);
595 kfree(dev);
596 input_free_device(input_dev); 683 input_free_device(input_dev);
684 kfree(dev);
597 return error; 685 return error;
598} 686}
599 687
600static void atp_disconnect(struct usb_interface *iface) 688static void bcm5974_disconnect(struct usb_interface *iface)
601{ 689{
602 struct atp *dev = usb_get_intfdata(iface); 690 struct bcm5974 *dev = usb_get_intfdata(iface);
603 691
604 usb_set_intfdata(iface, NULL); 692 usb_set_intfdata(iface, NULL);
605 693
606 if (dev) { 694 input_unregister_device(dev->input);
607 input_unregister_device(dev->input); 695 usb_buffer_free(dev->udev, dev->cfg.tp_datalen,
608 usb_buffer_free(dev->udev, dev->cfg.tp_datalen,
609 dev->tp_data, dev->tp_urb->transfer_dma); 696 dev->tp_data, dev->tp_urb->transfer_dma);
610 usb_buffer_free(dev->udev, dev->cfg.bt_datalen, 697 usb_buffer_free(dev->udev, dev->cfg.bt_datalen,
611 dev->bt_data, dev->bt_urb->transfer_dma); 698 dev->bt_data, dev->bt_urb->transfer_dma);
612 usb_free_urb(dev->tp_urb); 699 usb_free_urb(dev->tp_urb);
613 usb_free_urb(dev->bt_urb); 700 usb_free_urb(dev->bt_urb);
614 kfree(dev); 701 kfree(dev);
615 }
616
617 printk(KERN_INFO "bcm5974: disconnected\n");
618}
619
620static int atp_suspend(struct usb_interface *iface, pm_message_t message)
621{
622 struct atp *dev = usb_get_intfdata(iface);
623
624 if (dev) {
625 if (!dev->suspended)
626 atp_close(dev->input);
627 dev->suspended++;
628 }
629
630 return 0;
631}
632
633static int atp_resume(struct usb_interface *iface)
634{
635 struct atp *dev = usb_get_intfdata(iface);
636 int error = 0;
637
638 if (dev && dev->suspended) {
639 if (!--dev->suspended)
640 error = atp_open(dev->input);
641 }
642
643 return error;
644}
645
646static int atp_reset_resume(struct usb_interface *iface)
647{
648 struct atp *dev = usb_get_intfdata(iface);
649
650 if (dev && atp_wellspring_init(dev))
651 printk(KERN_INFO "bcm5974: warning: reset failed\n");
652
653 return atp_resume(iface);
654}
655
656static int atp_pre_reset(struct usb_interface *iface)
657{
658 return atp_suspend(iface, PMSG_ON);
659}
660
661static int atp_post_reset(struct usb_interface *iface)
662{
663 return atp_reset_resume(iface);
664} 702}
665 703
666static struct usb_driver atp_driver = { 704static struct usb_driver bcm5974_driver = {
667 .name = "bcm5974", 705 .name = "bcm5974",
668 .probe = atp_probe, 706 .probe = bcm5974_probe,
669 .disconnect = atp_disconnect, 707 .disconnect = bcm5974_disconnect,
670 .suspend = atp_suspend, 708 .suspend = bcm5974_suspend,
671 .resume = atp_resume, 709 .resume = bcm5974_resume,
672 .reset_resume = atp_reset_resume, 710 .reset_resume = bcm5974_resume,
673 .pre_reset = atp_pre_reset, 711 .id_table = bcm5974_table,
674 .post_reset = atp_post_reset, 712 .supports_autosuspend = 1,
675 .id_table = atp_table,
676}; 713};
677 714
678static int __init atp_init(void) 715static int __init bcm5974_init(void)
679{ 716{
680 return usb_register(&atp_driver); 717 return usb_register(&bcm5974_driver);
681} 718}
682 719
683static void __exit atp_exit(void) 720static void __exit bcm5974_exit(void)
684{ 721{
685 usb_deregister(&atp_driver); 722 usb_deregister(&bcm5974_driver);
686} 723}
687 724
688module_init(atp_init); 725module_init(bcm5974_init);
689module_exit(atp_exit); 726module_exit(bcm5974_exit);
690 727
diff --git a/dkms.conf b/dkms.conf
index 89d112e..aec50fa 100644
--- a/dkms.conf
+++ b/dkms.conf
@@ -1,8 +1,9 @@
1PACKAGE_NAME="bcm5974" 1PACKAGE_NAME="bcm5974"
2PACKAGE_VERSION="0.5" 2PACKAGE_VERSION="0.65"
3MAKE[0]="make -C ${kernel_source_dir} 3MAKE[0]="make -C ${kernel_source_dir}
4 SUBDIRS=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build modules" 4 SUBDIRS=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build modules"
5BUILT_MODULE_NAME[0]="bcm5974" 5BUILT_MODULE_NAME[0]="bcm5974"
6DEST_MODULE_LOCATION[0]="/kernel/drivers/input/mouse" 6DEST_MODULE_LOCATION[0]="/kernel/drivers/input/mouse"
7PRE_INSTALL="scripts/bcm5974-pre-install"
7POST_INSTALL="scripts/bcm5974-post-install" 8POST_INSTALL="scripts/bcm5974-post-install"
8POST_REMOVE="scripts/bcm5974-post-remove" 9POST_REMOVE="scripts/bcm5974-post-remove"
diff --git a/scripts/bcm5974-diagnostics b/scripts/bcm5974-diagnostics
index 0322158..acd0bf4 100755
--- a/scripts/bcm5974-diagnostics
+++ b/scripts/bcm5974-diagnostics
@@ -131,22 +131,13 @@ if [ -f $DEVPATH ]; then
131 echo \* $DEVPATH: module is registered 131 echo \* $DEVPATH: module is registered
132 else 132 else
133 echo \* $DEVPATH: module is NOT registered 133 echo \* $DEVPATH: module is NOT registered
134 echo No help on this one... 134 echo "Please double-check the quirks settings in $DRIVMOD"
135 exit 1 135 exit 1
136 fi 136 fi
137else 137else
138 echo \* $DEVPATH: does not exist, ignore 138 echo \* $DEVPATH: does not exist, ignore
139fi 139fi
140 140
141# Was the $DRIVER properly initialized?
142WELLSPRING=`dmesg|grep $DRIVER|grep Wellspring`
143if [ "$WELLSPRING" != "" ]; then
144 echo \* $DRIVER: Wellspring was initialized
145else
146 echo \* $DRIVER: Wellspring was NOT initialized
147 exit 1
148fi
149
150# Do we have synaptics working properly? 141# Do we have synaptics working properly?
151typeset -i SYNLINES=`synclient -l|wc -l` 142typeset -i SYNLINES=`synclient -l|wc -l`
152if [ $SYNLINES -gt 10 ]; then 143if [ $SYNLINES -gt 10 ]; then
diff --git a/scripts/bcm5974-post-install b/scripts/bcm5974-post-install
index 21e989e..5674d40 100755
--- a/scripts/bcm5974-post-install
+++ b/scripts/bcm5974-post-install
@@ -25,17 +25,19 @@ ETCPATH=/etc/modprobe.d/$DRIVER
25echo ----------------------------------------------------------------------- 25echo -----------------------------------------------------------------------
26 26
27DIR=`dirname $0` 27DIR=`dirname $0`
28LSUSB=/usr/sbin/lsusb
29
28PAT_HEAD="options usbhid quirks=" 30PAT_HEAD="options usbhid quirks="
29PAT_MBA="0x05ac:0x022" 31PAT[0]="05ac:022"
30PAT_MBP="0x05ac:0x023" 32PAT[1]="05ac:023"
31MATCH_MBA=$PAT_HEAD$PAT_MBA 33MATCH[0]=${PAT_HEAD}0x05ac:0x022
32MATCH_MBB=$PAT_HEAD$PAT_MBB 34MATCH[1]=${PAT_HEAD}0x05ac:0x023
33 35
34if [ -x /usr/sbin/lsusb ]; then 36if [ -x $LSUSB ]; then
35 if [ "lsusb|grep $PAT_MBA" != "" ]; then 37 if [ "`$LSUSB|grep ${PAT[0]}`" != "" ]; then
36 SED="s/#$MATCH_MBA/$MATCH_MBA/" 38 SED="s/#${MATCH[0]}/${MATCH[0]}/"
37 elif [ $has_mbb -gt 0 ]; then 39 elif [ "`$LSUSB|grep ${PAT[1]}`" != "" ]; then
38 SED="s/#$MATCH_MBP/$MATCH_MBP/" 40 SED="s/#${MATCH[1]}/${MATCH[1]}/"
39 else 41 else
40 echo No suitable device found 42 echo No suitable device found
41 exit 1 43 exit 1
diff --git a/scripts/bcm5974-pre-install b/scripts/bcm5974-pre-install
new file mode 100755
index 0000000..1e2b864
--- /dev/null
+++ b/scripts/bcm5974-pre-install
@@ -0,0 +1,42 @@
1#!/bin/bash
2#
3# bcm5943-pre-install - check system before installing the bcm5974
4#
5# Copyright (C) 2008 Henrik Rydberg (rydberg@euromail.se)
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20#
21
22DRIVER=bcm5974
23LSUSB=/usr/sbin/lsusb
24
25PAT[0]="05ac:022"
26PAT[1]="05ac:023"
27
28if [ -x $LSUSB ]; then
29 if [ "`$LSUSB|grep ${PAT[0]}`" != "" ]; then
30 exit 0
31 elif [ "`$LSUSB|grep ${PAT[1]}`" != "" ]; then
32 exit 0
33 else
34 echo bcm5974: no suitable device found
35 exit -1
36 fi
37else
38 echo bcm5974: cannot determine device type
39 exit -1
40fi
41
42exit 0