Bug Summary

File:dev/pckbc/pms.c
Warning:line 1723, column 15
The left operand of '&' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name pms.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/pckbc/pms.c
1/* $OpenBSD: pms.c,v 1.95 2020/10/23 22:06:27 bru Exp $ */
2/* $NetBSD: psm.c,v 1.11 2000/06/05 22:20:57 sommerfeld Exp $ */
3
4/*-
5 * Copyright (c) 1994 Charles M. Hannum.
6 * Copyright (c) 1992, 1993 Erik Forsberg.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18 * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/param.h>
28#include <sys/systm.h>
29#include <sys/rwlock.h>
30#include <sys/device.h>
31#include <sys/ioctl.h>
32#include <sys/malloc.h>
33#include <sys/task.h>
34#include <sys/timeout.h>
35
36#include <machine/bus.h>
37
38#include <dev/ic/pckbcvar.h>
39
40#include <dev/pckbc/pmsreg.h>
41
42#include <dev/wscons/wsconsio.h>
43#include <dev/wscons/wsmousevar.h>
44
45#if defined(__i386__) || defined(__amd64__1)
46#include "acpi.h"
47#endif
48
49#if !defined(SMALL_KERNEL) && NACPI1 > 0
50extern int mouse_has_softbtn;
51#else
52int mouse_has_softbtn;
53#endif
54
55#ifdef DEBUG
56#define DPRINTF(x...) do { printf(x); } while (0);
57#else
58#define DPRINTF(x...)
59#endif
60
61#define DEVNAME(sc)((sc)->sc_dev.dv_xname) ((sc)->sc_dev.dv_xname)
62
63#define WSMOUSE_BUTTON(x)(1 << ((x) - 1)) (1 << ((x) - 1))
64
65struct pms_softc;
66
67struct pms_protocol {
68 int type;
69#define PMS_STANDARD0 0
70#define PMS_INTELLI1 1
71#define PMS_SYNAPTICS2 2
72#define PMS_ALPS3 3
73#define PMS_ELANTECH_V14 4
74#define PMS_ELANTECH_V25 5
75#define PMS_ELANTECH_V36 6
76#define PMS_ELANTECH_V47 7
77 u_int packetsize;
78 int (*enable)(struct pms_softc *);
79 int (*ioctl)(struct pms_softc *, u_long, caddr_t, int, struct proc *);
80 int (*sync)(struct pms_softc *, int);
81 void (*proc)(struct pms_softc *);
82 void (*disable)(struct pms_softc *);
83};
84
85struct synaptics_softc {
86 int identify;
87 int capabilities, ext_capabilities, ext2_capabilities;
88 int model, ext_model;
89 int modes;
90
91 int mode;
92
93 int mask;
94#define SYNAPTICS_MASK_NEWABS_STRICT0xc8 0xc8
95#define SYNAPTICS_MASK_NEWABS_RELAXED0xc0 0xc0
96#define SYNAPTICS_VALID_NEWABS_FIRST0x80 0x80
97#define SYNAPTICS_VALID_NEWABS_NEXT0xc0 0xc0
98
99 u_int sec_buttons;
100
101#define SYNAPTICS_PRESSURE_HI30 30
102#define SYNAPTICS_PRESSURE_LO25 25
103#define SYNAPTICS_PRESSURE30 SYNAPTICS_PRESSURE_HI30
104#define SYNAPTICS_SCALE4 4
105#define SYNAPTICS_MAX_FINGERS3 3
106};
107
108struct alps_softc {
109 int model;
110#define ALPS_GLIDEPOINT(1 << 1) (1 << 1)
111#define ALPS_DUALPOINT(1 << 2) (1 << 2)
112#define ALPS_PASSTHROUGH(1 << 3) (1 << 3)
113#define ALPS_INTERLEAVED(1 << 4) (1 << 4)
114
115 int mask;
116 int version;
117
118 u_int gesture;
119
120 u_int sec_buttons; /* trackpoint */
121
122 int old_x, old_y;
123#define ALPS_PRESSURE40 40
124};
125
126struct elantech_softc {
127 int flags;
128#define ELANTECH_F_REPORTS_PRESSURE0x01 0x01
129#define ELANTECH_F_HAS_ROCKER0x02 0x02
130#define ELANTECH_F_2FINGER_PACKET0x04 0x04
131#define ELANTECH_F_HW_V1_OLD0x08 0x08
132#define ELANTECH_F_CRC_ENABLED0x10 0x10
133#define ELANTECH_F_TRACKPOINT0x20 0x20
134 int fw_version;
135
136 u_int mt_slots;
137
138 int width;
139
140 u_char parity[256];
141 u_char p1, p2, p3;
142
143 int max_x, max_y;
144 int old_x, old_y;
145 int initial_pkt;
146};
147#define ELANTECH_IS_CLICKPAD(sc)(((sc)->elantech->fw_version & 0x1000) != 0) (((sc)->elantech->fw_version & 0x1000) != 0)
148
149struct pms_softc { /* driver status information */
150 struct device sc_dev;
151
152 pckbc_tag_t sc_kbctag;
153
154 int sc_state;
155#define PMS_STATE_DISABLED0 0
156#define PMS_STATE_ENABLED1 1
157#define PMS_STATE_SUSPENDED2 2
158
159 struct rwlock sc_state_lock;
160
161 int sc_dev_enable;
162#define PMS_DEV_IGNORE0x00 0x00
163#define PMS_DEV_PRIMARY0x01 0x01
164#define PMS_DEV_SECONDARY0x02 0x02
165
166 struct task sc_rsttask;
167 struct timeout sc_rsttimo;
168 int sc_rststate;
169#define PMS_RST_COMMENCE0x01 0x01
170#define PMS_RST_ANNOUNCED0x02 0x02
171
172 int poll;
173 int inputstate;
174
175 const struct pms_protocol *protocol;
176 struct synaptics_softc *synaptics;
177 struct alps_softc *alps;
178 struct elantech_softc *elantech;
179
180 u_char packet[8];
181
182 struct device *sc_wsmousedev;
183 struct device *sc_sec_wsmousedev;
184};
185
186static const u_int butmap[8] = {
187 0,
188 WSMOUSE_BUTTON(1)(1 << ((1) - 1)),
189 WSMOUSE_BUTTON(3)(1 << ((3) - 1)),
190 WSMOUSE_BUTTON(1)(1 << ((1) - 1)) | WSMOUSE_BUTTON(3)(1 << ((3) - 1)),
191 WSMOUSE_BUTTON(2)(1 << ((2) - 1)),
192 WSMOUSE_BUTTON(1)(1 << ((1) - 1)) | WSMOUSE_BUTTON(2)(1 << ((2) - 1)),
193 WSMOUSE_BUTTON(2)(1 << ((2) - 1)) | WSMOUSE_BUTTON(3)(1 << ((3) - 1)),
194 WSMOUSE_BUTTON(1)(1 << ((1) - 1)) | WSMOUSE_BUTTON(2)(1 << ((2) - 1)) | WSMOUSE_BUTTON(3)(1 << ((3) - 1))
195};
196
197static const struct alps_model {
198 int version;
199 int mask;
200 int model;
201} alps_models[] = {
202 { 0x2021, 0xf8, ALPS_DUALPOINT(1 << 2) | ALPS_PASSTHROUGH(1 << 3) },
203 { 0x2221, 0xf8, ALPS_DUALPOINT(1 << 2) | ALPS_PASSTHROUGH(1 << 3) },
204 { 0x2222, 0xff, ALPS_DUALPOINT(1 << 2) | ALPS_PASSTHROUGH(1 << 3) },
205 { 0x3222, 0xf8, ALPS_DUALPOINT(1 << 2) | ALPS_PASSTHROUGH(1 << 3) },
206 { 0x5212, 0xff, ALPS_DUALPOINT(1 << 2) | ALPS_PASSTHROUGH(1 << 3) | ALPS_INTERLEAVED(1 << 4) },
207 { 0x5321, 0xf8, ALPS_GLIDEPOINT(1 << 1) },
208 { 0x5322, 0xf8, ALPS_GLIDEPOINT(1 << 1) },
209 { 0x603b, 0xf8, ALPS_GLIDEPOINT(1 << 1) },
210 { 0x6222, 0xcf, ALPS_DUALPOINT(1 << 2) | ALPS_PASSTHROUGH(1 << 3) | ALPS_INTERLEAVED(1 << 4) },
211 { 0x6321, 0xf8, ALPS_GLIDEPOINT(1 << 1) },
212 { 0x6322, 0xf8, ALPS_GLIDEPOINT(1 << 1) },
213 { 0x6323, 0xf8, ALPS_GLIDEPOINT(1 << 1) },
214 { 0x6324, 0x8f, ALPS_GLIDEPOINT(1 << 1) },
215 { 0x6325, 0xef, ALPS_GLIDEPOINT(1 << 1) },
216 { 0x6326, 0xf8, ALPS_GLIDEPOINT(1 << 1) },
217 { 0x7301, 0xf8, ALPS_DUALPOINT(1 << 2) },
218 { 0x7321, 0xf8, ALPS_GLIDEPOINT(1 << 1) },
219 { 0x7322, 0xf8, ALPS_GLIDEPOINT(1 << 1) },
220 { 0x7325, 0xcf, ALPS_GLIDEPOINT(1 << 1) },
221#if 0
222 /*
223 * This model has a clitpad sending almost compatible PS2
224 * packets but not compatible enough to be used with the
225 * ALPS protocol.
226 */
227 { 0x633b, 0xf8, ALPS_DUALPOINT(1 << 2) | ALPS_PASSTHROUGH(1 << 3) },
228
229 { 0x7326, 0, 0 }, /* XXX Uses unknown v3 protocol */
230
231 { 0x7331, 0x8f, ALPS_DUALPOINT(1 << 2) }, /* not supported */
232#endif
233};
234
235static struct wsmouse_param synaptics_params[] = {
236 { WSMOUSECFG_PRESSURE_LO, SYNAPTICS_PRESSURE_LO25 },
237 { WSMOUSECFG_PRESSURE_HI, SYNAPTICS_PRESSURE_HI30 }
238};
239
240static struct wsmouse_param alps_params[] = {
241 { WSMOUSECFG_SMOOTHING, 3 }
242};
243
244int pmsprobe(struct device *, void *, void *);
245void pmsattach(struct device *, struct device *, void *);
246int pmsactivate(struct device *, int);
247
248void pmsinput(void *, int);
249
250int pms_change_state(struct pms_softc *, int, int);
251
252int pms_ioctl(void *, u_long, caddr_t, int, struct proc *);
253int pms_enable(void *);
254void pms_disable(void *);
255
256int pms_sec_ioctl(void *, u_long, caddr_t, int, struct proc *);
257int pms_sec_enable(void *);
258void pms_sec_disable(void *);
259
260int pms_cmd(struct pms_softc *, u_char *, int, u_char *, int);
261int pms_spec_cmd(struct pms_softc *, int);
262int pms_get_devid(struct pms_softc *, u_char *);
263int pms_get_status(struct pms_softc *, u_char *);
264int pms_set_rate(struct pms_softc *, int);
265int pms_set_resolution(struct pms_softc *, int);
266int pms_set_scaling(struct pms_softc *, int);
267int pms_reset(struct pms_softc *);
268int pms_dev_enable(struct pms_softc *);
269int pms_dev_disable(struct pms_softc *);
270void pms_protocol_lookup(struct pms_softc *);
271void pms_reset_detect(struct pms_softc *, int);
272void pms_reset_task(void *);
273void pms_reset_timo(void *);
274
275int pms_enable_intelli(struct pms_softc *);
276
277int pms_ioctl_mouse(struct pms_softc *, u_long, caddr_t, int, struct proc *);
278int pms_sync_mouse(struct pms_softc *, int);
279void pms_proc_mouse(struct pms_softc *);
280
281int pms_enable_synaptics(struct pms_softc *);
282int pms_ioctl_synaptics(struct pms_softc *, u_long, caddr_t, int, struct proc *);
283int pms_sync_synaptics(struct pms_softc *, int);
284void pms_proc_synaptics(struct pms_softc *);
285void pms_disable_synaptics(struct pms_softc *);
286
287int pms_enable_alps(struct pms_softc *);
288int pms_ioctl_alps(struct pms_softc *, u_long, caddr_t, int, struct proc *);
289int pms_sync_alps(struct pms_softc *, int);
290void pms_proc_alps(struct pms_softc *);
291
292int pms_enable_elantech_v1(struct pms_softc *);
293int pms_enable_elantech_v2(struct pms_softc *);
294int pms_enable_elantech_v3(struct pms_softc *);
295int pms_enable_elantech_v4(struct pms_softc *);
296int pms_ioctl_elantech(struct pms_softc *, u_long, caddr_t, int,
297 struct proc *);
298int pms_sync_elantech_v1(struct pms_softc *, int);
299int pms_sync_elantech_v2(struct pms_softc *, int);
300int pms_sync_elantech_v3(struct pms_softc *, int);
301int pms_sync_elantech_v4(struct pms_softc *, int);
302void pms_proc_elantech_v1(struct pms_softc *);
303void pms_proc_elantech_v2(struct pms_softc *);
304void pms_proc_elantech_v3(struct pms_softc *);
305void pms_proc_elantech_v4(struct pms_softc *);
306
307int synaptics_knock(struct pms_softc *);
308int synaptics_set_mode(struct pms_softc *, int, int);
309int synaptics_query(struct pms_softc *, int, int *);
310int synaptics_get_hwinfo(struct pms_softc *);
311void synaptics_sec_proc(struct pms_softc *);
312
313int alps_sec_proc(struct pms_softc *);
314int alps_get_hwinfo(struct pms_softc *);
315
316int elantech_knock(struct pms_softc *);
317int elantech_get_hwinfo_v1(struct pms_softc *);
318int elantech_get_hwinfo_v2(struct pms_softc *);
319int elantech_get_hwinfo_v3(struct pms_softc *);
320int elantech_get_hwinfo_v4(struct pms_softc *);
321int elantech_ps2_cmd(struct pms_softc *, u_char);
322int elantech_set_absolute_mode_v1(struct pms_softc *);
323int elantech_set_absolute_mode_v2(struct pms_softc *);
324int elantech_set_absolute_mode_v3(struct pms_softc *);
325int elantech_set_absolute_mode_v4(struct pms_softc *);
326
327struct cfattach pms_ca = {
328 sizeof(struct pms_softc), pmsprobe, pmsattach, NULL((void *)0),
329 pmsactivate
330};
331
332struct cfdriver pms_cd = {
333 NULL((void *)0), "pms", DV_DULL
334};
335
336const struct wsmouse_accessops pms_accessops = {
337 pms_enable,
338 pms_ioctl,
339 pms_disable,
340};
341
342const struct wsmouse_accessops pms_sec_accessops = {
343 pms_sec_enable,
344 pms_sec_ioctl,
345 pms_sec_disable,
346};
347
348const struct pms_protocol pms_protocols[] = {
349 /* Generic PS/2 mouse */
350 {
351 PMS_STANDARD0, 3,
352 NULL((void *)0),
353 pms_ioctl_mouse,
354 pms_sync_mouse,
355 pms_proc_mouse,
356 NULL((void *)0)
357 },
358 /* Synaptics touchpad */
359 {
360 PMS_SYNAPTICS2, 6,
361 pms_enable_synaptics,
362 pms_ioctl_synaptics,
363 pms_sync_synaptics,
364 pms_proc_synaptics,
365 pms_disable_synaptics
366 },
367 /* ALPS touchpad */
368 {
369 PMS_ALPS3, 6,
370 pms_enable_alps,
371 pms_ioctl_alps,
372 pms_sync_alps,
373 pms_proc_alps,
374 NULL((void *)0)
375 },
376 /* Elantech touchpad (hardware version 1) */
377 {
378 PMS_ELANTECH_V14, 4,
379 pms_enable_elantech_v1,
380 pms_ioctl_elantech,
381 pms_sync_elantech_v1,
382 pms_proc_elantech_v1,
383 NULL((void *)0)
384 },
385 /* Elantech touchpad (hardware version 2) */
386 {
387 PMS_ELANTECH_V25, 6,
388 pms_enable_elantech_v2,
389 pms_ioctl_elantech,
390 pms_sync_elantech_v2,
391 pms_proc_elantech_v2,
392 NULL((void *)0)
393 },
394 /* Elantech touchpad (hardware version 3) */
395 {
396 PMS_ELANTECH_V36, 6,
397 pms_enable_elantech_v3,
398 pms_ioctl_elantech,
399 pms_sync_elantech_v3,
400 pms_proc_elantech_v3,
401 NULL((void *)0)
402 },
403 /* Elantech touchpad (hardware version 4) */
404 {
405 PMS_ELANTECH_V47, 6,
406 pms_enable_elantech_v4,
407 pms_ioctl_elantech,
408 pms_sync_elantech_v4,
409 pms_proc_elantech_v4,
410 NULL((void *)0)
411 },
412 /* Microsoft IntelliMouse */
413 {
414 PMS_INTELLI1, 4,
415 pms_enable_intelli,
416 pms_ioctl_mouse,
417 pms_sync_mouse,
418 pms_proc_mouse,
419 NULL((void *)0)
420 },
421};
422
423int
424pms_cmd(struct pms_softc *sc, u_char *cmd, int len, u_char *resp, int resplen)
425{
426 if (sc->poll
15.1
Field 'poll' is 0
25.1
Field 'poll' is 0
35.1
Field 'poll' is 0
43.1
Field 'poll' is 0
63.1
Field 'poll' is 0, which participates in a condition later
73.1
Field 'poll' is 0, which participates in a condition later
83.1
Field 'poll' is 0, which participates in a condition later
93.1
Field 'poll' is 0, which participates in a condition later
103.1
Field 'poll' is 0, which participates in a condition later
120.1
Field 'poll' is 0, which participates in a condition later
130.1
Field 'poll' is 0, which participates in a condition later
140.1
Field 'poll' is 0, which participates in a condition later
150.1
Field 'poll' is 0, which participates in a condition later
160.1
Field 'poll' is 0, which participates in a condition later
177.1
Field 'poll' is 0, which participates in a condition later
187.1
Field 'poll' is 0, which participates in a condition later
197.1
Field 'poll' is 0, which participates in a condition later
207.1
Field 'poll' is 0, which participates in a condition later
217.1
Field 'poll' is 0, which participates in a condition later
233.1
Field 'poll' is 0, which participates in a condition later
246.1
Field 'poll' is 0, which participates in a condition later
256.1
Field 'poll' is 0, which participates in a condition later
266.1
Field 'poll' is 0, which participates in a condition later
276.1
Field 'poll' is 0, which participates in a condition later
286.1
Field 'poll' is 0, which participates in a condition later
303.1
Field 'poll' is 0, which participates in a condition later
313.1
Field 'poll' is 0, which participates in a condition later
323.1
Field 'poll' is 0, which participates in a condition later
333.1
Field 'poll' is 0, which participates in a condition later
343.1
Field 'poll' is 0, which participates in a condition later
360.1
Field 'poll' is 0, which participates in a condition later
370.1
Field 'poll' is 0, which participates in a condition later
380.1
Field 'poll' is 0, which participates in a condition later
390.1
Field 'poll' is 0, which participates in a condition later
400.1
Field 'poll' is 0, which participates in a condition later
416.1
Field 'poll' is 0
) {
4
Assuming field 'poll' is 0
5
Taking false branch
16
Taking false branch
26
Taking false branch
36
Taking false branch
44
Taking false branch
64
Taking false branch
74
Taking false branch
84
Taking false branch
94
Taking false branch
104
Taking false branch
121
Taking false branch
131
Taking false branch
141
Taking false branch
151
Taking false branch
161
Taking false branch
178
Taking false branch
188
Taking false branch
198
Taking false branch
208
Taking false branch
218
Taking false branch
234
Taking false branch
247
Taking false branch
257
Taking false branch
267
Taking false branch
277
Taking false branch
287
Taking false branch
304
Taking false branch
314
Taking false branch
324
Taking false branch
334
Taking false branch
344
Taking false branch
361
Taking false branch
371
Taking false branch
381
Taking false branch
391
Taking false branch
401
Taking false branch
417
Taking false branch
427 return pckbc_poll_cmd(sc->sc_kbctag, PCKBC_AUX_SLOT1,
428 cmd, len, resplen, resp, 1);
429 } else {
430 return pckbc_enqueue_cmd(sc->sc_kbctag, PCKBC_AUX_SLOT1,
6
Returning without writing to 'sc->poll', which participates in a condition later
17
Returning without writing to 'sc->poll', which participates in a condition later
27
Returning without writing to 'sc->poll', which participates in a condition later
37
Returning without writing to 'sc->poll', which participates in a condition later
45
Returning without writing to 'sc->poll', which participates in a condition later
65
Returning without writing to 'sc->poll', which participates in a condition later
66
Returning value, which participates in a condition later
75
Returning without writing to 'sc->poll', which participates in a condition later
76
Returning value, which participates in a condition later
85
Returning without writing to 'sc->poll', which participates in a condition later
86
Returning value, which participates in a condition later
95
Returning without writing to 'sc->poll', which participates in a condition later
96
Returning value, which participates in a condition later
105
Returning without writing to 'sc->poll', which participates in a condition later
106
Returning value, which participates in a condition later
122
Returning without writing to 'sc->poll', which participates in a condition later
123
Returning value, which participates in a condition later
132
Returning without writing to 'sc->poll', which participates in a condition later
133
Returning value, which participates in a condition later
142
Returning without writing to 'sc->poll', which participates in a condition later
143
Returning value, which participates in a condition later
152
Returning without writing to 'sc->poll', which participates in a condition later
153
Returning value, which participates in a condition later
162
Returning without writing to 'sc->poll', which participates in a condition later
163
Returning value, which participates in a condition later
179
Returning without writing to 'sc->poll', which participates in a condition later
180
Returning value, which participates in a condition later
189
Returning without writing to 'sc->poll', which participates in a condition later
190
Returning value, which participates in a condition later
199
Returning without writing to 'sc->poll', which participates in a condition later
200
Returning value, which participates in a condition later
209
Returning without writing to 'sc->poll', which participates in a condition later
210
Returning value, which participates in a condition later
219
Returning without writing to 'sc->poll', which participates in a condition later
220
Returning value, which participates in a condition later
235
Returning without writing to 'sc->poll', which participates in a condition later
236
Returning value, which participates in a condition later
248
Returning without writing to 'sc->poll', which participates in a condition later
249
Returning value, which participates in a condition later
258
Returning without writing to 'sc->poll', which participates in a condition later
259
Returning value, which participates in a condition later
268
Returning without writing to 'sc->poll', which participates in a condition later
269
Returning value, which participates in a condition later
278
Returning without writing to 'sc->poll', which participates in a condition later
279
Returning value, which participates in a condition later
288
Returning without writing to 'sc->poll', which participates in a condition later
289
Returning value, which participates in a condition later
305
Returning without writing to 'sc->poll', which participates in a condition later
306
Returning value, which participates in a condition later
315
Returning without writing to 'sc->poll', which participates in a condition later
316
Returning value, which participates in a condition later
325
Returning without writing to 'sc->poll', which participates in a condition later
326
Returning value, which participates in a condition later
335
Returning without writing to 'sc->poll', which participates in a condition later
336
Returning value, which participates in a condition later
345
Returning without writing to 'sc->poll', which participates in a condition later
346
Returning value, which participates in a condition later
362
Returning without writing to 'sc->poll', which participates in a condition later
363
Returning value, which participates in a condition later
372
Returning without writing to 'sc->poll', which participates in a condition later
373
Returning value, which participates in a condition later
382
Returning without writing to 'sc->poll', which participates in a condition later
383
Returning value, which participates in a condition later
392
Returning without writing to 'sc->poll', which participates in a condition later
393
Returning value, which participates in a condition later
402
Returning without writing to 'sc->poll', which participates in a condition later
403
Returning value, which participates in a condition later
418
Returning value, which participates in a condition later
431 cmd, len, resplen, 1, resp);
432 }
433}
434
435int
436pms_spec_cmd(struct pms_softc *sc, int cmd)
437{
438 if (pms_set_scaling(sc, 1) ||
60
Calling 'pms_set_scaling'
70
Returning from 'pms_set_scaling'
71
Assuming the condition is false
112
Taking false branch
117
Calling 'pms_set_scaling'
127
Returning from 'pms_set_scaling'
128
Assuming the condition is false
169
Taking false branch
174
Calling 'pms_set_scaling'
184
Returning from 'pms_set_scaling'
185
Assuming the condition is false
226
Taking false branch
243
Calling 'pms_set_scaling'
253
Returning from 'pms_set_scaling'
254
Assuming the condition is false
295
Taking false branch
300
Calling 'pms_set_scaling'
310
Returning from 'pms_set_scaling'
311
Assuming the condition is false
352
Taking false branch
357
Calling 'pms_set_scaling'
367
Returning from 'pms_set_scaling'
368
Assuming the condition is false
409
Taking false branch
439 pms_set_resolution(sc, (cmd >> 6) & 0x03) ||
72
Calling 'pms_set_resolution'
80
Returning from 'pms_set_resolution'
81
Assuming the condition is false
129
Calling 'pms_set_resolution'
137
Returning from 'pms_set_resolution'
138
Assuming the condition is false
186
Calling 'pms_set_resolution'
194
Returning from 'pms_set_resolution'
195
Assuming the condition is false
255
Calling 'pms_set_resolution'
263
Returning from 'pms_set_resolution'
264
Assuming the condition is false
312
Calling 'pms_set_resolution'
320
Returning from 'pms_set_resolution'
321
Assuming the condition is false
369
Calling 'pms_set_resolution'
377
Returning from 'pms_set_resolution'
378
Assuming the condition is false
440 pms_set_resolution(sc, (cmd >> 4) & 0x03) ||
82
Calling 'pms_set_resolution'
90
Returning from 'pms_set_resolution'
91
Assuming the condition is false
139
Calling 'pms_set_resolution'
147
Returning from 'pms_set_resolution'
148
Assuming the condition is false
196
Calling 'pms_set_resolution'
204
Returning from 'pms_set_resolution'
205
Assuming the condition is false
265
Calling 'pms_set_resolution'
273
Returning from 'pms_set_resolution'
274
Assuming the condition is false
322
Calling 'pms_set_resolution'
330
Returning from 'pms_set_resolution'
331
Assuming the condition is false
379
Calling 'pms_set_resolution'
387
Returning from 'pms_set_resolution'
388
Assuming the condition is false
441 pms_set_resolution(sc, (cmd >> 2) & 0x03) ||
92
Calling 'pms_set_resolution'
100
Returning from 'pms_set_resolution'
101
Assuming the condition is false
149
Calling 'pms_set_resolution'
157
Returning from 'pms_set_resolution'
158
Assuming the condition is false
206
Calling 'pms_set_resolution'
214
Returning from 'pms_set_resolution'
215
Assuming the condition is false
275
Calling 'pms_set_resolution'
283
Returning from 'pms_set_resolution'
284
Assuming the condition is false
332
Calling 'pms_set_resolution'
340
Returning from 'pms_set_resolution'
341
Assuming the condition is false
389
Calling 'pms_set_resolution'
397
Returning from 'pms_set_resolution'
398
Assuming the condition is false
442 pms_set_resolution(sc, (cmd >> 0) & 0x03))
102
Calling 'pms_set_resolution'
110
Returning from 'pms_set_resolution'
111
Assuming the condition is false
159
Calling 'pms_set_resolution'
167
Returning from 'pms_set_resolution'
168
Assuming the condition is false
216
Calling 'pms_set_resolution'
224
Returning from 'pms_set_resolution'
225
Assuming the condition is false
285
Calling 'pms_set_resolution'
293
Returning from 'pms_set_resolution'
294
Assuming the condition is false
342
Calling 'pms_set_resolution'
350
Returning from 'pms_set_resolution'
351
Assuming the condition is false
399
Calling 'pms_set_resolution'
407
Returning from 'pms_set_resolution'
408
Assuming the condition is false
443 return (-1);
444 return (0);
113
Returning without writing to 'sc->poll', which participates in a condition later
114
Returning zero, which participates in a condition later
170
Returning without writing to 'sc->poll', which participates in a condition later
171
Returning zero, which participates in a condition later
227
Returning without writing to 'sc->poll', which participates in a condition later
228
Returning zero, which participates in a condition later
296
Returning without writing to 'sc->poll', which participates in a condition later
297
Returning zero, which participates in a condition later
353
Returning without writing to 'sc->poll', which participates in a condition later
354
Returning zero, which participates in a condition later
410
Returning without writing to 'sc->poll', which participates in a condition later
411
Returning zero, which participates in a condition later
445}
446
447int
448pms_get_devid(struct pms_softc *sc, u_char *resp)
449{
450 u_char cmd[1];
451
452 cmd[0] = PMS_SEND_DEV_ID0xf2;
453 return (pms_cmd(sc, cmd, 1, resp, 1));
454}
455
456int
457pms_get_status(struct pms_softc *sc, u_char *resp)
458{
459 u_char cmd[1];
460
461 cmd[0] = PMS_SEND_DEV_STATUS0xe9;
462 return (pms_cmd(sc, cmd, 1, resp, 3));
43
Calling 'pms_cmd'
46
Returning from 'pms_cmd'
47
Returning without writing to 'sc->poll', which participates in a condition later
463}
464
465int
466pms_set_rate(struct pms_softc *sc, int value)
467{
468 u_char cmd[2];
469
470 cmd[0] = PMS_SET_SAMPLE0xf3;
471 cmd[1] = value;
472 return (pms_cmd(sc, cmd, 2, NULL((void *)0), 0));
473}
474
475int
476pms_set_resolution(struct pms_softc *sc, int value)
477{
478 u_char cmd[2];
479
480 cmd[0] = PMS_SET_RES0xe8;
481 cmd[1] = value;
482 return (pms_cmd(sc, cmd, 2, NULL((void *)0), 0));
73
Calling 'pms_cmd'
77
Returning from 'pms_cmd'
78
Returning without writing to 'sc->poll', which participates in a condition later
79
Returning value, which participates in a condition later
83
Calling 'pms_cmd'
87
Returning from 'pms_cmd'
88
Returning without writing to 'sc->poll', which participates in a condition later
89
Returning value, which participates in a condition later
93
Calling 'pms_cmd'
97
Returning from 'pms_cmd'
98
Returning without writing to 'sc->poll', which participates in a condition later
99
Returning value, which participates in a condition later
103
Calling 'pms_cmd'
107
Returning from 'pms_cmd'
108
Returning without writing to 'sc->poll', which participates in a condition later
109
Returning value, which participates in a condition later
130
Calling 'pms_cmd'
134
Returning from 'pms_cmd'
135
Returning without writing to 'sc->poll', which participates in a condition later
136
Returning value, which participates in a condition later
140
Calling 'pms_cmd'
144
Returning from 'pms_cmd'
145
Returning without writing to 'sc->poll', which participates in a condition later
146
Returning value, which participates in a condition later
150
Calling 'pms_cmd'
154
Returning from 'pms_cmd'
155
Returning without writing to 'sc->poll', which participates in a condition later
156
Returning value, which participates in a condition later
160
Calling 'pms_cmd'
164
Returning from 'pms_cmd'
165
Returning without writing to 'sc->poll', which participates in a condition later
166
Returning value, which participates in a condition later
187
Calling 'pms_cmd'
191
Returning from 'pms_cmd'
192
Returning without writing to 'sc->poll', which participates in a condition later
193
Returning value, which participates in a condition later
197
Calling 'pms_cmd'
201
Returning from 'pms_cmd'
202
Returning without writing to 'sc->poll', which participates in a condition later
203
Returning value, which participates in a condition later
207
Calling 'pms_cmd'
211
Returning from 'pms_cmd'
212
Returning without writing to 'sc->poll', which participates in a condition later
213
Returning value, which participates in a condition later
217
Calling 'pms_cmd'
221
Returning from 'pms_cmd'
222
Returning without writing to 'sc->poll', which participates in a condition later
223
Returning value, which participates in a condition later
256
Calling 'pms_cmd'
260
Returning from 'pms_cmd'
261
Returning without writing to 'sc->poll', which participates in a condition later
262
Returning value, which participates in a condition later
266
Calling 'pms_cmd'
270
Returning from 'pms_cmd'
271
Returning without writing to 'sc->poll', which participates in a condition later
272
Returning value, which participates in a condition later
276
Calling 'pms_cmd'
280
Returning from 'pms_cmd'
281
Returning without writing to 'sc->poll', which participates in a condition later
282
Returning value, which participates in a condition later
286
Calling 'pms_cmd'
290
Returning from 'pms_cmd'
291
Returning without writing to 'sc->poll', which participates in a condition later
292
Returning value, which participates in a condition later
313
Calling 'pms_cmd'
317
Returning from 'pms_cmd'
318
Returning without writing to 'sc->poll', which participates in a condition later
319
Returning value, which participates in a condition later
323
Calling 'pms_cmd'
327
Returning from 'pms_cmd'
328
Returning without writing to 'sc->poll', which participates in a condition later
329
Returning value, which participates in a condition later
333
Calling 'pms_cmd'
337
Returning from 'pms_cmd'
338
Returning without writing to 'sc->poll', which participates in a condition later
339
Returning value, which participates in a condition later
343
Calling 'pms_cmd'
347
Returning from 'pms_cmd'
348
Returning without writing to 'sc->poll', which participates in a condition later
349
Returning value, which participates in a condition later
370
Calling 'pms_cmd'
374
Returning from 'pms_cmd'
375
Returning without writing to 'sc->poll', which participates in a condition later
376
Returning value, which participates in a condition later
380
Calling 'pms_cmd'
384
Returning from 'pms_cmd'
385
Returning without writing to 'sc->poll', which participates in a condition later
386
Returning value, which participates in a condition later
390
Calling 'pms_cmd'
394
Returning from 'pms_cmd'
395
Returning without writing to 'sc->poll', which participates in a condition later
396
Returning value, which participates in a condition later
400
Calling 'pms_cmd'
404
Returning from 'pms_cmd'
405
Returning without writing to 'sc->poll', which participates in a condition later
406
Returning value, which participates in a condition later
483}
484
485int
486pms_set_scaling(struct pms_softc *sc, int scale)
487{
488 u_char cmd[1];
489
490 switch (scale) {
13
Control jumps to 'case 1:' at line 491
23
Control jumps to 'case 1:' at line 491
33
Control jumps to 'case 1:' at line 491
61
Control jumps to 'case 1:' at line 491
118
Control jumps to 'case 1:' at line 491
175
Control jumps to 'case 1:' at line 491
231
Control jumps to 'case 1:' at line 491
244
Control jumps to 'case 1:' at line 491
301
Control jumps to 'case 1:' at line 491
358
Control jumps to 'case 1:' at line 491
414
Control jumps to 'case 1:' at line 491
491 case 1:
492 default:
493 cmd[0] = PMS_SET_SCALE110xe6;
494 break;
14
Execution continues on line 499
24
Execution continues on line 499
34
Execution continues on line 499
62
Execution continues on line 499
119
Execution continues on line 499
176
Execution continues on line 499
232
Execution continues on line 499
245
Execution continues on line 499
302
Execution continues on line 499
359
Execution continues on line 499
415
Execution continues on line 499
495 case 2:
496 cmd[0] = PMS_SET_SCALE210xe7;
497 break;
498 }
499 return (pms_cmd(sc, cmd, 1, NULL((void *)0), 0));
15
Calling 'pms_cmd'
18
Returning from 'pms_cmd'
19
Returning without writing to 'sc->poll', which participates in a condition later
25
Calling 'pms_cmd'
28
Returning from 'pms_cmd'
29
Returning without writing to 'sc->poll', which participates in a condition later
35
Calling 'pms_cmd'
38
Returning from 'pms_cmd'
39
Returning without writing to 'sc->poll', which participates in a condition later
63
Calling 'pms_cmd'
67
Returning from 'pms_cmd'
68
Returning without writing to 'sc->poll', which participates in a condition later
69
Returning value, which participates in a condition later
120
Calling 'pms_cmd'
124
Returning from 'pms_cmd'
125
Returning without writing to 'sc->poll', which participates in a condition later
126
Returning value, which participates in a condition later
177
Calling 'pms_cmd'
181
Returning from 'pms_cmd'
182
Returning without writing to 'sc->poll', which participates in a condition later
183
Returning value, which participates in a condition later
233
Calling 'pms_cmd'
237
Returning from 'pms_cmd'
238
Returning without writing to 'sc->poll', which participates in a condition later
239
Returning value, which participates in a condition later
246
Calling 'pms_cmd'
250
Returning from 'pms_cmd'
251
Returning without writing to 'sc->poll', which participates in a condition later
252
Returning value, which participates in a condition later
303
Calling 'pms_cmd'
307
Returning from 'pms_cmd'
308
Returning without writing to 'sc->poll', which participates in a condition later
309
Returning value, which participates in a condition later
360
Calling 'pms_cmd'
364
Returning from 'pms_cmd'
365
Returning without writing to 'sc->poll', which participates in a condition later
366
Returning value, which participates in a condition later
416
Calling 'pms_cmd'
419
Returning from 'pms_cmd'
420
Returning value, which participates in a condition later
500}
501
502int
503pms_reset(struct pms_softc *sc)
504{
505 u_char cmd[1], resp[2];
506 int res;
507
508 cmd[0] = PMS_RESET0xff;
509 res = pms_cmd(sc, cmd, 1, resp, 2);
510#ifdef DEBUG
511 if (res || resp[0] != PMS_RSTDONE0xaa || resp[1] != 0)
512 printf("%s: reset error %d (response 0x%02x, type 0x%02x)\n",
513 DEVNAME(sc)((sc)->sc_dev.dv_xname), res, resp[0], resp[1]);
514#endif
515 return (res);
516}
517
518int
519pms_dev_enable(struct pms_softc *sc)
520{
521 u_char cmd[1];
522 int res;
523
524 cmd[0] = PMS_DEV_ENABLE0xf4;
525 res = pms_cmd(sc, cmd, 1, NULL((void *)0), 0);
526 if (res)
527 printf("%s: enable error\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
528 return (res);
529}
530
531int
532pms_dev_disable(struct pms_softc *sc)
533{
534 u_char cmd[1];
535 int res;
536
537 cmd[0] = PMS_DEV_DISABLE0xf5;
538 res = pms_cmd(sc, cmd, 1, NULL((void *)0), 0);
3
Calling 'pms_cmd'
7
Returning from 'pms_cmd'
539 if (res)
8
Assuming 'res' is 0
9
Taking false branch
540 printf("%s: disable error\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
541 return (res);
10
Returning without writing to 'sc->poll', which participates in a condition later
542}
543
544void
545pms_protocol_lookup(struct pms_softc *sc)
546{
547 int i;
548
549 sc->protocol = &pms_protocols[0];
550 for (i = 1; i < nitems(pms_protocols)(sizeof((pms_protocols)) / sizeof((pms_protocols)[0])); i++) {
551 pms_reset(sc);
552 if (pms_protocols[i].enable(sc)) {
553 sc->protocol = &pms_protocols[i];
554 break;
555 }
556 }
557
558 DPRINTF("%s: protocol type %d\n", DEVNAME(sc), sc->protocol->type);
559}
560
561/*
562 * Detect reset announcement ([0xaa, 0x0]).
563 * The sequence will be sent as input on rare occasions when the touchpad was
564 * reset due to a power failure.
565 */
566void
567pms_reset_detect(struct pms_softc *sc, int data)
568{
569 switch (sc->sc_rststate) {
570 case PMS_RST_COMMENCE0x01:
571 if (data == 0x0) {
572 sc->sc_rststate = PMS_RST_ANNOUNCED0x02;
573 timeout_add_msec(&sc->sc_rsttimo, 100);
574 } else if (data != PMS_RSTDONE0xaa) {
575 sc->sc_rststate = 0;
576 }
577 break;
578 default:
579 if (data == PMS_RSTDONE0xaa)
580 sc->sc_rststate = PMS_RST_COMMENCE0x01;
581 else
582 sc->sc_rststate = 0;
583 }
584}
585
586void
587pms_reset_timo(void *v)
588{
589 struct pms_softc *sc = v;
590 int s = spltty()splraise(0x9);
591
592 /*
593 * Do nothing if the reset was a false positive or if the device already
594 * is disabled.
595 */
596 if (sc->sc_rststate == PMS_RST_ANNOUNCED0x02 &&
597 sc->sc_state != PMS_STATE_DISABLED0)
598 task_add(systq, &sc->sc_rsttask);
599
600 splx(s)spllower(s);
601}
602
603void
604pms_reset_task(void *v)
605{
606 struct pms_softc *sc = v;
607 int s = spltty()splraise(0x9);
608
609#ifdef DIAGNOSTIC1
610 printf("%s: device reset (state = %d)\n", DEVNAME(sc)((sc)->sc_dev.dv_xname), sc->sc_rststate);
611#endif
612
613 rw_enter_write(&sc->sc_state_lock);
614
615 if (sc->sc_sec_wsmousedev != NULL((void *)0))
616 pms_change_state(sc, PMS_STATE_DISABLED0, PMS_DEV_SECONDARY0x02);
617 pms_change_state(sc, PMS_STATE_DISABLED0, PMS_DEV_PRIMARY0x01);
618
619 pms_change_state(sc, PMS_STATE_ENABLED1, PMS_DEV_PRIMARY0x01);
620 if (sc->sc_sec_wsmousedev != NULL((void *)0))
621 pms_change_state(sc, PMS_STATE_ENABLED1, PMS_DEV_SECONDARY0x02);
622
623 rw_exit_write(&sc->sc_state_lock);
624 splx(s)spllower(s);
625}
626
627int
628pms_enable_intelli(struct pms_softc *sc)
629{
630 u_char resp;
631
632 /* the special sequence to enable the third button and the roller */
633 if (pms_set_rate(sc, PMS_INTELLI_MAGIC1200) ||
634 pms_set_rate(sc, PMS_INTELLI_MAGIC2100) ||
635 pms_set_rate(sc, PMS_INTELLI_MAGIC380) ||
636 pms_get_devid(sc, &resp) ||
637 resp != PMS_INTELLI_ID0x03)
638 return (0);
639
640 return (1);
641}
642
643int
644pms_ioctl_mouse(struct pms_softc *sc, u_long cmd, caddr_t data, int flag,
645 struct proc *p)
646{
647 int i;
648
649 switch (cmd) {
650 case WSMOUSEIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((32)))
:
651 *(u_int *)data = WSMOUSE_TYPE_PS22;
652 break;
653 case WSMOUSEIO_SRES((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((33)))
:
654 i = ((int) *(u_int *)data - 12) / 25;
655 /* valid values are {0,1,2,3} */
656 if (i < 0)
657 i = 0;
658 if (i > 3)
659 i = 3;
660
661 if (pms_set_resolution(sc, i))
662 printf("%s: SET_RES command error\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
663 break;
664 default:
665 return (-1);
666 }
667 return (0);
668}
669
670int
671pms_sync_mouse(struct pms_softc *sc, int data)
672{
673 if (sc->inputstate != 0)
674 return (0);
675
676 switch (sc->protocol->type) {
677 case PMS_STANDARD0:
678 if ((data & 0xc0) != 0)
679 return (-1);
680 break;
681 case PMS_INTELLI1:
682 if ((data & 0x08) != 0x08)
683 return (-1);
684 break;
685 }
686
687 return (0);
688}
689
690void
691pms_proc_mouse(struct pms_softc *sc)
692{
693 u_int buttons;
694 int dx, dy, dz;
695
696 buttons = butmap[sc->packet[0] & PMS_PS2_BUTTONSMASK0x07];
697 dx = (sc->packet[0] & PMS_PS2_XNEG0x10) ?
698 (int)sc->packet[1] - 256 : sc->packet[1];
699 dy = (sc->packet[0] & PMS_PS2_YNEG0x20) ?
700 (int)sc->packet[2] - 256 : sc->packet[2];
701
702 if (sc->protocol->type == PMS_INTELLI1)
703 dz = (signed char)sc->packet[3];
704 else
705 dz = 0;
706
707 WSMOUSE_INPUT(sc->sc_wsmousedev, buttons, dx, dy, dz, 0)do { wsmouse_buttons((sc->sc_wsmousedev), (buttons)); wsmouse_motion
((sc->sc_wsmousedev), (dx), (dy), (dz), (0)); wsmouse_input_sync
(sc->sc_wsmousedev); } while (0)
;
708}
709
710int
711pmsprobe(struct device *parent, void *match, void *aux)
712{
713 struct pckbc_attach_args *pa = aux;
714 u_char cmd[1], resp[2];
715 int res;
716
717 if (pa->pa_slot != PCKBC_AUX_SLOT1)
718 return (0);
719
720 /* Flush any garbage. */
721 pckbc_flush(pa->pa_tag, pa->pa_slot);
722
723 /* reset the device */
724 cmd[0] = PMS_RESET0xff;
725 res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 1);
726 if (res || resp[0] != PMS_RSTDONE0xaa || resp[1] != 0) {
727#ifdef DEBUG
728 printf("pms: reset error %d (response 0x%02x, type 0x%02x)\n",
729 res, resp[0], resp[1]);
730#endif
731 return (0);
732 }
733
734 return (1);
735}
736
737void
738pmsattach(struct device *parent, struct device *self, void *aux)
739{
740 struct pms_softc *sc = (void *)self;
741 struct pckbc_attach_args *pa = aux;
742 struct wsmousedev_attach_args a;
743
744 sc->sc_kbctag = pa->pa_tag;
745
746 pckbc_set_inputhandler(sc->sc_kbctag, PCKBC_AUX_SLOT1,
747 pmsinput, sc, DEVNAME(sc)((sc)->sc_dev.dv_xname));
748
749 printf("\n");
750
751 a.accessops = &pms_accessops;
752 a.accesscookie = sc;
753
754 rw_init(&sc->sc_state_lock, "pmsst")_rw_init_flags(&sc->sc_state_lock, "pmsst", 0, ((void *
)0))
;
755
756 /*
757 * Attach the wsmouse, saving a handle to it.
758 * Note that we don't need to check this pointer against NULL
759 * here or in pmsintr, because if this fails pms_enable() will
760 * never be called, so pmsinput() will never be called.
761 */
762 sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint)config_found_sm((self), (&a), (wsmousedevprint), ((void *
)0))
;
763
764 task_set(&sc->sc_rsttask, pms_reset_task, sc);
765 timeout_set(&sc->sc_rsttimo, pms_reset_timo, sc);
766
767 sc->poll = 1;
768 sc->sc_dev_enable = 0;
769
770 /* See if the device understands an extended (touchpad) protocol. */
771 pms_protocol_lookup(sc);
772
773 /* no interrupts until enabled */
774 pms_change_state(sc, PMS_STATE_DISABLED0, PMS_DEV_IGNORE0x00);
775}
776
777int
778pmsactivate(struct device *self, int act)
779{
780 struct pms_softc *sc = (struct pms_softc *)self;
781
782 switch (act) {
783 case DVACT_SUSPEND3:
784 if (sc->sc_state == PMS_STATE_ENABLED1)
785 pms_change_state(sc, PMS_STATE_SUSPENDED2,
786 PMS_DEV_IGNORE0x00);
787 break;
788 case DVACT_RESUME4:
789 if (sc->sc_state == PMS_STATE_SUSPENDED2)
790 pms_change_state(sc, PMS_STATE_ENABLED1,
791 PMS_DEV_IGNORE0x00);
792 break;
793 }
794 return (0);
795}
796
797int
798pms_change_state(struct pms_softc *sc, int newstate, int dev)
799{
800 if (dev != PMS_DEV_IGNORE0x00) {
801 switch (newstate) {
802 case PMS_STATE_ENABLED1:
803 if (sc->sc_dev_enable & dev)
804 return (EBUSY16);
805
806 sc->sc_dev_enable |= dev;
807
808 if (sc->sc_state == PMS_STATE_ENABLED1)
809 return (0);
810
811 break;
812 case PMS_STATE_DISABLED0:
813 sc->sc_dev_enable &= ~dev;
814
815 if (sc->sc_dev_enable)
816 return (0);
817
818 break;
819 }
820 }
821
822 switch (newstate) {
823 case PMS_STATE_ENABLED1:
824 sc->inputstate = 0;
825 sc->sc_rststate = 0;
826
827 pckbc_slot_enable(sc->sc_kbctag, PCKBC_AUX_SLOT1, 1);
828
829 if (sc->poll)
830 pckbc_flush(sc->sc_kbctag, PCKBC_AUX_SLOT1);
831
832 pms_reset(sc);
833 if (sc->protocol->enable != NULL((void *)0) &&
834 sc->protocol->enable(sc) == 0)
835 pms_protocol_lookup(sc);
836
837 pms_dev_enable(sc);
838 break;
839 case PMS_STATE_DISABLED0:
840 case PMS_STATE_SUSPENDED2:
841 pms_dev_disable(sc);
842
843 if (sc->protocol->disable)
844 sc->protocol->disable(sc);
845
846 pckbc_slot_enable(sc->sc_kbctag, PCKBC_AUX_SLOT1, 0);
847 break;
848 }
849
850 sc->sc_state = newstate;
851 sc->poll = (newstate == PMS_STATE_SUSPENDED2) ? 1 : 0;
852
853 return (0);
854}
855
856int
857pms_enable(void *v)
858{
859 struct pms_softc *sc = v;
860 int rv;
861
862 rw_enter_write(&sc->sc_state_lock);
863 rv = pms_change_state(sc, PMS_STATE_ENABLED1, PMS_DEV_PRIMARY0x01);
864 rw_exit_write(&sc->sc_state_lock);
865
866 return (rv);
867}
868
869void
870pms_disable(void *v)
871{
872 struct pms_softc *sc = v;
873
874 rw_enter_write(&sc->sc_state_lock);
875 pms_change_state(sc, PMS_STATE_DISABLED0, PMS_DEV_PRIMARY0x01);
876 rw_exit_write(&sc->sc_state_lock);
877}
878
879int
880pms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
881{
882 struct pms_softc *sc = v;
883
884 if (sc->protocol->ioctl)
885 return (sc->protocol->ioctl(sc, cmd, data, flag, p));
886 else
887 return (-1);
888}
889
890int
891pms_sec_enable(void *v)
892{
893 struct pms_softc *sc = v;
894 int rv;
895
896 rw_enter_write(&sc->sc_state_lock);
897 rv = pms_change_state(sc, PMS_STATE_ENABLED1, PMS_DEV_SECONDARY0x02);
898 rw_exit_write(&sc->sc_state_lock);
899
900 return (rv);
901}
902
903void
904pms_sec_disable(void *v)
905{
906 struct pms_softc *sc = v;
907
908 rw_enter_write(&sc->sc_state_lock);
909 pms_change_state(sc, PMS_STATE_DISABLED0, PMS_DEV_SECONDARY0x02);
910 rw_exit_write(&sc->sc_state_lock);
911}
912
913int
914pms_sec_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
915{
916 switch (cmd) {
917 case WSMOUSEIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((32)))
:
918 *(u_int *)data = WSMOUSE_TYPE_PS22;
919 break;
920 default:
921 return (-1);
922 }
923 return (0);
924}
925
926#ifdef DIAGNOSTIC1
927static inline void
928pms_print_packet(struct pms_softc *sc)
929{
930 int i, state, size;
931
932 state = sc->inputstate;
933 size = sc->protocol->packetsize;
934 for (i = 0; i < size; i++)
935 printf(i == state ? " %02x |" : " %02x", sc->packet[i]);
936}
937#endif
938
939void
940pmsinput(void *vsc, int data)
941{
942 struct pms_softc *sc = vsc;
943
944 if (sc->sc_state != PMS_STATE_ENABLED1) {
945 /* Interrupts are not expected. Discard the byte. */
946 return;
947 }
948
949 sc->packet[sc->inputstate] = data;
950 pms_reset_detect(sc, data);
951 if (sc->protocol->sync(sc, data)) {
952#ifdef DIAGNOSTIC1
953 printf("%s: not in sync yet, discard input "
954 "(state = %d,",
955 DEVNAME(sc)((sc)->sc_dev.dv_xname), sc->inputstate);
956 pms_print_packet(sc);
957 printf(")\n");
958#endif
959
960 sc->inputstate = 0;
961 return;
962 }
963
964 sc->inputstate++;
965
966 if (sc->inputstate != sc->protocol->packetsize)
967 return;
968
969 sc->inputstate = 0;
970 sc->protocol->proc(sc);
971}
972
973int
974synaptics_set_mode(struct pms_softc *sc, int mode, int rate)
975{
976 struct synaptics_softc *syn = sc->synaptics;
977
978 if (pms_spec_cmd(sc, mode) ||
979 pms_set_rate(sc, rate == 0 ? SYNAPTICS_CMD_SET_MODE0x14 : rate))
980 return (-1);
981
982 /*
983 * Make sure that the set mode command has finished.
984 * Otherwise enabling the device before that will make it fail.
985 */
986 delay(10000)(*delay_func)(10000);
987
988 if (rate == 0)
989 syn->mode = mode;
990
991 return (0);
992}
993
994int
995synaptics_query(struct pms_softc *sc, int query, int *val)
996{
997 u_char resp[3];
998
999 if (pms_spec_cmd(sc, query) ||
1000 pms_get_status(sc, resp))
1001 return (-1);
1002
1003 if (val)
1004 *val = (resp[0] << 16) | (resp[1] << 8) | resp[2];
1005
1006 return (0);
1007}
1008
1009int
1010synaptics_get_hwinfo(struct pms_softc *sc)
1011{
1012 struct synaptics_softc *syn = sc->synaptics;
1013 struct wsmousehw *hw;
1014 int resolution = 0, max_coords = 0, min_coords = 0;
1015
1016 hw = wsmouse_get_hw(sc->sc_wsmousedev);
1017
1018 if (synaptics_query(sc, SYNAPTICS_QUE_IDENTIFY0x00, &syn->identify))
1019 return (-1);
1020 if (synaptics_query(sc, SYNAPTICS_QUE_CAPABILITIES0x02,
1021 &syn->capabilities))
1022 return (-1);
1023 if (synaptics_query(sc, SYNAPTICS_QUE_MODEL0x03, &syn->model))
1024 return (-1);
1025 if ((SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities)(((syn->capabilities) >> 20) & 0x07) >= 1) &&
1026 synaptics_query(sc, SYNAPTICS_QUE_EXT_MODEL0x09, &syn->ext_model))
1027 return (-1);
1028 if ((SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities)(((syn->capabilities) >> 20) & 0x07) >= 4) &&
1029 synaptics_query(sc, SYNAPTICS_QUE_EXT_CAPABILITIES0x0c,
1030 &syn->ext_capabilities))
1031 return (-1);
1032 if ((SYNAPTICS_ID_MAJOR(syn->identify)((syn->identify) & 0x0f) >= 4) &&
1033 synaptics_query(sc, SYNAPTICS_QUE_RESOLUTION0x08, &resolution))
1034 return (-1);
1035 if ((SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities)(((syn->capabilities) >> 20) & 0x07) >= 5) &&
1036 (syn->ext_capabilities & SYNAPTICS_EXT_CAP_MAX_COORDS(1 << 17)) &&
1037 synaptics_query(sc, SYNAPTICS_QUE_EXT_MAX_COORDS0x0d, &max_coords))
1038 return (-1);
1039 if ((SYNAPTICS_CAP_EXTENDED_QUERIES(syn->capabilities)(((syn->capabilities) >> 20) & 0x07) >= 7 ||
1040 SYNAPTICS_ID_FULL(syn->identify)(((syn->identify) & 0x0f) << 8 | (((syn->identify
) >> 16) & 0xff))
== 0x801) &&
1041 (syn->ext_capabilities & SYNAPTICS_EXT_CAP_MIN_COORDS(1 << 13)) &&
1042 synaptics_query(sc, SYNAPTICS_QUE_EXT_MIN_COORDS0x0f, &min_coords))
1043 return (-1);
1044
1045 if (SYNAPTICS_ID_FULL(syn->identify)(((syn->identify) & 0x0f) << 8 | (((syn->identify
) >> 16) & 0xff))
>= 0x705) {
1046 if (synaptics_query(sc, SYNAPTICS_QUE_MODES0x01, &syn->modes))
1047 return (-1);
1048 if ((syn->modes & SYNAPTICS_EXT2_CAP(1 << 17)) &&
1049 synaptics_query(sc, SYNAPTICS_QUE_EXT2_CAPABILITIES0x10,
1050 &syn->ext2_capabilities))
1051 return (-1);
1052 }
1053
1054 if ((syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD(1 << 20)) &&
1055 !(syn->ext2_capabilities & SYNAPTICS_EXT2_CAP_BUTTONS_STICK(1 << 16))
1056 && mouse_has_softbtn)
1057 hw->type = WSMOUSE_TYPE_SYNAP_SBTN19;
1058 else
1059 hw->type = WSMOUSE_TYPE_SYNAPTICS15;
1060
1061 hw->hw_type = (syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD(1 << 20))
1062 ? WSMOUSEHW_CLICKPAD : WSMOUSEHW_TOUCHPAD;
1063
1064 if (resolution & SYNAPTICS_RESOLUTION_VALID(1 << 15)) {
1065 hw->h_res = SYNAPTICS_RESOLUTION_X(resolution)(((resolution) >> 16) & 0xff);
1066 hw->v_res = SYNAPTICS_RESOLUTION_Y(resolution)((resolution) & 0xff);
1067 }
1068
1069 hw->x_min = (min_coords ?
1070 SYNAPTICS_X_LIMIT(min_coords)((((min_coords) & 0xff0000) >> 11) | (((min_coords)
& 0xf00) >> 7))
: SYNAPTICS_XMIN_BEZEL1472);
1071 hw->y_min = (min_coords ?
1072 SYNAPTICS_Y_LIMIT(min_coords)((((min_coords) & 0xff) << 5) | (((min_coords) &
0xf000) >> 11))
: SYNAPTICS_YMIN_BEZEL1408);
1073 hw->x_max = (max_coords ?
1074 SYNAPTICS_X_LIMIT(max_coords)((((max_coords) & 0xff0000) >> 11) | (((max_coords)
& 0xf00) >> 7))
: SYNAPTICS_XMAX_BEZEL5472);
1075 hw->y_max = (max_coords ?
1076 SYNAPTICS_Y_LIMIT(max_coords)((((max_coords) & 0xff) << 5) | (((max_coords) &
0xf000) >> 11))
: SYNAPTICS_YMAX_BEZEL4448);
1077
1078 hw->contacts_max = SYNAPTICS_MAX_FINGERS3;
1079
1080 syn->sec_buttons = 0;
1081
1082 if (SYNAPTICS_EXT_MODEL_BUTTONS(syn->ext_model)((syn->ext_model >> 12) & 0x0f) > 8)
1083 syn->ext_model &= ~0xf000;
1084
1085 if ((syn->model & SYNAPTICS_MODEL_NEWABS(1 << 7)) == 0) {
1086 printf("%s: don't support Synaptics OLDABS\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
1087 return (-1);
1088 }
1089
1090 if ((SYNAPTICS_ID_MAJOR(syn->identify)((syn->identify) & 0x0f) == 5) &&
1091 (SYNAPTICS_ID_MINOR(syn->identify)(((syn->identify) >> 16) & 0xff) == 9))
1092 syn->mask = SYNAPTICS_MASK_NEWABS_RELAXED0xc0;
1093 else
1094 syn->mask = SYNAPTICS_MASK_NEWABS_STRICT0xc8;
1095
1096 return (0);
1097}
1098
1099void
1100synaptics_sec_proc(struct pms_softc *sc)
1101{
1102 struct synaptics_softc *syn = sc->synaptics;
1103 u_int buttons;
1104 int dx, dy;
1105
1106 if ((sc->sc_dev_enable & PMS_DEV_SECONDARY0x02) == 0)
1107 return;
1108
1109 buttons = butmap[sc->packet[1] & PMS_PS2_BUTTONSMASK0x07];
1110 buttons |= syn->sec_buttons;
1111 dx = (sc->packet[1] & PMS_PS2_XNEG0x10) ?
1112 (int)sc->packet[4] - 256 : sc->packet[4];
1113 dy = (sc->packet[1] & PMS_PS2_YNEG0x20) ?
1114 (int)sc->packet[5] - 256 : sc->packet[5];
1115
1116 WSMOUSE_INPUT(sc->sc_sec_wsmousedev, buttons, dx, dy, 0, 0)do { wsmouse_buttons((sc->sc_sec_wsmousedev), (buttons)); wsmouse_motion
((sc->sc_sec_wsmousedev), (dx), (dy), (0), (0)); wsmouse_input_sync
(sc->sc_sec_wsmousedev); } while (0)
;
1117}
1118
1119int
1120synaptics_knock(struct pms_softc *sc)
1121{
1122 u_char resp[3];
1123
1124 if (pms_set_resolution(sc, 0) ||
1125 pms_set_resolution(sc, 0) ||
1126 pms_set_resolution(sc, 0) ||
1127 pms_set_resolution(sc, 0) ||
1128 pms_get_status(sc, resp) ||
1129 resp[1] != SYNAPTICS_ID_MAGIC0x47)
1130 return (-1);
1131
1132 return (0);
1133}
1134
1135int
1136pms_enable_synaptics(struct pms_softc *sc)
1137{
1138 struct synaptics_softc *syn = sc->synaptics;
1139 struct wsmousedev_attach_args a;
1140 int mode, i;
1141
1142 if (synaptics_knock(sc)) {
1143 if (sc->synaptics == NULL((void *)0))
1144 goto err;
1145 /*
1146 * Some synaptics touchpads don't resume quickly.
1147 * Retry a few times.
1148 */
1149 for (i = 10; i > 0; --i) {
1150 printf("%s: device not resuming, retrying\n",
1151 DEVNAME(sc)((sc)->sc_dev.dv_xname));
1152 pms_reset(sc);
1153 if (synaptics_knock(sc) == 0)
1154 break;
1155 delay(100000)(*delay_func)(100000);
1156 }
1157 if (i == 0) {
1158 printf("%s: lost device\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
1159 goto err;
1160 }
1161 }
1162
1163 if (sc->synaptics == NULL((void *)0)) {
1164 sc->synaptics = syn = malloc(sizeof(struct synaptics_softc),
1165 M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
1166 if (syn == NULL((void *)0)) {
1167 printf("%s: synaptics: not enough memory\n",
1168 DEVNAME(sc)((sc)->sc_dev.dv_xname));
1169 goto err;
1170 }
1171
1172 if (synaptics_get_hwinfo(sc)) {
1173 free(sc->synaptics, M_DEVBUF2,
1174 sizeof(struct synaptics_softc));
1175 sc->synaptics = NULL((void *)0);
1176 goto err;
1177 }
1178
1179 /* enable pass-through PS/2 port if supported */
1180 if (syn->capabilities & SYNAPTICS_CAP_PASSTHROUGH(1 << 7)) {
1181 a.accessops = &pms_sec_accessops;
1182 a.accesscookie = sc;
1183 sc->sc_sec_wsmousedev = config_found((void *)sc, &a,config_found_sm(((void *)sc), (&a), (wsmousedevprint), ((
void *)0))
1184 wsmousedevprint)config_found_sm(((void *)sc), (&a), (wsmousedevprint), ((
void *)0))
;
1185 }
1186
1187 if (wsmouse_configure(sc->sc_wsmousedev, synaptics_params,
1188 nitems(synaptics_params)(sizeof((synaptics_params)) / sizeof((synaptics_params)[0]))))
1189 goto err;
1190
1191 printf("%s: Synaptics %s, firmware %d.%d, "
1192 "0x%x 0x%x 0x%x 0x%x 0x%x\n",
1193 DEVNAME(sc)((sc)->sc_dev.dv_xname),
1194 (syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD(1 << 20) ?
1195 "clickpad" : "touchpad"),
1196 SYNAPTICS_ID_MAJOR(syn->identify)((syn->identify) & 0x0f),
1197 SYNAPTICS_ID_MINOR(syn->identify)(((syn->identify) >> 16) & 0xff),
1198 syn->model, syn->ext_model, syn->modes,
1199 syn->capabilities, syn->ext_capabilities);
1200 }
1201
1202 /*
1203 * Enable absolute mode, plain W-mode and "advanced gesture mode"
1204 * (AGM), if possible. AGM, which seems to be a prerequisite for the
1205 * extended W-mode, might not always be necessary here, but at least
1206 * some older Synaptics models do not report finger counts without it.
1207 */
1208 mode = SYNAPTICS_ABSOLUTE_MODE(1 << 7) | SYNAPTICS_HIGH_RATE(1 << 6);
1209 if (syn->capabilities & SYNAPTICS_CAP_EXTENDED(1 << 23))
1210 mode |= SYNAPTICS_W_MODE(1 << 0);
1211 else if (SYNAPTICS_ID_MAJOR(syn->identify)((syn->identify) & 0x0f) >= 4)
1212 mode |= SYNAPTICS_DISABLE_GESTURE(1 << 2);
1213 if (synaptics_set_mode(sc, mode, 0))
1214 goto err;
1215
1216 if (SYNAPTICS_SUPPORTS_AGM(syn->ext_capabilities)((syn->ext_capabilities) & ((1 << 19) | (1 <<
11)))
&&
1217 synaptics_set_mode(sc, SYNAPTICS_QUE_MODEL0x03,
1218 SYNAPTICS_CMD_SET_ADV_GESTURE_MODE0xc8))
1219 goto err;
1220
1221 return (1);
1222
1223err:
1224 pms_reset(sc);
1225
1226 return (0);
1227}
1228
1229int
1230pms_ioctl_synaptics(struct pms_softc *sc, u_long cmd, caddr_t data, int flag,
1231 struct proc *p)
1232{
1233 struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
1234 struct wsmousehw *hw;
1235 int wsmode;
1236
1237 hw = wsmouse_get_hw(sc->sc_wsmousedev);
1238 switch (cmd) {
1239 case WSMOUSEIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((32)))
:
1240 *(u_int *)data = hw->type;
1241 break;
1242 case WSMOUSEIO_GCALIBCOORDS((unsigned long)0x40000000 | ((sizeof(struct wsmouse_calibcoords
) & 0x1fff) << 16) | ((('W')) << 8) | ((37)))
:
1243 wsmc->minx = hw->x_min;
1244 wsmc->maxx = hw->x_max;
1245 wsmc->miny = hw->y_min;
1246 wsmc->maxy = hw->y_max;
1247 wsmc->swapxy = 0;
1248 wsmc->resx = hw->h_res;
1249 wsmc->resy = hw->v_res;
1250 break;
1251 case WSMOUSEIO_SETMODE((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('W')) << 8) | ((38)))
:
1252 wsmode = *(u_int *)data;
1253 if (wsmode != WSMOUSE_COMPAT0 && wsmode != WSMOUSE_NATIVE1)
1254 return (EINVAL22);
1255 wsmouse_set_mode(sc->sc_wsmousedev, wsmode);
1256 break;
1257 default:
1258 return (-1);
1259 }
1260 return (0);
1261}
1262
1263int
1264pms_sync_synaptics(struct pms_softc *sc, int data)
1265{
1266 struct synaptics_softc *syn = sc->synaptics;
1267
1268 switch (sc->inputstate) {
1269 case 0:
1270 if ((data & syn->mask) != SYNAPTICS_VALID_NEWABS_FIRST0x80)
1271 return (-1);
1272 break;
1273 case 3:
1274 if ((data & syn->mask) != SYNAPTICS_VALID_NEWABS_NEXT0xc0)
1275 return (-1);
1276 break;
1277 }
1278
1279 return (0);
1280}
1281
1282void
1283pms_proc_synaptics(struct pms_softc *sc)
1284{
1285 struct synaptics_softc *syn = sc->synaptics;
1286 u_int buttons;
1287 int x, y, z, w, fingerwidth;
1288
1289 w = ((sc->packet[0] & 0x30) >> 2) | ((sc->packet[0] & 0x04) >> 1) |
1290 ((sc->packet[3] & 0x04) >> 2);
1291 z = sc->packet[2];
1292
1293 if ((syn->capabilities & SYNAPTICS_CAP_EXTENDED(1 << 23)) == 0) {
1294 /*
1295 * Emulate W mode for models that don't provide it. Bit 3
1296 * of the w-input signals a touch ("finger"), Bit 2 and
1297 * the "gesture" bits 1-0 can be ignored.
1298 */
1299 if (w & 8)
1300 w = 4;
1301 else
1302 z = w = 0;
1303 }
1304
1305
1306 if (w == 3) {
1307 if (syn->capabilities & SYNAPTICS_CAP_PASSTHROUGH(1 << 7))
1308 synaptics_sec_proc(sc);
1309 return;
1310 }
1311
1312 if ((sc->sc_dev_enable & PMS_DEV_PRIMARY0x01) == 0)
1313 return;
1314
1315 if (w == 2)
1316 return; /* EW-mode packets are not expected here. */
1317
1318 x = ((sc->packet[3] & 0x10) << 8) | ((sc->packet[1] & 0x0f) << 8) |
1319 sc->packet[4];
1320 y = ((sc->packet[3] & 0x20) << 7) | ((sc->packet[1] & 0xf0) << 4) |
1321 sc->packet[5];
1322
1323 buttons = ((sc->packet[0] & sc->packet[3]) & 0x01) ?
1324 WSMOUSE_BUTTON(1)(1 << ((1) - 1)) : 0;
1325 buttons |= ((sc->packet[0] & sc->packet[3]) & 0x02) ?
1326 WSMOUSE_BUTTON(3)(1 << ((3) - 1)) : 0;
1327
1328 if (syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD(1 << 20)) {
1329 buttons |= ((sc->packet[0] ^ sc->packet[3]) & 0x01) ?
1330 WSMOUSE_BUTTON(1)(1 << ((1) - 1)) : 0;
1331 } else if (syn->capabilities & SYNAPTICS_CAP_MIDDLE_BUTTON(1 << 18)) {
1332 buttons |= ((sc->packet[0] ^ sc->packet[3]) & 0x01) ?
1333 WSMOUSE_BUTTON(2)(1 << ((2) - 1)) : 0;
1334 }
1335
1336 if (syn->capabilities & SYNAPTICS_CAP_FOUR_BUTTON(1 << 3)) {
1337 buttons |= ((sc->packet[0] ^ sc->packet[3]) & 0x01) ?
1338 WSMOUSE_BUTTON(4)(1 << ((4) - 1)) : 0;
1339 buttons |= ((sc->packet[0] ^ sc->packet[3]) & 0x02) ?
1340 WSMOUSE_BUTTON(5)(1 << ((5) - 1)) : 0;
1341 } else if (SYNAPTICS_EXT_MODEL_BUTTONS(syn->ext_model)((syn->ext_model >> 12) & 0x0f) &&
1342 ((sc->packet[0] ^ sc->packet[3]) & 0x02)) {
1343 if (syn->ext2_capabilities & SYNAPTICS_EXT2_CAP_BUTTONS_STICK(1 << 16)) {
1344 /*
1345 * Trackstick buttons on this machine are wired to the
1346 * trackpad as extra buttons, so route the event
1347 * through the trackstick interface as normal buttons
1348 */
1349 syn->sec_buttons =
1350 (sc->packet[4] & 0x01) ? WSMOUSE_BUTTON(1)(1 << ((1) - 1)) : 0;
1351 syn->sec_buttons |=
1352 (sc->packet[5] & 0x01) ? WSMOUSE_BUTTON(3)(1 << ((3) - 1)) : 0;
1353 syn->sec_buttons |=
1354 (sc->packet[4] & 0x02) ? WSMOUSE_BUTTON(2)(1 << ((2) - 1)) : 0;
1355 wsmouse_buttons(
1356 sc->sc_sec_wsmousedev, syn->sec_buttons);
1357 wsmouse_input_sync(sc->sc_sec_wsmousedev);
1358 return;
1359 }
1360
1361 buttons |= (sc->packet[4] & 0x01) ? WSMOUSE_BUTTON(6)(1 << ((6) - 1)) : 0;
1362 buttons |= (sc->packet[5] & 0x01) ? WSMOUSE_BUTTON(7)(1 << ((7) - 1)) : 0;
1363 buttons |= (sc->packet[4] & 0x02) ? WSMOUSE_BUTTON(8)(1 << ((8) - 1)) : 0;
1364 buttons |= (sc->packet[5] & 0x02) ? WSMOUSE_BUTTON(9)(1 << ((9) - 1)) : 0;
1365 buttons |= (sc->packet[4] & 0x04) ? WSMOUSE_BUTTON(10)(1 << ((10) - 1)) : 0;
1366 buttons |= (sc->packet[5] & 0x04) ? WSMOUSE_BUTTON(11)(1 << ((11) - 1)) : 0;
1367 buttons |= (sc->packet[4] & 0x08) ? WSMOUSE_BUTTON(12)(1 << ((12) - 1)) : 0;
1368 buttons |= (sc->packet[5] & 0x08) ? WSMOUSE_BUTTON(13)(1 << ((13) - 1)) : 0;
1369 x &= ~0x0f;
1370 y &= ~0x0f;
1371 }
1372
1373 if (z) {
1374 fingerwidth = max(w, 4);
1375 w = (w < 2 ? w + 2 : 1);
1376 } else {
1377 fingerwidth = 0;
1378 w = 0;
1379 }
1380 wsmouse_set(sc->sc_wsmousedev, WSMOUSE_TOUCH_WIDTH, fingerwidth, 0);
1381 WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, w)do { wsmouse_buttons((sc->sc_wsmousedev), (buttons)); wsmouse_position
((sc->sc_wsmousedev), (x), (y)); wsmouse_touch((sc->sc_wsmousedev
), (z), (w)); wsmouse_input_sync(sc->sc_wsmousedev); } while
(0)
;
1382}
1383
1384void
1385pms_disable_synaptics(struct pms_softc *sc)
1386{
1387 struct synaptics_softc *syn = sc->synaptics;
1388
1389 if (syn->capabilities & SYNAPTICS_CAP_SLEEP(1 << 4))
1390 synaptics_set_mode(sc, SYNAPTICS_SLEEP_MODE(1 << 3) |
1391 SYNAPTICS_DISABLE_GESTURE(1 << 2), 0);
1392}
1393
1394int
1395alps_sec_proc(struct pms_softc *sc)
1396{
1397 struct alps_softc *alps = sc->alps;
1398 int dx, dy, pos = 0;
1399
1400 if ((sc->packet[0] & PMS_ALPS_PS2_MASK0xc8) == PMS_ALPS_PS2_VALID0x08) {
1401 /*
1402 * We need to keep buttons states because interleaved
1403 * packets only signalize x/y movements.
1404 */
1405 alps->sec_buttons = butmap[sc->packet[0] & PMS_PS2_BUTTONSMASK0x07];
1406 } else if ((sc->packet[3] & PMS_ALPS_INTERLEAVED_MASK0xcf) ==
1407 PMS_ALPS_INTERLEAVED_VALID0x0f) {
1408 sc->inputstate = 3;
1409 pos = 3;
1410 } else {
1411 return (0);
1412 }
1413
1414 if ((sc->sc_dev_enable & PMS_DEV_SECONDARY0x02) == 0)
1415 return (1);
1416
1417 dx = (sc->packet[pos] & PMS_PS2_XNEG0x10) ?
1418 (int)sc->packet[pos + 1] - 256 : sc->packet[pos + 1];
1419 dy = (sc->packet[pos] & PMS_PS2_YNEG0x20) ?
1420 (int)sc->packet[pos + 2] - 256 : sc->packet[pos + 2];
1421
1422 WSMOUSE_INPUT(sc->sc_sec_wsmousedev, alps->sec_buttons, dx, dy, 0, 0)do { wsmouse_buttons((sc->sc_sec_wsmousedev), (alps->sec_buttons
)); wsmouse_motion((sc->sc_sec_wsmousedev), (dx), (dy), (0
), (0)); wsmouse_input_sync(sc->sc_sec_wsmousedev); } while
(0)
;
1423
1424 return (1);
1425}
1426
1427int
1428alps_get_hwinfo(struct pms_softc *sc)
1429{
1430 struct alps_softc *alps = sc->alps;
1431 u_char resp[3];
1432 int i;
1433 struct wsmousehw *hw;
1434
1435 if (pms_set_resolution(sc, 0) ||
1436 pms_set_scaling(sc, 2) ||
1437 pms_set_scaling(sc, 2) ||
1438 pms_set_scaling(sc, 2) ||
1439 pms_get_status(sc, resp)) {
1440 DPRINTF("%s: alps: model query error\n", DEVNAME(sc));
1441 return (-1);
1442 }
1443
1444 alps->version = (resp[0] << 8) | (resp[1] << 4) | (resp[2] / 20 + 1);
1445
1446 for (i = 0; i < nitems(alps_models)(sizeof((alps_models)) / sizeof((alps_models)[0])); i++)
1447 if (alps->version == alps_models[i].version) {
1448 alps->model = alps_models[i].model;
1449 alps->mask = alps_models[i].mask;
1450
1451 hw = wsmouse_get_hw(sc->sc_wsmousedev);
1452 hw->type = WSMOUSE_TYPE_ALPS16;
1453 hw->hw_type = WSMOUSEHW_TOUCHPAD;
1454 hw->x_min = ALPS_XMIN_BEZEL0;
1455 hw->y_min = ALPS_YMIN_BEZEL0;
1456 hw->x_max = ALPS_XMAX_BEZEL1023;
1457 hw->y_max = ALPS_YMAX_BEZEL767;
1458 hw->contacts_max = 1;
1459
1460 return (0);
1461 }
1462
1463 return (-1);
1464}
1465
1466int
1467pms_enable_alps(struct pms_softc *sc)
1468{
1469 struct alps_softc *alps = sc->alps;
1470 struct wsmousedev_attach_args a;
1471 u_char resp[3];
1472
1473 if (pms_set_resolution(sc, 0) ||
1474 pms_set_scaling(sc, 1) ||
1475 pms_set_scaling(sc, 1) ||
1476 pms_set_scaling(sc, 1) ||
1477 pms_get_status(sc, resp) ||
1478 resp[0] != PMS_ALPS_MAGIC10 ||
1479 resp[1] != PMS_ALPS_MAGIC20 ||
1480 (resp[2] != PMS_ALPS_MAGIC3_110 && resp[2] != PMS_ALPS_MAGIC3_280 &&
1481 resp[2] != PMS_ALPS_MAGIC3_3100))
1482 goto err;
1483
1484 if (sc->alps == NULL((void *)0)) {
1485 sc->alps = alps = malloc(sizeof(struct alps_softc),
1486 M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
1487 if (alps == NULL((void *)0)) {
1488 printf("%s: alps: not enough memory\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
1489 goto err;
1490 }
1491
1492 if (alps_get_hwinfo(sc)) {
1493 free(sc->alps, M_DEVBUF2, sizeof(struct alps_softc));
1494 sc->alps = NULL((void *)0);
1495 goto err;
1496 }
1497
1498 if (wsmouse_configure(sc->sc_wsmousedev, alps_params,
1499 nitems(alps_params)(sizeof((alps_params)) / sizeof((alps_params)[0])))) {
1500 free(sc->alps, M_DEVBUF2, sizeof(struct alps_softc));
1501 sc->alps = NULL((void *)0);
1502 printf("%s: setup failed\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
1503 goto err;
1504 }
1505
1506 printf("%s: ALPS %s, version 0x%04x\n", DEVNAME(sc)((sc)->sc_dev.dv_xname),
1507 (alps->model & ALPS_DUALPOINT(1 << 2) ? "Dualpoint" : "Glidepoint"),
1508 alps->version);
1509
1510
1511 if (alps->model & ALPS_DUALPOINT(1 << 2)) {
1512 a.accessops = &pms_sec_accessops;
1513 a.accesscookie = sc;
1514 sc->sc_sec_wsmousedev = config_found((void *)sc, &a,config_found_sm(((void *)sc), (&a), (wsmousedevprint), ((
void *)0))
1515 wsmousedevprint)config_found_sm(((void *)sc), (&a), (wsmousedevprint), ((
void *)0))
;
1516 }
1517 }
1518
1519 if (alps->model == 0)
1520 goto err;
1521
1522 if ((alps->model & ALPS_PASSTHROUGH(1 << 3)) &&
1523 (pms_set_scaling(sc, 2) ||
1524 pms_set_scaling(sc, 2) ||
1525 pms_set_scaling(sc, 2) ||
1526 pms_dev_disable(sc))) {
1527 DPRINTF("%s: alps: passthrough on error\n", DEVNAME(sc));
1528 goto err;
1529 }
1530
1531 if (pms_dev_disable(sc) ||
1532 pms_dev_disable(sc) ||
1533 pms_set_rate(sc, 0x0a)) {
1534 DPRINTF("%s: alps: tapping error\n", DEVNAME(sc));
1535 goto err;
1536 }
1537
1538 if (pms_dev_disable(sc) ||
1539 pms_dev_disable(sc) ||
1540 pms_dev_disable(sc) ||
1541 pms_dev_disable(sc) ||
1542 pms_dev_enable(sc)) {
1543 DPRINTF("%s: alps: absolute mode error\n", DEVNAME(sc));
1544 goto err;
1545 }
1546
1547 if ((alps->model & ALPS_PASSTHROUGH(1 << 3)) &&
1548 (pms_set_scaling(sc, 1) ||
1549 pms_set_scaling(sc, 1) ||
1550 pms_set_scaling(sc, 1) ||
1551 pms_dev_disable(sc))) {
1552 DPRINTF("%s: alps: passthrough off error\n", DEVNAME(sc));
1553 goto err;
1554 }
1555
1556 alps->sec_buttons = 0;
1557
1558 return (1);
1559
1560err:
1561 pms_reset(sc);
1562
1563 return (0);
1564}
1565
1566int
1567pms_ioctl_alps(struct pms_softc *sc, u_long cmd, caddr_t data, int flag,
1568 struct proc *p)
1569{
1570 struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
1571 int wsmode;
1572 struct wsmousehw *hw;
1573
1574 switch (cmd) {
1575 case WSMOUSEIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((32)))
:
1576 *(u_int *)data = WSMOUSE_TYPE_ALPS16;
1577 break;
1578 case WSMOUSEIO_GCALIBCOORDS((unsigned long)0x40000000 | ((sizeof(struct wsmouse_calibcoords
) & 0x1fff) << 16) | ((('W')) << 8) | ((37)))
:
1579 hw = wsmouse_get_hw(sc->sc_wsmousedev);
1580 wsmc->minx = hw->x_min;
1581 wsmc->maxx = hw->x_max;
1582 wsmc->miny = hw->y_min;
1583 wsmc->maxy = hw->y_max;
1584 wsmc->swapxy = 0;
1585 break;
1586 case WSMOUSEIO_SETMODE((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('W')) << 8) | ((38)))
:
1587 wsmode = *(u_int *)data;
1588 if (wsmode != WSMOUSE_COMPAT0 && wsmode != WSMOUSE_NATIVE1)
1589 return (EINVAL22);
1590 wsmouse_set_mode(sc->sc_wsmousedev, wsmode);
1591 break;
1592 default:
1593 return (-1);
1594 }
1595 return (0);
1596}
1597
1598int
1599pms_sync_alps(struct pms_softc *sc, int data)
1600{
1601 struct alps_softc *alps = sc->alps;
1602
1603 if ((alps->model & ALPS_DUALPOINT(1 << 2)) &&
1604 (sc->packet[0] & PMS_ALPS_PS2_MASK0xc8) == PMS_ALPS_PS2_VALID0x08) {
1605 if (sc->inputstate == 2)
1606 sc->inputstate += 3;
1607 return (0);
1608 }
1609
1610 switch (sc->inputstate) {
1611 case 0:
1612 if ((data & alps->mask) != alps->mask)
1613 return (-1);
1614 break;
1615 case 1:
1616 case 2:
1617 case 3:
1618 if ((data & PMS_ALPS_MASK0x80) != PMS_ALPS_VALID0x00)
1619 return (-1);
1620 break;
1621 case 4:
1622 case 5:
1623 if ((alps->model & ALPS_INTERLEAVED(1 << 4)) == 0 &&
1624 (data & PMS_ALPS_MASK0x80) != PMS_ALPS_VALID0x00)
1625 return (-1);
1626 break;
1627 }
1628
1629 return (0);
1630}
1631
1632void
1633pms_proc_alps(struct pms_softc *sc)
1634{
1635 struct alps_softc *alps = sc->alps;
1636 int x, y, z, dx, dy;
1637 u_int buttons, gesture;
1638
1639 if ((alps->model & ALPS_DUALPOINT(1 << 2)) && alps_sec_proc(sc))
1640 return;
1641
1642 x = sc->packet[1] | ((sc->packet[2] & 0x78) << 4);
1643 y = sc->packet[4] | ((sc->packet[3] & 0x70) << 3);
1644 z = sc->packet[5];
1645
1646 buttons = ((sc->packet[3] & 1) ? WSMOUSE_BUTTON(1)(1 << ((1) - 1)) : 0) |
1647 ((sc->packet[3] & 2) ? WSMOUSE_BUTTON(3)(1 << ((3) - 1)) : 0) |
1648 ((sc->packet[3] & 4) ? WSMOUSE_BUTTON(2)(1 << ((2) - 1)) : 0);
1649
1650 if ((sc->sc_dev_enable & PMS_DEV_SECONDARY0x02) && z == ALPS_Z_MAGIC127) {
1651 dx = (x > ALPS_XSEC_BEZEL768 / 2) ? (x - ALPS_XSEC_BEZEL768) : x;
1652 dy = (y > ALPS_YSEC_BEZEL512 / 2) ? (y - ALPS_YSEC_BEZEL512) : y;
1653
1654 WSMOUSE_INPUT(sc->sc_sec_wsmousedev, buttons, dx, dy, 0, 0)do { wsmouse_buttons((sc->sc_sec_wsmousedev), (buttons)); wsmouse_motion
((sc->sc_sec_wsmousedev), (dx), (dy), (0), (0)); wsmouse_input_sync
(sc->sc_sec_wsmousedev); } while (0)
;
1655
1656 return;
1657 }
1658
1659 if ((sc->sc_dev_enable & PMS_DEV_PRIMARY0x01) == 0)
1660 return;
1661
1662 /*
1663 * XXX The Y-axis is in the oposit direction compared to
1664 * Synaptics touchpads and PS/2 mouses.
1665 * It's why we need to translate the y value here for both
1666 * NATIVE and COMPAT modes.
1667 */
1668 y = ALPS_YMAX_BEZEL767 - y + ALPS_YMIN_BEZEL0;
1669
1670 if (alps->gesture == ALPS_TAP0x01) {
1671 /* Report a touch with the tap coordinates. */
1672 WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons,do { wsmouse_buttons((sc->sc_wsmousedev), (buttons)); wsmouse_position
((sc->sc_wsmousedev), (alps->old_x), (alps->old_y));
wsmouse_touch((sc->sc_wsmousedev), (40), (0)); wsmouse_input_sync
(sc->sc_wsmousedev); } while (0)
1673 alps->old_x, alps->old_y, ALPS_PRESSURE, 0)do { wsmouse_buttons((sc->sc_wsmousedev), (buttons)); wsmouse_position
((sc->sc_wsmousedev), (alps->old_x), (alps->old_y));
wsmouse_touch((sc->sc_wsmousedev), (40), (0)); wsmouse_input_sync
(sc->sc_wsmousedev); } while (0)
;
1674 if (z > 0) {
1675 /*
1676 * The hardware doesn't send a null pressure
1677 * event when dragging starts.
1678 */
1679 WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons,do { wsmouse_buttons((sc->sc_wsmousedev), (buttons)); wsmouse_position
((sc->sc_wsmousedev), (alps->old_x), (alps->old_y));
wsmouse_touch((sc->sc_wsmousedev), (0), (0)); wsmouse_input_sync
(sc->sc_wsmousedev); } while (0)
1680 alps->old_x, alps->old_y, 0, 0)do { wsmouse_buttons((sc->sc_wsmousedev), (buttons)); wsmouse_position
((sc->sc_wsmousedev), (alps->old_x), (alps->old_y));
wsmouse_touch((sc->sc_wsmousedev), (0), (0)); wsmouse_input_sync
(sc->sc_wsmousedev); } while (0)
;
1681 }
1682 }
1683
1684 gesture = sc->packet[2] & 0x03;
1685 if (gesture != ALPS_TAP0x01)
1686 WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, 0)do { wsmouse_buttons((sc->sc_wsmousedev), (buttons)); wsmouse_position
((sc->sc_wsmousedev), (x), (y)); wsmouse_touch((sc->sc_wsmousedev
), (z), (0)); wsmouse_input_sync(sc->sc_wsmousedev); } while
(0)
;
1687
1688 if (alps->gesture != ALPS_DRAG0x03 || gesture != ALPS_TAP0x01)
1689 alps->gesture = gesture;
1690
1691 alps->old_x = x;
1692 alps->old_y = y;
1693}
1694
1695int
1696elantech_set_absolute_mode_v1(struct pms_softc *sc)
1697{
1698 int i;
1699 u_char resp[3];
1700
1701 /* Enable absolute mode. Magic numbers from Linux driver. */
1702 if (pms_spec_cmd(sc, ELANTECH_CMD_WRITE_REG0x11) ||
59
Calling 'pms_spec_cmd'
115
Returning from 'pms_spec_cmd'
423
Taking false branch
1703 pms_spec_cmd(sc, 0x10) ||
116
Calling 'pms_spec_cmd'
172
Returning from 'pms_spec_cmd'
1704 pms_spec_cmd(sc, 0x16) ||
173
Calling 'pms_spec_cmd'
229
Returning from 'pms_spec_cmd'
1705 pms_set_scaling(sc, 1) ||
230
Calling 'pms_set_scaling'
240
Returning from 'pms_set_scaling'
241
Assuming the condition is false
1706 pms_spec_cmd(sc, ELANTECH_CMD_WRITE_REG0x11) ||
242
Calling 'pms_spec_cmd'
298
Returning from 'pms_spec_cmd'
1707 pms_spec_cmd(sc, 0x11) ||
299
Calling 'pms_spec_cmd'
355
Returning from 'pms_spec_cmd'
1708 pms_spec_cmd(sc, 0x8f) ||
356
Calling 'pms_spec_cmd'
412
Returning from 'pms_spec_cmd'
1709 pms_set_scaling(sc, 1))
413
Calling 'pms_set_scaling'
421
Returning from 'pms_set_scaling'
422
Assuming the condition is false
1710 return (-1);
1711
1712 /* Read back reg 0x10 to ensure hardware is ready. */
1713 for (i = 0; i < 5; i++) {
424
Loop condition is true. Entering loop body
1714 if (pms_spec_cmd(sc, ELANTECH_CMD_READ_REG0x10) ||
1715 pms_spec_cmd(sc, 0x10) ||
1716 pms_get_status(sc, resp) == 0)
1717 break;
425
Execution continues on line 1720
1718 delay(2000)(*delay_func)(2000);
1719 }
1720 if (i
425.1
'i' is not equal to 5
== 5)
426
Taking false branch
1721 return (-1);
1722
1723 if ((resp[0] & ELANTECH_ABSOLUTE_MODE0x04) == 0)
427
The left operand of '&' is a garbage value
1724 return (-1);
1725
1726 return (0);
1727}
1728
1729int
1730elantech_set_absolute_mode_v2(struct pms_softc *sc)
1731{
1732 int i;
1733 u_char resp[3];
1734 u_char reg10 = (sc->elantech->fw_version == 0x20030 ? 0x54 : 0xc4);
1735
1736 /* Enable absolute mode. Magic numbers from Linux driver. */
1737 if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1738 elantech_ps2_cmd(sc, ELANTECH_CMD_WRITE_REG0x11) ||
1739 elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1740 elantech_ps2_cmd(sc, 0x10) ||
1741 elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1742 elantech_ps2_cmd(sc, reg10) ||
1743 pms_set_scaling(sc, 1) ||
1744 elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1745 elantech_ps2_cmd(sc, ELANTECH_CMD_WRITE_REG0x11) ||
1746 elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1747 elantech_ps2_cmd(sc, 0x11) ||
1748 elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1749 elantech_ps2_cmd(sc, 0x88) ||
1750 pms_set_scaling(sc, 1))
1751 return (-1);
1752
1753 /* Read back reg 0x10 to ensure hardware is ready. */
1754 for (i = 0; i < 5; i++) {
1755 if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1756 elantech_ps2_cmd(sc, ELANTECH_CMD_READ_REG0x10) ||
1757 elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1758 elantech_ps2_cmd(sc, 0x10) ||
1759 pms_get_status(sc, resp) == 0)
1760 break;
1761 delay(2000)(*delay_func)(2000);
1762 }
1763 if (i == 5)
1764 return (-1);
1765
1766 return (0);
1767}
1768
1769int
1770elantech_set_absolute_mode_v3(struct pms_softc *sc)
1771{
1772 int i;
1773 u_char resp[3];
1774
1775 /* Enable absolute mode. Magic numbers from Linux driver. */
1776 if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1777 elantech_ps2_cmd(sc, ELANTECH_CMD_READ_WRITE_REG0x00) ||
1778 elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1779 elantech_ps2_cmd(sc, 0x10) ||
1780 elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1781 elantech_ps2_cmd(sc, 0x0b) ||
1782 pms_set_scaling(sc, 1))
1783 return (-1);
1784
1785 /* Read back reg 0x10 to ensure hardware is ready. */
1786 for (i = 0; i < 5; i++) {
1787 if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1788 elantech_ps2_cmd(sc, ELANTECH_CMD_READ_WRITE_REG0x00) ||
1789 elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1790 elantech_ps2_cmd(sc, 0x10) ||
1791 pms_get_status(sc, resp) == 0)
1792 break;
1793 delay(2000)(*delay_func)(2000);
1794 }
1795 if (i == 5)
1796 return (-1);
1797
1798 return (0);
1799}
1800
1801int
1802elantech_set_absolute_mode_v4(struct pms_softc *sc)
1803{
1804 /* Enable absolute mode. Magic numbers from Linux driver. */
1805 if (elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1806 elantech_ps2_cmd(sc, ELANTECH_CMD_READ_WRITE_REG0x00) ||
1807 elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1808 elantech_ps2_cmd(sc, 0x07) ||
1809 elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1810 elantech_ps2_cmd(sc, ELANTECH_CMD_READ_WRITE_REG0x00) ||
1811 elantech_ps2_cmd(sc, ELANTECH_PS2_CUSTOM_COMMAND0xf8) ||
1812 elantech_ps2_cmd(sc, 0x01) ||
1813 pms_set_scaling(sc, 1))
1814 return (-1);
1815
1816 /* v4 has no register 0x10 to read response from */
1817
1818 return (0);
1819}
1820
1821int
1822elantech_get_hwinfo_v1(struct pms_softc *sc)
1823{
1824 struct elantech_softc *elantech = sc->elantech;
1825 struct wsmousehw *hw;
1826 int fw_version;
1827 u_char capabilities[3];
1828
1829 if (synaptics_query(sc, ELANTECH_QUE_FW_VER1, &fw_version))
1830 return (-1);
1831
1832 if (fw_version < 0x20030 || fw_version == 0x20600) {
1833 if (fw_version < 0x20000)
1834 elantech->flags |= ELANTECH_F_HW_V1_OLD0x08;
1835 } else
1836 return (-1);
1837
1838 elantech->fw_version = fw_version;
1839
1840 if (pms_spec_cmd(sc, ELANTECH_QUE_CAPABILITIES2) ||
1841 pms_get_status(sc, capabilities))
1842 return (-1);
1843
1844 if (capabilities[0] & ELANTECH_CAP_HAS_ROCKER4)
1845 elantech->flags |= ELANTECH_F_HAS_ROCKER0x02;
1846
1847 if (elantech_set_absolute_mode_v1(sc))
1848 return (-1);
1849
1850 hw = wsmouse_get_hw(sc->sc_wsmousedev);
1851 hw->type = WSMOUSE_TYPE_ELANTECH18;
1852 hw->hw_type = WSMOUSEHW_TOUCHPAD;
1853 hw->x_min = ELANTECH_V1_X_MIN(0 + 32);
1854 hw->x_max = ELANTECH_V1_X_MAX(576 - 32);
1855 hw->y_min = ELANTECH_V1_Y_MIN(0 + 32);
1856 hw->y_max = ELANTECH_V1_Y_MAX(384 - 32);
1857
1858 return (0);
1859}
1860
1861int
1862elantech_get_hwinfo_v2(struct pms_softc *sc)
1863{
1864 struct elantech_softc *elantech = sc->elantech;
1865 struct wsmousehw *hw;
1866 int fw_version, ic_ver;
1867 u_char capabilities[3];
1868 int i, fixed_dpi;
1869 u_char resp[3];
1870
1871 if (synaptics_query(sc, ELANTECH_QUE_FW_VER1, &fw_version))
1872 return (-1);
1873
1874 ic_ver = (fw_version & 0x0f0000) >> 16;
1875 if (ic_ver != 2 && ic_ver != 4)
1876 return (-1);
1877
1878 elantech->fw_version = fw_version;
1879 if (fw_version >= 0x20800)
1880 elantech->flags |= ELANTECH_F_REPORTS_PRESSURE0x01;
1881
1882 if (pms_spec_cmd(sc, ELANTECH_QUE_CAPABILITIES2) ||
1883 pms_get_status(sc, capabilities))
1884 return (-1);
1885
1886 if (elantech_set_absolute_mode_v2(sc))
1887 return (-1);
1888
1889 hw = wsmouse_get_hw(sc->sc_wsmousedev);
1890 hw->type = WSMOUSE_TYPE_ELANTECH18;
1891 hw->hw_type = WSMOUSEHW_TOUCHPAD;
1892
1893 if (fw_version == 0x20800 || fw_version == 0x20b00 ||
1894 fw_version == 0x20030) {
1895 hw->x_max = ELANTECH_V2_X_MAX1152;
1896 hw->y_max = ELANTECH_V2_Y_MAX768;
1897 } else {
1898 if (pms_spec_cmd(sc, ELANTECH_QUE_FW_ID0) ||
1899 pms_get_status(sc, resp))
1900 return (-1);
1901 fixed_dpi = resp[1] & 0x10;
1902 i = (fw_version > 0x20800 && fw_version < 0x20900) ? 1 : 2;
1903 if ((fw_version >> 16) == 0x14 && fixed_dpi) {
1904 if (pms_spec_cmd(sc, ELANTECH_QUE_SAMPLE3) ||
1905 pms_get_status(sc, resp))
1906 return (-1);
1907 hw->x_max = (capabilities[1] - i) * resp[1] / 2;
1908 hw->y_max = (capabilities[2] - i) * resp[2] / 2;
1909 } else if (fw_version == 0x040216) {
1910 hw->x_max = 819;
1911 hw->y_max = 405;
1912 } else if (fw_version == 0x040219 || fw_version == 0x040215) {
1913 hw->x_max = 900;
1914 hw->y_max = 500;
1915 } else {
1916 hw->x_max = (capabilities[1] - i) * 64;
1917 hw->y_max = (capabilities[2] - i) * 64;
1918 }
1919 }
1920
1921 return (0);
1922}
1923
1924int
1925elantech_get_hwinfo_v3(struct pms_softc *sc)
1926{
1927 struct elantech_softc *elantech = sc->elantech;
1928 struct wsmousehw *hw;
1929 int fw_version;
1930 u_char resp[3];
1931
1932 if (synaptics_query(sc, ELANTECH_QUE_FW_VER1, &fw_version))
1933 return (-1);
1934
1935 if (((fw_version & 0x0f0000) >> 16) != 5)
1936 return (-1);
1937
1938 elantech->fw_version = fw_version;
1939 elantech->flags |= ELANTECH_F_REPORTS_PRESSURE0x01;
1940
1941 if ((fw_version & 0x4000) == 0x4000)
1942 elantech->flags |= ELANTECH_F_CRC_ENABLED0x10;
1943
1944 if (elantech_set_absolute_mode_v3(sc))
1945 return (-1);
1946
1947 if (pms_spec_cmd(sc, ELANTECH_QUE_FW_ID0) ||
1948 pms_get_status(sc, resp))
1949 return (-1);
1950
1951 hw = wsmouse_get_hw(sc->sc_wsmousedev);
1952 hw->x_max = elantech->max_x = (resp[0] & 0x0f) << 8 | resp[1];
1953 hw->y_max = elantech->max_y = (resp[0] & 0xf0) << 4 | resp[2];
1954
1955 hw->type = WSMOUSE_TYPE_ELANTECH18;
1956 hw->hw_type = WSMOUSEHW_TOUCHPAD;
1957
1958 return (0);
1959}
1960
1961int
1962elantech_get_hwinfo_v4(struct pms_softc *sc)
1963{
1964 struct elantech_softc *elantech = sc->elantech;
1965 struct wsmousehw *hw;
1966 int fw_version;
1967 u_char capabilities[3];
1968 u_char resp[3];
1969
1970 if (synaptics_query(sc, ELANTECH_QUE_FW_VER1, &fw_version))
1971 return (-1);
1972
1973 if ((fw_version & 0x0f0000) >> 16 < 6)
1974 return (-1);
1975
1976 elantech->fw_version = fw_version;
1977 elantech->flags |= ELANTECH_F_REPORTS_PRESSURE0x01;
1978
1979 if ((fw_version & 0x4000) == 0x4000)
1980 elantech->flags |= ELANTECH_F_CRC_ENABLED0x10;
1981
1982 if (elantech_set_absolute_mode_v4(sc))
1983 return (-1);
1984
1985 if (pms_spec_cmd(sc, ELANTECH_QUE_CAPABILITIES2) ||
1986 pms_get_status(sc, capabilities))
1987 return (-1);
1988
1989 if (pms_spec_cmd(sc, ELANTECH_QUE_FW_ID0) ||
1990 pms_get_status(sc, resp))
1991 return (-1);
1992
1993 hw = wsmouse_get_hw(sc->sc_wsmousedev);
1994 hw->x_max = (resp[0] & 0x0f) << 8 | resp[1];
1995 hw->y_max = (resp[0] & 0xf0) << 4 | resp[2];
1996
1997 if ((capabilities[1] < 2) || (capabilities[1] > hw->x_max))
1998 return (-1);
1999
2000 if (capabilities[0] & ELANTECH_CAP_TRACKPOINT0x80)
2001 elantech->flags |= ELANTECH_F_TRACKPOINT0x20;
2002
2003 hw->type = WSMOUSE_TYPE_ELANTECH18;
2004 hw->hw_type = (ELANTECH_IS_CLICKPAD(sc)(((sc)->elantech->fw_version & 0x1000) != 0)
2005 ? WSMOUSEHW_CLICKPAD : WSMOUSEHW_TOUCHPAD);
2006 hw->mt_slots = ELANTECH_MAX_FINGERS5;
2007
2008 elantech->width = hw->x_max / (capabilities[1] - 1);
2009
2010 return (0);
2011}
2012
2013int
2014elantech_ps2_cmd(struct pms_softc *sc, u_char command)
2015{
2016 u_char cmd[1];
2017
2018 cmd[0] = command;
2019 return (pms_cmd(sc, cmd, 1, NULL((void *)0), 0));
2020}
2021
2022int
2023elantech_knock(struct pms_softc *sc)
2024{
2025 u_char resp[3];
2026
2027 if (pms_dev_disable(sc) ||
2
Calling 'pms_dev_disable'
11
Returning from 'pms_dev_disable'
2028 pms_set_scaling(sc, 1) ||
12
Calling 'pms_set_scaling'
20
Returning from 'pms_set_scaling'
21
Assuming the condition is false
2029 pms_set_scaling(sc, 1) ||
22
Calling 'pms_set_scaling'
30
Returning from 'pms_set_scaling'
31
Assuming the condition is false
2030 pms_set_scaling(sc, 1) ||
32
Calling 'pms_set_scaling'
40
Returning from 'pms_set_scaling'
41
Assuming the condition is false
2031 pms_get_status(sc, resp) ||
42
Calling 'pms_get_status'
48
Returning from 'pms_get_status'
49
Assuming the condition is false
2032 resp[0] != PMS_ELANTECH_MAGIC10x3c ||
50
Assuming the condition is false
2033 resp[1] != PMS_ELANTECH_MAGIC20x03 ||
51
Assuming the condition is false
2034 (resp[2] != PMS_ELANTECH_MAGIC3_10xc8 &&
52
Assuming the condition is false
2035 resp[2] != PMS_ELANTECH_MAGIC3_20x00))
2036 return (-1);
2037
2038 return (0);
53
Returning without writing to 'sc->poll', which participates in a condition later
2039}
2040
2041int
2042pms_enable_elantech_v1(struct pms_softc *sc)
2043{
2044 struct elantech_softc *elantech = sc->elantech;
2045 int i;
2046
2047 if (elantech_knock(sc))
1
Calling 'elantech_knock'
54
Returning from 'elantech_knock'
55
Taking false branch
2048 goto err;
2049
2050 if (sc->elantech == NULL((void *)0)) {
56
Assuming field 'elantech' is not equal to NULL
57
Taking false branch
2051 sc->elantech = elantech = malloc(sizeof(struct elantech_softc),
2052 M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
2053 if (elantech == NULL((void *)0)) {
2054 printf("%s: elantech: not enough memory\n",
2055 DEVNAME(sc)((sc)->sc_dev.dv_xname));
2056 goto err;
2057 }
2058
2059 if (elantech_get_hwinfo_v1(sc)) {
2060 free(sc->elantech, M_DEVBUF2,
2061 sizeof(struct elantech_softc));
2062 sc->elantech = NULL((void *)0);
2063 goto err;
2064 }
2065 if (wsmouse_configure(sc->sc_wsmousedev, NULL((void *)0), 0)) {
2066 free(sc->elantech, M_DEVBUF2,
2067 sizeof(struct elantech_softc));
2068 sc->elantech = NULL((void *)0);
2069 printf("%s: elantech: setup failed\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
2070 goto err;
2071 }
2072
2073 printf("%s: Elantech Touchpad, version %d, firmware 0x%x\n",
2074 DEVNAME(sc)((sc)->sc_dev.dv_xname), 1, sc->elantech->fw_version);
2075 } else if (elantech_set_absolute_mode_v1(sc))
58
Calling 'elantech_set_absolute_mode_v1'
2076 goto err;
2077
2078 for (i = 0; i < nitems(sc->elantech->parity)(sizeof((sc->elantech->parity)) / sizeof((sc->elantech
->parity)[0]))
; i++)
2079 sc->elantech->parity[i] = sc->elantech->parity[i & (i - 1)] ^ 1;
2080
2081 return (1);
2082
2083err:
2084 pms_reset(sc);
2085
2086 return (0);
2087}
2088
2089int
2090pms_enable_elantech_v2(struct pms_softc *sc)
2091{
2092 struct elantech_softc *elantech = sc->elantech;
2093
2094 if (elantech_knock(sc))
2095 goto err;
2096
2097 if (sc->elantech == NULL((void *)0)) {
2098 sc->elantech = elantech = malloc(sizeof(struct elantech_softc),
2099 M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
2100 if (elantech == NULL((void *)0)) {
2101 printf("%s: elantech: not enough memory\n",
2102 DEVNAME(sc)((sc)->sc_dev.dv_xname));
2103 goto err;
2104 }
2105
2106 if (elantech_get_hwinfo_v2(sc)) {
2107 free(sc->elantech, M_DEVBUF2,
2108 sizeof(struct elantech_softc));
2109 sc->elantech = NULL((void *)0);
2110 goto err;
2111 }
2112 if (wsmouse_configure(sc->sc_wsmousedev, NULL((void *)0), 0)) {
2113 free(sc->elantech, M_DEVBUF2,
2114 sizeof(struct elantech_softc));
2115 sc->elantech = NULL((void *)0);
2116 printf("%s: elantech: setup failed\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
2117 goto err;
2118 }
2119
2120 printf("%s: Elantech Touchpad, version %d, firmware 0x%x\n",
2121 DEVNAME(sc)((sc)->sc_dev.dv_xname), 2, sc->elantech->fw_version);
2122 } else if (elantech_set_absolute_mode_v2(sc))
2123 goto err;
2124
2125 return (1);
2126
2127err:
2128 pms_reset(sc);
2129
2130 return (0);
2131}
2132
2133int
2134pms_enable_elantech_v3(struct pms_softc *sc)
2135{
2136 struct elantech_softc *elantech = sc->elantech;
2137
2138 if (elantech_knock(sc))
2139 goto err;
2140
2141 if (sc->elantech == NULL((void *)0)) {
2142 sc->elantech = elantech = malloc(sizeof(struct elantech_softc),
2143 M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
2144 if (elantech == NULL((void *)0)) {
2145 printf("%s: elantech: not enough memory\n",
2146 DEVNAME(sc)((sc)->sc_dev.dv_xname));
2147 goto err;
2148 }
2149
2150 if (elantech_get_hwinfo_v3(sc)) {
2151 free(sc->elantech, M_DEVBUF2,
2152 sizeof(struct elantech_softc));
2153 sc->elantech = NULL((void *)0);
2154 goto err;
2155 }
2156 if (wsmouse_configure(sc->sc_wsmousedev, NULL((void *)0), 0)) {
2157 free(sc->elantech, M_DEVBUF2,
2158 sizeof(struct elantech_softc));
2159 sc->elantech = NULL((void *)0);
2160 printf("%s: elantech: setup failed\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
2161 goto err;
2162 }
2163
2164 printf("%s: Elantech Touchpad, version %d, firmware 0x%x\n",
2165 DEVNAME(sc)((sc)->sc_dev.dv_xname), 3, sc->elantech->fw_version);
2166 } else if (elantech_set_absolute_mode_v3(sc))
2167 goto err;
2168
2169 return (1);
2170
2171err:
2172 pms_reset(sc);
2173
2174 return (0);
2175}
2176
2177int
2178pms_enable_elantech_v4(struct pms_softc *sc)
2179{
2180 struct elantech_softc *elantech = sc->elantech;
2181 struct wsmousedev_attach_args a;
2182
2183 if (elantech_knock(sc))
2184 goto err;
2185
2186 if (sc->elantech == NULL((void *)0)) {
2187 sc->elantech = elantech = malloc(sizeof(struct elantech_softc),
2188 M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
2189 if (elantech == NULL((void *)0)) {
2190 printf("%s: elantech: not enough memory\n",
2191 DEVNAME(sc)((sc)->sc_dev.dv_xname));
2192 goto err;
2193 }
2194
2195 if (elantech_get_hwinfo_v4(sc)) {
2196 free(sc->elantech, M_DEVBUF2,
2197 sizeof(struct elantech_softc));
2198 sc->elantech = NULL((void *)0);
2199 goto err;
2200 }
2201 if (wsmouse_configure(sc->sc_wsmousedev, NULL((void *)0), 0)) {
2202 free(sc->elantech, M_DEVBUF2,
2203 sizeof(struct elantech_softc));
2204 sc->elantech = NULL((void *)0);
2205 printf("%s: elantech: setup failed\n", DEVNAME(sc)((sc)->sc_dev.dv_xname));
2206 goto err;
2207 }
2208
2209 printf("%s: Elantech %s, version 4, firmware 0x%x\n",
2210 DEVNAME(sc)((sc)->sc_dev.dv_xname), (ELANTECH_IS_CLICKPAD(sc)(((sc)->elantech->fw_version & 0x1000) != 0) ? "Clickpad"
2211 : "Touchpad"), sc->elantech->fw_version);
2212
2213 if (sc->elantech->flags & ELANTECH_F_TRACKPOINT0x20) {
2214 a.accessops = &pms_sec_accessops;
2215 a.accesscookie = sc;
2216 sc->sc_sec_wsmousedev = config_found((void *) sc, &a,config_found_sm(((void *) sc), (&a), (wsmousedevprint), (
(void *)0))
2217 wsmousedevprint)config_found_sm(((void *) sc), (&a), (wsmousedevprint), (
(void *)0))
;
2218 }
2219
2220 } else if (elantech_set_absolute_mode_v4(sc))
2221 goto err;
2222
2223 return (1);
2224
2225err:
2226 pms_reset(sc);
2227
2228 return (0);
2229}
2230
2231int
2232pms_ioctl_elantech(struct pms_softc *sc, u_long cmd, caddr_t data, int flag,
2233 struct proc *p)
2234{
2235 struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
2236 struct wsmousehw *hw;
2237 int wsmode;
2238
2239 switch (cmd) {
2240 case WSMOUSEIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((32)))
:
2241 *(u_int *)data = WSMOUSE_TYPE_ELANTECH18;
2242 break;
2243 case WSMOUSEIO_GCALIBCOORDS((unsigned long)0x40000000 | ((sizeof(struct wsmouse_calibcoords
) & 0x1fff) << 16) | ((('W')) << 8) | ((37)))
:
2244 hw = wsmouse_get_hw(sc->sc_wsmousedev);
2245 wsmc->minx = hw->x_min;
2246 wsmc->maxx = hw->x_max;
2247 wsmc->miny = hw->y_min;
2248 wsmc->maxy = hw->y_max;
2249 wsmc->swapxy = 0;
2250 wsmc->resx = hw->h_res;
2251 wsmc->resy = hw->v_res;
2252 break;
2253 case WSMOUSEIO_SETMODE((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('W')) << 8) | ((38)))
:
2254 wsmode = *(u_int *)data;
2255 if (wsmode != WSMOUSE_COMPAT0 && wsmode != WSMOUSE_NATIVE1)
2256 return (EINVAL22);
2257 wsmouse_set_mode(sc->sc_wsmousedev, wsmode);
2258 break;
2259 default:
2260 return (-1);
2261 }
2262 return (0);
2263}
2264
2265int
2266pms_sync_elantech_v1(struct pms_softc *sc, int data)
2267{
2268 struct elantech_softc *elantech = sc->elantech;
2269 u_char p;
2270
2271 switch (sc->inputstate) {
2272 case 0:
2273 if (elantech->flags & ELANTECH_F_HW_V1_OLD0x08) {
2274 elantech->p1 = (data & 0x20) >> 5;
2275 elantech->p2 = (data & 0x10) >> 4;
2276 } else {
2277 elantech->p1 = (data & 0x10) >> 4;
2278 elantech->p2 = (data & 0x20) >> 5;
2279 }
2280 elantech->p3 = (data & 0x04) >> 2;
2281 return (0);
2282 case 1:
2283 p = elantech->p1;
2284 break;
2285 case 2:
2286 p = elantech->p2;
2287 break;
2288 case 3:
2289 p = elantech->p3;
2290 break;
2291 default:
2292 return (-1);
2293 }
2294
2295 if (data < 0 || data >= nitems(elantech->parity)(sizeof((elantech->parity)) / sizeof((elantech->parity)
[0]))
||
2296 /*
2297 * FW 0x20022 sends inverted parity bits on cold boot, returning
2298 * to normal after suspend & resume, so the parity check is
2299 * disabled for this one.
2300 */
2301 (elantech->fw_version != 0x20022 && elantech->parity[data] != p))
2302 return (-1);
2303
2304 return (0);
2305}
2306
2307int
2308pms_sync_elantech_v2(struct pms_softc *sc, int data)
2309{
2310 struct elantech_softc *elantech = sc->elantech;
2311
2312 /* Variants reporting pressure always have the same constant bits. */
2313 if (elantech->flags & ELANTECH_F_REPORTS_PRESSURE0x01) {
2314 if (sc->inputstate == 0 && (data & 0x0c) != 0x04)
2315 return (-1);
2316 if (sc->inputstate == 3 && (data & 0x0f) != 0x02)
2317 return (-1);
2318 return (0);
2319 }
2320
2321 /* For variants not reporting pressure, 1 and 3 finger touch packets
2322 * have different constant bits than 2 finger touch packets. */
2323 switch (sc->inputstate) {
2324 case 0:
2325 if ((data & 0xc0) == 0x80) {
2326 if ((data & 0x0c) != 0x0c)
2327 return (-1);
2328 elantech->flags |= ELANTECH_F_2FINGER_PACKET0x04;
2329 } else {
2330 if ((data & 0x3c) != 0x3c)
2331 return (-1);
2332 elantech->flags &= ~ELANTECH_F_2FINGER_PACKET0x04;
2333 }
2334 break;
2335 case 1:
2336 case 4:
2337 if (elantech->flags & ELANTECH_F_2FINGER_PACKET0x04)
2338 break;
2339 if ((data & 0xf0) != 0x00)
2340 return (-1);
2341 break;
2342 case 3:
2343 if (elantech->flags & ELANTECH_F_2FINGER_PACKET0x04) {
2344 if ((data & 0x0e) != 0x08)
2345 return (-1);
2346 } else {
2347 if ((data & 0x3e) != 0x38)
2348 return (-1);
2349 }
2350 break;
2351 default:
2352 break;
2353 }
2354
2355 return (0);
2356}
2357
2358int
2359pms_sync_elantech_v3(struct pms_softc *sc, int data)
2360{
2361 struct elantech_softc *elantech = sc->elantech;
2362
2363 switch (sc->inputstate) {
2364 case 0:
2365 if (elantech->flags & ELANTECH_F_CRC_ENABLED0x10)
2366 break;
2367 if ((data & 0x0c) != 0x04 && (data & 0x0c) != 0x0c)
2368 return (-1);
2369 break;
2370 case 3:
2371 if (elantech->flags & ELANTECH_F_CRC_ENABLED0x10) {
2372 if ((data & 0x09) != 0x08 && (data & 0x09) != 0x09)
2373 return (-1);
2374 } else {
2375 if ((data & 0xcf) != 0x02 && (data & 0xce) != 0x0c)
2376 return (-1);
2377 }
2378 break;
2379 }
2380
2381 return (0);
2382}
2383
2384/* Extract the type bits from packet[3]. */
2385static inline int
2386elantech_packet_type(struct elantech_softc *elantech, u_char b)
2387{
2388 /*
2389 * This looks dubious, but in the "crc-enabled" format bit 2 may
2390 * be set even in MOTION packets.
2391 */
2392 if ((elantech->flags & ELANTECH_F_TRACKPOINT0x20) && ((b & 0x0f) == 0x06))
2393 return (ELANTECH_PKT_TRACKPOINT0x06);
2394 else
2395 return (b & 0x03);
2396}
2397
2398int
2399pms_sync_elantech_v4(struct pms_softc *sc, int data)
2400{
2401 if (sc->inputstate == 0)
2402 return ((data & 0x08) == 0 ? 0 : -1);
2403
2404 if (sc->inputstate == 3) {
2405 switch (elantech_packet_type(sc->elantech, data)) {
2406 case ELANTECH_V4_PKT_STATUS0:
2407 case ELANTECH_V4_PKT_HEAD0x01:
2408 case ELANTECH_V4_PKT_MOTION0x02:
2409 if (sc->elantech->flags & ELANTECH_F_CRC_ENABLED0x10)
2410 return ((data & 0x08) == 0 ? 0 : -1);
2411 else
2412 return ((data & 0x1c) == 0x10 ? 0 : -1);
2413 case ELANTECH_PKT_TRACKPOINT0x06:
2414 return ((sc->packet[0] & 0xc8) == 0
2415 && sc->packet[1] == ((data & 0x10) << 3)
2416 && sc->packet[2] == ((data & 0x20) << 2)
2417 && (data ^ (sc->packet[0] & 0x30)) == 0x36
2418 ? 0 : -1);
2419 }
2420 return (-1);
2421 }
2422 return (0);
2423}
2424
2425void
2426pms_proc_elantech_v1(struct pms_softc *sc)
2427{
2428 struct elantech_softc *elantech = sc->elantech;
2429 int x, y, w, z;
2430 u_int buttons;
2431
2432 buttons = butmap[sc->packet[0] & 3];
2433
2434 if (elantech->flags & ELANTECH_F_HAS_ROCKER0x02) {
2435 if (sc->packet[0] & 0x40) /* up */
2436 buttons |= WSMOUSE_BUTTON(4)(1 << ((4) - 1));
2437 if (sc->packet[0] & 0x80) /* down */
2438 buttons |= WSMOUSE_BUTTON(5)(1 << ((5) - 1));
2439 }
2440
2441 if (elantech->flags & ELANTECH_F_HW_V1_OLD0x08)
2442 w = ((sc->packet[1] & 0x80) >> 7) +
2443 ((sc->packet[1] & 0x30) >> 4);
2444 else
2445 w = (sc->packet[0] & 0xc0) >> 6;
2446
2447 /*
2448 * Firmwares 0x20022 and 0x20600 have a bug, position data in the
2449 * first two reports for single-touch contacts may be corrupt.
2450 */
2451 if (elantech->fw_version == 0x20022 ||
2452 elantech->fw_version == 0x20600) {
2453 if (w == 1) {
2454 if (elantech->initial_pkt < 2) {
2455 elantech->initial_pkt++;
2456 return;
2457 }
2458 } else if (elantech->initial_pkt) {
2459 elantech->initial_pkt = 0;
2460 }
2461 }
2462
2463 /* Hardware version 1 doesn't report pressure. */
2464 if (w) {
2465 x = ((sc->packet[1] & 0x0c) << 6) | sc->packet[2];
2466 y = ((sc->packet[1] & 0x03) << 8) | sc->packet[3];
2467 z = SYNAPTICS_PRESSURE30;
2468 } else {
2469 x = y = z = 0;
2470 }
2471
2472 WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, w)do { wsmouse_buttons((sc->sc_wsmousedev), (buttons)); wsmouse_position
((sc->sc_wsmousedev), (x), (y)); wsmouse_touch((sc->sc_wsmousedev
), (z), (w)); wsmouse_input_sync(sc->sc_wsmousedev); } while
(0)
;
2473}
2474
2475void
2476pms_proc_elantech_v2(struct pms_softc *sc)
2477{
2478 const u_char debounce_pkt[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff };
2479 struct elantech_softc *elantech = sc->elantech;
2480 int x, y, w, z;
2481 u_int buttons;
2482
2483 /*
2484 * The hardware sends this packet when in debounce state.
2485 * The packet should be ignored.
2486 */
2487 if (!memcmp(sc->packet, debounce_pkt, sizeof(debounce_pkt))__builtin_memcmp((sc->packet), (debounce_pkt), (sizeof(debounce_pkt
)))
)
2488 return;
2489
2490 buttons = butmap[sc->packet[0] & 3];
2491
2492 w = (sc->packet[0] & 0xc0) >> 6;
2493 if (w == 1 || w == 3) {
2494 x = ((sc->packet[1] & 0x0f) << 8) | sc->packet[2];
2495 y = ((sc->packet[4] & 0x0f) << 8) | sc->packet[5];
2496 if (elantech->flags & ELANTECH_F_REPORTS_PRESSURE0x01)
2497 z = ((sc->packet[1] & 0xf0) |
2498 (sc->packet[4] & 0xf0) >> 4);
2499 else
2500 z = SYNAPTICS_PRESSURE30;
2501 } else if (w == 2) {
2502 x = (((sc->packet[0] & 0x10) << 4) | sc->packet[1]) << 2;
2503 y = (((sc->packet[0] & 0x20) << 3) | sc->packet[2]) << 2;
2504 z = SYNAPTICS_PRESSURE30;
2505 } else {
2506 x = y = z = 0;
2507 }
2508
2509 WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, w)do { wsmouse_buttons((sc->sc_wsmousedev), (buttons)); wsmouse_position
((sc->sc_wsmousedev), (x), (y)); wsmouse_touch((sc->sc_wsmousedev
), (z), (w)); wsmouse_input_sync(sc->sc_wsmousedev); } while
(0)
;
2510}
2511
2512void
2513pms_proc_elantech_v3(struct pms_softc *sc)
2514{
2515 const u_char debounce_pkt[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
2516 struct elantech_softc *elantech = sc->elantech;
2517 int x, y, w, z;
2518 u_int buttons;
2519
2520 buttons = butmap[sc->packet[0] & 3];
2521
2522 x = ((sc->packet[1] & 0x0f) << 8 | sc->packet[2]);
2523 y = ((sc->packet[4] & 0x0f) << 8 | sc->packet[5]);
2524 z = 0;
2525 w = (sc->packet[0] & 0xc0) >> 6;
2526 if (w == 2) {
2527 /*
2528 * Two-finger touch causes two packets -- a head packet
2529 * and a tail packet. We report a single event and ignore
2530 * the tail packet.
2531 */
2532 if (elantech->flags & ELANTECH_F_CRC_ENABLED0x10) {
2533 if ((sc->packet[3] & 0x09) != 0x08)
2534 return;
2535 } else {
2536 /* The hardware sends this packet when in debounce state.
2537 * The packet should be ignored. */
2538 if (!memcmp(sc->packet, debounce_pkt, sizeof(debounce_pkt))__builtin_memcmp((sc->packet), (debounce_pkt), (sizeof(debounce_pkt
)))
)
2539 return;
2540 if ((sc->packet[0] & 0x0c) != 0x04 &&
2541 (sc->packet[3] & 0xcf) != 0x02) {
2542 /* not the head packet -- ignore */
2543 return;
2544 }
2545 }
2546 }
2547
2548 /* Prevent jumping cursor if pad isn't touched or reports garbage. */
2549 if (w == 0 ||
2550 ((x == 0 || y == 0 || x == elantech->max_x || y == elantech->max_y)
2551 && (x != elantech->old_x || y != elantech->old_y))) {
2552 x = elantech->old_x;
2553 y = elantech->old_y;
2554 }
2555
2556 if (elantech->flags & ELANTECH_F_REPORTS_PRESSURE0x01)
2557 z = (sc->packet[1] & 0xf0) | ((sc->packet[4] & 0xf0) >> 4);
2558 else if (w)
2559 z = SYNAPTICS_PRESSURE30;
2560
2561 WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, w)do { wsmouse_buttons((sc->sc_wsmousedev), (buttons)); wsmouse_position
((sc->sc_wsmousedev), (x), (y)); wsmouse_touch((sc->sc_wsmousedev
), (z), (w)); wsmouse_input_sync(sc->sc_wsmousedev); } while
(0)
;
2562 elantech->old_x = x;
2563 elantech->old_y = y;
2564}
2565
2566void
2567pms_proc_elantech_v4(struct pms_softc *sc)
2568{
2569 struct elantech_softc *elantech = sc->elantech;
2570 struct device *sc_wsmousedev = sc->sc_wsmousedev;
2571 int id, weight, n, x, y, z;
2572 u_int buttons, slots;
2573
2574 switch (elantech_packet_type(elantech, sc->packet[3])) {
2575 case ELANTECH_V4_PKT_STATUS0:
2576 slots = elantech->mt_slots;
2577 elantech->mt_slots = sc->packet[1] & 0x1f;
2578 slots &= ~elantech->mt_slots;
2579 for (id = 0; slots; id++, slots >>= 1) {
2580 if (slots & 1)
2581 wsmouse_mtstate(sc_wsmousedev, id, 0, 0, 0);
2582 }
2583 break;
2584
2585 case ELANTECH_V4_PKT_HEAD0x01:
2586 id = ((sc->packet[3] & 0xe0) >> 5) - 1;
2587 if (id > -1 && id < ELANTECH_MAX_FINGERS5) {
2588 x = ((sc->packet[1] & 0x0f) << 8) | sc->packet[2];
2589 y = ((sc->packet[4] & 0x0f) << 8) | sc->packet[5];
2590 z = (sc->packet[1] & 0xf0)
2591 | ((sc->packet[4] & 0xf0) >> 4);
2592 wsmouse_mtstate(sc_wsmousedev, id, x, y, z);
2593 }
2594 break;
2595
2596 case ELANTECH_V4_PKT_MOTION0x02:
2597 weight = (sc->packet[0] & 0x10) ? ELANTECH_V4_WEIGHT_VALUE5 : 1;
2598 for (n = 0; n < 6; n += 3) {
2599 id = ((sc->packet[n] & 0xe0) >> 5) - 1;
2600 if (id < 0 || id >= ELANTECH_MAX_FINGERS5)
2601 continue;
2602 x = weight * (signed char)sc->packet[n + 1];
2603 y = weight * (signed char)sc->packet[n + 2];
2604 z = WSMOUSE_DEFAULT_PRESSURE45;
2605 wsmouse_set(sc_wsmousedev, WSMOUSE_MT_REL_X, x, id);
2606 wsmouse_set(sc_wsmousedev, WSMOUSE_MT_REL_Y, y, id);
2607 wsmouse_set(sc_wsmousedev, WSMOUSE_MT_PRESSURE, z, id);
2608 }
2609 break;
2610
2611 case ELANTECH_PKT_TRACKPOINT0x06:
2612 if (sc->sc_dev_enable & PMS_DEV_SECONDARY0x02) {
2613 x = sc->packet[4] - 0x100 + (sc->packet[1] << 1);
2614 y = sc->packet[5] - 0x100 + (sc->packet[2] << 1);
2615 buttons = butmap[sc->packet[0] & 7];
2616 WSMOUSE_INPUT(sc->sc_sec_wsmousedev,do { wsmouse_buttons((sc->sc_sec_wsmousedev), (buttons)); wsmouse_motion
((sc->sc_sec_wsmousedev), (x), (y), (0), (0)); wsmouse_input_sync
(sc->sc_sec_wsmousedev); } while (0)
2617 buttons, x, y, 0, 0)do { wsmouse_buttons((sc->sc_sec_wsmousedev), (buttons)); wsmouse_motion
((sc->sc_sec_wsmousedev), (x), (y), (0), (0)); wsmouse_input_sync
(sc->sc_sec_wsmousedev); } while (0)
;
2618 }
2619 return;
2620
2621 default:
2622 printf("%s: unknown packet type 0x%x\n", DEVNAME(sc)((sc)->sc_dev.dv_xname),
2623 sc->packet[3] & 0x1f);
2624 return;
2625 }
2626
2627 buttons = butmap[sc->packet[0] & 3];
2628 wsmouse_buttons(sc_wsmousedev, buttons);
2629
2630 wsmouse_input_sync(sc_wsmousedev);
2631}