Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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