Bug Summary

File:dev/usb/uts.c
Warning:line 403, column 6
Branch condition evaluates to a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name uts.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/usb/uts.c
1/* $OpenBSD: uts.c,v 1.43 2020/07/31 10:49:33 mglocker Exp $ */
2
3/*
4 * Copyright (c) 2007 Robert Nagy <robert@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/param.h>
20#include <sys/sockio.h>
21#include <sys/mbuf.h>
22#include <sys/kernel.h>
23#include <sys/socket.h>
24#include <sys/systm.h>
25#include <sys/malloc.h>
26#include <sys/timeout.h>
27#include <sys/conf.h>
28#include <sys/device.h>
29#include <sys/endian.h>
30
31#include <machine/intr.h>
32
33#include <dev/usb/usb.h>
34#include <dev/usb/usbdi.h>
35#include <dev/usb/usbdi_util.h>
36#include <dev/usb/usbdevs.h>
37
38#include <dev/wscons/wsconsio.h>
39#include <dev/wscons/wsmousevar.h>
40
41#ifdef UTS_DEBUG
42#define DPRINTF(x) do { printf x; } while (0)
43#else
44#define DPRINTF(x)
45#endif
46
47struct tsscale {
48 int minx, maxx;
49 int miny, maxy;
50 int swapxy;
51 int resx, resy;
52} def_scale = {
53 67, 1931, 102, 1937, 0, 1024, 768
54};
55
56struct uts_softc {
57 struct device sc_dev;
58 struct usbd_device *sc_udev;
59 struct usbd_interface *sc_iface;
60 int sc_product;
61 int sc_vendor;
62
63 int sc_intr_number;
64 struct usbd_pipe *sc_intr_pipe;
65 u_char *sc_ibuf;
66 int sc_isize;
67 u_int8_t sc_pkts;
68
69 struct device *sc_wsmousedev;
70
71 int sc_enabled;
72 int sc_buttons;
73 int sc_oldx;
74 int sc_oldy;
75 int sc_rawmode;
76
77 struct tsscale sc_tsscale;
78};
79
80struct uts_pos {
81 int down;
82 int x;
83 int y;
84 int z; /* touch pressure */
85};
86
87const struct usb_devno uts_devs[] = {
88 { USB_VENDOR_FTDI0x0403, USB_PRODUCT_FTDI_ITM_TOUCH0xf9e9 },
89 { USB_VENDOR_EGALAX0x0eef, USB_PRODUCT_EGALAX_TPANEL0x0001 },
90 { USB_VENDOR_EGALAX0x0eef, USB_PRODUCT_EGALAX_TPANEL20x0002 },
91 { USB_VENDOR_GUNZE0x0637, USB_PRODUCT_GUNZE_TOUCHPANEL0x0001 }
92};
93
94void uts_intr(struct usbd_xfer *, void *, usbd_status);
95void uts_get_pos(void *addr, struct uts_pos *tp);
96
97int uts_enable(void *);
98void uts_disable(void *);
99int uts_ioctl(void *, u_long, caddr_t, int, struct proc *);
100
101const struct wsmouse_accessops uts_accessops = {
102 uts_enable,
103 uts_ioctl,
104 uts_disable,
105};
106
107int uts_match(struct device *, void *, void *);
108void uts_attach(struct device *, struct device *, void *);
109int uts_detach(struct device *, int);
110int uts_activate(struct device *, int);
111
112struct cfdriver uts_cd = {
113 NULL((void *)0), "uts", DV_DULL
114};
115
116const struct cfattach uts_ca = {
117 sizeof(struct uts_softc),
118 uts_match,
119 uts_attach,
120 uts_detach,
121 uts_activate,
122};
123
124int
125uts_match(struct device *parent, void *match, void *aux)
126{
127 struct usb_attach_arg *uaa = aux;
128 usb_interface_descriptor_t *id;
129
130 if (uaa->iface == NULL((void *)0))
131 return (UMATCH_NONE0);
132
133 /* Some eGalax touch screens are HID devices. ignore them */
134 id = usbd_get_interface_descriptor(uaa->iface);
135 if (id != NULL((void *)0) && id->bInterfaceClass == UICLASS_HID0x03)
136 return (UMATCH_NONE0);
137
138 return (usb_lookup(uts_devs, uaa->vendor, uaa->product)usbd_match_device((const struct usb_devno *)(uts_devs), sizeof
(uts_devs) / sizeof ((uts_devs)[0]), sizeof ((uts_devs)[0]),
(uaa->vendor), (uaa->product))
!= NULL((void *)0)) ?
139 UMATCH_VENDOR_PRODUCT13 : UMATCH_NONE0;
140}
141
142void
143uts_attach(struct device *parent, struct device *self, void *aux)
144{
145 struct uts_softc *sc = (struct uts_softc *)self;
146 struct usb_attach_arg *uaa = aux;
147 usb_config_descriptor_t *cdesc;
148 usb_interface_descriptor_t *id;
149 usb_endpoint_descriptor_t *ed;
150 struct wsmousedev_attach_args a;
151 int i;
152
153 sc->sc_udev = uaa->device;
154 sc->sc_product = uaa->product;
155 sc->sc_vendor = uaa->vendor;
156 sc->sc_intr_number = -1;
157 sc->sc_intr_pipe = NULL((void *)0);
158 sc->sc_enabled = sc->sc_isize = 0;
159
160 /* Copy the default scalue values to each softc */
161 bcopy(&def_scale, &sc->sc_tsscale, sizeof(sc->sc_tsscale));
162
163 /* get the config descriptor */
164 cdesc = usbd_get_config_descriptor(sc->sc_udev);
165 if (cdesc == NULL((void *)0)) {
166 printf("%s: failed to get configuration descriptor\n",
167 sc->sc_dev.dv_xname);
168 usbd_deactivate(sc->sc_udev);
169 return;
170 }
171
172 /* get the interface */
173 if (usbd_device2interface_handle(uaa->device, 0, &sc->sc_iface) != 0) {
174 printf("%s: failed to get interface\n",
175 sc->sc_dev.dv_xname);
176 usbd_deactivate(sc->sc_udev);
177 return;
178 }
179
180 /* Find the interrupt endpoint */
181 id = usbd_get_interface_descriptor(sc->sc_iface);
182
183 for (i = 0; i < id->bNumEndpoints; i++) {
184 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
185 if (ed == NULL((void *)0)) {
186 printf("%s: no endpoint descriptor for %d\n",
187 sc->sc_dev.dv_xname, i);
188 usbd_deactivate(sc->sc_udev);
189 return;
190 }
191
192 if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80 &&
193 UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_INTERRUPT0x03) {
194 sc->sc_intr_number = ed->bEndpointAddress;
195 sc->sc_isize = UGETW(ed->wMaxPacketSize)(*(u_int16_t *)(ed->wMaxPacketSize));
196 }
197 }
198
199 if (sc->sc_intr_number== -1) {
200 printf("%s: Could not find interrupt in\n",
201 sc->sc_dev.dv_xname);
202 usbd_deactivate(sc->sc_udev);
203 return;
204 }
205
206 a.accessops = &uts_accessops;
207 a.accesscookie = sc;
208
209 sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint)config_found_sm((self), (&a), (wsmousedevprint), ((void *
)0))
;
210}
211
212int
213uts_detach(struct device *self, int flags)
214{
215 struct uts_softc *sc = (struct uts_softc *)self;
216 int rv = 0;
217
218 if (sc->sc_intr_pipe != NULL((void *)0)) {
219 usbd_close_pipe(sc->sc_intr_pipe);
220 sc->sc_intr_pipe = NULL((void *)0);
221 }
222
223 if (sc->sc_wsmousedev != NULL((void *)0)) {
224 rv = config_detach(sc->sc_wsmousedev, flags);
225 sc->sc_wsmousedev = NULL((void *)0);
226 }
227
228 return (rv);
229}
230
231int
232uts_activate(struct device *self, int act)
233{
234 struct uts_softc *sc = (struct uts_softc *)self;
235 int rv = 0;
236
237 switch (act) {
238 case DVACT_DEACTIVATE1:
239 if (sc->sc_wsmousedev != NULL((void *)0))
240 rv = config_deactivate(sc->sc_wsmousedev);
241 usbd_deactivate(sc->sc_udev);
242 break;
243 }
244
245 return (rv);
246}
247
248int
249uts_enable(void *v)
250{
251 struct uts_softc *sc = v;
252 int err;
253
254 if (usbd_is_dying(sc->sc_udev))
255 return (EIO5);
256
257 if (sc->sc_enabled)
258 return (EBUSY16);
259
260 if (sc->sc_isize == 0)
261 return (0);
262 sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV102, M_WAITOK0x0001);
263 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_intr_number,
264 USBD_SHORT_XFER_OK0x04, &sc->sc_intr_pipe, sc, sc->sc_ibuf,
265 sc->sc_isize, uts_intr, USBD_DEFAULT_INTERVAL(-1));
266 if (err) {
267 free(sc->sc_ibuf, M_USBDEV102, sc->sc_isize);
268 sc->sc_intr_pipe = NULL((void *)0);
269 return (EIO5);
270 }
271
272 sc->sc_enabled = 1;
273 sc->sc_buttons = 0;
274
275 return (0);
276}
277
278void
279uts_disable(void *v)
280{
281 struct uts_softc *sc = v;
282
283 if (!sc->sc_enabled) {
284 printf("uts_disable: already disabled!\n");
285 return;
286 }
287
288 /* Disable interrupts. */
289 if (sc->sc_intr_pipe != NULL((void *)0)) {
290 usbd_close_pipe(sc->sc_intr_pipe);
291 sc->sc_intr_pipe = NULL((void *)0);
292 }
293
294 if (sc->sc_ibuf != NULL((void *)0)) {
295 free(sc->sc_ibuf, M_USBDEV102, sc->sc_isize);
296 sc->sc_ibuf = NULL((void *)0);
297 }
298
299 sc->sc_enabled = 0;
300}
301
302int
303uts_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *l)
304{
305 int error = 0;
306 struct uts_softc *sc = v;
307 struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
308
309 DPRINTF(("uts_ioctl(%zu, '%c', %zu)\n",
310 IOCPARM_LEN(cmd), (int) IOCGROUP(cmd), cmd & 0xff));
311
312 switch (cmd) {
313 case WSMOUSEIO_SCALIBCOORDS((unsigned long)0x80000000 | ((sizeof(struct wsmouse_calibcoords
) & 0x1fff) << 16) | ((('W')) << 8) | ((36)))
:
314 if (!(wsmc->minx >= -32768 && wsmc->maxx >= 0 &&
315 wsmc->miny >= -32768 && wsmc->maxy >= 0 &&
316 wsmc->resx >= 0 && wsmc->resy >= 0 &&
317 wsmc->minx < 32768 && wsmc->maxx < 32768 &&
318 wsmc->miny < 32768 && wsmc->maxy < 32768 &&
319 (wsmc->maxx - wsmc->minx) != 0 &&
320 (wsmc->maxy - wsmc->miny) != 0 &&
321 wsmc->resx < 32768 && wsmc->resy < 32768 &&
322 wsmc->swapxy >= 0 && wsmc->swapxy <= 1 &&
323 wsmc->samplelen >= 0 && wsmc->samplelen <= 1))
324 return (EINVAL22);
325
326 sc->sc_tsscale.minx = wsmc->minx;
327 sc->sc_tsscale.maxx = wsmc->maxx;
328 sc->sc_tsscale.miny = wsmc->miny;
329 sc->sc_tsscale.maxy = wsmc->maxy;
330 sc->sc_tsscale.swapxy = wsmc->swapxy;
331 sc->sc_tsscale.resx = wsmc->resx;
332 sc->sc_tsscale.resy = wsmc->resy;
333 sc->sc_rawmode = wsmc->samplelen;
334 break;
335 case WSMOUSEIO_GCALIBCOORDS((unsigned long)0x40000000 | ((sizeof(struct wsmouse_calibcoords
) & 0x1fff) << 16) | ((('W')) << 8) | ((37)))
:
336 wsmc->minx = sc->sc_tsscale.minx;
337 wsmc->maxx = sc->sc_tsscale.maxx;
338 wsmc->miny = sc->sc_tsscale.miny;
339 wsmc->maxy = sc->sc_tsscale.maxy;
340 wsmc->swapxy = sc->sc_tsscale.swapxy;
341 wsmc->resx = sc->sc_tsscale.resx;
342 wsmc->resy = sc->sc_tsscale.resy;
343 wsmc->samplelen = sc->sc_rawmode;
344 break;
345 case WSMOUSEIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((32)))
:
346 *(u_int *)data = WSMOUSE_TYPE_TPANEL6;
347 break;
348 default:
349 error = ENOTTY25;
350 break;
351 }
352
353 return (error);
354}
355
356void
357uts_get_pos(void *addr, struct uts_pos *tp)
358{
359 struct uts_softc *sc = addr;
360 u_char *p = sc->sc_ibuf;
361 int down, x, y, z;
6
'down' declared without an initial value
362
363 switch (sc->sc_product) {
7
'Default' branch taken. Execution continues on line 403
364 case USB_PRODUCT_FTDI_ITM_TOUCH0xf9e9:
365 down = (~p[7] & 0x20);
366 x = ((p[0] & 0x1f) << 7) | (p[3] & 0x7f);
367 /* Invert the Y coordinate */
368 y = 0x0fff - abs(((p[1] & 0x1f) << 7) | (p[4] & 0x7f));
369 z = ((p[2] & 0x1) << 7) | (p[5] & 0x7f);
370 sc->sc_pkts = 0x8;
371 break;
372 case USB_PRODUCT_EGALAX_TPANEL0x0001:
373 case USB_PRODUCT_EGALAX_TPANEL20x0002:
374 /*
375 * eGalax and Gunze USB touch panels have the same device ID,
376 * so decide upon the vendor ID.
377 */
378 switch (sc->sc_vendor) {
379 case USB_VENDOR_EGALAX0x0eef:
380 down = (p[0] & 0x01);
381 /* Invert the X coordinate */
382 x = 0x07ff - abs(((p[3] & 0x0f) << 7) | (p[4] & 0x7f));
383 y = ((p[1] & 0x0f) << 7) | (p[2] & 0x7f);
384 z = down;
385 sc->sc_pkts = 0x5;
386 break;
387 case USB_VENDOR_GUNZE0x0637:
388 down = (~p[7] & 0x20);
389 /* Invert the X coordinate */
390 x = 0x0fff - abs(((p[0] & 0x1f) << 7) | (p[2] & 0x7f));
391 y = ((p[1] & 0x1f) << 7) | (p[3] & 0x7f);
392 z = (down != 0);
393 sc->sc_pkts = 0x4;
394 break;
395 }
396 break;
397 }
398
399 DPRINTF(("%s: down = 0x%x, sc->sc_pkts = 0x%x\n",
400 sc->sc_dev.dv_xname, down, sc->sc_pkts));
401
402 /* x/y values are not reliable if there is no pressure */
403 if (down) {
8
Branch condition evaluates to a garbage value
404 if (sc->sc_tsscale.swapxy && !sc->sc_rawmode) {
405 /* Swap X/Y-Axis */
406 tp->y = x;
407 tp->x = y;
408 } else {
409 tp->x = x;
410 tp->y = y;
411 }
412 if (!sc->sc_rawmode &&
413 (sc->sc_tsscale.maxx - sc->sc_tsscale.minx) != 0 &&
414 (sc->sc_tsscale.maxy - sc->sc_tsscale.miny) != 0) {
415 /* Scale down to the screen resolution. */
416 tp->x = ((tp->x - sc->sc_tsscale.minx) *
417 sc->sc_tsscale.resx) /
418 (sc->sc_tsscale.maxx - sc->sc_tsscale.minx);
419 tp->y = ((tp->y - sc->sc_tsscale.miny) *
420 sc->sc_tsscale.resy) /
421 (sc->sc_tsscale.maxy - sc->sc_tsscale.miny);
422 }
423 } else {
424 tp->x = sc->sc_oldx;
425 tp->y = sc->sc_oldy;
426 }
427 tp->z = z;
428 tp->down = down;
429}
430
431void
432uts_intr(struct usbd_xfer *xfer, void *addr, usbd_status status)
433{
434 struct uts_softc *sc = addr;
435 u_int32_t len;
436 int s;
437 struct uts_pos tp;
438
439 if (status == USBD_CANCELLED)
1
Assuming 'status' is not equal to USBD_CANCELLED
2
Taking false branch
440 return;
441
442 if (status != USBD_NORMAL_COMPLETION) {
3
Assuming 'status' is equal to USBD_NORMAL_COMPLETION
4
Taking false branch
443 printf("%s: status %d\n", sc->sc_dev.dv_xname, status);
444 if (status == USBD_STALLED)
445 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
446 return;
447 }
448
449 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
450
451 s = spltty()splraise(0x9);
452
453 uts_get_pos(sc, &tp);
5
Calling 'uts_get_pos'
454
455 if (len != sc->sc_pkts) {
456 DPRINTF(("%s: bad input length %d != %d\n",
457 sc->sc_dev.dv_xname, len, sc->sc_isize));
458 splx(s)spllower(s);
459 return;
460 }
461
462 DPRINTF(("%s: tp.down = %d, tp.z = %d, tp.x = %d, tp.y = %d\n",
463 sc->sc_dev.dv_xname, tp.down, tp.z, tp.x, tp.y));
464
465 WSMOUSE_TOUCH(sc->sc_wsmousedev, tp.down, tp.x, tp.y, tp.z, 0)do { wsmouse_buttons((sc->sc_wsmousedev), (tp.down)); wsmouse_position
((sc->sc_wsmousedev), (tp.x), (tp.y)); wsmouse_touch((sc->
sc_wsmousedev), (tp.z), (0)); wsmouse_input_sync(sc->sc_wsmousedev
); } while (0)
;
466 sc->sc_oldy = tp.y;
467 sc->sc_oldx = tp.x;
468
469 splx(s)spllower(s);
470}