Bug Summary

File:dev/wscons/wsmouse.c
Warning:line 1277, column 7
Array subscript is undefined

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 wsmouse.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/wscons/wsmouse.c
1/* $OpenBSD: wsmouse.c,v 1.67 2021/03/21 16:20:49 bru Exp $ */
2/* $NetBSD: wsmouse.c,v 1.35 2005/02/27 00:27:52 perry Exp $ */
3
4/*
5 * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Christopher G. Demetriou
18 * for the NetBSD Project.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/*
35 * Copyright (c) 1992, 1993
36 * The Regents of the University of California. All rights reserved.
37 *
38 * This software was developed by the Computer Systems Engineering group
39 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
40 * contributed to Berkeley.
41 *
42 * All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed by the University of
45 * California, Lawrence Berkeley Laboratory.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * @(#)ms.c 8.1 (Berkeley) 6/11/93
72 */
73
74/*
75 * Copyright (c) 2015, 2016 Ulf Brosziewski
76 *
77 * Permission to use, copy, modify, and distribute this software for any
78 * purpose with or without fee is hereby granted, provided that the above
79 * copyright notice and this permission notice appear in all copies.
80 *
81 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
82 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
83 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
84 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
85 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
86 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
87 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
88 */
89
90/*
91 * Mouse driver.
92 */
93
94#include <sys/param.h>
95#include <sys/conf.h>
96#include <sys/ioctl.h>
97#include <sys/fcntl.h>
98#include <sys/kernel.h>
99#include <sys/proc.h>
100#include <sys/syslog.h>
101#include <sys/systm.h>
102#include <sys/tty.h>
103#include <sys/signalvar.h>
104#include <sys/device.h>
105#include <sys/vnode.h>
106#include <sys/poll.h>
107#include <sys/malloc.h>
108
109#include <dev/wscons/wscons_features.h>
110#include <dev/wscons/wsconsio.h>
111#include <dev/wscons/wsmousevar.h>
112#include <dev/wscons/wseventvar.h>
113#include <dev/wscons/wsmouseinput.h>
114
115#include "wsmux.h"
116#include "wsdisplay.h"
117#include "wskbd.h"
118
119#include <dev/wscons/wsmuxvar.h>
120
121#if defined(WSMUX_DEBUG) && NWSMUX1 > 0
122#define DPRINTF(x) if (wsmuxdebug) printf x
123extern int wsmuxdebug;
124#else
125#define DPRINTF(x)
126#endif
127
128struct wsmouse_softc {
129 struct wsevsrc sc_base;
130
131 const struct wsmouse_accessops *sc_accessops;
132 void *sc_accesscookie;
133
134 struct wsmouseinput sc_input;
135
136 int sc_refcnt;
137 u_char sc_dying; /* device is being detached */
138};
139
140int wsmouse_match(struct device *, void *, void *);
141void wsmouse_attach(struct device *, struct device *, void *);
142int wsmouse_detach(struct device *, int);
143int wsmouse_activate(struct device *, int);
144
145int wsmouse_do_ioctl(struct wsmouse_softc *, u_long, caddr_t,
146 int, struct proc *);
147
148#if NWSMUX1 > 0
149int wsmouse_mux_open(struct wsevsrc *, struct wseventvar *);
150int wsmouse_mux_close(struct wsevsrc *);
151#endif
152
153int wsmousedoioctl(struct device *, u_long, caddr_t, int,
154 struct proc *);
155int wsmousedoopen(struct wsmouse_softc *, struct wseventvar *);
156
157struct cfdriver wsmouse_cd = {
158 NULL((void *)0), "wsmouse", DV_TTY
159};
160
161struct cfattach wsmouse_ca = {
162 sizeof (struct wsmouse_softc), wsmouse_match, wsmouse_attach,
163 wsmouse_detach, wsmouse_activate
164};
165
166#if NWSMUX1 > 0
167struct wssrcops wsmouse_srcops = {
168 .type = WSMUX_MOUSE1,
169 .dopen = wsmouse_mux_open,
170 .dclose = wsmouse_mux_close,
171 .dioctl = wsmousedoioctl,
172 .ddispioctl = NULL((void *)0),
173 .dsetdisplay = NULL((void *)0),
174};
175#endif
176
177/*
178 * Print function (for parent devices).
179 */
180int
181wsmousedevprint(void *aux, const char *pnp)
182{
183
184 if (pnp)
185 printf("wsmouse at %s", pnp);
186 return (UNCONF1);
187}
188
189int
190wsmouse_match(struct device *parent, void *match, void *aux)
191{
192 return (1);
193}
194
195void
196wsmouse_attach(struct device *parent, struct device *self, void *aux)
197{
198 struct wsmouse_softc *sc = (struct wsmouse_softc *)self;
199 struct wsmousedev_attach_args *ap = aux;
200#if NWSMUX1 > 0
201 int mux, error;
202#endif
203
204 sc->sc_accessops = ap->accessops;
205 sc->sc_accesscookie = ap->accesscookie;
206
207 sc->sc_input.evar = &sc->sc_base.me_evp;
208
209#if NWSMUX1 > 0
210 sc->sc_base.me_ops = &wsmouse_srcops;
211 mux = sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_muxcf_loc[0];
212 if (mux >= 0) {
213 error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base);
214 if (error)
215 printf(" attach error=%d", error);
216 else
217 printf(" mux %d", mux);
218 }
219#else
220#if 0 /* not worth keeping, especially since the default value is not -1... */
221 if (sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_muxcf_loc[0] >= 0)
222 printf(" (mux ignored)");
223#endif
224#endif /* NWSMUX > 0 */
225
226 printf("\n");
227}
228
229int
230wsmouse_activate(struct device *self, int act)
231{
232 struct wsmouse_softc *sc = (struct wsmouse_softc *)self;
233
234 if (act == DVACT_DEACTIVATE1)
235 sc->sc_dying = 1;
236 return (0);
237}
238
239/*
240 * Detach a mouse. To keep track of users of the softc we keep
241 * a reference count that's incremented while inside, e.g., read.
242 * If the mouse is active and the reference count is > 0 (0 is the
243 * normal state) we post an event and then wait for the process
244 * that had the reference to wake us up again. Then we blow away the
245 * vnode and return (which will deallocate the softc).
246 */
247int
248wsmouse_detach(struct device *self, int flags)
249{
250 struct wsmouse_softc *sc = (struct wsmouse_softc *)self;
251 struct wseventvar *evar;
252 int maj, mn;
253 int s;
254
255#if NWSMUX1 > 0
256 /* Tell parent mux we're leaving. */
257 if (sc->sc_base.me_parent != NULL((void *)0)) {
258 DPRINTF(("%s\n", __func__));
259 wsmux_detach_sc(&sc->sc_base);
260 }
261#endif
262
263 /* If we're open ... */
264 evar = sc->sc_base.me_evp;
265 if (evar != NULL((void *)0)) {
266 s = spltty()splraise(0x9);
267 if (--sc->sc_refcnt >= 0) {
268 /* Wake everyone by generating a dummy event. */
269 if (++evar->put >= WSEVENT_QSIZE256)
270 evar->put = 0;
271 WSEVENT_WAKEUP(evar){ selwakeup(&(evar)->sel); if ((evar)->wanted) { (evar
)->wanted = 0; wakeup((caddr_t)(evar)); } if ((evar)->async
) pgsigio(&(evar)->sigio, 23, 0); }
;
272 /* Wait for processes to go away. */
273 if (tsleep_nsec(sc, PZERO22, "wsmdet", SEC_TO_NSEC(60)))
274 printf("wsmouse_detach: %s didn't detach\n",
275 sc->sc_base.me_dv.dv_xname);
276 }
277 splx(s)spllower(s);
278 }
279
280 /* locate the major number */
281 for (maj = 0; maj < nchrdev; maj++)
282 if (cdevsw[maj].d_open == wsmouseopen)
283 break;
284
285 /* Nuke the vnodes for any open instances (calls close). */
286 mn = self->dv_unit;
287 vdevgone(maj, mn, mn, VCHR);
288
289 wsmouse_input_cleanup(&sc->sc_input);
290
291 return (0);
292}
293
294int
295wsmouseopen(dev_t dev, int flags, int mode, struct proc *p)
296{
297 struct wsmouse_softc *sc;
298 struct wseventvar *evar;
299 int error, unit;
300
301 unit = minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
;
302 if (unit >= wsmouse_cd.cd_ndevs || /* make sure it was attached */
303 (sc = wsmouse_cd.cd_devs[unit]) == NULL((void *)0))
304 return (ENXIO6);
305
306#if NWSMUX1 > 0
307 DPRINTF(("%s: %s mux=%p\n", __func__, sc->sc_base.me_dv.dv_xname,
308 sc->sc_base.me_parent));
309#endif
310
311 if (sc->sc_dying)
312 return (EIO5);
313
314 if ((flags & (FREAD0x0001 | FWRITE0x0002)) == FWRITE0x0002)
315 return (0); /* always allow open for write
316 so ioctl() is possible. */
317
318#if NWSMUX1 > 0
319 if (sc->sc_base.me_parent != NULL((void *)0)) {
320 /* Grab the mouse out of the greedy hands of the mux. */
321 DPRINTF(("%s: detach\n", __func__));
322 wsmux_detach_sc(&sc->sc_base);
323 }
324#endif
325
326 if (sc->sc_base.me_evp != NULL((void *)0))
327 return (EBUSY16);
328
329 evar = &sc->sc_base.me_evar;
330 if (wsevent_init(evar))
331 return (EBUSY16);
332
333 error = wsmousedoopen(sc, evar);
334 if (error)
335 wsevent_fini(evar);
336 return (error);
337}
338
339int
340wsmouseclose(dev_t dev, int flags, int mode, struct proc *p)
341{
342 struct wsmouse_softc *sc =
343 (struct wsmouse_softc *)wsmouse_cd.cd_devs[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
];
344 struct wseventvar *evar = sc->sc_base.me_evp;
345
346 if ((flags & (FREAD0x0001 | FWRITE0x0002)) == FWRITE0x0002)
347 /* Not open for read */
348 return (0);
349
350 sc->sc_base.me_evp = NULL((void *)0);
351 (*sc->sc_accessops->disable)(sc->sc_accesscookie);
352 wsevent_fini(evar);
353
354#if NWSMUX1 > 0
355 if (sc->sc_base.me_parent == NULL((void *)0)) {
356 int mux, error;
357
358 DPRINTF(("%s: attach\n", __func__));
359 mux = sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_muxcf_loc[0];
360 if (mux >= 0) {
361 error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base);
362 if (error)
363 printf("%s: can't attach mux (error=%d)\n",
364 sc->sc_base.me_dv.dv_xname, error);
365 }
366 }
367#endif
368
369 return (0);
370}
371
372int
373wsmousedoopen(struct wsmouse_softc *sc, struct wseventvar *evp)
374{
375 int error;
376
377 /* The device could already be attached to a mux. */
378 if (sc->sc_base.me_evp != NULL((void *)0))
379 return (EBUSY16);
380 sc->sc_base.me_evp = evp;
381
382 wsmouse_input_reset(&sc->sc_input);
383
384 /* enable the device, and punt if that's not possible */
385 error = (*sc->sc_accessops->enable)(sc->sc_accesscookie);
386 if (error)
387 sc->sc_base.me_evp = NULL((void *)0);
388 return (error);
389}
390
391int
392wsmouseread(dev_t dev, struct uio *uio, int flags)
393{
394 struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
];
395 int error;
396
397 if (sc->sc_dying)
398 return (EIO5);
399
400#ifdef DIAGNOSTIC1
401 if (sc->sc_base.me_evp == NULL((void *)0)) {
402 printf("wsmouseread: evp == NULL\n");
403 return (EINVAL22);
404 }
405#endif
406
407 sc->sc_refcnt++;
408 error = wsevent_read(sc->sc_base.me_evp, uio, flags);
409 if (--sc->sc_refcnt < 0) {
410 wakeup(sc);
411 error = EIO5;
412 }
413 return (error);
414}
415
416int
417wsmouseioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
418{
419 return (wsmousedoioctl(wsmouse_cd.cd_devs[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
],
420 cmd, data, flag, p));
421}
422
423/* A wrapper around the ioctl() workhorse to make reference counting easy. */
424int
425wsmousedoioctl(struct device *dv, u_long cmd, caddr_t data, int flag,
426 struct proc *p)
427{
428 struct wsmouse_softc *sc = (struct wsmouse_softc *)dv;
429 int error;
430
431 sc->sc_refcnt++;
432 error = wsmouse_do_ioctl(sc, cmd, data, flag, p);
433 if (--sc->sc_refcnt < 0)
434 wakeup(sc);
435 return (error);
436}
437
438int
439wsmouse_param_ioctl(struct wsmouse_softc *sc,
440 u_long cmd, struct wsmouse_param *params, u_int nparams)
441{
442 struct wsmouse_param *buf;
443 int error, s, size;
444
445 if (params == NULL((void *)0) || nparams > WSMOUSECFG_MAX41)
446 return (EINVAL22);
447
448 size = nparams * sizeof(struct wsmouse_param);
449 buf = malloc(size, M_DEVBUF2, M_WAITOK0x0001);
450 if (buf == NULL((void *)0))
451 return (ENOMEM12);
452
453 if ((error = copyin(params, buf, size))) {
454 free(buf, M_DEVBUF2, size);
455 return (error);
456 }
457
458 s = spltty()splraise(0x9);
459 if (cmd == WSMOUSEIO_SETPARAMS((unsigned long)0x80000000 | ((sizeof(struct wsmouse_parameters
) & 0x1fff) << 16) | ((('W')) << 8) | ((40)))
) {
460 if (wsmouse_set_params((struct device *) sc, buf, nparams))
461 error = EINVAL22;
462 } else {
463 if (wsmouse_get_params((struct device *) sc, buf, nparams))
464 error = EINVAL22;
465 else
466 error = copyout(buf, params, size);
467 }
468 splx(s)spllower(s);
469 free(buf, M_DEVBUF2, size);
470 return (error);
471}
472
473int
474wsmouse_do_ioctl(struct wsmouse_softc *sc, u_long cmd, caddr_t data, int flag,
475 struct proc *p)
476{
477 struct wseventvar *evar;
478 int error;
479
480 if (sc->sc_dying)
481 return (EIO5);
482
483 /*
484 * Try the generic ioctls that the wsmouse interface supports.
485 */
486
487 switch (cmd) {
488 case FIOASYNC((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((125)))
:
489 case FIOSETOWN((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((124)))
:
490 case TIOCSPGRP((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((118)))
:
491 if ((flag & FWRITE0x0002) == 0)
492 return (EACCES13);
493 }
494
495 switch (cmd) {
496 case FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((126)))
: /* we will remove this someday (soon???) */
497 return (0);
498
499 case FIOASYNC((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((125)))
:
500 if (sc->sc_base.me_evp == NULL((void *)0))
501 return (EINVAL22);
502 sc->sc_base.me_evp->async = *(int *)data != 0;
503 return (0);
504
505 case FIOGETOWN((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((123)))
:
506 case TIOCGPGRP((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((119)))
:
507 evar = sc->sc_base.me_evp;
508 if (evar == NULL((void *)0))
509 return (EINVAL22);
510 sigio_getown(&evar->sigio, cmd, data);
511 return (0);
512
513 case FIOSETOWN((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((124)))
:
514 case TIOCSPGRP((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((118)))
:
515 evar = sc->sc_base.me_evp;
516 if (evar == NULL((void *)0))
517 return (EINVAL22);
518 return (sigio_setown(&evar->sigio, cmd, data));
519
520 case WSMOUSEIO_GETPARAMS((unsigned long)0x80000000 | ((sizeof(struct wsmouse_parameters
) & 0x1fff) << 16) | ((('W')) << 8) | ((39)))
:
521 case WSMOUSEIO_SETPARAMS((unsigned long)0x80000000 | ((sizeof(struct wsmouse_parameters
) & 0x1fff) << 16) | ((('W')) << 8) | ((40)))
:
522 return (wsmouse_param_ioctl(sc, cmd,
523 ((struct wsmouse_parameters *) data)->params,
524 ((struct wsmouse_parameters *) data)->nparams));
525 }
526
527 /*
528 * Try the mouse driver for WSMOUSEIO ioctls. It returns -1
529 * if it didn't recognize the request.
530 */
531 error = (*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd,
532 data, flag, p);
533 return (error != -1 ? error : ENOTTY25);
534}
535
536int
537wsmousepoll(dev_t dev, int events, struct proc *p)
538{
539 struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
];
540
541 if (sc->sc_base.me_evp == NULL((void *)0))
542 return (POLLERR0x0008);
543 return (wsevent_poll(sc->sc_base.me_evp, events, p));
544}
545
546int
547wsmousekqfilter(dev_t dev, struct knote *kn)
548{
549 struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
];
550
551 if (sc->sc_base.me_evp == NULL((void *)0))
552 return (ENXIO6);
553 return (wsevent_kqfilter(sc->sc_base.me_evp, kn));
554}
555
556#if NWSMUX1 > 0
557int
558wsmouse_mux_open(struct wsevsrc *me, struct wseventvar *evp)
559{
560 struct wsmouse_softc *sc = (struct wsmouse_softc *)me;
561
562 return (wsmousedoopen(sc, evp));
563}
564
565int
566wsmouse_mux_close(struct wsevsrc *me)
567{
568 struct wsmouse_softc *sc = (struct wsmouse_softc *)me;
569
570 (*sc->sc_accessops->disable)(sc->sc_accesscookie);
571 sc->sc_base.me_evp = NULL((void *)0);
572
573 return (0);
574}
575
576int
577wsmouse_add_mux(int unit, struct wsmux_softc *muxsc)
578{
579 struct wsmouse_softc *sc;
580
581 if (unit < 0 || unit >= wsmouse_cd.cd_ndevs ||
582 (sc = wsmouse_cd.cd_devs[unit]) == NULL((void *)0))
583 return (ENXIO6);
584
585 if (sc->sc_base.me_parent != NULL((void *)0) || sc->sc_base.me_evp != NULL((void *)0))
586 return (EBUSY16);
587
588 return (wsmux_attach_sc(muxsc, &sc->sc_base));
589}
590#endif /* NWSMUX > 0 */
591
592void
593wsmouse_buttons(struct device *sc, u_int buttons)
594{
595 struct btn_state *btn = &((struct wsmouse_softc *) sc)->sc_input.btn;
596
597 if (btn->sync)
598 /* Restore the old state. */
599 btn->buttons ^= btn->sync;
600
601 btn->sync = btn->buttons ^ buttons;
602 btn->buttons = buttons;
603}
604
605void
606wsmouse_motion(struct device *sc, int dx, int dy, int dz, int dw)
607{
608 struct motion_state *motion =
609 &((struct wsmouse_softc *) sc)->sc_input.motion;
610
611 motion->dx = dx;
612 motion->dy = dy;
613 motion->dz = dz;
614 motion->dw = dw;
615 if (dx || dy || dz || dw)
616 motion->sync |= SYNC_DELTAS(1 << 0);
617}
618
619static inline void
620set_x(struct position *pos, int x, u_int *sync, u_int mask)
621{
622 if (*sync & mask) {
623 if (x == pos->x)
624 return;
625 pos->x -= pos->dx;
626 pos->acc_dx -= pos->dx;
627 }
628 if ((pos->dx = x - pos->x)) {
629 pos->x = x;
630 if ((pos->dx > 0) == (pos->acc_dx > 0))
631 pos->acc_dx += pos->dx;
632 else
633 pos->acc_dx = pos->dx;
634 *sync |= mask;
635 }
636}
637
638static inline void
639set_y(struct position *pos, int y, u_int *sync, u_int mask)
640{
641 if (*sync & mask) {
642 if (y == pos->y)
643 return;
644 pos->y -= pos->dy;
645 pos->acc_dy -= pos->dy;
646 }
647 if ((pos->dy = y - pos->y)) {
648 pos->y = y;
649 if ((pos->dy > 0) == (pos->acc_dy > 0))
650 pos->acc_dy += pos->dy;
651 else
652 pos->acc_dy = pos->dy;
653 *sync |= mask;
654 }
655}
656
657static inline void
658cleardeltas(struct position *pos)
659{
660 pos->dx = pos->acc_dx = 0;
661 pos->dy = pos->acc_dy = 0;
662}
663
664void
665wsmouse_position(struct device *sc, int x, int y)
666{
667 struct motion_state *motion =
668 &((struct wsmouse_softc *) sc)->sc_input.motion;
669
670 set_x(&motion->pos, x, &motion->sync, SYNC_X(1 << 1));
671 set_y(&motion->pos, y, &motion->sync, SYNC_Y(1 << 2));
672}
673
674static inline int
675normalized_pressure(struct wsmouseinput *input, int pressure)
676{
677 int limit = imax(input->touch.min_pressure, 1);
678
679 if (pressure >= limit)
680 return pressure;
681 else
682 return (pressure < 0 ? limit : 0);
683}
684
685void
686wsmouse_touch(struct device *sc, int pressure, int contacts)
687{
688 struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input;
689 struct touch_state *touch = &input->touch;
690
691 pressure = normalized_pressure(input, pressure);
692 contacts = (pressure ? imax(contacts, 1) : 0);
693
694 if (pressure == 0 || pressure != touch->pressure) {
695 /*
696 * pressure == 0: Drivers may report possibly arbitrary
697 * coordinates in this case; touch_update will correct them.
698 */
699 touch->pressure = pressure;
700 touch->sync |= SYNC_PRESSURE(1 << 0);
701 }
702 if (contacts != touch->contacts) {
703 touch->contacts = contacts;
704 touch->sync |= SYNC_CONTACTS(1 << 1);
705 }
706}
707
708void
709wsmouse_mtstate(struct device *sc, int slot, int x, int y, int pressure)
710{
711 struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input;
712 struct mt_state *mt = &input->mt;
713 struct mt_slot *mts;
714 u_int bit;
715
716 if (slot < 0 || slot >= mt->num_slots)
717 return;
718
719 bit = (1 << slot);
720 mt->frame |= bit;
721
722 mts = &mt->slots[slot];
723
724 set_x(&mts->pos, x, mt->sync + MTS_X1, bit);
725 set_y(&mts->pos, y, mt->sync + MTS_Y2, bit);
726
727 /* Is this a new touch? */
728 if ((mt->touches & bit) == (mt->sync[MTS_TOUCH0] & bit))
729 cleardeltas(&mts->pos);
730
731 pressure = normalized_pressure(input, pressure);
732 if (pressure != mts->pressure) {
733 mts->pressure = pressure;
734 mt->sync[MTS_PRESSURE3] |= bit;
735
736 if (pressure) {
737 if ((mt->touches & bit) == 0) {
738 mt->num_touches++;
739 mt->touches |= bit;
740 mt->sync[MTS_TOUCH0] |= bit;
741
742 mt->sync[MTS_X1] |= bit;
743 mt->sync[MTS_Y2] |= bit;
744 }
745 } else if (mt->touches & bit) {
746 mt->num_touches--;
747 mt->touches ^= bit;
748 mt->sync[MTS_TOUCH0] |= bit;
749 mt->ptr_mask &= mt->touches;
750 }
751 }
752}
753
754void
755wsmouse_set(struct device *sc, enum wsmouseval type, int value, int aux)
756{
757 struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input;
758 struct mt_slot *mts;
759
760 if (WSMOUSE_IS_MT_CODE(type)((type) >= WSMOUSE_MT_REL_X && (type) <= WSMOUSE_MT_PRESSURE
)
) {
761 if (aux < 0 || aux >= input->mt.num_slots)
762 return;
763 mts = &input->mt.slots[aux];
764 }
765
766 switch (type) {
767 case WSMOUSE_REL_X:
768 value += input->motion.pos.x; /* fall through */
769 case WSMOUSE_ABS_X:
770 wsmouse_position(sc, value, input->motion.pos.y);
771 return;
772 case WSMOUSE_REL_Y:
773 value += input->motion.pos.y; /* fall through */
774 case WSMOUSE_ABS_Y:
775 wsmouse_position(sc, input->motion.pos.x, value);
776 return;
777 case WSMOUSE_PRESSURE:
778 wsmouse_touch(sc, value, input->touch.contacts);
779 return;
780 case WSMOUSE_CONTACTS:
781 /* Contact counts can be overridden by wsmouse_touch. */
782 if (value != input->touch.contacts) {
783 input->touch.contacts = value;
784 input->touch.sync |= SYNC_CONTACTS(1 << 1);
785 }
786 return;
787 case WSMOUSE_TOUCH_WIDTH:
788 if (value != input->touch.width) {
789 input->touch.width = value;
790 input->touch.sync |= SYNC_TOUCH_WIDTH(1 << 2);
791 }
792 return;
793 case WSMOUSE_MT_REL_X:
794 value += mts->pos.x; /* fall through */
795 case WSMOUSE_MT_ABS_X:
796 wsmouse_mtstate(sc, aux, value, mts->pos.y, mts->pressure);
797 return;
798 case WSMOUSE_MT_REL_Y:
799 value += mts->pos.y; /* fall through */
800 case WSMOUSE_MT_ABS_Y:
801 wsmouse_mtstate(sc, aux, mts->pos.x, value, mts->pressure);
802 return;
803 case WSMOUSE_MT_PRESSURE:
804 wsmouse_mtstate(sc, aux, mts->pos.x, mts->pos.y, value);
805 return;
806 }
807}
808
809/* Make touch and motion state consistent. */
810void
811wsmouse_touch_update(struct wsmouseinput *input)
812{
813 struct motion_state *motion = &input->motion;
814 struct touch_state *touch = &input->touch;
815
816 if (touch->pressure == 0) {
817 /*
818 * There may be zero coordinates, or coordinates of
819 * touches with pressure values below min_pressure.
820 */
821 if (motion->sync & SYNC_POSITION((1 << 1) | (1 << 2))) {
822 /* Restore valid coordinates. */
823 motion->pos.x -= motion->pos.dx;
824 motion->pos.y -= motion->pos.dy;
825 motion->sync &= ~SYNC_POSITION((1 << 1) | (1 << 2));
826 }
827
828 if (touch->prev_contacts == 0)
829 touch->sync &= ~SYNC_PRESSURE(1 << 0);
830
831 }
832
833 if (touch->sync & SYNC_CONTACTS(1 << 1))
834 /* Suppress pointer movement. */
835 cleardeltas(&motion->pos);
836
837 if ((touch->sync & SYNC_PRESSURE(1 << 0)) && touch->min_pressure) {
838 if (touch->pressure >= input->filter.pressure_hi)
839 touch->min_pressure = input->filter.pressure_lo;
840 else if (touch->pressure < input->filter.pressure_lo)
841 touch->min_pressure = input->filter.pressure_hi;
842 }
843}
844
845/* Normalize multitouch state. */
846void
847wsmouse_mt_update(struct wsmouseinput *input)
848{
849 int i;
850
851 /*
852 * The same as above: There may be arbitrary coordinates if
853 * (pressure == 0). Clear the sync flags for touches that have
854 * been released.
855 */
856 if (input->mt.frame & ~input->mt.touches) {
857 for (i = MTS_X1; i < MTS_SIZE4; i++)
858 input->mt.sync[i] &= input->mt.touches;
859 }
860}
861
862/* Return TRUE if a coordinate update may be noise. */
863int
864wsmouse_hysteresis(struct wsmouseinput *input, struct position *pos)
865{
866 return (abs(pos->acc_dx) < input->filter.h.hysteresis
867 && abs(pos->acc_dy) < input->filter.v.hysteresis);
868}
869
870/*
871 * Select the pointer-controlling MT slot.
872 *
873 * Pointer-control is assigned to slots with non-zero motion deltas if
874 * at least one such slot exists. This function doesn't impose any
875 * restrictions on the way drivers use wsmouse_mtstate(), it covers
876 * partial, unordered, and "delta-filtered" input.
877 *
878 * The "cycle" is the set of slots with X/Y updates in previous sync
879 * operations; it will be cleared and rebuilt whenever a slot that is
880 * being updated is already a member. If a cycle ends that doesn't
881 * contain the pointer-controlling slot, a new slot will be selected.
882 */
883void
884wsmouse_ptr_ctrl(struct wsmouseinput *input)
885{
886 struct mt_state *mt = &input->mt;
887 u_int updates;
888 int select, slot;
889
890 mt->prev_ptr = mt->ptr;
891
892 if (mt->num_touches <= 1) {
893 mt->ptr = mt->touches;
894 mt->ptr_cycle = mt->ptr;
895 return;
896 }
897
898 updates = (mt->sync[MTS_X1] | mt->sync[MTS_Y2]) & ~mt->sync[MTS_TOUCH0];
899 FOREACHBIT(updates, slot)for ((slot) = ffs(updates) - 1; (slot) != -1; (slot) = ffs((updates
) & (~1 << (slot))) - 1)
{
900 /*
901 * Touches that just produce noise are no problem if the
902 * frequency of zero deltas is high enough, but there might
903 * be no guarantee for that.
904 */
905 if (wsmouse_hysteresis(input, &mt->slots[slot].pos))
906 updates ^= (1 << slot);
907 }
908
909 /*
910 * If there is no pointer-controlling slot, or if it should be
911 * masked, select a new one.
912 */
913 select = ((mt->ptr & mt->touches & ~mt->ptr_mask) == 0);
914
915 /* Remove slots without coordinate deltas from the cycle. */
916 mt->ptr_cycle &= ~(mt->frame ^ updates);
917
918 if (mt->ptr_cycle & updates) {
919 select |= ((mt->ptr_cycle & mt->ptr) == 0);
920 mt->ptr_cycle = updates;
921 } else {
922 mt->ptr_cycle |= updates;
923 }
924 if (select) {
925 if (mt->ptr_cycle & ~mt->ptr_mask)
926 slot = ffs(mt->ptr_cycle & ~mt->ptr_mask) - 1;
927 else if (mt->touches & ~mt->ptr_mask)
928 slot = ffs(mt->touches & ~mt->ptr_mask) - 1;
929 else
930 slot = ffs(mt->touches) - 1;
931 mt->ptr = (1 << slot);
932 }
933}
934
935/* Derive touch and motion state from MT state. */
936void
937wsmouse_mt_convert(struct device *sc)
938{
939 struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input;
940 struct mt_state *mt = &input->mt;
941 struct mt_slot *mts;
942 int slot, pressure;
943
944 wsmouse_ptr_ctrl(input);
945
946 if (mt->ptr) {
947 slot = ffs(mt->ptr) - 1;
948 mts = &mt->slots[slot];
949 if (mts->pos.x != input->motion.pos.x)
950 input->motion.sync |= SYNC_X(1 << 1);
951 if (mts->pos.y != input->motion.pos.y)
952 input->motion.sync |= SYNC_Y(1 << 2);
953 if (mt->ptr != mt->prev_ptr)
954 /* Suppress pointer movement. */
955 mts->pos.dx = mts->pos.dy = 0;
956 memcpy(&input->motion.pos, &mts->pos, sizeof(struct position))__builtin_memcpy((&input->motion.pos), (&mts->pos
), (sizeof(struct position)))
;
957
958 pressure = mts->pressure;
959 } else {
960 pressure = 0;
961 }
962
963 wsmouse_touch(sc, pressure, mt->num_touches);
964}
965
966void
967wsmouse_evq_put(struct evq_access *evq, int ev_type, int ev_value)
968{
969 struct wscons_event *ev;
970 int space;
971
972 space = evq->evar->get - evq->put;
973 if (space != 1 && space != 1 - WSEVENT_QSIZE256) {
974 ev = &evq->evar->q[evq->put++];
975 evq->put %= WSEVENT_QSIZE256;
976 ev->type = ev_type;
977 ev->value = ev_value;
978 memcpy(&ev->time, &evq->ts, sizeof(struct timespec))__builtin_memcpy((&ev->time), (&evq->ts), (sizeof
(struct timespec)))
;
979 evq->result |= EVQ_RESULT_SUCCESS1;
980 } else {
981 evq->result = EVQ_RESULT_OVERFLOW-1;
982 }
983}
984
985
986void
987wsmouse_btn_sync(struct btn_state *btn, struct evq_access *evq)
988{
989 int button, ev_type;
990 u_int bit, sync;
991
992 for (sync = btn->sync; sync; sync ^= bit) {
993 button = ffs(sync) - 1;
994 bit = (1 << button);
995 ev_type = (btn->buttons & bit) ? BTN_DOWN_EV5 : BTN_UP_EV4;
996 wsmouse_evq_put(evq, ev_type, button);
997 }
998}
999
1000/*
1001 * Scale with a [*.12] fixed-point factor and a remainder:
1002 */
1003static inline int
1004scale(int val, int factor, int *rmdr)
1005{
1006 val = val * factor + *rmdr;
1007 if (val >= 0) {
1008 *rmdr = val & 0xfff;
1009 return (val >> 12);
1010 } else {
1011 *rmdr = -(-val & 0xfff);
1012 return -(-val >> 12);
1013 }
1014}
1015
1016void
1017wsmouse_motion_sync(struct wsmouseinput *input, struct evq_access *evq)
1018{
1019 struct motion_state *motion = &input->motion;
1020 struct axis_filter *h = &input->filter.h;
1021 struct axis_filter *v = &input->filter.v;
1022 int x, y, dx, dy, dz, dw;
1023
1024 if (motion->sync & SYNC_DELTAS(1 << 0)) {
1025 dx = h->inv ? -motion->dx : motion->dx;
1026 dy = v->inv ? -motion->dy : motion->dy;
1027 if (h->scale)
1028 dx = scale(dx, h->scale, &h->rmdr);
1029 if (v->scale)
1030 dy = scale(dy, v->scale, &v->rmdr);
1031 if (dx)
1032 wsmouse_evq_put(evq, DELTA_X_EV(input)((input)->filter.swapxy ? 7 : 6), dx);
1033 if (dy)
1034 wsmouse_evq_put(evq, DELTA_Y_EV(input)((input)->filter.swapxy ? 6 : 7), dy);
1035 if (motion->dz) {
1036 dz = (input->flags & REVERSE_SCROLLING(1 << 3))
1037 ? -motion->dz : motion->dz;
1038 if (IS_TOUCHPAD(input)((input)->hw.hw_type == WSMOUSEHW_TOUCHPAD || (input)->
hw.hw_type == WSMOUSEHW_CLICKPAD)
)
1039 wsmouse_evq_put(evq, VSCROLL_EV27, dz);
1040 else
1041 wsmouse_evq_put(evq, DELTA_Z_EV10, dz);
1042 }
1043 if (motion->dw) {
1044 dw = (input->flags & REVERSE_SCROLLING(1 << 3))
1045 ? -motion->dw : motion->dw;
1046 if (IS_TOUCHPAD(input)((input)->hw.hw_type == WSMOUSEHW_TOUCHPAD || (input)->
hw.hw_type == WSMOUSEHW_CLICKPAD)
)
1047 wsmouse_evq_put(evq, HSCROLL_EV26, dw);
1048 else
1049 wsmouse_evq_put(evq, DELTA_W_EV16, dw);
1050 }
1051 }
1052 if (motion->sync & SYNC_POSITION((1 << 1) | (1 << 2))) {
1053 if (motion->sync & SYNC_X(1 << 1)) {
1054 x = (h->inv ? h->inv - motion->pos.x : motion->pos.x);
1055 wsmouse_evq_put(evq, ABS_X_EV(input)((input)->filter.swapxy ? 9 : 8), x);
1056 }
1057 if (motion->sync & SYNC_Y(1 << 2)) {
1058 y = (v->inv ? v->inv - motion->pos.y : motion->pos.y);
1059 wsmouse_evq_put(evq, ABS_Y_EV(input)((input)->filter.swapxy ? 8 : 9), y);
1060 }
1061 if (motion->pos.dx == 0 && motion->pos.dy == 0
1062 && (input->flags & TPAD_NATIVE_MODE(1 << 1) ))
1063 /* Suppress pointer motion. */
1064 wsmouse_evq_put(evq, WSCONS_EVENT_TOUCH_RESET25, 0);
1065 }
1066}
1067
1068void
1069wsmouse_touch_sync(struct wsmouseinput *input, struct evq_access *evq)
1070{
1071 struct touch_state *touch = &input->touch;
1072
1073 if (touch->sync & SYNC_PRESSURE(1 << 0))
1074 wsmouse_evq_put(evq, ABS_Z_EV11, touch->pressure);
1075 if (touch->sync & SYNC_CONTACTS(1 << 1))
1076 wsmouse_evq_put(evq, ABS_W_EV17, touch->contacts);
1077 if ((touch->sync & SYNC_TOUCH_WIDTH(1 << 2))
1078 && (input->flags & TPAD_NATIVE_MODE(1 << 1)))
1079 wsmouse_evq_put(evq, WSCONS_EVENT_TOUCH_WIDTH24, touch->width);
1080}
1081
1082void
1083wsmouse_log_input(struct wsmouseinput *input, struct timespec *ts)
1084{
1085 struct motion_state *motion = &input->motion;
1086 int t_sync, mt_sync;
1087
1088 t_sync = (input->touch.sync & SYNC_CONTACTS(1 << 1));
1089 mt_sync = (input->mt.frame && (input->mt.sync[MTS_TOUCH0]
1090 || input->mt.ptr != input->mt.prev_ptr));
1091
1092 if (motion->sync || mt_sync || t_sync || input->btn.sync)
1093 printf("[%s-in][%04d]", DEVNAME(input)((char *) (input) - __builtin_offsetof(struct wsmouse_softc, sc_input
) + __builtin_offsetof(struct device, dv_xname))
, LOGTIME(ts)((int) (((ts)->tv_sec % 10) * 1000 + ((ts)->tv_nsec / 1000000
)))
);
1094 else
1095 return;
1096
1097 if (motion->sync & SYNC_POSITION((1 << 1) | (1 << 2)))
1098 printf(" abs:%d,%d", motion->pos.x, motion->pos.y);
1099 if (motion->sync & SYNC_DELTAS(1 << 0))
1100 printf(" rel:%d,%d,%d,%d", motion->dx, motion->dy,
1101 motion->dz, motion->dw);
1102 if (mt_sync)
1103 printf(" mt:0x%02x:%d", input->mt.touches,
1104 ffs(input->mt.ptr) - 1);
1105 else if (t_sync)
1106 printf(" t:%d", input->touch.contacts);
1107 if (input->btn.sync)
1108 printf(" btn:0x%02x", input->btn.buttons);
1109 printf("\n");
1110}
1111
1112void
1113wsmouse_log_events(struct wsmouseinput *input, struct evq_access *evq)
1114{
1115 struct wscons_event *ev;
1116 int n = evq->evar->put;
1117
1118 if (n != evq->put) {
1119 printf("[%s-ev][%04d]", DEVNAME(input)((char *) (input) - __builtin_offsetof(struct wsmouse_softc, sc_input
) + __builtin_offsetof(struct device, dv_xname))
, LOGTIME(&evq->ts)((int) (((&evq->ts)->tv_sec % 10) * 1000 + ((&evq
->ts)->tv_nsec / 1000000)))
);
1120 while (n != evq->put) {
1121 ev = &evq->evar->q[n++];
1122 n %= WSEVENT_QSIZE256;
1123 printf(" %d:%d", ev->type, ev->value);
1124 }
1125 printf("\n");
1126 }
1127}
1128
1129static inline void
1130clear_sync_flags(struct wsmouseinput *input)
1131{
1132 int i;
1133
1134 input->btn.sync = 0;
1135 input->sbtn.sync = 0;
1136 input->motion.sync = 0;
1137 input->touch.sync = 0;
1138 input->touch.prev_contacts = input->touch.contacts;
1139 if (input->mt.frame) {
1140 input->mt.frame = 0;
1141 for (i = 0; i < MTS_SIZE4; i++)
1142 input->mt.sync[i] = 0;
1143 }
1144}
1145
1146void
1147wsmouse_input_sync(struct device *sc)
1148{
1149 struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input;
1150 struct evq_access evq;
1151
1152 evq.evar = *input->evar;
1153 if (evq.evar == NULL((void *)0))
1154 return;
1155 evq.put = evq.evar->put;
1156 evq.result = EVQ_RESULT_NONE0;
1157 getnanotime(&evq.ts);
1158
1159 enqueue_randomness(input->btn.buttons
1160 ^ input->motion.dx ^ input->motion.dy
1161 ^ input->motion.pos.x ^ input->motion.pos.y
1162 ^ input->motion.dz ^ input->motion.dw);
1163
1164 if (input->mt.frame) {
1165 wsmouse_mt_update(input);
1166 wsmouse_mt_convert(sc);
1167 }
1168 if (input->touch.sync)
1169 wsmouse_touch_update(input);
1170
1171 if (input->flags & LOG_INPUT(1 << 19))
1172 wsmouse_log_input(input, &evq.ts);
1173
1174 if (input->flags & TPAD_COMPAT_MODE(1 << 0))
1175 wstpad_compat_convert(input, &evq);
1176
1177 if (input->flags & RESYNC(1 << 16)) {
1178 input->flags &= ~RESYNC(1 << 16);
1179 input->motion.sync &= SYNC_POSITION((1 << 1) | (1 << 2));
1180 }
1181
1182 if (input->btn.sync)
1183 wsmouse_btn_sync(&input->btn, &evq);
1184 if (input->sbtn.sync)
1185 wsmouse_btn_sync(&input->sbtn, &evq);
1186 if (input->motion.sync)
1187 wsmouse_motion_sync(input, &evq);
1188 if (input->touch.sync)
1189 wsmouse_touch_sync(input, &evq);
1190 /* No MT events are generated yet. */
1191
1192 if (evq.result == EVQ_RESULT_SUCCESS1) {
1193 wsmouse_evq_put(&evq, WSCONS_EVENT_SYNC18, 0);
1194 if (evq.result == EVQ_RESULT_SUCCESS1) {
1195 if (input->flags & LOG_EVENTS(1 << 20)) {
1196 wsmouse_log_events(input, &evq);
1197 }
1198 evq.evar->put = evq.put;
1199 WSEVENT_WAKEUP(evq.evar){ selwakeup(&(evq.evar)->sel); if ((evq.evar)->wanted
) { (evq.evar)->wanted = 0; wakeup((caddr_t)(evq.evar)); }
if ((evq.evar)->async) pgsigio(&(evq.evar)->sigio,
23, 0); }
;
1200 }
1201 }
1202
1203 if (evq.result != EVQ_RESULT_OVERFLOW-1)
1204 clear_sync_flags(input);
1205 else
1206 input->flags |= RESYNC(1 << 16);
1207}
1208
1209int
1210wsmouse_id_to_slot(struct device *sc, int id)
1211{
1212 struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input;
1213 struct mt_state *mt = &input->mt;
1214 int slot;
1215
1216 if (mt->num_slots == 0)
1217 return (-1);
1218
1219 FOREACHBIT(mt->touches, slot)for ((slot) = ffs(mt->touches) - 1; (slot) != -1; (slot) =
ffs((mt->touches) & (~1 << (slot))) - 1)
{
1220 if (mt->slots[slot].id == id)
1221 return slot;
1222 }
1223 slot = ffs(~(mt->touches | mt->frame)) - 1;
1224 if (slot >= 0 && slot < mt->num_slots) {
1225 mt->frame |= 1 << slot;
1226 mt->slots[slot].id = id;
1227 return (slot);
1228 } else {
1229 return (-1);
1230 }
1231}
1232
1233/*
1234 * Find a minimum-weight matching for an m-by-n matrix.
1235 *
1236 * m must be greater than or equal to n. The size of the buffer must be
1237 * at least 3m + 3n.
1238 *
1239 * On return, the first m elements of the buffer contain the row-to-
1240 * column mappings, i.e., buffer[i] is the column index for row i, or -1
1241 * if there is no assignment for that row (which may happen if n < m).
1242 *
1243 * Wrong results because of overflows will not occur with input values
1244 * in the range of 0 to INT_MAX / 2 inclusive.
1245 *
1246 * The function applies the Dinic-Kronrod algorithm. It is not modern or
1247 * popular, but it seems to be a good choice for small matrices at least.
1248 * The original form of the algorithm is modified as follows: There is no
1249 * initial search for row minima, the initial assignments are in a
1250 * "virtual" column with the index -1 and zero values. This permits inputs
1251 * with n < m, and it simplifies the reassignments.
1252 */
1253void
1254wsmouse_matching(int *matrix, int m, int n, int *buffer)
1255{
1256 int i, j, k, d, e, row, col, delta;
9
'row' declared without an initial value
1257 int *p;
1258 int *r2c = buffer; /* row-to-column assignments */
1259 int *red = r2c + m; /* reduced values of the assignments */
1260 int *mc = red + m; /* row-wise minimal elements of cs */
1261 int *cs = mc + m; /* the column set */
1262 int *c2r = cs + n; /* column-to-row assignments in cs */
1263 int *cd = c2r + n; /* column deltas (reduction) */
1264
1265 for (p = r2c; p < red; *p++ = -1) {}
10
Loop condition is false. Execution continues on line 1266
1266 for (; p < mc; *p++ = 0) {}
11
Loop condition is false. Execution continues on line 1267
1267 for (col = 0; col
11.1
'col' is < 'n'
< n; col++) {
12
Loop condition is true. Entering loop body
1268 delta = INT_MAX0x7fffffff;
1269 for (i = 0, p = matrix + col; i < m; i++, p += n) {
13
Assuming 'i' is >= 'm'
14
Loop condition is false. Execution continues on line 1276
1270 d = *p - red[i];
1271 if (d < delta || (d == delta && r2c[i] < 0)) {
1272 delta = d;
1273 row = i;
1274 }
1275 }
1276 cd[col] = delta;
1277 if (r2c[row] < 0) {
15
Array subscript is undefined
1278 r2c[row] = col;
1279 continue;
1280 }
1281 for (p = mc; p < cs; *p++ = col) {}
1282 for (k = 0; (j = r2c[row]) >= 0;) {
1283 cs[k++] = j;
1284 c2r[j] = row;
1285 mc[row] -= n;
1286 delta = INT_MAX0x7fffffff;
1287 for (i = 0, p = matrix; i < m; i++, p += n)
1288 if (mc[i] >= 0) {
1289 d = p[mc[i]] - cd[mc[i]];
1290 e = p[j] - cd[j];
1291 if (e < d) {
1292 d = e;
1293 mc[i] = j;
1294 }
1295 d -= red[i];
1296 if (d < delta || (d == delta
1297 && r2c[i] < 0)) {
1298 delta = d;
1299 row = i;
1300 }
1301 }
1302 cd[col] += delta;
1303 for (i = 0; i < k; i++) {
1304 cd[cs[i]] += delta;
1305 red[c2r[cs[i]]] -= delta;
1306 }
1307 }
1308 for (j = mc[row]; (r2c[row] = j) != col;) {
1309 row = c2r[j];
1310 j = mc[row] + n;
1311 }
1312 }
1313}
1314
1315/*
1316 * Assign slot numbers to the points in the pt array, and update all slots by
1317 * calling wsmouse_mtstate internally. The slot numbers are passed to the
1318 * caller in the pt->slot fields.
1319 *
1320 * The slot assignment pairs the points with points of the previous frame in
1321 * such a way that the sum of the squared distances is minimal. Using
1322 * squares instead of simple distances favours assignments with more uniform
1323 * distances, and it is faster.
1324 */
1325void
1326wsmouse_mtframe(struct device *sc, struct mtpoint *pt, int size)
1327{
1328 struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input;
1329 struct mt_state *mt = &input->mt;
1330 int i, j, m, n, dx, dy, slot, maxdist;
1331 int *p, *r2c, *c2r;
1332 u_int touches;
1333
1334 if (mt->num_slots == 0 || mt->matrix == NULL((void *)0))
1
Assuming field 'num_slots' is not equal to 0
2
Assuming field 'matrix' is not equal to NULL
3
Taking false branch
1335 return;
1336
1337 size = imax(0, imin(size, mt->num_slots));
1338 p = mt->matrix;
1339 touches = mt->touches;
1340 if (mt->num_touches >= size) {
4
Assuming 'size' is <= field 'num_touches'
5
Taking true branch
1341 FOREACHBIT(touches, slot)for ((slot) = ffs(touches) - 1; (slot) != -1; (slot) = ffs((touches
) & (~1 << (slot))) - 1)
6
Assuming the condition is false
7
Loop condition is false. Execution continues on line 1347
1342 for (i = 0; i < size; i++) {
1343 dx = pt[i].x - mt->slots[slot].pos.x;
1344 dy = pt[i].y - mt->slots[slot].pos.y;
1345 *p++ = dx * dx + dy * dy;
1346 }
1347 m = mt->num_touches;
1348 n = size;
1349 } else {
1350 for (i = 0; i < size; i++)
1351 FOREACHBIT(touches, slot)for ((slot) = ffs(touches) - 1; (slot) != -1; (slot) = ffs((touches
) & (~1 << (slot))) - 1)
{
1352 dx = pt[i].x - mt->slots[slot].pos.x;
1353 dy = pt[i].y - mt->slots[slot].pos.y;
1354 *p++ = dx * dx + dy * dy;
1355 }
1356 m = size;
1357 n = mt->num_touches;
1358 }
1359 wsmouse_matching(mt->matrix, m, n, p);
8
Calling 'wsmouse_matching'
1360
1361 r2c = p;
1362 c2r = p + m;
1363 maxdist = input->filter.tracking_maxdist;
1364 maxdist = (maxdist ? maxdist * maxdist : INT_MAX0x7fffffff);
1365 for (i = 0, p = mt->matrix; i < m; i++, p += n)
1366 if ((j = r2c[i]) >= 0) {
1367 if (p[j] <= maxdist)
1368 c2r[j] = i;
1369 else
1370 c2r[j] = r2c[i] = -1;
1371 }
1372
1373 p = (n == size ? c2r : r2c);
1374 for (i = 0; i < size; i++)
1375 if (*p++ < 0) {
1376 slot = ffs(~(mt->touches | mt->frame)) - 1;
1377 if (slot < 0 || slot >= mt->num_slots)
1378 break;
1379 wsmouse_mtstate(sc, slot,
1380 pt[i].x, pt[i].y, pt[i].pressure);
1381 pt[i].slot = slot;
1382 }
1383
1384 p = (n == size ? r2c : c2r);
1385 FOREACHBIT(touches, slot)for ((slot) = ffs(touches) - 1; (slot) != -1; (slot) = ffs((touches
) & (~1 << (slot))) - 1)
1386 if ((i = *p++) >= 0) {
1387 wsmouse_mtstate(sc, slot,
1388 pt[i].x, pt[i].y, pt[i].pressure);
1389 pt[i].slot = slot;
1390 } else {
1391 wsmouse_mtstate(sc, slot, 0, 0, 0);
1392 }
1393}
1394
1395static inline void
1396free_mt_slots(struct wsmouseinput *input)
1397{
1398 int n, size;
1399
1400 if ((n = input->mt.num_slots)) {
1401 size = n * sizeof(struct mt_slot);
1402 if (input->flags & MT_TRACKING(1 << 2))
1403 size += MATRIX_SIZE(n)(((n) + 6) * (n) * sizeof(int));
1404 input->mt.num_slots = 0;
1405 free(input->mt.slots, M_DEVBUF2, size);
1406 input->mt.slots = NULL((void *)0);
1407 input->mt.matrix = NULL((void *)0);
1408 }
1409}
1410
1411/* Allocate the MT slots and, if necessary, the buffers for MT tracking. */
1412int
1413wsmouse_mt_init(struct device *sc, int num_slots, int tracking)
1414{
1415 struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input;
1416 int n, size;
1417
1418 if (num_slots == input->mt.num_slots
1419 && (!tracking == ((input->flags & MT_TRACKING(1 << 2)) == 0)))
1420 return (0);
1421
1422 free_mt_slots(input);
1423
1424 if (tracking)
1425 input->flags |= MT_TRACKING(1 << 2);
1426 else
1427 input->flags &= ~MT_TRACKING(1 << 2);
1428 n = imin(imax(num_slots, 0), WSMOUSE_MT_SLOTS_MAX10);
1429 if (n) {
1430 size = n * sizeof(struct mt_slot);
1431 if (input->flags & MT_TRACKING(1 << 2))
1432 size += MATRIX_SIZE(n)(((n) + 6) * (n) * sizeof(int));
1433 input->mt.slots = malloc(size, M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
1434 if (input->mt.slots != NULL((void *)0)) {
1435 if (input->flags & MT_TRACKING(1 << 2))
1436 input->mt.matrix = (int *)
1437 (input->mt.slots + n);
1438 input->mt.num_slots = n;
1439 return (0);
1440 }
1441 }
1442 return (-1);
1443}
1444
1445int
1446wsmouse_get_params(struct device *sc,
1447 struct wsmouse_param *params, u_int nparams)
1448{
1449 struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input;
1450 int i, key, error = 0;
1451
1452 for (i = 0; i < nparams; i++) {
1453 key = params[i].key;
1454 switch (key) {
1455 case WSMOUSECFG_DX_SCALE:
1456 params[i].value = input->filter.h.scale;
1457 break;
1458 case WSMOUSECFG_DY_SCALE:
1459 params[i].value = input->filter.v.scale;
1460 break;
1461 case WSMOUSECFG_PRESSURE_LO:
1462 params[i].value = input->filter.pressure_lo;
1463 break;
1464 case WSMOUSECFG_PRESSURE_HI:
1465 params[i].value = input->filter.pressure_hi;
1466 break;
1467 case WSMOUSECFG_TRKMAXDIST:
1468 params[i].value = input->filter.tracking_maxdist;
1469 break;
1470 case WSMOUSECFG_SWAPXY:
1471 params[i].value = input->filter.swapxy;
1472 break;
1473 case WSMOUSECFG_X_INV:
1474 params[i].value = input->filter.h.inv;
1475 break;
1476 case WSMOUSECFG_Y_INV:
1477 params[i].value = input->filter.v.inv;
1478 break;
1479 case WSMOUSECFG_REVERSE_SCROLLING:
1480 params[i].value = !!(input->flags & REVERSE_SCROLLING(1 << 3));
1481 break;
1482 case WSMOUSECFG_DX_MAX:
1483 params[i].value = input->filter.h.dmax;
1484 break;
1485 case WSMOUSECFG_DY_MAX:
1486 params[i].value = input->filter.v.dmax;
1487 break;
1488 case WSMOUSECFG_X_HYSTERESIS:
1489 params[i].value = input->filter.h.hysteresis;
1490 break;
1491 case WSMOUSECFG_Y_HYSTERESIS:
1492 params[i].value = input->filter.v.hysteresis;
1493 break;
1494 case WSMOUSECFG_DECELERATION:
1495 params[i].value = input->filter.dclr;
1496 break;
1497 case WSMOUSECFG_STRONG_HYSTERESIS:
1498 params[i].value = 0; /* The feature has been removed. */
1499 break;
1500 case WSMOUSECFG_SMOOTHING:
1501 params[i].value =
1502 input->filter.mode & SMOOTHING_MASK7;
1503 break;
1504 case WSMOUSECFG_LOG_INPUT:
1505 params[i].value = !!(input->flags & LOG_INPUT(1 << 19));
1506 break;
1507 case WSMOUSECFG_LOG_EVENTS:
1508 params[i].value = !!(input->flags & LOG_EVENTS(1 << 20));
1509 break;
1510 default:
1511 error = wstpad_get_param(input, key, &params[i].value);
1512 if (error != 0)
1513 return (error);
1514 break;
1515 }
1516 }
1517
1518 return (0);
1519}
1520
1521int
1522wsmouse_set_params(struct device *sc,
1523 const struct wsmouse_param *params, u_int nparams)
1524{
1525 struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input;
1526 int i, val, key, needreset = 0, error = 0;
1527
1528 for (i = 0; i < nparams; i++) {
1529 key = params[i].key;
1530 val = params[i].value;
1531 switch (params[i].key) {
1532 case WSMOUSECFG_PRESSURE_LO:
1533 input->filter.pressure_lo = val;
1534 if (val > input->filter.pressure_hi)
1535 input->filter.pressure_hi = val;
1536 input->touch.min_pressure = input->filter.pressure_hi;
1537 break;
1538 case WSMOUSECFG_PRESSURE_HI:
1539 input->filter.pressure_hi = val;
1540 if (val < input->filter.pressure_lo)
1541 input->filter.pressure_lo = val;
1542 input->touch.min_pressure = val;
1543 break;
1544 case WSMOUSECFG_X_HYSTERESIS:
1545 input->filter.h.hysteresis = val;
1546 break;
1547 case WSMOUSECFG_Y_HYSTERESIS:
1548 input->filter.v.hysteresis = val;
1549 break;
1550 case WSMOUSECFG_DECELERATION:
1551 input->filter.dclr = val;
1552 wstpad_init_deceleration(input);
1553 break;
1554 case WSMOUSECFG_DX_SCALE:
1555 input->filter.h.scale = val;
1556 break;
1557 case WSMOUSECFG_DY_SCALE:
1558 input->filter.v.scale = val;
1559 break;
1560 case WSMOUSECFG_TRKMAXDIST:
1561 input->filter.tracking_maxdist = val;
1562 break;
1563 case WSMOUSECFG_SWAPXY:
1564 input->filter.swapxy = val;
1565 break;
1566 case WSMOUSECFG_X_INV:
1567 input->filter.h.inv = val;
1568 break;
1569 case WSMOUSECFG_Y_INV:
1570 input->filter.v.inv = val;
1571 break;
1572 case WSMOUSECFG_REVERSE_SCROLLING:
1573 if (val)
1574 input->flags |= REVERSE_SCROLLING(1 << 3);
1575 else
1576 input->flags &= ~REVERSE_SCROLLING(1 << 3);
1577 break;
1578 case WSMOUSECFG_DX_MAX:
1579 input->filter.h.dmax = val;
1580 break;
1581 case WSMOUSECFG_DY_MAX:
1582 input->filter.v.dmax = val;
1583 break;
1584 case WSMOUSECFG_SMOOTHING:
1585 input->filter.mode &= ~SMOOTHING_MASK7;
1586 input->filter.mode |= (val & SMOOTHING_MASK7);
1587 break;
1588 case WSMOUSECFG_LOG_INPUT:
1589 if (val)
1590 input->flags |= LOG_INPUT(1 << 19);
1591 else
1592 input->flags &= ~LOG_INPUT(1 << 19);
1593 break;
1594 case WSMOUSECFG_LOG_EVENTS:
1595 if (val)
1596 input->flags |= LOG_EVENTS(1 << 20);
1597 else
1598 input->flags &= ~LOG_EVENTS(1 << 20);
1599 break;
1600 default:
1601 needreset = 1;
1602 error = wstpad_set_param(input, key, val);
1603 if (error != 0)
1604 return (error);
1605 break;
1606 }
1607 }
1608
1609 /* Reset soft-states if touchpad parameters changed */
1610 if (needreset) {
1611 wstpad_reset(input);
1612 return (wstpad_configure(input));
1613 }
1614
1615 return (0);
1616}
1617
1618int
1619wsmouse_set_mode(struct device *sc, int mode)
1620{
1621 struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input;
1622
1623 if (mode == WSMOUSE_COMPAT0) {
1624 input->flags &= ~TPAD_NATIVE_MODE(1 << 1);
1625 input->flags |= TPAD_COMPAT_MODE(1 << 0);
1626 return (0);
1627 } else if (mode == WSMOUSE_NATIVE1) {
1628 input->flags &= ~TPAD_COMPAT_MODE(1 << 0);
1629 input->flags |= TPAD_NATIVE_MODE(1 << 1);
1630 return (0);
1631 }
1632 return (-1);
1633}
1634
1635struct wsmousehw *wsmouse_get_hw(struct device *sc)
1636{
1637 return &((struct wsmouse_softc *) sc)->sc_input.hw;
1638}
1639
1640/*
1641 * Create a default configuration based on the hardware infos in the 'hw'
1642 * fields. The 'params' argument is optional, hardware drivers can use it
1643 * to modify the generic defaults. Up to now this function is only useful
1644 * for touchpads.
1645 */
1646int
1647wsmouse_configure(struct device *sc,
1648 struct wsmouse_param *params, u_int nparams)
1649{
1650 struct wsmouseinput *input = &((struct wsmouse_softc *) sc)->sc_input;
1651 int error;
1652
1653 if (!(input->flags & CONFIGURED(1 << 18))) {
1654 if (input->hw.x_max && input->hw.y_max) {
1655 if (input->hw.flags & WSMOUSEHW_LR_DOWN(1 << 0)) {
1656 input->filter.v.inv =
1657 input->hw.y_max + input->hw.y_min;
1658 }
1659 }
1660 input->filter.ratio = 1 << 12;
1661 if (input->hw.h_res > 0 && input->hw.v_res > 0) {
1662 input->filter.ratio *= input->hw.h_res;
1663 input->filter.ratio /= input->hw.v_res;
1664 }
1665 if (wsmouse_mt_init(sc, input->hw.mt_slots,
1666 (input->hw.flags & WSMOUSEHW_MT_TRACKING(1 << 1)))) {
1667 printf("wsmouse_configure: "
1668 "MT initialization failed.\n");
1669 return (-1);
1670 }
1671 if (IS_TOUCHPAD(input)((input)->hw.hw_type == WSMOUSEHW_TOUCHPAD || (input)->
hw.hw_type == WSMOUSEHW_CLICKPAD)
&& wstpad_configure(input)) {
1672 printf("wstpad_configure: "
1673 "Initialization failed.\n");
1674 return (-1);
1675 }
1676 if (params != NULL((void *)0)) {
1677 if ((error = wsmouse_set_params(sc, params, nparams)))
1678 return (error);
1679 }
1680 input->flags |= CONFIGURED(1 << 18);
1681 }
1682 if (IS_TOUCHPAD(input)((input)->hw.hw_type == WSMOUSEHW_TOUCHPAD || (input)->
hw.hw_type == WSMOUSEHW_CLICKPAD)
)
1683 wsmouse_set_mode(sc, WSMOUSE_COMPAT0);
1684
1685 return (0);
1686}
1687
1688
1689void
1690wsmouse_input_reset(struct wsmouseinput *input)
1691{
1692 int num_slots, *matrix;
1693 struct mt_slot *slots;
1694
1695 memset(&input->btn, 0, sizeof(struct btn_state))__builtin_memset((&input->btn), (0), (sizeof(struct btn_state
)))
;
1696 memset(&input->motion, 0, sizeof(struct motion_state))__builtin_memset((&input->motion), (0), (sizeof(struct
motion_state)))
;
1697 memset(&input->touch, 0, sizeof(struct touch_state))__builtin_memset((&input->touch), (0), (sizeof(struct touch_state
)))
;
1698 input->touch.min_pressure = input->filter.pressure_hi;
1699 if ((num_slots = input->mt.num_slots)) {
1700 slots = input->mt.slots;
1701 matrix = input->mt.matrix;
1702 memset(&input->mt, 0, sizeof(struct mt_state))__builtin_memset((&input->mt), (0), (sizeof(struct mt_state
)))
;
1703 memset(slots, 0, num_slots * sizeof(struct mt_slot))__builtin_memset((slots), (0), (num_slots * sizeof(struct mt_slot
)))
;
1704 input->mt.num_slots = num_slots;
1705 input->mt.slots = slots;
1706 input->mt.matrix = matrix;
1707 }
1708 if (input->tp != NULL((void *)0))
1709 wstpad_reset(input);
1710}
1711
1712void
1713wsmouse_input_cleanup(struct wsmouseinput *input)
1714{
1715 if (input->tp != NULL((void *)0))
1716 wstpad_cleanup(input);
1717
1718 free_mt_slots(input);
1719}