src/sbin/wsconsctl/mouse.c

223 lines
6.6 KiB
C

/* $OpenBSD: mouse.c,v 1.21 2023/07/02 21:44:04 bru Exp $ */
/* $NetBSD: mouse.c,v 1.3 1999/11/15 13:47:30 ad Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Juergen Hannken-Illjes.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/ioctl.h>
#include <sys/time.h>
#include <dev/wscons/wsconsio.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include "wsconsctl.h"
#include "mousecfg.h"
static u_int mstype;
static u_int resolution;
static u_int samplerate;
static int rawmode;
struct wsmouse_calibcoords wmcoords, wmcoords_save;
struct field mouse_field_tab[] = {
{ "resolution", &resolution, FMT_UINT, FLG_WRONLY },
{ "samplerate", &samplerate, FMT_UINT, FLG_WRONLY },
{ "type", &mstype, FMT_MSTYPE, FLG_RDONLY },
{ "rawmode", &rawmode, FMT_UINT, FLG_MODIFY|FLG_INIT},
{ "scale", &wmcoords, FMT_SCALE, FLG_MODIFY|FLG_INIT},
/* mouse and touchpad configuration (mousecfg): */
{ "reverse_scrolling", &cfg_revscroll, FMT_CFG, FLG_NORDBACK },
/* touchpad-specific options: */
{ "tp.tapping", &cfg_tapping, FMT_CFG, FLG_NORDBACK },
{ "tp.mtbuttons", &cfg_mtbuttons, FMT_CFG, FLG_NORDBACK },
{ "tp.scaling", &cfg_scaling, FMT_CFG, FLG_NORDBACK },
{ "tp.swapsides", &cfg_swapsides, FMT_CFG, FLG_NORDBACK },
{ "tp.disable", &cfg_disable, FMT_CFG, FLG_NORDBACK },
{ "tp.edges", &cfg_edges, FMT_CFG, FLG_NORDBACK },
{ "tp.param", &cfg_param, FMT_CFG, FLG_WRONLY },
/* Add an alias. This field is valid for all wsmouse devices. */
{ "param", &cfg_param, FMT_CFG, FLG_WRONLY },
{ NULL }
};
static int dev_index = -1;
static struct wsmouse_parameters mtbtn_maxdist = {
(struct wsmouse_param[]) { { WSMOUSECFG_MTBTN_MAXDIST, 0 } }, 1
};
void
mouse_init(int devfd, int devidx) {
struct field *f;
const char *errstr;
int err;
if (dev_index == devidx)
return;
if ((err = mousecfg_init(devfd, &errstr))) {
devidx = -1;
for (f = mouse_field_tab; f->name != NULL; f++) {
if (f->format == FMT_CFG)
f->flags |= FLG_DEAD;
}
warnx("mousecfg error: %s (%d)", errstr, err);
} else if (cfg_touchpad) {
for (f = mouse_field_tab; f->name != NULL; f++)
if (f->format == FMT_CFG) {
f->flags &= ~FLG_DEAD;
}
/* Hide the 'mtbuttons' field if the feature is unavailable. */
if (mousecfg_get_field(&mtbtn_maxdist) ||
mtbtn_maxdist.params[0].value < 0) {
f = field_by_value(mouse_field_tab, &cfg_mtbuttons);
f->flags |= FLG_DEAD;
}
} else {
for (f = mouse_field_tab; f->name != NULL; f++)
if (f->format == FMT_CFG) {
if (f->valp != &cfg_param
&& f->valp != &cfg_revscroll)
f->flags |= FLG_DEAD;
else
f->flags &= ~FLG_DEAD;
}
}
dev_index = devidx;
}
void
mouse_get_values(int fd)
{
struct field *f;
if (field_by_value(mouse_field_tab, &mstype)->flags & FLG_GET)
if (ioctl(fd, WSMOUSEIO_GTYPE, &mstype) == -1)
warn("WSMOUSEIO_GTYPE");
if (field_by_value(mouse_field_tab, &rawmode)->flags & FLG_GET) {
if (ioctl(fd, WSMOUSEIO_GCALIBCOORDS, &wmcoords) == -1) {
if (errno == ENOTTY)
field_by_value(mouse_field_tab,
&rawmode)->flags |= FLG_DEAD;
else
warn("WSMOUSEIO_GCALIBCOORDS");
}
rawmode = wmcoords.samplelen;
}
if (field_by_value(mouse_field_tab, &wmcoords)->flags & FLG_GET)
if (ioctl(fd, WSMOUSEIO_GCALIBCOORDS, &wmcoords) == -1) {
if (errno == ENOTTY)
field_by_value(mouse_field_tab,
&wmcoords)->flags |= FLG_DEAD;
else
warn("WSMOUSEIO_GCALIBCOORDS");
}
for (f = mouse_field_tab; f->name != NULL; f++) {
if (f->format != FMT_CFG || !(f->flags & FLG_GET)
|| f->valp == &cfg_param || (f->flags & FLG_DEAD))
continue;
if (mousecfg_get_field((struct wsmouse_parameters *) f->valp)) {
f->flags |= FLG_DEAD;
warnx("mousecfg: invalid key in '%s'", f->name);
}
}
}
int
mouse_put_values(int fd)
{
struct field *f;
if (field_by_value(mouse_field_tab, &resolution)->flags & FLG_SET) {
if (ioctl(fd, WSMOUSEIO_SRES, &resolution) == -1) {
warn("WSMOUSEIO_SRES");
return 1;
}
}
if (field_by_value(mouse_field_tab, &rawmode)->flags & FLG_SET) {
wmcoords.samplelen = rawmode;
if (ioctl(fd, WSMOUSEIO_SCALIBCOORDS, &wmcoords) == -1) {
if (errno == ENOTTY) {
field_by_value(mouse_field_tab,
&rawmode)->flags |= FLG_DEAD;
} else {
warn("WSMOUSEIO_SCALIBCOORDS");
return 1;
}
}
}
if (field_by_value(mouse_field_tab, &wmcoords)->flags & FLG_SET) {
if (ioctl(fd, WSMOUSEIO_GCALIBCOORDS, &wmcoords_save) == -1) {
if (errno == ENOTTY)
field_by_value(mouse_field_tab,
&wmcoords)->flags |= FLG_DEAD;
else
warn("WSMOUSEIO_GCALIBCOORDS");
}
wmcoords.samplelen = wmcoords_save.samplelen;
if (ioctl(fd, WSMOUSEIO_SCALIBCOORDS, &wmcoords) == -1) {
if (errno == ENOTTY) {
field_by_value(mouse_field_tab,
&wmcoords)->flags |= FLG_DEAD;
} else {
warn("WSMOUSEIO_SCALIBCOORDS");
return 1;
}
}
}
for (f = mouse_field_tab; f->name != NULL; f++) {
if (f->format != FMT_CFG || !(f->flags & FLG_SET))
continue;
if (mousecfg_put_field(fd,
(struct wsmouse_parameters *) f->valp)) {
warn("mousecfg error (%s)", f->name);
return 1;
}
}
return 0;
}
char *
mouse_next_device(int index)
{
static char devname[20];
snprintf(devname, sizeof(devname), "/dev/wsmouse%d", index);
return (devname);
}