Commit 56c381f93d57b88a3e667a2f55137947315c17e2
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input subsystem updates from Dmitry Torokhov: "Mostly small fixups to PS/2 tochpad drivers (ALPS, Elantech, Synaptics) to better deal with specific hardware" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: elantech - update the documentation Input: elantech - provide a sysfs knob for crc_enabled Input: elantech - report the middle button of the touchpad Input: alps - ignore bad data on Dell Latitudes E6440 and E7440 Input: alps - allow up to 2 invalid packets without resetting device Input: alps - ignore potential bare packets when device is out of sync Input: elantech - fix crc_enabled for Fujitsu H730 Input: elantech - use elantech_report_trackpoint for hardware v4 too Input: twl4030-pwrbutton - ensure a wakeup event is recorded. Input: synaptics - add min/max quirk for Lenovo T440s
Showing 5 changed files Inline Diff
Documentation/input/elantech.txt
1 | Elantech Touchpad Driver | 1 | Elantech Touchpad Driver |
2 | ======================== | 2 | ======================== |
3 | 3 | ||
4 | Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net> | 4 | Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net> |
5 | 5 | ||
6 | Extra information for hardware version 1 found and | 6 | Extra information for hardware version 1 found and |
7 | provided by Steve Havelka | 7 | provided by Steve Havelka |
8 | 8 | ||
9 | Version 2 (EeePC) hardware support based on patches | 9 | Version 2 (EeePC) hardware support based on patches |
10 | received from Woody at Xandros and forwarded to me | 10 | received from Woody at Xandros and forwarded to me |
11 | by user StewieGriffin at the eeeuser.com forum | 11 | by user StewieGriffin at the eeeuser.com forum |
12 | 12 | ||
13 | 13 | ||
14 | Contents | 14 | Contents |
15 | ~~~~~~~~ | 15 | ~~~~~~~~ |
16 | 16 | ||
17 | 1. Introduction | 17 | 1. Introduction |
18 | 2. Extra knobs | 18 | 2. Extra knobs |
19 | 3. Differentiating hardware versions | 19 | 3. Differentiating hardware versions |
20 | 4. Hardware version 1 | 20 | 4. Hardware version 1 |
21 | 4.1 Registers | 21 | 4.1 Registers |
22 | 4.2 Native relative mode 4 byte packet format | 22 | 4.2 Native relative mode 4 byte packet format |
23 | 4.3 Native absolute mode 4 byte packet format | 23 | 4.3 Native absolute mode 4 byte packet format |
24 | 5. Hardware version 2 | 24 | 5. Hardware version 2 |
25 | 5.1 Registers | 25 | 5.1 Registers |
26 | 5.2 Native absolute mode 6 byte packet format | 26 | 5.2 Native absolute mode 6 byte packet format |
27 | 5.2.1 Parity checking and packet re-synchronization | 27 | 5.2.1 Parity checking and packet re-synchronization |
28 | 5.2.2 One/Three finger touch | 28 | 5.2.2 One/Three finger touch |
29 | 5.2.3 Two finger touch | 29 | 5.2.3 Two finger touch |
30 | 6. Hardware version 3 | 30 | 6. Hardware version 3 |
31 | 6.1 Registers | 31 | 6.1 Registers |
32 | 6.2 Native absolute mode 6 byte packet format | 32 | 6.2 Native absolute mode 6 byte packet format |
33 | 6.2.1 One/Three finger touch | 33 | 6.2.1 One/Three finger touch |
34 | 6.2.2 Two finger touch | 34 | 6.2.2 Two finger touch |
35 | 7. Hardware version 4 | 35 | 7. Hardware version 4 |
36 | 7.1 Registers | 36 | 7.1 Registers |
37 | 7.2 Native absolute mode 6 byte packet format | 37 | 7.2 Native absolute mode 6 byte packet format |
38 | 7.2.1 Status packet | 38 | 7.2.1 Status packet |
39 | 7.2.2 Head packet | 39 | 7.2.2 Head packet |
40 | 7.2.3 Motion packet | 40 | 7.2.3 Motion packet |
41 | 8. Trackpoint (for Hardware version 3 and 4) | ||
42 | 8.1 Registers | ||
43 | 8.2 Native relative mode 6 byte packet format | ||
44 | 8.2.1 Status Packet | ||
41 | 45 | ||
42 | 46 | ||
43 | 47 | ||
44 | 1. Introduction | 48 | 1. Introduction |
45 | ~~~~~~~~~~~~ | 49 | ~~~~~~~~~~~~ |
46 | 50 | ||
47 | Currently the Linux Elantech touchpad driver is aware of two different | 51 | Currently the Linux Elantech touchpad driver is aware of four different |
48 | hardware versions unimaginatively called version 1 and version 2. Version 1 | 52 | hardware versions unimaginatively called version 1,version 2, version 3 |
49 | is found in "older" laptops and uses 4 bytes per packet. Version 2 seems to | 53 | and version 4. Version 1 is found in "older" laptops and uses 4 bytes per |
50 | be introduced with the EeePC and uses 6 bytes per packet, and provides | 54 | packet. Version 2 seems to be introduced with the EeePC and uses 6 bytes |
51 | additional features such as position of two fingers, and width of the touch. | 55 | per packet, and provides additional features such as position of two fingers, |
56 | and width of the touch. Hardware version 3 uses 6 bytes per packet (and | ||
57 | for 2 fingers the concatenation of two 6 bytes packets) and allows tracking | ||
58 | of up to 3 fingers. Hardware version 4 uses 6 bytes per packet, and can | ||
59 | combine a status packet with multiple head or motion packets. Hardware version | ||
60 | 4 allows tracking up to 5 fingers. | ||
52 | 61 | ||
62 | Some Hardware version 3 and version 4 also have a trackpoint which uses a | ||
63 | separate packet format. It is also 6 bytes per packet. | ||
64 | |||
53 | The driver tries to support both hardware versions and should be compatible | 65 | The driver tries to support both hardware versions and should be compatible |
54 | with the Xorg Synaptics touchpad driver and its graphical configuration | 66 | with the Xorg Synaptics touchpad driver and its graphical configuration |
55 | utilities. | 67 | utilities. |
56 | 68 | ||
69 | Note that a mouse button is also associated with either the touchpad or the | ||
70 | trackpoint when a trackpoint is available. Disabling the Touchpad in xorg | ||
71 | (TouchPadOff=0) will also disable the buttons associated with the touchpad. | ||
72 | |||
57 | Additionally the operation of the touchpad can be altered by adjusting the | 73 | Additionally the operation of the touchpad can be altered by adjusting the |
58 | contents of some of its internal registers. These registers are represented | 74 | contents of some of its internal registers. These registers are represented |
59 | by the driver as sysfs entries under /sys/bus/serio/drivers/psmouse/serio? | 75 | by the driver as sysfs entries under /sys/bus/serio/drivers/psmouse/serio? |
60 | that can be read from and written to. | 76 | that can be read from and written to. |
61 | 77 | ||
62 | Currently only the registers for hardware version 1 are somewhat understood. | 78 | Currently only the registers for hardware version 1 are somewhat understood. |
63 | Hardware version 2 seems to use some of the same registers but it is not | 79 | Hardware version 2 seems to use some of the same registers but it is not |
64 | known whether the bits in the registers represent the same thing or might | 80 | known whether the bits in the registers represent the same thing or might |
65 | have changed their meaning. | 81 | have changed their meaning. |
66 | 82 | ||
67 | On top of that, some register settings have effect only when the touchpad is | 83 | On top of that, some register settings have effect only when the touchpad is |
68 | in relative mode and not in absolute mode. As the Linux Elantech touchpad | 84 | in relative mode and not in absolute mode. As the Linux Elantech touchpad |
69 | driver always puts the hardware into absolute mode not all information | 85 | driver always puts the hardware into absolute mode not all information |
70 | mentioned below can be used immediately. But because there is no freely | 86 | mentioned below can be used immediately. But because there is no freely |
71 | available Elantech documentation the information is provided here anyway for | 87 | available Elantech documentation the information is provided here anyway for |
72 | completeness sake. | 88 | completeness sake. |
73 | 89 | ||
74 | 90 | ||
75 | ///////////////////////////////////////////////////////////////////////////// | 91 | ///////////////////////////////////////////////////////////////////////////// |
76 | 92 | ||
77 | 93 | ||
78 | 2. Extra knobs | 94 | 2. Extra knobs |
79 | ~~~~~~~~~~~ | 95 | ~~~~~~~~~~~ |
80 | 96 | ||
81 | Currently the Linux Elantech touchpad driver provides two extra knobs under | 97 | Currently the Linux Elantech touchpad driver provides three extra knobs under |
82 | /sys/bus/serio/drivers/psmouse/serio? for the user. | 98 | /sys/bus/serio/drivers/psmouse/serio? for the user. |
83 | 99 | ||
84 | * debug | 100 | * debug |
85 | 101 | ||
86 | Turn different levels of debugging ON or OFF. | 102 | Turn different levels of debugging ON or OFF. |
87 | 103 | ||
88 | By echoing "0" to this file all debugging will be turned OFF. | 104 | By echoing "0" to this file all debugging will be turned OFF. |
89 | 105 | ||
90 | Currently a value of "1" will turn on some basic debugging and a value of | 106 | Currently a value of "1" will turn on some basic debugging and a value of |
91 | "2" will turn on packet debugging. For hardware version 1 the default is | 107 | "2" will turn on packet debugging. For hardware version 1 the default is |
92 | OFF. For version 2 the default is "1". | 108 | OFF. For version 2 the default is "1". |
93 | 109 | ||
94 | Turning packet debugging on will make the driver dump every packet | 110 | Turning packet debugging on will make the driver dump every packet |
95 | received to the syslog before processing it. Be warned that this can | 111 | received to the syslog before processing it. Be warned that this can |
96 | generate quite a lot of data! | 112 | generate quite a lot of data! |
97 | 113 | ||
98 | * paritycheck | 114 | * paritycheck |
99 | 115 | ||
100 | Turns parity checking ON or OFF. | 116 | Turns parity checking ON or OFF. |
101 | 117 | ||
102 | By echoing "0" to this file parity checking will be turned OFF. Any | 118 | By echoing "0" to this file parity checking will be turned OFF. Any |
103 | non-zero value will turn it ON. For hardware version 1 the default is ON. | 119 | non-zero value will turn it ON. For hardware version 1 the default is ON. |
104 | For version 2 the default it is OFF. | 120 | For version 2 the default it is OFF. |
105 | 121 | ||
106 | Hardware version 1 provides basic data integrity verification by | 122 | Hardware version 1 provides basic data integrity verification by |
107 | calculating a parity bit for the last 3 bytes of each packet. The driver | 123 | calculating a parity bit for the last 3 bytes of each packet. The driver |
108 | can check these bits and reject any packet that appears corrupted. Using | 124 | can check these bits and reject any packet that appears corrupted. Using |
109 | this knob you can bypass that check. | 125 | this knob you can bypass that check. |
110 | 126 | ||
111 | Hardware version 2 does not provide the same parity bits. Only some basic | 127 | Hardware version 2 does not provide the same parity bits. Only some basic |
112 | data consistency checking can be done. For now checking is disabled by | 128 | data consistency checking can be done. For now checking is disabled by |
113 | default. Currently even turning it on will do nothing. | 129 | default. Currently even turning it on will do nothing. |
114 | 130 | ||
131 | * crc_enabled | ||
132 | |||
133 | Sets crc_enabled to 0/1. The name "crc_enabled" is the official name of | ||
134 | this integrity check, even though it is not an actual cyclic redundancy | ||
135 | check. | ||
136 | |||
137 | Depending on the state of crc_enabled, certain basic data integrity | ||
138 | verification is done by the driver on hardware version 3 and 4. The | ||
139 | driver will reject any packet that appears corrupted. Using this knob, | ||
140 | The state of crc_enabled can be altered with this knob. | ||
141 | |||
142 | Reading the crc_enabled value will show the active value. Echoing | ||
143 | "0" or "1" to this file will set the state to "0" or "1". | ||
144 | |||
115 | ///////////////////////////////////////////////////////////////////////////// | 145 | ///////////////////////////////////////////////////////////////////////////// |
116 | 146 | ||
117 | 3. Differentiating hardware versions | 147 | 3. Differentiating hardware versions |
118 | ================================= | 148 | ================================= |
119 | 149 | ||
120 | To detect the hardware version, read the version number as param[0].param[1].param[2] | 150 | To detect the hardware version, read the version number as param[0].param[1].param[2] |
121 | 151 | ||
122 | 4 bytes version: (after the arrow is the name given in the Dell-provided driver) | 152 | 4 bytes version: (after the arrow is the name given in the Dell-provided driver) |
123 | 02.00.22 => EF013 | 153 | 02.00.22 => EF013 |
124 | 02.06.00 => EF019 | 154 | 02.06.00 => EF019 |
125 | In the wild, there appear to be more versions, such as 00.01.64, 01.00.21, | 155 | In the wild, there appear to be more versions, such as 00.01.64, 01.00.21, |
126 | 02.00.00, 02.00.04, 02.00.06. | 156 | 02.00.00, 02.00.04, 02.00.06. |
127 | 157 | ||
128 | 6 bytes: | 158 | 6 bytes: |
129 | 02.00.30 => EF113 | 159 | 02.00.30 => EF113 |
130 | 02.08.00 => EF023 | 160 | 02.08.00 => EF023 |
131 | 02.08.XX => EF123 | 161 | 02.08.XX => EF123 |
132 | 02.0B.00 => EF215 | 162 | 02.0B.00 => EF215 |
133 | 04.01.XX => Scroll_EF051 | 163 | 04.01.XX => Scroll_EF051 |
134 | 04.02.XX => EF051 | 164 | 04.02.XX => EF051 |
135 | In the wild, there appear to be more versions, such as 04.03.01, 04.04.11. There | 165 | In the wild, there appear to be more versions, such as 04.03.01, 04.04.11. There |
136 | appears to be almost no difference, except for EF113, which does not report | 166 | appears to be almost no difference, except for EF113, which does not report |
137 | pressure/width and has different data consistency checks. | 167 | pressure/width and has different data consistency checks. |
138 | 168 | ||
139 | Probably all the versions with param[0] <= 01 can be considered as | 169 | Probably all the versions with param[0] <= 01 can be considered as |
140 | 4 bytes/firmware 1. The versions < 02.08.00, with the exception of 02.00.30, as | 170 | 4 bytes/firmware 1. The versions < 02.08.00, with the exception of 02.00.30, as |
141 | 4 bytes/firmware 2. Everything >= 02.08.00 can be considered as 6 bytes. | 171 | 4 bytes/firmware 2. Everything >= 02.08.00 can be considered as 6 bytes. |
142 | 172 | ||
143 | ///////////////////////////////////////////////////////////////////////////// | 173 | ///////////////////////////////////////////////////////////////////////////// |
144 | 174 | ||
145 | 4. Hardware version 1 | 175 | 4. Hardware version 1 |
146 | ================== | 176 | ================== |
147 | 177 | ||
148 | 4.1 Registers | 178 | 4.1 Registers |
149 | ~~~~~~~~~ | 179 | ~~~~~~~~~ |
150 | 180 | ||
151 | By echoing a hexadecimal value to a register it contents can be altered. | 181 | By echoing a hexadecimal value to a register it contents can be altered. |
152 | 182 | ||
153 | For example: | 183 | For example: |
154 | 184 | ||
155 | echo -n 0x16 > reg_10 | 185 | echo -n 0x16 > reg_10 |
156 | 186 | ||
157 | * reg_10 | 187 | * reg_10 |
158 | 188 | ||
159 | bit 7 6 5 4 3 2 1 0 | 189 | bit 7 6 5 4 3 2 1 0 |
160 | B C T D L A S E | 190 | B C T D L A S E |
161 | 191 | ||
162 | E: 1 = enable smart edges unconditionally | 192 | E: 1 = enable smart edges unconditionally |
163 | S: 1 = enable smart edges only when dragging | 193 | S: 1 = enable smart edges only when dragging |
164 | A: 1 = absolute mode (needs 4 byte packets, see reg_11) | 194 | A: 1 = absolute mode (needs 4 byte packets, see reg_11) |
165 | L: 1 = enable drag lock (see reg_22) | 195 | L: 1 = enable drag lock (see reg_22) |
166 | D: 1 = disable dynamic resolution | 196 | D: 1 = disable dynamic resolution |
167 | T: 1 = disable tapping | 197 | T: 1 = disable tapping |
168 | C: 1 = enable corner tap | 198 | C: 1 = enable corner tap |
169 | B: 1 = swap left and right button | 199 | B: 1 = swap left and right button |
170 | 200 | ||
171 | * reg_11 | 201 | * reg_11 |
172 | 202 | ||
173 | bit 7 6 5 4 3 2 1 0 | 203 | bit 7 6 5 4 3 2 1 0 |
174 | 1 0 0 H V 1 F P | 204 | 1 0 0 H V 1 F P |
175 | 205 | ||
176 | P: 1 = enable parity checking for relative mode | 206 | P: 1 = enable parity checking for relative mode |
177 | F: 1 = enable native 4 byte packet mode | 207 | F: 1 = enable native 4 byte packet mode |
178 | V: 1 = enable vertical scroll area | 208 | V: 1 = enable vertical scroll area |
179 | H: 1 = enable horizontal scroll area | 209 | H: 1 = enable horizontal scroll area |
180 | 210 | ||
181 | * reg_20 | 211 | * reg_20 |
182 | 212 | ||
183 | single finger width? | 213 | single finger width? |
184 | 214 | ||
185 | * reg_21 | 215 | * reg_21 |
186 | 216 | ||
187 | scroll area width (small: 0x40 ... wide: 0xff) | 217 | scroll area width (small: 0x40 ... wide: 0xff) |
188 | 218 | ||
189 | * reg_22 | 219 | * reg_22 |
190 | 220 | ||
191 | drag lock time out (short: 0x14 ... long: 0xfe; | 221 | drag lock time out (short: 0x14 ... long: 0xfe; |
192 | 0xff = tap again to release) | 222 | 0xff = tap again to release) |
193 | 223 | ||
194 | * reg_23 | 224 | * reg_23 |
195 | 225 | ||
196 | tap make timeout? | 226 | tap make timeout? |
197 | 227 | ||
198 | * reg_24 | 228 | * reg_24 |
199 | 229 | ||
200 | tap release timeout? | 230 | tap release timeout? |
201 | 231 | ||
202 | * reg_25 | 232 | * reg_25 |
203 | 233 | ||
204 | smart edge cursor speed (0x02 = slow, 0x03 = medium, 0x04 = fast) | 234 | smart edge cursor speed (0x02 = slow, 0x03 = medium, 0x04 = fast) |
205 | 235 | ||
206 | * reg_26 | 236 | * reg_26 |
207 | 237 | ||
208 | smart edge activation area width? | 238 | smart edge activation area width? |
209 | 239 | ||
210 | 240 | ||
211 | 4.2 Native relative mode 4 byte packet format | 241 | 4.2 Native relative mode 4 byte packet format |
212 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 242 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
213 | 243 | ||
214 | byte 0: | 244 | byte 0: |
215 | bit 7 6 5 4 3 2 1 0 | 245 | bit 7 6 5 4 3 2 1 0 |
216 | c c p2 p1 1 M R L | 246 | c c p2 p1 1 M R L |
217 | 247 | ||
218 | L, R, M = 1 when Left, Right, Middle mouse button pressed | 248 | L, R, M = 1 when Left, Right, Middle mouse button pressed |
219 | some models have M as byte 3 odd parity bit | 249 | some models have M as byte 3 odd parity bit |
220 | when parity checking is enabled (reg_11, P = 1): | 250 | when parity checking is enabled (reg_11, P = 1): |
221 | p1..p2 = byte 1 and 2 odd parity bit | 251 | p1..p2 = byte 1 and 2 odd parity bit |
222 | c = 1 when corner tap detected | 252 | c = 1 when corner tap detected |
223 | 253 | ||
224 | byte 1: | 254 | byte 1: |
225 | bit 7 6 5 4 3 2 1 0 | 255 | bit 7 6 5 4 3 2 1 0 |
226 | dx7 dx6 dx5 dx4 dx3 dx2 dx1 dx0 | 256 | dx7 dx6 dx5 dx4 dx3 dx2 dx1 dx0 |
227 | 257 | ||
228 | dx7..dx0 = x movement; positive = right, negative = left | 258 | dx7..dx0 = x movement; positive = right, negative = left |
229 | byte 1 = 0xf0 when corner tap detected | 259 | byte 1 = 0xf0 when corner tap detected |
230 | 260 | ||
231 | byte 2: | 261 | byte 2: |
232 | bit 7 6 5 4 3 2 1 0 | 262 | bit 7 6 5 4 3 2 1 0 |
233 | dy7 dy6 dy5 dy4 dy3 dy2 dy1 dy0 | 263 | dy7 dy6 dy5 dy4 dy3 dy2 dy1 dy0 |
234 | 264 | ||
235 | dy7..dy0 = y movement; positive = up, negative = down | 265 | dy7..dy0 = y movement; positive = up, negative = down |
236 | 266 | ||
237 | byte 3: | 267 | byte 3: |
238 | parity checking enabled (reg_11, P = 1): | 268 | parity checking enabled (reg_11, P = 1): |
239 | 269 | ||
240 | bit 7 6 5 4 3 2 1 0 | 270 | bit 7 6 5 4 3 2 1 0 |
241 | w h n1 n0 ds3 ds2 ds1 ds0 | 271 | w h n1 n0 ds3 ds2 ds1 ds0 |
242 | 272 | ||
243 | normally: | 273 | normally: |
244 | ds3..ds0 = scroll wheel amount and direction | 274 | ds3..ds0 = scroll wheel amount and direction |
245 | positive = down or left | 275 | positive = down or left |
246 | negative = up or right | 276 | negative = up or right |
247 | when corner tap detected: | 277 | when corner tap detected: |
248 | ds0 = 1 when top right corner tapped | 278 | ds0 = 1 when top right corner tapped |
249 | ds1 = 1 when bottom right corner tapped | 279 | ds1 = 1 when bottom right corner tapped |
250 | ds2 = 1 when bottom left corner tapped | 280 | ds2 = 1 when bottom left corner tapped |
251 | ds3 = 1 when top left corner tapped | 281 | ds3 = 1 when top left corner tapped |
252 | n1..n0 = number of fingers on touchpad | 282 | n1..n0 = number of fingers on touchpad |
253 | only models with firmware 2.x report this, models with | 283 | only models with firmware 2.x report this, models with |
254 | firmware 1.x seem to map one, two and three finger taps | 284 | firmware 1.x seem to map one, two and three finger taps |
255 | directly to L, M and R mouse buttons | 285 | directly to L, M and R mouse buttons |
256 | h = 1 when horizontal scroll action | 286 | h = 1 when horizontal scroll action |
257 | w = 1 when wide finger touch? | 287 | w = 1 when wide finger touch? |
258 | 288 | ||
259 | otherwise (reg_11, P = 0): | 289 | otherwise (reg_11, P = 0): |
260 | 290 | ||
261 | bit 7 6 5 4 3 2 1 0 | 291 | bit 7 6 5 4 3 2 1 0 |
262 | ds7 ds6 ds5 ds4 ds3 ds2 ds1 ds0 | 292 | ds7 ds6 ds5 ds4 ds3 ds2 ds1 ds0 |
263 | 293 | ||
264 | ds7..ds0 = vertical scroll amount and direction | 294 | ds7..ds0 = vertical scroll amount and direction |
265 | negative = up | 295 | negative = up |
266 | positive = down | 296 | positive = down |
267 | 297 | ||
268 | 298 | ||
269 | 4.3 Native absolute mode 4 byte packet format | 299 | 4.3 Native absolute mode 4 byte packet format |
270 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 300 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
271 | 301 | ||
272 | EF013 and EF019 have a special behaviour (due to a bug in the firmware?), and | 302 | EF013 and EF019 have a special behaviour (due to a bug in the firmware?), and |
273 | when 1 finger is touching, the first 2 position reports must be discarded. | 303 | when 1 finger is touching, the first 2 position reports must be discarded. |
274 | This counting is reset whenever a different number of fingers is reported. | 304 | This counting is reset whenever a different number of fingers is reported. |
275 | 305 | ||
276 | byte 0: | 306 | byte 0: |
277 | firmware version 1.x: | 307 | firmware version 1.x: |
278 | 308 | ||
279 | bit 7 6 5 4 3 2 1 0 | 309 | bit 7 6 5 4 3 2 1 0 |
280 | D U p1 p2 1 p3 R L | 310 | D U p1 p2 1 p3 R L |
281 | 311 | ||
282 | L, R = 1 when Left, Right mouse button pressed | 312 | L, R = 1 when Left, Right mouse button pressed |
283 | p1..p3 = byte 1..3 odd parity bit | 313 | p1..p3 = byte 1..3 odd parity bit |
284 | D, U = 1 when rocker switch pressed Up, Down | 314 | D, U = 1 when rocker switch pressed Up, Down |
285 | 315 | ||
286 | firmware version 2.x: | 316 | firmware version 2.x: |
287 | 317 | ||
288 | bit 7 6 5 4 3 2 1 0 | 318 | bit 7 6 5 4 3 2 1 0 |
289 | n1 n0 p2 p1 1 p3 R L | 319 | n1 n0 p2 p1 1 p3 R L |
290 | 320 | ||
291 | L, R = 1 when Left, Right mouse button pressed | 321 | L, R = 1 when Left, Right mouse button pressed |
292 | p1..p3 = byte 1..3 odd parity bit | 322 | p1..p3 = byte 1..3 odd parity bit |
293 | n1..n0 = number of fingers on touchpad | 323 | n1..n0 = number of fingers on touchpad |
294 | 324 | ||
295 | byte 1: | 325 | byte 1: |
296 | firmware version 1.x: | 326 | firmware version 1.x: |
297 | 327 | ||
298 | bit 7 6 5 4 3 2 1 0 | 328 | bit 7 6 5 4 3 2 1 0 |
299 | f 0 th tw x9 x8 y9 y8 | 329 | f 0 th tw x9 x8 y9 y8 |
300 | 330 | ||
301 | tw = 1 when two finger touch | 331 | tw = 1 when two finger touch |
302 | th = 1 when three finger touch | 332 | th = 1 when three finger touch |
303 | f = 1 when finger touch | 333 | f = 1 when finger touch |
304 | 334 | ||
305 | firmware version 2.x: | 335 | firmware version 2.x: |
306 | 336 | ||
307 | bit 7 6 5 4 3 2 1 0 | 337 | bit 7 6 5 4 3 2 1 0 |
308 | . . . . x9 x8 y9 y8 | 338 | . . . . x9 x8 y9 y8 |
309 | 339 | ||
310 | byte 2: | 340 | byte 2: |
311 | bit 7 6 5 4 3 2 1 0 | 341 | bit 7 6 5 4 3 2 1 0 |
312 | x7 x6 x5 x4 x3 x2 x1 x0 | 342 | x7 x6 x5 x4 x3 x2 x1 x0 |
313 | 343 | ||
314 | x9..x0 = absolute x value (horizontal) | 344 | x9..x0 = absolute x value (horizontal) |
315 | 345 | ||
316 | byte 3: | 346 | byte 3: |
317 | bit 7 6 5 4 3 2 1 0 | 347 | bit 7 6 5 4 3 2 1 0 |
318 | y7 y6 y5 y4 y3 y2 y1 y0 | 348 | y7 y6 y5 y4 y3 y2 y1 y0 |
319 | 349 | ||
320 | y9..y0 = absolute y value (vertical) | 350 | y9..y0 = absolute y value (vertical) |
321 | 351 | ||
322 | 352 | ||
323 | ///////////////////////////////////////////////////////////////////////////// | 353 | ///////////////////////////////////////////////////////////////////////////// |
324 | 354 | ||
325 | 355 | ||
326 | 5. Hardware version 2 | 356 | 5. Hardware version 2 |
327 | ================== | 357 | ================== |
328 | 358 | ||
329 | 359 | ||
330 | 5.1 Registers | 360 | 5.1 Registers |
331 | ~~~~~~~~~ | 361 | ~~~~~~~~~ |
332 | 362 | ||
333 | By echoing a hexadecimal value to a register it contents can be altered. | 363 | By echoing a hexadecimal value to a register it contents can be altered. |
334 | 364 | ||
335 | For example: | 365 | For example: |
336 | 366 | ||
337 | echo -n 0x56 > reg_10 | 367 | echo -n 0x56 > reg_10 |
338 | 368 | ||
339 | * reg_10 | 369 | * reg_10 |
340 | 370 | ||
341 | bit 7 6 5 4 3 2 1 0 | 371 | bit 7 6 5 4 3 2 1 0 |
342 | 0 1 0 1 0 1 D 0 | 372 | 0 1 0 1 0 1 D 0 |
343 | 373 | ||
344 | D: 1 = enable drag and drop | 374 | D: 1 = enable drag and drop |
345 | 375 | ||
346 | * reg_11 | 376 | * reg_11 |
347 | 377 | ||
348 | bit 7 6 5 4 3 2 1 0 | 378 | bit 7 6 5 4 3 2 1 0 |
349 | 1 0 0 0 S 0 1 0 | 379 | 1 0 0 0 S 0 1 0 |
350 | 380 | ||
351 | S: 1 = enable vertical scroll | 381 | S: 1 = enable vertical scroll |
352 | 382 | ||
353 | * reg_21 | 383 | * reg_21 |
354 | 384 | ||
355 | unknown (0x00) | 385 | unknown (0x00) |
356 | 386 | ||
357 | * reg_22 | 387 | * reg_22 |
358 | 388 | ||
359 | drag and drop release time out (short: 0x70 ... long 0x7e; | 389 | drag and drop release time out (short: 0x70 ... long 0x7e; |
360 | 0x7f = never i.e. tap again to release) | 390 | 0x7f = never i.e. tap again to release) |
361 | 391 | ||
362 | 392 | ||
363 | 5.2 Native absolute mode 6 byte packet format | 393 | 5.2 Native absolute mode 6 byte packet format |
364 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 394 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
365 | 5.2.1 Parity checking and packet re-synchronization | 395 | 5.2.1 Parity checking and packet re-synchronization |
366 | There is no parity checking, however some consistency checks can be performed. | 396 | There is no parity checking, however some consistency checks can be performed. |
367 | 397 | ||
368 | For instance for EF113: | 398 | For instance for EF113: |
369 | SA1= packet[0]; | 399 | SA1= packet[0]; |
370 | A1 = packet[1]; | 400 | A1 = packet[1]; |
371 | B1 = packet[2]; | 401 | B1 = packet[2]; |
372 | SB1= packet[3]; | 402 | SB1= packet[3]; |
373 | C1 = packet[4]; | 403 | C1 = packet[4]; |
374 | D1 = packet[5]; | 404 | D1 = packet[5]; |
375 | if( (((SA1 & 0x3C) != 0x3C) && ((SA1 & 0xC0) != 0x80)) || // check Byte 1 | 405 | if( (((SA1 & 0x3C) != 0x3C) && ((SA1 & 0xC0) != 0x80)) || // check Byte 1 |
376 | (((SA1 & 0x0C) != 0x0C) && ((SA1 & 0xC0) == 0x80)) || // check Byte 1 (one finger pressed) | 406 | (((SA1 & 0x0C) != 0x0C) && ((SA1 & 0xC0) == 0x80)) || // check Byte 1 (one finger pressed) |
377 | (((SA1 & 0xC0) != 0x80) && (( A1 & 0xF0) != 0x00)) || // check Byte 2 | 407 | (((SA1 & 0xC0) != 0x80) && (( A1 & 0xF0) != 0x00)) || // check Byte 2 |
378 | (((SB1 & 0x3E) != 0x38) && ((SA1 & 0xC0) != 0x80)) || // check Byte 4 | 408 | (((SB1 & 0x3E) != 0x38) && ((SA1 & 0xC0) != 0x80)) || // check Byte 4 |
379 | (((SB1 & 0x0E) != 0x08) && ((SA1 & 0xC0) == 0x80)) || // check Byte 4 (one finger pressed) | 409 | (((SB1 & 0x0E) != 0x08) && ((SA1 & 0xC0) == 0x80)) || // check Byte 4 (one finger pressed) |
380 | (((SA1 & 0xC0) != 0x80) && (( C1 & 0xF0) != 0x00)) ) // check Byte 5 | 410 | (((SA1 & 0xC0) != 0x80) && (( C1 & 0xF0) != 0x00)) ) // check Byte 5 |
381 | // error detected | 411 | // error detected |
382 | 412 | ||
383 | For all the other ones, there are just a few constant bits: | 413 | For all the other ones, there are just a few constant bits: |
384 | if( ((packet[0] & 0x0C) != 0x04) || | 414 | if( ((packet[0] & 0x0C) != 0x04) || |
385 | ((packet[3] & 0x0f) != 0x02) ) | 415 | ((packet[3] & 0x0f) != 0x02) ) |
386 | // error detected | 416 | // error detected |
387 | 417 | ||
388 | 418 | ||
389 | In case an error is detected, all the packets are shifted by one (and packet[0] is discarded). | 419 | In case an error is detected, all the packets are shifted by one (and packet[0] is discarded). |
390 | 420 | ||
391 | 5.2.2 One/Three finger touch | 421 | 5.2.2 One/Three finger touch |
392 | ~~~~~~~~~~~~~~~~ | 422 | ~~~~~~~~~~~~~~~~ |
393 | 423 | ||
394 | byte 0: | 424 | byte 0: |
395 | 425 | ||
396 | bit 7 6 5 4 3 2 1 0 | 426 | bit 7 6 5 4 3 2 1 0 |
397 | n1 n0 w3 w2 . . R L | 427 | n1 n0 w3 w2 . . R L |
398 | 428 | ||
399 | L, R = 1 when Left, Right mouse button pressed | 429 | L, R = 1 when Left, Right mouse button pressed |
400 | n1..n0 = number of fingers on touchpad | 430 | n1..n0 = number of fingers on touchpad |
401 | 431 | ||
402 | byte 1: | 432 | byte 1: |
403 | 433 | ||
404 | bit 7 6 5 4 3 2 1 0 | 434 | bit 7 6 5 4 3 2 1 0 |
405 | p7 p6 p5 p4 x11 x10 x9 x8 | 435 | p7 p6 p5 p4 x11 x10 x9 x8 |
406 | 436 | ||
407 | byte 2: | 437 | byte 2: |
408 | 438 | ||
409 | bit 7 6 5 4 3 2 1 0 | 439 | bit 7 6 5 4 3 2 1 0 |
410 | x7 x6 x5 x4 x3 x2 x1 x0 | 440 | x7 x6 x5 x4 x3 x2 x1 x0 |
411 | 441 | ||
412 | x11..x0 = absolute x value (horizontal) | 442 | x11..x0 = absolute x value (horizontal) |
413 | 443 | ||
414 | byte 3: | 444 | byte 3: |
415 | 445 | ||
416 | bit 7 6 5 4 3 2 1 0 | 446 | bit 7 6 5 4 3 2 1 0 |
417 | n4 vf w1 w0 . . . b2 | 447 | n4 vf w1 w0 . . . b2 |
418 | 448 | ||
419 | n4 = set if more than 3 fingers (only in 3 fingers mode) | 449 | n4 = set if more than 3 fingers (only in 3 fingers mode) |
420 | vf = a kind of flag ? (only on EF123, 0 when finger is over one | 450 | vf = a kind of flag ? (only on EF123, 0 when finger is over one |
421 | of the buttons, 1 otherwise) | 451 | of the buttons, 1 otherwise) |
422 | w3..w0 = width of the finger touch (not EF113) | 452 | w3..w0 = width of the finger touch (not EF113) |
423 | b2 (on EF113 only, 0 otherwise), b2.R.L indicates one button pressed: | 453 | b2 (on EF113 only, 0 otherwise), b2.R.L indicates one button pressed: |
424 | 0 = none | 454 | 0 = none |
425 | 1 = Left | 455 | 1 = Left |
426 | 2 = Right | 456 | 2 = Right |
427 | 3 = Middle (Left and Right) | 457 | 3 = Middle (Left and Right) |
428 | 4 = Forward | 458 | 4 = Forward |
429 | 5 = Back | 459 | 5 = Back |
430 | 6 = Another one | 460 | 6 = Another one |
431 | 7 = Another one | 461 | 7 = Another one |
432 | 462 | ||
433 | byte 4: | 463 | byte 4: |
434 | 464 | ||
435 | bit 7 6 5 4 3 2 1 0 | 465 | bit 7 6 5 4 3 2 1 0 |
436 | p3 p1 p2 p0 y11 y10 y9 y8 | 466 | p3 p1 p2 p0 y11 y10 y9 y8 |
437 | 467 | ||
438 | p7..p0 = pressure (not EF113) | 468 | p7..p0 = pressure (not EF113) |
439 | 469 | ||
440 | byte 5: | 470 | byte 5: |
441 | 471 | ||
442 | bit 7 6 5 4 3 2 1 0 | 472 | bit 7 6 5 4 3 2 1 0 |
443 | y7 y6 y5 y4 y3 y2 y1 y0 | 473 | y7 y6 y5 y4 y3 y2 y1 y0 |
444 | 474 | ||
445 | y11..y0 = absolute y value (vertical) | 475 | y11..y0 = absolute y value (vertical) |
446 | 476 | ||
447 | 477 | ||
448 | 5.2.3 Two finger touch | 478 | 5.2.3 Two finger touch |
449 | ~~~~~~~~~~~~~~~~ | 479 | ~~~~~~~~~~~~~~~~ |
450 | 480 | ||
451 | Note that the two pairs of coordinates are not exactly the coordinates of the | 481 | Note that the two pairs of coordinates are not exactly the coordinates of the |
452 | two fingers, but only the pair of the lower-left and upper-right coordinates. | 482 | two fingers, but only the pair of the lower-left and upper-right coordinates. |
453 | So the actual fingers might be situated on the other diagonal of the square | 483 | So the actual fingers might be situated on the other diagonal of the square |
454 | defined by these two points. | 484 | defined by these two points. |
455 | 485 | ||
456 | byte 0: | 486 | byte 0: |
457 | 487 | ||
458 | bit 7 6 5 4 3 2 1 0 | 488 | bit 7 6 5 4 3 2 1 0 |
459 | n1 n0 ay8 ax8 . . R L | 489 | n1 n0 ay8 ax8 . . R L |
460 | 490 | ||
461 | L, R = 1 when Left, Right mouse button pressed | 491 | L, R = 1 when Left, Right mouse button pressed |
462 | n1..n0 = number of fingers on touchpad | 492 | n1..n0 = number of fingers on touchpad |
463 | 493 | ||
464 | byte 1: | 494 | byte 1: |
465 | 495 | ||
466 | bit 7 6 5 4 3 2 1 0 | 496 | bit 7 6 5 4 3 2 1 0 |
467 | ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 | 497 | ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 |
468 | 498 | ||
469 | ax8..ax0 = lower-left finger absolute x value | 499 | ax8..ax0 = lower-left finger absolute x value |
470 | 500 | ||
471 | byte 2: | 501 | byte 2: |
472 | 502 | ||
473 | bit 7 6 5 4 3 2 1 0 | 503 | bit 7 6 5 4 3 2 1 0 |
474 | ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 | 504 | ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 |
475 | 505 | ||
476 | ay8..ay0 = lower-left finger absolute y value | 506 | ay8..ay0 = lower-left finger absolute y value |
477 | 507 | ||
478 | byte 3: | 508 | byte 3: |
479 | 509 | ||
480 | bit 7 6 5 4 3 2 1 0 | 510 | bit 7 6 5 4 3 2 1 0 |
481 | . . by8 bx8 . . . . | 511 | . . by8 bx8 . . . . |
482 | 512 | ||
483 | byte 4: | 513 | byte 4: |
484 | 514 | ||
485 | bit 7 6 5 4 3 2 1 0 | 515 | bit 7 6 5 4 3 2 1 0 |
486 | bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 | 516 | bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 |
487 | 517 | ||
488 | bx8..bx0 = upper-right finger absolute x value | 518 | bx8..bx0 = upper-right finger absolute x value |
489 | 519 | ||
490 | byte 5: | 520 | byte 5: |
491 | 521 | ||
492 | bit 7 6 5 4 3 2 1 0 | 522 | bit 7 6 5 4 3 2 1 0 |
493 | by7 by8 by5 by4 by3 by2 by1 by0 | 523 | by7 by8 by5 by4 by3 by2 by1 by0 |
494 | 524 | ||
495 | by8..by0 = upper-right finger absolute y value | 525 | by8..by0 = upper-right finger absolute y value |
496 | 526 | ||
497 | ///////////////////////////////////////////////////////////////////////////// | 527 | ///////////////////////////////////////////////////////////////////////////// |
498 | 528 | ||
499 | 6. Hardware version 3 | 529 | 6. Hardware version 3 |
500 | ================== | 530 | ================== |
501 | 531 | ||
502 | 6.1 Registers | 532 | 6.1 Registers |
503 | ~~~~~~~~~ | 533 | ~~~~~~~~~ |
504 | * reg_10 | 534 | * reg_10 |
505 | 535 | ||
506 | bit 7 6 5 4 3 2 1 0 | 536 | bit 7 6 5 4 3 2 1 0 |
507 | 0 0 0 0 R F T A | 537 | 0 0 0 0 R F T A |
508 | 538 | ||
509 | A: 1 = enable absolute tracking | 539 | A: 1 = enable absolute tracking |
510 | T: 1 = enable two finger mode auto correct | 540 | T: 1 = enable two finger mode auto correct |
511 | F: 1 = disable ABS Position Filter | 541 | F: 1 = disable ABS Position Filter |
512 | R: 1 = enable real hardware resolution | 542 | R: 1 = enable real hardware resolution |
513 | 543 | ||
514 | 6.2 Native absolute mode 6 byte packet format | 544 | 6.2 Native absolute mode 6 byte packet format |
515 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 545 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
516 | 1 and 3 finger touch shares the same 6-byte packet format, except that | 546 | 1 and 3 finger touch shares the same 6-byte packet format, except that |
517 | 3 finger touch only reports the position of the center of all three fingers. | 547 | 3 finger touch only reports the position of the center of all three fingers. |
518 | 548 | ||
519 | Firmware would send 12 bytes of data for 2 finger touch. | 549 | Firmware would send 12 bytes of data for 2 finger touch. |
520 | 550 | ||
521 | Note on debounce: | 551 | Note on debounce: |
522 | In case the box has unstable power supply or other electricity issues, or | 552 | In case the box has unstable power supply or other electricity issues, or |
523 | when number of finger changes, F/W would send "debounce packet" to inform | 553 | when number of finger changes, F/W would send "debounce packet" to inform |
524 | driver that the hardware is in debounce status. | 554 | driver that the hardware is in debounce status. |
525 | The debouce packet has the following signature: | 555 | The debouce packet has the following signature: |
526 | byte 0: 0xc4 | 556 | byte 0: 0xc4 |
527 | byte 1: 0xff | 557 | byte 1: 0xff |
528 | byte 2: 0xff | 558 | byte 2: 0xff |
529 | byte 3: 0x02 | 559 | byte 3: 0x02 |
530 | byte 4: 0xff | 560 | byte 4: 0xff |
531 | byte 5: 0xff | 561 | byte 5: 0xff |
532 | When we encounter this kind of packet, we just ignore it. | 562 | When we encounter this kind of packet, we just ignore it. |
533 | 563 | ||
534 | 6.2.1 One/Three finger touch | 564 | 6.2.1 One/Three finger touch |
535 | ~~~~~~~~~~~~~~~~~~~~~~ | 565 | ~~~~~~~~~~~~~~~~~~~~~~ |
536 | 566 | ||
537 | byte 0: | 567 | byte 0: |
538 | 568 | ||
539 | bit 7 6 5 4 3 2 1 0 | 569 | bit 7 6 5 4 3 2 1 0 |
540 | n1 n0 w3 w2 0 1 R L | 570 | n1 n0 w3 w2 0 1 R L |
541 | 571 | ||
542 | L, R = 1 when Left, Right mouse button pressed | 572 | L, R = 1 when Left, Right mouse button pressed |
543 | n1..n0 = number of fingers on touchpad | 573 | n1..n0 = number of fingers on touchpad |
544 | 574 | ||
545 | byte 1: | 575 | byte 1: |
546 | 576 | ||
547 | bit 7 6 5 4 3 2 1 0 | 577 | bit 7 6 5 4 3 2 1 0 |
548 | p7 p6 p5 p4 x11 x10 x9 x8 | 578 | p7 p6 p5 p4 x11 x10 x9 x8 |
549 | 579 | ||
550 | byte 2: | 580 | byte 2: |
551 | 581 | ||
552 | bit 7 6 5 4 3 2 1 0 | 582 | bit 7 6 5 4 3 2 1 0 |
553 | x7 x6 x5 x4 x3 x2 x1 x0 | 583 | x7 x6 x5 x4 x3 x2 x1 x0 |
554 | 584 | ||
555 | x11..x0 = absolute x value (horizontal) | 585 | x11..x0 = absolute x value (horizontal) |
556 | 586 | ||
557 | byte 3: | 587 | byte 3: |
558 | 588 | ||
559 | bit 7 6 5 4 3 2 1 0 | 589 | bit 7 6 5 4 3 2 1 0 |
560 | 0 0 w1 w0 0 0 1 0 | 590 | 0 0 w1 w0 0 0 1 0 |
561 | 591 | ||
562 | w3..w0 = width of the finger touch | 592 | w3..w0 = width of the finger touch |
563 | 593 | ||
564 | byte 4: | 594 | byte 4: |
565 | 595 | ||
566 | bit 7 6 5 4 3 2 1 0 | 596 | bit 7 6 5 4 3 2 1 0 |
567 | p3 p1 p2 p0 y11 y10 y9 y8 | 597 | p3 p1 p2 p0 y11 y10 y9 y8 |
568 | 598 | ||
569 | p7..p0 = pressure | 599 | p7..p0 = pressure |
570 | 600 | ||
571 | byte 5: | 601 | byte 5: |
572 | 602 | ||
573 | bit 7 6 5 4 3 2 1 0 | 603 | bit 7 6 5 4 3 2 1 0 |
574 | y7 y6 y5 y4 y3 y2 y1 y0 | 604 | y7 y6 y5 y4 y3 y2 y1 y0 |
575 | 605 | ||
576 | y11..y0 = absolute y value (vertical) | 606 | y11..y0 = absolute y value (vertical) |
577 | 607 | ||
578 | 6.2.2 Two finger touch | 608 | 6.2.2 Two finger touch |
579 | ~~~~~~~~~~~~~~~~ | 609 | ~~~~~~~~~~~~~~~~ |
580 | 610 | ||
581 | The packet format is exactly the same for two finger touch, except the hardware | 611 | The packet format is exactly the same for two finger touch, except the hardware |
582 | sends two 6 byte packets. The first packet contains data for the first finger, | 612 | sends two 6 byte packets. The first packet contains data for the first finger, |
583 | the second packet has data for the second finger. So for two finger touch a | 613 | the second packet has data for the second finger. So for two finger touch a |
584 | total of 12 bytes are sent. | 614 | total of 12 bytes are sent. |
585 | 615 | ||
586 | ///////////////////////////////////////////////////////////////////////////// | 616 | ///////////////////////////////////////////////////////////////////////////// |
587 | 617 | ||
588 | 7. Hardware version 4 | 618 | 7. Hardware version 4 |
589 | ================== | 619 | ================== |
590 | 620 | ||
591 | 7.1 Registers | 621 | 7.1 Registers |
592 | ~~~~~~~~~ | 622 | ~~~~~~~~~ |
593 | * reg_07 | 623 | * reg_07 |
594 | 624 | ||
595 | bit 7 6 5 4 3 2 1 0 | 625 | bit 7 6 5 4 3 2 1 0 |
596 | 0 0 0 0 0 0 0 A | 626 | 0 0 0 0 0 0 0 A |
597 | 627 | ||
598 | A: 1 = enable absolute tracking | 628 | A: 1 = enable absolute tracking |
599 | 629 | ||
600 | 7.2 Native absolute mode 6 byte packet format | 630 | 7.2 Native absolute mode 6 byte packet format |
601 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 631 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
602 | v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers. | 632 | v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers. |
603 | Unfortunately, due to PS/2's limited bandwidth, its packet format is rather | 633 | Unfortunately, due to PS/2's limited bandwidth, its packet format is rather |
604 | complex. | 634 | complex. |
605 | 635 | ||
606 | Whenever the numbers or identities of the fingers changes, the hardware sends a | 636 | Whenever the numbers or identities of the fingers changes, the hardware sends a |
607 | status packet to indicate how many and which fingers is on touchpad, followed by | 637 | status packet to indicate how many and which fingers is on touchpad, followed by |
608 | head packets or motion packets. A head packet contains data of finger id, finger | 638 | head packets or motion packets. A head packet contains data of finger id, finger |
609 | position (absolute x, y values), width, and pressure. A motion packet contains | 639 | position (absolute x, y values), width, and pressure. A motion packet contains |
610 | two fingers' position delta. | 640 | two fingers' position delta. |
611 | 641 | ||
612 | For example, when status packet tells there are 2 fingers on touchpad, then we | 642 | For example, when status packet tells there are 2 fingers on touchpad, then we |
613 | can expect two following head packets. If the finger status doesn't change, | 643 | can expect two following head packets. If the finger status doesn't change, |
614 | the following packets would be motion packets, only sending delta of finger | 644 | the following packets would be motion packets, only sending delta of finger |
615 | position, until we receive a status packet. | 645 | position, until we receive a status packet. |
616 | 646 | ||
617 | One exception is one finger touch. when a status packet tells us there is only | 647 | One exception is one finger touch. when a status packet tells us there is only |
618 | one finger, the hardware would just send head packets afterwards. | 648 | one finger, the hardware would just send head packets afterwards. |
619 | 649 | ||
620 | 7.2.1 Status packet | 650 | 7.2.1 Status packet |
621 | ~~~~~~~~~~~~~ | 651 | ~~~~~~~~~~~~~ |
622 | 652 | ||
623 | byte 0: | 653 | byte 0: |
624 | 654 | ||
625 | bit 7 6 5 4 3 2 1 0 | 655 | bit 7 6 5 4 3 2 1 0 |
626 | . . . . 0 1 R L | 656 | . . . . 0 1 R L |
627 | 657 | ||
628 | L, R = 1 when Left, Right mouse button pressed | 658 | L, R = 1 when Left, Right mouse button pressed |
629 | 659 | ||
630 | byte 1: | 660 | byte 1: |
631 | 661 | ||
632 | bit 7 6 5 4 3 2 1 0 | 662 | bit 7 6 5 4 3 2 1 0 |
633 | . . . ft4 ft3 ft2 ft1 ft0 | 663 | . . . ft4 ft3 ft2 ft1 ft0 |
634 | 664 | ||
635 | ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad | 665 | ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad |
636 | 666 | ||
637 | byte 2: not used | 667 | byte 2: not used |
638 | 668 | ||
639 | byte 3: | 669 | byte 3: |
640 | 670 | ||
641 | bit 7 6 5 4 3 2 1 0 | 671 | bit 7 6 5 4 3 2 1 0 |
642 | . . . 1 0 0 0 0 | 672 | . . . 1 0 0 0 0 |
643 | 673 | ||
644 | constant bits | 674 | constant bits |
645 | 675 | ||
646 | byte 4: | 676 | byte 4: |
647 | 677 | ||
648 | bit 7 6 5 4 3 2 1 0 | 678 | bit 7 6 5 4 3 2 1 0 |
649 | p . . . . . . . | 679 | p . . . . . . . |
650 | 680 | ||
651 | p = 1 for palm | 681 | p = 1 for palm |
652 | 682 | ||
653 | byte 5: not used | 683 | byte 5: not used |
654 | 684 | ||
655 | 7.2.2 Head packet | 685 | 7.2.2 Head packet |
656 | ~~~~~~~~~~~ | 686 | ~~~~~~~~~~~ |
657 | 687 | ||
658 | byte 0: | 688 | byte 0: |
659 | 689 | ||
660 | bit 7 6 5 4 3 2 1 0 | 690 | bit 7 6 5 4 3 2 1 0 |
661 | w3 w2 w1 w0 0 1 R L | 691 | w3 w2 w1 w0 0 1 R L |
662 | 692 | ||
663 | L, R = 1 when Left, Right mouse button pressed | 693 | L, R = 1 when Left, Right mouse button pressed |
664 | w3..w0 = finger width (spans how many trace lines) | 694 | w3..w0 = finger width (spans how many trace lines) |
665 | 695 | ||
666 | byte 1: | 696 | byte 1: |
667 | 697 | ||
668 | bit 7 6 5 4 3 2 1 0 | 698 | bit 7 6 5 4 3 2 1 0 |
669 | p7 p6 p5 p4 x11 x10 x9 x8 | 699 | p7 p6 p5 p4 x11 x10 x9 x8 |
670 | 700 | ||
671 | byte 2: | 701 | byte 2: |
672 | 702 | ||
673 | bit 7 6 5 4 3 2 1 0 | 703 | bit 7 6 5 4 3 2 1 0 |
674 | x7 x6 x5 x4 x3 x2 x1 x0 | 704 | x7 x6 x5 x4 x3 x2 x1 x0 |
675 | 705 | ||
676 | x11..x0 = absolute x value (horizontal) | 706 | x11..x0 = absolute x value (horizontal) |
677 | 707 | ||
678 | byte 3: | 708 | byte 3: |
679 | 709 | ||
680 | bit 7 6 5 4 3 2 1 0 | 710 | bit 7 6 5 4 3 2 1 0 |
681 | id2 id1 id0 1 0 0 0 1 | 711 | id2 id1 id0 1 0 0 0 1 |
682 | 712 | ||
683 | id2..id0 = finger id | 713 | id2..id0 = finger id |
684 | 714 | ||
685 | byte 4: | 715 | byte 4: |
686 | 716 | ||
687 | bit 7 6 5 4 3 2 1 0 | 717 | bit 7 6 5 4 3 2 1 0 |
688 | p3 p1 p2 p0 y11 y10 y9 y8 | 718 | p3 p1 p2 p0 y11 y10 y9 y8 |
689 | 719 | ||
690 | p7..p0 = pressure | 720 | p7..p0 = pressure |
691 | 721 | ||
692 | byte 5: | 722 | byte 5: |
693 | 723 | ||
694 | bit 7 6 5 4 3 2 1 0 | 724 | bit 7 6 5 4 3 2 1 0 |
695 | y7 y6 y5 y4 y3 y2 y1 y0 | 725 | y7 y6 y5 y4 y3 y2 y1 y0 |
696 | 726 | ||
697 | y11..y0 = absolute y value (vertical) | 727 | y11..y0 = absolute y value (vertical) |
698 | 728 | ||
699 | 7.2.3 Motion packet | 729 | 7.2.3 Motion packet |
700 | ~~~~~~~~~~~~~ | 730 | ~~~~~~~~~~~~~ |
701 | 731 | ||
702 | byte 0: | 732 | byte 0: |
703 | 733 | ||
704 | bit 7 6 5 4 3 2 1 0 | 734 | bit 7 6 5 4 3 2 1 0 |
705 | id2 id1 id0 w 0 1 R L | 735 | id2 id1 id0 w 0 1 R L |
706 | 736 | ||
707 | L, R = 1 when Left, Right mouse button pressed | 737 | L, R = 1 when Left, Right mouse button pressed |
708 | id2..id0 = finger id | 738 | id2..id0 = finger id |
709 | w = 1 when delta overflows (> 127 or < -128), in this case | 739 | w = 1 when delta overflows (> 127 or < -128), in this case |
710 | firmware sends us (delta x / 5) and (delta y / 5) | 740 | firmware sends us (delta x / 5) and (delta y / 5) |
711 | 741 | ||
712 | byte 1: | 742 | byte 1: |
713 | 743 | ||
714 | bit 7 6 5 4 3 2 1 0 | 744 | bit 7 6 5 4 3 2 1 0 |
715 | x7 x6 x5 x4 x3 x2 x1 x0 | 745 | x7 x6 x5 x4 x3 x2 x1 x0 |
716 | 746 | ||
717 | x7..x0 = delta x (two's complement) | 747 | x7..x0 = delta x (two's complement) |
718 | 748 | ||
719 | byte 2: | 749 | byte 2: |
720 | 750 | ||
721 | bit 7 6 5 4 3 2 1 0 | 751 | bit 7 6 5 4 3 2 1 0 |
722 | y7 y6 y5 y4 y3 y2 y1 y0 | 752 | y7 y6 y5 y4 y3 y2 y1 y0 |
723 | 753 | ||
724 | y7..y0 = delta y (two's complement) | 754 | y7..y0 = delta y (two's complement) |
725 | 755 | ||
726 | byte 3: | 756 | byte 3: |
727 | 757 | ||
728 | bit 7 6 5 4 3 2 1 0 | 758 | bit 7 6 5 4 3 2 1 0 |
729 | id2 id1 id0 1 0 0 1 0 | 759 | id2 id1 id0 1 0 0 1 0 |
730 | 760 | ||
731 | id2..id0 = finger id | 761 | id2..id0 = finger id |
732 | 762 | ||
733 | byte 4: | 763 | byte 4: |
734 | 764 | ||
735 | bit 7 6 5 4 3 2 1 0 | 765 | bit 7 6 5 4 3 2 1 0 |
736 | x7 x6 x5 x4 x3 x2 x1 x0 | 766 | x7 x6 x5 x4 x3 x2 x1 x0 |
737 | 767 | ||
738 | x7..x0 = delta x (two's complement) | 768 | x7..x0 = delta x (two's complement) |
739 | 769 | ||
740 | byte 5: | 770 | byte 5: |
741 | 771 | ||
742 | bit 7 6 5 4 3 2 1 0 | 772 | bit 7 6 5 4 3 2 1 0 |
743 | y7 y6 y5 y4 y3 y2 y1 y0 | 773 | y7 y6 y5 y4 y3 y2 y1 y0 |
744 | 774 | ||
745 | y7..y0 = delta y (two's complement) | 775 | y7..y0 = delta y (two's complement) |
746 | 776 | ||
747 | byte 0 ~ 2 for one finger | 777 | byte 0 ~ 2 for one finger |
748 | byte 3 ~ 5 for another | 778 | byte 3 ~ 5 for another |
779 | |||
780 | |||
781 | 8. Trackpoint (for Hardware version 3 and 4) | ||
782 | ========================================= | ||
783 | 8.1 Registers | ||
784 | ~~~~~~~~~ | ||
785 | No special registers have been identified. | ||
786 | |||
787 | 8.2 Native relative mode 6 byte packet format | ||
788 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
789 | 8.2.1 Status Packet | ||
790 | ~~~~~~~~~~~~~ | ||
791 | |||
792 | byte 0: | ||
793 | bit 7 6 5 4 3 2 1 0 | ||
794 | 0 0 sx sy 0 M R L | ||
795 | byte 1: | ||
796 | bit 7 6 5 4 3 2 1 0 | ||
797 | ~sx 0 0 0 0 0 0 0 | ||
798 | byte 2: | ||
799 | bit 7 6 5 4 3 2 1 0 | ||
800 | ~sy 0 0 0 0 0 0 0 | ||
801 | byte 3: | ||
802 | bit 7 6 5 4 3 2 1 0 | ||
803 | 0 0 ~sy ~sx 0 1 1 0 | ||
804 | byte 4: | ||
805 | bit 7 6 5 4 3 2 1 0 | ||
806 | x7 x6 x5 x4 x3 x2 x1 x0 | ||
807 | byte 5: | ||
808 | bit 7 6 5 4 3 2 1 0 | ||
809 | y7 y6 y5 y4 y3 y2 y1 y0 | ||
810 | |||
811 | |||
812 | x and y are written in two's complement spread | ||
813 | over 9 bits with sx/sy the relative top bit and | ||
814 | x7..x0 and y7..y0 the lower bits. | ||
815 | ~sx is the inverse of sx, ~sy is the inverse of sy. | ||
816 | The sign of y is opposite to what the input driver | ||
817 | expects for a relative movement | ||
749 | 818 |
drivers/input/misc/twl4030-pwrbutton.c
1 | /** | 1 | /** |
2 | * twl4030-pwrbutton.c - TWL4030 Power Button Input Driver | 2 | * twl4030-pwrbutton.c - TWL4030 Power Button Input Driver |
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Nokia Corporation | 4 | * Copyright (C) 2008-2009 Nokia Corporation |
5 | * | 5 | * |
6 | * Written by Peter De Schrijver <peter.de-schrijver@nokia.com> | 6 | * Written by Peter De Schrijver <peter.de-schrijver@nokia.com> |
7 | * Several fixes by Felipe Balbi <felipe.balbi@nokia.com> | 7 | * Several fixes by Felipe Balbi <felipe.balbi@nokia.com> |
8 | * | 8 | * |
9 | * This file is subject to the terms and conditions of the GNU General | 9 | * This file is subject to the terms and conditions of the GNU General |
10 | * Public License. See the file "COPYING" in the main directory of this | 10 | * Public License. See the file "COPYING" in the main directory of this |
11 | * archive for more details. | 11 | * archive for more details. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
27 | #include <linux/input.h> | 27 | #include <linux/input.h> |
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
30 | #include <linux/i2c/twl.h> | 30 | #include <linux/i2c/twl.h> |
31 | 31 | ||
32 | #define PWR_PWRON_IRQ (1 << 0) | 32 | #define PWR_PWRON_IRQ (1 << 0) |
33 | 33 | ||
34 | #define STS_HW_CONDITIONS 0xf | 34 | #define STS_HW_CONDITIONS 0xf |
35 | 35 | ||
36 | static irqreturn_t powerbutton_irq(int irq, void *_pwr) | 36 | static irqreturn_t powerbutton_irq(int irq, void *_pwr) |
37 | { | 37 | { |
38 | struct input_dev *pwr = _pwr; | 38 | struct input_dev *pwr = _pwr; |
39 | int err; | 39 | int err; |
40 | u8 value; | 40 | u8 value; |
41 | 41 | ||
42 | err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &value, STS_HW_CONDITIONS); | 42 | err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &value, STS_HW_CONDITIONS); |
43 | if (!err) { | 43 | if (!err) { |
44 | pm_wakeup_event(pwr->dev.parent, 0); | 44 | pm_wakeup_event(pwr->dev.parent, 0); |
45 | input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); | 45 | input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); |
46 | input_sync(pwr); | 46 | input_sync(pwr); |
47 | } else { | 47 | } else { |
48 | dev_err(pwr->dev.parent, "twl4030: i2c error %d while reading" | 48 | dev_err(pwr->dev.parent, "twl4030: i2c error %d while reading" |
49 | " TWL4030 PM_MASTER STS_HW_CONDITIONS register\n", err); | 49 | " TWL4030 PM_MASTER STS_HW_CONDITIONS register\n", err); |
50 | } | 50 | } |
51 | 51 | ||
52 | return IRQ_HANDLED; | 52 | return IRQ_HANDLED; |
53 | } | 53 | } |
54 | 54 | ||
55 | static int twl4030_pwrbutton_probe(struct platform_device *pdev) | 55 | static int twl4030_pwrbutton_probe(struct platform_device *pdev) |
56 | { | 56 | { |
57 | struct input_dev *pwr; | 57 | struct input_dev *pwr; |
58 | int irq = platform_get_irq(pdev, 0); | 58 | int irq = platform_get_irq(pdev, 0); |
59 | int err; | 59 | int err; |
60 | 60 | ||
61 | pwr = devm_input_allocate_device(&pdev->dev); | 61 | pwr = devm_input_allocate_device(&pdev->dev); |
62 | if (!pwr) { | 62 | if (!pwr) { |
63 | dev_err(&pdev->dev, "Can't allocate power button\n"); | 63 | dev_err(&pdev->dev, "Can't allocate power button\n"); |
64 | return -ENOMEM; | 64 | return -ENOMEM; |
65 | } | 65 | } |
66 | 66 | ||
67 | pwr->evbit[0] = BIT_MASK(EV_KEY); | 67 | pwr->evbit[0] = BIT_MASK(EV_KEY); |
68 | pwr->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); | 68 | pwr->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); |
69 | pwr->name = "twl4030_pwrbutton"; | 69 | pwr->name = "twl4030_pwrbutton"; |
70 | pwr->phys = "twl4030_pwrbutton/input0"; | 70 | pwr->phys = "twl4030_pwrbutton/input0"; |
71 | pwr->dev.parent = &pdev->dev; | 71 | pwr->dev.parent = &pdev->dev; |
72 | 72 | ||
73 | err = devm_request_threaded_irq(&pwr->dev, irq, NULL, powerbutton_irq, | 73 | err = devm_request_threaded_irq(&pwr->dev, irq, NULL, powerbutton_irq, |
74 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 74 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, |
75 | "twl4030_pwrbutton", pwr); | 75 | "twl4030_pwrbutton", pwr); |
76 | if (err < 0) { | 76 | if (err < 0) { |
77 | dev_err(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); | 77 | dev_err(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); |
78 | return err; | 78 | return err; |
79 | } | 79 | } |
80 | 80 | ||
81 | err = input_register_device(pwr); | 81 | err = input_register_device(pwr); |
82 | if (err) { | 82 | if (err) { |
83 | dev_err(&pdev->dev, "Can't register power button: %d\n", err); | 83 | dev_err(&pdev->dev, "Can't register power button: %d\n", err); |
84 | return err; | 84 | return err; |
85 | } | 85 | } |
86 | 86 | ||
87 | platform_set_drvdata(pdev, pwr); | 87 | platform_set_drvdata(pdev, pwr); |
88 | device_init_wakeup(&pdev->dev, true); | ||
88 | 89 | ||
89 | return 0; | 90 | return 0; |
90 | } | 91 | } |
91 | 92 | ||
92 | #ifdef CONFIG_OF | 93 | #ifdef CONFIG_OF |
93 | static const struct of_device_id twl4030_pwrbutton_dt_match_table[] = { | 94 | static const struct of_device_id twl4030_pwrbutton_dt_match_table[] = { |
94 | { .compatible = "ti,twl4030-pwrbutton" }, | 95 | { .compatible = "ti,twl4030-pwrbutton" }, |
95 | {}, | 96 | {}, |
96 | }; | 97 | }; |
97 | MODULE_DEVICE_TABLE(of, twl4030_pwrbutton_dt_match_table); | 98 | MODULE_DEVICE_TABLE(of, twl4030_pwrbutton_dt_match_table); |
98 | #endif | 99 | #endif |
99 | 100 | ||
100 | static struct platform_driver twl4030_pwrbutton_driver = { | 101 | static struct platform_driver twl4030_pwrbutton_driver = { |
101 | .probe = twl4030_pwrbutton_probe, | 102 | .probe = twl4030_pwrbutton_probe, |
102 | .driver = { | 103 | .driver = { |
103 | .name = "twl4030_pwrbutton", | 104 | .name = "twl4030_pwrbutton", |
104 | .owner = THIS_MODULE, | 105 | .owner = THIS_MODULE, |
105 | .of_match_table = of_match_ptr(twl4030_pwrbutton_dt_match_table), | 106 | .of_match_table = of_match_ptr(twl4030_pwrbutton_dt_match_table), |
106 | }, | 107 | }, |
107 | }; | 108 | }; |
108 | module_platform_driver(twl4030_pwrbutton_driver); | 109 | module_platform_driver(twl4030_pwrbutton_driver); |
109 | 110 | ||
110 | MODULE_ALIAS("platform:twl4030_pwrbutton"); | 111 | MODULE_ALIAS("platform:twl4030_pwrbutton"); |
111 | MODULE_DESCRIPTION("Triton2 Power Button"); | 112 | MODULE_DESCRIPTION("Triton2 Power Button"); |
112 | MODULE_LICENSE("GPL"); | 113 | MODULE_LICENSE("GPL"); |
113 | MODULE_AUTHOR("Peter De Schrijver <peter.de-schrijver@nokia.com>"); | 114 | MODULE_AUTHOR("Peter De Schrijver <peter.de-schrijver@nokia.com>"); |
114 | MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>"); | 115 | MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>"); |
115 | 116 | ||
116 | 117 |
drivers/input/mouse/alps.c
1 | /* | 1 | /* |
2 | * ALPS touchpad PS/2 mouse driver | 2 | * ALPS touchpad PS/2 mouse driver |
3 | * | 3 | * |
4 | * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au> | 4 | * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au> |
5 | * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> | 5 | * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> |
6 | * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> | 6 | * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> |
7 | * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> | 7 | * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> |
8 | * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net> | 8 | * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net> |
9 | * | 9 | * |
10 | * ALPS detection, tap switching and status querying info is taken from | 10 | * ALPS detection, tap switching and status querying info is taken from |
11 | * tpconfig utility (by C. Scott Ananian and Bruce Kall). | 11 | * tpconfig utility (by C. Scott Ananian and Bruce Kall). |
12 | * | 12 | * |
13 | * This program is free software; you can redistribute it and/or modify it | 13 | * This program is free software; you can redistribute it and/or modify it |
14 | * under the terms of the GNU General Public License version 2 as published by | 14 | * under the terms of the GNU General Public License version 2 as published by |
15 | * the Free Software Foundation. | 15 | * the Free Software Foundation. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/input.h> | 19 | #include <linux/input.h> |
20 | #include <linux/input/mt.h> | 20 | #include <linux/input/mt.h> |
21 | #include <linux/serio.h> | 21 | #include <linux/serio.h> |
22 | #include <linux/libps2.h> | 22 | #include <linux/libps2.h> |
23 | 23 | ||
24 | #include "psmouse.h" | 24 | #include "psmouse.h" |
25 | #include "alps.h" | 25 | #include "alps.h" |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Definitions for ALPS version 3 and 4 command mode protocol | 28 | * Definitions for ALPS version 3 and 4 command mode protocol |
29 | */ | 29 | */ |
30 | #define ALPS_CMD_NIBBLE_10 0x01f2 | 30 | #define ALPS_CMD_NIBBLE_10 0x01f2 |
31 | 31 | ||
32 | #define ALPS_REG_BASE_RUSHMORE 0xc2c0 | 32 | #define ALPS_REG_BASE_RUSHMORE 0xc2c0 |
33 | #define ALPS_REG_BASE_PINNACLE 0x0000 | 33 | #define ALPS_REG_BASE_PINNACLE 0x0000 |
34 | 34 | ||
35 | static const struct alps_nibble_commands alps_v3_nibble_commands[] = { | 35 | static const struct alps_nibble_commands alps_v3_nibble_commands[] = { |
36 | { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ | 36 | { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ |
37 | { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ | 37 | { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ |
38 | { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ | 38 | { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ |
39 | { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ | 39 | { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ |
40 | { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ | 40 | { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ |
41 | { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ | 41 | { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ |
42 | { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ | 42 | { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ |
43 | { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ | 43 | { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ |
44 | { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ | 44 | { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ |
45 | { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ | 45 | { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ |
46 | { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ | 46 | { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ |
47 | { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ | 47 | { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ |
48 | { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ | 48 | { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ |
49 | { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ | 49 | { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ |
50 | { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ | 50 | { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ |
51 | { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ | 51 | { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static const struct alps_nibble_commands alps_v4_nibble_commands[] = { | 54 | static const struct alps_nibble_commands alps_v4_nibble_commands[] = { |
55 | { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */ | 55 | { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */ |
56 | { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ | 56 | { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ |
57 | { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ | 57 | { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */ |
58 | { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ | 58 | { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */ |
59 | { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ | 59 | { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */ |
60 | { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ | 60 | { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */ |
61 | { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ | 61 | { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */ |
62 | { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ | 62 | { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */ |
63 | { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ | 63 | { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */ |
64 | { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ | 64 | { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */ |
65 | { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ | 65 | { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */ |
66 | { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ | 66 | { PSMOUSE_CMD_SETRES, 0x00 }, /* b */ |
67 | { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ | 67 | { PSMOUSE_CMD_SETRES, 0x01 }, /* c */ |
68 | { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ | 68 | { PSMOUSE_CMD_SETRES, 0x02 }, /* d */ |
69 | { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ | 69 | { PSMOUSE_CMD_SETRES, 0x03 }, /* e */ |
70 | { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ | 70 | { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ |
71 | }; | 71 | }; |
72 | 72 | ||
73 | static const struct alps_nibble_commands alps_v6_nibble_commands[] = { | 73 | static const struct alps_nibble_commands alps_v6_nibble_commands[] = { |
74 | { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */ | 74 | { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */ |
75 | { PSMOUSE_CMD_SETRATE, 0x0a }, /* 1 */ | 75 | { PSMOUSE_CMD_SETRATE, 0x0a }, /* 1 */ |
76 | { PSMOUSE_CMD_SETRATE, 0x14 }, /* 2 */ | 76 | { PSMOUSE_CMD_SETRATE, 0x14 }, /* 2 */ |
77 | { PSMOUSE_CMD_SETRATE, 0x28 }, /* 3 */ | 77 | { PSMOUSE_CMD_SETRATE, 0x28 }, /* 3 */ |
78 | { PSMOUSE_CMD_SETRATE, 0x3c }, /* 4 */ | 78 | { PSMOUSE_CMD_SETRATE, 0x3c }, /* 4 */ |
79 | { PSMOUSE_CMD_SETRATE, 0x50 }, /* 5 */ | 79 | { PSMOUSE_CMD_SETRATE, 0x50 }, /* 5 */ |
80 | { PSMOUSE_CMD_SETRATE, 0x64 }, /* 6 */ | 80 | { PSMOUSE_CMD_SETRATE, 0x64 }, /* 6 */ |
81 | { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 7 */ | 81 | { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 7 */ |
82 | { PSMOUSE_CMD_GETID, 0x00 }, /* 8 */ | 82 | { PSMOUSE_CMD_GETID, 0x00 }, /* 8 */ |
83 | { PSMOUSE_CMD_GETINFO, 0x00 }, /* 9 */ | 83 | { PSMOUSE_CMD_GETINFO, 0x00 }, /* 9 */ |
84 | { PSMOUSE_CMD_SETRES, 0x00 }, /* a */ | 84 | { PSMOUSE_CMD_SETRES, 0x00 }, /* a */ |
85 | { PSMOUSE_CMD_SETRES, 0x01 }, /* b */ | 85 | { PSMOUSE_CMD_SETRES, 0x01 }, /* b */ |
86 | { PSMOUSE_CMD_SETRES, 0x02 }, /* c */ | 86 | { PSMOUSE_CMD_SETRES, 0x02 }, /* c */ |
87 | { PSMOUSE_CMD_SETRES, 0x03 }, /* d */ | 87 | { PSMOUSE_CMD_SETRES, 0x03 }, /* d */ |
88 | { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* e */ | 88 | { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* e */ |
89 | { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ | 89 | { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ |
90 | }; | 90 | }; |
91 | 91 | ||
92 | 92 | ||
93 | #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ | 93 | #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ |
94 | #define ALPS_PASS 0x04 /* device has a pass-through port */ | 94 | #define ALPS_PASS 0x04 /* device has a pass-through port */ |
95 | 95 | ||
96 | #define ALPS_WHEEL 0x08 /* hardware wheel present */ | 96 | #define ALPS_WHEEL 0x08 /* hardware wheel present */ |
97 | #define ALPS_FW_BK_1 0x10 /* front & back buttons present */ | 97 | #define ALPS_FW_BK_1 0x10 /* front & back buttons present */ |
98 | #define ALPS_FW_BK_2 0x20 /* front & back buttons present */ | 98 | #define ALPS_FW_BK_2 0x20 /* front & back buttons present */ |
99 | #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ | 99 | #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ |
100 | #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with | 100 | #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with |
101 | 6-byte ALPS packet */ | 101 | 6-byte ALPS packet */ |
102 | #define ALPS_IS_RUSHMORE 0x100 /* device is a rushmore */ | 102 | #define ALPS_IS_RUSHMORE 0x100 /* device is a rushmore */ |
103 | #define ALPS_BUTTONPAD 0x200 /* device is a clickpad */ | 103 | #define ALPS_BUTTONPAD 0x200 /* device is a clickpad */ |
104 | 104 | ||
105 | static const struct alps_model_info alps_model_data[] = { | 105 | static const struct alps_model_info alps_model_data[] = { |
106 | { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ | 106 | { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ |
107 | { { 0x33, 0x02, 0x0a }, 0x00, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ | 107 | { { 0x33, 0x02, 0x0a }, 0x00, ALPS_PROTO_V1, 0x88, 0xf8, 0 }, /* UMAX-530T */ |
108 | { { 0x53, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, | 108 | { { 0x53, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, |
109 | { { 0x53, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, | 109 | { { 0x53, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, |
110 | { { 0x60, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ | 110 | { { 0x60, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, /* HP ze1115 */ |
111 | { { 0x63, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, | 111 | { { 0x63, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, |
112 | { { 0x63, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, | 112 | { { 0x63, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, |
113 | { { 0x63, 0x02, 0x28 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ | 113 | { { 0x63, 0x02, 0x28 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */ |
114 | { { 0x63, 0x02, 0x3c }, 0x00, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ | 114 | { { 0x63, 0x02, 0x3c }, 0x00, ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ |
115 | { { 0x63, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ | 115 | { { 0x63, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ |
116 | { { 0x63, 0x02, 0x64 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, | 116 | { { 0x63, 0x02, 0x64 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, |
117 | { { 0x63, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ | 117 | { { 0x63, 0x03, 0xc8 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D800 */ |
118 | { { 0x73, 0x00, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ | 118 | { { 0x73, 0x00, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */ |
119 | { { 0x73, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, | 119 | { { 0x73, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, 0 }, |
120 | { { 0x73, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ | 120 | { { 0x73, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ |
121 | { { 0x20, 0x02, 0x0e }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ | 121 | { { 0x20, 0x02, 0x0e }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ |
122 | { { 0x22, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 122 | { { 0x22, 0x02, 0x0a }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
123 | { { 0x22, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 123 | { { 0x22, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ |
124 | /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ | 124 | /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ |
125 | { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, | 125 | { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, |
126 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, | 126 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, |
127 | { { 0x73, 0x00, 0x14 }, 0x00, ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT }, /* Dell XT2 */ | 127 | { { 0x73, 0x00, 0x14 }, 0x00, ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT }, /* Dell XT2 */ |
128 | { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ | 128 | { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ |
129 | { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, | 129 | { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, |
130 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ | 130 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ |
131 | { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, | 131 | { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, |
132 | }; | 132 | }; |
133 | 133 | ||
134 | static void alps_set_abs_params_st(struct alps_data *priv, | 134 | static void alps_set_abs_params_st(struct alps_data *priv, |
135 | struct input_dev *dev1); | 135 | struct input_dev *dev1); |
136 | static void alps_set_abs_params_mt(struct alps_data *priv, | 136 | static void alps_set_abs_params_mt(struct alps_data *priv, |
137 | struct input_dev *dev1); | 137 | struct input_dev *dev1); |
138 | 138 | ||
139 | /* | 139 | /* |
140 | * XXX - this entry is suspicious. First byte has zero lower nibble, | 140 | * XXX - this entry is suspicious. First byte has zero lower nibble, |
141 | * which is what a normal mouse would report. Also, the value 0x0e | 141 | * which is what a normal mouse would report. Also, the value 0x0e |
142 | * isn't valid per PS/2 spec. | 142 | * isn't valid per PS/2 spec. |
143 | */ | 143 | */ |
144 | 144 | ||
145 | /* Packet formats are described in Documentation/input/alps.txt */ | 145 | /* Packet formats are described in Documentation/input/alps.txt */ |
146 | 146 | ||
147 | static bool alps_is_valid_first_byte(struct alps_data *priv, | 147 | static bool alps_is_valid_first_byte(struct alps_data *priv, |
148 | unsigned char data) | 148 | unsigned char data) |
149 | { | 149 | { |
150 | return (data & priv->mask0) == priv->byte0; | 150 | return (data & priv->mask0) == priv->byte0; |
151 | } | 151 | } |
152 | 152 | ||
153 | static void alps_report_buttons(struct psmouse *psmouse, | 153 | static void alps_report_buttons(struct psmouse *psmouse, |
154 | struct input_dev *dev1, struct input_dev *dev2, | 154 | struct input_dev *dev1, struct input_dev *dev2, |
155 | int left, int right, int middle) | 155 | int left, int right, int middle) |
156 | { | 156 | { |
157 | struct input_dev *dev; | 157 | struct input_dev *dev; |
158 | 158 | ||
159 | /* | 159 | /* |
160 | * If shared button has already been reported on the | 160 | * If shared button has already been reported on the |
161 | * other device (dev2) then this event should be also | 161 | * other device (dev2) then this event should be also |
162 | * sent through that device. | 162 | * sent through that device. |
163 | */ | 163 | */ |
164 | dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; | 164 | dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; |
165 | input_report_key(dev, BTN_LEFT, left); | 165 | input_report_key(dev, BTN_LEFT, left); |
166 | 166 | ||
167 | dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; | 167 | dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; |
168 | input_report_key(dev, BTN_RIGHT, right); | 168 | input_report_key(dev, BTN_RIGHT, right); |
169 | 169 | ||
170 | dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; | 170 | dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; |
171 | input_report_key(dev, BTN_MIDDLE, middle); | 171 | input_report_key(dev, BTN_MIDDLE, middle); |
172 | 172 | ||
173 | /* | 173 | /* |
174 | * Sync the _other_ device now, we'll do the first | 174 | * Sync the _other_ device now, we'll do the first |
175 | * device later once we report the rest of the events. | 175 | * device later once we report the rest of the events. |
176 | */ | 176 | */ |
177 | input_sync(dev2); | 177 | input_sync(dev2); |
178 | } | 178 | } |
179 | 179 | ||
180 | static void alps_process_packet_v1_v2(struct psmouse *psmouse) | 180 | static void alps_process_packet_v1_v2(struct psmouse *psmouse) |
181 | { | 181 | { |
182 | struct alps_data *priv = psmouse->private; | 182 | struct alps_data *priv = psmouse->private; |
183 | unsigned char *packet = psmouse->packet; | 183 | unsigned char *packet = psmouse->packet; |
184 | struct input_dev *dev = psmouse->dev; | 184 | struct input_dev *dev = psmouse->dev; |
185 | struct input_dev *dev2 = priv->dev2; | 185 | struct input_dev *dev2 = priv->dev2; |
186 | int x, y, z, ges, fin, left, right, middle; | 186 | int x, y, z, ges, fin, left, right, middle; |
187 | int back = 0, forward = 0; | 187 | int back = 0, forward = 0; |
188 | 188 | ||
189 | if (priv->proto_version == ALPS_PROTO_V1) { | 189 | if (priv->proto_version == ALPS_PROTO_V1) { |
190 | left = packet[2] & 0x10; | 190 | left = packet[2] & 0x10; |
191 | right = packet[2] & 0x08; | 191 | right = packet[2] & 0x08; |
192 | middle = 0; | 192 | middle = 0; |
193 | x = packet[1] | ((packet[0] & 0x07) << 7); | 193 | x = packet[1] | ((packet[0] & 0x07) << 7); |
194 | y = packet[4] | ((packet[3] & 0x07) << 7); | 194 | y = packet[4] | ((packet[3] & 0x07) << 7); |
195 | z = packet[5]; | 195 | z = packet[5]; |
196 | } else { | 196 | } else { |
197 | left = packet[3] & 1; | 197 | left = packet[3] & 1; |
198 | right = packet[3] & 2; | 198 | right = packet[3] & 2; |
199 | middle = packet[3] & 4; | 199 | middle = packet[3] & 4; |
200 | x = packet[1] | ((packet[2] & 0x78) << (7 - 3)); | 200 | x = packet[1] | ((packet[2] & 0x78) << (7 - 3)); |
201 | y = packet[4] | ((packet[3] & 0x70) << (7 - 4)); | 201 | y = packet[4] | ((packet[3] & 0x70) << (7 - 4)); |
202 | z = packet[5]; | 202 | z = packet[5]; |
203 | } | 203 | } |
204 | 204 | ||
205 | if (priv->flags & ALPS_FW_BK_1) { | 205 | if (priv->flags & ALPS_FW_BK_1) { |
206 | back = packet[0] & 0x10; | 206 | back = packet[0] & 0x10; |
207 | forward = packet[2] & 4; | 207 | forward = packet[2] & 4; |
208 | } | 208 | } |
209 | 209 | ||
210 | if (priv->flags & ALPS_FW_BK_2) { | 210 | if (priv->flags & ALPS_FW_BK_2) { |
211 | back = packet[3] & 4; | 211 | back = packet[3] & 4; |
212 | forward = packet[2] & 4; | 212 | forward = packet[2] & 4; |
213 | if ((middle = forward && back)) | 213 | if ((middle = forward && back)) |
214 | forward = back = 0; | 214 | forward = back = 0; |
215 | } | 215 | } |
216 | 216 | ||
217 | ges = packet[2] & 1; | 217 | ges = packet[2] & 1; |
218 | fin = packet[2] & 2; | 218 | fin = packet[2] & 2; |
219 | 219 | ||
220 | if ((priv->flags & ALPS_DUALPOINT) && z == 127) { | 220 | if ((priv->flags & ALPS_DUALPOINT) && z == 127) { |
221 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); | 221 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); |
222 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); | 222 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); |
223 | 223 | ||
224 | alps_report_buttons(psmouse, dev2, dev, left, right, middle); | 224 | alps_report_buttons(psmouse, dev2, dev, left, right, middle); |
225 | 225 | ||
226 | input_sync(dev2); | 226 | input_sync(dev2); |
227 | return; | 227 | return; |
228 | } | 228 | } |
229 | 229 | ||
230 | alps_report_buttons(psmouse, dev, dev2, left, right, middle); | 230 | alps_report_buttons(psmouse, dev, dev2, left, right, middle); |
231 | 231 | ||
232 | /* Convert hardware tap to a reasonable Z value */ | 232 | /* Convert hardware tap to a reasonable Z value */ |
233 | if (ges && !fin) | 233 | if (ges && !fin) |
234 | z = 40; | 234 | z = 40; |
235 | 235 | ||
236 | /* | 236 | /* |
237 | * A "tap and drag" operation is reported by the hardware as a transition | 237 | * A "tap and drag" operation is reported by the hardware as a transition |
238 | * from (!fin && ges) to (fin && ges). This should be translated to the | 238 | * from (!fin && ges) to (fin && ges). This should be translated to the |
239 | * sequence Z>0, Z==0, Z>0, so the Z==0 event has to be generated manually. | 239 | * sequence Z>0, Z==0, Z>0, so the Z==0 event has to be generated manually. |
240 | */ | 240 | */ |
241 | if (ges && fin && !priv->prev_fin) { | 241 | if (ges && fin && !priv->prev_fin) { |
242 | input_report_abs(dev, ABS_X, x); | 242 | input_report_abs(dev, ABS_X, x); |
243 | input_report_abs(dev, ABS_Y, y); | 243 | input_report_abs(dev, ABS_Y, y); |
244 | input_report_abs(dev, ABS_PRESSURE, 0); | 244 | input_report_abs(dev, ABS_PRESSURE, 0); |
245 | input_report_key(dev, BTN_TOOL_FINGER, 0); | 245 | input_report_key(dev, BTN_TOOL_FINGER, 0); |
246 | input_sync(dev); | 246 | input_sync(dev); |
247 | } | 247 | } |
248 | priv->prev_fin = fin; | 248 | priv->prev_fin = fin; |
249 | 249 | ||
250 | if (z > 30) | 250 | if (z > 30) |
251 | input_report_key(dev, BTN_TOUCH, 1); | 251 | input_report_key(dev, BTN_TOUCH, 1); |
252 | if (z < 25) | 252 | if (z < 25) |
253 | input_report_key(dev, BTN_TOUCH, 0); | 253 | input_report_key(dev, BTN_TOUCH, 0); |
254 | 254 | ||
255 | if (z > 0) { | 255 | if (z > 0) { |
256 | input_report_abs(dev, ABS_X, x); | 256 | input_report_abs(dev, ABS_X, x); |
257 | input_report_abs(dev, ABS_Y, y); | 257 | input_report_abs(dev, ABS_Y, y); |
258 | } | 258 | } |
259 | 259 | ||
260 | input_report_abs(dev, ABS_PRESSURE, z); | 260 | input_report_abs(dev, ABS_PRESSURE, z); |
261 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); | 261 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); |
262 | 262 | ||
263 | if (priv->flags & ALPS_WHEEL) | 263 | if (priv->flags & ALPS_WHEEL) |
264 | input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); | 264 | input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); |
265 | 265 | ||
266 | if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { | 266 | if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
267 | input_report_key(dev, BTN_FORWARD, forward); | 267 | input_report_key(dev, BTN_FORWARD, forward); |
268 | input_report_key(dev, BTN_BACK, back); | 268 | input_report_key(dev, BTN_BACK, back); |
269 | } | 269 | } |
270 | 270 | ||
271 | if (priv->flags & ALPS_FOUR_BUTTONS) { | 271 | if (priv->flags & ALPS_FOUR_BUTTONS) { |
272 | input_report_key(dev, BTN_0, packet[2] & 4); | 272 | input_report_key(dev, BTN_0, packet[2] & 4); |
273 | input_report_key(dev, BTN_1, packet[0] & 0x10); | 273 | input_report_key(dev, BTN_1, packet[0] & 0x10); |
274 | input_report_key(dev, BTN_2, packet[3] & 4); | 274 | input_report_key(dev, BTN_2, packet[3] & 4); |
275 | input_report_key(dev, BTN_3, packet[0] & 0x20); | 275 | input_report_key(dev, BTN_3, packet[0] & 0x20); |
276 | } | 276 | } |
277 | 277 | ||
278 | input_sync(dev); | 278 | input_sync(dev); |
279 | } | 279 | } |
280 | 280 | ||
281 | /* | 281 | /* |
282 | * Process bitmap data for V5 protocols. Return value is null. | 282 | * Process bitmap data for V5 protocols. Return value is null. |
283 | * | 283 | * |
284 | * The bitmaps don't have enough data to track fingers, so this function | 284 | * The bitmaps don't have enough data to track fingers, so this function |
285 | * only generates points representing a bounding box of at most two contacts. | 285 | * only generates points representing a bounding box of at most two contacts. |
286 | * These two points are returned in fields->mt. | 286 | * These two points are returned in fields->mt. |
287 | */ | 287 | */ |
288 | static void alps_process_bitmap_dolphin(struct alps_data *priv, | 288 | static void alps_process_bitmap_dolphin(struct alps_data *priv, |
289 | struct alps_fields *fields) | 289 | struct alps_fields *fields) |
290 | { | 290 | { |
291 | int box_middle_x, box_middle_y; | 291 | int box_middle_x, box_middle_y; |
292 | unsigned int x_map, y_map; | 292 | unsigned int x_map, y_map; |
293 | unsigned char start_bit, end_bit; | 293 | unsigned char start_bit, end_bit; |
294 | unsigned char x_msb, x_lsb, y_msb, y_lsb; | 294 | unsigned char x_msb, x_lsb, y_msb, y_lsb; |
295 | 295 | ||
296 | x_map = fields->x_map; | 296 | x_map = fields->x_map; |
297 | y_map = fields->y_map; | 297 | y_map = fields->y_map; |
298 | 298 | ||
299 | if (!x_map || !y_map) | 299 | if (!x_map || !y_map) |
300 | return; | 300 | return; |
301 | 301 | ||
302 | /* Get Most-significant and Least-significant bit */ | 302 | /* Get Most-significant and Least-significant bit */ |
303 | x_msb = fls(x_map); | 303 | x_msb = fls(x_map); |
304 | x_lsb = ffs(x_map); | 304 | x_lsb = ffs(x_map); |
305 | y_msb = fls(y_map); | 305 | y_msb = fls(y_map); |
306 | y_lsb = ffs(y_map); | 306 | y_lsb = ffs(y_map); |
307 | 307 | ||
308 | /* Most-significant bit should never exceed max sensor line number */ | 308 | /* Most-significant bit should never exceed max sensor line number */ |
309 | if (x_msb > priv->x_bits || y_msb > priv->y_bits) | 309 | if (x_msb > priv->x_bits || y_msb > priv->y_bits) |
310 | return; | 310 | return; |
311 | 311 | ||
312 | if (fields->fingers > 1) { | 312 | if (fields->fingers > 1) { |
313 | start_bit = priv->x_bits - x_msb; | 313 | start_bit = priv->x_bits - x_msb; |
314 | end_bit = priv->x_bits - x_lsb; | 314 | end_bit = priv->x_bits - x_lsb; |
315 | box_middle_x = (priv->x_max * (start_bit + end_bit)) / | 315 | box_middle_x = (priv->x_max * (start_bit + end_bit)) / |
316 | (2 * (priv->x_bits - 1)); | 316 | (2 * (priv->x_bits - 1)); |
317 | 317 | ||
318 | start_bit = y_lsb - 1; | 318 | start_bit = y_lsb - 1; |
319 | end_bit = y_msb - 1; | 319 | end_bit = y_msb - 1; |
320 | box_middle_y = (priv->y_max * (start_bit + end_bit)) / | 320 | box_middle_y = (priv->y_max * (start_bit + end_bit)) / |
321 | (2 * (priv->y_bits - 1)); | 321 | (2 * (priv->y_bits - 1)); |
322 | fields->mt[0] = fields->st; | 322 | fields->mt[0] = fields->st; |
323 | fields->mt[1].x = 2 * box_middle_x - fields->mt[0].x; | 323 | fields->mt[1].x = 2 * box_middle_x - fields->mt[0].x; |
324 | fields->mt[1].y = 2 * box_middle_y - fields->mt[0].y; | 324 | fields->mt[1].y = 2 * box_middle_y - fields->mt[0].y; |
325 | } | 325 | } |
326 | } | 326 | } |
327 | 327 | ||
328 | static void alps_get_bitmap_points(unsigned int map, | 328 | static void alps_get_bitmap_points(unsigned int map, |
329 | struct alps_bitmap_point *low, | 329 | struct alps_bitmap_point *low, |
330 | struct alps_bitmap_point *high, | 330 | struct alps_bitmap_point *high, |
331 | int *fingers) | 331 | int *fingers) |
332 | { | 332 | { |
333 | struct alps_bitmap_point *point; | 333 | struct alps_bitmap_point *point; |
334 | int i, bit, prev_bit = 0; | 334 | int i, bit, prev_bit = 0; |
335 | 335 | ||
336 | point = low; | 336 | point = low; |
337 | for (i = 0; map != 0; i++, map >>= 1) { | 337 | for (i = 0; map != 0; i++, map >>= 1) { |
338 | bit = map & 1; | 338 | bit = map & 1; |
339 | if (bit) { | 339 | if (bit) { |
340 | if (!prev_bit) { | 340 | if (!prev_bit) { |
341 | point->start_bit = i; | 341 | point->start_bit = i; |
342 | point->num_bits = 0; | 342 | point->num_bits = 0; |
343 | (*fingers)++; | 343 | (*fingers)++; |
344 | } | 344 | } |
345 | point->num_bits++; | 345 | point->num_bits++; |
346 | } else { | 346 | } else { |
347 | if (prev_bit) | 347 | if (prev_bit) |
348 | point = high; | 348 | point = high; |
349 | } | 349 | } |
350 | prev_bit = bit; | 350 | prev_bit = bit; |
351 | } | 351 | } |
352 | } | 352 | } |
353 | 353 | ||
354 | /* | 354 | /* |
355 | * Process bitmap data from v3 and v4 protocols. Returns the number of | 355 | * Process bitmap data from v3 and v4 protocols. Returns the number of |
356 | * fingers detected. A return value of 0 means at least one of the | 356 | * fingers detected. A return value of 0 means at least one of the |
357 | * bitmaps was empty. | 357 | * bitmaps was empty. |
358 | * | 358 | * |
359 | * The bitmaps don't have enough data to track fingers, so this function | 359 | * The bitmaps don't have enough data to track fingers, so this function |
360 | * only generates points representing a bounding box of all contacts. | 360 | * only generates points representing a bounding box of all contacts. |
361 | * These points are returned in fields->mt when the return value | 361 | * These points are returned in fields->mt when the return value |
362 | * is greater than 0. | 362 | * is greater than 0. |
363 | */ | 363 | */ |
364 | static int alps_process_bitmap(struct alps_data *priv, | 364 | static int alps_process_bitmap(struct alps_data *priv, |
365 | struct alps_fields *fields) | 365 | struct alps_fields *fields) |
366 | { | 366 | { |
367 | int i, fingers_x = 0, fingers_y = 0, fingers; | 367 | int i, fingers_x = 0, fingers_y = 0, fingers; |
368 | struct alps_bitmap_point x_low = {0,}, x_high = {0,}; | 368 | struct alps_bitmap_point x_low = {0,}, x_high = {0,}; |
369 | struct alps_bitmap_point y_low = {0,}, y_high = {0,}; | 369 | struct alps_bitmap_point y_low = {0,}, y_high = {0,}; |
370 | 370 | ||
371 | if (!fields->x_map || !fields->y_map) | 371 | if (!fields->x_map || !fields->y_map) |
372 | return 0; | 372 | return 0; |
373 | 373 | ||
374 | alps_get_bitmap_points(fields->x_map, &x_low, &x_high, &fingers_x); | 374 | alps_get_bitmap_points(fields->x_map, &x_low, &x_high, &fingers_x); |
375 | alps_get_bitmap_points(fields->y_map, &y_low, &y_high, &fingers_y); | 375 | alps_get_bitmap_points(fields->y_map, &y_low, &y_high, &fingers_y); |
376 | 376 | ||
377 | /* | 377 | /* |
378 | * Fingers can overlap, so we use the maximum count of fingers | 378 | * Fingers can overlap, so we use the maximum count of fingers |
379 | * on either axis as the finger count. | 379 | * on either axis as the finger count. |
380 | */ | 380 | */ |
381 | fingers = max(fingers_x, fingers_y); | 381 | fingers = max(fingers_x, fingers_y); |
382 | 382 | ||
383 | /* | 383 | /* |
384 | * If an axis reports only a single contact, we have overlapping or | 384 | * If an axis reports only a single contact, we have overlapping or |
385 | * adjacent fingers. Divide the single contact between the two points. | 385 | * adjacent fingers. Divide the single contact between the two points. |
386 | */ | 386 | */ |
387 | if (fingers_x == 1) { | 387 | if (fingers_x == 1) { |
388 | i = (x_low.num_bits - 1) / 2; | 388 | i = (x_low.num_bits - 1) / 2; |
389 | x_low.num_bits = x_low.num_bits - i; | 389 | x_low.num_bits = x_low.num_bits - i; |
390 | x_high.start_bit = x_low.start_bit + i; | 390 | x_high.start_bit = x_low.start_bit + i; |
391 | x_high.num_bits = max(i, 1); | 391 | x_high.num_bits = max(i, 1); |
392 | } | 392 | } |
393 | if (fingers_y == 1) { | 393 | if (fingers_y == 1) { |
394 | i = (y_low.num_bits - 1) / 2; | 394 | i = (y_low.num_bits - 1) / 2; |
395 | y_low.num_bits = y_low.num_bits - i; | 395 | y_low.num_bits = y_low.num_bits - i; |
396 | y_high.start_bit = y_low.start_bit + i; | 396 | y_high.start_bit = y_low.start_bit + i; |
397 | y_high.num_bits = max(i, 1); | 397 | y_high.num_bits = max(i, 1); |
398 | } | 398 | } |
399 | 399 | ||
400 | fields->mt[0].x = | 400 | fields->mt[0].x = |
401 | (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / | 401 | (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / |
402 | (2 * (priv->x_bits - 1)); | 402 | (2 * (priv->x_bits - 1)); |
403 | fields->mt[0].y = | 403 | fields->mt[0].y = |
404 | (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / | 404 | (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / |
405 | (2 * (priv->y_bits - 1)); | 405 | (2 * (priv->y_bits - 1)); |
406 | 406 | ||
407 | fields->mt[1].x = | 407 | fields->mt[1].x = |
408 | (priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) / | 408 | (priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) / |
409 | (2 * (priv->x_bits - 1)); | 409 | (2 * (priv->x_bits - 1)); |
410 | fields->mt[1].y = | 410 | fields->mt[1].y = |
411 | (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) / | 411 | (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) / |
412 | (2 * (priv->y_bits - 1)); | 412 | (2 * (priv->y_bits - 1)); |
413 | 413 | ||
414 | /* y-bitmap order is reversed, except on rushmore */ | 414 | /* y-bitmap order is reversed, except on rushmore */ |
415 | if (!(priv->flags & ALPS_IS_RUSHMORE)) { | 415 | if (!(priv->flags & ALPS_IS_RUSHMORE)) { |
416 | fields->mt[0].y = priv->y_max - fields->mt[0].y; | 416 | fields->mt[0].y = priv->y_max - fields->mt[0].y; |
417 | fields->mt[1].y = priv->y_max - fields->mt[1].y; | 417 | fields->mt[1].y = priv->y_max - fields->mt[1].y; |
418 | } | 418 | } |
419 | 419 | ||
420 | return fingers; | 420 | return fingers; |
421 | } | 421 | } |
422 | 422 | ||
423 | static void alps_set_slot(struct input_dev *dev, int slot, int x, int y) | 423 | static void alps_set_slot(struct input_dev *dev, int slot, int x, int y) |
424 | { | 424 | { |
425 | input_mt_slot(dev, slot); | 425 | input_mt_slot(dev, slot); |
426 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); | 426 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); |
427 | input_report_abs(dev, ABS_MT_POSITION_X, x); | 427 | input_report_abs(dev, ABS_MT_POSITION_X, x); |
428 | input_report_abs(dev, ABS_MT_POSITION_Y, y); | 428 | input_report_abs(dev, ABS_MT_POSITION_Y, y); |
429 | } | 429 | } |
430 | 430 | ||
431 | static void alps_report_mt_data(struct psmouse *psmouse, int n) | 431 | static void alps_report_mt_data(struct psmouse *psmouse, int n) |
432 | { | 432 | { |
433 | struct alps_data *priv = psmouse->private; | 433 | struct alps_data *priv = psmouse->private; |
434 | struct input_dev *dev = psmouse->dev; | 434 | struct input_dev *dev = psmouse->dev; |
435 | struct alps_fields *f = &priv->f; | 435 | struct alps_fields *f = &priv->f; |
436 | int i, slot[MAX_TOUCHES]; | 436 | int i, slot[MAX_TOUCHES]; |
437 | 437 | ||
438 | input_mt_assign_slots(dev, slot, f->mt, n); | 438 | input_mt_assign_slots(dev, slot, f->mt, n); |
439 | for (i = 0; i < n; i++) | 439 | for (i = 0; i < n; i++) |
440 | alps_set_slot(dev, slot[i], f->mt[i].x, f->mt[i].y); | 440 | alps_set_slot(dev, slot[i], f->mt[i].x, f->mt[i].y); |
441 | 441 | ||
442 | input_mt_sync_frame(dev); | 442 | input_mt_sync_frame(dev); |
443 | } | 443 | } |
444 | 444 | ||
445 | static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers) | 445 | static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers) |
446 | { | 446 | { |
447 | struct alps_data *priv = psmouse->private; | 447 | struct alps_data *priv = psmouse->private; |
448 | struct input_dev *dev = psmouse->dev; | 448 | struct input_dev *dev = psmouse->dev; |
449 | struct alps_fields *f = &priv->f; | 449 | struct alps_fields *f = &priv->f; |
450 | 450 | ||
451 | /* Use st data when we don't have mt data */ | 451 | /* Use st data when we don't have mt data */ |
452 | if (fingers < 2) { | 452 | if (fingers < 2) { |
453 | f->mt[0].x = f->st.x; | 453 | f->mt[0].x = f->st.x; |
454 | f->mt[0].y = f->st.y; | 454 | f->mt[0].y = f->st.y; |
455 | fingers = f->pressure > 0 ? 1 : 0; | 455 | fingers = f->pressure > 0 ? 1 : 0; |
456 | } | 456 | } |
457 | 457 | ||
458 | alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 2); | 458 | alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 2); |
459 | 459 | ||
460 | input_mt_report_finger_count(dev, fingers); | 460 | input_mt_report_finger_count(dev, fingers); |
461 | 461 | ||
462 | input_report_key(dev, BTN_LEFT, f->left); | 462 | input_report_key(dev, BTN_LEFT, f->left); |
463 | input_report_key(dev, BTN_RIGHT, f->right); | 463 | input_report_key(dev, BTN_RIGHT, f->right); |
464 | input_report_key(dev, BTN_MIDDLE, f->middle); | 464 | input_report_key(dev, BTN_MIDDLE, f->middle); |
465 | 465 | ||
466 | input_report_abs(dev, ABS_PRESSURE, f->pressure); | 466 | input_report_abs(dev, ABS_PRESSURE, f->pressure); |
467 | 467 | ||
468 | input_sync(dev); | 468 | input_sync(dev); |
469 | } | 469 | } |
470 | 470 | ||
471 | static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) | 471 | static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) |
472 | { | 472 | { |
473 | struct alps_data *priv = psmouse->private; | 473 | struct alps_data *priv = psmouse->private; |
474 | unsigned char *packet = psmouse->packet; | 474 | unsigned char *packet = psmouse->packet; |
475 | struct input_dev *dev = priv->dev2; | 475 | struct input_dev *dev = priv->dev2; |
476 | int x, y, z, left, right, middle; | 476 | int x, y, z, left, right, middle; |
477 | 477 | ||
478 | /* Sanity check packet */ | 478 | /* Sanity check packet */ |
479 | if (!(packet[0] & 0x40)) { | 479 | if (!(packet[0] & 0x40)) { |
480 | psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); | 480 | psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n"); |
481 | return; | 481 | return; |
482 | } | 482 | } |
483 | 483 | ||
484 | /* | 484 | /* |
485 | * There's a special packet that seems to indicate the end | 485 | * There's a special packet that seems to indicate the end |
486 | * of a stream of trackstick data. Filter these out. | 486 | * of a stream of trackstick data. Filter these out. |
487 | */ | 487 | */ |
488 | if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f) | 488 | if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f) |
489 | return; | 489 | return; |
490 | 490 | ||
491 | x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f)); | 491 | x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f)); |
492 | y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f)); | 492 | y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f)); |
493 | z = (packet[4] & 0x7c) >> 2; | 493 | z = (packet[4] & 0x7c) >> 2; |
494 | 494 | ||
495 | /* | 495 | /* |
496 | * The x and y values tend to be quite large, and when used | 496 | * The x and y values tend to be quite large, and when used |
497 | * alone the trackstick is difficult to use. Scale them down | 497 | * alone the trackstick is difficult to use. Scale them down |
498 | * to compensate. | 498 | * to compensate. |
499 | */ | 499 | */ |
500 | x /= 8; | 500 | x /= 8; |
501 | y /= 8; | 501 | y /= 8; |
502 | 502 | ||
503 | input_report_rel(dev, REL_X, x); | 503 | input_report_rel(dev, REL_X, x); |
504 | input_report_rel(dev, REL_Y, -y); | 504 | input_report_rel(dev, REL_Y, -y); |
505 | 505 | ||
506 | /* | 506 | /* |
507 | * Most ALPS models report the trackstick buttons in the touchpad | 507 | * Most ALPS models report the trackstick buttons in the touchpad |
508 | * packets, but a few report them here. No reliable way has been | 508 | * packets, but a few report them here. No reliable way has been |
509 | * found to differentiate between the models upfront, so we enable | 509 | * found to differentiate between the models upfront, so we enable |
510 | * the quirk in response to seeing a button press in the trackstick | 510 | * the quirk in response to seeing a button press in the trackstick |
511 | * packet. | 511 | * packet. |
512 | */ | 512 | */ |
513 | left = packet[3] & 0x01; | 513 | left = packet[3] & 0x01; |
514 | right = packet[3] & 0x02; | 514 | right = packet[3] & 0x02; |
515 | middle = packet[3] & 0x04; | 515 | middle = packet[3] & 0x04; |
516 | 516 | ||
517 | if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) && | 517 | if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) && |
518 | (left || right || middle)) | 518 | (left || right || middle)) |
519 | priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS; | 519 | priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS; |
520 | 520 | ||
521 | if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) { | 521 | if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) { |
522 | input_report_key(dev, BTN_LEFT, left); | 522 | input_report_key(dev, BTN_LEFT, left); |
523 | input_report_key(dev, BTN_RIGHT, right); | 523 | input_report_key(dev, BTN_RIGHT, right); |
524 | input_report_key(dev, BTN_MIDDLE, middle); | 524 | input_report_key(dev, BTN_MIDDLE, middle); |
525 | } | 525 | } |
526 | 526 | ||
527 | input_sync(dev); | 527 | input_sync(dev); |
528 | return; | 528 | return; |
529 | } | 529 | } |
530 | 530 | ||
531 | static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p) | 531 | static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p) |
532 | { | 532 | { |
533 | f->left = !!(p[3] & 0x01); | 533 | f->left = !!(p[3] & 0x01); |
534 | f->right = !!(p[3] & 0x02); | 534 | f->right = !!(p[3] & 0x02); |
535 | f->middle = !!(p[3] & 0x04); | 535 | f->middle = !!(p[3] & 0x04); |
536 | 536 | ||
537 | f->ts_left = !!(p[3] & 0x10); | 537 | f->ts_left = !!(p[3] & 0x10); |
538 | f->ts_right = !!(p[3] & 0x20); | 538 | f->ts_right = !!(p[3] & 0x20); |
539 | f->ts_middle = !!(p[3] & 0x40); | 539 | f->ts_middle = !!(p[3] & 0x40); |
540 | } | 540 | } |
541 | 541 | ||
542 | static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p, | 542 | static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p, |
543 | struct psmouse *psmouse) | 543 | struct psmouse *psmouse) |
544 | { | 544 | { |
545 | f->first_mp = !!(p[4] & 0x40); | 545 | f->first_mp = !!(p[4] & 0x40); |
546 | f->is_mp = !!(p[0] & 0x40); | 546 | f->is_mp = !!(p[0] & 0x40); |
547 | 547 | ||
548 | f->fingers = (p[5] & 0x3) + 1; | 548 | f->fingers = (p[5] & 0x3) + 1; |
549 | f->x_map = ((p[4] & 0x7e) << 8) | | 549 | f->x_map = ((p[4] & 0x7e) << 8) | |
550 | ((p[1] & 0x7f) << 2) | | 550 | ((p[1] & 0x7f) << 2) | |
551 | ((p[0] & 0x30) >> 4); | 551 | ((p[0] & 0x30) >> 4); |
552 | f->y_map = ((p[3] & 0x70) << 4) | | 552 | f->y_map = ((p[3] & 0x70) << 4) | |
553 | ((p[2] & 0x7f) << 1) | | 553 | ((p[2] & 0x7f) << 1) | |
554 | (p[4] & 0x01); | 554 | (p[4] & 0x01); |
555 | 555 | ||
556 | f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | | 556 | f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | |
557 | ((p[0] & 0x30) >> 4); | 557 | ((p[0] & 0x30) >> 4); |
558 | f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); | 558 | f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); |
559 | f->pressure = p[5] & 0x7f; | 559 | f->pressure = p[5] & 0x7f; |
560 | 560 | ||
561 | alps_decode_buttons_v3(f, p); | 561 | alps_decode_buttons_v3(f, p); |
562 | 562 | ||
563 | return 0; | 563 | return 0; |
564 | } | 564 | } |
565 | 565 | ||
566 | static int alps_decode_rushmore(struct alps_fields *f, unsigned char *p, | 566 | static int alps_decode_rushmore(struct alps_fields *f, unsigned char *p, |
567 | struct psmouse *psmouse) | 567 | struct psmouse *psmouse) |
568 | { | 568 | { |
569 | alps_decode_pinnacle(f, p, psmouse); | 569 | alps_decode_pinnacle(f, p, psmouse); |
570 | 570 | ||
571 | /* Rushmore's packet decode has a bit difference with Pinnacle's */ | 571 | /* Rushmore's packet decode has a bit difference with Pinnacle's */ |
572 | f->is_mp = !!(p[5] & 0x40); | 572 | f->is_mp = !!(p[5] & 0x40); |
573 | f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1; | 573 | f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1; |
574 | f->x_map |= (p[5] & 0x10) << 11; | 574 | f->x_map |= (p[5] & 0x10) << 11; |
575 | f->y_map |= (p[5] & 0x20) << 6; | 575 | f->y_map |= (p[5] & 0x20) << 6; |
576 | 576 | ||
577 | return 0; | 577 | return 0; |
578 | } | 578 | } |
579 | 579 | ||
580 | static int alps_decode_dolphin(struct alps_fields *f, unsigned char *p, | 580 | static int alps_decode_dolphin(struct alps_fields *f, unsigned char *p, |
581 | struct psmouse *psmouse) | 581 | struct psmouse *psmouse) |
582 | { | 582 | { |
583 | u64 palm_data = 0; | 583 | u64 palm_data = 0; |
584 | struct alps_data *priv = psmouse->private; | 584 | struct alps_data *priv = psmouse->private; |
585 | 585 | ||
586 | f->first_mp = !!(p[0] & 0x02); | 586 | f->first_mp = !!(p[0] & 0x02); |
587 | f->is_mp = !!(p[0] & 0x20); | 587 | f->is_mp = !!(p[0] & 0x20); |
588 | 588 | ||
589 | if (!f->is_mp) { | 589 | if (!f->is_mp) { |
590 | f->st.x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); | 590 | f->st.x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); |
591 | f->st.y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); | 591 | f->st.y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); |
592 | f->pressure = (p[0] & 4) ? 0 : p[5] & 0x7f; | 592 | f->pressure = (p[0] & 4) ? 0 : p[5] & 0x7f; |
593 | alps_decode_buttons_v3(f, p); | 593 | alps_decode_buttons_v3(f, p); |
594 | } else { | 594 | } else { |
595 | f->fingers = ((p[0] & 0x6) >> 1 | | 595 | f->fingers = ((p[0] & 0x6) >> 1 | |
596 | (p[0] & 0x10) >> 2); | 596 | (p[0] & 0x10) >> 2); |
597 | 597 | ||
598 | palm_data = (p[1] & 0x7f) | | 598 | palm_data = (p[1] & 0x7f) | |
599 | ((p[2] & 0x7f) << 7) | | 599 | ((p[2] & 0x7f) << 7) | |
600 | ((p[4] & 0x7f) << 14) | | 600 | ((p[4] & 0x7f) << 14) | |
601 | ((p[5] & 0x7f) << 21) | | 601 | ((p[5] & 0x7f) << 21) | |
602 | ((p[3] & 0x07) << 28) | | 602 | ((p[3] & 0x07) << 28) | |
603 | (((u64)p[3] & 0x70) << 27) | | 603 | (((u64)p[3] & 0x70) << 27) | |
604 | (((u64)p[0] & 0x01) << 34); | 604 | (((u64)p[0] & 0x01) << 34); |
605 | 605 | ||
606 | /* Y-profile is stored in P(0) to p(n-1), n = y_bits; */ | 606 | /* Y-profile is stored in P(0) to p(n-1), n = y_bits; */ |
607 | f->y_map = palm_data & (BIT(priv->y_bits) - 1); | 607 | f->y_map = palm_data & (BIT(priv->y_bits) - 1); |
608 | 608 | ||
609 | /* X-profile is stored in p(n) to p(n+m-1), m = x_bits; */ | 609 | /* X-profile is stored in p(n) to p(n+m-1), m = x_bits; */ |
610 | f->x_map = (palm_data >> priv->y_bits) & | 610 | f->x_map = (palm_data >> priv->y_bits) & |
611 | (BIT(priv->x_bits) - 1); | 611 | (BIT(priv->x_bits) - 1); |
612 | } | 612 | } |
613 | 613 | ||
614 | return 0; | 614 | return 0; |
615 | } | 615 | } |
616 | 616 | ||
617 | static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) | 617 | static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) |
618 | { | 618 | { |
619 | struct alps_data *priv = psmouse->private; | 619 | struct alps_data *priv = psmouse->private; |
620 | unsigned char *packet = psmouse->packet; | 620 | unsigned char *packet = psmouse->packet; |
621 | struct input_dev *dev2 = priv->dev2; | 621 | struct input_dev *dev2 = priv->dev2; |
622 | struct alps_fields *f = &priv->f; | 622 | struct alps_fields *f = &priv->f; |
623 | int fingers = 0; | 623 | int fingers = 0; |
624 | 624 | ||
625 | memset(f, 0, sizeof(*f)); | 625 | memset(f, 0, sizeof(*f)); |
626 | 626 | ||
627 | priv->decode_fields(f, packet, psmouse); | 627 | priv->decode_fields(f, packet, psmouse); |
628 | 628 | ||
629 | /* | 629 | /* |
630 | * There's no single feature of touchpad position and bitmap packets | 630 | * There's no single feature of touchpad position and bitmap packets |
631 | * that can be used to distinguish between them. We rely on the fact | 631 | * that can be used to distinguish between them. We rely on the fact |
632 | * that a bitmap packet should always follow a position packet with | 632 | * that a bitmap packet should always follow a position packet with |
633 | * bit 6 of packet[4] set. | 633 | * bit 6 of packet[4] set. |
634 | */ | 634 | */ |
635 | if (priv->multi_packet) { | 635 | if (priv->multi_packet) { |
636 | /* | 636 | /* |
637 | * Sometimes a position packet will indicate a multi-packet | 637 | * Sometimes a position packet will indicate a multi-packet |
638 | * sequence, but then what follows is another position | 638 | * sequence, but then what follows is another position |
639 | * packet. Check for this, and when it happens process the | 639 | * packet. Check for this, and when it happens process the |
640 | * position packet as usual. | 640 | * position packet as usual. |
641 | */ | 641 | */ |
642 | if (f->is_mp) { | 642 | if (f->is_mp) { |
643 | fingers = f->fingers; | 643 | fingers = f->fingers; |
644 | if (priv->proto_version == ALPS_PROTO_V3) { | 644 | if (priv->proto_version == ALPS_PROTO_V3) { |
645 | if (alps_process_bitmap(priv, f) == 0) | 645 | if (alps_process_bitmap(priv, f) == 0) |
646 | fingers = 0; /* Use st data */ | 646 | fingers = 0; /* Use st data */ |
647 | 647 | ||
648 | /* Now process position packet */ | 648 | /* Now process position packet */ |
649 | priv->decode_fields(f, priv->multi_data, | 649 | priv->decode_fields(f, priv->multi_data, |
650 | psmouse); | 650 | psmouse); |
651 | } else { | 651 | } else { |
652 | /* | 652 | /* |
653 | * Because Dolphin uses position packet's | 653 | * Because Dolphin uses position packet's |
654 | * coordinate data as Pt1 and uses it to | 654 | * coordinate data as Pt1 and uses it to |
655 | * calculate Pt2, so we need to do position | 655 | * calculate Pt2, so we need to do position |
656 | * packet decode first. | 656 | * packet decode first. |
657 | */ | 657 | */ |
658 | priv->decode_fields(f, priv->multi_data, | 658 | priv->decode_fields(f, priv->multi_data, |
659 | psmouse); | 659 | psmouse); |
660 | 660 | ||
661 | /* | 661 | /* |
662 | * Since Dolphin's finger number is reliable, | 662 | * Since Dolphin's finger number is reliable, |
663 | * there is no need to compare with bmap_fn. | 663 | * there is no need to compare with bmap_fn. |
664 | */ | 664 | */ |
665 | alps_process_bitmap_dolphin(priv, f); | 665 | alps_process_bitmap_dolphin(priv, f); |
666 | } | 666 | } |
667 | } else { | 667 | } else { |
668 | priv->multi_packet = 0; | 668 | priv->multi_packet = 0; |
669 | } | 669 | } |
670 | } | 670 | } |
671 | 671 | ||
672 | /* | 672 | /* |
673 | * Bit 6 of byte 0 is not usually set in position packets. The only | 673 | * Bit 6 of byte 0 is not usually set in position packets. The only |
674 | * times it seems to be set is in situations where the data is | 674 | * times it seems to be set is in situations where the data is |
675 | * suspect anyway, e.g. a palm resting flat on the touchpad. Given | 675 | * suspect anyway, e.g. a palm resting flat on the touchpad. Given |
676 | * this combined with the fact that this bit is useful for filtering | 676 | * this combined with the fact that this bit is useful for filtering |
677 | * out misidentified bitmap packets, we reject anything with this | 677 | * out misidentified bitmap packets, we reject anything with this |
678 | * bit set. | 678 | * bit set. |
679 | */ | 679 | */ |
680 | if (f->is_mp) | 680 | if (f->is_mp) |
681 | return; | 681 | return; |
682 | 682 | ||
683 | if (!priv->multi_packet && f->first_mp) { | 683 | if (!priv->multi_packet && f->first_mp) { |
684 | priv->multi_packet = 1; | 684 | priv->multi_packet = 1; |
685 | memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); | 685 | memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); |
686 | return; | 686 | return; |
687 | } | 687 | } |
688 | 688 | ||
689 | priv->multi_packet = 0; | 689 | priv->multi_packet = 0; |
690 | 690 | ||
691 | /* | 691 | /* |
692 | * Sometimes the hardware sends a single packet with z = 0 | 692 | * Sometimes the hardware sends a single packet with z = 0 |
693 | * in the middle of a stream. Real releases generate packets | 693 | * in the middle of a stream. Real releases generate packets |
694 | * with x, y, and z all zero, so these seem to be flukes. | 694 | * with x, y, and z all zero, so these seem to be flukes. |
695 | * Ignore them. | 695 | * Ignore them. |
696 | */ | 696 | */ |
697 | if (f->st.x && f->st.y && !f->pressure) | 697 | if (f->st.x && f->st.y && !f->pressure) |
698 | return; | 698 | return; |
699 | 699 | ||
700 | alps_report_semi_mt_data(psmouse, fingers); | 700 | alps_report_semi_mt_data(psmouse, fingers); |
701 | 701 | ||
702 | if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { | 702 | if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { |
703 | input_report_key(dev2, BTN_LEFT, f->ts_left); | 703 | input_report_key(dev2, BTN_LEFT, f->ts_left); |
704 | input_report_key(dev2, BTN_RIGHT, f->ts_right); | 704 | input_report_key(dev2, BTN_RIGHT, f->ts_right); |
705 | input_report_key(dev2, BTN_MIDDLE, f->ts_middle); | 705 | input_report_key(dev2, BTN_MIDDLE, f->ts_middle); |
706 | input_sync(dev2); | 706 | input_sync(dev2); |
707 | } | 707 | } |
708 | } | 708 | } |
709 | 709 | ||
710 | static void alps_process_packet_v3(struct psmouse *psmouse) | 710 | static void alps_process_packet_v3(struct psmouse *psmouse) |
711 | { | 711 | { |
712 | unsigned char *packet = psmouse->packet; | 712 | unsigned char *packet = psmouse->packet; |
713 | 713 | ||
714 | /* | 714 | /* |
715 | * v3 protocol packets come in three types, two representing | 715 | * v3 protocol packets come in three types, two representing |
716 | * touchpad data and one representing trackstick data. | 716 | * touchpad data and one representing trackstick data. |
717 | * Trackstick packets seem to be distinguished by always | 717 | * Trackstick packets seem to be distinguished by always |
718 | * having 0x3f in the last byte. This value has never been | 718 | * having 0x3f in the last byte. This value has never been |
719 | * observed in the last byte of either of the other types | 719 | * observed in the last byte of either of the other types |
720 | * of packets. | 720 | * of packets. |
721 | */ | 721 | */ |
722 | if (packet[5] == 0x3f) { | 722 | if (packet[5] == 0x3f) { |
723 | alps_process_trackstick_packet_v3(psmouse); | 723 | alps_process_trackstick_packet_v3(psmouse); |
724 | return; | 724 | return; |
725 | } | 725 | } |
726 | 726 | ||
727 | alps_process_touchpad_packet_v3_v5(psmouse); | 727 | alps_process_touchpad_packet_v3_v5(psmouse); |
728 | } | 728 | } |
729 | 729 | ||
730 | static void alps_process_packet_v6(struct psmouse *psmouse) | 730 | static void alps_process_packet_v6(struct psmouse *psmouse) |
731 | { | 731 | { |
732 | struct alps_data *priv = psmouse->private; | 732 | struct alps_data *priv = psmouse->private; |
733 | unsigned char *packet = psmouse->packet; | 733 | unsigned char *packet = psmouse->packet; |
734 | struct input_dev *dev = psmouse->dev; | 734 | struct input_dev *dev = psmouse->dev; |
735 | struct input_dev *dev2 = priv->dev2; | 735 | struct input_dev *dev2 = priv->dev2; |
736 | int x, y, z, left, right, middle; | 736 | int x, y, z, left, right, middle; |
737 | 737 | ||
738 | /* | 738 | /* |
739 | * We can use Byte5 to distinguish if the packet is from Touchpad | 739 | * We can use Byte5 to distinguish if the packet is from Touchpad |
740 | * or Trackpoint. | 740 | * or Trackpoint. |
741 | * Touchpad: 0 - 0x7E | 741 | * Touchpad: 0 - 0x7E |
742 | * Trackpoint: 0x7F | 742 | * Trackpoint: 0x7F |
743 | */ | 743 | */ |
744 | if (packet[5] == 0x7F) { | 744 | if (packet[5] == 0x7F) { |
745 | /* It should be a DualPoint when received Trackpoint packet */ | 745 | /* It should be a DualPoint when received Trackpoint packet */ |
746 | if (!(priv->flags & ALPS_DUALPOINT)) | 746 | if (!(priv->flags & ALPS_DUALPOINT)) |
747 | return; | 747 | return; |
748 | 748 | ||
749 | /* Trackpoint packet */ | 749 | /* Trackpoint packet */ |
750 | x = packet[1] | ((packet[3] & 0x20) << 2); | 750 | x = packet[1] | ((packet[3] & 0x20) << 2); |
751 | y = packet[2] | ((packet[3] & 0x40) << 1); | 751 | y = packet[2] | ((packet[3] & 0x40) << 1); |
752 | z = packet[4]; | 752 | z = packet[4]; |
753 | left = packet[3] & 0x01; | 753 | left = packet[3] & 0x01; |
754 | right = packet[3] & 0x02; | 754 | right = packet[3] & 0x02; |
755 | middle = packet[3] & 0x04; | 755 | middle = packet[3] & 0x04; |
756 | 756 | ||
757 | /* To prevent the cursor jump when finger lifted */ | 757 | /* To prevent the cursor jump when finger lifted */ |
758 | if (x == 0x7F && y == 0x7F && z == 0x7F) | 758 | if (x == 0x7F && y == 0x7F && z == 0x7F) |
759 | x = y = z = 0; | 759 | x = y = z = 0; |
760 | 760 | ||
761 | /* Divide 4 since trackpoint's speed is too fast */ | 761 | /* Divide 4 since trackpoint's speed is too fast */ |
762 | input_report_rel(dev2, REL_X, (char)x / 4); | 762 | input_report_rel(dev2, REL_X, (char)x / 4); |
763 | input_report_rel(dev2, REL_Y, -((char)y / 4)); | 763 | input_report_rel(dev2, REL_Y, -((char)y / 4)); |
764 | 764 | ||
765 | input_report_key(dev2, BTN_LEFT, left); | 765 | input_report_key(dev2, BTN_LEFT, left); |
766 | input_report_key(dev2, BTN_RIGHT, right); | 766 | input_report_key(dev2, BTN_RIGHT, right); |
767 | input_report_key(dev2, BTN_MIDDLE, middle); | 767 | input_report_key(dev2, BTN_MIDDLE, middle); |
768 | 768 | ||
769 | input_sync(dev2); | 769 | input_sync(dev2); |
770 | return; | 770 | return; |
771 | } | 771 | } |
772 | 772 | ||
773 | /* Touchpad packet */ | 773 | /* Touchpad packet */ |
774 | x = packet[1] | ((packet[3] & 0x78) << 4); | 774 | x = packet[1] | ((packet[3] & 0x78) << 4); |
775 | y = packet[2] | ((packet[4] & 0x78) << 4); | 775 | y = packet[2] | ((packet[4] & 0x78) << 4); |
776 | z = packet[5]; | 776 | z = packet[5]; |
777 | left = packet[3] & 0x01; | 777 | left = packet[3] & 0x01; |
778 | right = packet[3] & 0x02; | 778 | right = packet[3] & 0x02; |
779 | 779 | ||
780 | if (z > 30) | 780 | if (z > 30) |
781 | input_report_key(dev, BTN_TOUCH, 1); | 781 | input_report_key(dev, BTN_TOUCH, 1); |
782 | if (z < 25) | 782 | if (z < 25) |
783 | input_report_key(dev, BTN_TOUCH, 0); | 783 | input_report_key(dev, BTN_TOUCH, 0); |
784 | 784 | ||
785 | if (z > 0) { | 785 | if (z > 0) { |
786 | input_report_abs(dev, ABS_X, x); | 786 | input_report_abs(dev, ABS_X, x); |
787 | input_report_abs(dev, ABS_Y, y); | 787 | input_report_abs(dev, ABS_Y, y); |
788 | } | 788 | } |
789 | 789 | ||
790 | input_report_abs(dev, ABS_PRESSURE, z); | 790 | input_report_abs(dev, ABS_PRESSURE, z); |
791 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); | 791 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); |
792 | 792 | ||
793 | /* v6 touchpad does not have middle button */ | 793 | /* v6 touchpad does not have middle button */ |
794 | input_report_key(dev, BTN_LEFT, left); | 794 | input_report_key(dev, BTN_LEFT, left); |
795 | input_report_key(dev, BTN_RIGHT, right); | 795 | input_report_key(dev, BTN_RIGHT, right); |
796 | 796 | ||
797 | input_sync(dev); | 797 | input_sync(dev); |
798 | } | 798 | } |
799 | 799 | ||
800 | static void alps_process_packet_v4(struct psmouse *psmouse) | 800 | static void alps_process_packet_v4(struct psmouse *psmouse) |
801 | { | 801 | { |
802 | struct alps_data *priv = psmouse->private; | 802 | struct alps_data *priv = psmouse->private; |
803 | unsigned char *packet = psmouse->packet; | 803 | unsigned char *packet = psmouse->packet; |
804 | struct alps_fields *f = &priv->f; | 804 | struct alps_fields *f = &priv->f; |
805 | int offset; | 805 | int offset; |
806 | 806 | ||
807 | /* | 807 | /* |
808 | * v4 has a 6-byte encoding for bitmap data, but this data is | 808 | * v4 has a 6-byte encoding for bitmap data, but this data is |
809 | * broken up between 3 normal packets. Use priv->multi_packet to | 809 | * broken up between 3 normal packets. Use priv->multi_packet to |
810 | * track our position in the bitmap packet. | 810 | * track our position in the bitmap packet. |
811 | */ | 811 | */ |
812 | if (packet[6] & 0x40) { | 812 | if (packet[6] & 0x40) { |
813 | /* sync, reset position */ | 813 | /* sync, reset position */ |
814 | priv->multi_packet = 0; | 814 | priv->multi_packet = 0; |
815 | } | 815 | } |
816 | 816 | ||
817 | if (WARN_ON_ONCE(priv->multi_packet > 2)) | 817 | if (WARN_ON_ONCE(priv->multi_packet > 2)) |
818 | return; | 818 | return; |
819 | 819 | ||
820 | offset = 2 * priv->multi_packet; | 820 | offset = 2 * priv->multi_packet; |
821 | priv->multi_data[offset] = packet[6]; | 821 | priv->multi_data[offset] = packet[6]; |
822 | priv->multi_data[offset + 1] = packet[7]; | 822 | priv->multi_data[offset + 1] = packet[7]; |
823 | 823 | ||
824 | if (++priv->multi_packet > 2) { | 824 | if (++priv->multi_packet > 2) { |
825 | priv->multi_packet = 0; | 825 | priv->multi_packet = 0; |
826 | 826 | ||
827 | f->x_map = ((priv->multi_data[2] & 0x1f) << 10) | | 827 | f->x_map = ((priv->multi_data[2] & 0x1f) << 10) | |
828 | ((priv->multi_data[3] & 0x60) << 3) | | 828 | ((priv->multi_data[3] & 0x60) << 3) | |
829 | ((priv->multi_data[0] & 0x3f) << 2) | | 829 | ((priv->multi_data[0] & 0x3f) << 2) | |
830 | ((priv->multi_data[1] & 0x60) >> 5); | 830 | ((priv->multi_data[1] & 0x60) >> 5); |
831 | f->y_map = ((priv->multi_data[5] & 0x01) << 10) | | 831 | f->y_map = ((priv->multi_data[5] & 0x01) << 10) | |
832 | ((priv->multi_data[3] & 0x1f) << 5) | | 832 | ((priv->multi_data[3] & 0x1f) << 5) | |
833 | (priv->multi_data[1] & 0x1f); | 833 | (priv->multi_data[1] & 0x1f); |
834 | 834 | ||
835 | f->fingers = alps_process_bitmap(priv, f); | 835 | f->fingers = alps_process_bitmap(priv, f); |
836 | } | 836 | } |
837 | 837 | ||
838 | f->left = !!(packet[4] & 0x01); | 838 | f->left = !!(packet[4] & 0x01); |
839 | f->right = !!(packet[4] & 0x02); | 839 | f->right = !!(packet[4] & 0x02); |
840 | 840 | ||
841 | f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | | 841 | f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | |
842 | ((packet[0] & 0x30) >> 4); | 842 | ((packet[0] & 0x30) >> 4); |
843 | f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); | 843 | f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); |
844 | f->pressure = packet[5] & 0x7f; | 844 | f->pressure = packet[5] & 0x7f; |
845 | 845 | ||
846 | alps_report_semi_mt_data(psmouse, f->fingers); | 846 | alps_report_semi_mt_data(psmouse, f->fingers); |
847 | } | 847 | } |
848 | 848 | ||
849 | static bool alps_is_valid_package_v7(struct psmouse *psmouse) | 849 | static bool alps_is_valid_package_v7(struct psmouse *psmouse) |
850 | { | 850 | { |
851 | switch (psmouse->pktcnt) { | 851 | switch (psmouse->pktcnt) { |
852 | case 3: | 852 | case 3: |
853 | return (psmouse->packet[2] & 0x40) == 0x40; | 853 | return (psmouse->packet[2] & 0x40) == 0x40; |
854 | case 4: | 854 | case 4: |
855 | return (psmouse->packet[3] & 0x48) == 0x48; | 855 | return (psmouse->packet[3] & 0x48) == 0x48; |
856 | case 6: | 856 | case 6: |
857 | return (psmouse->packet[5] & 0x40) == 0x00; | 857 | return (psmouse->packet[5] & 0x40) == 0x00; |
858 | } | 858 | } |
859 | return true; | 859 | return true; |
860 | } | 860 | } |
861 | 861 | ||
862 | static unsigned char alps_get_packet_id_v7(char *byte) | 862 | static unsigned char alps_get_packet_id_v7(char *byte) |
863 | { | 863 | { |
864 | unsigned char packet_id; | 864 | unsigned char packet_id; |
865 | 865 | ||
866 | if (byte[4] & 0x40) | 866 | if (byte[4] & 0x40) |
867 | packet_id = V7_PACKET_ID_TWO; | 867 | packet_id = V7_PACKET_ID_TWO; |
868 | else if (byte[4] & 0x01) | 868 | else if (byte[4] & 0x01) |
869 | packet_id = V7_PACKET_ID_MULTI; | 869 | packet_id = V7_PACKET_ID_MULTI; |
870 | else if ((byte[0] & 0x10) && !(byte[4] & 0x43)) | 870 | else if ((byte[0] & 0x10) && !(byte[4] & 0x43)) |
871 | packet_id = V7_PACKET_ID_NEW; | 871 | packet_id = V7_PACKET_ID_NEW; |
872 | else if (byte[1] == 0x00 && byte[4] == 0x00) | 872 | else if (byte[1] == 0x00 && byte[4] == 0x00) |
873 | packet_id = V7_PACKET_ID_IDLE; | 873 | packet_id = V7_PACKET_ID_IDLE; |
874 | else | 874 | else |
875 | packet_id = V7_PACKET_ID_UNKNOWN; | 875 | packet_id = V7_PACKET_ID_UNKNOWN; |
876 | 876 | ||
877 | return packet_id; | 877 | return packet_id; |
878 | } | 878 | } |
879 | 879 | ||
880 | static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt, | 880 | static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt, |
881 | unsigned char *pkt, | 881 | unsigned char *pkt, |
882 | unsigned char pkt_id) | 882 | unsigned char pkt_id) |
883 | { | 883 | { |
884 | mt[0].x = ((pkt[2] & 0x80) << 4); | 884 | mt[0].x = ((pkt[2] & 0x80) << 4); |
885 | mt[0].x |= ((pkt[2] & 0x3F) << 5); | 885 | mt[0].x |= ((pkt[2] & 0x3F) << 5); |
886 | mt[0].x |= ((pkt[3] & 0x30) >> 1); | 886 | mt[0].x |= ((pkt[3] & 0x30) >> 1); |
887 | mt[0].x |= (pkt[3] & 0x07); | 887 | mt[0].x |= (pkt[3] & 0x07); |
888 | mt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07); | 888 | mt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07); |
889 | 889 | ||
890 | mt[1].x = ((pkt[3] & 0x80) << 4); | 890 | mt[1].x = ((pkt[3] & 0x80) << 4); |
891 | mt[1].x |= ((pkt[4] & 0x80) << 3); | 891 | mt[1].x |= ((pkt[4] & 0x80) << 3); |
892 | mt[1].x |= ((pkt[4] & 0x3F) << 4); | 892 | mt[1].x |= ((pkt[4] & 0x3F) << 4); |
893 | mt[1].y = ((pkt[5] & 0x80) << 3); | 893 | mt[1].y = ((pkt[5] & 0x80) << 3); |
894 | mt[1].y |= ((pkt[5] & 0x3F) << 4); | 894 | mt[1].y |= ((pkt[5] & 0x3F) << 4); |
895 | 895 | ||
896 | switch (pkt_id) { | 896 | switch (pkt_id) { |
897 | case V7_PACKET_ID_TWO: | 897 | case V7_PACKET_ID_TWO: |
898 | mt[1].x &= ~0x000F; | 898 | mt[1].x &= ~0x000F; |
899 | mt[1].y |= 0x000F; | 899 | mt[1].y |= 0x000F; |
900 | break; | 900 | break; |
901 | 901 | ||
902 | case V7_PACKET_ID_MULTI: | 902 | case V7_PACKET_ID_MULTI: |
903 | mt[1].x &= ~0x003F; | 903 | mt[1].x &= ~0x003F; |
904 | mt[1].y &= ~0x0020; | 904 | mt[1].y &= ~0x0020; |
905 | mt[1].y |= ((pkt[4] & 0x02) << 4); | 905 | mt[1].y |= ((pkt[4] & 0x02) << 4); |
906 | mt[1].y |= 0x001F; | 906 | mt[1].y |= 0x001F; |
907 | break; | 907 | break; |
908 | 908 | ||
909 | case V7_PACKET_ID_NEW: | 909 | case V7_PACKET_ID_NEW: |
910 | mt[1].x &= ~0x003F; | 910 | mt[1].x &= ~0x003F; |
911 | mt[1].x |= (pkt[0] & 0x20); | 911 | mt[1].x |= (pkt[0] & 0x20); |
912 | mt[1].y |= 0x000F; | 912 | mt[1].y |= 0x000F; |
913 | break; | 913 | break; |
914 | } | 914 | } |
915 | 915 | ||
916 | mt[0].y = 0x7FF - mt[0].y; | 916 | mt[0].y = 0x7FF - mt[0].y; |
917 | mt[1].y = 0x7FF - mt[1].y; | 917 | mt[1].y = 0x7FF - mt[1].y; |
918 | } | 918 | } |
919 | 919 | ||
920 | static int alps_get_mt_count(struct input_mt_pos *mt) | 920 | static int alps_get_mt_count(struct input_mt_pos *mt) |
921 | { | 921 | { |
922 | int i; | 922 | int i; |
923 | 923 | ||
924 | for (i = 0; i < MAX_TOUCHES && mt[i].x != 0 && mt[i].y != 0; i++) | 924 | for (i = 0; i < MAX_TOUCHES && mt[i].x != 0 && mt[i].y != 0; i++) |
925 | /* empty */; | 925 | /* empty */; |
926 | 926 | ||
927 | return i; | 927 | return i; |
928 | } | 928 | } |
929 | 929 | ||
930 | static int alps_decode_packet_v7(struct alps_fields *f, | 930 | static int alps_decode_packet_v7(struct alps_fields *f, |
931 | unsigned char *p, | 931 | unsigned char *p, |
932 | struct psmouse *psmouse) | 932 | struct psmouse *psmouse) |
933 | { | 933 | { |
934 | unsigned char pkt_id; | 934 | unsigned char pkt_id; |
935 | 935 | ||
936 | pkt_id = alps_get_packet_id_v7(p); | 936 | pkt_id = alps_get_packet_id_v7(p); |
937 | if (pkt_id == V7_PACKET_ID_IDLE) | 937 | if (pkt_id == V7_PACKET_ID_IDLE) |
938 | return 0; | 938 | return 0; |
939 | if (pkt_id == V7_PACKET_ID_UNKNOWN) | 939 | if (pkt_id == V7_PACKET_ID_UNKNOWN) |
940 | return -1; | 940 | return -1; |
941 | 941 | ||
942 | alps_get_finger_coordinate_v7(f->mt, p, pkt_id); | 942 | alps_get_finger_coordinate_v7(f->mt, p, pkt_id); |
943 | 943 | ||
944 | if (pkt_id == V7_PACKET_ID_TWO || pkt_id == V7_PACKET_ID_MULTI) { | 944 | if (pkt_id == V7_PACKET_ID_TWO || pkt_id == V7_PACKET_ID_MULTI) { |
945 | f->left = (p[0] & 0x80) >> 7; | 945 | f->left = (p[0] & 0x80) >> 7; |
946 | f->right = (p[0] & 0x20) >> 5; | 946 | f->right = (p[0] & 0x20) >> 5; |
947 | f->middle = (p[0] & 0x10) >> 4; | 947 | f->middle = (p[0] & 0x10) >> 4; |
948 | } | 948 | } |
949 | 949 | ||
950 | if (pkt_id == V7_PACKET_ID_TWO) | 950 | if (pkt_id == V7_PACKET_ID_TWO) |
951 | f->fingers = alps_get_mt_count(f->mt); | 951 | f->fingers = alps_get_mt_count(f->mt); |
952 | else if (pkt_id == V7_PACKET_ID_MULTI) | 952 | else if (pkt_id == V7_PACKET_ID_MULTI) |
953 | f->fingers = 3 + (p[5] & 0x03); | 953 | f->fingers = 3 + (p[5] & 0x03); |
954 | 954 | ||
955 | return 0; | 955 | return 0; |
956 | } | 956 | } |
957 | 957 | ||
958 | static void alps_process_trackstick_packet_v7(struct psmouse *psmouse) | 958 | static void alps_process_trackstick_packet_v7(struct psmouse *psmouse) |
959 | { | 959 | { |
960 | struct alps_data *priv = psmouse->private; | 960 | struct alps_data *priv = psmouse->private; |
961 | unsigned char *packet = psmouse->packet; | 961 | unsigned char *packet = psmouse->packet; |
962 | struct input_dev *dev2 = priv->dev2; | 962 | struct input_dev *dev2 = priv->dev2; |
963 | int x, y, z, left, right, middle; | 963 | int x, y, z, left, right, middle; |
964 | 964 | ||
965 | /* | 965 | /* |
966 | * b7 b6 b5 b4 b3 b2 b1 b0 | 966 | * b7 b6 b5 b4 b3 b2 b1 b0 |
967 | * Byte0 0 1 0 0 1 0 0 0 | 967 | * Byte0 0 1 0 0 1 0 0 0 |
968 | * Byte1 1 1 * * 1 M R L | 968 | * Byte1 1 1 * * 1 M R L |
969 | * Byte2 X7 1 X5 X4 X3 X2 X1 X0 | 969 | * Byte2 X7 1 X5 X4 X3 X2 X1 X0 |
970 | * Byte3 Z6 1 Y6 X6 1 Y2 Y1 Y0 | 970 | * Byte3 Z6 1 Y6 X6 1 Y2 Y1 Y0 |
971 | * Byte4 Y7 0 Y5 Y4 Y3 1 1 0 | 971 | * Byte4 Y7 0 Y5 Y4 Y3 1 1 0 |
972 | * Byte5 T&P 0 Z5 Z4 Z3 Z2 Z1 Z0 | 972 | * Byte5 T&P 0 Z5 Z4 Z3 Z2 Z1 Z0 |
973 | * M / R / L: Middle / Right / Left button | 973 | * M / R / L: Middle / Right / Left button |
974 | */ | 974 | */ |
975 | 975 | ||
976 | x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2); | 976 | x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2); |
977 | y = (packet[3] & 0x07) | (packet[4] & 0xb8) | | 977 | y = (packet[3] & 0x07) | (packet[4] & 0xb8) | |
978 | ((packet[3] & 0x20) << 1); | 978 | ((packet[3] & 0x20) << 1); |
979 | z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1); | 979 | z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1); |
980 | 980 | ||
981 | left = (packet[1] & 0x01); | 981 | left = (packet[1] & 0x01); |
982 | right = (packet[1] & 0x02) >> 1; | 982 | right = (packet[1] & 0x02) >> 1; |
983 | middle = (packet[1] & 0x04) >> 2; | 983 | middle = (packet[1] & 0x04) >> 2; |
984 | 984 | ||
985 | /* Divide 2 since trackpoint's speed is too fast */ | 985 | /* Divide 2 since trackpoint's speed is too fast */ |
986 | input_report_rel(dev2, REL_X, (char)x / 2); | 986 | input_report_rel(dev2, REL_X, (char)x / 2); |
987 | input_report_rel(dev2, REL_Y, -((char)y / 2)); | 987 | input_report_rel(dev2, REL_Y, -((char)y / 2)); |
988 | 988 | ||
989 | input_report_key(dev2, BTN_LEFT, left); | 989 | input_report_key(dev2, BTN_LEFT, left); |
990 | input_report_key(dev2, BTN_RIGHT, right); | 990 | input_report_key(dev2, BTN_RIGHT, right); |
991 | input_report_key(dev2, BTN_MIDDLE, middle); | 991 | input_report_key(dev2, BTN_MIDDLE, middle); |
992 | 992 | ||
993 | input_sync(dev2); | 993 | input_sync(dev2); |
994 | } | 994 | } |
995 | 995 | ||
996 | static void alps_process_touchpad_packet_v7(struct psmouse *psmouse) | 996 | static void alps_process_touchpad_packet_v7(struct psmouse *psmouse) |
997 | { | 997 | { |
998 | struct alps_data *priv = psmouse->private; | 998 | struct alps_data *priv = psmouse->private; |
999 | struct input_dev *dev = psmouse->dev; | 999 | struct input_dev *dev = psmouse->dev; |
1000 | struct alps_fields *f = &priv->f; | 1000 | struct alps_fields *f = &priv->f; |
1001 | 1001 | ||
1002 | memset(f, 0, sizeof(*f)); | 1002 | memset(f, 0, sizeof(*f)); |
1003 | 1003 | ||
1004 | if (priv->decode_fields(f, psmouse->packet, psmouse)) | 1004 | if (priv->decode_fields(f, psmouse->packet, psmouse)) |
1005 | return; | 1005 | return; |
1006 | 1006 | ||
1007 | alps_report_mt_data(psmouse, alps_get_mt_count(f->mt)); | 1007 | alps_report_mt_data(psmouse, alps_get_mt_count(f->mt)); |
1008 | 1008 | ||
1009 | input_mt_report_finger_count(dev, f->fingers); | 1009 | input_mt_report_finger_count(dev, f->fingers); |
1010 | 1010 | ||
1011 | input_report_key(dev, BTN_LEFT, f->left); | 1011 | input_report_key(dev, BTN_LEFT, f->left); |
1012 | input_report_key(dev, BTN_RIGHT, f->right); | 1012 | input_report_key(dev, BTN_RIGHT, f->right); |
1013 | input_report_key(dev, BTN_MIDDLE, f->middle); | 1013 | input_report_key(dev, BTN_MIDDLE, f->middle); |
1014 | 1014 | ||
1015 | input_sync(dev); | 1015 | input_sync(dev); |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | static void alps_process_packet_v7(struct psmouse *psmouse) | 1018 | static void alps_process_packet_v7(struct psmouse *psmouse) |
1019 | { | 1019 | { |
1020 | unsigned char *packet = psmouse->packet; | 1020 | unsigned char *packet = psmouse->packet; |
1021 | 1021 | ||
1022 | if (packet[0] == 0x48 && (packet[4] & 0x47) == 0x06) | 1022 | if (packet[0] == 0x48 && (packet[4] & 0x47) == 0x06) |
1023 | alps_process_trackstick_packet_v7(psmouse); | 1023 | alps_process_trackstick_packet_v7(psmouse); |
1024 | else | 1024 | else |
1025 | alps_process_touchpad_packet_v7(psmouse); | 1025 | alps_process_touchpad_packet_v7(psmouse); |
1026 | } | 1026 | } |
1027 | 1027 | ||
1028 | static void alps_report_bare_ps2_packet(struct psmouse *psmouse, | 1028 | static void alps_report_bare_ps2_packet(struct psmouse *psmouse, |
1029 | unsigned char packet[], | 1029 | unsigned char packet[], |
1030 | bool report_buttons) | 1030 | bool report_buttons) |
1031 | { | 1031 | { |
1032 | struct alps_data *priv = psmouse->private; | 1032 | struct alps_data *priv = psmouse->private; |
1033 | struct input_dev *dev2 = priv->dev2; | 1033 | struct input_dev *dev2 = priv->dev2; |
1034 | 1034 | ||
1035 | if (report_buttons) | 1035 | if (report_buttons) |
1036 | alps_report_buttons(psmouse, dev2, psmouse->dev, | 1036 | alps_report_buttons(psmouse, dev2, psmouse->dev, |
1037 | packet[0] & 1, packet[0] & 2, packet[0] & 4); | 1037 | packet[0] & 1, packet[0] & 2, packet[0] & 4); |
1038 | 1038 | ||
1039 | input_report_rel(dev2, REL_X, | 1039 | input_report_rel(dev2, REL_X, |
1040 | packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); | 1040 | packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); |
1041 | input_report_rel(dev2, REL_Y, | 1041 | input_report_rel(dev2, REL_Y, |
1042 | packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); | 1042 | packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); |
1043 | 1043 | ||
1044 | input_sync(dev2); | 1044 | input_sync(dev2); |
1045 | } | 1045 | } |
1046 | 1046 | ||
1047 | static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) | 1047 | static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) |
1048 | { | 1048 | { |
1049 | struct alps_data *priv = psmouse->private; | 1049 | struct alps_data *priv = psmouse->private; |
1050 | 1050 | ||
1051 | if (psmouse->pktcnt < 6) | 1051 | if (psmouse->pktcnt < 6) |
1052 | return PSMOUSE_GOOD_DATA; | 1052 | return PSMOUSE_GOOD_DATA; |
1053 | 1053 | ||
1054 | if (psmouse->pktcnt == 6) { | 1054 | if (psmouse->pktcnt == 6) { |
1055 | /* | 1055 | /* |
1056 | * Start a timer to flush the packet if it ends up last | 1056 | * Start a timer to flush the packet if it ends up last |
1057 | * 6-byte packet in the stream. Timer needs to fire | 1057 | * 6-byte packet in the stream. Timer needs to fire |
1058 | * psmouse core times out itself. 20 ms should be enough | 1058 | * psmouse core times out itself. 20 ms should be enough |
1059 | * to decide if we are getting more data or not. | 1059 | * to decide if we are getting more data or not. |
1060 | */ | 1060 | */ |
1061 | mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20)); | 1061 | mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20)); |
1062 | return PSMOUSE_GOOD_DATA; | 1062 | return PSMOUSE_GOOD_DATA; |
1063 | } | 1063 | } |
1064 | 1064 | ||
1065 | del_timer(&priv->timer); | 1065 | del_timer(&priv->timer); |
1066 | 1066 | ||
1067 | if (psmouse->packet[6] & 0x80) { | 1067 | if (psmouse->packet[6] & 0x80) { |
1068 | 1068 | ||
1069 | /* | 1069 | /* |
1070 | * Highest bit is set - that means we either had | 1070 | * Highest bit is set - that means we either had |
1071 | * complete ALPS packet and this is start of the | 1071 | * complete ALPS packet and this is start of the |
1072 | * next packet or we got garbage. | 1072 | * next packet or we got garbage. |
1073 | */ | 1073 | */ |
1074 | 1074 | ||
1075 | if (((psmouse->packet[3] | | 1075 | if (((psmouse->packet[3] | |
1076 | psmouse->packet[4] | | 1076 | psmouse->packet[4] | |
1077 | psmouse->packet[5]) & 0x80) || | 1077 | psmouse->packet[5]) & 0x80) || |
1078 | (!alps_is_valid_first_byte(priv, psmouse->packet[6]))) { | 1078 | (!alps_is_valid_first_byte(priv, psmouse->packet[6]))) { |
1079 | psmouse_dbg(psmouse, | 1079 | psmouse_dbg(psmouse, |
1080 | "refusing packet %4ph (suspected interleaved ps/2)\n", | 1080 | "refusing packet %4ph (suspected interleaved ps/2)\n", |
1081 | psmouse->packet + 3); | 1081 | psmouse->packet + 3); |
1082 | return PSMOUSE_BAD_DATA; | 1082 | return PSMOUSE_BAD_DATA; |
1083 | } | 1083 | } |
1084 | 1084 | ||
1085 | priv->process_packet(psmouse); | 1085 | priv->process_packet(psmouse); |
1086 | 1086 | ||
1087 | /* Continue with the next packet */ | 1087 | /* Continue with the next packet */ |
1088 | psmouse->packet[0] = psmouse->packet[6]; | 1088 | psmouse->packet[0] = psmouse->packet[6]; |
1089 | psmouse->pktcnt = 1; | 1089 | psmouse->pktcnt = 1; |
1090 | 1090 | ||
1091 | } else { | 1091 | } else { |
1092 | 1092 | ||
1093 | /* | 1093 | /* |
1094 | * High bit is 0 - that means that we indeed got a PS/2 | 1094 | * High bit is 0 - that means that we indeed got a PS/2 |
1095 | * packet in the middle of ALPS packet. | 1095 | * packet in the middle of ALPS packet. |
1096 | * | 1096 | * |
1097 | * There is also possibility that we got 6-byte ALPS | 1097 | * There is also possibility that we got 6-byte ALPS |
1098 | * packet followed by 3-byte packet from trackpoint. We | 1098 | * packet followed by 3-byte packet from trackpoint. We |
1099 | * can not distinguish between these 2 scenarios but | 1099 | * can not distinguish between these 2 scenarios but |
1100 | * because the latter is unlikely to happen in course of | 1100 | * because the latter is unlikely to happen in course of |
1101 | * normal operation (user would need to press all | 1101 | * normal operation (user would need to press all |
1102 | * buttons on the pad and start moving trackpoint | 1102 | * buttons on the pad and start moving trackpoint |
1103 | * without touching the pad surface) we assume former. | 1103 | * without touching the pad surface) we assume former. |
1104 | * Even if we are wrong the wost thing that would happen | 1104 | * Even if we are wrong the wost thing that would happen |
1105 | * the cursor would jump but we should not get protocol | 1105 | * the cursor would jump but we should not get protocol |
1106 | * de-synchronization. | 1106 | * de-synchronization. |
1107 | */ | 1107 | */ |
1108 | 1108 | ||
1109 | alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], | 1109 | alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], |
1110 | false); | 1110 | false); |
1111 | 1111 | ||
1112 | /* | 1112 | /* |
1113 | * Continue with the standard ALPS protocol handling, | 1113 | * Continue with the standard ALPS protocol handling, |
1114 | * but make sure we won't process it as an interleaved | 1114 | * but make sure we won't process it as an interleaved |
1115 | * packet again, which may happen if all buttons are | 1115 | * packet again, which may happen if all buttons are |
1116 | * pressed. To avoid this let's reset the 4th bit which | 1116 | * pressed. To avoid this let's reset the 4th bit which |
1117 | * is normally 1. | 1117 | * is normally 1. |
1118 | */ | 1118 | */ |
1119 | psmouse->packet[3] = psmouse->packet[6] & 0xf7; | 1119 | psmouse->packet[3] = psmouse->packet[6] & 0xf7; |
1120 | psmouse->pktcnt = 4; | 1120 | psmouse->pktcnt = 4; |
1121 | } | 1121 | } |
1122 | 1122 | ||
1123 | return PSMOUSE_GOOD_DATA; | 1123 | return PSMOUSE_GOOD_DATA; |
1124 | } | 1124 | } |
1125 | 1125 | ||
1126 | static void alps_flush_packet(unsigned long data) | 1126 | static void alps_flush_packet(unsigned long data) |
1127 | { | 1127 | { |
1128 | struct psmouse *psmouse = (struct psmouse *)data; | 1128 | struct psmouse *psmouse = (struct psmouse *)data; |
1129 | struct alps_data *priv = psmouse->private; | 1129 | struct alps_data *priv = psmouse->private; |
1130 | 1130 | ||
1131 | serio_pause_rx(psmouse->ps2dev.serio); | 1131 | serio_pause_rx(psmouse->ps2dev.serio); |
1132 | 1132 | ||
1133 | if (psmouse->pktcnt == psmouse->pktsize) { | 1133 | if (psmouse->pktcnt == psmouse->pktsize) { |
1134 | 1134 | ||
1135 | /* | 1135 | /* |
1136 | * We did not any more data in reasonable amount of time. | 1136 | * We did not any more data in reasonable amount of time. |
1137 | * Validate the last 3 bytes and process as a standard | 1137 | * Validate the last 3 bytes and process as a standard |
1138 | * ALPS packet. | 1138 | * ALPS packet. |
1139 | */ | 1139 | */ |
1140 | if ((psmouse->packet[3] | | 1140 | if ((psmouse->packet[3] | |
1141 | psmouse->packet[4] | | 1141 | psmouse->packet[4] | |
1142 | psmouse->packet[5]) & 0x80) { | 1142 | psmouse->packet[5]) & 0x80) { |
1143 | psmouse_dbg(psmouse, | 1143 | psmouse_dbg(psmouse, |
1144 | "refusing packet %3ph (suspected interleaved ps/2)\n", | 1144 | "refusing packet %3ph (suspected interleaved ps/2)\n", |
1145 | psmouse->packet + 3); | 1145 | psmouse->packet + 3); |
1146 | } else { | 1146 | } else { |
1147 | priv->process_packet(psmouse); | 1147 | priv->process_packet(psmouse); |
1148 | } | 1148 | } |
1149 | psmouse->pktcnt = 0; | 1149 | psmouse->pktcnt = 0; |
1150 | } | 1150 | } |
1151 | 1151 | ||
1152 | serio_continue_rx(psmouse->ps2dev.serio); | 1152 | serio_continue_rx(psmouse->ps2dev.serio); |
1153 | } | 1153 | } |
1154 | 1154 | ||
1155 | static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | 1155 | static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) |
1156 | { | 1156 | { |
1157 | struct alps_data *priv = psmouse->private; | 1157 | struct alps_data *priv = psmouse->private; |
1158 | 1158 | ||
1159 | if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ | 1159 | /* |
1160 | * Check if we are dealing with a bare PS/2 packet, presumably from | ||
1161 | * a device connected to the external PS/2 port. Because bare PS/2 | ||
1162 | * protocol does not have enough constant bits to self-synchronize | ||
1163 | * properly we only do this if the device is fully synchronized. | ||
1164 | */ | ||
1165 | if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) { | ||
1160 | if (psmouse->pktcnt == 3) { | 1166 | if (psmouse->pktcnt == 3) { |
1161 | alps_report_bare_ps2_packet(psmouse, psmouse->packet, | 1167 | alps_report_bare_ps2_packet(psmouse, psmouse->packet, |
1162 | true); | 1168 | true); |
1163 | return PSMOUSE_FULL_PACKET; | 1169 | return PSMOUSE_FULL_PACKET; |
1164 | } | 1170 | } |
1165 | return PSMOUSE_GOOD_DATA; | 1171 | return PSMOUSE_GOOD_DATA; |
1166 | } | 1172 | } |
1167 | 1173 | ||
1168 | /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ | 1174 | /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ |
1169 | 1175 | ||
1170 | if ((priv->flags & ALPS_PS2_INTERLEAVED) && | 1176 | if ((priv->flags & ALPS_PS2_INTERLEAVED) && |
1171 | psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) { | 1177 | psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) { |
1172 | return alps_handle_interleaved_ps2(psmouse); | 1178 | return alps_handle_interleaved_ps2(psmouse); |
1173 | } | 1179 | } |
1174 | 1180 | ||
1175 | if (!alps_is_valid_first_byte(priv, psmouse->packet[0])) { | 1181 | if (!alps_is_valid_first_byte(priv, psmouse->packet[0])) { |
1176 | psmouse_dbg(psmouse, | 1182 | psmouse_dbg(psmouse, |
1177 | "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", | 1183 | "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", |
1178 | psmouse->packet[0], priv->mask0, priv->byte0); | 1184 | psmouse->packet[0], priv->mask0, priv->byte0); |
1179 | return PSMOUSE_BAD_DATA; | 1185 | return PSMOUSE_BAD_DATA; |
1180 | } | 1186 | } |
1181 | 1187 | ||
1182 | /* Bytes 2 - pktsize should have 0 in the highest bit */ | 1188 | /* Bytes 2 - pktsize should have 0 in the highest bit */ |
1183 | if ((priv->proto_version < ALPS_PROTO_V5) && | 1189 | if (priv->proto_version < ALPS_PROTO_V5 && |
1184 | psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && | 1190 | psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && |
1185 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { | 1191 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { |
1186 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", | 1192 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", |
1187 | psmouse->pktcnt - 1, | 1193 | psmouse->pktcnt - 1, |
1188 | psmouse->packet[psmouse->pktcnt - 1]); | 1194 | psmouse->packet[psmouse->pktcnt - 1]); |
1195 | |||
1196 | if (priv->proto_version == ALPS_PROTO_V3 && | ||
1197 | psmouse->pktcnt == psmouse->pktsize) { | ||
1198 | /* | ||
1199 | * Some Dell boxes, such as Latitude E6440 or E7440 | ||
1200 | * with closed lid, quite often smash last byte of | ||
1201 | * otherwise valid packet with 0xff. Given that the | ||
1202 | * next packet is very likely to be valid let's | ||
1203 | * report PSMOUSE_FULL_PACKET but not process data, | ||
1204 | * rather than reporting PSMOUSE_BAD_DATA and | ||
1205 | * filling the logs. | ||
1206 | */ | ||
1207 | return PSMOUSE_FULL_PACKET; | ||
1208 | } | ||
1209 | |||
1189 | return PSMOUSE_BAD_DATA; | 1210 | return PSMOUSE_BAD_DATA; |
1190 | } | 1211 | } |
1191 | 1212 | ||
1192 | if (priv->proto_version == ALPS_PROTO_V7 && | 1213 | if (priv->proto_version == ALPS_PROTO_V7 && |
1193 | !alps_is_valid_package_v7(psmouse)) { | 1214 | !alps_is_valid_package_v7(psmouse)) { |
1194 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", | 1215 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", |
1195 | psmouse->pktcnt - 1, | 1216 | psmouse->pktcnt - 1, |
1196 | psmouse->packet[psmouse->pktcnt - 1]); | 1217 | psmouse->packet[psmouse->pktcnt - 1]); |
1197 | return PSMOUSE_BAD_DATA; | 1218 | return PSMOUSE_BAD_DATA; |
1198 | } | 1219 | } |
1199 | 1220 | ||
1200 | if (psmouse->pktcnt == psmouse->pktsize) { | 1221 | if (psmouse->pktcnt == psmouse->pktsize) { |
1201 | priv->process_packet(psmouse); | 1222 | priv->process_packet(psmouse); |
1202 | return PSMOUSE_FULL_PACKET; | 1223 | return PSMOUSE_FULL_PACKET; |
1203 | } | 1224 | } |
1204 | 1225 | ||
1205 | return PSMOUSE_GOOD_DATA; | 1226 | return PSMOUSE_GOOD_DATA; |
1206 | } | 1227 | } |
1207 | 1228 | ||
1208 | static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble) | 1229 | static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble) |
1209 | { | 1230 | { |
1210 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1231 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1211 | struct alps_data *priv = psmouse->private; | 1232 | struct alps_data *priv = psmouse->private; |
1212 | int command; | 1233 | int command; |
1213 | unsigned char *param; | 1234 | unsigned char *param; |
1214 | unsigned char dummy[4]; | 1235 | unsigned char dummy[4]; |
1215 | 1236 | ||
1216 | BUG_ON(nibble > 0xf); | 1237 | BUG_ON(nibble > 0xf); |
1217 | 1238 | ||
1218 | command = priv->nibble_commands[nibble].command; | 1239 | command = priv->nibble_commands[nibble].command; |
1219 | param = (command & 0x0f00) ? | 1240 | param = (command & 0x0f00) ? |
1220 | dummy : (unsigned char *)&priv->nibble_commands[nibble].data; | 1241 | dummy : (unsigned char *)&priv->nibble_commands[nibble].data; |
1221 | 1242 | ||
1222 | if (ps2_command(ps2dev, param, command)) | 1243 | if (ps2_command(ps2dev, param, command)) |
1223 | return -1; | 1244 | return -1; |
1224 | 1245 | ||
1225 | return 0; | 1246 | return 0; |
1226 | } | 1247 | } |
1227 | 1248 | ||
1228 | static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr) | 1249 | static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr) |
1229 | { | 1250 | { |
1230 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1251 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1231 | struct alps_data *priv = psmouse->private; | 1252 | struct alps_data *priv = psmouse->private; |
1232 | int i, nibble; | 1253 | int i, nibble; |
1233 | 1254 | ||
1234 | if (ps2_command(ps2dev, NULL, priv->addr_command)) | 1255 | if (ps2_command(ps2dev, NULL, priv->addr_command)) |
1235 | return -1; | 1256 | return -1; |
1236 | 1257 | ||
1237 | for (i = 12; i >= 0; i -= 4) { | 1258 | for (i = 12; i >= 0; i -= 4) { |
1238 | nibble = (addr >> i) & 0xf; | 1259 | nibble = (addr >> i) & 0xf; |
1239 | if (alps_command_mode_send_nibble(psmouse, nibble)) | 1260 | if (alps_command_mode_send_nibble(psmouse, nibble)) |
1240 | return -1; | 1261 | return -1; |
1241 | } | 1262 | } |
1242 | 1263 | ||
1243 | return 0; | 1264 | return 0; |
1244 | } | 1265 | } |
1245 | 1266 | ||
1246 | static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr) | 1267 | static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr) |
1247 | { | 1268 | { |
1248 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1269 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1249 | unsigned char param[4]; | 1270 | unsigned char param[4]; |
1250 | 1271 | ||
1251 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) | 1272 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) |
1252 | return -1; | 1273 | return -1; |
1253 | 1274 | ||
1254 | /* | 1275 | /* |
1255 | * The address being read is returned in the first two bytes | 1276 | * The address being read is returned in the first two bytes |
1256 | * of the result. Check that this address matches the expected | 1277 | * of the result. Check that this address matches the expected |
1257 | * address. | 1278 | * address. |
1258 | */ | 1279 | */ |
1259 | if (addr != ((param[0] << 8) | param[1])) | 1280 | if (addr != ((param[0] << 8) | param[1])) |
1260 | return -1; | 1281 | return -1; |
1261 | 1282 | ||
1262 | return param[2]; | 1283 | return param[2]; |
1263 | } | 1284 | } |
1264 | 1285 | ||
1265 | static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr) | 1286 | static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr) |
1266 | { | 1287 | { |
1267 | if (alps_command_mode_set_addr(psmouse, addr)) | 1288 | if (alps_command_mode_set_addr(psmouse, addr)) |
1268 | return -1; | 1289 | return -1; |
1269 | return __alps_command_mode_read_reg(psmouse, addr); | 1290 | return __alps_command_mode_read_reg(psmouse, addr); |
1270 | } | 1291 | } |
1271 | 1292 | ||
1272 | static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value) | 1293 | static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value) |
1273 | { | 1294 | { |
1274 | if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf)) | 1295 | if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf)) |
1275 | return -1; | 1296 | return -1; |
1276 | if (alps_command_mode_send_nibble(psmouse, value & 0xf)) | 1297 | if (alps_command_mode_send_nibble(psmouse, value & 0xf)) |
1277 | return -1; | 1298 | return -1; |
1278 | return 0; | 1299 | return 0; |
1279 | } | 1300 | } |
1280 | 1301 | ||
1281 | static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, | 1302 | static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, |
1282 | u8 value) | 1303 | u8 value) |
1283 | { | 1304 | { |
1284 | if (alps_command_mode_set_addr(psmouse, addr)) | 1305 | if (alps_command_mode_set_addr(psmouse, addr)) |
1285 | return -1; | 1306 | return -1; |
1286 | return __alps_command_mode_write_reg(psmouse, value); | 1307 | return __alps_command_mode_write_reg(psmouse, value); |
1287 | } | 1308 | } |
1288 | 1309 | ||
1289 | static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, | 1310 | static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, |
1290 | int repeated_command, unsigned char *param) | 1311 | int repeated_command, unsigned char *param) |
1291 | { | 1312 | { |
1292 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1313 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1293 | 1314 | ||
1294 | param[0] = 0; | 1315 | param[0] = 0; |
1295 | if (init_command && ps2_command(ps2dev, param, init_command)) | 1316 | if (init_command && ps2_command(ps2dev, param, init_command)) |
1296 | return -EIO; | 1317 | return -EIO; |
1297 | 1318 | ||
1298 | if (ps2_command(ps2dev, NULL, repeated_command) || | 1319 | if (ps2_command(ps2dev, NULL, repeated_command) || |
1299 | ps2_command(ps2dev, NULL, repeated_command) || | 1320 | ps2_command(ps2dev, NULL, repeated_command) || |
1300 | ps2_command(ps2dev, NULL, repeated_command)) | 1321 | ps2_command(ps2dev, NULL, repeated_command)) |
1301 | return -EIO; | 1322 | return -EIO; |
1302 | 1323 | ||
1303 | param[0] = param[1] = param[2] = 0xff; | 1324 | param[0] = param[1] = param[2] = 0xff; |
1304 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) | 1325 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) |
1305 | return -EIO; | 1326 | return -EIO; |
1306 | 1327 | ||
1307 | psmouse_dbg(psmouse, "%2.2X report: %3ph\n", | 1328 | psmouse_dbg(psmouse, "%2.2X report: %3ph\n", |
1308 | repeated_command, param); | 1329 | repeated_command, param); |
1309 | return 0; | 1330 | return 0; |
1310 | } | 1331 | } |
1311 | 1332 | ||
1312 | static bool alps_check_valid_firmware_id(unsigned char id[]) | 1333 | static bool alps_check_valid_firmware_id(unsigned char id[]) |
1313 | { | 1334 | { |
1314 | if (id[0] == 0x73) | 1335 | if (id[0] == 0x73) |
1315 | return true; | 1336 | return true; |
1316 | 1337 | ||
1317 | if (id[0] == 0x88 && | 1338 | if (id[0] == 0x88 && |
1318 | (id[1] == 0x07 || | 1339 | (id[1] == 0x07 || |
1319 | id[1] == 0x08 || | 1340 | id[1] == 0x08 || |
1320 | (id[1] & 0xf0) == 0xb0 || | 1341 | (id[1] & 0xf0) == 0xb0 || |
1321 | (id[1] & 0xf0) == 0xc0)) { | 1342 | (id[1] & 0xf0) == 0xc0)) { |
1322 | return true; | 1343 | return true; |
1323 | } | 1344 | } |
1324 | 1345 | ||
1325 | return false; | 1346 | return false; |
1326 | } | 1347 | } |
1327 | 1348 | ||
1328 | static int alps_enter_command_mode(struct psmouse *psmouse) | 1349 | static int alps_enter_command_mode(struct psmouse *psmouse) |
1329 | { | 1350 | { |
1330 | unsigned char param[4]; | 1351 | unsigned char param[4]; |
1331 | 1352 | ||
1332 | if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) { | 1353 | if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) { |
1333 | psmouse_err(psmouse, "failed to enter command mode\n"); | 1354 | psmouse_err(psmouse, "failed to enter command mode\n"); |
1334 | return -1; | 1355 | return -1; |
1335 | } | 1356 | } |
1336 | 1357 | ||
1337 | if (!alps_check_valid_firmware_id(param)) { | 1358 | if (!alps_check_valid_firmware_id(param)) { |
1338 | psmouse_dbg(psmouse, | 1359 | psmouse_dbg(psmouse, |
1339 | "unknown response while entering command mode\n"); | 1360 | "unknown response while entering command mode\n"); |
1340 | return -1; | 1361 | return -1; |
1341 | } | 1362 | } |
1342 | return 0; | 1363 | return 0; |
1343 | } | 1364 | } |
1344 | 1365 | ||
1345 | static inline int alps_exit_command_mode(struct psmouse *psmouse) | 1366 | static inline int alps_exit_command_mode(struct psmouse *psmouse) |
1346 | { | 1367 | { |
1347 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1368 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1348 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) | 1369 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) |
1349 | return -1; | 1370 | return -1; |
1350 | return 0; | 1371 | return 0; |
1351 | } | 1372 | } |
1352 | 1373 | ||
1353 | /* | 1374 | /* |
1354 | * For DualPoint devices select the device that should respond to | 1375 | * For DualPoint devices select the device that should respond to |
1355 | * subsequent commands. It looks like glidepad is behind stickpointer, | 1376 | * subsequent commands. It looks like glidepad is behind stickpointer, |
1356 | * I'd thought it would be other way around... | 1377 | * I'd thought it would be other way around... |
1357 | */ | 1378 | */ |
1358 | static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable) | 1379 | static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable) |
1359 | { | 1380 | { |
1360 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1381 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1361 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; | 1382 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; |
1362 | 1383 | ||
1363 | if (ps2_command(ps2dev, NULL, cmd) || | 1384 | if (ps2_command(ps2dev, NULL, cmd) || |
1364 | ps2_command(ps2dev, NULL, cmd) || | 1385 | ps2_command(ps2dev, NULL, cmd) || |
1365 | ps2_command(ps2dev, NULL, cmd) || | 1386 | ps2_command(ps2dev, NULL, cmd) || |
1366 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE)) | 1387 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE)) |
1367 | return -1; | 1388 | return -1; |
1368 | 1389 | ||
1369 | /* we may get 3 more bytes, just ignore them */ | 1390 | /* we may get 3 more bytes, just ignore them */ |
1370 | ps2_drain(ps2dev, 3, 100); | 1391 | ps2_drain(ps2dev, 3, 100); |
1371 | 1392 | ||
1372 | return 0; | 1393 | return 0; |
1373 | } | 1394 | } |
1374 | 1395 | ||
1375 | static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) | 1396 | static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) |
1376 | { | 1397 | { |
1377 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1398 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1378 | 1399 | ||
1379 | /* Try ALPS magic knock - 4 disable before enable */ | 1400 | /* Try ALPS magic knock - 4 disable before enable */ |
1380 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || | 1401 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || |
1381 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || | 1402 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || |
1382 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || | 1403 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || |
1383 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || | 1404 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || |
1384 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) | 1405 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) |
1385 | return -1; | 1406 | return -1; |
1386 | 1407 | ||
1387 | /* | 1408 | /* |
1388 | * Switch mouse to poll (remote) mode so motion data will not | 1409 | * Switch mouse to poll (remote) mode so motion data will not |
1389 | * get in our way | 1410 | * get in our way |
1390 | */ | 1411 | */ |
1391 | return ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETPOLL); | 1412 | return ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETPOLL); |
1392 | } | 1413 | } |
1393 | 1414 | ||
1394 | static int alps_monitor_mode_send_word(struct psmouse *psmouse, u16 word) | 1415 | static int alps_monitor_mode_send_word(struct psmouse *psmouse, u16 word) |
1395 | { | 1416 | { |
1396 | int i, nibble; | 1417 | int i, nibble; |
1397 | 1418 | ||
1398 | /* | 1419 | /* |
1399 | * b0-b11 are valid bits, send sequence is inverse. | 1420 | * b0-b11 are valid bits, send sequence is inverse. |
1400 | * e.g. when word = 0x0123, nibble send sequence is 3, 2, 1 | 1421 | * e.g. when word = 0x0123, nibble send sequence is 3, 2, 1 |
1401 | */ | 1422 | */ |
1402 | for (i = 0; i <= 8; i += 4) { | 1423 | for (i = 0; i <= 8; i += 4) { |
1403 | nibble = (word >> i) & 0xf; | 1424 | nibble = (word >> i) & 0xf; |
1404 | if (alps_command_mode_send_nibble(psmouse, nibble)) | 1425 | if (alps_command_mode_send_nibble(psmouse, nibble)) |
1405 | return -1; | 1426 | return -1; |
1406 | } | 1427 | } |
1407 | 1428 | ||
1408 | return 0; | 1429 | return 0; |
1409 | } | 1430 | } |
1410 | 1431 | ||
1411 | static int alps_monitor_mode_write_reg(struct psmouse *psmouse, | 1432 | static int alps_monitor_mode_write_reg(struct psmouse *psmouse, |
1412 | u16 addr, u16 value) | 1433 | u16 addr, u16 value) |
1413 | { | 1434 | { |
1414 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1435 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1415 | 1436 | ||
1416 | /* 0x0A0 is the command to write the word */ | 1437 | /* 0x0A0 is the command to write the word */ |
1417 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE) || | 1438 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE) || |
1418 | alps_monitor_mode_send_word(psmouse, 0x0A0) || | 1439 | alps_monitor_mode_send_word(psmouse, 0x0A0) || |
1419 | alps_monitor_mode_send_word(psmouse, addr) || | 1440 | alps_monitor_mode_send_word(psmouse, addr) || |
1420 | alps_monitor_mode_send_word(psmouse, value) || | 1441 | alps_monitor_mode_send_word(psmouse, value) || |
1421 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE)) | 1442 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE)) |
1422 | return -1; | 1443 | return -1; |
1423 | 1444 | ||
1424 | return 0; | 1445 | return 0; |
1425 | } | 1446 | } |
1426 | 1447 | ||
1427 | static int alps_monitor_mode(struct psmouse *psmouse, bool enable) | 1448 | static int alps_monitor_mode(struct psmouse *psmouse, bool enable) |
1428 | { | 1449 | { |
1429 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1450 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1430 | 1451 | ||
1431 | if (enable) { | 1452 | if (enable) { |
1432 | /* EC E9 F5 F5 E7 E6 E7 E9 to enter monitor mode */ | 1453 | /* EC E9 F5 F5 E7 E6 E7 E9 to enter monitor mode */ |
1433 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || | 1454 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || |
1434 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO) || | 1455 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO) || |
1435 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || | 1456 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || |
1436 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || | 1457 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || |
1437 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || | 1458 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || |
1438 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 1459 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
1439 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || | 1460 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || |
1440 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO)) | 1461 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO)) |
1441 | return -1; | 1462 | return -1; |
1442 | } else { | 1463 | } else { |
1443 | /* EC to exit monitor mode */ | 1464 | /* EC to exit monitor mode */ |
1444 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP)) | 1465 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP)) |
1445 | return -1; | 1466 | return -1; |
1446 | } | 1467 | } |
1447 | 1468 | ||
1448 | return 0; | 1469 | return 0; |
1449 | } | 1470 | } |
1450 | 1471 | ||
1451 | static int alps_absolute_mode_v6(struct psmouse *psmouse) | 1472 | static int alps_absolute_mode_v6(struct psmouse *psmouse) |
1452 | { | 1473 | { |
1453 | u16 reg_val = 0x181; | 1474 | u16 reg_val = 0x181; |
1454 | int ret = -1; | 1475 | int ret = -1; |
1455 | 1476 | ||
1456 | /* enter monitor mode, to write the register */ | 1477 | /* enter monitor mode, to write the register */ |
1457 | if (alps_monitor_mode(psmouse, true)) | 1478 | if (alps_monitor_mode(psmouse, true)) |
1458 | return -1; | 1479 | return -1; |
1459 | 1480 | ||
1460 | ret = alps_monitor_mode_write_reg(psmouse, 0x000, reg_val); | 1481 | ret = alps_monitor_mode_write_reg(psmouse, 0x000, reg_val); |
1461 | 1482 | ||
1462 | if (alps_monitor_mode(psmouse, false)) | 1483 | if (alps_monitor_mode(psmouse, false)) |
1463 | ret = -1; | 1484 | ret = -1; |
1464 | 1485 | ||
1465 | return ret; | 1486 | return ret; |
1466 | } | 1487 | } |
1467 | 1488 | ||
1468 | static int alps_get_status(struct psmouse *psmouse, char *param) | 1489 | static int alps_get_status(struct psmouse *psmouse, char *param) |
1469 | { | 1490 | { |
1470 | /* Get status: 0xF5 0xF5 0xF5 0xE9 */ | 1491 | /* Get status: 0xF5 0xF5 0xF5 0xE9 */ |
1471 | if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_DISABLE, param)) | 1492 | if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_DISABLE, param)) |
1472 | return -1; | 1493 | return -1; |
1473 | 1494 | ||
1474 | return 0; | 1495 | return 0; |
1475 | } | 1496 | } |
1476 | 1497 | ||
1477 | /* | 1498 | /* |
1478 | * Turn touchpad tapping on or off. The sequences are: | 1499 | * Turn touchpad tapping on or off. The sequences are: |
1479 | * 0xE9 0xF5 0xF5 0xF3 0x0A to enable, | 1500 | * 0xE9 0xF5 0xF5 0xF3 0x0A to enable, |
1480 | * 0xE9 0xF5 0xF5 0xE8 0x00 to disable. | 1501 | * 0xE9 0xF5 0xF5 0xE8 0x00 to disable. |
1481 | * My guess that 0xE9 (GetInfo) is here as a sync point. | 1502 | * My guess that 0xE9 (GetInfo) is here as a sync point. |
1482 | * For models that also have stickpointer (DualPoints) its tapping | 1503 | * For models that also have stickpointer (DualPoints) its tapping |
1483 | * is controlled separately (0xE6 0xE6 0xE6 0xF3 0x14|0x0A) but | 1504 | * is controlled separately (0xE6 0xE6 0xE6 0xF3 0x14|0x0A) but |
1484 | * we don't fiddle with it. | 1505 | * we don't fiddle with it. |
1485 | */ | 1506 | */ |
1486 | static int alps_tap_mode(struct psmouse *psmouse, int enable) | 1507 | static int alps_tap_mode(struct psmouse *psmouse, int enable) |
1487 | { | 1508 | { |
1488 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1509 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1489 | int cmd = enable ? PSMOUSE_CMD_SETRATE : PSMOUSE_CMD_SETRES; | 1510 | int cmd = enable ? PSMOUSE_CMD_SETRATE : PSMOUSE_CMD_SETRES; |
1490 | unsigned char tap_arg = enable ? 0x0A : 0x00; | 1511 | unsigned char tap_arg = enable ? 0x0A : 0x00; |
1491 | unsigned char param[4]; | 1512 | unsigned char param[4]; |
1492 | 1513 | ||
1493 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) || | 1514 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) || |
1494 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || | 1515 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || |
1495 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || | 1516 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || |
1496 | ps2_command(ps2dev, &tap_arg, cmd)) | 1517 | ps2_command(ps2dev, &tap_arg, cmd)) |
1497 | return -1; | 1518 | return -1; |
1498 | 1519 | ||
1499 | if (alps_get_status(psmouse, param)) | 1520 | if (alps_get_status(psmouse, param)) |
1500 | return -1; | 1521 | return -1; |
1501 | 1522 | ||
1502 | return 0; | 1523 | return 0; |
1503 | } | 1524 | } |
1504 | 1525 | ||
1505 | /* | 1526 | /* |
1506 | * alps_poll() - poll the touchpad for current motion packet. | 1527 | * alps_poll() - poll the touchpad for current motion packet. |
1507 | * Used in resync. | 1528 | * Used in resync. |
1508 | */ | 1529 | */ |
1509 | static int alps_poll(struct psmouse *psmouse) | 1530 | static int alps_poll(struct psmouse *psmouse) |
1510 | { | 1531 | { |
1511 | struct alps_data *priv = psmouse->private; | 1532 | struct alps_data *priv = psmouse->private; |
1512 | unsigned char buf[sizeof(psmouse->packet)]; | 1533 | unsigned char buf[sizeof(psmouse->packet)]; |
1513 | bool poll_failed; | 1534 | bool poll_failed; |
1514 | 1535 | ||
1515 | if (priv->flags & ALPS_PASS) | 1536 | if (priv->flags & ALPS_PASS) |
1516 | alps_passthrough_mode_v2(psmouse, true); | 1537 | alps_passthrough_mode_v2(psmouse, true); |
1517 | 1538 | ||
1518 | poll_failed = ps2_command(&psmouse->ps2dev, buf, | 1539 | poll_failed = ps2_command(&psmouse->ps2dev, buf, |
1519 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; | 1540 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; |
1520 | 1541 | ||
1521 | if (priv->flags & ALPS_PASS) | 1542 | if (priv->flags & ALPS_PASS) |
1522 | alps_passthrough_mode_v2(psmouse, false); | 1543 | alps_passthrough_mode_v2(psmouse, false); |
1523 | 1544 | ||
1524 | if (poll_failed || (buf[0] & priv->mask0) != priv->byte0) | 1545 | if (poll_failed || (buf[0] & priv->mask0) != priv->byte0) |
1525 | return -1; | 1546 | return -1; |
1526 | 1547 | ||
1527 | if ((psmouse->badbyte & 0xc8) == 0x08) { | 1548 | if ((psmouse->badbyte & 0xc8) == 0x08) { |
1528 | /* | 1549 | /* |
1529 | * Poll the track stick ... | 1550 | * Poll the track stick ... |
1530 | */ | 1551 | */ |
1531 | if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8))) | 1552 | if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8))) |
1532 | return -1; | 1553 | return -1; |
1533 | } | 1554 | } |
1534 | 1555 | ||
1535 | memcpy(psmouse->packet, buf, sizeof(buf)); | 1556 | memcpy(psmouse->packet, buf, sizeof(buf)); |
1536 | return 0; | 1557 | return 0; |
1537 | } | 1558 | } |
1538 | 1559 | ||
1539 | static int alps_hw_init_v1_v2(struct psmouse *psmouse) | 1560 | static int alps_hw_init_v1_v2(struct psmouse *psmouse) |
1540 | { | 1561 | { |
1541 | struct alps_data *priv = psmouse->private; | 1562 | struct alps_data *priv = psmouse->private; |
1542 | 1563 | ||
1543 | if ((priv->flags & ALPS_PASS) && | 1564 | if ((priv->flags & ALPS_PASS) && |
1544 | alps_passthrough_mode_v2(psmouse, true)) { | 1565 | alps_passthrough_mode_v2(psmouse, true)) { |
1545 | return -1; | 1566 | return -1; |
1546 | } | 1567 | } |
1547 | 1568 | ||
1548 | if (alps_tap_mode(psmouse, true)) { | 1569 | if (alps_tap_mode(psmouse, true)) { |
1549 | psmouse_warn(psmouse, "Failed to enable hardware tapping\n"); | 1570 | psmouse_warn(psmouse, "Failed to enable hardware tapping\n"); |
1550 | return -1; | 1571 | return -1; |
1551 | } | 1572 | } |
1552 | 1573 | ||
1553 | if (alps_absolute_mode_v1_v2(psmouse)) { | 1574 | if (alps_absolute_mode_v1_v2(psmouse)) { |
1554 | psmouse_err(psmouse, "Failed to enable absolute mode\n"); | 1575 | psmouse_err(psmouse, "Failed to enable absolute mode\n"); |
1555 | return -1; | 1576 | return -1; |
1556 | } | 1577 | } |
1557 | 1578 | ||
1558 | if ((priv->flags & ALPS_PASS) && | 1579 | if ((priv->flags & ALPS_PASS) && |
1559 | alps_passthrough_mode_v2(psmouse, false)) { | 1580 | alps_passthrough_mode_v2(psmouse, false)) { |
1560 | return -1; | 1581 | return -1; |
1561 | } | 1582 | } |
1562 | 1583 | ||
1563 | /* ALPS needs stream mode, otherwise it won't report any data */ | 1584 | /* ALPS needs stream mode, otherwise it won't report any data */ |
1564 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) { | 1585 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) { |
1565 | psmouse_err(psmouse, "Failed to enable stream mode\n"); | 1586 | psmouse_err(psmouse, "Failed to enable stream mode\n"); |
1566 | return -1; | 1587 | return -1; |
1567 | } | 1588 | } |
1568 | 1589 | ||
1569 | return 0; | 1590 | return 0; |
1570 | } | 1591 | } |
1571 | 1592 | ||
1572 | static int alps_hw_init_v6(struct psmouse *psmouse) | 1593 | static int alps_hw_init_v6(struct psmouse *psmouse) |
1573 | { | 1594 | { |
1574 | unsigned char param[2] = {0xC8, 0x14}; | 1595 | unsigned char param[2] = {0xC8, 0x14}; |
1575 | 1596 | ||
1576 | /* Enter passthrough mode to let trackpoint enter 6byte raw mode */ | 1597 | /* Enter passthrough mode to let trackpoint enter 6byte raw mode */ |
1577 | if (alps_passthrough_mode_v2(psmouse, true)) | 1598 | if (alps_passthrough_mode_v2(psmouse, true)) |
1578 | return -1; | 1599 | return -1; |
1579 | 1600 | ||
1580 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 1601 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
1581 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 1602 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
1582 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 1603 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
1583 | ps2_command(&psmouse->ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || | 1604 | ps2_command(&psmouse->ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || |
1584 | ps2_command(&psmouse->ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) | 1605 | ps2_command(&psmouse->ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) |
1585 | return -1; | 1606 | return -1; |
1586 | 1607 | ||
1587 | if (alps_passthrough_mode_v2(psmouse, false)) | 1608 | if (alps_passthrough_mode_v2(psmouse, false)) |
1588 | return -1; | 1609 | return -1; |
1589 | 1610 | ||
1590 | if (alps_absolute_mode_v6(psmouse)) { | 1611 | if (alps_absolute_mode_v6(psmouse)) { |
1591 | psmouse_err(psmouse, "Failed to enable absolute mode\n"); | 1612 | psmouse_err(psmouse, "Failed to enable absolute mode\n"); |
1592 | return -1; | 1613 | return -1; |
1593 | } | 1614 | } |
1594 | 1615 | ||
1595 | return 0; | 1616 | return 0; |
1596 | } | 1617 | } |
1597 | 1618 | ||
1598 | /* | 1619 | /* |
1599 | * Enable or disable passthrough mode to the trackstick. | 1620 | * Enable or disable passthrough mode to the trackstick. |
1600 | */ | 1621 | */ |
1601 | static int alps_passthrough_mode_v3(struct psmouse *psmouse, | 1622 | static int alps_passthrough_mode_v3(struct psmouse *psmouse, |
1602 | int reg_base, bool enable) | 1623 | int reg_base, bool enable) |
1603 | { | 1624 | { |
1604 | int reg_val, ret = -1; | 1625 | int reg_val, ret = -1; |
1605 | 1626 | ||
1606 | if (alps_enter_command_mode(psmouse)) | 1627 | if (alps_enter_command_mode(psmouse)) |
1607 | return -1; | 1628 | return -1; |
1608 | 1629 | ||
1609 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); | 1630 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); |
1610 | if (reg_val == -1) | 1631 | if (reg_val == -1) |
1611 | goto error; | 1632 | goto error; |
1612 | 1633 | ||
1613 | if (enable) | 1634 | if (enable) |
1614 | reg_val |= 0x01; | 1635 | reg_val |= 0x01; |
1615 | else | 1636 | else |
1616 | reg_val &= ~0x01; | 1637 | reg_val &= ~0x01; |
1617 | 1638 | ||
1618 | ret = __alps_command_mode_write_reg(psmouse, reg_val); | 1639 | ret = __alps_command_mode_write_reg(psmouse, reg_val); |
1619 | 1640 | ||
1620 | error: | 1641 | error: |
1621 | if (alps_exit_command_mode(psmouse)) | 1642 | if (alps_exit_command_mode(psmouse)) |
1622 | ret = -1; | 1643 | ret = -1; |
1623 | return ret; | 1644 | return ret; |
1624 | } | 1645 | } |
1625 | 1646 | ||
1626 | /* Must be in command mode when calling this function */ | 1647 | /* Must be in command mode when calling this function */ |
1627 | static int alps_absolute_mode_v3(struct psmouse *psmouse) | 1648 | static int alps_absolute_mode_v3(struct psmouse *psmouse) |
1628 | { | 1649 | { |
1629 | int reg_val; | 1650 | int reg_val; |
1630 | 1651 | ||
1631 | reg_val = alps_command_mode_read_reg(psmouse, 0x0004); | 1652 | reg_val = alps_command_mode_read_reg(psmouse, 0x0004); |
1632 | if (reg_val == -1) | 1653 | if (reg_val == -1) |
1633 | return -1; | 1654 | return -1; |
1634 | 1655 | ||
1635 | reg_val |= 0x06; | 1656 | reg_val |= 0x06; |
1636 | if (__alps_command_mode_write_reg(psmouse, reg_val)) | 1657 | if (__alps_command_mode_write_reg(psmouse, reg_val)) |
1637 | return -1; | 1658 | return -1; |
1638 | 1659 | ||
1639 | return 0; | 1660 | return 0; |
1640 | } | 1661 | } |
1641 | 1662 | ||
1642 | static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) | 1663 | static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) |
1643 | { | 1664 | { |
1644 | int ret = -EIO, reg_val; | 1665 | int ret = -EIO, reg_val; |
1645 | 1666 | ||
1646 | if (alps_enter_command_mode(psmouse)) | 1667 | if (alps_enter_command_mode(psmouse)) |
1647 | goto error; | 1668 | goto error; |
1648 | 1669 | ||
1649 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); | 1670 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); |
1650 | if (reg_val == -1) | 1671 | if (reg_val == -1) |
1651 | goto error; | 1672 | goto error; |
1652 | 1673 | ||
1653 | /* bit 7: trackstick is present */ | 1674 | /* bit 7: trackstick is present */ |
1654 | ret = reg_val & 0x80 ? 0 : -ENODEV; | 1675 | ret = reg_val & 0x80 ? 0 : -ENODEV; |
1655 | 1676 | ||
1656 | error: | 1677 | error: |
1657 | alps_exit_command_mode(psmouse); | 1678 | alps_exit_command_mode(psmouse); |
1658 | return ret; | 1679 | return ret; |
1659 | } | 1680 | } |
1660 | 1681 | ||
1661 | static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) | 1682 | static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) |
1662 | { | 1683 | { |
1663 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1684 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1664 | int ret = 0; | 1685 | int ret = 0; |
1665 | unsigned char param[4]; | 1686 | unsigned char param[4]; |
1666 | 1687 | ||
1667 | if (alps_passthrough_mode_v3(psmouse, reg_base, true)) | 1688 | if (alps_passthrough_mode_v3(psmouse, reg_base, true)) |
1668 | return -EIO; | 1689 | return -EIO; |
1669 | 1690 | ||
1670 | /* | 1691 | /* |
1671 | * E7 report for the trackstick | 1692 | * E7 report for the trackstick |
1672 | * | 1693 | * |
1673 | * There have been reports of failures to seem to trace back | 1694 | * There have been reports of failures to seem to trace back |
1674 | * to the above trackstick check failing. When these occur | 1695 | * to the above trackstick check failing. When these occur |
1675 | * this E7 report fails, so when that happens we continue | 1696 | * this E7 report fails, so when that happens we continue |
1676 | * with the assumption that there isn't a trackstick after | 1697 | * with the assumption that there isn't a trackstick after |
1677 | * all. | 1698 | * all. |
1678 | */ | 1699 | */ |
1679 | if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) { | 1700 | if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) { |
1680 | psmouse_warn(psmouse, "trackstick E7 report failed\n"); | 1701 | psmouse_warn(psmouse, "trackstick E7 report failed\n"); |
1681 | ret = -ENODEV; | 1702 | ret = -ENODEV; |
1682 | } else { | 1703 | } else { |
1683 | psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param); | 1704 | psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param); |
1684 | 1705 | ||
1685 | /* | 1706 | /* |
1686 | * Not sure what this does, but it is absolutely | 1707 | * Not sure what this does, but it is absolutely |
1687 | * essential. Without it, the touchpad does not | 1708 | * essential. Without it, the touchpad does not |
1688 | * work at all and the trackstick just emits normal | 1709 | * work at all and the trackstick just emits normal |
1689 | * PS/2 packets. | 1710 | * PS/2 packets. |
1690 | */ | 1711 | */ |
1691 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 1712 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
1692 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 1713 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
1693 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 1714 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
1694 | alps_command_mode_send_nibble(psmouse, 0x9) || | 1715 | alps_command_mode_send_nibble(psmouse, 0x9) || |
1695 | alps_command_mode_send_nibble(psmouse, 0x4)) { | 1716 | alps_command_mode_send_nibble(psmouse, 0x4)) { |
1696 | psmouse_err(psmouse, | 1717 | psmouse_err(psmouse, |
1697 | "Error sending magic E6 sequence\n"); | 1718 | "Error sending magic E6 sequence\n"); |
1698 | ret = -EIO; | 1719 | ret = -EIO; |
1699 | goto error; | 1720 | goto error; |
1700 | } | 1721 | } |
1701 | 1722 | ||
1702 | /* | 1723 | /* |
1703 | * This ensures the trackstick packets are in the format | 1724 | * This ensures the trackstick packets are in the format |
1704 | * supported by this driver. If bit 1 isn't set the packet | 1725 | * supported by this driver. If bit 1 isn't set the packet |
1705 | * format is different. | 1726 | * format is different. |
1706 | */ | 1727 | */ |
1707 | if (alps_enter_command_mode(psmouse) || | 1728 | if (alps_enter_command_mode(psmouse) || |
1708 | alps_command_mode_write_reg(psmouse, | 1729 | alps_command_mode_write_reg(psmouse, |
1709 | reg_base + 0x08, 0x82) || | 1730 | reg_base + 0x08, 0x82) || |
1710 | alps_exit_command_mode(psmouse)) | 1731 | alps_exit_command_mode(psmouse)) |
1711 | ret = -EIO; | 1732 | ret = -EIO; |
1712 | } | 1733 | } |
1713 | 1734 | ||
1714 | error: | 1735 | error: |
1715 | if (alps_passthrough_mode_v3(psmouse, reg_base, false)) | 1736 | if (alps_passthrough_mode_v3(psmouse, reg_base, false)) |
1716 | ret = -EIO; | 1737 | ret = -EIO; |
1717 | 1738 | ||
1718 | return ret; | 1739 | return ret; |
1719 | } | 1740 | } |
1720 | 1741 | ||
1721 | static int alps_hw_init_v3(struct psmouse *psmouse) | 1742 | static int alps_hw_init_v3(struct psmouse *psmouse) |
1722 | { | 1743 | { |
1723 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1744 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1724 | int reg_val; | 1745 | int reg_val; |
1725 | unsigned char param[4]; | 1746 | unsigned char param[4]; |
1726 | 1747 | ||
1727 | reg_val = alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE); | 1748 | reg_val = alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE); |
1728 | if (reg_val == -EIO) | 1749 | if (reg_val == -EIO) |
1729 | goto error; | 1750 | goto error; |
1730 | 1751 | ||
1731 | if (reg_val == 0 && | 1752 | if (reg_val == 0 && |
1732 | alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) | 1753 | alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) |
1733 | goto error; | 1754 | goto error; |
1734 | 1755 | ||
1735 | if (alps_enter_command_mode(psmouse) || | 1756 | if (alps_enter_command_mode(psmouse) || |
1736 | alps_absolute_mode_v3(psmouse)) { | 1757 | alps_absolute_mode_v3(psmouse)) { |
1737 | psmouse_err(psmouse, "Failed to enter absolute mode\n"); | 1758 | psmouse_err(psmouse, "Failed to enter absolute mode\n"); |
1738 | goto error; | 1759 | goto error; |
1739 | } | 1760 | } |
1740 | 1761 | ||
1741 | reg_val = alps_command_mode_read_reg(psmouse, 0x0006); | 1762 | reg_val = alps_command_mode_read_reg(psmouse, 0x0006); |
1742 | if (reg_val == -1) | 1763 | if (reg_val == -1) |
1743 | goto error; | 1764 | goto error; |
1744 | if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) | 1765 | if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) |
1745 | goto error; | 1766 | goto error; |
1746 | 1767 | ||
1747 | reg_val = alps_command_mode_read_reg(psmouse, 0x0007); | 1768 | reg_val = alps_command_mode_read_reg(psmouse, 0x0007); |
1748 | if (reg_val == -1) | 1769 | if (reg_val == -1) |
1749 | goto error; | 1770 | goto error; |
1750 | if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) | 1771 | if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01)) |
1751 | goto error; | 1772 | goto error; |
1752 | 1773 | ||
1753 | if (alps_command_mode_read_reg(psmouse, 0x0144) == -1) | 1774 | if (alps_command_mode_read_reg(psmouse, 0x0144) == -1) |
1754 | goto error; | 1775 | goto error; |
1755 | if (__alps_command_mode_write_reg(psmouse, 0x04)) | 1776 | if (__alps_command_mode_write_reg(psmouse, 0x04)) |
1756 | goto error; | 1777 | goto error; |
1757 | 1778 | ||
1758 | if (alps_command_mode_read_reg(psmouse, 0x0159) == -1) | 1779 | if (alps_command_mode_read_reg(psmouse, 0x0159) == -1) |
1759 | goto error; | 1780 | goto error; |
1760 | if (__alps_command_mode_write_reg(psmouse, 0x03)) | 1781 | if (__alps_command_mode_write_reg(psmouse, 0x03)) |
1761 | goto error; | 1782 | goto error; |
1762 | 1783 | ||
1763 | if (alps_command_mode_read_reg(psmouse, 0x0163) == -1) | 1784 | if (alps_command_mode_read_reg(psmouse, 0x0163) == -1) |
1764 | goto error; | 1785 | goto error; |
1765 | if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03)) | 1786 | if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03)) |
1766 | goto error; | 1787 | goto error; |
1767 | 1788 | ||
1768 | if (alps_command_mode_read_reg(psmouse, 0x0162) == -1) | 1789 | if (alps_command_mode_read_reg(psmouse, 0x0162) == -1) |
1769 | goto error; | 1790 | goto error; |
1770 | if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) | 1791 | if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) |
1771 | goto error; | 1792 | goto error; |
1772 | 1793 | ||
1773 | alps_exit_command_mode(psmouse); | 1794 | alps_exit_command_mode(psmouse); |
1774 | 1795 | ||
1775 | /* Set rate and enable data reporting */ | 1796 | /* Set rate and enable data reporting */ |
1776 | param[0] = 0x64; | 1797 | param[0] = 0x64; |
1777 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || | 1798 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || |
1778 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { | 1799 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { |
1779 | psmouse_err(psmouse, "Failed to enable data reporting\n"); | 1800 | psmouse_err(psmouse, "Failed to enable data reporting\n"); |
1780 | return -1; | 1801 | return -1; |
1781 | } | 1802 | } |
1782 | 1803 | ||
1783 | return 0; | 1804 | return 0; |
1784 | 1805 | ||
1785 | error: | 1806 | error: |
1786 | /* | 1807 | /* |
1787 | * Leaving the touchpad in command mode will essentially render | 1808 | * Leaving the touchpad in command mode will essentially render |
1788 | * it unusable until the machine reboots, so exit it here just | 1809 | * it unusable until the machine reboots, so exit it here just |
1789 | * to be safe | 1810 | * to be safe |
1790 | */ | 1811 | */ |
1791 | alps_exit_command_mode(psmouse); | 1812 | alps_exit_command_mode(psmouse); |
1792 | return -1; | 1813 | return -1; |
1793 | } | 1814 | } |
1794 | 1815 | ||
1795 | static int alps_get_v3_v7_resolution(struct psmouse *psmouse, int reg_pitch) | 1816 | static int alps_get_v3_v7_resolution(struct psmouse *psmouse, int reg_pitch) |
1796 | { | 1817 | { |
1797 | int reg, x_pitch, y_pitch, x_electrode, y_electrode, x_phys, y_phys; | 1818 | int reg, x_pitch, y_pitch, x_electrode, y_electrode, x_phys, y_phys; |
1798 | struct alps_data *priv = psmouse->private; | 1819 | struct alps_data *priv = psmouse->private; |
1799 | 1820 | ||
1800 | reg = alps_command_mode_read_reg(psmouse, reg_pitch); | 1821 | reg = alps_command_mode_read_reg(psmouse, reg_pitch); |
1801 | if (reg < 0) | 1822 | if (reg < 0) |
1802 | return reg; | 1823 | return reg; |
1803 | 1824 | ||
1804 | x_pitch = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */ | 1825 | x_pitch = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */ |
1805 | x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */ | 1826 | x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */ |
1806 | 1827 | ||
1807 | y_pitch = (char)reg >> 4; /* sign extend upper 4 bits */ | 1828 | y_pitch = (char)reg >> 4; /* sign extend upper 4 bits */ |
1808 | y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */ | 1829 | y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */ |
1809 | 1830 | ||
1810 | reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1); | 1831 | reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1); |
1811 | if (reg < 0) | 1832 | if (reg < 0) |
1812 | return reg; | 1833 | return reg; |
1813 | 1834 | ||
1814 | x_electrode = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */ | 1835 | x_electrode = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */ |
1815 | x_electrode = 17 + x_electrode; | 1836 | x_electrode = 17 + x_electrode; |
1816 | 1837 | ||
1817 | y_electrode = (char)reg >> 4; /* sign extend upper 4 bits */ | 1838 | y_electrode = (char)reg >> 4; /* sign extend upper 4 bits */ |
1818 | y_electrode = 13 + y_electrode; | 1839 | y_electrode = 13 + y_electrode; |
1819 | 1840 | ||
1820 | x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */ | 1841 | x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */ |
1821 | y_phys = y_pitch * (y_electrode - 1); /* In 0.1 mm units */ | 1842 | y_phys = y_pitch * (y_electrode - 1); /* In 0.1 mm units */ |
1822 | 1843 | ||
1823 | priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */ | 1844 | priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */ |
1824 | priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */ | 1845 | priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */ |
1825 | 1846 | ||
1826 | psmouse_dbg(psmouse, | 1847 | psmouse_dbg(psmouse, |
1827 | "pitch %dx%d num-electrodes %dx%d physical size %dx%d mm res %dx%d\n", | 1848 | "pitch %dx%d num-electrodes %dx%d physical size %dx%d mm res %dx%d\n", |
1828 | x_pitch, y_pitch, x_electrode, y_electrode, | 1849 | x_pitch, y_pitch, x_electrode, y_electrode, |
1829 | x_phys / 10, y_phys / 10, priv->x_res, priv->y_res); | 1850 | x_phys / 10, y_phys / 10, priv->x_res, priv->y_res); |
1830 | 1851 | ||
1831 | return 0; | 1852 | return 0; |
1832 | } | 1853 | } |
1833 | 1854 | ||
1834 | static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) | 1855 | static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) |
1835 | { | 1856 | { |
1836 | struct alps_data *priv = psmouse->private; | 1857 | struct alps_data *priv = psmouse->private; |
1837 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1858 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1838 | int reg_val, ret = -1; | 1859 | int reg_val, ret = -1; |
1839 | 1860 | ||
1840 | if (priv->flags & ALPS_DUALPOINT) { | 1861 | if (priv->flags & ALPS_DUALPOINT) { |
1841 | reg_val = alps_setup_trackstick_v3(psmouse, | 1862 | reg_val = alps_setup_trackstick_v3(psmouse, |
1842 | ALPS_REG_BASE_RUSHMORE); | 1863 | ALPS_REG_BASE_RUSHMORE); |
1843 | if (reg_val == -EIO) | 1864 | if (reg_val == -EIO) |
1844 | goto error; | 1865 | goto error; |
1845 | if (reg_val == -ENODEV) | 1866 | if (reg_val == -ENODEV) |
1846 | priv->flags &= ~ALPS_DUALPOINT; | 1867 | priv->flags &= ~ALPS_DUALPOINT; |
1847 | } | 1868 | } |
1848 | 1869 | ||
1849 | if (alps_enter_command_mode(psmouse) || | 1870 | if (alps_enter_command_mode(psmouse) || |
1850 | alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || | 1871 | alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || |
1851 | alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) | 1872 | alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) |
1852 | goto error; | 1873 | goto error; |
1853 | 1874 | ||
1854 | if (alps_get_v3_v7_resolution(psmouse, 0xc2da)) | 1875 | if (alps_get_v3_v7_resolution(psmouse, 0xc2da)) |
1855 | goto error; | 1876 | goto error; |
1856 | 1877 | ||
1857 | reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6); | 1878 | reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6); |
1858 | if (reg_val == -1) | 1879 | if (reg_val == -1) |
1859 | goto error; | 1880 | goto error; |
1860 | if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd)) | 1881 | if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd)) |
1861 | goto error; | 1882 | goto error; |
1862 | 1883 | ||
1863 | if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64)) | 1884 | if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64)) |
1864 | goto error; | 1885 | goto error; |
1865 | 1886 | ||
1866 | /* enter absolute mode */ | 1887 | /* enter absolute mode */ |
1867 | reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4); | 1888 | reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4); |
1868 | if (reg_val == -1) | 1889 | if (reg_val == -1) |
1869 | goto error; | 1890 | goto error; |
1870 | if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02)) | 1891 | if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02)) |
1871 | goto error; | 1892 | goto error; |
1872 | 1893 | ||
1873 | alps_exit_command_mode(psmouse); | 1894 | alps_exit_command_mode(psmouse); |
1874 | return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 1895 | return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); |
1875 | 1896 | ||
1876 | error: | 1897 | error: |
1877 | alps_exit_command_mode(psmouse); | 1898 | alps_exit_command_mode(psmouse); |
1878 | return ret; | 1899 | return ret; |
1879 | } | 1900 | } |
1880 | 1901 | ||
1881 | /* Must be in command mode when calling this function */ | 1902 | /* Must be in command mode when calling this function */ |
1882 | static int alps_absolute_mode_v4(struct psmouse *psmouse) | 1903 | static int alps_absolute_mode_v4(struct psmouse *psmouse) |
1883 | { | 1904 | { |
1884 | int reg_val; | 1905 | int reg_val; |
1885 | 1906 | ||
1886 | reg_val = alps_command_mode_read_reg(psmouse, 0x0004); | 1907 | reg_val = alps_command_mode_read_reg(psmouse, 0x0004); |
1887 | if (reg_val == -1) | 1908 | if (reg_val == -1) |
1888 | return -1; | 1909 | return -1; |
1889 | 1910 | ||
1890 | reg_val |= 0x02; | 1911 | reg_val |= 0x02; |
1891 | if (__alps_command_mode_write_reg(psmouse, reg_val)) | 1912 | if (__alps_command_mode_write_reg(psmouse, reg_val)) |
1892 | return -1; | 1913 | return -1; |
1893 | 1914 | ||
1894 | return 0; | 1915 | return 0; |
1895 | } | 1916 | } |
1896 | 1917 | ||
1897 | static int alps_hw_init_v4(struct psmouse *psmouse) | 1918 | static int alps_hw_init_v4(struct psmouse *psmouse) |
1898 | { | 1919 | { |
1899 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1920 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1900 | unsigned char param[4]; | 1921 | unsigned char param[4]; |
1901 | 1922 | ||
1902 | if (alps_enter_command_mode(psmouse)) | 1923 | if (alps_enter_command_mode(psmouse)) |
1903 | goto error; | 1924 | goto error; |
1904 | 1925 | ||
1905 | if (alps_absolute_mode_v4(psmouse)) { | 1926 | if (alps_absolute_mode_v4(psmouse)) { |
1906 | psmouse_err(psmouse, "Failed to enter absolute mode\n"); | 1927 | psmouse_err(psmouse, "Failed to enter absolute mode\n"); |
1907 | goto error; | 1928 | goto error; |
1908 | } | 1929 | } |
1909 | 1930 | ||
1910 | if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c)) | 1931 | if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c)) |
1911 | goto error; | 1932 | goto error; |
1912 | 1933 | ||
1913 | if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03)) | 1934 | if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03)) |
1914 | goto error; | 1935 | goto error; |
1915 | 1936 | ||
1916 | if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03)) | 1937 | if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03)) |
1917 | goto error; | 1938 | goto error; |
1918 | 1939 | ||
1919 | if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15)) | 1940 | if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15)) |
1920 | goto error; | 1941 | goto error; |
1921 | 1942 | ||
1922 | if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01)) | 1943 | if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01)) |
1923 | goto error; | 1944 | goto error; |
1924 | 1945 | ||
1925 | if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03)) | 1946 | if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03)) |
1926 | goto error; | 1947 | goto error; |
1927 | 1948 | ||
1928 | if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03)) | 1949 | if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03)) |
1929 | goto error; | 1950 | goto error; |
1930 | 1951 | ||
1931 | if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03)) | 1952 | if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03)) |
1932 | goto error; | 1953 | goto error; |
1933 | 1954 | ||
1934 | alps_exit_command_mode(psmouse); | 1955 | alps_exit_command_mode(psmouse); |
1935 | 1956 | ||
1936 | /* | 1957 | /* |
1937 | * This sequence changes the output from a 9-byte to an | 1958 | * This sequence changes the output from a 9-byte to an |
1938 | * 8-byte format. All the same data seems to be present, | 1959 | * 8-byte format. All the same data seems to be present, |
1939 | * just in a more compact format. | 1960 | * just in a more compact format. |
1940 | */ | 1961 | */ |
1941 | param[0] = 0xc8; | 1962 | param[0] = 0xc8; |
1942 | param[1] = 0x64; | 1963 | param[1] = 0x64; |
1943 | param[2] = 0x50; | 1964 | param[2] = 0x50; |
1944 | if (ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || | 1965 | if (ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || |
1945 | ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE) || | 1966 | ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE) || |
1946 | ps2_command(ps2dev, ¶m[2], PSMOUSE_CMD_SETRATE) || | 1967 | ps2_command(ps2dev, ¶m[2], PSMOUSE_CMD_SETRATE) || |
1947 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETID)) | 1968 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETID)) |
1948 | return -1; | 1969 | return -1; |
1949 | 1970 | ||
1950 | /* Set rate and enable data reporting */ | 1971 | /* Set rate and enable data reporting */ |
1951 | param[0] = 0x64; | 1972 | param[0] = 0x64; |
1952 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || | 1973 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) || |
1953 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { | 1974 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { |
1954 | psmouse_err(psmouse, "Failed to enable data reporting\n"); | 1975 | psmouse_err(psmouse, "Failed to enable data reporting\n"); |
1955 | return -1; | 1976 | return -1; |
1956 | } | 1977 | } |
1957 | 1978 | ||
1958 | return 0; | 1979 | return 0; |
1959 | 1980 | ||
1960 | error: | 1981 | error: |
1961 | /* | 1982 | /* |
1962 | * Leaving the touchpad in command mode will essentially render | 1983 | * Leaving the touchpad in command mode will essentially render |
1963 | * it unusable until the machine reboots, so exit it here just | 1984 | * it unusable until the machine reboots, so exit it here just |
1964 | * to be safe | 1985 | * to be safe |
1965 | */ | 1986 | */ |
1966 | alps_exit_command_mode(psmouse); | 1987 | alps_exit_command_mode(psmouse); |
1967 | return -1; | 1988 | return -1; |
1968 | } | 1989 | } |
1969 | 1990 | ||
1970 | static int alps_dolphin_get_device_area(struct psmouse *psmouse, | 1991 | static int alps_dolphin_get_device_area(struct psmouse *psmouse, |
1971 | struct alps_data *priv) | 1992 | struct alps_data *priv) |
1972 | { | 1993 | { |
1973 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1994 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1974 | unsigned char param[4] = {0}; | 1995 | unsigned char param[4] = {0}; |
1975 | int num_x_electrode, num_y_electrode; | 1996 | int num_x_electrode, num_y_electrode; |
1976 | 1997 | ||
1977 | if (alps_enter_command_mode(psmouse)) | 1998 | if (alps_enter_command_mode(psmouse)) |
1978 | return -1; | 1999 | return -1; |
1979 | 2000 | ||
1980 | param[0] = 0x0a; | 2001 | param[0] = 0x0a; |
1981 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || | 2002 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || |
1982 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || | 2003 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || |
1983 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || | 2004 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || |
1984 | ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || | 2005 | ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || |
1985 | ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE)) | 2006 | ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE)) |
1986 | return -1; | 2007 | return -1; |
1987 | 2008 | ||
1988 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) | 2009 | if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) |
1989 | return -1; | 2010 | return -1; |
1990 | 2011 | ||
1991 | /* | 2012 | /* |
1992 | * Dolphin's sensor line number is not fixed. It can be calculated | 2013 | * Dolphin's sensor line number is not fixed. It can be calculated |
1993 | * by adding the device's register value with DOLPHIN_PROFILE_X/YOFFSET. | 2014 | * by adding the device's register value with DOLPHIN_PROFILE_X/YOFFSET. |
1994 | * Further more, we can get device's x_max and y_max by multiplying | 2015 | * Further more, we can get device's x_max and y_max by multiplying |
1995 | * sensor line number with DOLPHIN_COUNT_PER_ELECTRODE. | 2016 | * sensor line number with DOLPHIN_COUNT_PER_ELECTRODE. |
1996 | * | 2017 | * |
1997 | * e.g. When we get register's sensor_x = 11 & sensor_y = 8, | 2018 | * e.g. When we get register's sensor_x = 11 & sensor_y = 8, |
1998 | * real sensor line number X = 11 + 8 = 19, and | 2019 | * real sensor line number X = 11 + 8 = 19, and |
1999 | * real sensor line number Y = 8 + 1 = 9. | 2020 | * real sensor line number Y = 8 + 1 = 9. |
2000 | * So, x_max = (19 - 1) * 64 = 1152, and | 2021 | * So, x_max = (19 - 1) * 64 = 1152, and |
2001 | * y_max = (9 - 1) * 64 = 512. | 2022 | * y_max = (9 - 1) * 64 = 512. |
2002 | */ | 2023 | */ |
2003 | num_x_electrode = DOLPHIN_PROFILE_XOFFSET + (param[2] & 0x0F); | 2024 | num_x_electrode = DOLPHIN_PROFILE_XOFFSET + (param[2] & 0x0F); |
2004 | num_y_electrode = DOLPHIN_PROFILE_YOFFSET + ((param[2] >> 4) & 0x0F); | 2025 | num_y_electrode = DOLPHIN_PROFILE_YOFFSET + ((param[2] >> 4) & 0x0F); |
2005 | priv->x_bits = num_x_electrode; | 2026 | priv->x_bits = num_x_electrode; |
2006 | priv->y_bits = num_y_electrode; | 2027 | priv->y_bits = num_y_electrode; |
2007 | priv->x_max = (num_x_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE; | 2028 | priv->x_max = (num_x_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE; |
2008 | priv->y_max = (num_y_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE; | 2029 | priv->y_max = (num_y_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE; |
2009 | 2030 | ||
2010 | if (alps_exit_command_mode(psmouse)) | 2031 | if (alps_exit_command_mode(psmouse)) |
2011 | return -1; | 2032 | return -1; |
2012 | 2033 | ||
2013 | return 0; | 2034 | return 0; |
2014 | } | 2035 | } |
2015 | 2036 | ||
2016 | static int alps_hw_init_dolphin_v1(struct psmouse *psmouse) | 2037 | static int alps_hw_init_dolphin_v1(struct psmouse *psmouse) |
2017 | { | 2038 | { |
2018 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 2039 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
2019 | unsigned char param[2]; | 2040 | unsigned char param[2]; |
2020 | 2041 | ||
2021 | /* This is dolphin "v1" as empirically defined by florin9doi */ | 2042 | /* This is dolphin "v1" as empirically defined by florin9doi */ |
2022 | param[0] = 0x64; | 2043 | param[0] = 0x64; |
2023 | param[1] = 0x28; | 2044 | param[1] = 0x28; |
2024 | 2045 | ||
2025 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | 2046 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || |
2026 | ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || | 2047 | ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || |
2027 | ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) | 2048 | ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) |
2028 | return -1; | 2049 | return -1; |
2029 | 2050 | ||
2030 | return 0; | 2051 | return 0; |
2031 | } | 2052 | } |
2032 | 2053 | ||
2033 | static int alps_hw_init_v7(struct psmouse *psmouse) | 2054 | static int alps_hw_init_v7(struct psmouse *psmouse) |
2034 | { | 2055 | { |
2035 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 2056 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
2036 | int reg_val, ret = -1; | 2057 | int reg_val, ret = -1; |
2037 | 2058 | ||
2038 | if (alps_enter_command_mode(psmouse) || | 2059 | if (alps_enter_command_mode(psmouse) || |
2039 | alps_command_mode_read_reg(psmouse, 0xc2d9) == -1) | 2060 | alps_command_mode_read_reg(psmouse, 0xc2d9) == -1) |
2040 | goto error; | 2061 | goto error; |
2041 | 2062 | ||
2042 | if (alps_get_v3_v7_resolution(psmouse, 0xc397)) | 2063 | if (alps_get_v3_v7_resolution(psmouse, 0xc397)) |
2043 | goto error; | 2064 | goto error; |
2044 | 2065 | ||
2045 | if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64)) | 2066 | if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64)) |
2046 | goto error; | 2067 | goto error; |
2047 | 2068 | ||
2048 | reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4); | 2069 | reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4); |
2049 | if (reg_val == -1) | 2070 | if (reg_val == -1) |
2050 | goto error; | 2071 | goto error; |
2051 | if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02)) | 2072 | if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02)) |
2052 | goto error; | 2073 | goto error; |
2053 | 2074 | ||
2054 | alps_exit_command_mode(psmouse); | 2075 | alps_exit_command_mode(psmouse); |
2055 | return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 2076 | return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); |
2056 | 2077 | ||
2057 | error: | 2078 | error: |
2058 | alps_exit_command_mode(psmouse); | 2079 | alps_exit_command_mode(psmouse); |
2059 | return ret; | 2080 | return ret; |
2060 | } | 2081 | } |
2061 | 2082 | ||
2062 | static void alps_set_defaults(struct alps_data *priv) | 2083 | static void alps_set_defaults(struct alps_data *priv) |
2063 | { | 2084 | { |
2064 | priv->byte0 = 0x8f; | 2085 | priv->byte0 = 0x8f; |
2065 | priv->mask0 = 0x8f; | 2086 | priv->mask0 = 0x8f; |
2066 | priv->flags = ALPS_DUALPOINT; | 2087 | priv->flags = ALPS_DUALPOINT; |
2067 | 2088 | ||
2068 | priv->x_max = 2000; | 2089 | priv->x_max = 2000; |
2069 | priv->y_max = 1400; | 2090 | priv->y_max = 1400; |
2070 | priv->x_bits = 15; | 2091 | priv->x_bits = 15; |
2071 | priv->y_bits = 11; | 2092 | priv->y_bits = 11; |
2072 | 2093 | ||
2073 | switch (priv->proto_version) { | 2094 | switch (priv->proto_version) { |
2074 | case ALPS_PROTO_V1: | 2095 | case ALPS_PROTO_V1: |
2075 | case ALPS_PROTO_V2: | 2096 | case ALPS_PROTO_V2: |
2076 | priv->hw_init = alps_hw_init_v1_v2; | 2097 | priv->hw_init = alps_hw_init_v1_v2; |
2077 | priv->process_packet = alps_process_packet_v1_v2; | 2098 | priv->process_packet = alps_process_packet_v1_v2; |
2078 | priv->set_abs_params = alps_set_abs_params_st; | 2099 | priv->set_abs_params = alps_set_abs_params_st; |
2079 | priv->x_max = 1023; | 2100 | priv->x_max = 1023; |
2080 | priv->y_max = 767; | 2101 | priv->y_max = 767; |
2081 | break; | 2102 | break; |
2082 | case ALPS_PROTO_V3: | 2103 | case ALPS_PROTO_V3: |
2083 | priv->hw_init = alps_hw_init_v3; | 2104 | priv->hw_init = alps_hw_init_v3; |
2084 | priv->process_packet = alps_process_packet_v3; | 2105 | priv->process_packet = alps_process_packet_v3; |
2085 | priv->set_abs_params = alps_set_abs_params_mt; | 2106 | priv->set_abs_params = alps_set_abs_params_mt; |
2086 | priv->decode_fields = alps_decode_pinnacle; | 2107 | priv->decode_fields = alps_decode_pinnacle; |
2087 | priv->nibble_commands = alps_v3_nibble_commands; | 2108 | priv->nibble_commands = alps_v3_nibble_commands; |
2088 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | 2109 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; |
2089 | break; | 2110 | break; |
2090 | case ALPS_PROTO_V4: | 2111 | case ALPS_PROTO_V4: |
2091 | priv->hw_init = alps_hw_init_v4; | 2112 | priv->hw_init = alps_hw_init_v4; |
2092 | priv->process_packet = alps_process_packet_v4; | 2113 | priv->process_packet = alps_process_packet_v4; |
2093 | priv->set_abs_params = alps_set_abs_params_mt; | 2114 | priv->set_abs_params = alps_set_abs_params_mt; |
2094 | priv->nibble_commands = alps_v4_nibble_commands; | 2115 | priv->nibble_commands = alps_v4_nibble_commands; |
2095 | priv->addr_command = PSMOUSE_CMD_DISABLE; | 2116 | priv->addr_command = PSMOUSE_CMD_DISABLE; |
2096 | break; | 2117 | break; |
2097 | case ALPS_PROTO_V5: | 2118 | case ALPS_PROTO_V5: |
2098 | priv->hw_init = alps_hw_init_dolphin_v1; | 2119 | priv->hw_init = alps_hw_init_dolphin_v1; |
2099 | priv->process_packet = alps_process_touchpad_packet_v3_v5; | 2120 | priv->process_packet = alps_process_touchpad_packet_v3_v5; |
2100 | priv->decode_fields = alps_decode_dolphin; | 2121 | priv->decode_fields = alps_decode_dolphin; |
2101 | priv->set_abs_params = alps_set_abs_params_mt; | 2122 | priv->set_abs_params = alps_set_abs_params_mt; |
2102 | priv->nibble_commands = alps_v3_nibble_commands; | 2123 | priv->nibble_commands = alps_v3_nibble_commands; |
2103 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | 2124 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; |
2104 | priv->byte0 = 0xc8; | 2125 | priv->byte0 = 0xc8; |
2105 | priv->mask0 = 0xd8; | 2126 | priv->mask0 = 0xd8; |
2106 | priv->flags = 0; | 2127 | priv->flags = 0; |
2107 | priv->x_max = 1360; | 2128 | priv->x_max = 1360; |
2108 | priv->y_max = 660; | 2129 | priv->y_max = 660; |
2109 | priv->x_bits = 23; | 2130 | priv->x_bits = 23; |
2110 | priv->y_bits = 12; | 2131 | priv->y_bits = 12; |
2111 | break; | 2132 | break; |
2112 | case ALPS_PROTO_V6: | 2133 | case ALPS_PROTO_V6: |
2113 | priv->hw_init = alps_hw_init_v6; | 2134 | priv->hw_init = alps_hw_init_v6; |
2114 | priv->process_packet = alps_process_packet_v6; | 2135 | priv->process_packet = alps_process_packet_v6; |
2115 | priv->set_abs_params = alps_set_abs_params_st; | 2136 | priv->set_abs_params = alps_set_abs_params_st; |
2116 | priv->nibble_commands = alps_v6_nibble_commands; | 2137 | priv->nibble_commands = alps_v6_nibble_commands; |
2117 | priv->x_max = 2047; | 2138 | priv->x_max = 2047; |
2118 | priv->y_max = 1535; | 2139 | priv->y_max = 1535; |
2119 | break; | 2140 | break; |
2120 | case ALPS_PROTO_V7: | 2141 | case ALPS_PROTO_V7: |
2121 | priv->hw_init = alps_hw_init_v7; | 2142 | priv->hw_init = alps_hw_init_v7; |
2122 | priv->process_packet = alps_process_packet_v7; | 2143 | priv->process_packet = alps_process_packet_v7; |
2123 | priv->decode_fields = alps_decode_packet_v7; | 2144 | priv->decode_fields = alps_decode_packet_v7; |
2124 | priv->set_abs_params = alps_set_abs_params_mt; | 2145 | priv->set_abs_params = alps_set_abs_params_mt; |
2125 | priv->nibble_commands = alps_v3_nibble_commands; | 2146 | priv->nibble_commands = alps_v3_nibble_commands; |
2126 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | 2147 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; |
2127 | priv->x_max = 0xfff; | 2148 | priv->x_max = 0xfff; |
2128 | priv->y_max = 0x7ff; | 2149 | priv->y_max = 0x7ff; |
2129 | priv->byte0 = 0x48; | 2150 | priv->byte0 = 0x48; |
2130 | priv->mask0 = 0x48; | 2151 | priv->mask0 = 0x48; |
2131 | 2152 | ||
2132 | if (priv->fw_ver[1] != 0xba) | 2153 | if (priv->fw_ver[1] != 0xba) |
2133 | priv->flags |= ALPS_BUTTONPAD; | 2154 | priv->flags |= ALPS_BUTTONPAD; |
2134 | break; | 2155 | break; |
2135 | } | 2156 | } |
2136 | } | 2157 | } |
2137 | 2158 | ||
2138 | static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, | 2159 | static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, |
2139 | unsigned char *e7, unsigned char *ec) | 2160 | unsigned char *e7, unsigned char *ec) |
2140 | { | 2161 | { |
2141 | const struct alps_model_info *model; | 2162 | const struct alps_model_info *model; |
2142 | int i; | 2163 | int i; |
2143 | 2164 | ||
2144 | for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { | 2165 | for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { |
2145 | model = &alps_model_data[i]; | 2166 | model = &alps_model_data[i]; |
2146 | 2167 | ||
2147 | if (!memcmp(e7, model->signature, sizeof(model->signature)) && | 2168 | if (!memcmp(e7, model->signature, sizeof(model->signature)) && |
2148 | (!model->command_mode_resp || | 2169 | (!model->command_mode_resp || |
2149 | model->command_mode_resp == ec[2])) { | 2170 | model->command_mode_resp == ec[2])) { |
2150 | 2171 | ||
2151 | priv->proto_version = model->proto_version; | 2172 | priv->proto_version = model->proto_version; |
2152 | alps_set_defaults(priv); | 2173 | alps_set_defaults(priv); |
2153 | 2174 | ||
2154 | priv->flags = model->flags; | 2175 | priv->flags = model->flags; |
2155 | priv->byte0 = model->byte0; | 2176 | priv->byte0 = model->byte0; |
2156 | priv->mask0 = model->mask0; | 2177 | priv->mask0 = model->mask0; |
2157 | 2178 | ||
2158 | return 0; | 2179 | return 0; |
2159 | } | 2180 | } |
2160 | } | 2181 | } |
2161 | 2182 | ||
2162 | return -EINVAL; | 2183 | return -EINVAL; |
2163 | } | 2184 | } |
2164 | 2185 | ||
2165 | static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | 2186 | static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) |
2166 | { | 2187 | { |
2167 | unsigned char e6[4], e7[4], ec[4]; | 2188 | unsigned char e6[4], e7[4], ec[4]; |
2168 | 2189 | ||
2169 | /* | 2190 | /* |
2170 | * First try "E6 report". | 2191 | * First try "E6 report". |
2171 | * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. | 2192 | * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. |
2172 | * The bits 0-2 of the first byte will be 1s if some buttons are | 2193 | * The bits 0-2 of the first byte will be 1s if some buttons are |
2173 | * pressed. | 2194 | * pressed. |
2174 | */ | 2195 | */ |
2175 | if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, | 2196 | if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, |
2176 | PSMOUSE_CMD_SETSCALE11, e6)) | 2197 | PSMOUSE_CMD_SETSCALE11, e6)) |
2177 | return -EIO; | 2198 | return -EIO; |
2178 | 2199 | ||
2179 | if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100)) | 2200 | if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100)) |
2180 | return -EINVAL; | 2201 | return -EINVAL; |
2181 | 2202 | ||
2182 | /* | 2203 | /* |
2183 | * Now get the "E7" and "EC" reports. These will uniquely identify | 2204 | * Now get the "E7" and "EC" reports. These will uniquely identify |
2184 | * most ALPS touchpads. | 2205 | * most ALPS touchpads. |
2185 | */ | 2206 | */ |
2186 | if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, | 2207 | if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, |
2187 | PSMOUSE_CMD_SETSCALE21, e7) || | 2208 | PSMOUSE_CMD_SETSCALE21, e7) || |
2188 | alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, | 2209 | alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, |
2189 | PSMOUSE_CMD_RESET_WRAP, ec) || | 2210 | PSMOUSE_CMD_RESET_WRAP, ec) || |
2190 | alps_exit_command_mode(psmouse)) | 2211 | alps_exit_command_mode(psmouse)) |
2191 | return -EIO; | 2212 | return -EIO; |
2192 | 2213 | ||
2193 | /* Save the Firmware version */ | 2214 | /* Save the Firmware version */ |
2194 | memcpy(priv->fw_ver, ec, 3); | 2215 | memcpy(priv->fw_ver, ec, 3); |
2195 | 2216 | ||
2196 | if (alps_match_table(psmouse, priv, e7, ec) == 0) { | 2217 | if (alps_match_table(psmouse, priv, e7, ec) == 0) { |
2197 | return 0; | 2218 | return 0; |
2198 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && | 2219 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && |
2199 | ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) { | 2220 | ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) { |
2200 | priv->proto_version = ALPS_PROTO_V5; | 2221 | priv->proto_version = ALPS_PROTO_V5; |
2201 | alps_set_defaults(priv); | 2222 | alps_set_defaults(priv); |
2202 | if (alps_dolphin_get_device_area(psmouse, priv)) | 2223 | if (alps_dolphin_get_device_area(psmouse, priv)) |
2203 | return -EIO; | 2224 | return -EIO; |
2204 | else | 2225 | else |
2205 | return 0; | 2226 | return 0; |
2206 | } else if (ec[0] == 0x88 && | 2227 | } else if (ec[0] == 0x88 && |
2207 | ((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) { | 2228 | ((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) { |
2208 | priv->proto_version = ALPS_PROTO_V7; | 2229 | priv->proto_version = ALPS_PROTO_V7; |
2209 | alps_set_defaults(priv); | 2230 | alps_set_defaults(priv); |
2210 | 2231 | ||
2211 | return 0; | 2232 | return 0; |
2212 | } else if (ec[0] == 0x88 && ec[1] == 0x08) { | 2233 | } else if (ec[0] == 0x88 && ec[1] == 0x08) { |
2213 | priv->proto_version = ALPS_PROTO_V3; | 2234 | priv->proto_version = ALPS_PROTO_V3; |
2214 | alps_set_defaults(priv); | 2235 | alps_set_defaults(priv); |
2215 | 2236 | ||
2216 | priv->hw_init = alps_hw_init_rushmore_v3; | 2237 | priv->hw_init = alps_hw_init_rushmore_v3; |
2217 | priv->decode_fields = alps_decode_rushmore; | 2238 | priv->decode_fields = alps_decode_rushmore; |
2218 | priv->x_bits = 16; | 2239 | priv->x_bits = 16; |
2219 | priv->y_bits = 12; | 2240 | priv->y_bits = 12; |
2220 | priv->flags |= ALPS_IS_RUSHMORE; | 2241 | priv->flags |= ALPS_IS_RUSHMORE; |
2221 | 2242 | ||
2222 | /* hack to make addr_command, nibble_command available */ | 2243 | /* hack to make addr_command, nibble_command available */ |
2223 | psmouse->private = priv; | 2244 | psmouse->private = priv; |
2224 | 2245 | ||
2225 | if (alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_RUSHMORE)) | 2246 | if (alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_RUSHMORE)) |
2226 | priv->flags &= ~ALPS_DUALPOINT; | 2247 | priv->flags &= ~ALPS_DUALPOINT; |
2227 | 2248 | ||
2228 | return 0; | 2249 | return 0; |
2229 | } else if (ec[0] == 0x88 && ec[1] == 0x07 && | 2250 | } else if (ec[0] == 0x88 && ec[1] == 0x07 && |
2230 | ec[2] >= 0x90 && ec[2] <= 0x9d) { | 2251 | ec[2] >= 0x90 && ec[2] <= 0x9d) { |
2231 | priv->proto_version = ALPS_PROTO_V3; | 2252 | priv->proto_version = ALPS_PROTO_V3; |
2232 | alps_set_defaults(priv); | 2253 | alps_set_defaults(priv); |
2233 | 2254 | ||
2234 | return 0; | 2255 | return 0; |
2235 | } | 2256 | } |
2236 | 2257 | ||
2237 | psmouse_dbg(psmouse, | 2258 | psmouse_dbg(psmouse, |
2238 | "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); | 2259 | "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); |
2239 | 2260 | ||
2240 | return -EINVAL; | 2261 | return -EINVAL; |
2241 | } | 2262 | } |
2242 | 2263 | ||
2243 | static int alps_reconnect(struct psmouse *psmouse) | 2264 | static int alps_reconnect(struct psmouse *psmouse) |
2244 | { | 2265 | { |
2245 | struct alps_data *priv = psmouse->private; | 2266 | struct alps_data *priv = psmouse->private; |
2246 | 2267 | ||
2247 | psmouse_reset(psmouse); | 2268 | psmouse_reset(psmouse); |
2248 | 2269 | ||
2249 | if (alps_identify(psmouse, priv) < 0) | 2270 | if (alps_identify(psmouse, priv) < 0) |
2250 | return -1; | 2271 | return -1; |
2251 | 2272 | ||
2252 | return priv->hw_init(psmouse); | 2273 | return priv->hw_init(psmouse); |
2253 | } | 2274 | } |
2254 | 2275 | ||
2255 | static void alps_disconnect(struct psmouse *psmouse) | 2276 | static void alps_disconnect(struct psmouse *psmouse) |
2256 | { | 2277 | { |
2257 | struct alps_data *priv = psmouse->private; | 2278 | struct alps_data *priv = psmouse->private; |
2258 | 2279 | ||
2259 | psmouse_reset(psmouse); | 2280 | psmouse_reset(psmouse); |
2260 | del_timer_sync(&priv->timer); | 2281 | del_timer_sync(&priv->timer); |
2261 | input_unregister_device(priv->dev2); | 2282 | input_unregister_device(priv->dev2); |
2262 | kfree(priv); | 2283 | kfree(priv); |
2263 | } | 2284 | } |
2264 | 2285 | ||
2265 | static void alps_set_abs_params_st(struct alps_data *priv, | 2286 | static void alps_set_abs_params_st(struct alps_data *priv, |
2266 | struct input_dev *dev1) | 2287 | struct input_dev *dev1) |
2267 | { | 2288 | { |
2268 | input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); | 2289 | input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); |
2269 | input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); | 2290 | input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); |
2270 | } | 2291 | } |
2271 | 2292 | ||
2272 | static void alps_set_abs_params_mt(struct alps_data *priv, | 2293 | static void alps_set_abs_params_mt(struct alps_data *priv, |
2273 | struct input_dev *dev1) | 2294 | struct input_dev *dev1) |
2274 | { | 2295 | { |
2275 | input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); | 2296 | input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); |
2276 | input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); | 2297 | input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); |
2277 | 2298 | ||
2278 | input_abs_set_res(dev1, ABS_MT_POSITION_X, priv->x_res); | 2299 | input_abs_set_res(dev1, ABS_MT_POSITION_X, priv->x_res); |
2279 | input_abs_set_res(dev1, ABS_MT_POSITION_Y, priv->y_res); | 2300 | input_abs_set_res(dev1, ABS_MT_POSITION_Y, priv->y_res); |
2280 | 2301 | ||
2281 | input_mt_init_slots(dev1, MAX_TOUCHES, INPUT_MT_POINTER | | 2302 | input_mt_init_slots(dev1, MAX_TOUCHES, INPUT_MT_POINTER | |
2282 | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK | INPUT_MT_SEMI_MT); | 2303 | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK | INPUT_MT_SEMI_MT); |
2283 | 2304 | ||
2284 | set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); | 2305 | set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); |
2285 | set_bit(BTN_TOOL_QUADTAP, dev1->keybit); | 2306 | set_bit(BTN_TOOL_QUADTAP, dev1->keybit); |
2286 | 2307 | ||
2287 | /* V7 is real multi-touch */ | 2308 | /* V7 is real multi-touch */ |
2288 | if (priv->proto_version == ALPS_PROTO_V7) | 2309 | if (priv->proto_version == ALPS_PROTO_V7) |
2289 | clear_bit(INPUT_PROP_SEMI_MT, dev1->propbit); | 2310 | clear_bit(INPUT_PROP_SEMI_MT, dev1->propbit); |
2290 | } | 2311 | } |
2291 | 2312 | ||
2292 | int alps_init(struct psmouse *psmouse) | 2313 | int alps_init(struct psmouse *psmouse) |
2293 | { | 2314 | { |
2294 | struct alps_data *priv; | 2315 | struct alps_data *priv; |
2295 | struct input_dev *dev1 = psmouse->dev, *dev2; | 2316 | struct input_dev *dev1 = psmouse->dev, *dev2; |
2296 | 2317 | ||
2297 | priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); | 2318 | priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); |
2298 | dev2 = input_allocate_device(); | 2319 | dev2 = input_allocate_device(); |
2299 | if (!priv || !dev2) | 2320 | if (!priv || !dev2) |
2300 | goto init_fail; | 2321 | goto init_fail; |
2301 | 2322 | ||
2302 | priv->dev2 = dev2; | 2323 | priv->dev2 = dev2; |
2303 | setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse); | 2324 | setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse); |
2304 | 2325 | ||
2305 | psmouse->private = priv; | 2326 | psmouse->private = priv; |
2306 | 2327 | ||
2307 | psmouse_reset(psmouse); | 2328 | psmouse_reset(psmouse); |
2308 | 2329 | ||
2309 | if (alps_identify(psmouse, priv) < 0) | 2330 | if (alps_identify(psmouse, priv) < 0) |
2310 | goto init_fail; | 2331 | goto init_fail; |
2311 | 2332 | ||
2312 | if (priv->hw_init(psmouse)) | 2333 | if (priv->hw_init(psmouse)) |
2313 | goto init_fail; | 2334 | goto init_fail; |
2314 | 2335 | ||
2315 | /* | 2336 | /* |
2316 | * Undo part of setup done for us by psmouse core since touchpad | 2337 | * Undo part of setup done for us by psmouse core since touchpad |
2317 | * is not a relative device. | 2338 | * is not a relative device. |
2318 | */ | 2339 | */ |
2319 | __clear_bit(EV_REL, dev1->evbit); | 2340 | __clear_bit(EV_REL, dev1->evbit); |
2320 | __clear_bit(REL_X, dev1->relbit); | 2341 | __clear_bit(REL_X, dev1->relbit); |
2321 | __clear_bit(REL_Y, dev1->relbit); | 2342 | __clear_bit(REL_Y, dev1->relbit); |
2322 | 2343 | ||
2323 | /* | 2344 | /* |
2324 | * Now set up our capabilities. | 2345 | * Now set up our capabilities. |
2325 | */ | 2346 | */ |
2326 | dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); | 2347 | dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); |
2327 | dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); | 2348 | dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); |
2328 | dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); | 2349 | dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); |
2329 | dev1->keybit[BIT_WORD(BTN_LEFT)] |= | 2350 | dev1->keybit[BIT_WORD(BTN_LEFT)] |= |
2330 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); | 2351 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); |
2331 | 2352 | ||
2332 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); | 2353 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); |
2333 | 2354 | ||
2334 | priv->set_abs_params(priv, dev1); | 2355 | priv->set_abs_params(priv, dev1); |
2335 | /* No pressure on V7 */ | 2356 | /* No pressure on V7 */ |
2336 | if (priv->proto_version != ALPS_PROTO_V7) | 2357 | if (priv->proto_version != ALPS_PROTO_V7) |
2337 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | 2358 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); |
2338 | 2359 | ||
2339 | if (priv->flags & ALPS_WHEEL) { | 2360 | if (priv->flags & ALPS_WHEEL) { |
2340 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); | 2361 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); |
2341 | dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); | 2362 | dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); |
2342 | } | 2363 | } |
2343 | 2364 | ||
2344 | if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { | 2365 | if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
2345 | dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); | 2366 | dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); |
2346 | dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); | 2367 | dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); |
2347 | } | 2368 | } |
2348 | 2369 | ||
2349 | if (priv->flags & ALPS_FOUR_BUTTONS) { | 2370 | if (priv->flags & ALPS_FOUR_BUTTONS) { |
2350 | dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); | 2371 | dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); |
2351 | dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); | 2372 | dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); |
2352 | dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); | 2373 | dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); |
2353 | dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3); | 2374 | dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3); |
2354 | } else if (priv->flags & ALPS_BUTTONPAD) { | 2375 | } else if (priv->flags & ALPS_BUTTONPAD) { |
2355 | set_bit(INPUT_PROP_BUTTONPAD, dev1->propbit); | 2376 | set_bit(INPUT_PROP_BUTTONPAD, dev1->propbit); |
2356 | clear_bit(BTN_RIGHT, dev1->keybit); | 2377 | clear_bit(BTN_RIGHT, dev1->keybit); |
2357 | } else { | 2378 | } else { |
2358 | dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE); | 2379 | dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE); |
2359 | } | 2380 | } |
2360 | 2381 | ||
2361 | snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); | 2382 | snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); |
2362 | dev2->phys = priv->phys; | 2383 | dev2->phys = priv->phys; |
2363 | dev2->name = (priv->flags & ALPS_DUALPOINT) ? | 2384 | dev2->name = (priv->flags & ALPS_DUALPOINT) ? |
2364 | "DualPoint Stick" : "ALPS PS/2 Device"; | 2385 | "DualPoint Stick" : "ALPS PS/2 Device"; |
2365 | dev2->id.bustype = BUS_I8042; | 2386 | dev2->id.bustype = BUS_I8042; |
2366 | dev2->id.vendor = 0x0002; | 2387 | dev2->id.vendor = 0x0002; |
2367 | dev2->id.product = PSMOUSE_ALPS; | 2388 | dev2->id.product = PSMOUSE_ALPS; |
2368 | dev2->id.version = 0x0000; | 2389 | dev2->id.version = 0x0000; |
2369 | dev2->dev.parent = &psmouse->ps2dev.serio->dev; | 2390 | dev2->dev.parent = &psmouse->ps2dev.serio->dev; |
2370 | 2391 | ||
2371 | dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | 2392 | dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); |
2372 | dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); | 2393 | dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); |
2373 | dev2->keybit[BIT_WORD(BTN_LEFT)] = | 2394 | dev2->keybit[BIT_WORD(BTN_LEFT)] = |
2374 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 2395 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); |
2375 | 2396 | ||
2376 | __set_bit(INPUT_PROP_POINTER, dev2->propbit); | 2397 | __set_bit(INPUT_PROP_POINTER, dev2->propbit); |
2377 | if (priv->flags & ALPS_DUALPOINT) | 2398 | if (priv->flags & ALPS_DUALPOINT) |
2378 | __set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit); | 2399 | __set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit); |
2379 | 2400 | ||
2380 | if (input_register_device(priv->dev2)) | 2401 | if (input_register_device(priv->dev2)) |
2381 | goto init_fail; | 2402 | goto init_fail; |
2382 | 2403 | ||
2383 | psmouse->protocol_handler = alps_process_byte; | 2404 | psmouse->protocol_handler = alps_process_byte; |
2384 | psmouse->poll = alps_poll; | 2405 | psmouse->poll = alps_poll; |
2385 | psmouse->disconnect = alps_disconnect; | 2406 | psmouse->disconnect = alps_disconnect; |
2386 | psmouse->reconnect = alps_reconnect; | 2407 | psmouse->reconnect = alps_reconnect; |
2387 | psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6; | 2408 | psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6; |
2388 | 2409 | ||
2389 | /* We are having trouble resyncing ALPS touchpads so disable it for now */ | 2410 | /* We are having trouble resyncing ALPS touchpads so disable it for now */ |
2390 | psmouse->resync_time = 0; | 2411 | psmouse->resync_time = 0; |
2412 | |||
2413 | /* Allow 2 invalid packets without resetting device */ | ||
2414 | psmouse->resetafter = psmouse->pktsize * 2; | ||
2391 | 2415 | ||
2392 | return 0; | 2416 | return 0; |
2393 | 2417 | ||
2394 | init_fail: | 2418 | init_fail: |
2395 | psmouse_reset(psmouse); | 2419 | psmouse_reset(psmouse); |
2396 | input_free_device(dev2); | 2420 | input_free_device(dev2); |
2397 | kfree(priv); | 2421 | kfree(priv); |
2398 | psmouse->private = NULL; | 2422 | psmouse->private = NULL; |
2399 | return -1; | 2423 | return -1; |
2400 | } | 2424 | } |
2401 | 2425 | ||
2402 | int alps_detect(struct psmouse *psmouse, bool set_properties) | 2426 | int alps_detect(struct psmouse *psmouse, bool set_properties) |
2403 | { | 2427 | { |
2404 | struct alps_data dummy; | 2428 | struct alps_data dummy; |
2405 | 2429 | ||
2406 | if (alps_identify(psmouse, &dummy) < 0) | 2430 | if (alps_identify(psmouse, &dummy) < 0) |
2407 | return -1; | 2431 | return -1; |
2408 | 2432 | ||
2409 | if (set_properties) { | 2433 | if (set_properties) { |
2410 | psmouse->vendor = "ALPS"; | 2434 | psmouse->vendor = "ALPS"; |
2411 | psmouse->name = dummy.flags & ALPS_DUALPOINT ? | 2435 | psmouse->name = dummy.flags & ALPS_DUALPOINT ? |
2412 | "DualPoint TouchPad" : "GlidePoint"; | 2436 | "DualPoint TouchPad" : "GlidePoint"; |
2413 | psmouse->model = dummy.proto_version << 8; | 2437 | psmouse->model = dummy.proto_version << 8; |
2414 | } | 2438 | } |
2415 | return 0; | 2439 | return 0; |
2416 | } | 2440 | } |
2417 | 2441 | ||
2418 | 2442 |
drivers/input/mouse/elantech.c
1 | /* | 1 | /* |
2 | * Elantech Touchpad driver (v6) | 2 | * Elantech Touchpad driver (v6) |
3 | * | 3 | * |
4 | * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net> | 4 | * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License version 2 as published | 7 | * under the terms of the GNU General Public License version 2 as published |
8 | * by the Free Software Foundation. | 8 | * by the Free Software Foundation. |
9 | * | 9 | * |
10 | * Trademarks are the property of their respective owners. | 10 | * Trademarks are the property of their respective owners. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/dmi.h> | 14 | #include <linux/dmi.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/input.h> | 17 | #include <linux/input.h> |
18 | #include <linux/input/mt.h> | 18 | #include <linux/input/mt.h> |
19 | #include <linux/serio.h> | 19 | #include <linux/serio.h> |
20 | #include <linux/libps2.h> | 20 | #include <linux/libps2.h> |
21 | #include <asm/unaligned.h> | 21 | #include <asm/unaligned.h> |
22 | #include "psmouse.h" | 22 | #include "psmouse.h" |
23 | #include "elantech.h" | 23 | #include "elantech.h" |
24 | 24 | ||
25 | #define elantech_debug(fmt, ...) \ | 25 | #define elantech_debug(fmt, ...) \ |
26 | do { \ | 26 | do { \ |
27 | if (etd->debug) \ | 27 | if (etd->debug) \ |
28 | psmouse_printk(KERN_DEBUG, psmouse, \ | 28 | psmouse_printk(KERN_DEBUG, psmouse, \ |
29 | fmt, ##__VA_ARGS__); \ | 29 | fmt, ##__VA_ARGS__); \ |
30 | } while (0) | 30 | } while (0) |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * Send a Synaptics style sliced query command | 33 | * Send a Synaptics style sliced query command |
34 | */ | 34 | */ |
35 | static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, | 35 | static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, |
36 | unsigned char *param) | 36 | unsigned char *param) |
37 | { | 37 | { |
38 | if (psmouse_sliced_command(psmouse, c) || | 38 | if (psmouse_sliced_command(psmouse, c) || |
39 | ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) { | 39 | ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) { |
40 | psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c); | 40 | psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c); |
41 | return -1; | 41 | return -1; |
42 | } | 42 | } |
43 | 43 | ||
44 | return 0; | 44 | return 0; |
45 | } | 45 | } |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * V3 and later support this fast command | 48 | * V3 and later support this fast command |
49 | */ | 49 | */ |
50 | static int elantech_send_cmd(struct psmouse *psmouse, unsigned char c, | 50 | static int elantech_send_cmd(struct psmouse *psmouse, unsigned char c, |
51 | unsigned char *param) | 51 | unsigned char *param) |
52 | { | 52 | { |
53 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 53 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
54 | 54 | ||
55 | if (ps2_command(ps2dev, NULL, ETP_PS2_CUSTOM_COMMAND) || | 55 | if (ps2_command(ps2dev, NULL, ETP_PS2_CUSTOM_COMMAND) || |
56 | ps2_command(ps2dev, NULL, c) || | 56 | ps2_command(ps2dev, NULL, c) || |
57 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { | 57 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { |
58 | psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c); | 58 | psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c); |
59 | return -1; | 59 | return -1; |
60 | } | 60 | } |
61 | 61 | ||
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | /* | 65 | /* |
66 | * A retrying version of ps2_command | 66 | * A retrying version of ps2_command |
67 | */ | 67 | */ |
68 | static int elantech_ps2_command(struct psmouse *psmouse, | 68 | static int elantech_ps2_command(struct psmouse *psmouse, |
69 | unsigned char *param, int command) | 69 | unsigned char *param, int command) |
70 | { | 70 | { |
71 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 71 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
72 | struct elantech_data *etd = psmouse->private; | 72 | struct elantech_data *etd = psmouse->private; |
73 | int rc; | 73 | int rc; |
74 | int tries = ETP_PS2_COMMAND_TRIES; | 74 | int tries = ETP_PS2_COMMAND_TRIES; |
75 | 75 | ||
76 | do { | 76 | do { |
77 | rc = ps2_command(ps2dev, param, command); | 77 | rc = ps2_command(ps2dev, param, command); |
78 | if (rc == 0) | 78 | if (rc == 0) |
79 | break; | 79 | break; |
80 | tries--; | 80 | tries--; |
81 | elantech_debug("retrying ps2 command 0x%02x (%d).\n", | 81 | elantech_debug("retrying ps2 command 0x%02x (%d).\n", |
82 | command, tries); | 82 | command, tries); |
83 | msleep(ETP_PS2_COMMAND_DELAY); | 83 | msleep(ETP_PS2_COMMAND_DELAY); |
84 | } while (tries > 0); | 84 | } while (tries > 0); |
85 | 85 | ||
86 | if (rc) | 86 | if (rc) |
87 | psmouse_err(psmouse, "ps2 command 0x%02x failed.\n", command); | 87 | psmouse_err(psmouse, "ps2 command 0x%02x failed.\n", command); |
88 | 88 | ||
89 | return rc; | 89 | return rc; |
90 | } | 90 | } |
91 | 91 | ||
92 | /* | 92 | /* |
93 | * Send an Elantech style special command to read a value from a register | 93 | * Send an Elantech style special command to read a value from a register |
94 | */ | 94 | */ |
95 | static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, | 95 | static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, |
96 | unsigned char *val) | 96 | unsigned char *val) |
97 | { | 97 | { |
98 | struct elantech_data *etd = psmouse->private; | 98 | struct elantech_data *etd = psmouse->private; |
99 | unsigned char param[3]; | 99 | unsigned char param[3]; |
100 | int rc = 0; | 100 | int rc = 0; |
101 | 101 | ||
102 | if (reg < 0x07 || reg > 0x26) | 102 | if (reg < 0x07 || reg > 0x26) |
103 | return -1; | 103 | return -1; |
104 | 104 | ||
105 | if (reg > 0x11 && reg < 0x20) | 105 | if (reg > 0x11 && reg < 0x20) |
106 | return -1; | 106 | return -1; |
107 | 107 | ||
108 | switch (etd->hw_version) { | 108 | switch (etd->hw_version) { |
109 | case 1: | 109 | case 1: |
110 | if (psmouse_sliced_command(psmouse, ETP_REGISTER_READ) || | 110 | if (psmouse_sliced_command(psmouse, ETP_REGISTER_READ) || |
111 | psmouse_sliced_command(psmouse, reg) || | 111 | psmouse_sliced_command(psmouse, reg) || |
112 | ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) { | 112 | ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) { |
113 | rc = -1; | 113 | rc = -1; |
114 | } | 114 | } |
115 | break; | 115 | break; |
116 | 116 | ||
117 | case 2: | 117 | case 2: |
118 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 118 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
119 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READ) || | 119 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READ) || |
120 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 120 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
121 | elantech_ps2_command(psmouse, NULL, reg) || | 121 | elantech_ps2_command(psmouse, NULL, reg) || |
122 | elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) { | 122 | elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) { |
123 | rc = -1; | 123 | rc = -1; |
124 | } | 124 | } |
125 | break; | 125 | break; |
126 | 126 | ||
127 | case 3 ... 4: | 127 | case 3 ... 4: |
128 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 128 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
129 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || | 129 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || |
130 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 130 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
131 | elantech_ps2_command(psmouse, NULL, reg) || | 131 | elantech_ps2_command(psmouse, NULL, reg) || |
132 | elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) { | 132 | elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) { |
133 | rc = -1; | 133 | rc = -1; |
134 | } | 134 | } |
135 | break; | 135 | break; |
136 | } | 136 | } |
137 | 137 | ||
138 | if (rc) | 138 | if (rc) |
139 | psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg); | 139 | psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg); |
140 | else if (etd->hw_version != 4) | 140 | else if (etd->hw_version != 4) |
141 | *val = param[0]; | 141 | *val = param[0]; |
142 | else | 142 | else |
143 | *val = param[1]; | 143 | *val = param[1]; |
144 | 144 | ||
145 | return rc; | 145 | return rc; |
146 | } | 146 | } |
147 | 147 | ||
148 | /* | 148 | /* |
149 | * Send an Elantech style special command to write a register with a value | 149 | * Send an Elantech style special command to write a register with a value |
150 | */ | 150 | */ |
151 | static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, | 151 | static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, |
152 | unsigned char val) | 152 | unsigned char val) |
153 | { | 153 | { |
154 | struct elantech_data *etd = psmouse->private; | 154 | struct elantech_data *etd = psmouse->private; |
155 | int rc = 0; | 155 | int rc = 0; |
156 | 156 | ||
157 | if (reg < 0x07 || reg > 0x26) | 157 | if (reg < 0x07 || reg > 0x26) |
158 | return -1; | 158 | return -1; |
159 | 159 | ||
160 | if (reg > 0x11 && reg < 0x20) | 160 | if (reg > 0x11 && reg < 0x20) |
161 | return -1; | 161 | return -1; |
162 | 162 | ||
163 | switch (etd->hw_version) { | 163 | switch (etd->hw_version) { |
164 | case 1: | 164 | case 1: |
165 | if (psmouse_sliced_command(psmouse, ETP_REGISTER_WRITE) || | 165 | if (psmouse_sliced_command(psmouse, ETP_REGISTER_WRITE) || |
166 | psmouse_sliced_command(psmouse, reg) || | 166 | psmouse_sliced_command(psmouse, reg) || |
167 | psmouse_sliced_command(psmouse, val) || | 167 | psmouse_sliced_command(psmouse, val) || |
168 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) { | 168 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) { |
169 | rc = -1; | 169 | rc = -1; |
170 | } | 170 | } |
171 | break; | 171 | break; |
172 | 172 | ||
173 | case 2: | 173 | case 2: |
174 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 174 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
175 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_WRITE) || | 175 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_WRITE) || |
176 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 176 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
177 | elantech_ps2_command(psmouse, NULL, reg) || | 177 | elantech_ps2_command(psmouse, NULL, reg) || |
178 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 178 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
179 | elantech_ps2_command(psmouse, NULL, val) || | 179 | elantech_ps2_command(psmouse, NULL, val) || |
180 | elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { | 180 | elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { |
181 | rc = -1; | 181 | rc = -1; |
182 | } | 182 | } |
183 | break; | 183 | break; |
184 | 184 | ||
185 | case 3: | 185 | case 3: |
186 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 186 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
187 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || | 187 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || |
188 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 188 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
189 | elantech_ps2_command(psmouse, NULL, reg) || | 189 | elantech_ps2_command(psmouse, NULL, reg) || |
190 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 190 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
191 | elantech_ps2_command(psmouse, NULL, val) || | 191 | elantech_ps2_command(psmouse, NULL, val) || |
192 | elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { | 192 | elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { |
193 | rc = -1; | 193 | rc = -1; |
194 | } | 194 | } |
195 | break; | 195 | break; |
196 | 196 | ||
197 | case 4: | 197 | case 4: |
198 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 198 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
199 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || | 199 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || |
200 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 200 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
201 | elantech_ps2_command(psmouse, NULL, reg) || | 201 | elantech_ps2_command(psmouse, NULL, reg) || |
202 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 202 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
203 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || | 203 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || |
204 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | 204 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || |
205 | elantech_ps2_command(psmouse, NULL, val) || | 205 | elantech_ps2_command(psmouse, NULL, val) || |
206 | elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { | 206 | elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { |
207 | rc = -1; | 207 | rc = -1; |
208 | } | 208 | } |
209 | break; | 209 | break; |
210 | } | 210 | } |
211 | 211 | ||
212 | if (rc) | 212 | if (rc) |
213 | psmouse_err(psmouse, | 213 | psmouse_err(psmouse, |
214 | "failed to write register 0x%02x with value 0x%02x.\n", | 214 | "failed to write register 0x%02x with value 0x%02x.\n", |
215 | reg, val); | 215 | reg, val); |
216 | 216 | ||
217 | return rc; | 217 | return rc; |
218 | } | 218 | } |
219 | 219 | ||
220 | /* | 220 | /* |
221 | * Dump a complete mouse movement packet to the syslog | 221 | * Dump a complete mouse movement packet to the syslog |
222 | */ | 222 | */ |
223 | static void elantech_packet_dump(struct psmouse *psmouse) | 223 | static void elantech_packet_dump(struct psmouse *psmouse) |
224 | { | 224 | { |
225 | int i; | 225 | int i; |
226 | 226 | ||
227 | psmouse_printk(KERN_DEBUG, psmouse, "PS/2 packet ["); | 227 | psmouse_printk(KERN_DEBUG, psmouse, "PS/2 packet ["); |
228 | for (i = 0; i < psmouse->pktsize; i++) | 228 | for (i = 0; i < psmouse->pktsize; i++) |
229 | printk("%s0x%02x ", i ? ", " : " ", psmouse->packet[i]); | 229 | printk("%s0x%02x ", i ? ", " : " ", psmouse->packet[i]); |
230 | printk("]\n"); | 230 | printk("]\n"); |
231 | } | 231 | } |
232 | 232 | ||
233 | /* | 233 | /* |
234 | * Interpret complete data packets and report absolute mode input events for | 234 | * Interpret complete data packets and report absolute mode input events for |
235 | * hardware version 1. (4 byte packets) | 235 | * hardware version 1. (4 byte packets) |
236 | */ | 236 | */ |
237 | static void elantech_report_absolute_v1(struct psmouse *psmouse) | 237 | static void elantech_report_absolute_v1(struct psmouse *psmouse) |
238 | { | 238 | { |
239 | struct input_dev *dev = psmouse->dev; | 239 | struct input_dev *dev = psmouse->dev; |
240 | struct elantech_data *etd = psmouse->private; | 240 | struct elantech_data *etd = psmouse->private; |
241 | unsigned char *packet = psmouse->packet; | 241 | unsigned char *packet = psmouse->packet; |
242 | int fingers; | 242 | int fingers; |
243 | 243 | ||
244 | if (etd->fw_version < 0x020000) { | 244 | if (etd->fw_version < 0x020000) { |
245 | /* | 245 | /* |
246 | * byte 0: D U p1 p2 1 p3 R L | 246 | * byte 0: D U p1 p2 1 p3 R L |
247 | * byte 1: f 0 th tw x9 x8 y9 y8 | 247 | * byte 1: f 0 th tw x9 x8 y9 y8 |
248 | */ | 248 | */ |
249 | fingers = ((packet[1] & 0x80) >> 7) + | 249 | fingers = ((packet[1] & 0x80) >> 7) + |
250 | ((packet[1] & 0x30) >> 4); | 250 | ((packet[1] & 0x30) >> 4); |
251 | } else { | 251 | } else { |
252 | /* | 252 | /* |
253 | * byte 0: n1 n0 p2 p1 1 p3 R L | 253 | * byte 0: n1 n0 p2 p1 1 p3 R L |
254 | * byte 1: 0 0 0 0 x9 x8 y9 y8 | 254 | * byte 1: 0 0 0 0 x9 x8 y9 y8 |
255 | */ | 255 | */ |
256 | fingers = (packet[0] & 0xc0) >> 6; | 256 | fingers = (packet[0] & 0xc0) >> 6; |
257 | } | 257 | } |
258 | 258 | ||
259 | if (etd->jumpy_cursor) { | 259 | if (etd->jumpy_cursor) { |
260 | if (fingers != 1) { | 260 | if (fingers != 1) { |
261 | etd->single_finger_reports = 0; | 261 | etd->single_finger_reports = 0; |
262 | } else if (etd->single_finger_reports < 2) { | 262 | } else if (etd->single_finger_reports < 2) { |
263 | /* Discard first 2 reports of one finger, bogus */ | 263 | /* Discard first 2 reports of one finger, bogus */ |
264 | etd->single_finger_reports++; | 264 | etd->single_finger_reports++; |
265 | elantech_debug("discarding packet\n"); | 265 | elantech_debug("discarding packet\n"); |
266 | return; | 266 | return; |
267 | } | 267 | } |
268 | } | 268 | } |
269 | 269 | ||
270 | input_report_key(dev, BTN_TOUCH, fingers != 0); | 270 | input_report_key(dev, BTN_TOUCH, fingers != 0); |
271 | 271 | ||
272 | /* | 272 | /* |
273 | * byte 2: x7 x6 x5 x4 x3 x2 x1 x0 | 273 | * byte 2: x7 x6 x5 x4 x3 x2 x1 x0 |
274 | * byte 3: y7 y6 y5 y4 y3 y2 y1 y0 | 274 | * byte 3: y7 y6 y5 y4 y3 y2 y1 y0 |
275 | */ | 275 | */ |
276 | if (fingers) { | 276 | if (fingers) { |
277 | input_report_abs(dev, ABS_X, | 277 | input_report_abs(dev, ABS_X, |
278 | ((packet[1] & 0x0c) << 6) | packet[2]); | 278 | ((packet[1] & 0x0c) << 6) | packet[2]); |
279 | input_report_abs(dev, ABS_Y, | 279 | input_report_abs(dev, ABS_Y, |
280 | etd->y_max - (((packet[1] & 0x03) << 8) | packet[3])); | 280 | etd->y_max - (((packet[1] & 0x03) << 8) | packet[3])); |
281 | } | 281 | } |
282 | 282 | ||
283 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | 283 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
284 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); | 284 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); |
285 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); | 285 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); |
286 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | 286 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
287 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | 287 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
288 | 288 | ||
289 | if (etd->fw_version < 0x020000 && | 289 | if (etd->fw_version < 0x020000 && |
290 | (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { | 290 | (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { |
291 | /* rocker up */ | 291 | /* rocker up */ |
292 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); | 292 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); |
293 | /* rocker down */ | 293 | /* rocker down */ |
294 | input_report_key(dev, BTN_BACK, packet[0] & 0x80); | 294 | input_report_key(dev, BTN_BACK, packet[0] & 0x80); |
295 | } | 295 | } |
296 | 296 | ||
297 | input_sync(dev); | 297 | input_sync(dev); |
298 | } | 298 | } |
299 | 299 | ||
300 | static void elantech_set_slot(struct input_dev *dev, int slot, bool active, | 300 | static void elantech_set_slot(struct input_dev *dev, int slot, bool active, |
301 | unsigned int x, unsigned int y) | 301 | unsigned int x, unsigned int y) |
302 | { | 302 | { |
303 | input_mt_slot(dev, slot); | 303 | input_mt_slot(dev, slot); |
304 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); | 304 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); |
305 | if (active) { | 305 | if (active) { |
306 | input_report_abs(dev, ABS_MT_POSITION_X, x); | 306 | input_report_abs(dev, ABS_MT_POSITION_X, x); |
307 | input_report_abs(dev, ABS_MT_POSITION_Y, y); | 307 | input_report_abs(dev, ABS_MT_POSITION_Y, y); |
308 | } | 308 | } |
309 | } | 309 | } |
310 | 310 | ||
311 | /* x1 < x2 and y1 < y2 when two fingers, x = y = 0 when not pressed */ | 311 | /* x1 < x2 and y1 < y2 when two fingers, x = y = 0 when not pressed */ |
312 | static void elantech_report_semi_mt_data(struct input_dev *dev, | 312 | static void elantech_report_semi_mt_data(struct input_dev *dev, |
313 | unsigned int num_fingers, | 313 | unsigned int num_fingers, |
314 | unsigned int x1, unsigned int y1, | 314 | unsigned int x1, unsigned int y1, |
315 | unsigned int x2, unsigned int y2) | 315 | unsigned int x2, unsigned int y2) |
316 | { | 316 | { |
317 | elantech_set_slot(dev, 0, num_fingers != 0, x1, y1); | 317 | elantech_set_slot(dev, 0, num_fingers != 0, x1, y1); |
318 | elantech_set_slot(dev, 1, num_fingers == 2, x2, y2); | 318 | elantech_set_slot(dev, 1, num_fingers == 2, x2, y2); |
319 | } | 319 | } |
320 | 320 | ||
321 | /* | 321 | /* |
322 | * Interpret complete data packets and report absolute mode input events for | 322 | * Interpret complete data packets and report absolute mode input events for |
323 | * hardware version 2. (6 byte packets) | 323 | * hardware version 2. (6 byte packets) |
324 | */ | 324 | */ |
325 | static void elantech_report_absolute_v2(struct psmouse *psmouse) | 325 | static void elantech_report_absolute_v2(struct psmouse *psmouse) |
326 | { | 326 | { |
327 | struct elantech_data *etd = psmouse->private; | 327 | struct elantech_data *etd = psmouse->private; |
328 | struct input_dev *dev = psmouse->dev; | 328 | struct input_dev *dev = psmouse->dev; |
329 | unsigned char *packet = psmouse->packet; | 329 | unsigned char *packet = psmouse->packet; |
330 | unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0; | 330 | unsigned int fingers, x1 = 0, y1 = 0, x2 = 0, y2 = 0; |
331 | unsigned int width = 0, pres = 0; | 331 | unsigned int width = 0, pres = 0; |
332 | 332 | ||
333 | /* byte 0: n1 n0 . . . . R L */ | 333 | /* byte 0: n1 n0 . . . . R L */ |
334 | fingers = (packet[0] & 0xc0) >> 6; | 334 | fingers = (packet[0] & 0xc0) >> 6; |
335 | 335 | ||
336 | switch (fingers) { | 336 | switch (fingers) { |
337 | case 3: | 337 | case 3: |
338 | /* | 338 | /* |
339 | * Same as one finger, except report of more than 3 fingers: | 339 | * Same as one finger, except report of more than 3 fingers: |
340 | * byte 3: n4 . w1 w0 . . . . | 340 | * byte 3: n4 . w1 w0 . . . . |
341 | */ | 341 | */ |
342 | if (packet[3] & 0x80) | 342 | if (packet[3] & 0x80) |
343 | fingers = 4; | 343 | fingers = 4; |
344 | /* pass through... */ | 344 | /* pass through... */ |
345 | case 1: | 345 | case 1: |
346 | /* | 346 | /* |
347 | * byte 1: . . . . x11 x10 x9 x8 | 347 | * byte 1: . . . . x11 x10 x9 x8 |
348 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 | 348 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 |
349 | */ | 349 | */ |
350 | x1 = ((packet[1] & 0x0f) << 8) | packet[2]; | 350 | x1 = ((packet[1] & 0x0f) << 8) | packet[2]; |
351 | /* | 351 | /* |
352 | * byte 4: . . . . y11 y10 y9 y8 | 352 | * byte 4: . . . . y11 y10 y9 y8 |
353 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 | 353 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 |
354 | */ | 354 | */ |
355 | y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); | 355 | y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); |
356 | 356 | ||
357 | pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); | 357 | pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); |
358 | width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); | 358 | width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); |
359 | break; | 359 | break; |
360 | 360 | ||
361 | case 2: | 361 | case 2: |
362 | /* | 362 | /* |
363 | * The coordinate of each finger is reported separately | 363 | * The coordinate of each finger is reported separately |
364 | * with a lower resolution for two finger touches: | 364 | * with a lower resolution for two finger touches: |
365 | * byte 0: . . ay8 ax8 . . . . | 365 | * byte 0: . . ay8 ax8 . . . . |
366 | * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 | 366 | * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 |
367 | */ | 367 | */ |
368 | x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; | 368 | x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; |
369 | /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ | 369 | /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ |
370 | y1 = etd->y_max - | 370 | y1 = etd->y_max - |
371 | ((((packet[0] & 0x20) << 3) | packet[2]) << 2); | 371 | ((((packet[0] & 0x20) << 3) | packet[2]) << 2); |
372 | /* | 372 | /* |
373 | * byte 3: . . by8 bx8 . . . . | 373 | * byte 3: . . by8 bx8 . . . . |
374 | * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 | 374 | * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 |
375 | */ | 375 | */ |
376 | x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; | 376 | x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; |
377 | /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ | 377 | /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ |
378 | y2 = etd->y_max - | 378 | y2 = etd->y_max - |
379 | ((((packet[3] & 0x20) << 3) | packet[5]) << 2); | 379 | ((((packet[3] & 0x20) << 3) | packet[5]) << 2); |
380 | 380 | ||
381 | /* Unknown so just report sensible values */ | 381 | /* Unknown so just report sensible values */ |
382 | pres = 127; | 382 | pres = 127; |
383 | width = 7; | 383 | width = 7; |
384 | break; | 384 | break; |
385 | } | 385 | } |
386 | 386 | ||
387 | input_report_key(dev, BTN_TOUCH, fingers != 0); | 387 | input_report_key(dev, BTN_TOUCH, fingers != 0); |
388 | if (fingers != 0) { | 388 | if (fingers != 0) { |
389 | input_report_abs(dev, ABS_X, x1); | 389 | input_report_abs(dev, ABS_X, x1); |
390 | input_report_abs(dev, ABS_Y, y1); | 390 | input_report_abs(dev, ABS_Y, y1); |
391 | } | 391 | } |
392 | elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); | 392 | elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); |
393 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | 393 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
394 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); | 394 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); |
395 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); | 395 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); |
396 | input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); | 396 | input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); |
397 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | 397 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
398 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | 398 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
399 | if (etd->reports_pressure) { | 399 | if (etd->reports_pressure) { |
400 | input_report_abs(dev, ABS_PRESSURE, pres); | 400 | input_report_abs(dev, ABS_PRESSURE, pres); |
401 | input_report_abs(dev, ABS_TOOL_WIDTH, width); | 401 | input_report_abs(dev, ABS_TOOL_WIDTH, width); |
402 | } | 402 | } |
403 | 403 | ||
404 | input_sync(dev); | 404 | input_sync(dev); |
405 | } | 405 | } |
406 | 406 | ||
407 | static void elantech_report_trackpoint(struct psmouse *psmouse, | 407 | static void elantech_report_trackpoint(struct psmouse *psmouse, |
408 | int packet_type) | 408 | int packet_type) |
409 | { | 409 | { |
410 | /* | 410 | /* |
411 | * byte 0: 0 0 sx sy 0 M R L | 411 | * byte 0: 0 0 sx sy 0 M R L |
412 | * byte 1:~sx 0 0 0 0 0 0 0 | 412 | * byte 1:~sx 0 0 0 0 0 0 0 |
413 | * byte 2:~sy 0 0 0 0 0 0 0 | 413 | * byte 2:~sy 0 0 0 0 0 0 0 |
414 | * byte 3: 0 0 ~sy ~sx 0 1 1 0 | 414 | * byte 3: 0 0 ~sy ~sx 0 1 1 0 |
415 | * byte 4: x7 x6 x5 x4 x3 x2 x1 x0 | 415 | * byte 4: x7 x6 x5 x4 x3 x2 x1 x0 |
416 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 | 416 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 |
417 | * | 417 | * |
418 | * x and y are written in two's complement spread | 418 | * x and y are written in two's complement spread |
419 | * over 9 bits with sx/sy the relative top bit and | 419 | * over 9 bits with sx/sy the relative top bit and |
420 | * x7..x0 and y7..y0 the lower bits. | 420 | * x7..x0 and y7..y0 the lower bits. |
421 | * The sign of y is opposite to what the input driver | 421 | * The sign of y is opposite to what the input driver |
422 | * expects for a relative movement | 422 | * expects for a relative movement |
423 | */ | 423 | */ |
424 | 424 | ||
425 | struct elantech_data *etd = psmouse->private; | 425 | struct elantech_data *etd = psmouse->private; |
426 | struct input_dev *tp_dev = etd->tp_dev; | 426 | struct input_dev *tp_dev = etd->tp_dev; |
427 | unsigned char *packet = psmouse->packet; | 427 | unsigned char *packet = psmouse->packet; |
428 | int x, y; | 428 | int x, y; |
429 | u32 t; | 429 | u32 t; |
430 | 430 | ||
431 | if (dev_WARN_ONCE(&psmouse->ps2dev.serio->dev, | 431 | if (dev_WARN_ONCE(&psmouse->ps2dev.serio->dev, |
432 | !tp_dev, | 432 | !tp_dev, |
433 | psmouse_fmt("Unexpected trackpoint message\n"))) { | 433 | psmouse_fmt("Unexpected trackpoint message\n"))) { |
434 | if (etd->debug == 1) | 434 | if (etd->debug == 1) |
435 | elantech_packet_dump(psmouse); | 435 | elantech_packet_dump(psmouse); |
436 | return; | 436 | return; |
437 | } | 437 | } |
438 | 438 | ||
439 | t = get_unaligned_le32(&packet[0]); | 439 | t = get_unaligned_le32(&packet[0]); |
440 | 440 | ||
441 | switch (t & ~7U) { | 441 | switch (t & ~7U) { |
442 | case 0x06000030U: | 442 | case 0x06000030U: |
443 | case 0x16008020U: | 443 | case 0x16008020U: |
444 | case 0x26800010U: | 444 | case 0x26800010U: |
445 | case 0x36808000U: | 445 | case 0x36808000U: |
446 | x = packet[4] - (int)((packet[1]^0x80) << 1); | 446 | x = packet[4] - (int)((packet[1]^0x80) << 1); |
447 | y = (int)((packet[2]^0x80) << 1) - packet[5]; | 447 | y = (int)((packet[2]^0x80) << 1) - packet[5]; |
448 | 448 | ||
449 | input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01); | 449 | input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01); |
450 | input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02); | 450 | input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02); |
451 | input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04); | 451 | input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04); |
452 | 452 | ||
453 | input_report_rel(tp_dev, REL_X, x); | 453 | input_report_rel(tp_dev, REL_X, x); |
454 | input_report_rel(tp_dev, REL_Y, y); | 454 | input_report_rel(tp_dev, REL_Y, y); |
455 | 455 | ||
456 | input_sync(tp_dev); | 456 | input_sync(tp_dev); |
457 | 457 | ||
458 | break; | 458 | break; |
459 | 459 | ||
460 | default: | 460 | default: |
461 | /* Dump unexpected packet sequences if debug=1 (default) */ | 461 | /* Dump unexpected packet sequences if debug=1 (default) */ |
462 | if (etd->debug == 1) | 462 | if (etd->debug == 1) |
463 | elantech_packet_dump(psmouse); | 463 | elantech_packet_dump(psmouse); |
464 | 464 | ||
465 | break; | 465 | break; |
466 | } | 466 | } |
467 | } | 467 | } |
468 | 468 | ||
469 | /* | 469 | /* |
470 | * Interpret complete data packets and report absolute mode input events for | 470 | * Interpret complete data packets and report absolute mode input events for |
471 | * hardware version 3. (12 byte packets for two fingers) | 471 | * hardware version 3. (12 byte packets for two fingers) |
472 | */ | 472 | */ |
473 | static void elantech_report_absolute_v3(struct psmouse *psmouse, | 473 | static void elantech_report_absolute_v3(struct psmouse *psmouse, |
474 | int packet_type) | 474 | int packet_type) |
475 | { | 475 | { |
476 | struct input_dev *dev = psmouse->dev; | 476 | struct input_dev *dev = psmouse->dev; |
477 | struct elantech_data *etd = psmouse->private; | 477 | struct elantech_data *etd = psmouse->private; |
478 | unsigned char *packet = psmouse->packet; | 478 | unsigned char *packet = psmouse->packet; |
479 | unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0; | 479 | unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0; |
480 | unsigned int width = 0, pres = 0; | 480 | unsigned int width = 0, pres = 0; |
481 | 481 | ||
482 | /* byte 0: n1 n0 . . . . R L */ | 482 | /* byte 0: n1 n0 . . . . R L */ |
483 | fingers = (packet[0] & 0xc0) >> 6; | 483 | fingers = (packet[0] & 0xc0) >> 6; |
484 | 484 | ||
485 | switch (fingers) { | 485 | switch (fingers) { |
486 | case 3: | 486 | case 3: |
487 | case 1: | 487 | case 1: |
488 | /* | 488 | /* |
489 | * byte 1: . . . . x11 x10 x9 x8 | 489 | * byte 1: . . . . x11 x10 x9 x8 |
490 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 | 490 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 |
491 | */ | 491 | */ |
492 | x1 = ((packet[1] & 0x0f) << 8) | packet[2]; | 492 | x1 = ((packet[1] & 0x0f) << 8) | packet[2]; |
493 | /* | 493 | /* |
494 | * byte 4: . . . . y11 y10 y9 y8 | 494 | * byte 4: . . . . y11 y10 y9 y8 |
495 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 | 495 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 |
496 | */ | 496 | */ |
497 | y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); | 497 | y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); |
498 | break; | 498 | break; |
499 | 499 | ||
500 | case 2: | 500 | case 2: |
501 | if (packet_type == PACKET_V3_HEAD) { | 501 | if (packet_type == PACKET_V3_HEAD) { |
502 | /* | 502 | /* |
503 | * byte 1: . . . . ax11 ax10 ax9 ax8 | 503 | * byte 1: . . . . ax11 ax10 ax9 ax8 |
504 | * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 | 504 | * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 |
505 | */ | 505 | */ |
506 | etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2]; | 506 | etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2]; |
507 | /* | 507 | /* |
508 | * byte 4: . . . . ay11 ay10 ay9 ay8 | 508 | * byte 4: . . . . ay11 ay10 ay9 ay8 |
509 | * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 | 509 | * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 |
510 | */ | 510 | */ |
511 | etd->mt[0].y = etd->y_max - | 511 | etd->mt[0].y = etd->y_max - |
512 | (((packet[4] & 0x0f) << 8) | packet[5]); | 512 | (((packet[4] & 0x0f) << 8) | packet[5]); |
513 | /* | 513 | /* |
514 | * wait for next packet | 514 | * wait for next packet |
515 | */ | 515 | */ |
516 | return; | 516 | return; |
517 | } | 517 | } |
518 | 518 | ||
519 | /* packet_type == PACKET_V3_TAIL */ | 519 | /* packet_type == PACKET_V3_TAIL */ |
520 | x1 = etd->mt[0].x; | 520 | x1 = etd->mt[0].x; |
521 | y1 = etd->mt[0].y; | 521 | y1 = etd->mt[0].y; |
522 | x2 = ((packet[1] & 0x0f) << 8) | packet[2]; | 522 | x2 = ((packet[1] & 0x0f) << 8) | packet[2]; |
523 | y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); | 523 | y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); |
524 | break; | 524 | break; |
525 | } | 525 | } |
526 | 526 | ||
527 | pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); | 527 | pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); |
528 | width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); | 528 | width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); |
529 | 529 | ||
530 | input_report_key(dev, BTN_TOUCH, fingers != 0); | 530 | input_report_key(dev, BTN_TOUCH, fingers != 0); |
531 | if (fingers != 0) { | 531 | if (fingers != 0) { |
532 | input_report_abs(dev, ABS_X, x1); | 532 | input_report_abs(dev, ABS_X, x1); |
533 | input_report_abs(dev, ABS_Y, y1); | 533 | input_report_abs(dev, ABS_Y, y1); |
534 | } | 534 | } |
535 | elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); | 535 | elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); |
536 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | 536 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
537 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); | 537 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); |
538 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); | 538 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); |
539 | 539 | ||
540 | /* For clickpads map both buttons to BTN_LEFT */ | 540 | /* For clickpads map both buttons to BTN_LEFT */ |
541 | if (etd->fw_version & 0x001000) { | 541 | if (etd->fw_version & 0x001000) { |
542 | input_report_key(dev, BTN_LEFT, packet[0] & 0x03); | 542 | input_report_key(dev, BTN_LEFT, packet[0] & 0x03); |
543 | } else { | 543 | } else { |
544 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | 544 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
545 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | 545 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
546 | } | 546 | } |
547 | 547 | ||
548 | input_report_abs(dev, ABS_PRESSURE, pres); | 548 | input_report_abs(dev, ABS_PRESSURE, pres); |
549 | input_report_abs(dev, ABS_TOOL_WIDTH, width); | 549 | input_report_abs(dev, ABS_TOOL_WIDTH, width); |
550 | 550 | ||
551 | input_sync(dev); | 551 | input_sync(dev); |
552 | } | 552 | } |
553 | 553 | ||
554 | static void elantech_input_sync_v4(struct psmouse *psmouse) | 554 | static void elantech_input_sync_v4(struct psmouse *psmouse) |
555 | { | 555 | { |
556 | struct input_dev *dev = psmouse->dev; | 556 | struct input_dev *dev = psmouse->dev; |
557 | struct elantech_data *etd = psmouse->private; | 557 | struct elantech_data *etd = psmouse->private; |
558 | unsigned char *packet = psmouse->packet; | 558 | unsigned char *packet = psmouse->packet; |
559 | 559 | ||
560 | /* For clickpads map both buttons to BTN_LEFT */ | 560 | /* For clickpads map both buttons to BTN_LEFT */ |
561 | if (etd->fw_version & 0x001000) { | 561 | if (etd->fw_version & 0x001000) { |
562 | input_report_key(dev, BTN_LEFT, packet[0] & 0x03); | 562 | input_report_key(dev, BTN_LEFT, packet[0] & 0x03); |
563 | } else { | 563 | } else { |
564 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | 564 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
565 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | 565 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
566 | input_report_key(dev, BTN_MIDDLE, packet[0] & 0x04); | ||
566 | } | 567 | } |
567 | 568 | ||
568 | input_mt_report_pointer_emulation(dev, true); | 569 | input_mt_report_pointer_emulation(dev, true); |
569 | input_sync(dev); | 570 | input_sync(dev); |
570 | } | 571 | } |
571 | 572 | ||
572 | static void process_packet_status_v4(struct psmouse *psmouse) | 573 | static void process_packet_status_v4(struct psmouse *psmouse) |
573 | { | 574 | { |
574 | struct input_dev *dev = psmouse->dev; | 575 | struct input_dev *dev = psmouse->dev; |
575 | unsigned char *packet = psmouse->packet; | 576 | unsigned char *packet = psmouse->packet; |
576 | unsigned fingers; | 577 | unsigned fingers; |
577 | int i; | 578 | int i; |
578 | 579 | ||
579 | /* notify finger state change */ | 580 | /* notify finger state change */ |
580 | fingers = packet[1] & 0x1f; | 581 | fingers = packet[1] & 0x1f; |
581 | for (i = 0; i < ETP_MAX_FINGERS; i++) { | 582 | for (i = 0; i < ETP_MAX_FINGERS; i++) { |
582 | if ((fingers & (1 << i)) == 0) { | 583 | if ((fingers & (1 << i)) == 0) { |
583 | input_mt_slot(dev, i); | 584 | input_mt_slot(dev, i); |
584 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, false); | 585 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, false); |
585 | } | 586 | } |
586 | } | 587 | } |
587 | 588 | ||
588 | elantech_input_sync_v4(psmouse); | 589 | elantech_input_sync_v4(psmouse); |
589 | } | 590 | } |
590 | 591 | ||
591 | static void process_packet_head_v4(struct psmouse *psmouse) | 592 | static void process_packet_head_v4(struct psmouse *psmouse) |
592 | { | 593 | { |
593 | struct input_dev *dev = psmouse->dev; | 594 | struct input_dev *dev = psmouse->dev; |
594 | struct elantech_data *etd = psmouse->private; | 595 | struct elantech_data *etd = psmouse->private; |
595 | unsigned char *packet = psmouse->packet; | 596 | unsigned char *packet = psmouse->packet; |
596 | int id = ((packet[3] & 0xe0) >> 5) - 1; | 597 | int id = ((packet[3] & 0xe0) >> 5) - 1; |
597 | int pres, traces; | 598 | int pres, traces; |
598 | 599 | ||
599 | if (id < 0) | 600 | if (id < 0) |
600 | return; | 601 | return; |
601 | 602 | ||
602 | etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2]; | 603 | etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2]; |
603 | etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); | 604 | etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); |
604 | pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); | 605 | pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); |
605 | traces = (packet[0] & 0xf0) >> 4; | 606 | traces = (packet[0] & 0xf0) >> 4; |
606 | 607 | ||
607 | input_mt_slot(dev, id); | 608 | input_mt_slot(dev, id); |
608 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); | 609 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); |
609 | 610 | ||
610 | input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); | 611 | input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); |
611 | input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); | 612 | input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); |
612 | input_report_abs(dev, ABS_MT_PRESSURE, pres); | 613 | input_report_abs(dev, ABS_MT_PRESSURE, pres); |
613 | input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width); | 614 | input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width); |
614 | /* report this for backwards compatibility */ | 615 | /* report this for backwards compatibility */ |
615 | input_report_abs(dev, ABS_TOOL_WIDTH, traces); | 616 | input_report_abs(dev, ABS_TOOL_WIDTH, traces); |
616 | 617 | ||
617 | elantech_input_sync_v4(psmouse); | 618 | elantech_input_sync_v4(psmouse); |
618 | } | 619 | } |
619 | 620 | ||
620 | static void process_packet_motion_v4(struct psmouse *psmouse) | 621 | static void process_packet_motion_v4(struct psmouse *psmouse) |
621 | { | 622 | { |
622 | struct input_dev *dev = psmouse->dev; | 623 | struct input_dev *dev = psmouse->dev; |
623 | struct elantech_data *etd = psmouse->private; | 624 | struct elantech_data *etd = psmouse->private; |
624 | unsigned char *packet = psmouse->packet; | 625 | unsigned char *packet = psmouse->packet; |
625 | int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0; | 626 | int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0; |
626 | int id, sid; | 627 | int id, sid; |
627 | 628 | ||
628 | id = ((packet[0] & 0xe0) >> 5) - 1; | 629 | id = ((packet[0] & 0xe0) >> 5) - 1; |
629 | if (id < 0) | 630 | if (id < 0) |
630 | return; | 631 | return; |
631 | 632 | ||
632 | sid = ((packet[3] & 0xe0) >> 5) - 1; | 633 | sid = ((packet[3] & 0xe0) >> 5) - 1; |
633 | weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1; | 634 | weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1; |
634 | /* | 635 | /* |
635 | * Motion packets give us the delta of x, y values of specific fingers, | 636 | * Motion packets give us the delta of x, y values of specific fingers, |
636 | * but in two's complement. Let the compiler do the conversion for us. | 637 | * but in two's complement. Let the compiler do the conversion for us. |
637 | * Also _enlarge_ the numbers to int, in case of overflow. | 638 | * Also _enlarge_ the numbers to int, in case of overflow. |
638 | */ | 639 | */ |
639 | delta_x1 = (signed char)packet[1]; | 640 | delta_x1 = (signed char)packet[1]; |
640 | delta_y1 = (signed char)packet[2]; | 641 | delta_y1 = (signed char)packet[2]; |
641 | delta_x2 = (signed char)packet[4]; | 642 | delta_x2 = (signed char)packet[4]; |
642 | delta_y2 = (signed char)packet[5]; | 643 | delta_y2 = (signed char)packet[5]; |
643 | 644 | ||
644 | etd->mt[id].x += delta_x1 * weight; | 645 | etd->mt[id].x += delta_x1 * weight; |
645 | etd->mt[id].y -= delta_y1 * weight; | 646 | etd->mt[id].y -= delta_y1 * weight; |
646 | input_mt_slot(dev, id); | 647 | input_mt_slot(dev, id); |
647 | input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); | 648 | input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); |
648 | input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); | 649 | input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); |
649 | 650 | ||
650 | if (sid >= 0) { | 651 | if (sid >= 0) { |
651 | etd->mt[sid].x += delta_x2 * weight; | 652 | etd->mt[sid].x += delta_x2 * weight; |
652 | etd->mt[sid].y -= delta_y2 * weight; | 653 | etd->mt[sid].y -= delta_y2 * weight; |
653 | input_mt_slot(dev, sid); | 654 | input_mt_slot(dev, sid); |
654 | input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x); | 655 | input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x); |
655 | input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y); | 656 | input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y); |
656 | } | 657 | } |
657 | 658 | ||
658 | elantech_input_sync_v4(psmouse); | 659 | elantech_input_sync_v4(psmouse); |
659 | } | 660 | } |
660 | 661 | ||
661 | static void elantech_report_absolute_v4(struct psmouse *psmouse, | 662 | static void elantech_report_absolute_v4(struct psmouse *psmouse, |
662 | int packet_type) | 663 | int packet_type) |
663 | { | 664 | { |
664 | switch (packet_type) { | 665 | switch (packet_type) { |
665 | case PACKET_V4_STATUS: | 666 | case PACKET_V4_STATUS: |
666 | process_packet_status_v4(psmouse); | 667 | process_packet_status_v4(psmouse); |
667 | break; | 668 | break; |
668 | 669 | ||
669 | case PACKET_V4_HEAD: | 670 | case PACKET_V4_HEAD: |
670 | process_packet_head_v4(psmouse); | 671 | process_packet_head_v4(psmouse); |
671 | break; | 672 | break; |
672 | 673 | ||
673 | case PACKET_V4_MOTION: | 674 | case PACKET_V4_MOTION: |
674 | process_packet_motion_v4(psmouse); | 675 | process_packet_motion_v4(psmouse); |
675 | break; | 676 | break; |
676 | 677 | ||
677 | case PACKET_UNKNOWN: | 678 | case PACKET_UNKNOWN: |
678 | default: | 679 | default: |
679 | /* impossible to get here */ | 680 | /* impossible to get here */ |
680 | break; | 681 | break; |
681 | } | 682 | } |
682 | } | 683 | } |
683 | 684 | ||
684 | static int elantech_packet_check_v1(struct psmouse *psmouse) | 685 | static int elantech_packet_check_v1(struct psmouse *psmouse) |
685 | { | 686 | { |
686 | struct elantech_data *etd = psmouse->private; | 687 | struct elantech_data *etd = psmouse->private; |
687 | unsigned char *packet = psmouse->packet; | 688 | unsigned char *packet = psmouse->packet; |
688 | unsigned char p1, p2, p3; | 689 | unsigned char p1, p2, p3; |
689 | 690 | ||
690 | /* Parity bits are placed differently */ | 691 | /* Parity bits are placed differently */ |
691 | if (etd->fw_version < 0x020000) { | 692 | if (etd->fw_version < 0x020000) { |
692 | /* byte 0: D U p1 p2 1 p3 R L */ | 693 | /* byte 0: D U p1 p2 1 p3 R L */ |
693 | p1 = (packet[0] & 0x20) >> 5; | 694 | p1 = (packet[0] & 0x20) >> 5; |
694 | p2 = (packet[0] & 0x10) >> 4; | 695 | p2 = (packet[0] & 0x10) >> 4; |
695 | } else { | 696 | } else { |
696 | /* byte 0: n1 n0 p2 p1 1 p3 R L */ | 697 | /* byte 0: n1 n0 p2 p1 1 p3 R L */ |
697 | p1 = (packet[0] & 0x10) >> 4; | 698 | p1 = (packet[0] & 0x10) >> 4; |
698 | p2 = (packet[0] & 0x20) >> 5; | 699 | p2 = (packet[0] & 0x20) >> 5; |
699 | } | 700 | } |
700 | 701 | ||
701 | p3 = (packet[0] & 0x04) >> 2; | 702 | p3 = (packet[0] & 0x04) >> 2; |
702 | 703 | ||
703 | return etd->parity[packet[1]] == p1 && | 704 | return etd->parity[packet[1]] == p1 && |
704 | etd->parity[packet[2]] == p2 && | 705 | etd->parity[packet[2]] == p2 && |
705 | etd->parity[packet[3]] == p3; | 706 | etd->parity[packet[3]] == p3; |
706 | } | 707 | } |
707 | 708 | ||
708 | static int elantech_debounce_check_v2(struct psmouse *psmouse) | 709 | static int elantech_debounce_check_v2(struct psmouse *psmouse) |
709 | { | 710 | { |
710 | /* | 711 | /* |
711 | * When we encounter packet that matches this exactly, it means the | 712 | * When we encounter packet that matches this exactly, it means the |
712 | * hardware is in debounce status. Just ignore the whole packet. | 713 | * hardware is in debounce status. Just ignore the whole packet. |
713 | */ | 714 | */ |
714 | const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff }; | 715 | const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff }; |
715 | unsigned char *packet = psmouse->packet; | 716 | unsigned char *packet = psmouse->packet; |
716 | 717 | ||
717 | return !memcmp(packet, debounce_packet, sizeof(debounce_packet)); | 718 | return !memcmp(packet, debounce_packet, sizeof(debounce_packet)); |
718 | } | 719 | } |
719 | 720 | ||
720 | static int elantech_packet_check_v2(struct psmouse *psmouse) | 721 | static int elantech_packet_check_v2(struct psmouse *psmouse) |
721 | { | 722 | { |
722 | struct elantech_data *etd = psmouse->private; | 723 | struct elantech_data *etd = psmouse->private; |
723 | unsigned char *packet = psmouse->packet; | 724 | unsigned char *packet = psmouse->packet; |
724 | 725 | ||
725 | /* | 726 | /* |
726 | * V2 hardware has two flavors. Older ones that do not report pressure, | 727 | * V2 hardware has two flavors. Older ones that do not report pressure, |
727 | * and newer ones that reports pressure and width. With newer ones, all | 728 | * and newer ones that reports pressure and width. With newer ones, all |
728 | * packets (1, 2, 3 finger touch) have the same constant bits. With | 729 | * packets (1, 2, 3 finger touch) have the same constant bits. With |
729 | * older ones, 1/3 finger touch packets and 2 finger touch packets | 730 | * older ones, 1/3 finger touch packets and 2 finger touch packets |
730 | * have different constant bits. | 731 | * have different constant bits. |
731 | * With all three cases, if the constant bits are not exactly what I | 732 | * With all three cases, if the constant bits are not exactly what I |
732 | * expected, I consider them invalid. | 733 | * expected, I consider them invalid. |
733 | */ | 734 | */ |
734 | if (etd->reports_pressure) | 735 | if (etd->reports_pressure) |
735 | return (packet[0] & 0x0c) == 0x04 && | 736 | return (packet[0] & 0x0c) == 0x04 && |
736 | (packet[3] & 0x0f) == 0x02; | 737 | (packet[3] & 0x0f) == 0x02; |
737 | 738 | ||
738 | if ((packet[0] & 0xc0) == 0x80) | 739 | if ((packet[0] & 0xc0) == 0x80) |
739 | return (packet[0] & 0x0c) == 0x0c && | 740 | return (packet[0] & 0x0c) == 0x0c && |
740 | (packet[3] & 0x0e) == 0x08; | 741 | (packet[3] & 0x0e) == 0x08; |
741 | 742 | ||
742 | return (packet[0] & 0x3c) == 0x3c && | 743 | return (packet[0] & 0x3c) == 0x3c && |
743 | (packet[1] & 0xf0) == 0x00 && | 744 | (packet[1] & 0xf0) == 0x00 && |
744 | (packet[3] & 0x3e) == 0x38 && | 745 | (packet[3] & 0x3e) == 0x38 && |
745 | (packet[4] & 0xf0) == 0x00; | 746 | (packet[4] & 0xf0) == 0x00; |
746 | } | 747 | } |
747 | 748 | ||
748 | /* | 749 | /* |
749 | * We check the constant bits to determine what packet type we get, | 750 | * We check the constant bits to determine what packet type we get, |
750 | * so packet checking is mandatory for v3 and later hardware. | 751 | * so packet checking is mandatory for v3 and later hardware. |
751 | */ | 752 | */ |
752 | static int elantech_packet_check_v3(struct psmouse *psmouse) | 753 | static int elantech_packet_check_v3(struct psmouse *psmouse) |
753 | { | 754 | { |
754 | struct elantech_data *etd = psmouse->private; | 755 | struct elantech_data *etd = psmouse->private; |
755 | const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; | 756 | const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; |
756 | unsigned char *packet = psmouse->packet; | 757 | unsigned char *packet = psmouse->packet; |
757 | 758 | ||
758 | /* | 759 | /* |
759 | * check debounce first, it has the same signature in byte 0 | 760 | * check debounce first, it has the same signature in byte 0 |
760 | * and byte 3 as PACKET_V3_HEAD. | 761 | * and byte 3 as PACKET_V3_HEAD. |
761 | */ | 762 | */ |
762 | if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) | 763 | if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) |
763 | return PACKET_DEBOUNCE; | 764 | return PACKET_DEBOUNCE; |
764 | 765 | ||
765 | /* | 766 | /* |
766 | * If the hardware flag 'crc_enabled' is set the packets have | 767 | * If the hardware flag 'crc_enabled' is set the packets have |
767 | * different signatures. | 768 | * different signatures. |
768 | */ | 769 | */ |
769 | if (etd->crc_enabled) { | 770 | if (etd->crc_enabled) { |
770 | if ((packet[3] & 0x09) == 0x08) | 771 | if ((packet[3] & 0x09) == 0x08) |
771 | return PACKET_V3_HEAD; | 772 | return PACKET_V3_HEAD; |
772 | 773 | ||
773 | if ((packet[3] & 0x09) == 0x09) | 774 | if ((packet[3] & 0x09) == 0x09) |
774 | return PACKET_V3_TAIL; | 775 | return PACKET_V3_TAIL; |
775 | } else { | 776 | } else { |
776 | if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) | 777 | if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) |
777 | return PACKET_V3_HEAD; | 778 | return PACKET_V3_HEAD; |
778 | 779 | ||
779 | if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) | 780 | if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) |
780 | return PACKET_V3_TAIL; | 781 | return PACKET_V3_TAIL; |
781 | if ((packet[3] & 0x0f) == 0x06) | 782 | if ((packet[3] & 0x0f) == 0x06) |
782 | return PACKET_TRACKPOINT; | 783 | return PACKET_TRACKPOINT; |
783 | } | 784 | } |
784 | 785 | ||
785 | return PACKET_UNKNOWN; | 786 | return PACKET_UNKNOWN; |
786 | } | 787 | } |
787 | 788 | ||
788 | static int elantech_packet_check_v4(struct psmouse *psmouse) | 789 | static int elantech_packet_check_v4(struct psmouse *psmouse) |
789 | { | 790 | { |
790 | struct elantech_data *etd = psmouse->private; | 791 | struct elantech_data *etd = psmouse->private; |
791 | unsigned char *packet = psmouse->packet; | 792 | unsigned char *packet = psmouse->packet; |
792 | unsigned char packet_type = packet[3] & 0x03; | 793 | unsigned char packet_type = packet[3] & 0x03; |
793 | bool sanity_check; | 794 | bool sanity_check; |
794 | 795 | ||
796 | if ((packet[3] & 0x0f) == 0x06) | ||
797 | return PACKET_TRACKPOINT; | ||
798 | |||
795 | /* | 799 | /* |
796 | * Sanity check based on the constant bits of a packet. | 800 | * Sanity check based on the constant bits of a packet. |
797 | * The constant bits change depending on the value of | 801 | * The constant bits change depending on the value of |
798 | * the hardware flag 'crc_enabled' but are the same for | 802 | * the hardware flag 'crc_enabled' but are the same for |
799 | * every packet, regardless of the type. | 803 | * every packet, regardless of the type. |
800 | */ | 804 | */ |
801 | if (etd->crc_enabled) | 805 | if (etd->crc_enabled) |
802 | sanity_check = ((packet[3] & 0x08) == 0x00); | 806 | sanity_check = ((packet[3] & 0x08) == 0x00); |
803 | else | 807 | else |
804 | sanity_check = ((packet[0] & 0x0c) == 0x04 && | 808 | sanity_check = ((packet[0] & 0x0c) == 0x04 && |
805 | (packet[3] & 0x1c) == 0x10); | 809 | (packet[3] & 0x1c) == 0x10); |
806 | 810 | ||
807 | if (!sanity_check) | 811 | if (!sanity_check) |
808 | return PACKET_UNKNOWN; | 812 | return PACKET_UNKNOWN; |
809 | 813 | ||
810 | switch (packet_type) { | 814 | switch (packet_type) { |
811 | case 0: | 815 | case 0: |
812 | return PACKET_V4_STATUS; | 816 | return PACKET_V4_STATUS; |
813 | 817 | ||
814 | case 1: | 818 | case 1: |
815 | return PACKET_V4_HEAD; | 819 | return PACKET_V4_HEAD; |
816 | 820 | ||
817 | case 2: | 821 | case 2: |
818 | return PACKET_V4_MOTION; | 822 | return PACKET_V4_MOTION; |
819 | } | 823 | } |
820 | 824 | ||
821 | return PACKET_UNKNOWN; | 825 | return PACKET_UNKNOWN; |
822 | } | 826 | } |
823 | 827 | ||
824 | /* | 828 | /* |
825 | * Process byte stream from mouse and handle complete packets | 829 | * Process byte stream from mouse and handle complete packets |
826 | */ | 830 | */ |
827 | static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) | 831 | static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) |
828 | { | 832 | { |
829 | struct elantech_data *etd = psmouse->private; | 833 | struct elantech_data *etd = psmouse->private; |
830 | int packet_type; | 834 | int packet_type; |
831 | 835 | ||
832 | if (psmouse->pktcnt < psmouse->pktsize) | 836 | if (psmouse->pktcnt < psmouse->pktsize) |
833 | return PSMOUSE_GOOD_DATA; | 837 | return PSMOUSE_GOOD_DATA; |
834 | 838 | ||
835 | if (etd->debug > 1) | 839 | if (etd->debug > 1) |
836 | elantech_packet_dump(psmouse); | 840 | elantech_packet_dump(psmouse); |
837 | 841 | ||
838 | switch (etd->hw_version) { | 842 | switch (etd->hw_version) { |
839 | case 1: | 843 | case 1: |
840 | if (etd->paritycheck && !elantech_packet_check_v1(psmouse)) | 844 | if (etd->paritycheck && !elantech_packet_check_v1(psmouse)) |
841 | return PSMOUSE_BAD_DATA; | 845 | return PSMOUSE_BAD_DATA; |
842 | 846 | ||
843 | elantech_report_absolute_v1(psmouse); | 847 | elantech_report_absolute_v1(psmouse); |
844 | break; | 848 | break; |
845 | 849 | ||
846 | case 2: | 850 | case 2: |
847 | /* ignore debounce */ | 851 | /* ignore debounce */ |
848 | if (elantech_debounce_check_v2(psmouse)) | 852 | if (elantech_debounce_check_v2(psmouse)) |
849 | return PSMOUSE_FULL_PACKET; | 853 | return PSMOUSE_FULL_PACKET; |
850 | 854 | ||
851 | if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) | 855 | if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) |
852 | return PSMOUSE_BAD_DATA; | 856 | return PSMOUSE_BAD_DATA; |
853 | 857 | ||
854 | elantech_report_absolute_v2(psmouse); | 858 | elantech_report_absolute_v2(psmouse); |
855 | break; | 859 | break; |
856 | 860 | ||
857 | case 3: | 861 | case 3: |
858 | packet_type = elantech_packet_check_v3(psmouse); | 862 | packet_type = elantech_packet_check_v3(psmouse); |
859 | switch (packet_type) { | 863 | switch (packet_type) { |
860 | case PACKET_UNKNOWN: | 864 | case PACKET_UNKNOWN: |
861 | return PSMOUSE_BAD_DATA; | 865 | return PSMOUSE_BAD_DATA; |
862 | 866 | ||
863 | case PACKET_DEBOUNCE: | 867 | case PACKET_DEBOUNCE: |
864 | /* ignore debounce */ | 868 | /* ignore debounce */ |
865 | break; | 869 | break; |
866 | 870 | ||
867 | case PACKET_TRACKPOINT: | 871 | case PACKET_TRACKPOINT: |
868 | elantech_report_trackpoint(psmouse, packet_type); | 872 | elantech_report_trackpoint(psmouse, packet_type); |
869 | break; | 873 | break; |
870 | 874 | ||
871 | default: | 875 | default: |
872 | elantech_report_absolute_v3(psmouse, packet_type); | 876 | elantech_report_absolute_v3(psmouse, packet_type); |
873 | break; | 877 | break; |
874 | } | 878 | } |
875 | 879 | ||
876 | break; | 880 | break; |
877 | 881 | ||
878 | case 4: | 882 | case 4: |
879 | packet_type = elantech_packet_check_v4(psmouse); | 883 | packet_type = elantech_packet_check_v4(psmouse); |
880 | if (packet_type == PACKET_UNKNOWN) | 884 | switch (packet_type) { |
885 | case PACKET_UNKNOWN: | ||
881 | return PSMOUSE_BAD_DATA; | 886 | return PSMOUSE_BAD_DATA; |
882 | 887 | ||
883 | elantech_report_absolute_v4(psmouse, packet_type); | 888 | case PACKET_TRACKPOINT: |
889 | elantech_report_trackpoint(psmouse, packet_type); | ||
890 | break; | ||
891 | |||
892 | default: | ||
893 | elantech_report_absolute_v4(psmouse, packet_type); | ||
894 | break; | ||
895 | } | ||
896 | |||
884 | break; | 897 | break; |
885 | } | 898 | } |
886 | 899 | ||
887 | return PSMOUSE_FULL_PACKET; | 900 | return PSMOUSE_FULL_PACKET; |
888 | } | 901 | } |
889 | 902 | ||
890 | /* | 903 | /* |
891 | * Put the touchpad into absolute mode | 904 | * Put the touchpad into absolute mode |
892 | */ | 905 | */ |
893 | static int elantech_set_absolute_mode(struct psmouse *psmouse) | 906 | static int elantech_set_absolute_mode(struct psmouse *psmouse) |
894 | { | 907 | { |
895 | struct elantech_data *etd = psmouse->private; | 908 | struct elantech_data *etd = psmouse->private; |
896 | unsigned char val; | 909 | unsigned char val; |
897 | int tries = ETP_READ_BACK_TRIES; | 910 | int tries = ETP_READ_BACK_TRIES; |
898 | int rc = 0; | 911 | int rc = 0; |
899 | 912 | ||
900 | switch (etd->hw_version) { | 913 | switch (etd->hw_version) { |
901 | case 1: | 914 | case 1: |
902 | etd->reg_10 = 0x16; | 915 | etd->reg_10 = 0x16; |
903 | etd->reg_11 = 0x8f; | 916 | etd->reg_11 = 0x8f; |
904 | if (elantech_write_reg(psmouse, 0x10, etd->reg_10) || | 917 | if (elantech_write_reg(psmouse, 0x10, etd->reg_10) || |
905 | elantech_write_reg(psmouse, 0x11, etd->reg_11)) { | 918 | elantech_write_reg(psmouse, 0x11, etd->reg_11)) { |
906 | rc = -1; | 919 | rc = -1; |
907 | } | 920 | } |
908 | break; | 921 | break; |
909 | 922 | ||
910 | case 2: | 923 | case 2: |
911 | /* Windows driver values */ | 924 | /* Windows driver values */ |
912 | etd->reg_10 = 0x54; | 925 | etd->reg_10 = 0x54; |
913 | etd->reg_11 = 0x88; /* 0x8a */ | 926 | etd->reg_11 = 0x88; /* 0x8a */ |
914 | etd->reg_21 = 0x60; /* 0x00 */ | 927 | etd->reg_21 = 0x60; /* 0x00 */ |
915 | if (elantech_write_reg(psmouse, 0x10, etd->reg_10) || | 928 | if (elantech_write_reg(psmouse, 0x10, etd->reg_10) || |
916 | elantech_write_reg(psmouse, 0x11, etd->reg_11) || | 929 | elantech_write_reg(psmouse, 0x11, etd->reg_11) || |
917 | elantech_write_reg(psmouse, 0x21, etd->reg_21)) { | 930 | elantech_write_reg(psmouse, 0x21, etd->reg_21)) { |
918 | rc = -1; | 931 | rc = -1; |
919 | } | 932 | } |
920 | break; | 933 | break; |
921 | 934 | ||
922 | case 3: | 935 | case 3: |
923 | if (etd->set_hw_resolution) | 936 | if (etd->set_hw_resolution) |
924 | etd->reg_10 = 0x0b; | 937 | etd->reg_10 = 0x0b; |
925 | else | 938 | else |
926 | etd->reg_10 = 0x01; | 939 | etd->reg_10 = 0x01; |
927 | 940 | ||
928 | if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) | 941 | if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) |
929 | rc = -1; | 942 | rc = -1; |
930 | 943 | ||
931 | break; | 944 | break; |
932 | 945 | ||
933 | case 4: | 946 | case 4: |
934 | etd->reg_07 = 0x01; | 947 | etd->reg_07 = 0x01; |
935 | if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) | 948 | if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) |
936 | rc = -1; | 949 | rc = -1; |
937 | 950 | ||
938 | goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */ | 951 | goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */ |
939 | } | 952 | } |
940 | 953 | ||
941 | if (rc == 0) { | 954 | if (rc == 0) { |
942 | /* | 955 | /* |
943 | * Read back reg 0x10. For hardware version 1 we must make | 956 | * Read back reg 0x10. For hardware version 1 we must make |
944 | * sure the absolute mode bit is set. For hardware version 2 | 957 | * sure the absolute mode bit is set. For hardware version 2 |
945 | * the touchpad is probably initializing and not ready until | 958 | * the touchpad is probably initializing and not ready until |
946 | * we read back the value we just wrote. | 959 | * we read back the value we just wrote. |
947 | */ | 960 | */ |
948 | do { | 961 | do { |
949 | rc = elantech_read_reg(psmouse, 0x10, &val); | 962 | rc = elantech_read_reg(psmouse, 0x10, &val); |
950 | if (rc == 0) | 963 | if (rc == 0) |
951 | break; | 964 | break; |
952 | tries--; | 965 | tries--; |
953 | elantech_debug("retrying read (%d).\n", tries); | 966 | elantech_debug("retrying read (%d).\n", tries); |
954 | msleep(ETP_READ_BACK_DELAY); | 967 | msleep(ETP_READ_BACK_DELAY); |
955 | } while (tries > 0); | 968 | } while (tries > 0); |
956 | 969 | ||
957 | if (rc) { | 970 | if (rc) { |
958 | psmouse_err(psmouse, | 971 | psmouse_err(psmouse, |
959 | "failed to read back register 0x10.\n"); | 972 | "failed to read back register 0x10.\n"); |
960 | } else if (etd->hw_version == 1 && | 973 | } else if (etd->hw_version == 1 && |
961 | !(val & ETP_R10_ABSOLUTE_MODE)) { | 974 | !(val & ETP_R10_ABSOLUTE_MODE)) { |
962 | psmouse_err(psmouse, | 975 | psmouse_err(psmouse, |
963 | "touchpad refuses to switch to absolute mode.\n"); | 976 | "touchpad refuses to switch to absolute mode.\n"); |
964 | rc = -1; | 977 | rc = -1; |
965 | } | 978 | } |
966 | } | 979 | } |
967 | 980 | ||
968 | skip_readback_reg_10: | 981 | skip_readback_reg_10: |
969 | if (rc) | 982 | if (rc) |
970 | psmouse_err(psmouse, "failed to initialise registers.\n"); | 983 | psmouse_err(psmouse, "failed to initialise registers.\n"); |
971 | 984 | ||
972 | return rc; | 985 | return rc; |
973 | } | 986 | } |
974 | 987 | ||
975 | static int elantech_set_range(struct psmouse *psmouse, | 988 | static int elantech_set_range(struct psmouse *psmouse, |
976 | unsigned int *x_min, unsigned int *y_min, | 989 | unsigned int *x_min, unsigned int *y_min, |
977 | unsigned int *x_max, unsigned int *y_max, | 990 | unsigned int *x_max, unsigned int *y_max, |
978 | unsigned int *width) | 991 | unsigned int *width) |
979 | { | 992 | { |
980 | struct elantech_data *etd = psmouse->private; | 993 | struct elantech_data *etd = psmouse->private; |
981 | unsigned char param[3]; | 994 | unsigned char param[3]; |
982 | unsigned char traces; | 995 | unsigned char traces; |
983 | 996 | ||
984 | switch (etd->hw_version) { | 997 | switch (etd->hw_version) { |
985 | case 1: | 998 | case 1: |
986 | *x_min = ETP_XMIN_V1; | 999 | *x_min = ETP_XMIN_V1; |
987 | *y_min = ETP_YMIN_V1; | 1000 | *y_min = ETP_YMIN_V1; |
988 | *x_max = ETP_XMAX_V1; | 1001 | *x_max = ETP_XMAX_V1; |
989 | *y_max = ETP_YMAX_V1; | 1002 | *y_max = ETP_YMAX_V1; |
990 | break; | 1003 | break; |
991 | 1004 | ||
992 | case 2: | 1005 | case 2: |
993 | if (etd->fw_version == 0x020800 || | 1006 | if (etd->fw_version == 0x020800 || |
994 | etd->fw_version == 0x020b00 || | 1007 | etd->fw_version == 0x020b00 || |
995 | etd->fw_version == 0x020030) { | 1008 | etd->fw_version == 0x020030) { |
996 | *x_min = ETP_XMIN_V2; | 1009 | *x_min = ETP_XMIN_V2; |
997 | *y_min = ETP_YMIN_V2; | 1010 | *y_min = ETP_YMIN_V2; |
998 | *x_max = ETP_XMAX_V2; | 1011 | *x_max = ETP_XMAX_V2; |
999 | *y_max = ETP_YMAX_V2; | 1012 | *y_max = ETP_YMAX_V2; |
1000 | } else { | 1013 | } else { |
1001 | int i; | 1014 | int i; |
1002 | int fixed_dpi; | 1015 | int fixed_dpi; |
1003 | 1016 | ||
1004 | i = (etd->fw_version > 0x020800 && | 1017 | i = (etd->fw_version > 0x020800 && |
1005 | etd->fw_version < 0x020900) ? 1 : 2; | 1018 | etd->fw_version < 0x020900) ? 1 : 2; |
1006 | 1019 | ||
1007 | if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param)) | 1020 | if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param)) |
1008 | return -1; | 1021 | return -1; |
1009 | 1022 | ||
1010 | fixed_dpi = param[1] & 0x10; | 1023 | fixed_dpi = param[1] & 0x10; |
1011 | 1024 | ||
1012 | if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) { | 1025 | if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) { |
1013 | if (etd->send_cmd(psmouse, ETP_SAMPLE_QUERY, param)) | 1026 | if (etd->send_cmd(psmouse, ETP_SAMPLE_QUERY, param)) |
1014 | return -1; | 1027 | return -1; |
1015 | 1028 | ||
1016 | *x_max = (etd->capabilities[1] - i) * param[1] / 2; | 1029 | *x_max = (etd->capabilities[1] - i) * param[1] / 2; |
1017 | *y_max = (etd->capabilities[2] - i) * param[2] / 2; | 1030 | *y_max = (etd->capabilities[2] - i) * param[2] / 2; |
1018 | } else if (etd->fw_version == 0x040216) { | 1031 | } else if (etd->fw_version == 0x040216) { |
1019 | *x_max = 819; | 1032 | *x_max = 819; |
1020 | *y_max = 405; | 1033 | *y_max = 405; |
1021 | } else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) { | 1034 | } else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) { |
1022 | *x_max = 900; | 1035 | *x_max = 900; |
1023 | *y_max = 500; | 1036 | *y_max = 500; |
1024 | } else { | 1037 | } else { |
1025 | *x_max = (etd->capabilities[1] - i) * 64; | 1038 | *x_max = (etd->capabilities[1] - i) * 64; |
1026 | *y_max = (etd->capabilities[2] - i) * 64; | 1039 | *y_max = (etd->capabilities[2] - i) * 64; |
1027 | } | 1040 | } |
1028 | } | 1041 | } |
1029 | break; | 1042 | break; |
1030 | 1043 | ||
1031 | case 3: | 1044 | case 3: |
1032 | if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param)) | 1045 | if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param)) |
1033 | return -1; | 1046 | return -1; |
1034 | 1047 | ||
1035 | *x_max = (0x0f & param[0]) << 8 | param[1]; | 1048 | *x_max = (0x0f & param[0]) << 8 | param[1]; |
1036 | *y_max = (0xf0 & param[0]) << 4 | param[2]; | 1049 | *y_max = (0xf0 & param[0]) << 4 | param[2]; |
1037 | break; | 1050 | break; |
1038 | 1051 | ||
1039 | case 4: | 1052 | case 4: |
1040 | if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param)) | 1053 | if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param)) |
1041 | return -1; | 1054 | return -1; |
1042 | 1055 | ||
1043 | *x_max = (0x0f & param[0]) << 8 | param[1]; | 1056 | *x_max = (0x0f & param[0]) << 8 | param[1]; |
1044 | *y_max = (0xf0 & param[0]) << 4 | param[2]; | 1057 | *y_max = (0xf0 & param[0]) << 4 | param[2]; |
1045 | traces = etd->capabilities[1]; | 1058 | traces = etd->capabilities[1]; |
1046 | if ((traces < 2) || (traces > *x_max)) | 1059 | if ((traces < 2) || (traces > *x_max)) |
1047 | return -1; | 1060 | return -1; |
1048 | 1061 | ||
1049 | *width = *x_max / (traces - 1); | 1062 | *width = *x_max / (traces - 1); |
1050 | break; | 1063 | break; |
1051 | } | 1064 | } |
1052 | 1065 | ||
1053 | return 0; | 1066 | return 0; |
1054 | } | 1067 | } |
1055 | 1068 | ||
1056 | /* | 1069 | /* |
1057 | * (value from firmware) * 10 + 790 = dpi | 1070 | * (value from firmware) * 10 + 790 = dpi |
1058 | * we also have to convert dpi to dots/mm (*10/254 to avoid floating point) | 1071 | * we also have to convert dpi to dots/mm (*10/254 to avoid floating point) |
1059 | */ | 1072 | */ |
1060 | static unsigned int elantech_convert_res(unsigned int val) | 1073 | static unsigned int elantech_convert_res(unsigned int val) |
1061 | { | 1074 | { |
1062 | return (val * 10 + 790) * 10 / 254; | 1075 | return (val * 10 + 790) * 10 / 254; |
1063 | } | 1076 | } |
1064 | 1077 | ||
1065 | static int elantech_get_resolution_v4(struct psmouse *psmouse, | 1078 | static int elantech_get_resolution_v4(struct psmouse *psmouse, |
1066 | unsigned int *x_res, | 1079 | unsigned int *x_res, |
1067 | unsigned int *y_res) | 1080 | unsigned int *y_res) |
1068 | { | 1081 | { |
1069 | unsigned char param[3]; | 1082 | unsigned char param[3]; |
1070 | 1083 | ||
1071 | if (elantech_send_cmd(psmouse, ETP_RESOLUTION_QUERY, param)) | 1084 | if (elantech_send_cmd(psmouse, ETP_RESOLUTION_QUERY, param)) |
1072 | return -1; | 1085 | return -1; |
1073 | 1086 | ||
1074 | *x_res = elantech_convert_res(param[1] & 0x0f); | 1087 | *x_res = elantech_convert_res(param[1] & 0x0f); |
1075 | *y_res = elantech_convert_res((param[1] & 0xf0) >> 4); | 1088 | *y_res = elantech_convert_res((param[1] & 0xf0) >> 4); |
1076 | 1089 | ||
1077 | return 0; | 1090 | return 0; |
1078 | } | 1091 | } |
1079 | 1092 | ||
1080 | /* | 1093 | /* |
1081 | * Advertise INPUT_PROP_BUTTONPAD for clickpads. The testing of bit 12 in | 1094 | * Advertise INPUT_PROP_BUTTONPAD for clickpads. The testing of bit 12 in |
1082 | * fw_version for this is based on the following fw_version & caps table: | 1095 | * fw_version for this is based on the following fw_version & caps table: |
1083 | * | 1096 | * |
1084 | * Laptop-model: fw_version: caps: buttons: | 1097 | * Laptop-model: fw_version: caps: buttons: |
1085 | * Acer S3 0x461f00 10, 13, 0e clickpad | 1098 | * Acer S3 0x461f00 10, 13, 0e clickpad |
1086 | * Acer S7-392 0x581f01 50, 17, 0d clickpad | 1099 | * Acer S7-392 0x581f01 50, 17, 0d clickpad |
1087 | * Acer V5-131 0x461f02 01, 16, 0c clickpad | 1100 | * Acer V5-131 0x461f02 01, 16, 0c clickpad |
1088 | * Acer V5-551 0x461f00 ? clickpad | 1101 | * Acer V5-551 0x461f00 ? clickpad |
1089 | * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons | 1102 | * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons |
1090 | * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons | 1103 | * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons |
1091 | * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons | 1104 | * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons |
1092 | * Asus UX31 0x361f00 20, 15, 0e clickpad | 1105 | * Asus UX31 0x361f00 20, 15, 0e clickpad |
1093 | * Asus UX32VD 0x361f02 00, 15, 0e clickpad | 1106 | * Asus UX32VD 0x361f02 00, 15, 0e clickpad |
1094 | * Avatar AVIU-145A2 0x361f00 ? clickpad | 1107 | * Avatar AVIU-145A2 0x361f00 ? clickpad |
1095 | * Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**) | 1108 | * Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**) |
1096 | * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons | 1109 | * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons |
1097 | * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*) | 1110 | * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*) |
1098 | * Lenovo L530 0x350f02 b9, 15, 0c 2 hw buttons (*) | 1111 | * Lenovo L530 0x350f02 b9, 15, 0c 2 hw buttons (*) |
1099 | * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons | 1112 | * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons |
1100 | * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad | 1113 | * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad |
1101 | * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad | 1114 | * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad |
1102 | * Samsung NP900X3E-A02 0x575f03 ? clickpad | 1115 | * Samsung NP900X3E-A02 0x575f03 ? clickpad |
1103 | * Samsung NP-QX410 0x851b00 19, 14, 0c clickpad | 1116 | * Samsung NP-QX410 0x851b00 19, 14, 0c clickpad |
1104 | * Samsung RC512 0x450f00 08, 15, 0c 2 hw buttons | 1117 | * Samsung RC512 0x450f00 08, 15, 0c 2 hw buttons |
1105 | * Samsung RF710 0x450f00 ? 2 hw buttons | 1118 | * Samsung RF710 0x450f00 ? 2 hw buttons |
1106 | * System76 Pangolin 0x250f01 ? 2 hw buttons | 1119 | * System76 Pangolin 0x250f01 ? 2 hw buttons |
1107 | * (*) + 3 trackpoint buttons | 1120 | * (*) + 3 trackpoint buttons |
1108 | * (**) + 0 trackpoint buttons | 1121 | * (**) + 0 trackpoint buttons |
1109 | * Note: Lenovo L430 and Lenovo L430 have the same fw_version/caps | 1122 | * Note: Lenovo L430 and Lenovo L430 have the same fw_version/caps |
1110 | */ | 1123 | */ |
1111 | static void elantech_set_buttonpad_prop(struct psmouse *psmouse) | 1124 | static void elantech_set_buttonpad_prop(struct psmouse *psmouse) |
1112 | { | 1125 | { |
1113 | struct input_dev *dev = psmouse->dev; | 1126 | struct input_dev *dev = psmouse->dev; |
1114 | struct elantech_data *etd = psmouse->private; | 1127 | struct elantech_data *etd = psmouse->private; |
1115 | 1128 | ||
1116 | if (etd->fw_version & 0x001000) { | 1129 | if (etd->fw_version & 0x001000) { |
1117 | __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); | 1130 | __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); |
1118 | __clear_bit(BTN_RIGHT, dev->keybit); | 1131 | __clear_bit(BTN_RIGHT, dev->keybit); |
1119 | } | 1132 | } |
1120 | } | 1133 | } |
1121 | 1134 | ||
1122 | /* | 1135 | /* |
1136 | * Some hw_version 4 models do have a middle button | ||
1137 | */ | ||
1138 | static const struct dmi_system_id elantech_dmi_has_middle_button[] = { | ||
1139 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) | ||
1140 | { | ||
1141 | /* Fujitsu H730 has a middle button */ | ||
1142 | .matches = { | ||
1143 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | ||
1144 | DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"), | ||
1145 | }, | ||
1146 | }, | ||
1147 | #endif | ||
1148 | { } | ||
1149 | }; | ||
1150 | |||
1151 | /* | ||
1123 | * Set the appropriate event bits for the input subsystem | 1152 | * Set the appropriate event bits for the input subsystem |
1124 | */ | 1153 | */ |
1125 | static int elantech_set_input_params(struct psmouse *psmouse) | 1154 | static int elantech_set_input_params(struct psmouse *psmouse) |
1126 | { | 1155 | { |
1127 | struct input_dev *dev = psmouse->dev; | 1156 | struct input_dev *dev = psmouse->dev; |
1128 | struct elantech_data *etd = psmouse->private; | 1157 | struct elantech_data *etd = psmouse->private; |
1129 | unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; | 1158 | unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; |
1130 | unsigned int x_res = 0, y_res = 0; | 1159 | unsigned int x_res = 0, y_res = 0; |
1131 | 1160 | ||
1132 | if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) | 1161 | if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) |
1133 | return -1; | 1162 | return -1; |
1134 | 1163 | ||
1135 | __set_bit(INPUT_PROP_POINTER, dev->propbit); | 1164 | __set_bit(INPUT_PROP_POINTER, dev->propbit); |
1136 | __set_bit(EV_KEY, dev->evbit); | 1165 | __set_bit(EV_KEY, dev->evbit); |
1137 | __set_bit(EV_ABS, dev->evbit); | 1166 | __set_bit(EV_ABS, dev->evbit); |
1138 | __clear_bit(EV_REL, dev->evbit); | 1167 | __clear_bit(EV_REL, dev->evbit); |
1139 | 1168 | ||
1140 | __set_bit(BTN_LEFT, dev->keybit); | 1169 | __set_bit(BTN_LEFT, dev->keybit); |
1170 | if (dmi_check_system(elantech_dmi_has_middle_button)) | ||
1171 | __set_bit(BTN_MIDDLE, dev->keybit); | ||
1141 | __set_bit(BTN_RIGHT, dev->keybit); | 1172 | __set_bit(BTN_RIGHT, dev->keybit); |
1142 | 1173 | ||
1143 | __set_bit(BTN_TOUCH, dev->keybit); | 1174 | __set_bit(BTN_TOUCH, dev->keybit); |
1144 | __set_bit(BTN_TOOL_FINGER, dev->keybit); | 1175 | __set_bit(BTN_TOOL_FINGER, dev->keybit); |
1145 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); | 1176 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); |
1146 | __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); | 1177 | __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); |
1147 | 1178 | ||
1148 | switch (etd->hw_version) { | 1179 | switch (etd->hw_version) { |
1149 | case 1: | 1180 | case 1: |
1150 | /* Rocker button */ | 1181 | /* Rocker button */ |
1151 | if (etd->fw_version < 0x020000 && | 1182 | if (etd->fw_version < 0x020000 && |
1152 | (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { | 1183 | (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { |
1153 | __set_bit(BTN_FORWARD, dev->keybit); | 1184 | __set_bit(BTN_FORWARD, dev->keybit); |
1154 | __set_bit(BTN_BACK, dev->keybit); | 1185 | __set_bit(BTN_BACK, dev->keybit); |
1155 | } | 1186 | } |
1156 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); | 1187 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); |
1157 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); | 1188 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); |
1158 | break; | 1189 | break; |
1159 | 1190 | ||
1160 | case 2: | 1191 | case 2: |
1161 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | 1192 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
1162 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | 1193 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); |
1163 | /* fall through */ | 1194 | /* fall through */ |
1164 | case 3: | 1195 | case 3: |
1165 | if (etd->hw_version == 3) | 1196 | if (etd->hw_version == 3) |
1166 | elantech_set_buttonpad_prop(psmouse); | 1197 | elantech_set_buttonpad_prop(psmouse); |
1167 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); | 1198 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); |
1168 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); | 1199 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); |
1169 | if (etd->reports_pressure) { | 1200 | if (etd->reports_pressure) { |
1170 | input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, | 1201 | input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, |
1171 | ETP_PMAX_V2, 0, 0); | 1202 | ETP_PMAX_V2, 0, 0); |
1172 | input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, | 1203 | input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, |
1173 | ETP_WMAX_V2, 0, 0); | 1204 | ETP_WMAX_V2, 0, 0); |
1174 | } | 1205 | } |
1175 | input_mt_init_slots(dev, 2, 0); | 1206 | input_mt_init_slots(dev, 2, 0); |
1176 | input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); | 1207 | input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); |
1177 | input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); | 1208 | input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); |
1178 | break; | 1209 | break; |
1179 | 1210 | ||
1180 | case 4: | 1211 | case 4: |
1181 | if (elantech_get_resolution_v4(psmouse, &x_res, &y_res)) { | 1212 | if (elantech_get_resolution_v4(psmouse, &x_res, &y_res)) { |
1182 | /* | 1213 | /* |
1183 | * if query failed, print a warning and leave the values | 1214 | * if query failed, print a warning and leave the values |
1184 | * zero to resemble synaptics.c behavior. | 1215 | * zero to resemble synaptics.c behavior. |
1185 | */ | 1216 | */ |
1186 | psmouse_warn(psmouse, "couldn't query resolution data.\n"); | 1217 | psmouse_warn(psmouse, "couldn't query resolution data.\n"); |
1187 | } | 1218 | } |
1188 | elantech_set_buttonpad_prop(psmouse); | 1219 | elantech_set_buttonpad_prop(psmouse); |
1189 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | 1220 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
1190 | /* For X to recognize me as touchpad. */ | 1221 | /* For X to recognize me as touchpad. */ |
1191 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); | 1222 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); |
1192 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); | 1223 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); |
1193 | input_abs_set_res(dev, ABS_X, x_res); | 1224 | input_abs_set_res(dev, ABS_X, x_res); |
1194 | input_abs_set_res(dev, ABS_Y, y_res); | 1225 | input_abs_set_res(dev, ABS_Y, y_res); |
1195 | /* | 1226 | /* |
1196 | * range of pressure and width is the same as v2, | 1227 | * range of pressure and width is the same as v2, |
1197 | * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. | 1228 | * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. |
1198 | */ | 1229 | */ |
1199 | input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, | 1230 | input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, |
1200 | ETP_PMAX_V2, 0, 0); | 1231 | ETP_PMAX_V2, 0, 0); |
1201 | input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, | 1232 | input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, |
1202 | ETP_WMAX_V2, 0, 0); | 1233 | ETP_WMAX_V2, 0, 0); |
1203 | /* Multitouch capable pad, up to 5 fingers. */ | 1234 | /* Multitouch capable pad, up to 5 fingers. */ |
1204 | input_mt_init_slots(dev, ETP_MAX_FINGERS, 0); | 1235 | input_mt_init_slots(dev, ETP_MAX_FINGERS, 0); |
1205 | input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); | 1236 | input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); |
1206 | input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); | 1237 | input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); |
1207 | input_abs_set_res(dev, ABS_MT_POSITION_X, x_res); | 1238 | input_abs_set_res(dev, ABS_MT_POSITION_X, x_res); |
1208 | input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res); | 1239 | input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res); |
1209 | input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, | 1240 | input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, |
1210 | ETP_PMAX_V2, 0, 0); | 1241 | ETP_PMAX_V2, 0, 0); |
1211 | /* | 1242 | /* |
1212 | * The firmware reports how many trace lines the finger spans, | 1243 | * The firmware reports how many trace lines the finger spans, |
1213 | * convert to surface unit as Protocol-B requires. | 1244 | * convert to surface unit as Protocol-B requires. |
1214 | */ | 1245 | */ |
1215 | input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0, | 1246 | input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0, |
1216 | ETP_WMAX_V2 * width, 0, 0); | 1247 | ETP_WMAX_V2 * width, 0, 0); |
1217 | break; | 1248 | break; |
1218 | } | 1249 | } |
1219 | 1250 | ||
1220 | etd->y_max = y_max; | 1251 | etd->y_max = y_max; |
1221 | etd->width = width; | 1252 | etd->width = width; |
1222 | 1253 | ||
1223 | return 0; | 1254 | return 0; |
1224 | } | 1255 | } |
1225 | 1256 | ||
1226 | struct elantech_attr_data { | 1257 | struct elantech_attr_data { |
1227 | size_t field_offset; | 1258 | size_t field_offset; |
1228 | unsigned char reg; | 1259 | unsigned char reg; |
1229 | }; | 1260 | }; |
1230 | 1261 | ||
1231 | /* | 1262 | /* |
1232 | * Display a register value by reading a sysfs entry | 1263 | * Display a register value by reading a sysfs entry |
1233 | */ | 1264 | */ |
1234 | static ssize_t elantech_show_int_attr(struct psmouse *psmouse, void *data, | 1265 | static ssize_t elantech_show_int_attr(struct psmouse *psmouse, void *data, |
1235 | char *buf) | 1266 | char *buf) |
1236 | { | 1267 | { |
1237 | struct elantech_data *etd = psmouse->private; | 1268 | struct elantech_data *etd = psmouse->private; |
1238 | struct elantech_attr_data *attr = data; | 1269 | struct elantech_attr_data *attr = data; |
1239 | unsigned char *reg = (unsigned char *) etd + attr->field_offset; | 1270 | unsigned char *reg = (unsigned char *) etd + attr->field_offset; |
1240 | int rc = 0; | 1271 | int rc = 0; |
1241 | 1272 | ||
1242 | if (attr->reg) | 1273 | if (attr->reg) |
1243 | rc = elantech_read_reg(psmouse, attr->reg, reg); | 1274 | rc = elantech_read_reg(psmouse, attr->reg, reg); |
1244 | 1275 | ||
1245 | return sprintf(buf, "0x%02x\n", (attr->reg && rc) ? -1 : *reg); | 1276 | return sprintf(buf, "0x%02x\n", (attr->reg && rc) ? -1 : *reg); |
1246 | } | 1277 | } |
1247 | 1278 | ||
1248 | /* | 1279 | /* |
1249 | * Write a register value by writing a sysfs entry | 1280 | * Write a register value by writing a sysfs entry |
1250 | */ | 1281 | */ |
1251 | static ssize_t elantech_set_int_attr(struct psmouse *psmouse, | 1282 | static ssize_t elantech_set_int_attr(struct psmouse *psmouse, |
1252 | void *data, const char *buf, size_t count) | 1283 | void *data, const char *buf, size_t count) |
1253 | { | 1284 | { |
1254 | struct elantech_data *etd = psmouse->private; | 1285 | struct elantech_data *etd = psmouse->private; |
1255 | struct elantech_attr_data *attr = data; | 1286 | struct elantech_attr_data *attr = data; |
1256 | unsigned char *reg = (unsigned char *) etd + attr->field_offset; | 1287 | unsigned char *reg = (unsigned char *) etd + attr->field_offset; |
1257 | unsigned char value; | 1288 | unsigned char value; |
1258 | int err; | 1289 | int err; |
1259 | 1290 | ||
1260 | err = kstrtou8(buf, 16, &value); | 1291 | err = kstrtou8(buf, 16, &value); |
1261 | if (err) | 1292 | if (err) |
1262 | return err; | 1293 | return err; |
1263 | 1294 | ||
1264 | /* Do we need to preserve some bits for version 2 hardware too? */ | 1295 | /* Do we need to preserve some bits for version 2 hardware too? */ |
1265 | if (etd->hw_version == 1) { | 1296 | if (etd->hw_version == 1) { |
1266 | if (attr->reg == 0x10) | 1297 | if (attr->reg == 0x10) |
1267 | /* Force absolute mode always on */ | 1298 | /* Force absolute mode always on */ |
1268 | value |= ETP_R10_ABSOLUTE_MODE; | 1299 | value |= ETP_R10_ABSOLUTE_MODE; |
1269 | else if (attr->reg == 0x11) | 1300 | else if (attr->reg == 0x11) |
1270 | /* Force 4 byte mode always on */ | 1301 | /* Force 4 byte mode always on */ |
1271 | value |= ETP_R11_4_BYTE_MODE; | 1302 | value |= ETP_R11_4_BYTE_MODE; |
1272 | } | 1303 | } |
1273 | 1304 | ||
1274 | if (!attr->reg || elantech_write_reg(psmouse, attr->reg, value) == 0) | 1305 | if (!attr->reg || elantech_write_reg(psmouse, attr->reg, value) == 0) |
1275 | *reg = value; | 1306 | *reg = value; |
1276 | 1307 | ||
1277 | return count; | 1308 | return count; |
1278 | } | 1309 | } |
1279 | 1310 | ||
1280 | #define ELANTECH_INT_ATTR(_name, _register) \ | 1311 | #define ELANTECH_INT_ATTR(_name, _register) \ |
1281 | static struct elantech_attr_data elantech_attr_##_name = { \ | 1312 | static struct elantech_attr_data elantech_attr_##_name = { \ |
1282 | .field_offset = offsetof(struct elantech_data, _name), \ | 1313 | .field_offset = offsetof(struct elantech_data, _name), \ |
1283 | .reg = _register, \ | 1314 | .reg = _register, \ |
1284 | }; \ | 1315 | }; \ |
1285 | PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \ | 1316 | PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \ |
1286 | &elantech_attr_##_name, \ | 1317 | &elantech_attr_##_name, \ |
1287 | elantech_show_int_attr, \ | 1318 | elantech_show_int_attr, \ |
1288 | elantech_set_int_attr) | 1319 | elantech_set_int_attr) |
1289 | 1320 | ||
1290 | ELANTECH_INT_ATTR(reg_07, 0x07); | 1321 | ELANTECH_INT_ATTR(reg_07, 0x07); |
1291 | ELANTECH_INT_ATTR(reg_10, 0x10); | 1322 | ELANTECH_INT_ATTR(reg_10, 0x10); |
1292 | ELANTECH_INT_ATTR(reg_11, 0x11); | 1323 | ELANTECH_INT_ATTR(reg_11, 0x11); |
1293 | ELANTECH_INT_ATTR(reg_20, 0x20); | 1324 | ELANTECH_INT_ATTR(reg_20, 0x20); |
1294 | ELANTECH_INT_ATTR(reg_21, 0x21); | 1325 | ELANTECH_INT_ATTR(reg_21, 0x21); |
1295 | ELANTECH_INT_ATTR(reg_22, 0x22); | 1326 | ELANTECH_INT_ATTR(reg_22, 0x22); |
1296 | ELANTECH_INT_ATTR(reg_23, 0x23); | 1327 | ELANTECH_INT_ATTR(reg_23, 0x23); |
1297 | ELANTECH_INT_ATTR(reg_24, 0x24); | 1328 | ELANTECH_INT_ATTR(reg_24, 0x24); |
1298 | ELANTECH_INT_ATTR(reg_25, 0x25); | 1329 | ELANTECH_INT_ATTR(reg_25, 0x25); |
1299 | ELANTECH_INT_ATTR(reg_26, 0x26); | 1330 | ELANTECH_INT_ATTR(reg_26, 0x26); |
1300 | ELANTECH_INT_ATTR(debug, 0); | 1331 | ELANTECH_INT_ATTR(debug, 0); |
1301 | ELANTECH_INT_ATTR(paritycheck, 0); | 1332 | ELANTECH_INT_ATTR(paritycheck, 0); |
1333 | ELANTECH_INT_ATTR(crc_enabled, 0); | ||
1302 | 1334 | ||
1303 | static struct attribute *elantech_attrs[] = { | 1335 | static struct attribute *elantech_attrs[] = { |
1304 | &psmouse_attr_reg_07.dattr.attr, | 1336 | &psmouse_attr_reg_07.dattr.attr, |
1305 | &psmouse_attr_reg_10.dattr.attr, | 1337 | &psmouse_attr_reg_10.dattr.attr, |
1306 | &psmouse_attr_reg_11.dattr.attr, | 1338 | &psmouse_attr_reg_11.dattr.attr, |
1307 | &psmouse_attr_reg_20.dattr.attr, | 1339 | &psmouse_attr_reg_20.dattr.attr, |
1308 | &psmouse_attr_reg_21.dattr.attr, | 1340 | &psmouse_attr_reg_21.dattr.attr, |
1309 | &psmouse_attr_reg_22.dattr.attr, | 1341 | &psmouse_attr_reg_22.dattr.attr, |
1310 | &psmouse_attr_reg_23.dattr.attr, | 1342 | &psmouse_attr_reg_23.dattr.attr, |
1311 | &psmouse_attr_reg_24.dattr.attr, | 1343 | &psmouse_attr_reg_24.dattr.attr, |
1312 | &psmouse_attr_reg_25.dattr.attr, | 1344 | &psmouse_attr_reg_25.dattr.attr, |
1313 | &psmouse_attr_reg_26.dattr.attr, | 1345 | &psmouse_attr_reg_26.dattr.attr, |
1314 | &psmouse_attr_debug.dattr.attr, | 1346 | &psmouse_attr_debug.dattr.attr, |
1315 | &psmouse_attr_paritycheck.dattr.attr, | 1347 | &psmouse_attr_paritycheck.dattr.attr, |
1348 | &psmouse_attr_crc_enabled.dattr.attr, | ||
1316 | NULL | 1349 | NULL |
1317 | }; | 1350 | }; |
1318 | 1351 | ||
1319 | static struct attribute_group elantech_attr_group = { | 1352 | static struct attribute_group elantech_attr_group = { |
1320 | .attrs = elantech_attrs, | 1353 | .attrs = elantech_attrs, |
1321 | }; | 1354 | }; |
1322 | 1355 | ||
1323 | static bool elantech_is_signature_valid(const unsigned char *param) | 1356 | static bool elantech_is_signature_valid(const unsigned char *param) |
1324 | { | 1357 | { |
1325 | static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10 }; | 1358 | static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10 }; |
1326 | int i; | 1359 | int i; |
1327 | 1360 | ||
1328 | if (param[0] == 0) | 1361 | if (param[0] == 0) |
1329 | return false; | 1362 | return false; |
1330 | 1363 | ||
1331 | if (param[1] == 0) | 1364 | if (param[1] == 0) |
1332 | return true; | 1365 | return true; |
1333 | 1366 | ||
1334 | /* | 1367 | /* |
1335 | * Some models have a revision higher then 20. Meaning param[2] may | 1368 | * Some models have a revision higher then 20. Meaning param[2] may |
1336 | * be 10 or 20, skip the rates check for these. | 1369 | * be 10 or 20, skip the rates check for these. |
1337 | */ | 1370 | */ |
1338 | if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40) | 1371 | if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40) |
1339 | return true; | 1372 | return true; |
1340 | 1373 | ||
1341 | for (i = 0; i < ARRAY_SIZE(rates); i++) | 1374 | for (i = 0; i < ARRAY_SIZE(rates); i++) |
1342 | if (param[2] == rates[i]) | 1375 | if (param[2] == rates[i]) |
1343 | return false; | 1376 | return false; |
1344 | 1377 | ||
1345 | return true; | 1378 | return true; |
1346 | } | 1379 | } |
1347 | 1380 | ||
1348 | /* | 1381 | /* |
1349 | * Use magic knock to detect Elantech touchpad | 1382 | * Use magic knock to detect Elantech touchpad |
1350 | */ | 1383 | */ |
1351 | int elantech_detect(struct psmouse *psmouse, bool set_properties) | 1384 | int elantech_detect(struct psmouse *psmouse, bool set_properties) |
1352 | { | 1385 | { |
1353 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1386 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1354 | unsigned char param[3]; | 1387 | unsigned char param[3]; |
1355 | 1388 | ||
1356 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); | 1389 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); |
1357 | 1390 | ||
1358 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || | 1391 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || |
1359 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 1392 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
1360 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 1393 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
1361 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 1394 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
1362 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { | 1395 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { |
1363 | psmouse_dbg(psmouse, "sending Elantech magic knock failed.\n"); | 1396 | psmouse_dbg(psmouse, "sending Elantech magic knock failed.\n"); |
1364 | return -1; | 1397 | return -1; |
1365 | } | 1398 | } |
1366 | 1399 | ||
1367 | /* | 1400 | /* |
1368 | * Report this in case there are Elantech models that use a different | 1401 | * Report this in case there are Elantech models that use a different |
1369 | * set of magic numbers | 1402 | * set of magic numbers |
1370 | */ | 1403 | */ |
1371 | if (param[0] != 0x3c || param[1] != 0x03 || | 1404 | if (param[0] != 0x3c || param[1] != 0x03 || |
1372 | (param[2] != 0xc8 && param[2] != 0x00)) { | 1405 | (param[2] != 0xc8 && param[2] != 0x00)) { |
1373 | psmouse_dbg(psmouse, | 1406 | psmouse_dbg(psmouse, |
1374 | "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", | 1407 | "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", |
1375 | param[0], param[1], param[2]); | 1408 | param[0], param[1], param[2]); |
1376 | return -1; | 1409 | return -1; |
1377 | } | 1410 | } |
1378 | 1411 | ||
1379 | /* | 1412 | /* |
1380 | * Query touchpad's firmware version and see if it reports known | 1413 | * Query touchpad's firmware version and see if it reports known |
1381 | * value to avoid mis-detection. Logitech mice are known to respond | 1414 | * value to avoid mis-detection. Logitech mice are known to respond |
1382 | * to Elantech magic knock and there might be more. | 1415 | * to Elantech magic knock and there might be more. |
1383 | */ | 1416 | */ |
1384 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { | 1417 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { |
1385 | psmouse_dbg(psmouse, "failed to query firmware version.\n"); | 1418 | psmouse_dbg(psmouse, "failed to query firmware version.\n"); |
1386 | return -1; | 1419 | return -1; |
1387 | } | 1420 | } |
1388 | 1421 | ||
1389 | psmouse_dbg(psmouse, | 1422 | psmouse_dbg(psmouse, |
1390 | "Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", | 1423 | "Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", |
1391 | param[0], param[1], param[2]); | 1424 | param[0], param[1], param[2]); |
1392 | 1425 | ||
1393 | if (!elantech_is_signature_valid(param)) { | 1426 | if (!elantech_is_signature_valid(param)) { |
1394 | psmouse_dbg(psmouse, | 1427 | psmouse_dbg(psmouse, |
1395 | "Probably not a real Elantech touchpad. Aborting.\n"); | 1428 | "Probably not a real Elantech touchpad. Aborting.\n"); |
1396 | return -1; | 1429 | return -1; |
1397 | } | 1430 | } |
1398 | 1431 | ||
1399 | if (set_properties) { | 1432 | if (set_properties) { |
1400 | psmouse->vendor = "Elantech"; | 1433 | psmouse->vendor = "Elantech"; |
1401 | psmouse->name = "Touchpad"; | 1434 | psmouse->name = "Touchpad"; |
1402 | } | 1435 | } |
1403 | 1436 | ||
1404 | return 0; | 1437 | return 0; |
1405 | } | 1438 | } |
1406 | 1439 | ||
1407 | /* | 1440 | /* |
1408 | * Clean up sysfs entries when disconnecting | 1441 | * Clean up sysfs entries when disconnecting |
1409 | */ | 1442 | */ |
1410 | static void elantech_disconnect(struct psmouse *psmouse) | 1443 | static void elantech_disconnect(struct psmouse *psmouse) |
1411 | { | 1444 | { |
1412 | struct elantech_data *etd = psmouse->private; | 1445 | struct elantech_data *etd = psmouse->private; |
1413 | 1446 | ||
1414 | if (etd->tp_dev) | 1447 | if (etd->tp_dev) |
1415 | input_unregister_device(etd->tp_dev); | 1448 | input_unregister_device(etd->tp_dev); |
1416 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, | 1449 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, |
1417 | &elantech_attr_group); | 1450 | &elantech_attr_group); |
1418 | kfree(psmouse->private); | 1451 | kfree(psmouse->private); |
1419 | psmouse->private = NULL; | 1452 | psmouse->private = NULL; |
1420 | } | 1453 | } |
1421 | 1454 | ||
1422 | /* | 1455 | /* |
1423 | * Put the touchpad back into absolute mode when reconnecting | 1456 | * Put the touchpad back into absolute mode when reconnecting |
1424 | */ | 1457 | */ |
1425 | static int elantech_reconnect(struct psmouse *psmouse) | 1458 | static int elantech_reconnect(struct psmouse *psmouse) |
1426 | { | 1459 | { |
1427 | psmouse_reset(psmouse); | 1460 | psmouse_reset(psmouse); |
1428 | 1461 | ||
1429 | if (elantech_detect(psmouse, 0)) | 1462 | if (elantech_detect(psmouse, 0)) |
1430 | return -1; | 1463 | return -1; |
1431 | 1464 | ||
1432 | if (elantech_set_absolute_mode(psmouse)) { | 1465 | if (elantech_set_absolute_mode(psmouse)) { |
1433 | psmouse_err(psmouse, | 1466 | psmouse_err(psmouse, |
1434 | "failed to put touchpad back into absolute mode.\n"); | 1467 | "failed to put touchpad back into absolute mode.\n"); |
1435 | return -1; | 1468 | return -1; |
1436 | } | 1469 | } |
1437 | 1470 | ||
1438 | return 0; | 1471 | return 0; |
1439 | } | 1472 | } |
1440 | 1473 | ||
1441 | /* | 1474 | /* |
1475 | * Some hw_version 4 models do not work with crc_disabled | ||
1476 | */ | ||
1477 | static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = { | ||
1478 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) | ||
1479 | { | ||
1480 | /* Fujitsu H730 does not work with crc_enabled == 0 */ | ||
1481 | .matches = { | ||
1482 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | ||
1483 | DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"), | ||
1484 | }, | ||
1485 | }, | ||
1486 | #endif | ||
1487 | { } | ||
1488 | }; | ||
1489 | |||
1490 | /* | ||
1442 | * Some hw_version 3 models go into error state when we try to set | 1491 | * Some hw_version 3 models go into error state when we try to set |
1443 | * bit 3 and/or bit 1 of r10. | 1492 | * bit 3 and/or bit 1 of r10. |
1444 | */ | 1493 | */ |
1445 | static const struct dmi_system_id no_hw_res_dmi_table[] = { | 1494 | static const struct dmi_system_id no_hw_res_dmi_table[] = { |
1446 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) | 1495 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) |
1447 | { | 1496 | { |
1448 | /* Gigabyte U2442 */ | 1497 | /* Gigabyte U2442 */ |
1449 | .matches = { | 1498 | .matches = { |
1450 | DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), | 1499 | DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), |
1451 | DMI_MATCH(DMI_PRODUCT_NAME, "U2442"), | 1500 | DMI_MATCH(DMI_PRODUCT_NAME, "U2442"), |
1452 | }, | 1501 | }, |
1453 | }, | 1502 | }, |
1454 | #endif | 1503 | #endif |
1455 | { } | 1504 | { } |
1456 | }; | 1505 | }; |
1457 | 1506 | ||
1458 | /* | 1507 | /* |
1459 | * determine hardware version and set some properties according to it. | 1508 | * determine hardware version and set some properties according to it. |
1460 | */ | 1509 | */ |
1461 | static int elantech_set_properties(struct elantech_data *etd) | 1510 | static int elantech_set_properties(struct elantech_data *etd) |
1462 | { | 1511 | { |
1463 | /* This represents the version of IC body. */ | 1512 | /* This represents the version of IC body. */ |
1464 | int ver = (etd->fw_version & 0x0f0000) >> 16; | 1513 | int ver = (etd->fw_version & 0x0f0000) >> 16; |
1465 | 1514 | ||
1466 | /* Early version of Elan touchpads doesn't obey the rule. */ | 1515 | /* Early version of Elan touchpads doesn't obey the rule. */ |
1467 | if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) | 1516 | if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) |
1468 | etd->hw_version = 1; | 1517 | etd->hw_version = 1; |
1469 | else { | 1518 | else { |
1470 | switch (ver) { | 1519 | switch (ver) { |
1471 | case 2: | 1520 | case 2: |
1472 | case 4: | 1521 | case 4: |
1473 | etd->hw_version = 2; | 1522 | etd->hw_version = 2; |
1474 | break; | 1523 | break; |
1475 | case 5: | 1524 | case 5: |
1476 | etd->hw_version = 3; | 1525 | etd->hw_version = 3; |
1477 | break; | 1526 | break; |
1478 | case 6: | 1527 | case 6: |
1479 | case 7: | 1528 | case 7: |
1480 | case 8: | 1529 | case 8: |
1481 | case 9: | 1530 | case 9: |
1482 | etd->hw_version = 4; | 1531 | etd->hw_version = 4; |
1483 | break; | 1532 | break; |
1484 | default: | 1533 | default: |
1485 | return -1; | 1534 | return -1; |
1486 | } | 1535 | } |
1487 | } | 1536 | } |
1488 | 1537 | ||
1489 | /* decide which send_cmd we're gonna use early */ | 1538 | /* decide which send_cmd we're gonna use early */ |
1490 | etd->send_cmd = etd->hw_version >= 3 ? elantech_send_cmd : | 1539 | etd->send_cmd = etd->hw_version >= 3 ? elantech_send_cmd : |
1491 | synaptics_send_cmd; | 1540 | synaptics_send_cmd; |
1492 | 1541 | ||
1493 | /* Turn on packet checking by default */ | 1542 | /* Turn on packet checking by default */ |
1494 | etd->paritycheck = 1; | 1543 | etd->paritycheck = 1; |
1495 | 1544 | ||
1496 | /* | 1545 | /* |
1497 | * This firmware suffers from misreporting coordinates when | 1546 | * This firmware suffers from misreporting coordinates when |
1498 | * a touch action starts causing the mouse cursor or scrolled page | 1547 | * a touch action starts causing the mouse cursor or scrolled page |
1499 | * to jump. Enable a workaround. | 1548 | * to jump. Enable a workaround. |
1500 | */ | 1549 | */ |
1501 | etd->jumpy_cursor = | 1550 | etd->jumpy_cursor = |
1502 | (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); | 1551 | (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); |
1503 | 1552 | ||
1504 | if (etd->hw_version > 1) { | 1553 | if (etd->hw_version > 1) { |
1505 | /* For now show extra debug information */ | 1554 | /* For now show extra debug information */ |
1506 | etd->debug = 1; | 1555 | etd->debug = 1; |
1507 | 1556 | ||
1508 | if (etd->fw_version >= 0x020800) | 1557 | if (etd->fw_version >= 0x020800) |
1509 | etd->reports_pressure = true; | 1558 | etd->reports_pressure = true; |
1510 | } | 1559 | } |
1511 | 1560 | ||
1512 | /* | 1561 | /* |
1513 | * The signatures of v3 and v4 packets change depending on the | 1562 | * The signatures of v3 and v4 packets change depending on the |
1514 | * value of this hardware flag. | 1563 | * value of this hardware flag. |
1515 | */ | 1564 | */ |
1516 | etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000); | 1565 | etd->crc_enabled = (etd->fw_version & 0x4000) == 0x4000 || |
1566 | dmi_check_system(elantech_dmi_force_crc_enabled); | ||
1517 | 1567 | ||
1518 | /* Enable real hardware resolution on hw_version 3 ? */ | 1568 | /* Enable real hardware resolution on hw_version 3 ? */ |
1519 | etd->set_hw_resolution = !dmi_check_system(no_hw_res_dmi_table); | 1569 | etd->set_hw_resolution = !dmi_check_system(no_hw_res_dmi_table); |
1520 | 1570 | ||
1521 | return 0; | 1571 | return 0; |
1522 | } | 1572 | } |
1523 | 1573 | ||
1524 | /* | 1574 | /* |
1525 | * Initialize the touchpad and create sysfs entries | 1575 | * Initialize the touchpad and create sysfs entries |
1526 | */ | 1576 | */ |
1527 | int elantech_init(struct psmouse *psmouse) | 1577 | int elantech_init(struct psmouse *psmouse) |
1528 | { | 1578 | { |
1529 | struct elantech_data *etd; | 1579 | struct elantech_data *etd; |
1530 | int i; | 1580 | int i; |
1531 | int error = -EINVAL; | 1581 | int error = -EINVAL; |
1532 | unsigned char param[3]; | 1582 | unsigned char param[3]; |
1533 | struct input_dev *tp_dev; | 1583 | struct input_dev *tp_dev; |
1534 | 1584 | ||
1535 | psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); | 1585 | psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); |
1536 | if (!etd) | 1586 | if (!etd) |
1537 | return -ENOMEM; | 1587 | return -ENOMEM; |
1538 | 1588 | ||
1539 | psmouse_reset(psmouse); | 1589 | psmouse_reset(psmouse); |
1540 | 1590 | ||
1541 | etd->parity[0] = 1; | 1591 | etd->parity[0] = 1; |
1542 | for (i = 1; i < 256; i++) | 1592 | for (i = 1; i < 256; i++) |
1543 | etd->parity[i] = etd->parity[i & (i - 1)] ^ 1; | 1593 | etd->parity[i] = etd->parity[i & (i - 1)] ^ 1; |
1544 | 1594 | ||
1545 | /* | 1595 | /* |
1546 | * Do the version query again so we can store the result | 1596 | * Do the version query again so we can store the result |
1547 | */ | 1597 | */ |
1548 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { | 1598 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { |
1549 | psmouse_err(psmouse, "failed to query firmware version.\n"); | 1599 | psmouse_err(psmouse, "failed to query firmware version.\n"); |
1550 | goto init_fail; | 1600 | goto init_fail; |
1551 | } | 1601 | } |
1552 | etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; | 1602 | etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; |
1553 | 1603 | ||
1554 | if (elantech_set_properties(etd)) { | 1604 | if (elantech_set_properties(etd)) { |
1555 | psmouse_err(psmouse, "unknown hardware version, aborting...\n"); | 1605 | psmouse_err(psmouse, "unknown hardware version, aborting...\n"); |
1556 | goto init_fail; | 1606 | goto init_fail; |
1557 | } | 1607 | } |
1558 | psmouse_info(psmouse, | 1608 | psmouse_info(psmouse, |
1559 | "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n", | 1609 | "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n", |
1560 | etd->hw_version, param[0], param[1], param[2]); | 1610 | etd->hw_version, param[0], param[1], param[2]); |
1561 | 1611 | ||
1562 | if (etd->send_cmd(psmouse, ETP_CAPABILITIES_QUERY, | 1612 | if (etd->send_cmd(psmouse, ETP_CAPABILITIES_QUERY, |
1563 | etd->capabilities)) { | 1613 | etd->capabilities)) { |
1564 | psmouse_err(psmouse, "failed to query capabilities.\n"); | 1614 | psmouse_err(psmouse, "failed to query capabilities.\n"); |
1565 | goto init_fail; | 1615 | goto init_fail; |
1566 | } | 1616 | } |
1567 | psmouse_info(psmouse, | 1617 | psmouse_info(psmouse, |
1568 | "Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", | 1618 | "Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", |
1569 | etd->capabilities[0], etd->capabilities[1], | 1619 | etd->capabilities[0], etd->capabilities[1], |
1570 | etd->capabilities[2]); | 1620 | etd->capabilities[2]); |
1571 | 1621 | ||
1572 | if (elantech_set_absolute_mode(psmouse)) { | 1622 | if (elantech_set_absolute_mode(psmouse)) { |
1573 | psmouse_err(psmouse, | 1623 | psmouse_err(psmouse, |
1574 | "failed to put touchpad into absolute mode.\n"); | 1624 | "failed to put touchpad into absolute mode.\n"); |
1575 | goto init_fail; | 1625 | goto init_fail; |
1576 | } | 1626 | } |
1577 | 1627 | ||
1578 | if (elantech_set_input_params(psmouse)) { | 1628 | if (elantech_set_input_params(psmouse)) { |
1579 | psmouse_err(psmouse, "failed to query touchpad range.\n"); | 1629 | psmouse_err(psmouse, "failed to query touchpad range.\n"); |
1580 | goto init_fail; | 1630 | goto init_fail; |
1581 | } | 1631 | } |
1582 | 1632 | ||
1583 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, | 1633 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, |
1584 | &elantech_attr_group); | 1634 | &elantech_attr_group); |
1585 | if (error) { | 1635 | if (error) { |
1586 | psmouse_err(psmouse, | 1636 | psmouse_err(psmouse, |
1587 | "failed to create sysfs attributes, error: %d.\n", | 1637 | "failed to create sysfs attributes, error: %d.\n", |
1588 | error); | 1638 | error); |
1589 | goto init_fail; | 1639 | goto init_fail; |
1590 | } | 1640 | } |
1591 | 1641 | ||
1592 | /* The MSB indicates the presence of the trackpoint */ | 1642 | /* The MSB indicates the presence of the trackpoint */ |
1593 | if ((etd->capabilities[0] & 0x80) == 0x80) { | 1643 | if ((etd->capabilities[0] & 0x80) == 0x80) { |
1594 | tp_dev = input_allocate_device(); | 1644 | tp_dev = input_allocate_device(); |
1595 | 1645 | ||
1596 | if (!tp_dev) { | 1646 | if (!tp_dev) { |
1597 | error = -ENOMEM; | 1647 | error = -ENOMEM; |
1598 | goto init_fail_tp_alloc; | 1648 | goto init_fail_tp_alloc; |
1599 | } | 1649 | } |
1600 | 1650 | ||
1601 | etd->tp_dev = tp_dev; | 1651 | etd->tp_dev = tp_dev; |
1602 | snprintf(etd->tp_phys, sizeof(etd->tp_phys), "%s/input1", | 1652 | snprintf(etd->tp_phys, sizeof(etd->tp_phys), "%s/input1", |
1603 | psmouse->ps2dev.serio->phys); | 1653 | psmouse->ps2dev.serio->phys); |
1604 | tp_dev->phys = etd->tp_phys; | 1654 | tp_dev->phys = etd->tp_phys; |
1605 | tp_dev->name = "Elantech PS/2 TrackPoint"; | 1655 | tp_dev->name = "Elantech PS/2 TrackPoint"; |
1606 | tp_dev->id.bustype = BUS_I8042; | 1656 | tp_dev->id.bustype = BUS_I8042; |
1607 | tp_dev->id.vendor = 0x0002; | 1657 | tp_dev->id.vendor = 0x0002; |
1608 | tp_dev->id.product = PSMOUSE_ELANTECH; | 1658 | tp_dev->id.product = PSMOUSE_ELANTECH; |
1609 | tp_dev->id.version = 0x0000; | 1659 | tp_dev->id.version = 0x0000; |
1610 | tp_dev->dev.parent = &psmouse->ps2dev.serio->dev; | 1660 | tp_dev->dev.parent = &psmouse->ps2dev.serio->dev; |
1611 | tp_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | 1661 | tp_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); |
1612 | tp_dev->relbit[BIT_WORD(REL_X)] = | 1662 | tp_dev->relbit[BIT_WORD(REL_X)] = |
1613 | BIT_MASK(REL_X) | BIT_MASK(REL_Y); | 1663 | BIT_MASK(REL_X) | BIT_MASK(REL_Y); |
1614 | tp_dev->keybit[BIT_WORD(BTN_LEFT)] = | 1664 | tp_dev->keybit[BIT_WORD(BTN_LEFT)] = |
1615 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | | 1665 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | |
1616 | BIT_MASK(BTN_RIGHT); | 1666 | BIT_MASK(BTN_RIGHT); |
1617 | 1667 | ||
1618 | __set_bit(INPUT_PROP_POINTER, tp_dev->propbit); | 1668 | __set_bit(INPUT_PROP_POINTER, tp_dev->propbit); |
1619 | __set_bit(INPUT_PROP_POINTING_STICK, tp_dev->propbit); | 1669 | __set_bit(INPUT_PROP_POINTING_STICK, tp_dev->propbit); |
1620 | 1670 | ||
1621 | error = input_register_device(etd->tp_dev); | 1671 | error = input_register_device(etd->tp_dev); |
1622 | if (error < 0) | 1672 | if (error < 0) |
1623 | goto init_fail_tp_reg; | 1673 | goto init_fail_tp_reg; |
1624 | } | 1674 | } |
1625 | 1675 | ||
1626 | psmouse->protocol_handler = elantech_process_byte; | 1676 | psmouse->protocol_handler = elantech_process_byte; |
1627 | psmouse->disconnect = elantech_disconnect; | 1677 | psmouse->disconnect = elantech_disconnect; |
1628 | psmouse->reconnect = elantech_reconnect; | 1678 | psmouse->reconnect = elantech_reconnect; |
1629 | psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; | 1679 | psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; |
1630 | 1680 | ||
1631 | return 0; | 1681 | return 0; |
1632 | init_fail_tp_reg: | 1682 | init_fail_tp_reg: |
1633 | input_free_device(tp_dev); | 1683 | input_free_device(tp_dev); |
1634 | init_fail_tp_alloc: | 1684 | init_fail_tp_alloc: |
1635 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, | 1685 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, |
1636 | &elantech_attr_group); | 1686 | &elantech_attr_group); |
1637 | init_fail: | 1687 | init_fail: |
1638 | psmouse_reset(psmouse); | 1688 | psmouse_reset(psmouse); |
1639 | kfree(etd); | 1689 | kfree(etd); |
1640 | return error; | 1690 | return error; |
1641 | } | 1691 | } |
1642 | 1692 |
drivers/input/mouse/synaptics.c
1 | /* | 1 | /* |
2 | * Synaptics TouchPad PS/2 mouse driver | 2 | * Synaptics TouchPad PS/2 mouse driver |
3 | * | 3 | * |
4 | * 2003 Dmitry Torokhov <dtor@mail.ru> | 4 | * 2003 Dmitry Torokhov <dtor@mail.ru> |
5 | * Added support for pass-through port. Special thanks to Peter Berg Larsen | 5 | * Added support for pass-through port. Special thanks to Peter Berg Larsen |
6 | * for explaining various Synaptics quirks. | 6 | * for explaining various Synaptics quirks. |
7 | * | 7 | * |
8 | * 2003 Peter Osterlund <petero2@telia.com> | 8 | * 2003 Peter Osterlund <petero2@telia.com> |
9 | * Ported to 2.5 input device infrastructure. | 9 | * Ported to 2.5 input device infrastructure. |
10 | * | 10 | * |
11 | * Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch> | 11 | * Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch> |
12 | * start merging tpconfig and gpm code to a xfree-input module | 12 | * start merging tpconfig and gpm code to a xfree-input module |
13 | * adding some changes and extensions (ex. 3rd and 4th button) | 13 | * adding some changes and extensions (ex. 3rd and 4th button) |
14 | * | 14 | * |
15 | * Copyright (c) 1997 C. Scott Ananian <cananian@alumni.priceton.edu> | 15 | * Copyright (c) 1997 C. Scott Ananian <cananian@alumni.priceton.edu> |
16 | * Copyright (c) 1998-2000 Bruce Kalk <kall@compass.com> | 16 | * Copyright (c) 1998-2000 Bruce Kalk <kall@compass.com> |
17 | * code for the special synaptics commands (from the tpconfig-source) | 17 | * code for the special synaptics commands (from the tpconfig-source) |
18 | * | 18 | * |
19 | * This program is free software; you can redistribute it and/or modify it | 19 | * This program is free software; you can redistribute it and/or modify it |
20 | * under the terms of the GNU General Public License version 2 as published by | 20 | * under the terms of the GNU General Public License version 2 as published by |
21 | * the Free Software Foundation. | 21 | * the Free Software Foundation. |
22 | * | 22 | * |
23 | * Trademarks are the property of their respective owners. | 23 | * Trademarks are the property of their respective owners. |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/dmi.h> | 28 | #include <linux/dmi.h> |
29 | #include <linux/input/mt.h> | 29 | #include <linux/input/mt.h> |
30 | #include <linux/serio.h> | 30 | #include <linux/serio.h> |
31 | #include <linux/libps2.h> | 31 | #include <linux/libps2.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include "psmouse.h" | 33 | #include "psmouse.h" |
34 | #include "synaptics.h" | 34 | #include "synaptics.h" |
35 | 35 | ||
36 | /* | 36 | /* |
37 | * The x/y limits are taken from the Synaptics TouchPad interfacing Guide, | 37 | * The x/y limits are taken from the Synaptics TouchPad interfacing Guide, |
38 | * section 2.3.2, which says that they should be valid regardless of the | 38 | * section 2.3.2, which says that they should be valid regardless of the |
39 | * actual size of the sensor. | 39 | * actual size of the sensor. |
40 | * Note that newer firmware allows querying device for maximum useable | 40 | * Note that newer firmware allows querying device for maximum useable |
41 | * coordinates. | 41 | * coordinates. |
42 | */ | 42 | */ |
43 | #define XMIN 0 | 43 | #define XMIN 0 |
44 | #define XMAX 6143 | 44 | #define XMAX 6143 |
45 | #define YMIN 0 | 45 | #define YMIN 0 |
46 | #define YMAX 6143 | 46 | #define YMAX 6143 |
47 | #define XMIN_NOMINAL 1472 | 47 | #define XMIN_NOMINAL 1472 |
48 | #define XMAX_NOMINAL 5472 | 48 | #define XMAX_NOMINAL 5472 |
49 | #define YMIN_NOMINAL 1408 | 49 | #define YMIN_NOMINAL 1408 |
50 | #define YMAX_NOMINAL 4448 | 50 | #define YMAX_NOMINAL 4448 |
51 | 51 | ||
52 | /* Size in bits of absolute position values reported by the hardware */ | 52 | /* Size in bits of absolute position values reported by the hardware */ |
53 | #define ABS_POS_BITS 13 | 53 | #define ABS_POS_BITS 13 |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * These values should represent the absolute maximum value that will | 56 | * These values should represent the absolute maximum value that will |
57 | * be reported for a positive position value. Some Synaptics firmware | 57 | * be reported for a positive position value. Some Synaptics firmware |
58 | * uses this value to indicate a finger near the edge of the touchpad | 58 | * uses this value to indicate a finger near the edge of the touchpad |
59 | * whose precise position cannot be determined. | 59 | * whose precise position cannot be determined. |
60 | * | 60 | * |
61 | * At least one touchpad is known to report positions in excess of this | 61 | * At least one touchpad is known to report positions in excess of this |
62 | * value which are actually negative values truncated to the 13-bit | 62 | * value which are actually negative values truncated to the 13-bit |
63 | * reporting range. These values have never been observed to be lower | 63 | * reporting range. These values have never been observed to be lower |
64 | * than 8184 (i.e. -8), so we treat all values greater than 8176 as | 64 | * than 8184 (i.e. -8), so we treat all values greater than 8176 as |
65 | * negative and any other value as positive. | 65 | * negative and any other value as positive. |
66 | */ | 66 | */ |
67 | #define X_MAX_POSITIVE 8176 | 67 | #define X_MAX_POSITIVE 8176 |
68 | #define Y_MAX_POSITIVE 8176 | 68 | #define Y_MAX_POSITIVE 8176 |
69 | 69 | ||
70 | /***************************************************************************** | 70 | /***************************************************************************** |
71 | * Stuff we need even when we do not want native Synaptics support | 71 | * Stuff we need even when we do not want native Synaptics support |
72 | ****************************************************************************/ | 72 | ****************************************************************************/ |
73 | 73 | ||
74 | /* | 74 | /* |
75 | * Set the synaptics touchpad mode byte by special commands | 75 | * Set the synaptics touchpad mode byte by special commands |
76 | */ | 76 | */ |
77 | static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode) | 77 | static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode) |
78 | { | 78 | { |
79 | unsigned char param[1]; | 79 | unsigned char param[1]; |
80 | 80 | ||
81 | if (psmouse_sliced_command(psmouse, mode)) | 81 | if (psmouse_sliced_command(psmouse, mode)) |
82 | return -1; | 82 | return -1; |
83 | param[0] = SYN_PS_SET_MODE2; | 83 | param[0] = SYN_PS_SET_MODE2; |
84 | if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE)) | 84 | if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE)) |
85 | return -1; | 85 | return -1; |
86 | return 0; | 86 | return 0; |
87 | } | 87 | } |
88 | 88 | ||
89 | int synaptics_detect(struct psmouse *psmouse, bool set_properties) | 89 | int synaptics_detect(struct psmouse *psmouse, bool set_properties) |
90 | { | 90 | { |
91 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 91 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
92 | unsigned char param[4]; | 92 | unsigned char param[4]; |
93 | 93 | ||
94 | param[0] = 0; | 94 | param[0] = 0; |
95 | 95 | ||
96 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); | 96 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); |
97 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); | 97 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); |
98 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); | 98 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); |
99 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); | 99 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); |
100 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO); | 100 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO); |
101 | 101 | ||
102 | if (param[1] != 0x47) | 102 | if (param[1] != 0x47) |
103 | return -ENODEV; | 103 | return -ENODEV; |
104 | 104 | ||
105 | if (set_properties) { | 105 | if (set_properties) { |
106 | psmouse->vendor = "Synaptics"; | 106 | psmouse->vendor = "Synaptics"; |
107 | psmouse->name = "TouchPad"; | 107 | psmouse->name = "TouchPad"; |
108 | } | 108 | } |
109 | 109 | ||
110 | return 0; | 110 | return 0; |
111 | } | 111 | } |
112 | 112 | ||
113 | void synaptics_reset(struct psmouse *psmouse) | 113 | void synaptics_reset(struct psmouse *psmouse) |
114 | { | 114 | { |
115 | /* reset touchpad back to relative mode, gestures enabled */ | 115 | /* reset touchpad back to relative mode, gestures enabled */ |
116 | synaptics_mode_cmd(psmouse, 0); | 116 | synaptics_mode_cmd(psmouse, 0); |
117 | } | 117 | } |
118 | 118 | ||
119 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS | 119 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS |
120 | 120 | ||
121 | static bool cr48_profile_sensor; | 121 | static bool cr48_profile_sensor; |
122 | 122 | ||
123 | struct min_max_quirk { | 123 | struct min_max_quirk { |
124 | const char * const *pnp_ids; | 124 | const char * const *pnp_ids; |
125 | int x_min, x_max, y_min, y_max; | 125 | int x_min, x_max, y_min, y_max; |
126 | }; | 126 | }; |
127 | 127 | ||
128 | static const struct min_max_quirk min_max_pnpid_table[] = { | 128 | static const struct min_max_quirk min_max_pnpid_table[] = { |
129 | { | 129 | { |
130 | (const char * const []){"LEN0033", NULL}, | 130 | (const char * const []){"LEN0033", NULL}, |
131 | 1024, 5052, 2258, 4832 | 131 | 1024, 5052, 2258, 4832 |
132 | }, | 132 | }, |
133 | { | 133 | { |
134 | (const char * const []){"LEN0035", "LEN0042", NULL}, | 134 | (const char * const []){"LEN0035", "LEN0042", NULL}, |
135 | 1232, 5710, 1156, 4696 | 135 | 1232, 5710, 1156, 4696 |
136 | }, | 136 | }, |
137 | { | 137 | { |
138 | (const char * const []){"LEN0034", "LEN0036", "LEN2002", | 138 | (const char * const []){"LEN0034", "LEN0036", "LEN0039", |
139 | "LEN2004", NULL}, | 139 | "LEN2002", "LEN2004", NULL}, |
140 | 1024, 5112, 2024, 4832 | 140 | 1024, 5112, 2024, 4832 |
141 | }, | 141 | }, |
142 | { | 142 | { |
143 | (const char * const []){"LEN2001", NULL}, | 143 | (const char * const []){"LEN2001", NULL}, |
144 | 1024, 5022, 2508, 4832 | 144 | 1024, 5022, 2508, 4832 |
145 | }, | 145 | }, |
146 | { } | 146 | { } |
147 | }; | 147 | }; |
148 | 148 | ||
149 | /* This list has been kindly provided by Synaptics. */ | 149 | /* This list has been kindly provided by Synaptics. */ |
150 | static const char * const topbuttonpad_pnp_ids[] = { | 150 | static const char * const topbuttonpad_pnp_ids[] = { |
151 | "LEN0017", | 151 | "LEN0017", |
152 | "LEN0018", | 152 | "LEN0018", |
153 | "LEN0019", | 153 | "LEN0019", |
154 | "LEN0023", | 154 | "LEN0023", |
155 | "LEN002A", | 155 | "LEN002A", |
156 | "LEN002B", | 156 | "LEN002B", |
157 | "LEN002C", | 157 | "LEN002C", |
158 | "LEN002D", | 158 | "LEN002D", |
159 | "LEN002E", | 159 | "LEN002E", |
160 | "LEN0033", /* Helix */ | 160 | "LEN0033", /* Helix */ |
161 | "LEN0034", /* T431s, L440, L540, T540, W540, X1 Carbon 2nd */ | 161 | "LEN0034", /* T431s, L440, L540, T540, W540, X1 Carbon 2nd */ |
162 | "LEN0035", /* X240 */ | 162 | "LEN0035", /* X240 */ |
163 | "LEN0036", /* T440 */ | 163 | "LEN0036", /* T440 */ |
164 | "LEN0037", | 164 | "LEN0037", |
165 | "LEN0038", | 165 | "LEN0038", |
166 | "LEN0039", /* T440s */ | ||
166 | "LEN0041", | 167 | "LEN0041", |
167 | "LEN0042", /* Yoga */ | 168 | "LEN0042", /* Yoga */ |
168 | "LEN0045", | 169 | "LEN0045", |
169 | "LEN0046", | 170 | "LEN0046", |
170 | "LEN0047", | 171 | "LEN0047", |
171 | "LEN0048", | 172 | "LEN0048", |
172 | "LEN0049", | 173 | "LEN0049", |
173 | "LEN2000", | 174 | "LEN2000", |
174 | "LEN2001", /* Edge E431 */ | 175 | "LEN2001", /* Edge E431 */ |
175 | "LEN2002", /* Edge E531 */ | 176 | "LEN2002", /* Edge E531 */ |
176 | "LEN2003", | 177 | "LEN2003", |
177 | "LEN2004", /* L440 */ | 178 | "LEN2004", /* L440 */ |
178 | "LEN2005", | 179 | "LEN2005", |
179 | "LEN2006", | 180 | "LEN2006", |
180 | "LEN2007", | 181 | "LEN2007", |
181 | "LEN2008", | 182 | "LEN2008", |
182 | "LEN2009", | 183 | "LEN2009", |
183 | "LEN200A", | 184 | "LEN200A", |
184 | "LEN200B", | 185 | "LEN200B", |
185 | NULL | 186 | NULL |
186 | }; | 187 | }; |
187 | 188 | ||
188 | /***************************************************************************** | 189 | /***************************************************************************** |
189 | * Synaptics communications functions | 190 | * Synaptics communications functions |
190 | ****************************************************************************/ | 191 | ****************************************************************************/ |
191 | 192 | ||
192 | /* | 193 | /* |
193 | * Synaptics touchpads report the y coordinate from bottom to top, which is | 194 | * Synaptics touchpads report the y coordinate from bottom to top, which is |
194 | * opposite from what userspace expects. | 195 | * opposite from what userspace expects. |
195 | * This function is used to invert y before reporting. | 196 | * This function is used to invert y before reporting. |
196 | */ | 197 | */ |
197 | static int synaptics_invert_y(int y) | 198 | static int synaptics_invert_y(int y) |
198 | { | 199 | { |
199 | return YMAX_NOMINAL + YMIN_NOMINAL - y; | 200 | return YMAX_NOMINAL + YMIN_NOMINAL - y; |
200 | } | 201 | } |
201 | 202 | ||
202 | /* | 203 | /* |
203 | * Send a command to the synpatics touchpad by special commands | 204 | * Send a command to the synpatics touchpad by special commands |
204 | */ | 205 | */ |
205 | static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param) | 206 | static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param) |
206 | { | 207 | { |
207 | if (psmouse_sliced_command(psmouse, c)) | 208 | if (psmouse_sliced_command(psmouse, c)) |
208 | return -1; | 209 | return -1; |
209 | if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) | 210 | if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) |
210 | return -1; | 211 | return -1; |
211 | return 0; | 212 | return 0; |
212 | } | 213 | } |
213 | 214 | ||
214 | /* | 215 | /* |
215 | * Read the model-id bytes from the touchpad | 216 | * Read the model-id bytes from the touchpad |
216 | * see also SYN_MODEL_* macros | 217 | * see also SYN_MODEL_* macros |
217 | */ | 218 | */ |
218 | static int synaptics_model_id(struct psmouse *psmouse) | 219 | static int synaptics_model_id(struct psmouse *psmouse) |
219 | { | 220 | { |
220 | struct synaptics_data *priv = psmouse->private; | 221 | struct synaptics_data *priv = psmouse->private; |
221 | unsigned char mi[3]; | 222 | unsigned char mi[3]; |
222 | 223 | ||
223 | if (synaptics_send_cmd(psmouse, SYN_QUE_MODEL, mi)) | 224 | if (synaptics_send_cmd(psmouse, SYN_QUE_MODEL, mi)) |
224 | return -1; | 225 | return -1; |
225 | priv->model_id = (mi[0]<<16) | (mi[1]<<8) | mi[2]; | 226 | priv->model_id = (mi[0]<<16) | (mi[1]<<8) | mi[2]; |
226 | return 0; | 227 | return 0; |
227 | } | 228 | } |
228 | 229 | ||
229 | /* | 230 | /* |
230 | * Read the board id from the touchpad | 231 | * Read the board id from the touchpad |
231 | * The board id is encoded in the "QUERY MODES" response | 232 | * The board id is encoded in the "QUERY MODES" response |
232 | */ | 233 | */ |
233 | static int synaptics_board_id(struct psmouse *psmouse) | 234 | static int synaptics_board_id(struct psmouse *psmouse) |
234 | { | 235 | { |
235 | struct synaptics_data *priv = psmouse->private; | 236 | struct synaptics_data *priv = psmouse->private; |
236 | unsigned char bid[3]; | 237 | unsigned char bid[3]; |
237 | 238 | ||
238 | if (synaptics_send_cmd(psmouse, SYN_QUE_MODES, bid)) | 239 | if (synaptics_send_cmd(psmouse, SYN_QUE_MODES, bid)) |
239 | return -1; | 240 | return -1; |
240 | priv->board_id = ((bid[0] & 0xfc) << 6) | bid[1]; | 241 | priv->board_id = ((bid[0] & 0xfc) << 6) | bid[1]; |
241 | return 0; | 242 | return 0; |
242 | } | 243 | } |
243 | 244 | ||
244 | /* | 245 | /* |
245 | * Read the firmware id from the touchpad | 246 | * Read the firmware id from the touchpad |
246 | */ | 247 | */ |
247 | static int synaptics_firmware_id(struct psmouse *psmouse) | 248 | static int synaptics_firmware_id(struct psmouse *psmouse) |
248 | { | 249 | { |
249 | struct synaptics_data *priv = psmouse->private; | 250 | struct synaptics_data *priv = psmouse->private; |
250 | unsigned char fwid[3]; | 251 | unsigned char fwid[3]; |
251 | 252 | ||
252 | if (synaptics_send_cmd(psmouse, SYN_QUE_FIRMWARE_ID, fwid)) | 253 | if (synaptics_send_cmd(psmouse, SYN_QUE_FIRMWARE_ID, fwid)) |
253 | return -1; | 254 | return -1; |
254 | priv->firmware_id = (fwid[0] << 16) | (fwid[1] << 8) | fwid[2]; | 255 | priv->firmware_id = (fwid[0] << 16) | (fwid[1] << 8) | fwid[2]; |
255 | return 0; | 256 | return 0; |
256 | } | 257 | } |
257 | 258 | ||
258 | /* | 259 | /* |
259 | * Read the capability-bits from the touchpad | 260 | * Read the capability-bits from the touchpad |
260 | * see also the SYN_CAP_* macros | 261 | * see also the SYN_CAP_* macros |
261 | */ | 262 | */ |
262 | static int synaptics_capability(struct psmouse *psmouse) | 263 | static int synaptics_capability(struct psmouse *psmouse) |
263 | { | 264 | { |
264 | struct synaptics_data *priv = psmouse->private; | 265 | struct synaptics_data *priv = psmouse->private; |
265 | unsigned char cap[3]; | 266 | unsigned char cap[3]; |
266 | 267 | ||
267 | if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap)) | 268 | if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap)) |
268 | return -1; | 269 | return -1; |
269 | priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2]; | 270 | priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2]; |
270 | priv->ext_cap = priv->ext_cap_0c = 0; | 271 | priv->ext_cap = priv->ext_cap_0c = 0; |
271 | 272 | ||
272 | /* | 273 | /* |
273 | * Older firmwares had submodel ID fixed to 0x47 | 274 | * Older firmwares had submodel ID fixed to 0x47 |
274 | */ | 275 | */ |
275 | if (SYN_ID_FULL(priv->identity) < 0x705 && | 276 | if (SYN_ID_FULL(priv->identity) < 0x705 && |
276 | SYN_CAP_SUBMODEL_ID(priv->capabilities) != 0x47) { | 277 | SYN_CAP_SUBMODEL_ID(priv->capabilities) != 0x47) { |
277 | return -1; | 278 | return -1; |
278 | } | 279 | } |
279 | 280 | ||
280 | /* | 281 | /* |
281 | * Unless capExtended is set the rest of the flags should be ignored | 282 | * Unless capExtended is set the rest of the flags should be ignored |
282 | */ | 283 | */ |
283 | if (!SYN_CAP_EXTENDED(priv->capabilities)) | 284 | if (!SYN_CAP_EXTENDED(priv->capabilities)) |
284 | priv->capabilities = 0; | 285 | priv->capabilities = 0; |
285 | 286 | ||
286 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) { | 287 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) { |
287 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { | 288 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { |
288 | psmouse_warn(psmouse, | 289 | psmouse_warn(psmouse, |
289 | "device claims to have extended capabilities, but I'm not able to read them.\n"); | 290 | "device claims to have extended capabilities, but I'm not able to read them.\n"); |
290 | } else { | 291 | } else { |
291 | priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2]; | 292 | priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2]; |
292 | 293 | ||
293 | /* | 294 | /* |
294 | * if nExtBtn is greater than 8 it should be considered | 295 | * if nExtBtn is greater than 8 it should be considered |
295 | * invalid and treated as 0 | 296 | * invalid and treated as 0 |
296 | */ | 297 | */ |
297 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 8) | 298 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 8) |
298 | priv->ext_cap &= 0xff0fff; | 299 | priv->ext_cap &= 0xff0fff; |
299 | } | 300 | } |
300 | } | 301 | } |
301 | 302 | ||
302 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) { | 303 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) { |
303 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) { | 304 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) { |
304 | psmouse_warn(psmouse, | 305 | psmouse_warn(psmouse, |
305 | "device claims to have extended capability 0x0c, but I'm not able to read it.\n"); | 306 | "device claims to have extended capability 0x0c, but I'm not able to read it.\n"); |
306 | } else { | 307 | } else { |
307 | priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2]; | 308 | priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2]; |
308 | } | 309 | } |
309 | } | 310 | } |
310 | 311 | ||
311 | return 0; | 312 | return 0; |
312 | } | 313 | } |
313 | 314 | ||
314 | /* | 315 | /* |
315 | * Identify Touchpad | 316 | * Identify Touchpad |
316 | * See also the SYN_ID_* macros | 317 | * See also the SYN_ID_* macros |
317 | */ | 318 | */ |
318 | static int synaptics_identify(struct psmouse *psmouse) | 319 | static int synaptics_identify(struct psmouse *psmouse) |
319 | { | 320 | { |
320 | struct synaptics_data *priv = psmouse->private; | 321 | struct synaptics_data *priv = psmouse->private; |
321 | unsigned char id[3]; | 322 | unsigned char id[3]; |
322 | 323 | ||
323 | if (synaptics_send_cmd(psmouse, SYN_QUE_IDENTIFY, id)) | 324 | if (synaptics_send_cmd(psmouse, SYN_QUE_IDENTIFY, id)) |
324 | return -1; | 325 | return -1; |
325 | priv->identity = (id[0]<<16) | (id[1]<<8) | id[2]; | 326 | priv->identity = (id[0]<<16) | (id[1]<<8) | id[2]; |
326 | if (SYN_ID_IS_SYNAPTICS(priv->identity)) | 327 | if (SYN_ID_IS_SYNAPTICS(priv->identity)) |
327 | return 0; | 328 | return 0; |
328 | return -1; | 329 | return -1; |
329 | } | 330 | } |
330 | 331 | ||
331 | /* | 332 | /* |
332 | * Read touchpad resolution and maximum reported coordinates | 333 | * Read touchpad resolution and maximum reported coordinates |
333 | * Resolution is left zero if touchpad does not support the query | 334 | * Resolution is left zero if touchpad does not support the query |
334 | */ | 335 | */ |
335 | 336 | ||
336 | static int synaptics_resolution(struct psmouse *psmouse) | 337 | static int synaptics_resolution(struct psmouse *psmouse) |
337 | { | 338 | { |
338 | struct synaptics_data *priv = psmouse->private; | 339 | struct synaptics_data *priv = psmouse->private; |
339 | unsigned char resp[3]; | 340 | unsigned char resp[3]; |
340 | int i; | 341 | int i; |
341 | 342 | ||
342 | if (SYN_ID_MAJOR(priv->identity) < 4) | 343 | if (SYN_ID_MAJOR(priv->identity) < 4) |
343 | return 0; | 344 | return 0; |
344 | 345 | ||
345 | if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, resp) == 0) { | 346 | if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, resp) == 0) { |
346 | if (resp[0] != 0 && (resp[1] & 0x80) && resp[2] != 0) { | 347 | if (resp[0] != 0 && (resp[1] & 0x80) && resp[2] != 0) { |
347 | priv->x_res = resp[0]; /* x resolution in units/mm */ | 348 | priv->x_res = resp[0]; /* x resolution in units/mm */ |
348 | priv->y_res = resp[2]; /* y resolution in units/mm */ | 349 | priv->y_res = resp[2]; /* y resolution in units/mm */ |
349 | } | 350 | } |
350 | } | 351 | } |
351 | 352 | ||
352 | for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) { | 353 | for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) { |
353 | if (psmouse_matches_pnp_id(psmouse, | 354 | if (psmouse_matches_pnp_id(psmouse, |
354 | min_max_pnpid_table[i].pnp_ids)) { | 355 | min_max_pnpid_table[i].pnp_ids)) { |
355 | priv->x_min = min_max_pnpid_table[i].x_min; | 356 | priv->x_min = min_max_pnpid_table[i].x_min; |
356 | priv->x_max = min_max_pnpid_table[i].x_max; | 357 | priv->x_max = min_max_pnpid_table[i].x_max; |
357 | priv->y_min = min_max_pnpid_table[i].y_min; | 358 | priv->y_min = min_max_pnpid_table[i].y_min; |
358 | priv->y_max = min_max_pnpid_table[i].y_max; | 359 | priv->y_max = min_max_pnpid_table[i].y_max; |
359 | return 0; | 360 | return 0; |
360 | } | 361 | } |
361 | } | 362 | } |
362 | 363 | ||
363 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && | 364 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && |
364 | SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { | 365 | SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { |
365 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) { | 366 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) { |
366 | psmouse_warn(psmouse, | 367 | psmouse_warn(psmouse, |
367 | "device claims to have max coordinates query, but I'm not able to read it.\n"); | 368 | "device claims to have max coordinates query, but I'm not able to read it.\n"); |
368 | } else { | 369 | } else { |
369 | priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); | 370 | priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); |
370 | priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); | 371 | priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); |
371 | } | 372 | } |
372 | } | 373 | } |
373 | 374 | ||
374 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 && | 375 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 && |
375 | SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) { | 376 | SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) { |
376 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) { | 377 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) { |
377 | psmouse_warn(psmouse, | 378 | psmouse_warn(psmouse, |
378 | "device claims to have min coordinates query, but I'm not able to read it.\n"); | 379 | "device claims to have min coordinates query, but I'm not able to read it.\n"); |
379 | } else { | 380 | } else { |
380 | priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); | 381 | priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); |
381 | priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); | 382 | priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); |
382 | } | 383 | } |
383 | } | 384 | } |
384 | 385 | ||
385 | return 0; | 386 | return 0; |
386 | } | 387 | } |
387 | 388 | ||
388 | static int synaptics_query_hardware(struct psmouse *psmouse) | 389 | static int synaptics_query_hardware(struct psmouse *psmouse) |
389 | { | 390 | { |
390 | if (synaptics_identify(psmouse)) | 391 | if (synaptics_identify(psmouse)) |
391 | return -1; | 392 | return -1; |
392 | if (synaptics_model_id(psmouse)) | 393 | if (synaptics_model_id(psmouse)) |
393 | return -1; | 394 | return -1; |
394 | if (synaptics_firmware_id(psmouse)) | 395 | if (synaptics_firmware_id(psmouse)) |
395 | return -1; | 396 | return -1; |
396 | if (synaptics_board_id(psmouse)) | 397 | if (synaptics_board_id(psmouse)) |
397 | return -1; | 398 | return -1; |
398 | if (synaptics_capability(psmouse)) | 399 | if (synaptics_capability(psmouse)) |
399 | return -1; | 400 | return -1; |
400 | if (synaptics_resolution(psmouse)) | 401 | if (synaptics_resolution(psmouse)) |
401 | return -1; | 402 | return -1; |
402 | 403 | ||
403 | return 0; | 404 | return 0; |
404 | } | 405 | } |
405 | 406 | ||
406 | static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) | 407 | static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) |
407 | { | 408 | { |
408 | static unsigned char param = 0xc8; | 409 | static unsigned char param = 0xc8; |
409 | struct synaptics_data *priv = psmouse->private; | 410 | struct synaptics_data *priv = psmouse->private; |
410 | 411 | ||
411 | if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || | 412 | if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || |
412 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c))) | 413 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c))) |
413 | return 0; | 414 | return 0; |
414 | 415 | ||
415 | if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) | 416 | if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) |
416 | return -1; | 417 | return -1; |
417 | 418 | ||
418 | if (ps2_command(&psmouse->ps2dev, ¶m, PSMOUSE_CMD_SETRATE)) | 419 | if (ps2_command(&psmouse->ps2dev, ¶m, PSMOUSE_CMD_SETRATE)) |
419 | return -1; | 420 | return -1; |
420 | 421 | ||
421 | /* Advanced gesture mode also sends multi finger data */ | 422 | /* Advanced gesture mode also sends multi finger data */ |
422 | priv->capabilities |= BIT(1); | 423 | priv->capabilities |= BIT(1); |
423 | 424 | ||
424 | return 0; | 425 | return 0; |
425 | } | 426 | } |
426 | 427 | ||
427 | static int synaptics_set_mode(struct psmouse *psmouse) | 428 | static int synaptics_set_mode(struct psmouse *psmouse) |
428 | { | 429 | { |
429 | struct synaptics_data *priv = psmouse->private; | 430 | struct synaptics_data *priv = psmouse->private; |
430 | 431 | ||
431 | priv->mode = 0; | 432 | priv->mode = 0; |
432 | if (priv->absolute_mode) | 433 | if (priv->absolute_mode) |
433 | priv->mode |= SYN_BIT_ABSOLUTE_MODE; | 434 | priv->mode |= SYN_BIT_ABSOLUTE_MODE; |
434 | if (priv->disable_gesture) | 435 | if (priv->disable_gesture) |
435 | priv->mode |= SYN_BIT_DISABLE_GESTURE; | 436 | priv->mode |= SYN_BIT_DISABLE_GESTURE; |
436 | if (psmouse->rate >= 80) | 437 | if (psmouse->rate >= 80) |
437 | priv->mode |= SYN_BIT_HIGH_RATE; | 438 | priv->mode |= SYN_BIT_HIGH_RATE; |
438 | if (SYN_CAP_EXTENDED(priv->capabilities)) | 439 | if (SYN_CAP_EXTENDED(priv->capabilities)) |
439 | priv->mode |= SYN_BIT_W_MODE; | 440 | priv->mode |= SYN_BIT_W_MODE; |
440 | 441 | ||
441 | if (synaptics_mode_cmd(psmouse, priv->mode)) | 442 | if (synaptics_mode_cmd(psmouse, priv->mode)) |
442 | return -1; | 443 | return -1; |
443 | 444 | ||
444 | if (priv->absolute_mode && | 445 | if (priv->absolute_mode && |
445 | synaptics_set_advanced_gesture_mode(psmouse)) { | 446 | synaptics_set_advanced_gesture_mode(psmouse)) { |
446 | psmouse_err(psmouse, "Advanced gesture mode init failed.\n"); | 447 | psmouse_err(psmouse, "Advanced gesture mode init failed.\n"); |
447 | return -1; | 448 | return -1; |
448 | } | 449 | } |
449 | 450 | ||
450 | return 0; | 451 | return 0; |
451 | } | 452 | } |
452 | 453 | ||
453 | static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate) | 454 | static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate) |
454 | { | 455 | { |
455 | struct synaptics_data *priv = psmouse->private; | 456 | struct synaptics_data *priv = psmouse->private; |
456 | 457 | ||
457 | if (rate >= 80) { | 458 | if (rate >= 80) { |
458 | priv->mode |= SYN_BIT_HIGH_RATE; | 459 | priv->mode |= SYN_BIT_HIGH_RATE; |
459 | psmouse->rate = 80; | 460 | psmouse->rate = 80; |
460 | } else { | 461 | } else { |
461 | priv->mode &= ~SYN_BIT_HIGH_RATE; | 462 | priv->mode &= ~SYN_BIT_HIGH_RATE; |
462 | psmouse->rate = 40; | 463 | psmouse->rate = 40; |
463 | } | 464 | } |
464 | 465 | ||
465 | synaptics_mode_cmd(psmouse, priv->mode); | 466 | synaptics_mode_cmd(psmouse, priv->mode); |
466 | } | 467 | } |
467 | 468 | ||
468 | /***************************************************************************** | 469 | /***************************************************************************** |
469 | * Synaptics pass-through PS/2 port support | 470 | * Synaptics pass-through PS/2 port support |
470 | ****************************************************************************/ | 471 | ****************************************************************************/ |
471 | static int synaptics_pt_write(struct serio *serio, unsigned char c) | 472 | static int synaptics_pt_write(struct serio *serio, unsigned char c) |
472 | { | 473 | { |
473 | struct psmouse *parent = serio_get_drvdata(serio->parent); | 474 | struct psmouse *parent = serio_get_drvdata(serio->parent); |
474 | char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */ | 475 | char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */ |
475 | 476 | ||
476 | if (psmouse_sliced_command(parent, c)) | 477 | if (psmouse_sliced_command(parent, c)) |
477 | return -1; | 478 | return -1; |
478 | if (ps2_command(&parent->ps2dev, &rate_param, PSMOUSE_CMD_SETRATE)) | 479 | if (ps2_command(&parent->ps2dev, &rate_param, PSMOUSE_CMD_SETRATE)) |
479 | return -1; | 480 | return -1; |
480 | return 0; | 481 | return 0; |
481 | } | 482 | } |
482 | 483 | ||
483 | static int synaptics_pt_start(struct serio *serio) | 484 | static int synaptics_pt_start(struct serio *serio) |
484 | { | 485 | { |
485 | struct psmouse *parent = serio_get_drvdata(serio->parent); | 486 | struct psmouse *parent = serio_get_drvdata(serio->parent); |
486 | struct synaptics_data *priv = parent->private; | 487 | struct synaptics_data *priv = parent->private; |
487 | 488 | ||
488 | serio_pause_rx(parent->ps2dev.serio); | 489 | serio_pause_rx(parent->ps2dev.serio); |
489 | priv->pt_port = serio; | 490 | priv->pt_port = serio; |
490 | serio_continue_rx(parent->ps2dev.serio); | 491 | serio_continue_rx(parent->ps2dev.serio); |
491 | 492 | ||
492 | return 0; | 493 | return 0; |
493 | } | 494 | } |
494 | 495 | ||
495 | static void synaptics_pt_stop(struct serio *serio) | 496 | static void synaptics_pt_stop(struct serio *serio) |
496 | { | 497 | { |
497 | struct psmouse *parent = serio_get_drvdata(serio->parent); | 498 | struct psmouse *parent = serio_get_drvdata(serio->parent); |
498 | struct synaptics_data *priv = parent->private; | 499 | struct synaptics_data *priv = parent->private; |
499 | 500 | ||
500 | serio_pause_rx(parent->ps2dev.serio); | 501 | serio_pause_rx(parent->ps2dev.serio); |
501 | priv->pt_port = NULL; | 502 | priv->pt_port = NULL; |
502 | serio_continue_rx(parent->ps2dev.serio); | 503 | serio_continue_rx(parent->ps2dev.serio); |
503 | } | 504 | } |
504 | 505 | ||
505 | static int synaptics_is_pt_packet(unsigned char *buf) | 506 | static int synaptics_is_pt_packet(unsigned char *buf) |
506 | { | 507 | { |
507 | return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; | 508 | return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; |
508 | } | 509 | } |
509 | 510 | ||
510 | static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet) | 511 | static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet) |
511 | { | 512 | { |
512 | struct psmouse *child = serio_get_drvdata(ptport); | 513 | struct psmouse *child = serio_get_drvdata(ptport); |
513 | 514 | ||
514 | if (child && child->state == PSMOUSE_ACTIVATED) { | 515 | if (child && child->state == PSMOUSE_ACTIVATED) { |
515 | serio_interrupt(ptport, packet[1], 0); | 516 | serio_interrupt(ptport, packet[1], 0); |
516 | serio_interrupt(ptport, packet[4], 0); | 517 | serio_interrupt(ptport, packet[4], 0); |
517 | serio_interrupt(ptport, packet[5], 0); | 518 | serio_interrupt(ptport, packet[5], 0); |
518 | if (child->pktsize == 4) | 519 | if (child->pktsize == 4) |
519 | serio_interrupt(ptport, packet[2], 0); | 520 | serio_interrupt(ptport, packet[2], 0); |
520 | } else | 521 | } else |
521 | serio_interrupt(ptport, packet[1], 0); | 522 | serio_interrupt(ptport, packet[1], 0); |
522 | } | 523 | } |
523 | 524 | ||
524 | static void synaptics_pt_activate(struct psmouse *psmouse) | 525 | static void synaptics_pt_activate(struct psmouse *psmouse) |
525 | { | 526 | { |
526 | struct synaptics_data *priv = psmouse->private; | 527 | struct synaptics_data *priv = psmouse->private; |
527 | struct psmouse *child = serio_get_drvdata(priv->pt_port); | 528 | struct psmouse *child = serio_get_drvdata(priv->pt_port); |
528 | 529 | ||
529 | /* adjust the touchpad to child's choice of protocol */ | 530 | /* adjust the touchpad to child's choice of protocol */ |
530 | if (child) { | 531 | if (child) { |
531 | if (child->pktsize == 4) | 532 | if (child->pktsize == 4) |
532 | priv->mode |= SYN_BIT_FOUR_BYTE_CLIENT; | 533 | priv->mode |= SYN_BIT_FOUR_BYTE_CLIENT; |
533 | else | 534 | else |
534 | priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT; | 535 | priv->mode &= ~SYN_BIT_FOUR_BYTE_CLIENT; |
535 | 536 | ||
536 | if (synaptics_mode_cmd(psmouse, priv->mode)) | 537 | if (synaptics_mode_cmd(psmouse, priv->mode)) |
537 | psmouse_warn(psmouse, | 538 | psmouse_warn(psmouse, |
538 | "failed to switch guest protocol\n"); | 539 | "failed to switch guest protocol\n"); |
539 | } | 540 | } |
540 | } | 541 | } |
541 | 542 | ||
542 | static void synaptics_pt_create(struct psmouse *psmouse) | 543 | static void synaptics_pt_create(struct psmouse *psmouse) |
543 | { | 544 | { |
544 | struct serio *serio; | 545 | struct serio *serio; |
545 | 546 | ||
546 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | 547 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); |
547 | if (!serio) { | 548 | if (!serio) { |
548 | psmouse_err(psmouse, | 549 | psmouse_err(psmouse, |
549 | "not enough memory for pass-through port\n"); | 550 | "not enough memory for pass-through port\n"); |
550 | return; | 551 | return; |
551 | } | 552 | } |
552 | 553 | ||
553 | serio->id.type = SERIO_PS_PSTHRU; | 554 | serio->id.type = SERIO_PS_PSTHRU; |
554 | strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); | 555 | strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); |
555 | strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); | 556 | strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); |
556 | serio->write = synaptics_pt_write; | 557 | serio->write = synaptics_pt_write; |
557 | serio->start = synaptics_pt_start; | 558 | serio->start = synaptics_pt_start; |
558 | serio->stop = synaptics_pt_stop; | 559 | serio->stop = synaptics_pt_stop; |
559 | serio->parent = psmouse->ps2dev.serio; | 560 | serio->parent = psmouse->ps2dev.serio; |
560 | 561 | ||
561 | psmouse->pt_activate = synaptics_pt_activate; | 562 | psmouse->pt_activate = synaptics_pt_activate; |
562 | 563 | ||
563 | psmouse_info(psmouse, "serio: %s port at %s\n", | 564 | psmouse_info(psmouse, "serio: %s port at %s\n", |
564 | serio->name, psmouse->phys); | 565 | serio->name, psmouse->phys); |
565 | serio_register_port(serio); | 566 | serio_register_port(serio); |
566 | } | 567 | } |
567 | 568 | ||
568 | /***************************************************************************** | 569 | /***************************************************************************** |
569 | * Functions to interpret the absolute mode packets | 570 | * Functions to interpret the absolute mode packets |
570 | ****************************************************************************/ | 571 | ****************************************************************************/ |
571 | 572 | ||
572 | static void synaptics_mt_state_set(struct synaptics_mt_state *state, int count, | 573 | static void synaptics_mt_state_set(struct synaptics_mt_state *state, int count, |
573 | int sgm, int agm) | 574 | int sgm, int agm) |
574 | { | 575 | { |
575 | state->count = count; | 576 | state->count = count; |
576 | state->sgm = sgm; | 577 | state->sgm = sgm; |
577 | state->agm = agm; | 578 | state->agm = agm; |
578 | } | 579 | } |
579 | 580 | ||
580 | static void synaptics_parse_agm(const unsigned char buf[], | 581 | static void synaptics_parse_agm(const unsigned char buf[], |
581 | struct synaptics_data *priv, | 582 | struct synaptics_data *priv, |
582 | struct synaptics_hw_state *hw) | 583 | struct synaptics_hw_state *hw) |
583 | { | 584 | { |
584 | struct synaptics_hw_state *agm = &priv->agm; | 585 | struct synaptics_hw_state *agm = &priv->agm; |
585 | int agm_packet_type; | 586 | int agm_packet_type; |
586 | 587 | ||
587 | agm_packet_type = (buf[5] & 0x30) >> 4; | 588 | agm_packet_type = (buf[5] & 0x30) >> 4; |
588 | switch (agm_packet_type) { | 589 | switch (agm_packet_type) { |
589 | case 1: | 590 | case 1: |
590 | /* Gesture packet: (x, y, z) half resolution */ | 591 | /* Gesture packet: (x, y, z) half resolution */ |
591 | agm->w = hw->w; | 592 | agm->w = hw->w; |
592 | agm->x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1; | 593 | agm->x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1; |
593 | agm->y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1; | 594 | agm->y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1; |
594 | agm->z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1; | 595 | agm->z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1; |
595 | break; | 596 | break; |
596 | 597 | ||
597 | case 2: | 598 | case 2: |
598 | /* AGM-CONTACT packet: (count, sgm, agm) */ | 599 | /* AGM-CONTACT packet: (count, sgm, agm) */ |
599 | synaptics_mt_state_set(&agm->mt_state, buf[1], buf[2], buf[4]); | 600 | synaptics_mt_state_set(&agm->mt_state, buf[1], buf[2], buf[4]); |
600 | break; | 601 | break; |
601 | 602 | ||
602 | default: | 603 | default: |
603 | break; | 604 | break; |
604 | } | 605 | } |
605 | 606 | ||
606 | /* Record that at least one AGM has been received since last SGM */ | 607 | /* Record that at least one AGM has been received since last SGM */ |
607 | priv->agm_pending = true; | 608 | priv->agm_pending = true; |
608 | } | 609 | } |
609 | 610 | ||
610 | static bool is_forcepad; | 611 | static bool is_forcepad; |
611 | 612 | ||
612 | static int synaptics_parse_hw_state(const unsigned char buf[], | 613 | static int synaptics_parse_hw_state(const unsigned char buf[], |
613 | struct synaptics_data *priv, | 614 | struct synaptics_data *priv, |
614 | struct synaptics_hw_state *hw) | 615 | struct synaptics_hw_state *hw) |
615 | { | 616 | { |
616 | memset(hw, 0, sizeof(struct synaptics_hw_state)); | 617 | memset(hw, 0, sizeof(struct synaptics_hw_state)); |
617 | 618 | ||
618 | if (SYN_MODEL_NEWABS(priv->model_id)) { | 619 | if (SYN_MODEL_NEWABS(priv->model_id)) { |
619 | hw->w = (((buf[0] & 0x30) >> 2) | | 620 | hw->w = (((buf[0] & 0x30) >> 2) | |
620 | ((buf[0] & 0x04) >> 1) | | 621 | ((buf[0] & 0x04) >> 1) | |
621 | ((buf[3] & 0x04) >> 2)); | 622 | ((buf[3] & 0x04) >> 2)); |
622 | 623 | ||
623 | if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || | 624 | if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || |
624 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && | 625 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && |
625 | hw->w == 2) { | 626 | hw->w == 2) { |
626 | synaptics_parse_agm(buf, priv, hw); | 627 | synaptics_parse_agm(buf, priv, hw); |
627 | return 1; | 628 | return 1; |
628 | } | 629 | } |
629 | 630 | ||
630 | hw->x = (((buf[3] & 0x10) << 8) | | 631 | hw->x = (((buf[3] & 0x10) << 8) | |
631 | ((buf[1] & 0x0f) << 8) | | 632 | ((buf[1] & 0x0f) << 8) | |
632 | buf[4]); | 633 | buf[4]); |
633 | hw->y = (((buf[3] & 0x20) << 7) | | 634 | hw->y = (((buf[3] & 0x20) << 7) | |
634 | ((buf[1] & 0xf0) << 4) | | 635 | ((buf[1] & 0xf0) << 4) | |
635 | buf[5]); | 636 | buf[5]); |
636 | hw->z = buf[2]; | 637 | hw->z = buf[2]; |
637 | 638 | ||
638 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 639 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
639 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 640 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
640 | 641 | ||
641 | if (is_forcepad) { | 642 | if (is_forcepad) { |
642 | /* | 643 | /* |
643 | * ForcePads, like Clickpads, use middle button | 644 | * ForcePads, like Clickpads, use middle button |
644 | * bits to report primary button clicks. | 645 | * bits to report primary button clicks. |
645 | * Unfortunately they report primary button not | 646 | * Unfortunately they report primary button not |
646 | * only when user presses on the pad above certain | 647 | * only when user presses on the pad above certain |
647 | * threshold, but also when there are more than one | 648 | * threshold, but also when there are more than one |
648 | * finger on the touchpad, which interferes with | 649 | * finger on the touchpad, which interferes with |
649 | * out multi-finger gestures. | 650 | * out multi-finger gestures. |
650 | */ | 651 | */ |
651 | if (hw->z == 0) { | 652 | if (hw->z == 0) { |
652 | /* No contacts */ | 653 | /* No contacts */ |
653 | priv->press = priv->report_press = false; | 654 | priv->press = priv->report_press = false; |
654 | } else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) { | 655 | } else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) { |
655 | /* | 656 | /* |
656 | * Single-finger touch with pressure above | 657 | * Single-finger touch with pressure above |
657 | * the threshold. If pressure stays long | 658 | * the threshold. If pressure stays long |
658 | * enough, we'll start reporting primary | 659 | * enough, we'll start reporting primary |
659 | * button. We rely on the device continuing | 660 | * button. We rely on the device continuing |
660 | * sending data even if finger does not | 661 | * sending data even if finger does not |
661 | * move. | 662 | * move. |
662 | */ | 663 | */ |
663 | if (!priv->press) { | 664 | if (!priv->press) { |
664 | priv->press_start = jiffies; | 665 | priv->press_start = jiffies; |
665 | priv->press = true; | 666 | priv->press = true; |
666 | } else if (time_after(jiffies, | 667 | } else if (time_after(jiffies, |
667 | priv->press_start + | 668 | priv->press_start + |
668 | msecs_to_jiffies(50))) { | 669 | msecs_to_jiffies(50))) { |
669 | priv->report_press = true; | 670 | priv->report_press = true; |
670 | } | 671 | } |
671 | } else { | 672 | } else { |
672 | priv->press = false; | 673 | priv->press = false; |
673 | } | 674 | } |
674 | 675 | ||
675 | hw->left = priv->report_press; | 676 | hw->left = priv->report_press; |
676 | 677 | ||
677 | } else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | 678 | } else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { |
678 | /* | 679 | /* |
679 | * Clickpad's button is transmitted as middle button, | 680 | * Clickpad's button is transmitted as middle button, |
680 | * however, since it is primary button, we will report | 681 | * however, since it is primary button, we will report |
681 | * it as BTN_LEFT. | 682 | * it as BTN_LEFT. |
682 | */ | 683 | */ |
683 | hw->left = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; | 684 | hw->left = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; |
684 | 685 | ||
685 | } else if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { | 686 | } else if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { |
686 | hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; | 687 | hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; |
687 | if (hw->w == 2) | 688 | if (hw->w == 2) |
688 | hw->scroll = (signed char)(buf[1]); | 689 | hw->scroll = (signed char)(buf[1]); |
689 | } | 690 | } |
690 | 691 | ||
691 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) { | 692 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) { |
692 | hw->up = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; | 693 | hw->up = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; |
693 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; | 694 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; |
694 | } | 695 | } |
695 | 696 | ||
696 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && | 697 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && |
697 | ((buf[0] ^ buf[3]) & 0x02)) { | 698 | ((buf[0] ^ buf[3]) & 0x02)) { |
698 | switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { | 699 | switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { |
699 | default: | 700 | default: |
700 | /* | 701 | /* |
701 | * if nExtBtn is greater than 8 it should be | 702 | * if nExtBtn is greater than 8 it should be |
702 | * considered invalid and treated as 0 | 703 | * considered invalid and treated as 0 |
703 | */ | 704 | */ |
704 | break; | 705 | break; |
705 | case 8: | 706 | case 8: |
706 | hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0; | 707 | hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0; |
707 | hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0; | 708 | hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0; |
708 | case 6: | 709 | case 6: |
709 | hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0; | 710 | hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0; |
710 | hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0; | 711 | hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0; |
711 | case 4: | 712 | case 4: |
712 | hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0; | 713 | hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0; |
713 | hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0; | 714 | hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0; |
714 | case 2: | 715 | case 2: |
715 | hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0; | 716 | hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0; |
716 | hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0; | 717 | hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0; |
717 | } | 718 | } |
718 | } | 719 | } |
719 | } else { | 720 | } else { |
720 | hw->x = (((buf[1] & 0x1f) << 8) | buf[2]); | 721 | hw->x = (((buf[1] & 0x1f) << 8) | buf[2]); |
721 | hw->y = (((buf[4] & 0x1f) << 8) | buf[5]); | 722 | hw->y = (((buf[4] & 0x1f) << 8) | buf[5]); |
722 | 723 | ||
723 | hw->z = (((buf[0] & 0x30) << 2) | (buf[3] & 0x3F)); | 724 | hw->z = (((buf[0] & 0x30) << 2) | (buf[3] & 0x3F)); |
724 | hw->w = (((buf[1] & 0x80) >> 4) | ((buf[0] & 0x04) >> 1)); | 725 | hw->w = (((buf[1] & 0x80) >> 4) | ((buf[0] & 0x04) >> 1)); |
725 | 726 | ||
726 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 727 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
727 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 728 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
728 | } | 729 | } |
729 | 730 | ||
730 | /* | 731 | /* |
731 | * Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE | 732 | * Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE |
732 | * is used by some firmware to indicate a finger at the edge of | 733 | * is used by some firmware to indicate a finger at the edge of |
733 | * the touchpad whose precise position cannot be determined, so | 734 | * the touchpad whose precise position cannot be determined, so |
734 | * convert these values to the maximum axis value. | 735 | * convert these values to the maximum axis value. |
735 | */ | 736 | */ |
736 | if (hw->x > X_MAX_POSITIVE) | 737 | if (hw->x > X_MAX_POSITIVE) |
737 | hw->x -= 1 << ABS_POS_BITS; | 738 | hw->x -= 1 << ABS_POS_BITS; |
738 | else if (hw->x == X_MAX_POSITIVE) | 739 | else if (hw->x == X_MAX_POSITIVE) |
739 | hw->x = XMAX; | 740 | hw->x = XMAX; |
740 | 741 | ||
741 | if (hw->y > Y_MAX_POSITIVE) | 742 | if (hw->y > Y_MAX_POSITIVE) |
742 | hw->y -= 1 << ABS_POS_BITS; | 743 | hw->y -= 1 << ABS_POS_BITS; |
743 | else if (hw->y == Y_MAX_POSITIVE) | 744 | else if (hw->y == Y_MAX_POSITIVE) |
744 | hw->y = YMAX; | 745 | hw->y = YMAX; |
745 | 746 | ||
746 | return 0; | 747 | return 0; |
747 | } | 748 | } |
748 | 749 | ||
749 | static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot, | 750 | static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot, |
750 | bool active, int x, int y) | 751 | bool active, int x, int y) |
751 | { | 752 | { |
752 | input_mt_slot(dev, slot); | 753 | input_mt_slot(dev, slot); |
753 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); | 754 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); |
754 | if (active) { | 755 | if (active) { |
755 | input_report_abs(dev, ABS_MT_POSITION_X, x); | 756 | input_report_abs(dev, ABS_MT_POSITION_X, x); |
756 | input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(y)); | 757 | input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(y)); |
757 | } | 758 | } |
758 | } | 759 | } |
759 | 760 | ||
760 | static void synaptics_report_semi_mt_data(struct input_dev *dev, | 761 | static void synaptics_report_semi_mt_data(struct input_dev *dev, |
761 | const struct synaptics_hw_state *a, | 762 | const struct synaptics_hw_state *a, |
762 | const struct synaptics_hw_state *b, | 763 | const struct synaptics_hw_state *b, |
763 | int num_fingers) | 764 | int num_fingers) |
764 | { | 765 | { |
765 | if (num_fingers >= 2) { | 766 | if (num_fingers >= 2) { |
766 | synaptics_report_semi_mt_slot(dev, 0, true, min(a->x, b->x), | 767 | synaptics_report_semi_mt_slot(dev, 0, true, min(a->x, b->x), |
767 | min(a->y, b->y)); | 768 | min(a->y, b->y)); |
768 | synaptics_report_semi_mt_slot(dev, 1, true, max(a->x, b->x), | 769 | synaptics_report_semi_mt_slot(dev, 1, true, max(a->x, b->x), |
769 | max(a->y, b->y)); | 770 | max(a->y, b->y)); |
770 | } else if (num_fingers == 1) { | 771 | } else if (num_fingers == 1) { |
771 | synaptics_report_semi_mt_slot(dev, 0, true, a->x, a->y); | 772 | synaptics_report_semi_mt_slot(dev, 0, true, a->x, a->y); |
772 | synaptics_report_semi_mt_slot(dev, 1, false, 0, 0); | 773 | synaptics_report_semi_mt_slot(dev, 1, false, 0, 0); |
773 | } else { | 774 | } else { |
774 | synaptics_report_semi_mt_slot(dev, 0, false, 0, 0); | 775 | synaptics_report_semi_mt_slot(dev, 0, false, 0, 0); |
775 | synaptics_report_semi_mt_slot(dev, 1, false, 0, 0); | 776 | synaptics_report_semi_mt_slot(dev, 1, false, 0, 0); |
776 | } | 777 | } |
777 | } | 778 | } |
778 | 779 | ||
779 | static void synaptics_report_buttons(struct psmouse *psmouse, | 780 | static void synaptics_report_buttons(struct psmouse *psmouse, |
780 | const struct synaptics_hw_state *hw) | 781 | const struct synaptics_hw_state *hw) |
781 | { | 782 | { |
782 | struct input_dev *dev = psmouse->dev; | 783 | struct input_dev *dev = psmouse->dev; |
783 | struct synaptics_data *priv = psmouse->private; | 784 | struct synaptics_data *priv = psmouse->private; |
784 | int i; | 785 | int i; |
785 | 786 | ||
786 | input_report_key(dev, BTN_LEFT, hw->left); | 787 | input_report_key(dev, BTN_LEFT, hw->left); |
787 | input_report_key(dev, BTN_RIGHT, hw->right); | 788 | input_report_key(dev, BTN_RIGHT, hw->right); |
788 | 789 | ||
789 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) | 790 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) |
790 | input_report_key(dev, BTN_MIDDLE, hw->middle); | 791 | input_report_key(dev, BTN_MIDDLE, hw->middle); |
791 | 792 | ||
792 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) { | 793 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) { |
793 | input_report_key(dev, BTN_FORWARD, hw->up); | 794 | input_report_key(dev, BTN_FORWARD, hw->up); |
794 | input_report_key(dev, BTN_BACK, hw->down); | 795 | input_report_key(dev, BTN_BACK, hw->down); |
795 | } | 796 | } |
796 | 797 | ||
797 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) | 798 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) |
798 | input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i)); | 799 | input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i)); |
799 | } | 800 | } |
800 | 801 | ||
801 | static void synaptics_report_slot(struct input_dev *dev, int slot, | 802 | static void synaptics_report_slot(struct input_dev *dev, int slot, |
802 | const struct synaptics_hw_state *hw) | 803 | const struct synaptics_hw_state *hw) |
803 | { | 804 | { |
804 | input_mt_slot(dev, slot); | 805 | input_mt_slot(dev, slot); |
805 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, (hw != NULL)); | 806 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, (hw != NULL)); |
806 | if (!hw) | 807 | if (!hw) |
807 | return; | 808 | return; |
808 | 809 | ||
809 | input_report_abs(dev, ABS_MT_POSITION_X, hw->x); | 810 | input_report_abs(dev, ABS_MT_POSITION_X, hw->x); |
810 | input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(hw->y)); | 811 | input_report_abs(dev, ABS_MT_POSITION_Y, synaptics_invert_y(hw->y)); |
811 | input_report_abs(dev, ABS_MT_PRESSURE, hw->z); | 812 | input_report_abs(dev, ABS_MT_PRESSURE, hw->z); |
812 | } | 813 | } |
813 | 814 | ||
814 | static void synaptics_report_mt_data(struct psmouse *psmouse, | 815 | static void synaptics_report_mt_data(struct psmouse *psmouse, |
815 | struct synaptics_mt_state *mt_state, | 816 | struct synaptics_mt_state *mt_state, |
816 | const struct synaptics_hw_state *sgm) | 817 | const struct synaptics_hw_state *sgm) |
817 | { | 818 | { |
818 | struct input_dev *dev = psmouse->dev; | 819 | struct input_dev *dev = psmouse->dev; |
819 | struct synaptics_data *priv = psmouse->private; | 820 | struct synaptics_data *priv = psmouse->private; |
820 | struct synaptics_hw_state *agm = &priv->agm; | 821 | struct synaptics_hw_state *agm = &priv->agm; |
821 | struct synaptics_mt_state *old = &priv->mt_state; | 822 | struct synaptics_mt_state *old = &priv->mt_state; |
822 | 823 | ||
823 | switch (mt_state->count) { | 824 | switch (mt_state->count) { |
824 | case 0: | 825 | case 0: |
825 | synaptics_report_slot(dev, 0, NULL); | 826 | synaptics_report_slot(dev, 0, NULL); |
826 | synaptics_report_slot(dev, 1, NULL); | 827 | synaptics_report_slot(dev, 1, NULL); |
827 | break; | 828 | break; |
828 | case 1: | 829 | case 1: |
829 | if (mt_state->sgm == -1) { | 830 | if (mt_state->sgm == -1) { |
830 | synaptics_report_slot(dev, 0, NULL); | 831 | synaptics_report_slot(dev, 0, NULL); |
831 | synaptics_report_slot(dev, 1, NULL); | 832 | synaptics_report_slot(dev, 1, NULL); |
832 | } else if (mt_state->sgm == 0) { | 833 | } else if (mt_state->sgm == 0) { |
833 | synaptics_report_slot(dev, 0, sgm); | 834 | synaptics_report_slot(dev, 0, sgm); |
834 | synaptics_report_slot(dev, 1, NULL); | 835 | synaptics_report_slot(dev, 1, NULL); |
835 | } else { | 836 | } else { |
836 | synaptics_report_slot(dev, 0, NULL); | 837 | synaptics_report_slot(dev, 0, NULL); |
837 | synaptics_report_slot(dev, 1, sgm); | 838 | synaptics_report_slot(dev, 1, sgm); |
838 | } | 839 | } |
839 | break; | 840 | break; |
840 | default: | 841 | default: |
841 | /* | 842 | /* |
842 | * If the finger slot contained in SGM is valid, and either | 843 | * If the finger slot contained in SGM is valid, and either |
843 | * hasn't changed, or is new, or the old SGM has now moved to | 844 | * hasn't changed, or is new, or the old SGM has now moved to |
844 | * AGM, then report SGM in MTB slot 0. | 845 | * AGM, then report SGM in MTB slot 0. |
845 | * Otherwise, empty MTB slot 0. | 846 | * Otherwise, empty MTB slot 0. |
846 | */ | 847 | */ |
847 | if (mt_state->sgm != -1 && | 848 | if (mt_state->sgm != -1 && |
848 | (mt_state->sgm == old->sgm || | 849 | (mt_state->sgm == old->sgm || |
849 | old->sgm == -1 || mt_state->agm == old->sgm)) | 850 | old->sgm == -1 || mt_state->agm == old->sgm)) |
850 | synaptics_report_slot(dev, 0, sgm); | 851 | synaptics_report_slot(dev, 0, sgm); |
851 | else | 852 | else |
852 | synaptics_report_slot(dev, 0, NULL); | 853 | synaptics_report_slot(dev, 0, NULL); |
853 | 854 | ||
854 | /* | 855 | /* |
855 | * If the finger slot contained in AGM is valid, and either | 856 | * If the finger slot contained in AGM is valid, and either |
856 | * hasn't changed, or is new, then report AGM in MTB slot 1. | 857 | * hasn't changed, or is new, then report AGM in MTB slot 1. |
857 | * Otherwise, empty MTB slot 1. | 858 | * Otherwise, empty MTB slot 1. |
858 | * | 859 | * |
859 | * However, in the case where the AGM is new, make sure that | 860 | * However, in the case where the AGM is new, make sure that |
860 | * that it is either the same as the old SGM, or there was no | 861 | * that it is either the same as the old SGM, or there was no |
861 | * SGM. | 862 | * SGM. |
862 | * | 863 | * |
863 | * Otherwise, if the SGM was just 1, and the new AGM is 2, then | 864 | * Otherwise, if the SGM was just 1, and the new AGM is 2, then |
864 | * the new AGM will keep the old SGM's tracking ID, which can | 865 | * the new AGM will keep the old SGM's tracking ID, which can |
865 | * cause apparent drumroll. This happens if in the following | 866 | * cause apparent drumroll. This happens if in the following |
866 | * valid finger sequence: | 867 | * valid finger sequence: |
867 | * | 868 | * |
868 | * Action SGM AGM (MTB slot:Contact) | 869 | * Action SGM AGM (MTB slot:Contact) |
869 | * 1. Touch contact 0 (0:0) | 870 | * 1. Touch contact 0 (0:0) |
870 | * 2. Touch contact 1 (0:0, 1:1) | 871 | * 2. Touch contact 1 (0:0, 1:1) |
871 | * 3. Lift contact 0 (1:1) | 872 | * 3. Lift contact 0 (1:1) |
872 | * 4. Touch contacts 2,3 (0:2, 1:3) | 873 | * 4. Touch contacts 2,3 (0:2, 1:3) |
873 | * | 874 | * |
874 | * In step 4, contact 3, in AGM must not be given the same | 875 | * In step 4, contact 3, in AGM must not be given the same |
875 | * tracking ID as contact 1 had in step 3. To avoid this, | 876 | * tracking ID as contact 1 had in step 3. To avoid this, |
876 | * the first agm with contact 3 is dropped and slot 1 is | 877 | * the first agm with contact 3 is dropped and slot 1 is |
877 | * invalidated (tracking ID = -1). | 878 | * invalidated (tracking ID = -1). |
878 | */ | 879 | */ |
879 | if (mt_state->agm != -1 && | 880 | if (mt_state->agm != -1 && |
880 | (mt_state->agm == old->agm || | 881 | (mt_state->agm == old->agm || |
881 | (old->agm == -1 && | 882 | (old->agm == -1 && |
882 | (old->sgm == -1 || mt_state->agm == old->sgm)))) | 883 | (old->sgm == -1 || mt_state->agm == old->sgm)))) |
883 | synaptics_report_slot(dev, 1, agm); | 884 | synaptics_report_slot(dev, 1, agm); |
884 | else | 885 | else |
885 | synaptics_report_slot(dev, 1, NULL); | 886 | synaptics_report_slot(dev, 1, NULL); |
886 | break; | 887 | break; |
887 | } | 888 | } |
888 | 889 | ||
889 | /* Don't use active slot count to generate BTN_TOOL events. */ | 890 | /* Don't use active slot count to generate BTN_TOOL events. */ |
890 | input_mt_report_pointer_emulation(dev, false); | 891 | input_mt_report_pointer_emulation(dev, false); |
891 | 892 | ||
892 | /* Send the number of fingers reported by touchpad itself. */ | 893 | /* Send the number of fingers reported by touchpad itself. */ |
893 | input_mt_report_finger_count(dev, mt_state->count); | 894 | input_mt_report_finger_count(dev, mt_state->count); |
894 | 895 | ||
895 | synaptics_report_buttons(psmouse, sgm); | 896 | synaptics_report_buttons(psmouse, sgm); |
896 | 897 | ||
897 | input_sync(dev); | 898 | input_sync(dev); |
898 | } | 899 | } |
899 | 900 | ||
900 | /* Handle case where mt_state->count = 0 */ | 901 | /* Handle case where mt_state->count = 0 */ |
901 | static void synaptics_image_sensor_0f(struct synaptics_data *priv, | 902 | static void synaptics_image_sensor_0f(struct synaptics_data *priv, |
902 | struct synaptics_mt_state *mt_state) | 903 | struct synaptics_mt_state *mt_state) |
903 | { | 904 | { |
904 | synaptics_mt_state_set(mt_state, 0, -1, -1); | 905 | synaptics_mt_state_set(mt_state, 0, -1, -1); |
905 | priv->mt_state_lost = false; | 906 | priv->mt_state_lost = false; |
906 | } | 907 | } |
907 | 908 | ||
908 | /* Handle case where mt_state->count = 1 */ | 909 | /* Handle case where mt_state->count = 1 */ |
909 | static void synaptics_image_sensor_1f(struct synaptics_data *priv, | 910 | static void synaptics_image_sensor_1f(struct synaptics_data *priv, |
910 | struct synaptics_mt_state *mt_state) | 911 | struct synaptics_mt_state *mt_state) |
911 | { | 912 | { |
912 | struct synaptics_hw_state *agm = &priv->agm; | 913 | struct synaptics_hw_state *agm = &priv->agm; |
913 | struct synaptics_mt_state *old = &priv->mt_state; | 914 | struct synaptics_mt_state *old = &priv->mt_state; |
914 | 915 | ||
915 | /* | 916 | /* |
916 | * If the last AGM was (0,0,0), and there is only one finger left, | 917 | * If the last AGM was (0,0,0), and there is only one finger left, |
917 | * then we absolutely know that SGM contains slot 0, and all other | 918 | * then we absolutely know that SGM contains slot 0, and all other |
918 | * fingers have been removed. | 919 | * fingers have been removed. |
919 | */ | 920 | */ |
920 | if (priv->agm_pending && agm->z == 0) { | 921 | if (priv->agm_pending && agm->z == 0) { |
921 | synaptics_mt_state_set(mt_state, 1, 0, -1); | 922 | synaptics_mt_state_set(mt_state, 1, 0, -1); |
922 | priv->mt_state_lost = false; | 923 | priv->mt_state_lost = false; |
923 | return; | 924 | return; |
924 | } | 925 | } |
925 | 926 | ||
926 | switch (old->count) { | 927 | switch (old->count) { |
927 | case 0: | 928 | case 0: |
928 | synaptics_mt_state_set(mt_state, 1, 0, -1); | 929 | synaptics_mt_state_set(mt_state, 1, 0, -1); |
929 | break; | 930 | break; |
930 | case 1: | 931 | case 1: |
931 | /* | 932 | /* |
932 | * If mt_state_lost, then the previous transition was 3->1, | 933 | * If mt_state_lost, then the previous transition was 3->1, |
933 | * and SGM now contains either slot 0 or 1, but we don't know | 934 | * and SGM now contains either slot 0 or 1, but we don't know |
934 | * which. So, we just assume that the SGM now contains slot 1. | 935 | * which. So, we just assume that the SGM now contains slot 1. |
935 | * | 936 | * |
936 | * If pending AGM and either: | 937 | * If pending AGM and either: |
937 | * (a) the previous SGM slot contains slot 0, or | 938 | * (a) the previous SGM slot contains slot 0, or |
938 | * (b) there was no SGM slot | 939 | * (b) there was no SGM slot |
939 | * then, the SGM now contains slot 1 | 940 | * then, the SGM now contains slot 1 |
940 | * | 941 | * |
941 | * Case (a) happens with very rapid "drum roll" gestures, where | 942 | * Case (a) happens with very rapid "drum roll" gestures, where |
942 | * slot 0 finger is lifted and a new slot 1 finger touches | 943 | * slot 0 finger is lifted and a new slot 1 finger touches |
943 | * within one reporting interval. | 944 | * within one reporting interval. |
944 | * | 945 | * |
945 | * Case (b) happens if initially two or more fingers tap | 946 | * Case (b) happens if initially two or more fingers tap |
946 | * briefly, and all but one lift before the end of the first | 947 | * briefly, and all but one lift before the end of the first |
947 | * reporting interval. | 948 | * reporting interval. |
948 | * | 949 | * |
949 | * (In both these cases, slot 0 will becomes empty, so SGM | 950 | * (In both these cases, slot 0 will becomes empty, so SGM |
950 | * contains slot 1 with the new finger) | 951 | * contains slot 1 with the new finger) |
951 | * | 952 | * |
952 | * Else, if there was no previous SGM, it now contains slot 0. | 953 | * Else, if there was no previous SGM, it now contains slot 0. |
953 | * | 954 | * |
954 | * Otherwise, SGM still contains the same slot. | 955 | * Otherwise, SGM still contains the same slot. |
955 | */ | 956 | */ |
956 | if (priv->mt_state_lost || | 957 | if (priv->mt_state_lost || |
957 | (priv->agm_pending && old->sgm <= 0)) | 958 | (priv->agm_pending && old->sgm <= 0)) |
958 | synaptics_mt_state_set(mt_state, 1, 1, -1); | 959 | synaptics_mt_state_set(mt_state, 1, 1, -1); |
959 | else if (old->sgm == -1) | 960 | else if (old->sgm == -1) |
960 | synaptics_mt_state_set(mt_state, 1, 0, -1); | 961 | synaptics_mt_state_set(mt_state, 1, 0, -1); |
961 | break; | 962 | break; |
962 | case 2: | 963 | case 2: |
963 | /* | 964 | /* |
964 | * If mt_state_lost, we don't know which finger SGM contains. | 965 | * If mt_state_lost, we don't know which finger SGM contains. |
965 | * | 966 | * |
966 | * So, report 1 finger, but with both slots empty. | 967 | * So, report 1 finger, but with both slots empty. |
967 | * We will use slot 1 on subsequent 1->1 | 968 | * We will use slot 1 on subsequent 1->1 |
968 | */ | 969 | */ |
969 | if (priv->mt_state_lost) { | 970 | if (priv->mt_state_lost) { |
970 | synaptics_mt_state_set(mt_state, 1, -1, -1); | 971 | synaptics_mt_state_set(mt_state, 1, -1, -1); |
971 | break; | 972 | break; |
972 | } | 973 | } |
973 | /* | 974 | /* |
974 | * Since the last AGM was NOT (0,0,0), it was the finger in | 975 | * Since the last AGM was NOT (0,0,0), it was the finger in |
975 | * slot 0 that has been removed. | 976 | * slot 0 that has been removed. |
976 | * So, SGM now contains previous AGM's slot, and AGM is now | 977 | * So, SGM now contains previous AGM's slot, and AGM is now |
977 | * empty. | 978 | * empty. |
978 | */ | 979 | */ |
979 | synaptics_mt_state_set(mt_state, 1, old->agm, -1); | 980 | synaptics_mt_state_set(mt_state, 1, old->agm, -1); |
980 | break; | 981 | break; |
981 | case 3: | 982 | case 3: |
982 | /* | 983 | /* |
983 | * Since last AGM was not (0,0,0), we don't know which finger | 984 | * Since last AGM was not (0,0,0), we don't know which finger |
984 | * is left. | 985 | * is left. |
985 | * | 986 | * |
986 | * So, report 1 finger, but with both slots empty. | 987 | * So, report 1 finger, but with both slots empty. |
987 | * We will use slot 1 on subsequent 1->1 | 988 | * We will use slot 1 on subsequent 1->1 |
988 | */ | 989 | */ |
989 | synaptics_mt_state_set(mt_state, 1, -1, -1); | 990 | synaptics_mt_state_set(mt_state, 1, -1, -1); |
990 | priv->mt_state_lost = true; | 991 | priv->mt_state_lost = true; |
991 | break; | 992 | break; |
992 | case 4: | 993 | case 4: |
993 | case 5: | 994 | case 5: |
994 | /* mt_state was updated by AGM-CONTACT packet */ | 995 | /* mt_state was updated by AGM-CONTACT packet */ |
995 | break; | 996 | break; |
996 | } | 997 | } |
997 | } | 998 | } |
998 | 999 | ||
999 | /* Handle case where mt_state->count = 2 */ | 1000 | /* Handle case where mt_state->count = 2 */ |
1000 | static void synaptics_image_sensor_2f(struct synaptics_data *priv, | 1001 | static void synaptics_image_sensor_2f(struct synaptics_data *priv, |
1001 | struct synaptics_mt_state *mt_state) | 1002 | struct synaptics_mt_state *mt_state) |
1002 | { | 1003 | { |
1003 | struct synaptics_mt_state *old = &priv->mt_state; | 1004 | struct synaptics_mt_state *old = &priv->mt_state; |
1004 | 1005 | ||
1005 | switch (old->count) { | 1006 | switch (old->count) { |
1006 | case 0: | 1007 | case 0: |
1007 | synaptics_mt_state_set(mt_state, 2, 0, 1); | 1008 | synaptics_mt_state_set(mt_state, 2, 0, 1); |
1008 | break; | 1009 | break; |
1009 | case 1: | 1010 | case 1: |
1010 | /* | 1011 | /* |
1011 | * If previous SGM contained slot 1 or higher, SGM now contains | 1012 | * If previous SGM contained slot 1 or higher, SGM now contains |
1012 | * slot 0 (the newly touching finger) and AGM contains SGM's | 1013 | * slot 0 (the newly touching finger) and AGM contains SGM's |
1013 | * previous slot. | 1014 | * previous slot. |
1014 | * | 1015 | * |
1015 | * Otherwise, SGM still contains slot 0 and AGM now contains | 1016 | * Otherwise, SGM still contains slot 0 and AGM now contains |
1016 | * slot 1. | 1017 | * slot 1. |
1017 | */ | 1018 | */ |
1018 | if (old->sgm >= 1) | 1019 | if (old->sgm >= 1) |
1019 | synaptics_mt_state_set(mt_state, 2, 0, old->sgm); | 1020 | synaptics_mt_state_set(mt_state, 2, 0, old->sgm); |
1020 | else | 1021 | else |
1021 | synaptics_mt_state_set(mt_state, 2, 0, 1); | 1022 | synaptics_mt_state_set(mt_state, 2, 0, 1); |
1022 | break; | 1023 | break; |
1023 | case 2: | 1024 | case 2: |
1024 | /* | 1025 | /* |
1025 | * If mt_state_lost, SGM now contains either finger 1 or 2, but | 1026 | * If mt_state_lost, SGM now contains either finger 1 or 2, but |
1026 | * we don't know which. | 1027 | * we don't know which. |
1027 | * So, we just assume that the SGM contains slot 0 and AGM 1. | 1028 | * So, we just assume that the SGM contains slot 0 and AGM 1. |
1028 | */ | 1029 | */ |
1029 | if (priv->mt_state_lost) | 1030 | if (priv->mt_state_lost) |
1030 | synaptics_mt_state_set(mt_state, 2, 0, 1); | 1031 | synaptics_mt_state_set(mt_state, 2, 0, 1); |
1031 | /* | 1032 | /* |
1032 | * Otherwise, use the same mt_state, since it either hasn't | 1033 | * Otherwise, use the same mt_state, since it either hasn't |
1033 | * changed, or was updated by a recently received AGM-CONTACT | 1034 | * changed, or was updated by a recently received AGM-CONTACT |
1034 | * packet. | 1035 | * packet. |
1035 | */ | 1036 | */ |
1036 | break; | 1037 | break; |
1037 | case 3: | 1038 | case 3: |
1038 | /* | 1039 | /* |
1039 | * 3->2 transitions have two unsolvable problems: | 1040 | * 3->2 transitions have two unsolvable problems: |
1040 | * 1) no indication is given which finger was removed | 1041 | * 1) no indication is given which finger was removed |
1041 | * 2) no way to tell if agm packet was for finger 3 | 1042 | * 2) no way to tell if agm packet was for finger 3 |
1042 | * before 3->2, or finger 2 after 3->2. | 1043 | * before 3->2, or finger 2 after 3->2. |
1043 | * | 1044 | * |
1044 | * So, report 2 fingers, but empty all slots. | 1045 | * So, report 2 fingers, but empty all slots. |
1045 | * We will guess slots [0,1] on subsequent 2->2. | 1046 | * We will guess slots [0,1] on subsequent 2->2. |
1046 | */ | 1047 | */ |
1047 | synaptics_mt_state_set(mt_state, 2, -1, -1); | 1048 | synaptics_mt_state_set(mt_state, 2, -1, -1); |
1048 | priv->mt_state_lost = true; | 1049 | priv->mt_state_lost = true; |
1049 | break; | 1050 | break; |
1050 | case 4: | 1051 | case 4: |
1051 | case 5: | 1052 | case 5: |
1052 | /* mt_state was updated by AGM-CONTACT packet */ | 1053 | /* mt_state was updated by AGM-CONTACT packet */ |
1053 | break; | 1054 | break; |
1054 | } | 1055 | } |
1055 | } | 1056 | } |
1056 | 1057 | ||
1057 | /* Handle case where mt_state->count = 3 */ | 1058 | /* Handle case where mt_state->count = 3 */ |
1058 | static void synaptics_image_sensor_3f(struct synaptics_data *priv, | 1059 | static void synaptics_image_sensor_3f(struct synaptics_data *priv, |
1059 | struct synaptics_mt_state *mt_state) | 1060 | struct synaptics_mt_state *mt_state) |
1060 | { | 1061 | { |
1061 | struct synaptics_mt_state *old = &priv->mt_state; | 1062 | struct synaptics_mt_state *old = &priv->mt_state; |
1062 | 1063 | ||
1063 | switch (old->count) { | 1064 | switch (old->count) { |
1064 | case 0: | 1065 | case 0: |
1065 | synaptics_mt_state_set(mt_state, 3, 0, 2); | 1066 | synaptics_mt_state_set(mt_state, 3, 0, 2); |
1066 | break; | 1067 | break; |
1067 | case 1: | 1068 | case 1: |
1068 | /* | 1069 | /* |
1069 | * If previous SGM contained slot 2 or higher, SGM now contains | 1070 | * If previous SGM contained slot 2 or higher, SGM now contains |
1070 | * slot 0 (one of the newly touching fingers) and AGM contains | 1071 | * slot 0 (one of the newly touching fingers) and AGM contains |
1071 | * SGM's previous slot. | 1072 | * SGM's previous slot. |
1072 | * | 1073 | * |
1073 | * Otherwise, SGM now contains slot 0 and AGM contains slot 2. | 1074 | * Otherwise, SGM now contains slot 0 and AGM contains slot 2. |
1074 | */ | 1075 | */ |
1075 | if (old->sgm >= 2) | 1076 | if (old->sgm >= 2) |
1076 | synaptics_mt_state_set(mt_state, 3, 0, old->sgm); | 1077 | synaptics_mt_state_set(mt_state, 3, 0, old->sgm); |
1077 | else | 1078 | else |
1078 | synaptics_mt_state_set(mt_state, 3, 0, 2); | 1079 | synaptics_mt_state_set(mt_state, 3, 0, 2); |
1079 | break; | 1080 | break; |
1080 | case 2: | 1081 | case 2: |
1081 | /* | 1082 | /* |
1082 | * If the AGM previously contained slot 3 or higher, then the | 1083 | * If the AGM previously contained slot 3 or higher, then the |
1083 | * newly touching finger is in the lowest available slot. | 1084 | * newly touching finger is in the lowest available slot. |
1084 | * | 1085 | * |
1085 | * If SGM was previously 1 or higher, then the new SGM is | 1086 | * If SGM was previously 1 or higher, then the new SGM is |
1086 | * now slot 0 (with a new finger), otherwise, the new finger | 1087 | * now slot 0 (with a new finger), otherwise, the new finger |
1087 | * is now in a hidden slot between 0 and AGM's slot. | 1088 | * is now in a hidden slot between 0 and AGM's slot. |
1088 | * | 1089 | * |
1089 | * In all such cases, the SGM now contains slot 0, and the AGM | 1090 | * In all such cases, the SGM now contains slot 0, and the AGM |
1090 | * continues to contain the same slot as before. | 1091 | * continues to contain the same slot as before. |
1091 | */ | 1092 | */ |
1092 | if (old->agm >= 3) { | 1093 | if (old->agm >= 3) { |
1093 | synaptics_mt_state_set(mt_state, 3, 0, old->agm); | 1094 | synaptics_mt_state_set(mt_state, 3, 0, old->agm); |
1094 | break; | 1095 | break; |
1095 | } | 1096 | } |
1096 | 1097 | ||
1097 | /* | 1098 | /* |
1098 | * After some 3->1 and all 3->2 transitions, we lose track | 1099 | * After some 3->1 and all 3->2 transitions, we lose track |
1099 | * of which slot is reported by SGM and AGM. | 1100 | * of which slot is reported by SGM and AGM. |
1100 | * | 1101 | * |
1101 | * For 2->3 in this state, report 3 fingers, but empty all | 1102 | * For 2->3 in this state, report 3 fingers, but empty all |
1102 | * slots, and we will guess (0,2) on a subsequent 0->3. | 1103 | * slots, and we will guess (0,2) on a subsequent 0->3. |
1103 | * | 1104 | * |
1104 | * To userspace, the resulting transition will look like: | 1105 | * To userspace, the resulting transition will look like: |
1105 | * 2:[0,1] -> 3:[-1,-1] -> 3:[0,2] | 1106 | * 2:[0,1] -> 3:[-1,-1] -> 3:[0,2] |
1106 | */ | 1107 | */ |
1107 | if (priv->mt_state_lost) { | 1108 | if (priv->mt_state_lost) { |
1108 | synaptics_mt_state_set(mt_state, 3, -1, -1); | 1109 | synaptics_mt_state_set(mt_state, 3, -1, -1); |
1109 | break; | 1110 | break; |
1110 | } | 1111 | } |
1111 | 1112 | ||
1112 | /* | 1113 | /* |
1113 | * If the (SGM,AGM) really previously contained slots (0, 1), | 1114 | * If the (SGM,AGM) really previously contained slots (0, 1), |
1114 | * then we cannot know what slot was just reported by the AGM, | 1115 | * then we cannot know what slot was just reported by the AGM, |
1115 | * because the 2->3 transition can occur either before or after | 1116 | * because the 2->3 transition can occur either before or after |
1116 | * the AGM packet. Thus, this most recent AGM could contain | 1117 | * the AGM packet. Thus, this most recent AGM could contain |
1117 | * either the same old slot 1 or the new slot 2. | 1118 | * either the same old slot 1 or the new slot 2. |
1118 | * Subsequent AGMs will be reporting slot 2. | 1119 | * Subsequent AGMs will be reporting slot 2. |
1119 | * | 1120 | * |
1120 | * To userspace, the resulting transition will look like: | 1121 | * To userspace, the resulting transition will look like: |
1121 | * 2:[0,1] -> 3:[0,-1] -> 3:[0,2] | 1122 | * 2:[0,1] -> 3:[0,-1] -> 3:[0,2] |
1122 | */ | 1123 | */ |
1123 | synaptics_mt_state_set(mt_state, 3, 0, -1); | 1124 | synaptics_mt_state_set(mt_state, 3, 0, -1); |
1124 | break; | 1125 | break; |
1125 | case 3: | 1126 | case 3: |
1126 | /* | 1127 | /* |
1127 | * If, for whatever reason, the previous agm was invalid, | 1128 | * If, for whatever reason, the previous agm was invalid, |
1128 | * Assume SGM now contains slot 0, AGM now contains slot 2. | 1129 | * Assume SGM now contains slot 0, AGM now contains slot 2. |
1129 | */ | 1130 | */ |
1130 | if (old->agm <= 2) | 1131 | if (old->agm <= 2) |
1131 | synaptics_mt_state_set(mt_state, 3, 0, 2); | 1132 | synaptics_mt_state_set(mt_state, 3, 0, 2); |
1132 | /* | 1133 | /* |
1133 | * mt_state either hasn't changed, or was updated by a recently | 1134 | * mt_state either hasn't changed, or was updated by a recently |
1134 | * received AGM-CONTACT packet. | 1135 | * received AGM-CONTACT packet. |
1135 | */ | 1136 | */ |
1136 | break; | 1137 | break; |
1137 | 1138 | ||
1138 | case 4: | 1139 | case 4: |
1139 | case 5: | 1140 | case 5: |
1140 | /* mt_state was updated by AGM-CONTACT packet */ | 1141 | /* mt_state was updated by AGM-CONTACT packet */ |
1141 | break; | 1142 | break; |
1142 | } | 1143 | } |
1143 | } | 1144 | } |
1144 | 1145 | ||
1145 | /* Handle case where mt_state->count = 4, or = 5 */ | 1146 | /* Handle case where mt_state->count = 4, or = 5 */ |
1146 | static void synaptics_image_sensor_45f(struct synaptics_data *priv, | 1147 | static void synaptics_image_sensor_45f(struct synaptics_data *priv, |
1147 | struct synaptics_mt_state *mt_state) | 1148 | struct synaptics_mt_state *mt_state) |
1148 | { | 1149 | { |
1149 | /* mt_state was updated correctly by AGM-CONTACT packet */ | 1150 | /* mt_state was updated correctly by AGM-CONTACT packet */ |
1150 | priv->mt_state_lost = false; | 1151 | priv->mt_state_lost = false; |
1151 | } | 1152 | } |
1152 | 1153 | ||
1153 | static void synaptics_image_sensor_process(struct psmouse *psmouse, | 1154 | static void synaptics_image_sensor_process(struct psmouse *psmouse, |
1154 | struct synaptics_hw_state *sgm) | 1155 | struct synaptics_hw_state *sgm) |
1155 | { | 1156 | { |
1156 | struct synaptics_data *priv = psmouse->private; | 1157 | struct synaptics_data *priv = psmouse->private; |
1157 | struct synaptics_hw_state *agm = &priv->agm; | 1158 | struct synaptics_hw_state *agm = &priv->agm; |
1158 | struct synaptics_mt_state mt_state; | 1159 | struct synaptics_mt_state mt_state; |
1159 | 1160 | ||
1160 | /* Initialize using current mt_state (as updated by last agm) */ | 1161 | /* Initialize using current mt_state (as updated by last agm) */ |
1161 | mt_state = agm->mt_state; | 1162 | mt_state = agm->mt_state; |
1162 | 1163 | ||
1163 | /* | 1164 | /* |
1164 | * Update mt_state using the new finger count and current mt_state. | 1165 | * Update mt_state using the new finger count and current mt_state. |
1165 | */ | 1166 | */ |
1166 | if (sgm->z == 0) | 1167 | if (sgm->z == 0) |
1167 | synaptics_image_sensor_0f(priv, &mt_state); | 1168 | synaptics_image_sensor_0f(priv, &mt_state); |
1168 | else if (sgm->w >= 4) | 1169 | else if (sgm->w >= 4) |
1169 | synaptics_image_sensor_1f(priv, &mt_state); | 1170 | synaptics_image_sensor_1f(priv, &mt_state); |
1170 | else if (sgm->w == 0) | 1171 | else if (sgm->w == 0) |
1171 | synaptics_image_sensor_2f(priv, &mt_state); | 1172 | synaptics_image_sensor_2f(priv, &mt_state); |
1172 | else if (sgm->w == 1 && mt_state.count <= 3) | 1173 | else if (sgm->w == 1 && mt_state.count <= 3) |
1173 | synaptics_image_sensor_3f(priv, &mt_state); | 1174 | synaptics_image_sensor_3f(priv, &mt_state); |
1174 | else | 1175 | else |
1175 | synaptics_image_sensor_45f(priv, &mt_state); | 1176 | synaptics_image_sensor_45f(priv, &mt_state); |
1176 | 1177 | ||
1177 | /* Send resulting input events to user space */ | 1178 | /* Send resulting input events to user space */ |
1178 | synaptics_report_mt_data(psmouse, &mt_state, sgm); | 1179 | synaptics_report_mt_data(psmouse, &mt_state, sgm); |
1179 | 1180 | ||
1180 | /* Store updated mt_state */ | 1181 | /* Store updated mt_state */ |
1181 | priv->mt_state = agm->mt_state = mt_state; | 1182 | priv->mt_state = agm->mt_state = mt_state; |
1182 | priv->agm_pending = false; | 1183 | priv->agm_pending = false; |
1183 | } | 1184 | } |
1184 | 1185 | ||
1185 | static void synaptics_profile_sensor_process(struct psmouse *psmouse, | 1186 | static void synaptics_profile_sensor_process(struct psmouse *psmouse, |
1186 | struct synaptics_hw_state *sgm, | 1187 | struct synaptics_hw_state *sgm, |
1187 | int num_fingers) | 1188 | int num_fingers) |
1188 | { | 1189 | { |
1189 | struct input_dev *dev = psmouse->dev; | 1190 | struct input_dev *dev = psmouse->dev; |
1190 | struct synaptics_data *priv = psmouse->private; | 1191 | struct synaptics_data *priv = psmouse->private; |
1191 | struct synaptics_hw_state *hw[2] = { sgm, &priv->agm }; | 1192 | struct synaptics_hw_state *hw[2] = { sgm, &priv->agm }; |
1192 | struct input_mt_pos pos[2]; | 1193 | struct input_mt_pos pos[2]; |
1193 | int slot[2], nsemi, i; | 1194 | int slot[2], nsemi, i; |
1194 | 1195 | ||
1195 | nsemi = clamp_val(num_fingers, 0, 2); | 1196 | nsemi = clamp_val(num_fingers, 0, 2); |
1196 | 1197 | ||
1197 | for (i = 0; i < nsemi; i++) { | 1198 | for (i = 0; i < nsemi; i++) { |
1198 | pos[i].x = hw[i]->x; | 1199 | pos[i].x = hw[i]->x; |
1199 | pos[i].y = synaptics_invert_y(hw[i]->y); | 1200 | pos[i].y = synaptics_invert_y(hw[i]->y); |
1200 | } | 1201 | } |
1201 | 1202 | ||
1202 | input_mt_assign_slots(dev, slot, pos, nsemi); | 1203 | input_mt_assign_slots(dev, slot, pos, nsemi); |
1203 | 1204 | ||
1204 | for (i = 0; i < nsemi; i++) { | 1205 | for (i = 0; i < nsemi; i++) { |
1205 | input_mt_slot(dev, slot[i]); | 1206 | input_mt_slot(dev, slot[i]); |
1206 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); | 1207 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); |
1207 | input_report_abs(dev, ABS_MT_POSITION_X, pos[i].x); | 1208 | input_report_abs(dev, ABS_MT_POSITION_X, pos[i].x); |
1208 | input_report_abs(dev, ABS_MT_POSITION_Y, pos[i].y); | 1209 | input_report_abs(dev, ABS_MT_POSITION_Y, pos[i].y); |
1209 | input_report_abs(dev, ABS_MT_PRESSURE, hw[i]->z); | 1210 | input_report_abs(dev, ABS_MT_PRESSURE, hw[i]->z); |
1210 | } | 1211 | } |
1211 | 1212 | ||
1212 | input_mt_drop_unused(dev); | 1213 | input_mt_drop_unused(dev); |
1213 | input_mt_report_pointer_emulation(dev, false); | 1214 | input_mt_report_pointer_emulation(dev, false); |
1214 | input_mt_report_finger_count(dev, num_fingers); | 1215 | input_mt_report_finger_count(dev, num_fingers); |
1215 | 1216 | ||
1216 | synaptics_report_buttons(psmouse, sgm); | 1217 | synaptics_report_buttons(psmouse, sgm); |
1217 | 1218 | ||
1218 | input_sync(dev); | 1219 | input_sync(dev); |
1219 | } | 1220 | } |
1220 | 1221 | ||
1221 | /* | 1222 | /* |
1222 | * called for each full received packet from the touchpad | 1223 | * called for each full received packet from the touchpad |
1223 | */ | 1224 | */ |
1224 | static void synaptics_process_packet(struct psmouse *psmouse) | 1225 | static void synaptics_process_packet(struct psmouse *psmouse) |
1225 | { | 1226 | { |
1226 | struct input_dev *dev = psmouse->dev; | 1227 | struct input_dev *dev = psmouse->dev; |
1227 | struct synaptics_data *priv = psmouse->private; | 1228 | struct synaptics_data *priv = psmouse->private; |
1228 | struct synaptics_hw_state hw; | 1229 | struct synaptics_hw_state hw; |
1229 | int num_fingers; | 1230 | int num_fingers; |
1230 | int finger_width; | 1231 | int finger_width; |
1231 | 1232 | ||
1232 | if (synaptics_parse_hw_state(psmouse->packet, priv, &hw)) | 1233 | if (synaptics_parse_hw_state(psmouse->packet, priv, &hw)) |
1233 | return; | 1234 | return; |
1234 | 1235 | ||
1235 | if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { | 1236 | if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { |
1236 | synaptics_image_sensor_process(psmouse, &hw); | 1237 | synaptics_image_sensor_process(psmouse, &hw); |
1237 | return; | 1238 | return; |
1238 | } | 1239 | } |
1239 | 1240 | ||
1240 | if (hw.scroll) { | 1241 | if (hw.scroll) { |
1241 | priv->scroll += hw.scroll; | 1242 | priv->scroll += hw.scroll; |
1242 | 1243 | ||
1243 | while (priv->scroll >= 4) { | 1244 | while (priv->scroll >= 4) { |
1244 | input_report_key(dev, BTN_BACK, !hw.down); | 1245 | input_report_key(dev, BTN_BACK, !hw.down); |
1245 | input_sync(dev); | 1246 | input_sync(dev); |
1246 | input_report_key(dev, BTN_BACK, hw.down); | 1247 | input_report_key(dev, BTN_BACK, hw.down); |
1247 | input_sync(dev); | 1248 | input_sync(dev); |
1248 | priv->scroll -= 4; | 1249 | priv->scroll -= 4; |
1249 | } | 1250 | } |
1250 | while (priv->scroll <= -4) { | 1251 | while (priv->scroll <= -4) { |
1251 | input_report_key(dev, BTN_FORWARD, !hw.up); | 1252 | input_report_key(dev, BTN_FORWARD, !hw.up); |
1252 | input_sync(dev); | 1253 | input_sync(dev); |
1253 | input_report_key(dev, BTN_FORWARD, hw.up); | 1254 | input_report_key(dev, BTN_FORWARD, hw.up); |
1254 | input_sync(dev); | 1255 | input_sync(dev); |
1255 | priv->scroll += 4; | 1256 | priv->scroll += 4; |
1256 | } | 1257 | } |
1257 | return; | 1258 | return; |
1258 | } | 1259 | } |
1259 | 1260 | ||
1260 | if (hw.z > 0 && hw.x > 1) { | 1261 | if (hw.z > 0 && hw.x > 1) { |
1261 | num_fingers = 1; | 1262 | num_fingers = 1; |
1262 | finger_width = 5; | 1263 | finger_width = 5; |
1263 | if (SYN_CAP_EXTENDED(priv->capabilities)) { | 1264 | if (SYN_CAP_EXTENDED(priv->capabilities)) { |
1264 | switch (hw.w) { | 1265 | switch (hw.w) { |
1265 | case 0 ... 1: | 1266 | case 0 ... 1: |
1266 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) | 1267 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) |
1267 | num_fingers = hw.w + 2; | 1268 | num_fingers = hw.w + 2; |
1268 | break; | 1269 | break; |
1269 | case 2: | 1270 | case 2: |
1270 | if (SYN_MODEL_PEN(priv->model_id)) | 1271 | if (SYN_MODEL_PEN(priv->model_id)) |
1271 | ; /* Nothing, treat a pen as a single finger */ | 1272 | ; /* Nothing, treat a pen as a single finger */ |
1272 | break; | 1273 | break; |
1273 | case 4 ... 15: | 1274 | case 4 ... 15: |
1274 | if (SYN_CAP_PALMDETECT(priv->capabilities)) | 1275 | if (SYN_CAP_PALMDETECT(priv->capabilities)) |
1275 | finger_width = hw.w; | 1276 | finger_width = hw.w; |
1276 | break; | 1277 | break; |
1277 | } | 1278 | } |
1278 | } | 1279 | } |
1279 | } else { | 1280 | } else { |
1280 | num_fingers = 0; | 1281 | num_fingers = 0; |
1281 | finger_width = 0; | 1282 | finger_width = 0; |
1282 | } | 1283 | } |
1283 | 1284 | ||
1284 | if (cr48_profile_sensor) { | 1285 | if (cr48_profile_sensor) { |
1285 | synaptics_profile_sensor_process(psmouse, &hw, num_fingers); | 1286 | synaptics_profile_sensor_process(psmouse, &hw, num_fingers); |
1286 | return; | 1287 | return; |
1287 | } | 1288 | } |
1288 | 1289 | ||
1289 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) | 1290 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) |
1290 | synaptics_report_semi_mt_data(dev, &hw, &priv->agm, | 1291 | synaptics_report_semi_mt_data(dev, &hw, &priv->agm, |
1291 | num_fingers); | 1292 | num_fingers); |
1292 | 1293 | ||
1293 | /* Post events | 1294 | /* Post events |
1294 | * BTN_TOUCH has to be first as mousedev relies on it when doing | 1295 | * BTN_TOUCH has to be first as mousedev relies on it when doing |
1295 | * absolute -> relative conversion | 1296 | * absolute -> relative conversion |
1296 | */ | 1297 | */ |
1297 | if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1); | 1298 | if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1); |
1298 | if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0); | 1299 | if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0); |
1299 | 1300 | ||
1300 | if (num_fingers > 0) { | 1301 | if (num_fingers > 0) { |
1301 | input_report_abs(dev, ABS_X, hw.x); | 1302 | input_report_abs(dev, ABS_X, hw.x); |
1302 | input_report_abs(dev, ABS_Y, synaptics_invert_y(hw.y)); | 1303 | input_report_abs(dev, ABS_Y, synaptics_invert_y(hw.y)); |
1303 | } | 1304 | } |
1304 | input_report_abs(dev, ABS_PRESSURE, hw.z); | 1305 | input_report_abs(dev, ABS_PRESSURE, hw.z); |
1305 | 1306 | ||
1306 | if (SYN_CAP_PALMDETECT(priv->capabilities)) | 1307 | if (SYN_CAP_PALMDETECT(priv->capabilities)) |
1307 | input_report_abs(dev, ABS_TOOL_WIDTH, finger_width); | 1308 | input_report_abs(dev, ABS_TOOL_WIDTH, finger_width); |
1308 | 1309 | ||
1309 | input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1); | 1310 | input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1); |
1310 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { | 1311 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { |
1311 | input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); | 1312 | input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); |
1312 | input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); | 1313 | input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); |
1313 | } | 1314 | } |
1314 | 1315 | ||
1315 | synaptics_report_buttons(psmouse, &hw); | 1316 | synaptics_report_buttons(psmouse, &hw); |
1316 | 1317 | ||
1317 | input_sync(dev); | 1318 | input_sync(dev); |
1318 | } | 1319 | } |
1319 | 1320 | ||
1320 | static int synaptics_validate_byte(struct psmouse *psmouse, | 1321 | static int synaptics_validate_byte(struct psmouse *psmouse, |
1321 | int idx, unsigned char pkt_type) | 1322 | int idx, unsigned char pkt_type) |
1322 | { | 1323 | { |
1323 | static const unsigned char newabs_mask[] = { 0xC8, 0x00, 0x00, 0xC8, 0x00 }; | 1324 | static const unsigned char newabs_mask[] = { 0xC8, 0x00, 0x00, 0xC8, 0x00 }; |
1324 | static const unsigned char newabs_rel_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 }; | 1325 | static const unsigned char newabs_rel_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 }; |
1325 | static const unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 }; | 1326 | static const unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 }; |
1326 | static const unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 }; | 1327 | static const unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 }; |
1327 | static const unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 }; | 1328 | static const unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 }; |
1328 | const char *packet = psmouse->packet; | 1329 | const char *packet = psmouse->packet; |
1329 | 1330 | ||
1330 | if (idx < 0 || idx > 4) | 1331 | if (idx < 0 || idx > 4) |
1331 | return 0; | 1332 | return 0; |
1332 | 1333 | ||
1333 | switch (pkt_type) { | 1334 | switch (pkt_type) { |
1334 | 1335 | ||
1335 | case SYN_NEWABS: | 1336 | case SYN_NEWABS: |
1336 | case SYN_NEWABS_RELAXED: | 1337 | case SYN_NEWABS_RELAXED: |
1337 | return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx]; | 1338 | return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx]; |
1338 | 1339 | ||
1339 | case SYN_NEWABS_STRICT: | 1340 | case SYN_NEWABS_STRICT: |
1340 | return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx]; | 1341 | return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx]; |
1341 | 1342 | ||
1342 | case SYN_OLDABS: | 1343 | case SYN_OLDABS: |
1343 | return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx]; | 1344 | return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx]; |
1344 | 1345 | ||
1345 | default: | 1346 | default: |
1346 | psmouse_err(psmouse, "unknown packet type %d\n", pkt_type); | 1347 | psmouse_err(psmouse, "unknown packet type %d\n", pkt_type); |
1347 | return 0; | 1348 | return 0; |
1348 | } | 1349 | } |
1349 | } | 1350 | } |
1350 | 1351 | ||
1351 | static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse) | 1352 | static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse) |
1352 | { | 1353 | { |
1353 | int i; | 1354 | int i; |
1354 | 1355 | ||
1355 | for (i = 0; i < 5; i++) | 1356 | for (i = 0; i < 5; i++) |
1356 | if (!synaptics_validate_byte(psmouse, i, SYN_NEWABS_STRICT)) { | 1357 | if (!synaptics_validate_byte(psmouse, i, SYN_NEWABS_STRICT)) { |
1357 | psmouse_info(psmouse, "using relaxed packet validation\n"); | 1358 | psmouse_info(psmouse, "using relaxed packet validation\n"); |
1358 | return SYN_NEWABS_RELAXED; | 1359 | return SYN_NEWABS_RELAXED; |
1359 | } | 1360 | } |
1360 | 1361 | ||
1361 | return SYN_NEWABS_STRICT; | 1362 | return SYN_NEWABS_STRICT; |
1362 | } | 1363 | } |
1363 | 1364 | ||
1364 | static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) | 1365 | static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) |
1365 | { | 1366 | { |
1366 | struct synaptics_data *priv = psmouse->private; | 1367 | struct synaptics_data *priv = psmouse->private; |
1367 | 1368 | ||
1368 | if (psmouse->pktcnt >= 6) { /* Full packet received */ | 1369 | if (psmouse->pktcnt >= 6) { /* Full packet received */ |
1369 | if (unlikely(priv->pkt_type == SYN_NEWABS)) | 1370 | if (unlikely(priv->pkt_type == SYN_NEWABS)) |
1370 | priv->pkt_type = synaptics_detect_pkt_type(psmouse); | 1371 | priv->pkt_type = synaptics_detect_pkt_type(psmouse); |
1371 | 1372 | ||
1372 | if (SYN_CAP_PASS_THROUGH(priv->capabilities) && | 1373 | if (SYN_CAP_PASS_THROUGH(priv->capabilities) && |
1373 | synaptics_is_pt_packet(psmouse->packet)) { | 1374 | synaptics_is_pt_packet(psmouse->packet)) { |
1374 | if (priv->pt_port) | 1375 | if (priv->pt_port) |
1375 | synaptics_pass_pt_packet(priv->pt_port, psmouse->packet); | 1376 | synaptics_pass_pt_packet(priv->pt_port, psmouse->packet); |
1376 | } else | 1377 | } else |
1377 | synaptics_process_packet(psmouse); | 1378 | synaptics_process_packet(psmouse); |
1378 | 1379 | ||
1379 | return PSMOUSE_FULL_PACKET; | 1380 | return PSMOUSE_FULL_PACKET; |
1380 | } | 1381 | } |
1381 | 1382 | ||
1382 | return synaptics_validate_byte(psmouse, psmouse->pktcnt - 1, priv->pkt_type) ? | 1383 | return synaptics_validate_byte(psmouse, psmouse->pktcnt - 1, priv->pkt_type) ? |
1383 | PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; | 1384 | PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; |
1384 | } | 1385 | } |
1385 | 1386 | ||
1386 | /***************************************************************************** | 1387 | /***************************************************************************** |
1387 | * Driver initialization/cleanup functions | 1388 | * Driver initialization/cleanup functions |
1388 | ****************************************************************************/ | 1389 | ****************************************************************************/ |
1389 | static void set_abs_position_params(struct input_dev *dev, | 1390 | static void set_abs_position_params(struct input_dev *dev, |
1390 | struct synaptics_data *priv, int x_code, | 1391 | struct synaptics_data *priv, int x_code, |
1391 | int y_code) | 1392 | int y_code) |
1392 | { | 1393 | { |
1393 | int x_min = priv->x_min ?: XMIN_NOMINAL; | 1394 | int x_min = priv->x_min ?: XMIN_NOMINAL; |
1394 | int x_max = priv->x_max ?: XMAX_NOMINAL; | 1395 | int x_max = priv->x_max ?: XMAX_NOMINAL; |
1395 | int y_min = priv->y_min ?: YMIN_NOMINAL; | 1396 | int y_min = priv->y_min ?: YMIN_NOMINAL; |
1396 | int y_max = priv->y_max ?: YMAX_NOMINAL; | 1397 | int y_max = priv->y_max ?: YMAX_NOMINAL; |
1397 | int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ? | 1398 | int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ? |
1398 | SYN_REDUCED_FILTER_FUZZ : 0; | 1399 | SYN_REDUCED_FILTER_FUZZ : 0; |
1399 | 1400 | ||
1400 | input_set_abs_params(dev, x_code, x_min, x_max, fuzz, 0); | 1401 | input_set_abs_params(dev, x_code, x_min, x_max, fuzz, 0); |
1401 | input_set_abs_params(dev, y_code, y_min, y_max, fuzz, 0); | 1402 | input_set_abs_params(dev, y_code, y_min, y_max, fuzz, 0); |
1402 | input_abs_set_res(dev, x_code, priv->x_res); | 1403 | input_abs_set_res(dev, x_code, priv->x_res); |
1403 | input_abs_set_res(dev, y_code, priv->y_res); | 1404 | input_abs_set_res(dev, y_code, priv->y_res); |
1404 | } | 1405 | } |
1405 | 1406 | ||
1406 | static void set_input_params(struct psmouse *psmouse, | 1407 | static void set_input_params(struct psmouse *psmouse, |
1407 | struct synaptics_data *priv) | 1408 | struct synaptics_data *priv) |
1408 | { | 1409 | { |
1409 | struct input_dev *dev = psmouse->dev; | 1410 | struct input_dev *dev = psmouse->dev; |
1410 | int i; | 1411 | int i; |
1411 | 1412 | ||
1412 | /* Things that apply to both modes */ | 1413 | /* Things that apply to both modes */ |
1413 | __set_bit(INPUT_PROP_POINTER, dev->propbit); | 1414 | __set_bit(INPUT_PROP_POINTER, dev->propbit); |
1414 | __set_bit(EV_KEY, dev->evbit); | 1415 | __set_bit(EV_KEY, dev->evbit); |
1415 | __set_bit(BTN_LEFT, dev->keybit); | 1416 | __set_bit(BTN_LEFT, dev->keybit); |
1416 | __set_bit(BTN_RIGHT, dev->keybit); | 1417 | __set_bit(BTN_RIGHT, dev->keybit); |
1417 | 1418 | ||
1418 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) | 1419 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) |
1419 | __set_bit(BTN_MIDDLE, dev->keybit); | 1420 | __set_bit(BTN_MIDDLE, dev->keybit); |
1420 | 1421 | ||
1421 | if (!priv->absolute_mode) { | 1422 | if (!priv->absolute_mode) { |
1422 | /* Relative mode */ | 1423 | /* Relative mode */ |
1423 | __set_bit(EV_REL, dev->evbit); | 1424 | __set_bit(EV_REL, dev->evbit); |
1424 | __set_bit(REL_X, dev->relbit); | 1425 | __set_bit(REL_X, dev->relbit); |
1425 | __set_bit(REL_Y, dev->relbit); | 1426 | __set_bit(REL_Y, dev->relbit); |
1426 | return; | 1427 | return; |
1427 | } | 1428 | } |
1428 | 1429 | ||
1429 | /* Absolute mode */ | 1430 | /* Absolute mode */ |
1430 | __set_bit(EV_ABS, dev->evbit); | 1431 | __set_bit(EV_ABS, dev->evbit); |
1431 | set_abs_position_params(dev, priv, ABS_X, ABS_Y); | 1432 | set_abs_position_params(dev, priv, ABS_X, ABS_Y); |
1432 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 1433 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
1433 | 1434 | ||
1434 | if (cr48_profile_sensor) | 1435 | if (cr48_profile_sensor) |
1435 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); | 1436 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); |
1436 | 1437 | ||
1437 | if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { | 1438 | if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { |
1438 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, | 1439 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, |
1439 | ABS_MT_POSITION_Y); | 1440 | ABS_MT_POSITION_Y); |
1440 | /* Image sensors can report per-contact pressure */ | 1441 | /* Image sensors can report per-contact pressure */ |
1441 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); | 1442 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); |
1442 | input_mt_init_slots(dev, 2, INPUT_MT_POINTER); | 1443 | input_mt_init_slots(dev, 2, INPUT_MT_POINTER); |
1443 | 1444 | ||
1444 | /* Image sensors can signal 4 and 5 finger clicks */ | 1445 | /* Image sensors can signal 4 and 5 finger clicks */ |
1445 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | 1446 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
1446 | __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); | 1447 | __set_bit(BTN_TOOL_QUINTTAP, dev->keybit); |
1447 | } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { | 1448 | } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { |
1448 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, | 1449 | set_abs_position_params(dev, priv, ABS_MT_POSITION_X, |
1449 | ABS_MT_POSITION_Y); | 1450 | ABS_MT_POSITION_Y); |
1450 | /* | 1451 | /* |
1451 | * Profile sensor in CR-48 tracks contacts reasonably well, | 1452 | * Profile sensor in CR-48 tracks contacts reasonably well, |
1452 | * other non-image sensors with AGM use semi-mt. | 1453 | * other non-image sensors with AGM use semi-mt. |
1453 | */ | 1454 | */ |
1454 | input_mt_init_slots(dev, 2, | 1455 | input_mt_init_slots(dev, 2, |
1455 | INPUT_MT_POINTER | | 1456 | INPUT_MT_POINTER | |
1456 | (cr48_profile_sensor ? | 1457 | (cr48_profile_sensor ? |
1457 | INPUT_MT_TRACK : INPUT_MT_SEMI_MT)); | 1458 | INPUT_MT_TRACK : INPUT_MT_SEMI_MT)); |
1458 | } | 1459 | } |
1459 | 1460 | ||
1460 | if (SYN_CAP_PALMDETECT(priv->capabilities)) | 1461 | if (SYN_CAP_PALMDETECT(priv->capabilities)) |
1461 | input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); | 1462 | input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); |
1462 | 1463 | ||
1463 | __set_bit(BTN_TOUCH, dev->keybit); | 1464 | __set_bit(BTN_TOUCH, dev->keybit); |
1464 | __set_bit(BTN_TOOL_FINGER, dev->keybit); | 1465 | __set_bit(BTN_TOOL_FINGER, dev->keybit); |
1465 | 1466 | ||
1466 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { | 1467 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { |
1467 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); | 1468 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); |
1468 | __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); | 1469 | __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); |
1469 | } | 1470 | } |
1470 | 1471 | ||
1471 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities) || | 1472 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities) || |
1472 | SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { | 1473 | SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { |
1473 | __set_bit(BTN_FORWARD, dev->keybit); | 1474 | __set_bit(BTN_FORWARD, dev->keybit); |
1474 | __set_bit(BTN_BACK, dev->keybit); | 1475 | __set_bit(BTN_BACK, dev->keybit); |
1475 | } | 1476 | } |
1476 | 1477 | ||
1477 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) | 1478 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) |
1478 | __set_bit(BTN_0 + i, dev->keybit); | 1479 | __set_bit(BTN_0 + i, dev->keybit); |
1479 | 1480 | ||
1480 | __clear_bit(EV_REL, dev->evbit); | 1481 | __clear_bit(EV_REL, dev->evbit); |
1481 | __clear_bit(REL_X, dev->relbit); | 1482 | __clear_bit(REL_X, dev->relbit); |
1482 | __clear_bit(REL_Y, dev->relbit); | 1483 | __clear_bit(REL_Y, dev->relbit); |
1483 | 1484 | ||
1484 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | 1485 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { |
1485 | __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); | 1486 | __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); |
1486 | if (psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids)) | 1487 | if (psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids)) |
1487 | __set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit); | 1488 | __set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit); |
1488 | /* Clickpads report only left button */ | 1489 | /* Clickpads report only left button */ |
1489 | __clear_bit(BTN_RIGHT, dev->keybit); | 1490 | __clear_bit(BTN_RIGHT, dev->keybit); |
1490 | __clear_bit(BTN_MIDDLE, dev->keybit); | 1491 | __clear_bit(BTN_MIDDLE, dev->keybit); |
1491 | } | 1492 | } |
1492 | } | 1493 | } |
1493 | 1494 | ||
1494 | static ssize_t synaptics_show_disable_gesture(struct psmouse *psmouse, | 1495 | static ssize_t synaptics_show_disable_gesture(struct psmouse *psmouse, |
1495 | void *data, char *buf) | 1496 | void *data, char *buf) |
1496 | { | 1497 | { |
1497 | struct synaptics_data *priv = psmouse->private; | 1498 | struct synaptics_data *priv = psmouse->private; |
1498 | 1499 | ||
1499 | return sprintf(buf, "%c\n", priv->disable_gesture ? '1' : '0'); | 1500 | return sprintf(buf, "%c\n", priv->disable_gesture ? '1' : '0'); |
1500 | } | 1501 | } |
1501 | 1502 | ||
1502 | static ssize_t synaptics_set_disable_gesture(struct psmouse *psmouse, | 1503 | static ssize_t synaptics_set_disable_gesture(struct psmouse *psmouse, |
1503 | void *data, const char *buf, | 1504 | void *data, const char *buf, |
1504 | size_t len) | 1505 | size_t len) |
1505 | { | 1506 | { |
1506 | struct synaptics_data *priv = psmouse->private; | 1507 | struct synaptics_data *priv = psmouse->private; |
1507 | unsigned int value; | 1508 | unsigned int value; |
1508 | int err; | 1509 | int err; |
1509 | 1510 | ||
1510 | err = kstrtouint(buf, 10, &value); | 1511 | err = kstrtouint(buf, 10, &value); |
1511 | if (err) | 1512 | if (err) |
1512 | return err; | 1513 | return err; |
1513 | 1514 | ||
1514 | if (value > 1) | 1515 | if (value > 1) |
1515 | return -EINVAL; | 1516 | return -EINVAL; |
1516 | 1517 | ||
1517 | if (value == priv->disable_gesture) | 1518 | if (value == priv->disable_gesture) |
1518 | return len; | 1519 | return len; |
1519 | 1520 | ||
1520 | priv->disable_gesture = value; | 1521 | priv->disable_gesture = value; |
1521 | if (value) | 1522 | if (value) |
1522 | priv->mode |= SYN_BIT_DISABLE_GESTURE; | 1523 | priv->mode |= SYN_BIT_DISABLE_GESTURE; |
1523 | else | 1524 | else |
1524 | priv->mode &= ~SYN_BIT_DISABLE_GESTURE; | 1525 | priv->mode &= ~SYN_BIT_DISABLE_GESTURE; |
1525 | 1526 | ||
1526 | if (synaptics_mode_cmd(psmouse, priv->mode)) | 1527 | if (synaptics_mode_cmd(psmouse, priv->mode)) |
1527 | return -EIO; | 1528 | return -EIO; |
1528 | 1529 | ||
1529 | return len; | 1530 | return len; |
1530 | } | 1531 | } |
1531 | 1532 | ||
1532 | PSMOUSE_DEFINE_ATTR(disable_gesture, S_IWUSR | S_IRUGO, NULL, | 1533 | PSMOUSE_DEFINE_ATTR(disable_gesture, S_IWUSR | S_IRUGO, NULL, |
1533 | synaptics_show_disable_gesture, | 1534 | synaptics_show_disable_gesture, |
1534 | synaptics_set_disable_gesture); | 1535 | synaptics_set_disable_gesture); |
1535 | 1536 | ||
1536 | static void synaptics_disconnect(struct psmouse *psmouse) | 1537 | static void synaptics_disconnect(struct psmouse *psmouse) |
1537 | { | 1538 | { |
1538 | struct synaptics_data *priv = psmouse->private; | 1539 | struct synaptics_data *priv = psmouse->private; |
1539 | 1540 | ||
1540 | if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity)) | 1541 | if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity)) |
1541 | device_remove_file(&psmouse->ps2dev.serio->dev, | 1542 | device_remove_file(&psmouse->ps2dev.serio->dev, |
1542 | &psmouse_attr_disable_gesture.dattr); | 1543 | &psmouse_attr_disable_gesture.dattr); |
1543 | 1544 | ||
1544 | synaptics_reset(psmouse); | 1545 | synaptics_reset(psmouse); |
1545 | kfree(priv); | 1546 | kfree(priv); |
1546 | psmouse->private = NULL; | 1547 | psmouse->private = NULL; |
1547 | } | 1548 | } |
1548 | 1549 | ||
1549 | static int synaptics_reconnect(struct psmouse *psmouse) | 1550 | static int synaptics_reconnect(struct psmouse *psmouse) |
1550 | { | 1551 | { |
1551 | struct synaptics_data *priv = psmouse->private; | 1552 | struct synaptics_data *priv = psmouse->private; |
1552 | struct synaptics_data old_priv = *priv; | 1553 | struct synaptics_data old_priv = *priv; |
1553 | unsigned char param[2]; | 1554 | unsigned char param[2]; |
1554 | int retry = 0; | 1555 | int retry = 0; |
1555 | int error; | 1556 | int error; |
1556 | 1557 | ||
1557 | do { | 1558 | do { |
1558 | psmouse_reset(psmouse); | 1559 | psmouse_reset(psmouse); |
1559 | if (retry) { | 1560 | if (retry) { |
1560 | /* | 1561 | /* |
1561 | * On some boxes, right after resuming, the touchpad | 1562 | * On some boxes, right after resuming, the touchpad |
1562 | * needs some time to finish initializing (I assume | 1563 | * needs some time to finish initializing (I assume |
1563 | * it needs time to calibrate) and start responding | 1564 | * it needs time to calibrate) and start responding |
1564 | * to Synaptics-specific queries, so let's wait a | 1565 | * to Synaptics-specific queries, so let's wait a |
1565 | * bit. | 1566 | * bit. |
1566 | */ | 1567 | */ |
1567 | ssleep(1); | 1568 | ssleep(1); |
1568 | } | 1569 | } |
1569 | ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETID); | 1570 | ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETID); |
1570 | error = synaptics_detect(psmouse, 0); | 1571 | error = synaptics_detect(psmouse, 0); |
1571 | } while (error && ++retry < 3); | 1572 | } while (error && ++retry < 3); |
1572 | 1573 | ||
1573 | if (error) | 1574 | if (error) |
1574 | return -1; | 1575 | return -1; |
1575 | 1576 | ||
1576 | if (retry > 1) | 1577 | if (retry > 1) |
1577 | psmouse_dbg(psmouse, "reconnected after %d tries\n", retry); | 1578 | psmouse_dbg(psmouse, "reconnected after %d tries\n", retry); |
1578 | 1579 | ||
1579 | if (synaptics_query_hardware(psmouse)) { | 1580 | if (synaptics_query_hardware(psmouse)) { |
1580 | psmouse_err(psmouse, "Unable to query device.\n"); | 1581 | psmouse_err(psmouse, "Unable to query device.\n"); |
1581 | return -1; | 1582 | return -1; |
1582 | } | 1583 | } |
1583 | 1584 | ||
1584 | if (synaptics_set_mode(psmouse)) { | 1585 | if (synaptics_set_mode(psmouse)) { |
1585 | psmouse_err(psmouse, "Unable to initialize device.\n"); | 1586 | psmouse_err(psmouse, "Unable to initialize device.\n"); |
1586 | return -1; | 1587 | return -1; |
1587 | } | 1588 | } |
1588 | 1589 | ||
1589 | if (old_priv.identity != priv->identity || | 1590 | if (old_priv.identity != priv->identity || |
1590 | old_priv.model_id != priv->model_id || | 1591 | old_priv.model_id != priv->model_id || |
1591 | old_priv.capabilities != priv->capabilities || | 1592 | old_priv.capabilities != priv->capabilities || |
1592 | old_priv.ext_cap != priv->ext_cap) { | 1593 | old_priv.ext_cap != priv->ext_cap) { |
1593 | psmouse_err(psmouse, | 1594 | psmouse_err(psmouse, |
1594 | "hardware appears to be different: id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n", | 1595 | "hardware appears to be different: id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n", |
1595 | old_priv.identity, priv->identity, | 1596 | old_priv.identity, priv->identity, |
1596 | old_priv.model_id, priv->model_id, | 1597 | old_priv.model_id, priv->model_id, |
1597 | old_priv.capabilities, priv->capabilities, | 1598 | old_priv.capabilities, priv->capabilities, |
1598 | old_priv.ext_cap, priv->ext_cap); | 1599 | old_priv.ext_cap, priv->ext_cap); |
1599 | return -1; | 1600 | return -1; |
1600 | } | 1601 | } |
1601 | 1602 | ||
1602 | return 0; | 1603 | return 0; |
1603 | } | 1604 | } |
1604 | 1605 | ||
1605 | static bool impaired_toshiba_kbc; | 1606 | static bool impaired_toshiba_kbc; |
1606 | 1607 | ||
1607 | static const struct dmi_system_id toshiba_dmi_table[] __initconst = { | 1608 | static const struct dmi_system_id toshiba_dmi_table[] __initconst = { |
1608 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) | 1609 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) |
1609 | { | 1610 | { |
1610 | /* Toshiba Satellite */ | 1611 | /* Toshiba Satellite */ |
1611 | .matches = { | 1612 | .matches = { |
1612 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 1613 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
1613 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"), | 1614 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"), |
1614 | }, | 1615 | }, |
1615 | }, | 1616 | }, |
1616 | { | 1617 | { |
1617 | /* Toshiba Dynabook */ | 1618 | /* Toshiba Dynabook */ |
1618 | .matches = { | 1619 | .matches = { |
1619 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 1620 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
1620 | DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"), | 1621 | DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"), |
1621 | }, | 1622 | }, |
1622 | }, | 1623 | }, |
1623 | { | 1624 | { |
1624 | /* Toshiba Portege M300 */ | 1625 | /* Toshiba Portege M300 */ |
1625 | .matches = { | 1626 | .matches = { |
1626 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 1627 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
1627 | DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"), | 1628 | DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"), |
1628 | }, | 1629 | }, |
1629 | 1630 | ||
1630 | }, | 1631 | }, |
1631 | { | 1632 | { |
1632 | /* Toshiba Portege M300 */ | 1633 | /* Toshiba Portege M300 */ |
1633 | .matches = { | 1634 | .matches = { |
1634 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 1635 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
1635 | DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"), | 1636 | DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"), |
1636 | DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"), | 1637 | DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"), |
1637 | }, | 1638 | }, |
1638 | 1639 | ||
1639 | }, | 1640 | }, |
1640 | #endif | 1641 | #endif |
1641 | { } | 1642 | { } |
1642 | }; | 1643 | }; |
1643 | 1644 | ||
1644 | static bool broken_olpc_ec; | 1645 | static bool broken_olpc_ec; |
1645 | 1646 | ||
1646 | static const struct dmi_system_id olpc_dmi_table[] __initconst = { | 1647 | static const struct dmi_system_id olpc_dmi_table[] __initconst = { |
1647 | #if defined(CONFIG_DMI) && defined(CONFIG_OLPC) | 1648 | #if defined(CONFIG_DMI) && defined(CONFIG_OLPC) |
1648 | { | 1649 | { |
1649 | /* OLPC XO-1 or XO-1.5 */ | 1650 | /* OLPC XO-1 or XO-1.5 */ |
1650 | .matches = { | 1651 | .matches = { |
1651 | DMI_MATCH(DMI_SYS_VENDOR, "OLPC"), | 1652 | DMI_MATCH(DMI_SYS_VENDOR, "OLPC"), |
1652 | DMI_MATCH(DMI_PRODUCT_NAME, "XO"), | 1653 | DMI_MATCH(DMI_PRODUCT_NAME, "XO"), |
1653 | }, | 1654 | }, |
1654 | }, | 1655 | }, |
1655 | #endif | 1656 | #endif |
1656 | { } | 1657 | { } |
1657 | }; | 1658 | }; |
1658 | 1659 | ||
1659 | static const struct dmi_system_id __initconst cr48_dmi_table[] = { | 1660 | static const struct dmi_system_id __initconst cr48_dmi_table[] = { |
1660 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) | 1661 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) |
1661 | { | 1662 | { |
1662 | /* Cr-48 Chromebook (Codename Mario) */ | 1663 | /* Cr-48 Chromebook (Codename Mario) */ |
1663 | .matches = { | 1664 | .matches = { |
1664 | DMI_MATCH(DMI_SYS_VENDOR, "IEC"), | 1665 | DMI_MATCH(DMI_SYS_VENDOR, "IEC"), |
1665 | DMI_MATCH(DMI_PRODUCT_NAME, "Mario"), | 1666 | DMI_MATCH(DMI_PRODUCT_NAME, "Mario"), |
1666 | }, | 1667 | }, |
1667 | }, | 1668 | }, |
1668 | #endif | 1669 | #endif |
1669 | { } | 1670 | { } |
1670 | }; | 1671 | }; |
1671 | 1672 | ||
1672 | static const struct dmi_system_id forcepad_dmi_table[] __initconst = { | 1673 | static const struct dmi_system_id forcepad_dmi_table[] __initconst = { |
1673 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) | 1674 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) |
1674 | { | 1675 | { |
1675 | .matches = { | 1676 | .matches = { |
1676 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 1677 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
1677 | DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook Folio 1040 G1"), | 1678 | DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook Folio 1040 G1"), |
1678 | }, | 1679 | }, |
1679 | }, | 1680 | }, |
1680 | #endif | 1681 | #endif |
1681 | { } | 1682 | { } |
1682 | }; | 1683 | }; |
1683 | 1684 | ||
1684 | void __init synaptics_module_init(void) | 1685 | void __init synaptics_module_init(void) |
1685 | { | 1686 | { |
1686 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); | 1687 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); |
1687 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); | 1688 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); |
1688 | cr48_profile_sensor = dmi_check_system(cr48_dmi_table); | 1689 | cr48_profile_sensor = dmi_check_system(cr48_dmi_table); |
1689 | 1690 | ||
1690 | /* | 1691 | /* |
1691 | * Unfortunately ForcePad capability is not exported over PS/2, | 1692 | * Unfortunately ForcePad capability is not exported over PS/2, |
1692 | * so we have to resort to checking DMI. | 1693 | * so we have to resort to checking DMI. |
1693 | */ | 1694 | */ |
1694 | is_forcepad = dmi_check_system(forcepad_dmi_table); | 1695 | is_forcepad = dmi_check_system(forcepad_dmi_table); |
1695 | } | 1696 | } |
1696 | 1697 | ||
1697 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) | 1698 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) |
1698 | { | 1699 | { |
1699 | struct synaptics_data *priv; | 1700 | struct synaptics_data *priv; |
1700 | int err = -1; | 1701 | int err = -1; |
1701 | 1702 | ||
1702 | /* | 1703 | /* |
1703 | * The OLPC XO has issues with Synaptics' absolute mode; the constant | 1704 | * The OLPC XO has issues with Synaptics' absolute mode; the constant |
1704 | * packet spew overloads the EC such that key presses on the keyboard | 1705 | * packet spew overloads the EC such that key presses on the keyboard |
1705 | * are missed. Given that, don't even attempt to use Absolute mode. | 1706 | * are missed. Given that, don't even attempt to use Absolute mode. |
1706 | * Relative mode seems to work just fine. | 1707 | * Relative mode seems to work just fine. |
1707 | */ | 1708 | */ |
1708 | if (absolute_mode && broken_olpc_ec) { | 1709 | if (absolute_mode && broken_olpc_ec) { |
1709 | psmouse_info(psmouse, | 1710 | psmouse_info(psmouse, |
1710 | "OLPC XO detected, not enabling Synaptics protocol.\n"); | 1711 | "OLPC XO detected, not enabling Synaptics protocol.\n"); |
1711 | return -ENODEV; | 1712 | return -ENODEV; |
1712 | } | 1713 | } |
1713 | 1714 | ||
1714 | psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); | 1715 | psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); |
1715 | if (!priv) | 1716 | if (!priv) |
1716 | return -ENOMEM; | 1717 | return -ENOMEM; |
1717 | 1718 | ||
1718 | psmouse_reset(psmouse); | 1719 | psmouse_reset(psmouse); |
1719 | 1720 | ||
1720 | if (synaptics_query_hardware(psmouse)) { | 1721 | if (synaptics_query_hardware(psmouse)) { |
1721 | psmouse_err(psmouse, "Unable to query device.\n"); | 1722 | psmouse_err(psmouse, "Unable to query device.\n"); |
1722 | goto init_fail; | 1723 | goto init_fail; |
1723 | } | 1724 | } |
1724 | 1725 | ||
1725 | priv->absolute_mode = absolute_mode; | 1726 | priv->absolute_mode = absolute_mode; |
1726 | if (SYN_ID_DISGEST_SUPPORTED(priv->identity)) | 1727 | if (SYN_ID_DISGEST_SUPPORTED(priv->identity)) |
1727 | priv->disable_gesture = true; | 1728 | priv->disable_gesture = true; |
1728 | 1729 | ||
1729 | if (synaptics_set_mode(psmouse)) { | 1730 | if (synaptics_set_mode(psmouse)) { |
1730 | psmouse_err(psmouse, "Unable to initialize device.\n"); | 1731 | psmouse_err(psmouse, "Unable to initialize device.\n"); |
1731 | goto init_fail; | 1732 | goto init_fail; |
1732 | } | 1733 | } |
1733 | 1734 | ||
1734 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; | 1735 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; |
1735 | 1736 | ||
1736 | psmouse_info(psmouse, | 1737 | psmouse_info(psmouse, |
1737 | "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx, board id: %lu, fw id: %lu\n", | 1738 | "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx, board id: %lu, fw id: %lu\n", |
1738 | SYN_ID_MODEL(priv->identity), | 1739 | SYN_ID_MODEL(priv->identity), |
1739 | SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), | 1740 | SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), |
1740 | priv->model_id, | 1741 | priv->model_id, |
1741 | priv->capabilities, priv->ext_cap, priv->ext_cap_0c, | 1742 | priv->capabilities, priv->ext_cap, priv->ext_cap_0c, |
1742 | priv->board_id, priv->firmware_id); | 1743 | priv->board_id, priv->firmware_id); |
1743 | 1744 | ||
1744 | set_input_params(psmouse, priv); | 1745 | set_input_params(psmouse, priv); |
1745 | 1746 | ||
1746 | /* | 1747 | /* |
1747 | * Encode touchpad model so that it can be used to set | 1748 | * Encode touchpad model so that it can be used to set |
1748 | * input device->id.version and be visible to userspace. | 1749 | * input device->id.version and be visible to userspace. |
1749 | * Because version is __u16 we have to drop something. | 1750 | * Because version is __u16 we have to drop something. |
1750 | * Hardware info bits seem to be good candidates as they | 1751 | * Hardware info bits seem to be good candidates as they |
1751 | * are documented to be for Synaptics corp. internal use. | 1752 | * are documented to be for Synaptics corp. internal use. |
1752 | */ | 1753 | */ |
1753 | psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) | | 1754 | psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) | |
1754 | (priv->model_id & 0x000000ff); | 1755 | (priv->model_id & 0x000000ff); |
1755 | 1756 | ||
1756 | if (absolute_mode) { | 1757 | if (absolute_mode) { |
1757 | psmouse->protocol_handler = synaptics_process_byte; | 1758 | psmouse->protocol_handler = synaptics_process_byte; |
1758 | psmouse->pktsize = 6; | 1759 | psmouse->pktsize = 6; |
1759 | } else { | 1760 | } else { |
1760 | /* Relative mode follows standard PS/2 mouse protocol */ | 1761 | /* Relative mode follows standard PS/2 mouse protocol */ |
1761 | psmouse->protocol_handler = psmouse_process_byte; | 1762 | psmouse->protocol_handler = psmouse_process_byte; |
1762 | psmouse->pktsize = 3; | 1763 | psmouse->pktsize = 3; |
1763 | } | 1764 | } |
1764 | 1765 | ||
1765 | psmouse->set_rate = synaptics_set_rate; | 1766 | psmouse->set_rate = synaptics_set_rate; |
1766 | psmouse->disconnect = synaptics_disconnect; | 1767 | psmouse->disconnect = synaptics_disconnect; |
1767 | psmouse->reconnect = synaptics_reconnect; | 1768 | psmouse->reconnect = synaptics_reconnect; |
1768 | psmouse->cleanup = synaptics_reset; | 1769 | psmouse->cleanup = synaptics_reset; |
1769 | /* Synaptics can usually stay in sync without extra help */ | 1770 | /* Synaptics can usually stay in sync without extra help */ |
1770 | psmouse->resync_time = 0; | 1771 | psmouse->resync_time = 0; |
1771 | 1772 | ||
1772 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) | 1773 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) |
1773 | synaptics_pt_create(psmouse); | 1774 | synaptics_pt_create(psmouse); |
1774 | 1775 | ||
1775 | /* | 1776 | /* |
1776 | * Toshiba's KBC seems to have trouble handling data from | 1777 | * Toshiba's KBC seems to have trouble handling data from |
1777 | * Synaptics at full rate. Switch to a lower rate (roughly | 1778 | * Synaptics at full rate. Switch to a lower rate (roughly |
1778 | * the same rate as a standard PS/2 mouse). | 1779 | * the same rate as a standard PS/2 mouse). |
1779 | */ | 1780 | */ |
1780 | if (psmouse->rate >= 80 && impaired_toshiba_kbc) { | 1781 | if (psmouse->rate >= 80 && impaired_toshiba_kbc) { |
1781 | psmouse_info(psmouse, | 1782 | psmouse_info(psmouse, |
1782 | "Toshiba %s detected, limiting rate to 40pps.\n", | 1783 | "Toshiba %s detected, limiting rate to 40pps.\n", |
1783 | dmi_get_system_info(DMI_PRODUCT_NAME)); | 1784 | dmi_get_system_info(DMI_PRODUCT_NAME)); |
1784 | psmouse->rate = 40; | 1785 | psmouse->rate = 40; |
1785 | } | 1786 | } |
1786 | 1787 | ||
1787 | if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity)) { | 1788 | if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity)) { |
1788 | err = device_create_file(&psmouse->ps2dev.serio->dev, | 1789 | err = device_create_file(&psmouse->ps2dev.serio->dev, |
1789 | &psmouse_attr_disable_gesture.dattr); | 1790 | &psmouse_attr_disable_gesture.dattr); |
1790 | if (err) { | 1791 | if (err) { |
1791 | psmouse_err(psmouse, | 1792 | psmouse_err(psmouse, |
1792 | "Failed to create disable_gesture attribute (%d)", | 1793 | "Failed to create disable_gesture attribute (%d)", |
1793 | err); | 1794 | err); |
1794 | goto init_fail; | 1795 | goto init_fail; |
1795 | } | 1796 | } |
1796 | } | 1797 | } |
1797 | 1798 | ||
1798 | return 0; | 1799 | return 0; |
1799 | 1800 | ||
1800 | init_fail: | 1801 | init_fail: |
1801 | kfree(priv); | 1802 | kfree(priv); |
1802 | return err; | 1803 | return err; |
1803 | } | 1804 | } |
1804 | 1805 | ||
1805 | int synaptics_init(struct psmouse *psmouse) | 1806 | int synaptics_init(struct psmouse *psmouse) |
1806 | { | 1807 | { |
1807 | return __synaptics_init(psmouse, true); | 1808 | return __synaptics_init(psmouse, true); |
1808 | } | 1809 | } |
1809 | 1810 | ||
1810 | int synaptics_init_relative(struct psmouse *psmouse) | 1811 | int synaptics_init_relative(struct psmouse *psmouse) |
1811 | { | 1812 | { |
1812 | return __synaptics_init(psmouse, false); | 1813 | return __synaptics_init(psmouse, false); |
1813 | } | 1814 | } |
1814 | 1815 | ||
1815 | bool synaptics_supported(void) | 1816 | bool synaptics_supported(void) |
1816 | { | 1817 | { |
1817 | return true; | 1818 | return true; |
1818 | } | 1819 | } |
1819 | 1820 | ||
1820 | #else /* CONFIG_MOUSE_PS2_SYNAPTICS */ | 1821 | #else /* CONFIG_MOUSE_PS2_SYNAPTICS */ |
1821 | 1822 | ||
1822 | void __init synaptics_module_init(void) | 1823 | void __init synaptics_module_init(void) |
1823 | { | 1824 | { |
1824 | } | 1825 | } |
1825 | 1826 | ||
1826 | int synaptics_init(struct psmouse *psmouse) | 1827 | int synaptics_init(struct psmouse *psmouse) |
1827 | { | 1828 | { |
1828 | return -ENOSYS; | 1829 | return -ENOSYS; |
1829 | } | 1830 | } |
1830 | 1831 | ||
1831 | bool synaptics_supported(void) | 1832 | bool synaptics_supported(void) |
1832 | { | 1833 | { |
1833 | return false; | 1834 | return false; |
1834 | } | 1835 | } |
1835 | 1836 | ||
1836 | #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ | 1837 | #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ |
1837 | 1838 |