summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2008-10-08 23:13:06 +0200
committerHenrik Rydberg <rydberg@euromail.se>2008-10-08 23:13:06 +0200
commit563dae29cd97e8ab1428a4827bdef557ee6fd235 (patch)
tree7e5972ca3bbc0452fb47ff628f93aeef3a950e92
Initial import of bcm5974-0.42. Changelog from the absolute beginning:
bcm5974 (0.42) unstable; urgency=low * First button click registered. * Hooks pre/post-reset added. -- Henrik Rydberg <rydberg@euromail.se> Tue, 01 Jul 2008 20:59:39 +0200 bcm5974 (0.41) unstable; urgency=low * The reset_resume kernel function added. -- Henrik Rydberg <rydberg@euromail.se> Sun, 29 Jun 2008 20:59:39 +0200 bcm5974 (0.4) unstable; urgency=low * Both finger pressure and width reported. -- Henrik Rydberg <rydberg@euromail.se> Sun, 29 Jun 2008 18:59:39 +0200 bcm5974 (0.31) unstable; urgency=low * Administrative changes for kernel.org. -- Henrik Rydberg <rydberg@euromail.se> Fri, 27 Jun 2008 20:59:39 +0200 bcm5974 (0.3) unstable; urgency=low * Explicit device structure, use all packages. -- Henrik Rydberg <rydberg@euromail.se> Fri, 27 Jun 2008 18:59:39 +0200 bcm5974 (0.23) unstable; urgency=low * Finger release not reported properly. -- Henrik Rydberg <rydberg@euromail.se> Fri, 27 Jun 2008 17:59:39 +0200 bcm5974 (0.22) unstable; urgency=low * ABS coordinates more stable with synaptics. -- Henrik Rydberg <rydberg@euromail.se> Thu, 26 Jun 2008 20:59:39 +0200 bcm5974 (0.21) unstable; urgency=low * Fixed the relative coordinate scaling. -- Henrik Rydberg <rydberg@euromail.se> Wed, 25 Jun 2008 20:59:39 +0200 bcm5974 (0.2) unstable; urgency=low * Misinterpreted pressure input, noise reduction. -- Henrik Rydberg <rydberg@euromail.se> Wed, 25 Jun 2008 20:59:39 +0200 bcm5974 (0.1) unstable; urgency=low * First version. -- Henrik Rydberg <rydberg@euromail.se> Tue, 24 Jun 2008 20:59:39 +0200
-rw-r--r--LICENSE280
-rw-r--r--Makefile5
-rwxr-xr-xbcm5974-diagnostics203
-rw-r--r--bcm5974.c689
4 files changed, 1177 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..c7aea18
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,280 @@
1 GNU GENERAL PUBLIC LICENSE
2 Version 2, June 1991
3
4 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 675 Mass Ave, Cambridge, MA 02139, USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9 Preamble
10
11 The licenses for most software are designed to take away your
12freedom to share and change it. By contrast, the GNU General Public
13License is intended to guarantee your freedom to share and change free
14software--to make sure the software is free for all its users. This
15General Public License applies to most of the Free Software
16Foundation's software and to any other program whose authors commit to
17using it. (Some other Free Software Foundation software is covered by
18the GNU Library General Public License instead.) You can apply it to
19your programs, too.
20
21 When we speak of free software, we are referring to freedom, not
22price. Our General Public Licenses are designed to make sure that you
23have the freedom to distribute copies of free software (and charge for
24this service if you wish), that you receive source code or can get it
25if you want it, that you can change the software or use pieces of it
26in new free programs; and that you know you can do these things.
27
28 To protect your rights, we need to make restrictions that forbid
29anyone to deny you these rights or to ask you to surrender the rights.
30These restrictions translate to certain responsibilities for you if you
31distribute copies of the software, or if you modify it.
32
33 For example, if you distribute copies of such a program, whether
34gratis or for a fee, you must give the recipients all the rights that
35you have. You must make sure that they, too, receive or can get the
36source code. And you must show them these terms so they know their
37rights.
38
39 We protect your rights with two steps: (1) copyright the software, and
40(2) offer you this license which gives you legal permission to copy,
41distribute and/or modify the software.
42
43 Also, for each author's protection and ours, we want to make certain
44that everyone understands that there is no warranty for this free
45software. If the software is modified by someone else and passed on, we
46want its recipients to know that what they have is not the original, so
47that any problems introduced by others will not reflect on the original
48authors' reputations.
49
50 Finally, any free program is threatened constantly by software
51patents. We wish to avoid the danger that redistributors of a free
52program will individually obtain patent licenses, in effect making the
53program proprietary. To prevent this, we have made it clear that any
54patent must be licensed for everyone's free use or not licensed at all.
55
56 The precise terms and conditions for copying, distribution and
57modification follow.
58
59 GNU GENERAL PUBLIC LICENSE
60 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62 0. This License applies to any program or other work which contains
63a notice placed by the copyright holder saying it may be distributed
64under the terms of this General Public License. The "Program", below,
65refers to any such program or work, and a "work based on the Program"
66means either the Program or any derivative work under copyright law:
67that is to say, a work containing the Program or a portion of it,
68either verbatim or with modifications and/or translated into another
69language. (Hereinafter, translation is included without limitation in
70the term "modification".) Each licensee is addressed as "you".
71
72Activities other than copying, distribution and modification are not
73covered by this License; they are outside its scope. The act of
74running the Program is not restricted, and the output from the Program
75is covered only if its contents constitute a work based on the
76Program (independent of having been made by running the Program).
77Whether that is true depends on what the Program does.
78
79 1. You may copy and distribute verbatim copies of the Program's
80source code as you receive it, in any medium, provided that you
81conspicuously and appropriately publish on each copy an appropriate
82copyright notice and disclaimer of warranty; keep intact all the
83notices that refer to this License and to the absence of any warranty;
84and give any other recipients of the Program a copy of this License
85along with the Program.
86
87You may charge a fee for the physical act of transferring a copy, and
88you may at your option offer warranty protection in exchange for a fee.
89
90 2. You may modify your copy or copies of the Program or any portion
91of it, thus forming a work based on the Program, and copy and
92distribute such modifications or work under the terms of Section 1
93above, provided that you also meet all of these conditions:
94
95 a) You must cause the modified files to carry prominent notices
96 stating that you changed the files and the date of any change.
97
98 b) You must cause any work that you distribute or publish, that in
99 whole or in part contains or is derived from the Program or any
100 part thereof, to be licensed as a whole at no charge to all third
101 parties under the terms of this License.
102
103 c) If the modified program normally reads commands interactively
104 when run, you must cause it, when started running for such
105 interactive use in the most ordinary way, to print or display an
106 announcement including an appropriate copyright notice and a
107 notice that there is no warranty (or else, saying that you provide
108 a warranty) and that users may redistribute the program under
109 these conditions, and telling the user how to view a copy of this
110 License. (Exception: if the Program itself is interactive but
111 does not normally print such an announcement, your work based on
112 the Program is not required to print an announcement.)
113
114These requirements apply to the modified work as a whole. If
115identifiable sections of that work are not derived from the Program,
116and can be reasonably considered independent and separate works in
117themselves, then this License, and its terms, do not apply to those
118sections when you distribute them as separate works. But when you
119distribute the same sections as part of a whole which is a work based
120on the Program, the distribution of the whole must be on the terms of
121this License, whose permissions for other licensees extend to the
122entire whole, and thus to each and every part regardless of who wrote it.
123
124Thus, it is not the intent of this section to claim rights or contest
125your rights to work written entirely by you; rather, the intent is to
126exercise the right to control the distribution of derivative or
127collective works based on the Program.
128
129In addition, mere aggregation of another work not based on the Program
130with the Program (or with a work based on the Program) on a volume of
131a storage or distribution medium does not bring the other work under
132the scope of this License.
133
134 3. You may copy and distribute the Program (or a work based on it,
135under Section 2) in object code or executable form under the terms of
136Sections 1 and 2 above provided that you also do one of the following:
137
138 a) Accompany it with the complete corresponding machine-readable
139 source code, which must be distributed under the terms of Sections
140 1 and 2 above on a medium customarily used for software interchange; or,
141
142 b) Accompany it with a written offer, valid for at least three
143 years, to give any third party, for a charge no more than your
144 cost of physically performing source distribution, a complete
145 machine-readable copy of the corresponding source code, to be
146 distributed under the terms of Sections 1 and 2 above on a medium
147 customarily used for software interchange; or,
148
149 c) Accompany it with the information you received as to the offer
150 to distribute corresponding source code. (This alternative is
151 allowed only for noncommercial distribution and only if you
152 received the program in object code or executable form with such
153 an offer, in accord with Subsection b above.)
154
155The source code for a work means the preferred form of the work for
156making modifications to it. For an executable work, complete source
157code means all the source code for all modules it contains, plus any
158associated interface definition files, plus the scripts used to
159control compilation and installation of the executable. However, as a
160special exception, the source code distributed need not include
161anything that is normally distributed (in either source or binary
162form) with the major components (compiler, kernel, and so on) of the
163operating system on which the executable runs, unless that component
164itself accompanies the executable.
165
166If distribution of executable or object code is made by offering
167access to copy from a designated place, then offering equivalent
168access to copy the source code from the same place counts as
169distribution of the source code, even though third parties are not
170compelled to copy the source along with the object code.
171
172 4. You may not copy, modify, sublicense, or distribute the Program
173except as expressly provided under this License. Any attempt
174otherwise to copy, modify, sublicense or distribute the Program is
175void, and will automatically terminate your rights under this License.
176However, parties who have received copies, or rights, from you under
177this License will not have their licenses terminated so long as such
178parties remain in full compliance.
179
180 5. You are not required to accept this License, since you have not
181signed it. However, nothing else grants you permission to modify or
182distribute the Program or its derivative works. These actions are
183prohibited by law if you do not accept this License. Therefore, by
184modifying or distributing the Program (or any work based on the
185Program), you indicate your acceptance of this License to do so, and
186all its terms and conditions for copying, distributing or modifying
187the Program or works based on it.
188
189 6. Each time you redistribute the Program (or any work based on the
190Program), the recipient automatically receives a license from the
191original licensor to copy, distribute or modify the Program subject to
192these terms and conditions. You may not impose any further
193restrictions on the recipients' exercise of the rights granted herein.
194You are not responsible for enforcing compliance by third parties to
195this License.
196
197 7. If, as a consequence of a court judgment or allegation of patent
198infringement or for any other reason (not limited to patent issues),
199conditions are imposed on you (whether by court order, agreement or
200otherwise) that contradict the conditions of this License, they do not
201excuse you from the conditions of this License. If you cannot
202distribute so as to satisfy simultaneously your obligations under this
203License and any other pertinent obligations, then as a consequence you
204may not distribute the Program at all. For example, if a patent
205license would not permit royalty-free redistribution of the Program by
206all those who receive copies directly or indirectly through you, then
207the only way you could satisfy both it and this License would be to
208refrain entirely from distribution of the Program.
209
210If any portion of this section is held invalid or unenforceable under
211any particular circumstance, the balance of the section is intended to
212apply and the section as a whole is intended to apply in other
213circumstances.
214
215It is not the purpose of this section to induce you to infringe any
216patents or other property right claims or to contest validity of any
217such claims; this section has the sole purpose of protecting the
218integrity of the free software distribution system, which is
219implemented by public license practices. Many people have made
220generous contributions to the wide range of software distributed
221through that system in reliance on consistent application of that
222system; it is up to the author/donor to decide if he or she is willing
223to distribute software through any other system and a licensee cannot
224impose that choice.
225
226This section is intended to make thoroughly clear what is believed to
227be a consequence of the rest of this License.
228
229 8. If the distribution and/or use of the Program is restricted in
230certain countries either by patents or by copyrighted interfaces, the
231original copyright holder who places the Program under this License
232may add an explicit geographical distribution limitation excluding
233those countries, so that distribution is permitted only in or among
234countries not thus excluded. In such case, this License incorporates
235the limitation as if written in the body of this License.
236
237 9. The Free Software Foundation may publish revised and/or new versions
238of the General Public License from time to time. Such new versions will
239be similar in spirit to the present version, but may differ in detail to
240address new problems or concerns.
241
242Each version is given a distinguishing version number. If the Program
243specifies a version number of this License which applies to it and "any
244later version", you have the option of following the terms and conditions
245either of that version or of any later version published by the Free
246Software Foundation. If the Program does not specify a version number of
247this License, you may choose any version ever published by the Free Software
248Foundation.
249
250 10. If you wish to incorporate parts of the Program into other free
251programs whose distribution conditions are different, write to the author
252to ask for permission. For software which is copyrighted by the Free
253Software Foundation, write to the Free Software Foundation; we sometimes
254make exceptions for this. Our decision will be guided by the two goals
255of preserving the free status of all derivatives of our free software and
256of promoting the sharing and reuse of software generally.
257
258 NO WARRANTY
259
260 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268REPAIR OR CORRECTION.
269
270 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278POSSIBILITY OF SUCH DAMAGES.
279
280 END OF TERMS AND CONDITIONS
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..74335c8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for USB Network drivers
3#
4
5obj-m := bcm5974.o
diff --git a/bcm5974-diagnostics b/bcm5974-diagnostics
new file mode 100755
index 0000000..fa6a4ef
--- /dev/null
+++ b/bcm5974-diagnostics
@@ -0,0 +1,203 @@
1#!/bin/bash
2#
3# bcm5943-diagnostics - troubleshooting the BCM5974 setup
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
23
24echo -----------------------------------------------------------------------
25
26# What kernel version am I running?
27KERNEL=`uname -r`
28echo \* Kernel version: $KERNEL
29
30# What synaptics version is installed (debian)?
31if [ -x /usr/bin/dpkg-query ]; then
32 SYNAPTICS=`/usr/bin/dpkg-query -W -f='${Version}\n' xserver-xorg-input-synaptics`
33 echo \* Synaptics version: $SYNAPTICS
34else
35 echo \* Synaptics version: UNKNOWN - dpkg not found
36fi
37
38# What USB devices of interest can we find?
39if [ -x /usr/sbin/lsusb ]; then
40 LSUSB=`lsusb|grep -c 05ac:022`
41 echo \* USB device: $LSUSB
42else
43 echo \* USB device: UNKNOWN - lsusb not found
44fi
45
46# Do we have the module intalled?
47MODLIB=/lib/modules/$KERNEL/kernel/drivers/input/mouse/$DRIVER.ko
48if [ -f $MODLIB ]; then
49 echo \* $MODLIB: exists
50else
51 echo \* $MODLIB: does NOT exist
52 echo Copy the file $DRIVER.ko to $MODLIB
53 exit 1
54fi
55
56# Do we have the module configured?
57MODULES=/etc/modules
58if [ -f $MODULES ]; then
59 if (grep -q $DRIVER $MODULES); then
60 echo \* $MODULES: has $DRIVER
61 else
62 echo \* $MODULES: does NOT have $DRIVER
63 echo Add this line to $MODULES:
64 echo $DRIVER
65 exit 1
66 fi
67else
68 echo \* $MODULES: file not found
69 exit 1
70fi
71
72# Do we have the right quirks?
73MODPROBE=/etc/modprobe.d/options
74if [ -f $MODPROBE ]; then
75 MODPROBEOPTS=`grep quirks= $MODPROBE|grep -v ^#|grep 0x05ac:0x02`
76 if [ "$MODPROBEOPTS" != "" ]; then
77 echo \* $MODPROBE: has quirks
78 else
79 echo \* $MODPROBE: does NOT have quirks
80 echo Add this line to $MODPROBE:
81 echo -n options usbhid quirks=
82 (lsusb|grep -q 05ac:022) && echo 0x05ac:0x0223:0x00020800,0x05ac:0x0224:0x00024800,0x05ac:0x0225:0x00020800
83 (lsusb|grep -q 05ac:023) && echo 0x05ac:0x0230:0x00020800,0x05ac:0x0231:0x00024800,0x05ac:0x0232:0x00020800
84 exit 1
85 fi
86else
87 echo \* $MODPROBE: file not found
88 exit 1
89fi
90
91# Was the $DRIVER module loaded?
92DMESG=`lsmod|grep $DRIVER`
93if [ "$DMESG" != "" ]; then
94 echo \* $DRIVER: module is loaded
95else
96 echo \* $DRIVER: module is NOT loaded
97 echo Add this line to /etc/modules:
98 echo "$DRIVER"
99 exit 1
100fi
101
102# Was the $DRIVER properly initialized?
103WELLSPRING=`dmesg|grep $DRIVER|grep Wellspring`
104if [ "$WELLSPRING" != "" ]; then
105 echo \* $DRIVER: Wellspring was initialized
106else
107 echo \* $DRIVER: Wellspring was NOT initialized
108 exit 1
109fi
110
111# Do we have synaptics working properly?
112typeset -i SYNLINES=`synclient -l|wc -l`
113if [ $SYNLINES -gt 10 ]; then
114 echo \* synaptics: configuration readable
115else
116 echo \* synaptics: configuration NOT readable
117 exit 1
118fi
119
120# Do we have a working synaptics configuration?
121DIFF=/tmp/synclient-output.diff.$$
122TMP=/tmp/synclient-output.txt.$$
123synclient -l | sort > $TMP
124diff -u - $TMP > $DIFF <<EOF
125 AccelFactor = 0.1
126 BottomEdge = 800
127 CircScrollDelta = 0.1
128 CircScrollTrigger = 0
129 CircularPad = 0
130 CircularScrolling = 0
131 ClickTime = 100
132 CoastingSpeed = 0
133 CornerCoasting = 0
134 EdgeMotionMaxSpeed = 80
135 EdgeMotionMaxZ = 160
136 EdgeMotionMinSpeed = 1
137 EdgeMotionMinZ = 30
138 EdgeMotionUseAlways = 0
139 EmulateMidButtonTime = 75
140 EmulateTwoFingerMinZ = 257
141 FastTaps = 0
142 FingerHigh = 23
143 FingerLow = 16
144 FingerPress = 256
145 GrabEventDevice = 1
146 GuestMouseOff = 0
147 HorizEdgeScroll = 0
148 HorizScrollDelta = 0
149 HorizTwoFingerScroll = 1
150 LBCornerButton = 0
151 LeftEdge = 0
152 LeftRightScrolling = 1
153 LeftRightScrollRepeat = 1
154 LockedDrags = 0
155 LockedDragTimeout = 5000
156 LTCornerButton = 0
157 MaxDoubleTapTime = 200
158 MaxSpeed = 1.2
159 MaxTapMove = 100
160 MaxTapTime = 223
161 MinSpeed = 0.8
162 MultiFingerButton = 2
163 PalmDetect = 0
164 PalmMinWidth = 180
165 PalmMinZ = 10
166Parameter settings:
167 PressureMotionMaxFactor = 1
168 PressureMotionMaxZ = 160
169 PressureMotionMinFactor = 1
170 PressureMotionMinZ = 10
171 RBCornerButton = 0
172 RightEdge = 1280
173 RTCornerButton = 0
174 ScrollButtonRepeat = 100
175 SingleTapTimeout = 180
176 TapButton1 = 0
177 TapButton2 = 0
178 TapButton3 = 0
179 TopEdge = 0
180 TouchpadOff = 0
181 TrackstickSpeed = 40
182 UpDownScrolling = 1
183 UpDownScrollRepeat = 1
184 VertEdgeScroll = 0
185 VertScrollDelta = 40
186 VertTwoFingerScroll = 1
187EOF
188rm -f $TMP
189
190echo =======================================================================
191echo The bcm5974 seems properly configured
192
193typeset -i NDIFF=`cat $DIFF|wc -l`
194if [ $NDIFF -gt 0 ]; then
195 echo
196 echo Your synaptics settings differ from the bcm5974 default:
197 echo -----------------------------------------------------------------------
198 tail -n +4 $DIFF
199 echo -----------------------------------------------------------------------
200 echo If in doubt, please check your /etc/X11/xorg.conf settings
201fi
202
203rm -f $DIFF
diff --git a/bcm5974.c b/bcm5974.c
new file mode 100644
index 0000000..68f92c5
--- /dev/null
+++ b/bcm5974.c
@@ -0,0 +1,689 @@
1/*
2 * Apple USB BCM5974 (Macbook Air and Penryn Macbook Pro) multitouch driver
3 *
4 * Copyright (C) 2008 Henrik Rydberg (rydberg@euromail.se)
5 *
6 * The USB initialization and package decoding was made by
7 * Scott Shawcroft as part of the touchd user-space driver project:
8 * Copyright (C) 2008 Scott Shawcroft (scott.shawcroft@gmail.com)
9 *
10 * The BCM5974 driver is based on the appletouch driver:
11 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
12 * Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)
13 * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
14 * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
15 * Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
16 * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
17 * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch)
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 *
33 */
34
35#include <linux/kernel.h>
36#include <linux/errno.h>
37#include <linux/init.h>
38#include <linux/slab.h>
39#include <linux/module.h>
40#include <linux/usb/input.h>
41#include <linux/hid.h>
42
43#define APPLE_VENDOR_ID 0x05AC
44
45/* MacbookAir BCM5974, aka wellspring */
46
47#define ATP_WELLSPRING_ANSI 0x0223
48#define ATP_WELLSPRING_ISO 0x0224
49#define ATP_WELLSPRING_JIS 0x0225
50#define ATP_WELLSPRING2_ANSI 0x0230
51#define ATP_WELLSPRING2_ISO 0x0231
52#define ATP_WELLSPRING2_JIS 0x0232
53
54#define ATP_DEVICE(prod) { \
55 .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
56 USB_DEVICE_ID_MATCH_INT_CLASS | \
57 USB_DEVICE_ID_MATCH_INT_PROTOCOL), \
58 .idVendor = APPLE_VENDOR_ID, \
59 .idProduct = (prod), \
60 .bInterfaceClass = USB_INTERFACE_CLASS_HID, \
61 .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE \
62 }
63
64/* table of devices that work with this driver */
65static const struct usb_device_id atp_table [] = {
66 /* MacbookAir1.1 */
67 ATP_DEVICE(ATP_WELLSPRING_ANSI),
68 ATP_DEVICE(ATP_WELLSPRING_ISO),
69 ATP_DEVICE(ATP_WELLSPRING_JIS),
70
71 /* MacbookProPenryn */
72 ATP_DEVICE(ATP_WELLSPRING2_ANSI),
73 ATP_DEVICE(ATP_WELLSPRING2_ISO),
74 ATP_DEVICE(ATP_WELLSPRING2_JIS),
75
76 /* Terminating entry */
77 {}
78};
79MODULE_DEVICE_TABLE(usb, atp_table);
80
81struct atp_params_t {
82 int devmin; /* device minimum reading */
83 int devmax; /* device maximum reading */
84 int min; /* logical minimum reading */
85 int max; /* logical maximum reading */
86 int fuzz; /* reading noise value */
87 int flat; /* zero */
88};
89
90struct atp_config_t {
91 int ansi, iso, jis; /* the product id of this device */
92 int bt_ep; /* the endpoint of the button interface */
93 int bt_datalen; /* data length of the button interface */
94 int tp_ep; /* the endpoint of the trackpad interface */
95 int tp_datalen; /* data length of the trackpad interface */
96 struct atp_params_t x; /* horizontal limits */
97 struct atp_params_t y; /* vertical limits */
98 struct atp_params_t p; /* finger pressure limits */
99 struct atp_params_t w; /* finger width limits */
100};
101
102/* trackpad header structure */
103struct tp_header_t {
104 u8 unknown1[16]; /* constants, timers, etc */
105 u8 nfinger; /* number of fingers on trackpad */
106 u8 unknown2[9]; /* constants, timers, etc */
107};
108
109/* trackpad finger structure */
110struct tp_finger_t {
111 __le16 origin; /* left/right origin? */
112 __le16 abs_x; /* absolute x coodinate */
113 __le16 abs_y; /* absolute y coodinate */
114 __le16 rel_x; /* relative x coodinate */
115 __le16 rel_y; /* relative y coodinate */
116 __le16 size_major; /* finger size, major axis? */
117 __le16 size_minor; /* finger size, minor axis? */
118 __le16 orientation; /* 16384 when point, else 15 bit angle */
119 __le16 force_major; /* trackpad force, major axis? */
120 __le16 force_minor; /* trackpad force, minor axis? */
121 __le16 unused[3]; /* zeros */
122 __le16 multi; /* one finger: varies, more fingers: constant */
123};
124
125/* trackpad data structure */
126struct tp_data_t {
127 struct tp_header_t header;
128 struct tp_finger_t finger[16];
129};
130
131/* device constants */
132static const struct atp_config_t atp_config_table[] = {
133 {
134 ATP_WELLSPRING_ANSI,
135 ATP_WELLSPRING_ISO,
136 ATP_WELLSPRING_JIS,
137 0x84, 4,
138 0x81, sizeof(struct tp_data_t),
139 {-4824, 5342, 0, 1280, 16, 0},
140 {-172, 5820, 0, 800, 16, 0},
141 {0, 256, 0, 256, 16, 0},
142 {0, 2048, 0, 256, 16, 0}
143 },
144 {
145 ATP_WELLSPRING2_ANSI,
146 ATP_WELLSPRING2_ISO,
147 ATP_WELLSPRING2_JIS,
148 0x84, 4,
149 0x81, sizeof(struct tp_data_t),
150 {-4824, 5342, 0, 1280, 16, 0},
151 {-172, 5820, 0, 800, 16, 0},
152 {0, 256, 0, 256, 16, 0},
153 {0, 2048, 0, 256, 16, 0}
154 },
155 {}
156};
157
158static inline
159const struct atp_config_t *atp_product_config(struct usb_device *udev)
160{
161 u16 id = le16_to_cpu(udev->descriptor.idProduct);
162 const struct atp_config_t *config;
163 for (config = atp_config_table; config->ansi; ++config)
164 if (config->ansi == id || config->iso == id || config->jis == id)
165 return config;
166 return atp_config_table;
167}
168
169/* Wellspring initialization constants */
170#define ATP_WELLSPRING_MODE_READ_REQUEST_ID 1
171#define ATP_WELLSPRING_MODE_WRITE_REQUEST_ID 9
172#define ATP_WELLSPRING_MODE_REQUEST_VALUE 0x300
173#define ATP_WELLSPRING_MODE_REQUEST_INDEX 0
174#define ATP_WELLSPRING_MODE_VENDOR_VALUE_1 0x01
175#define ATP_WELLSPRING_MODE_VENDOR_VALUE_2 0x05
176
177#define dprintk(format, a...) \
178 { if (debug) printk(KERN_DEBUG format, ##a); }
179
180MODULE_AUTHOR("Henrik Rydberg");
181MODULE_DESCRIPTION("Apple USB BCM5974 multitouch driver");
182MODULE_LICENSE("GPL");
183
184static int debug = 1;
185module_param(debug, int, 0644);
186MODULE_PARM_DESC(debug, "Activate debugging output");
187
188static int atp_wellspring_init(struct usb_device *udev)
189{
190 const struct atp_config_t *cfg = atp_product_config(udev);
191 char *data = kmalloc(8, GFP_KERNEL);
192 int size;
193
194 /* reset button endpoint */
195 if (usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
196 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
197 0, cfg->bt_ep, NULL, 0, 5000)) {
198 err("Could not reset button endpoint");
199 goto error;
200 }
201
202 /* reset trackpad endpoint */
203 if (usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
204 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
205 0, cfg->tp_ep, NULL, 0, 5000)) {
206 err("Could not reset trackpad endpoint");
207 goto error;
208 }
209
210 /* read configuration */
211 size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
212 ATP_WELLSPRING_MODE_READ_REQUEST_ID,
213 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
214 ATP_WELLSPRING_MODE_REQUEST_VALUE,
215 ATP_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
216
217 if (size != 8) {
218 err("Could not do mode read request from device (Wellspring Raw mode)");
219 goto error;
220 }
221
222 /* apply the mode switch */
223 data[0] = ATP_WELLSPRING_MODE_VENDOR_VALUE_1;
224 data[1] = ATP_WELLSPRING_MODE_VENDOR_VALUE_2;
225
226 /* write configuration */
227 size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
228 ATP_WELLSPRING_MODE_WRITE_REQUEST_ID,
229 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
230 ATP_WELLSPRING_MODE_REQUEST_VALUE,
231 ATP_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
232
233 if (size != 8) {
234 err("Could not do mode write request to device (Wellspring Raw mode)");
235 goto error;
236 }
237
238 printk(KERN_INFO "bcm5974: Wellspring mode initialized.\n");
239
240 kfree(data);
241 return 0;
242
243 error:
244 kfree(data);
245 return -EIO;
246}
247
248/* Structure to hold all of our device specific stuff */
249struct atp {
250 char phys[64];
251 struct usb_device *udev; /* usb device */
252 struct input_dev *input; /* input dev */
253 struct atp_config_t cfg; /* device configuration */
254 int open; /* >0: open, else closed */
255 int suspended; /* >0: suspended, else open */
256 struct urb *bt_urb; /* button usb request block */
257 signed char *bt_data; /* button transferred data */
258 unsigned bt_state; /* current button state */
259 struct urb *tp_urb; /* trackpad usb request block */
260 signed char *tp_data; /* trackpad transferred data */
261 unsigned tp_valid; /* are the trackpad sensors valid ? */
262};
263
264static inline int raw2int(__le16 x)
265{
266 return (short)le16_to_cpu(x);
267}
268
269static inline int int2scale(const struct atp_params_t *p, int x)
270{
271 return ((p->max-p->min)*x)/(p->devmax-p->devmin);
272}
273
274/**
275 * all value ranges, both device and logical, are assumed to be [a,b).
276 */
277static inline int int2bound(const struct atp_params_t *p, int x)
278{
279 int s = p->min+int2scale(p, x);
280 return s < p->min?p->min:s >= p->max?p->max-1:s;
281}
282
283/**
284 * check quality of reading.
285 * -1: bad data
286 * 0: ignore this reading
287 * 1: good reading
288 */
289static int compute_quality(const unsigned char *data, int size)
290{
291 if (size < 26 || (size-26)%28 != 0)
292 return -1;
293
294 return 1;
295}
296
297/**
298 * convert raw data to synaptics sensor output.
299 * returns the number of fingers on the trackpad,
300 * or a negative number in vase of bad data.
301 */
302static int compute_movement(int *abs_x, int *abs_y,
303 int *rel_x, int *rel_y,
304 int *pressure, int *width,
305 struct atp_config_t *cfg,
306 const unsigned char *data, int size)
307{
308 const int nfinger = (size-26)/28;
309 const struct tp_data_t *tp = (struct tp_data_t *) data;
310
311 if (nfinger) {
312 *abs_x = int2bound(&cfg->x, raw2int(tp->finger->abs_x) - cfg->x.devmin);
313 *abs_y = int2bound(&cfg->y, cfg->y.devmax - raw2int(tp->finger->abs_y));
314 *rel_x = int2scale(&cfg->x, raw2int(tp->finger->rel_x));
315 *rel_y = int2scale(&cfg->y, -raw2int(tp->finger->rel_y));
316 *pressure = int2bound(&cfg->p, raw2int(tp->finger->force_major));
317 *width = int2bound(&cfg->w, raw2int(tp->finger->size_major));
318 } else {
319 *abs_x = 0;
320 *abs_y = 0;
321 *rel_x = 0;
322 *rel_y = 0;
323 *pressure = 0;
324 *width = 0;
325 }
326
327 /* report zero fingers for zero pressure */
328 return *pressure > 0?nfinger:0;
329}
330
331static void atp_button(struct urb *urb)
332{
333 struct atp *dev = urb->context;
334 int button, retval;
335
336 switch (urb->status) {
337 case 0:
338 break;
339 case -EOVERFLOW:
340 case -ECONNRESET:
341 case -ENOENT:
342 case -ESHUTDOWN:
343 dbg("bcm5974: button urb shutting down: %d", urb->status);
344 return;
345 default:
346 dbg("bcm5974: button urb status: %d", urb->status);
347 goto exit;
348 }
349
350 /* drop incomplete datasets */
351 if (dev->bt_urb->actual_length != 4) {
352 dprintk("bcm5974: incomplete button package (first byte: %d, length: %d)\n",
353 (int)dev->bt_data[0], dev->bt_urb->actual_length);
354 goto exit;
355 }
356
357 button = dev->bt_data[1];
358
359 /* only report button state changes */
360 if (button != dev->bt_state) {
361 input_report_key(dev->input, BTN_LEFT, button);
362 input_sync(dev->input);
363 }
364
365 dev->bt_state = button;
366
367 exit:
368 retval = usb_submit_urb(dev->bt_urb, GFP_ATOMIC);
369 if (retval)
370 err("bcm5974: button urb failed: %d", retval);
371}
372
373static void atp_trackpad(struct urb *urb)
374{
375 struct atp *dev = urb->context;
376 int abs_x, abs_y, rel_x, rel_y, pressure, width;
377 int quality, nfinger, retval;
378
379 switch (urb->status) {
380 case 0:
381 break;
382 case -EOVERFLOW:
383 case -ECONNRESET:
384 case -ENOENT:
385 case -ESHUTDOWN:
386 dbg("bcm5974: trackpad urb shutting down: %d", urb->status);
387 return;
388 default:
389 dbg("bcm5974: trackpad urb status: %d", urb->status);
390 goto exit;
391 }
392
393 /* first sample data ignored */
394 if (!dev->tp_valid) {
395 dev->tp_valid = 1;
396 goto exit;
397 }
398
399 /* determine quality of reading */
400 quality = compute_quality(dev->tp_data, dev->tp_urb->actual_length);
401
402 /* drop incomplete datasets */
403 if (quality < 0) {
404 dprintk("bcm5974: incomplete trackpad package "
405 "(first byte: %d, length: %d)\n",
406 (int)dev->tp_data[0], dev->tp_urb->actual_length);
407 goto exit;
408 }
409
410 /* drop poor quality readings */
411 if (quality == 0)
412 goto exit;
413
414 nfinger = compute_movement(&abs_x, &abs_y,
415 &rel_x, &rel_y,
416 &pressure, &width,
417 &dev->cfg,
418 dev->tp_data, dev->tp_urb->actual_length);
419
420 if (debug > 1) {
421 printk(KERN_DEBUG "bcm5974: x: %04d y: %04d "
422 "dx: %3d dy: %3d p: %3d w: %3d\n",
423 abs_x, abs_y, rel_x, rel_y, pressure, width);
424 }
425
426 input_report_abs(dev->input, ABS_X, abs_x);
427 input_report_abs(dev->input, ABS_Y, abs_y);
428 input_report_abs(dev->input, ABS_PRESSURE, pressure);
429 input_report_abs(dev->input, ABS_TOOL_WIDTH, width);
430 input_report_key(dev->input, BTN_TOOL_FINGER, nfinger == 1);
431 input_report_key(dev->input, BTN_TOOL_DOUBLETAP, nfinger == 2);
432 input_report_key(dev->input, BTN_TOOL_TRIPLETAP, nfinger > 2);
433 input_sync(dev->input);
434
435 exit:
436 retval = usb_submit_urb(dev->tp_urb, GFP_ATOMIC);
437 if (retval)
438 err("bcm5974: trackpad urb failed: %d", retval);
439}
440
441static int atp_open(struct input_dev *input)
442{
443 struct atp *dev = input_get_drvdata(input);
444
445 if (!dev->open) {
446 if (usb_submit_urb(dev->bt_urb, GFP_ATOMIC))
447 goto error;
448 if (usb_submit_urb(dev->tp_urb, GFP_ATOMIC))
449 goto err_free_bt_urb;
450 }
451
452 dev->open = 1;
453 dev->suspended = 0;
454 dev->tp_valid = 0;
455
456 return 0;
457
458 err_free_bt_urb:
459 usb_free_urb(dev->bt_urb);
460 error:
461 return -EIO;
462}
463
464static void atp_close(struct input_dev *input)
465{
466 struct atp *dev = input_get_drvdata(input);
467
468 if (dev->open && !dev->suspended) {
469 usb_kill_urb(dev->tp_urb);
470 usb_kill_urb(dev->bt_urb);
471 }
472
473 dev->open = 0;
474 dev->suspended = 0;
475}
476
477static int atp_probe(struct usb_interface *iface,
478 const struct usb_device_id *id)
479{
480 int error = -ENOMEM;
481 struct usb_device *udev = interface_to_usbdev(iface);
482 const struct atp_config_t *cfg;
483 struct atp *dev;
484 struct input_dev *input_dev;
485
486 printk(KERN_INFO "bcm5974: Probing device...\n");
487
488 /* find the product index */
489 cfg = atp_product_config(udev);
490
491 /* allocate memory for our device state and initialize it */
492 dev = kzalloc(sizeof(struct atp), GFP_KERNEL);
493 input_dev = input_allocate_device();
494 if (!dev || !input_dev) {
495 err("Out of memory");
496 goto err_free_devs;
497 }
498
499 dev->udev = udev;
500 dev->input = input_dev;
501 dev->cfg = *cfg;
502
503 /* switch to raw sensor mode */
504 if (atp_wellspring_init(udev))
505 goto err_free_devs;
506
507 dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL);
508 if (!dev->bt_urb)
509 goto err_free_devs;
510
511 dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL);
512 if (!dev->tp_urb)
513 goto err_free_bt_urb;
514
515 dev->bt_data = usb_buffer_alloc(dev->udev,
516 dev->cfg.bt_datalen,
517 GFP_KERNEL,
518 &dev->bt_urb->transfer_dma);
519 if (!dev->bt_data)
520 goto err_free_urb;
521
522 dev->tp_data = usb_buffer_alloc(dev->udev,
523 dev->cfg.tp_datalen,
524 GFP_KERNEL,
525 &dev->tp_urb->transfer_dma);
526 if (!dev->tp_data)
527 goto err_free_bt_buffer;
528
529 usb_fill_int_urb(dev->bt_urb, udev,
530 usb_rcvintpipe(udev, cfg->bt_ep),
531 dev->bt_data, dev->cfg.bt_datalen,
532 atp_button, dev, 1);
533
534 usb_fill_int_urb(dev->tp_urb, udev,
535 usb_rcvintpipe(udev, cfg->tp_ep),
536 dev->tp_data, dev->cfg.tp_datalen,
537 atp_trackpad, dev, 1);
538
539 usb_make_path(udev, dev->phys, sizeof(dev->phys));
540 strlcat(dev->phys, "/input0", sizeof(dev->phys));
541
542 input_dev->name = "bcm5974";
543 input_dev->phys = dev->phys;
544 usb_to_input_id(dev->udev, &input_dev->id);
545 input_dev->dev.parent = &iface->dev;
546
547 input_set_drvdata(input_dev, dev);
548
549 input_dev->open = atp_open;
550 input_dev->close = atp_close;
551
552 set_bit(EV_ABS, input_dev->evbit);
553 input_set_abs_params(input_dev, ABS_X,
554 cfg->x.min, cfg->x.max, cfg->x.fuzz, cfg->x.flat);
555 input_set_abs_params(input_dev, ABS_Y,
556 cfg->y.min, cfg->y.max, cfg->y.fuzz, cfg->y.flat);
557 input_set_abs_params(input_dev, ABS_PRESSURE,
558 cfg->p.min, cfg->p.max, cfg->p.fuzz, cfg->p.flat);
559 input_set_abs_params(input_dev, ABS_TOOL_WIDTH,
560 cfg->w.min, cfg->w.max, cfg->w.fuzz, cfg->w.flat);
561
562 set_bit(EV_KEY, input_dev->evbit);
563 set_bit(BTN_TOOL_FINGER, input_dev->keybit);
564 set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
565 set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
566 set_bit(BTN_LEFT, input_dev->keybit);
567
568 error = input_register_device(dev->input);
569 if (error)
570 goto err_free_buffer;
571
572 /* save our data pointer in this interface device */
573 usb_set_intfdata(iface, dev);
574
575 return 0;
576
577 err_free_buffer:
578 usb_buffer_free(dev->udev, dev->cfg.tp_datalen,
579 dev->tp_data, dev->tp_urb->transfer_dma);
580 err_free_bt_buffer:
581 usb_buffer_free(dev->udev, dev->cfg.bt_datalen,
582 dev->bt_data, dev->bt_urb->transfer_dma);
583 err_free_urb:
584 usb_free_urb(dev->tp_urb);
585 err_free_bt_urb:
586 usb_free_urb(dev->bt_urb);
587 err_free_devs:
588 usb_set_intfdata(iface, NULL);
589 kfree(dev);
590 input_free_device(input_dev);
591 return error;
592}
593
594static void atp_disconnect(struct usb_interface *iface)
595{
596 struct atp *dev = usb_get_intfdata(iface);
597
598 usb_set_intfdata(iface, NULL);
599 if (dev) {
600 input_unregister_device(dev->input);
601 usb_buffer_free(dev->udev, dev->cfg.tp_datalen,
602 dev->tp_data, dev->tp_urb->transfer_dma);
603 usb_buffer_free(dev->udev, dev->cfg.bt_datalen,
604 dev->bt_data, dev->bt_urb->transfer_dma);
605 usb_free_urb(dev->tp_urb);
606 usb_free_urb(dev->bt_urb);
607 kfree(dev);
608 }
609 printk(KERN_INFO "bcm5974: disconnected\n");
610}
611
612static int atp_suspend(struct usb_interface *iface, pm_message_t message)
613{
614 struct atp *dev = usb_get_intfdata(iface);
615
616 if (dev->open && !dev->suspended++) {
617 usb_kill_urb(dev->tp_urb);
618 usb_kill_urb(dev->bt_urb);
619 }
620
621 return 0;
622}
623
624static int atp_resume(struct usb_interface *iface)
625{
626 struct atp *dev = usb_get_intfdata(iface);
627
628 if (dev->open && !--dev->suspended) {
629 if (usb_submit_urb(dev->bt_urb, GFP_ATOMIC))
630 goto error;
631 if (usb_submit_urb(dev->tp_urb, GFP_ATOMIC))
632 goto err_free_bt_urb;
633 }
634
635 dev->tp_valid = 0;
636 return 0;
637
638 err_free_bt_urb:
639 usb_free_urb(dev->bt_urb);
640 error:
641 return -EIO;
642}
643
644static int atp_reset_resume(struct usb_interface *iface)
645{
646 struct atp *dev = usb_get_intfdata(iface);
647
648 if (dev->suspended == 1) {
649 if (atp_wellspring_init(dev->udev))
650 printk(KERN_INFO "bcm5974: warning: reset failed\n");
651 }
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}
665
666static struct usb_driver atp_driver = {
667 .name = "bcm5974",
668 .probe = atp_probe,
669 .disconnect = atp_disconnect,
670 .suspend = atp_suspend,
671 .resume = atp_resume,
672 .reset_resume = atp_reset_resume,
673 .pre_reset = atp_pre_reset,
674 .post_reset = atp_post_reset,
675 .id_table = atp_table,
676};
677
678static int __init atp_init(void)
679{
680 return usb_register(&atp_driver);
681}
682
683static void __exit atp_exit(void)
684{
685 usb_deregister(&atp_driver);
686}
687
688module_init(atp_init);
689module_exit(atp_exit);