xref: /openbsd-src/sbin/wsconsctl/mouse.c (revision c08965e9c177ac9b4ce34a134339d443b08de977)
1*c08965e9Schrisz /*	$OpenBSD: mouse.c,v 1.22 2024/10/05 13:27:16 chrisz Exp $	*/
2e0b2c52dSmickey /*	$NetBSD: mouse.c,v 1.3 1999/11/15 13:47:30 ad Exp $ */
3e0b2c52dSmickey 
4e0b2c52dSmickey /*-
5e0b2c52dSmickey  * Copyright (c) 1998 The NetBSD Foundation, Inc.
6e0b2c52dSmickey  * All rights reserved.
7e0b2c52dSmickey  *
8e0b2c52dSmickey  * This code is derived from software contributed to The NetBSD Foundation
9e0b2c52dSmickey  * by Juergen Hannken-Illjes.
10e0b2c52dSmickey  *
11e0b2c52dSmickey  * Redistribution and use in source and binary forms, with or without
12e0b2c52dSmickey  * modification, are permitted provided that the following conditions
13e0b2c52dSmickey  * are met:
14e0b2c52dSmickey  * 1. Redistributions of source code must retain the above copyright
15e0b2c52dSmickey  *    notice, this list of conditions and the following disclaimer.
16e0b2c52dSmickey  * 2. Redistributions in binary form must reproduce the above copyright
17e0b2c52dSmickey  *    notice, this list of conditions and the following disclaimer in the
18e0b2c52dSmickey  *    documentation and/or other materials provided with the distribution.
19e0b2c52dSmickey  *
20e0b2c52dSmickey  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21e0b2c52dSmickey  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22e0b2c52dSmickey  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23e0b2c52dSmickey  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24e0b2c52dSmickey  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25e0b2c52dSmickey  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26e0b2c52dSmickey  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27e0b2c52dSmickey  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28e0b2c52dSmickey  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29e0b2c52dSmickey  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30e0b2c52dSmickey  * POSSIBILITY OF SUCH DAMAGE.
31e0b2c52dSmickey  */
32e0b2c52dSmickey 
33e0b2c52dSmickey #include <sys/ioctl.h>
34e0b2c52dSmickey #include <sys/time.h>
35e0b2c52dSmickey #include <dev/wscons/wsconsio.h>
36e0b2c52dSmickey #include <err.h>
37589b65e9Srobert #include <errno.h>
381222b15bSmaja #include <fcntl.h>
391222b15bSmaja #include <stdio.h>
40e0b2c52dSmickey #include "wsconsctl.h"
41d22ea701Sbru #include "mousecfg.h"
42e0b2c52dSmickey 
43f7ed5097Sshadchin static u_int mstype;
44f7ed5097Sshadchin static u_int resolution;
45f7ed5097Sshadchin static u_int samplerate;
46589b65e9Srobert static int rawmode;
47589b65e9Srobert 
4888e6ce2aSmatthieu struct wsmouse_calibcoords wmcoords, wmcoords_save;
49e0b2c52dSmickey 
50e0b2c52dSmickey struct field mouse_field_tab[] = {
51e0b2c52dSmickey     { "resolution",		&resolution,	FMT_UINT,	FLG_WRONLY },
52e0b2c52dSmickey     { "samplerate",		&samplerate,	FMT_UINT,	FLG_WRONLY },
53e0b2c52dSmickey     { "type",			&mstype,	FMT_MSTYPE,	FLG_RDONLY },
54589b65e9Srobert     { "rawmode",		&rawmode,	FMT_UINT,	FLG_MODIFY|FLG_INIT},
55589b65e9Srobert     { "scale",			&wmcoords,	FMT_SCALE,	FLG_MODIFY|FLG_INIT},
5677727bd5Sbru     /* mouse and touchpad configuration (mousecfg): */
5777727bd5Sbru     { "reverse_scrolling",	&cfg_revscroll, FMT_CFG,	FLG_NORDBACK },
5877727bd5Sbru     /* touchpad-specific options: */
59d22ea701Sbru     { "tp.tapping",		&cfg_tapping,	FMT_CFG,	FLG_NORDBACK },
609310c18aSbru     { "tp.mtbuttons",		&cfg_mtbuttons,	FMT_CFG,	FLG_NORDBACK },
61*c08965e9Schrisz     { "tp.scaling",		&cfg_scaling,	FMT_CFG,	FLG_NORDBACK | FLG_WRONLY },
62d22ea701Sbru     { "tp.swapsides",		&cfg_swapsides,	FMT_CFG,	FLG_NORDBACK },
63d22ea701Sbru     { "tp.disable",		&cfg_disable,	FMT_CFG,	FLG_NORDBACK },
640137e658Sbru     { "tp.edges",		&cfg_edges,	FMT_CFG,	FLG_NORDBACK },
65d22ea701Sbru     { "tp.param",		&cfg_param,	FMT_CFG,	FLG_WRONLY },
66*c08965e9Schrisz     /* Add aliases.  These fields are valid for all wsmouse devices. */
67a143f7beSbru     { "param",			&cfg_param,	FMT_CFG,	FLG_WRONLY },
68*c08965e9Schrisz     { "scaling",		&cfg_scaling,	FMT_CFG,	FLG_NORDBACK },
6982bc7287Smickey     { NULL }
70e0b2c52dSmickey };
71e0b2c52dSmickey 
72d22ea701Sbru static int dev_index = -1;
73d22ea701Sbru 
749310c18aSbru static struct wsmouse_parameters mtbtn_maxdist = {
759310c18aSbru     (struct wsmouse_param[]) { { WSMOUSECFG_MTBTN_MAXDIST, 0 } }, 1
769310c18aSbru };
779310c18aSbru 
78d22ea701Sbru 
79d22ea701Sbru void
80d22ea701Sbru mouse_init(int devfd, int devidx) {
81d22ea701Sbru 	struct field *f;
82d22ea701Sbru 	const char *errstr;
83d22ea701Sbru 	int err;
84d22ea701Sbru 
85d22ea701Sbru 	if (dev_index == devidx)
86d22ea701Sbru 		return;
87d22ea701Sbru 
88d22ea701Sbru 	if ((err = mousecfg_init(devfd, &errstr))) {
89d22ea701Sbru 		devidx = -1;
90d22ea701Sbru 		for (f = mouse_field_tab; f->name != NULL; f++) {
91d22ea701Sbru 			if (f->format == FMT_CFG)
92d22ea701Sbru 				f->flags |= FLG_DEAD;
93d22ea701Sbru 		}
94d22ea701Sbru 		warnx("mousecfg error: %s (%d)", errstr, err);
95a143f7beSbru 	} else if (cfg_touchpad) {
96a143f7beSbru 		for (f = mouse_field_tab; f->name != NULL; f++)
97a143f7beSbru 			if (f->format == FMT_CFG) {
98a143f7beSbru 				f->flags &= ~FLG_DEAD;
99a143f7beSbru 			}
1009310c18aSbru 		/* Hide the 'mtbuttons' field if the feature is unavailable. */
1019310c18aSbru 		if (mousecfg_get_field(&mtbtn_maxdist) ||
1029310c18aSbru 		    mtbtn_maxdist.params[0].value < 0) {
1039310c18aSbru 			f = field_by_value(mouse_field_tab, &cfg_mtbuttons);
1049310c18aSbru 			f->flags |= FLG_DEAD;
1059310c18aSbru 		}
106ff9cd955Sbru 	} else {
107a143f7beSbru 		for (f = mouse_field_tab; f->name != NULL; f++)
108a143f7beSbru 			if (f->format == FMT_CFG) {
10977727bd5Sbru 				if (f->valp != &cfg_param
110*c08965e9Schrisz 				    && f->valp != &cfg_scaling
11177727bd5Sbru 				    && f->valp != &cfg_revscroll)
112a143f7beSbru 					f->flags |= FLG_DEAD;
113a143f7beSbru 				else
114d22ea701Sbru 					f->flags &= ~FLG_DEAD;
115d22ea701Sbru 			}
116d22ea701Sbru 	}
117d22ea701Sbru 
118d22ea701Sbru 	dev_index = devidx;
119d22ea701Sbru }
120d22ea701Sbru 
121e0b2c52dSmickey void
12254e3cb1dSfgsch mouse_get_values(int fd)
123e0b2c52dSmickey {
124d22ea701Sbru 	struct field *f;
125d22ea701Sbru 
12682bc7287Smickey 	if (field_by_value(mouse_field_tab, &mstype)->flags & FLG_GET)
127df69c215Sderaadt 		if (ioctl(fd, WSMOUSEIO_GTYPE, &mstype) == -1)
128b0520bc4Smiod 			warn("WSMOUSEIO_GTYPE");
129589b65e9Srobert 
130589b65e9Srobert 	if (field_by_value(mouse_field_tab, &rawmode)->flags & FLG_GET) {
131df69c215Sderaadt 		if (ioctl(fd, WSMOUSEIO_GCALIBCOORDS, &wmcoords) == -1) {
132589b65e9Srobert 			if (errno == ENOTTY)
133589b65e9Srobert 				field_by_value(mouse_field_tab,
134589b65e9Srobert 				    &rawmode)->flags |= FLG_DEAD;
135589b65e9Srobert 			else
136589b65e9Srobert 				warn("WSMOUSEIO_GCALIBCOORDS");
137589b65e9Srobert 		}
138589b65e9Srobert 		rawmode = wmcoords.samplelen;
139589b65e9Srobert 	}
140589b65e9Srobert 
141589b65e9Srobert 	if (field_by_value(mouse_field_tab, &wmcoords)->flags & FLG_GET)
142df69c215Sderaadt 		if (ioctl(fd, WSMOUSEIO_GCALIBCOORDS, &wmcoords) == -1) {
143589b65e9Srobert 			if (errno == ENOTTY)
144589b65e9Srobert 				field_by_value(mouse_field_tab,
145589b65e9Srobert 				    &wmcoords)->flags |= FLG_DEAD;
146589b65e9Srobert 			else
147589b65e9Srobert 				warn("WSMOUSEIO_GCALIBCOORDS");
148589b65e9Srobert 	}
149d22ea701Sbru 
150d22ea701Sbru 	for (f = mouse_field_tab; f->name != NULL; f++) {
151a143f7beSbru 		if (f->format != FMT_CFG || !(f->flags & FLG_GET)
152a143f7beSbru 		    || f->valp == &cfg_param || (f->flags & FLG_DEAD))
153d22ea701Sbru 			continue;
154d22ea701Sbru 		if (mousecfg_get_field((struct wsmouse_parameters *) f->valp)) {
155d22ea701Sbru 			f->flags |= FLG_DEAD;
156d22ea701Sbru 			warnx("mousecfg: invalid key in '%s'", f->name);
157d22ea701Sbru 		}
158d22ea701Sbru 	}
159e0b2c52dSmickey }
160e0b2c52dSmickey 
161f0cd74dfSmartynas int
16254e3cb1dSfgsch mouse_put_values(int fd)
163e0b2c52dSmickey {
164d22ea701Sbru 	struct field *f;
165d22ea701Sbru 
16682bc7287Smickey 	if (field_by_value(mouse_field_tab, &resolution)->flags & FLG_SET) {
167df69c215Sderaadt 		if (ioctl(fd, WSMOUSEIO_SRES, &resolution) == -1) {
168b0520bc4Smiod 			warn("WSMOUSEIO_SRES");
169f0cd74dfSmartynas 			return 1;
170e0b2c52dSmickey 		}
171b0520bc4Smiod 	}
172589b65e9Srobert 	if (field_by_value(mouse_field_tab, &rawmode)->flags & FLG_SET) {
173589b65e9Srobert 		wmcoords.samplelen = rawmode;
174df69c215Sderaadt 		if (ioctl(fd, WSMOUSEIO_SCALIBCOORDS, &wmcoords) == -1) {
175589b65e9Srobert 			if (errno == ENOTTY) {
176589b65e9Srobert 				field_by_value(mouse_field_tab,
177589b65e9Srobert 				    &rawmode)->flags |= FLG_DEAD;
178589b65e9Srobert 			} else {
179f0cd74dfSmartynas 				warn("WSMOUSEIO_SCALIBCOORDS");
180f0cd74dfSmartynas 				return 1;
181f0cd74dfSmartynas 			}
182589b65e9Srobert 		}
183589b65e9Srobert 	}
184589b65e9Srobert 	if (field_by_value(mouse_field_tab, &wmcoords)->flags & FLG_SET) {
185df69c215Sderaadt 		if (ioctl(fd, WSMOUSEIO_GCALIBCOORDS, &wmcoords_save) == -1) {
18688e6ce2aSmatthieu 			if (errno == ENOTTY)
18788e6ce2aSmatthieu 				field_by_value(mouse_field_tab,
18888e6ce2aSmatthieu 				    &wmcoords)->flags |= FLG_DEAD;
18988e6ce2aSmatthieu 			else
19088e6ce2aSmatthieu 				warn("WSMOUSEIO_GCALIBCOORDS");
19154e3cb1dSfgsch 		}
19288e6ce2aSmatthieu 		wmcoords.samplelen = wmcoords_save.samplelen;
193df69c215Sderaadt 		if (ioctl(fd, WSMOUSEIO_SCALIBCOORDS, &wmcoords) == -1) {
194589b65e9Srobert 			if (errno == ENOTTY) {
195589b65e9Srobert 				field_by_value(mouse_field_tab,
196589b65e9Srobert 				    &wmcoords)->flags |= FLG_DEAD;
197589b65e9Srobert 			} else {
198f0cd74dfSmartynas 				warn("WSMOUSEIO_SCALIBCOORDS");
199f0cd74dfSmartynas 				return 1;
200589b65e9Srobert 			}
201589b65e9Srobert 		}
202e0b2c52dSmickey 	}
203f0cd74dfSmartynas 
204d22ea701Sbru 	for (f = mouse_field_tab; f->name != NULL; f++) {
205d22ea701Sbru 		if (f->format != FMT_CFG || !(f->flags & FLG_SET))
206d22ea701Sbru 			continue;
207d22ea701Sbru 		if (mousecfg_put_field(fd,
208d22ea701Sbru 		    (struct wsmouse_parameters *) f->valp)) {
209d22ea701Sbru 			warn("mousecfg error (%s)", f->name);
210d22ea701Sbru 			return 1;
211d22ea701Sbru 		}
212d22ea701Sbru 	}
213d22ea701Sbru 
214f0cd74dfSmartynas 	return 0;
215f0cd74dfSmartynas }
2161222b15bSmaja 
21754e3cb1dSfgsch char *
21854e3cb1dSfgsch mouse_next_device(int index)
2191222b15bSmaja {
22054e3cb1dSfgsch 	static char devname[20];
2211222b15bSmaja 
22254e3cb1dSfgsch 	snprintf(devname, sizeof(devname), "/dev/wsmouse%d", index);
22354e3cb1dSfgsch 	return (devname);
2241222b15bSmaja }
225