diff options
author | Ulf Brosziewski <bru@cvs.openbsd.org> | 2017-07-21 20:38:21 +0000 |
---|---|---|
committer | Ulf Brosziewski <bru@cvs.openbsd.org> | 2017-07-21 20:38:21 +0000 |
commit | 0ffe602890e2d2a20d14c9b6b97feef9a73c4229 (patch) | |
tree | 1ff9fd91a62142b2d78ce2a3ed54f4dad5228737 | |
parent | 91b9b66787de23b3afc7ffde4ce00de6b24ddf98 (diff) |
Add fields for wsmouse/touchpad configuration.
-rw-r--r-- | sbin/wsconsctl/Makefile | 4 | ||||
-rw-r--r-- | sbin/wsconsctl/mouse.c | 64 | ||||
-rw-r--r-- | sbin/wsconsctl/mousecfg.c | 339 | ||||
-rw-r--r-- | sbin/wsconsctl/mousecfg.h | 29 | ||||
-rw-r--r-- | sbin/wsconsctl/util.c | 9 | ||||
-rw-r--r-- | sbin/wsconsctl/wsconsctl.c | 15 | ||||
-rw-r--r-- | sbin/wsconsctl/wsconsctl.h | 4 |
7 files changed, 455 insertions, 9 deletions
diff --git a/sbin/wsconsctl/Makefile b/sbin/wsconsctl/Makefile index d9095d30669..260e1562ca5 100644 --- a/sbin/wsconsctl/Makefile +++ b/sbin/wsconsctl/Makefile @@ -1,10 +1,10 @@ -# $OpenBSD: Makefile,v 1.43 2017/07/10 21:30:37 espie Exp $ +# $OpenBSD: Makefile,v 1.44 2017/07/21 20:38:20 bru Exp $ .if ${MACHINE} != "octeon" PROG= wsconsctl SRCS= display.c keyboard.c keysym.c map_parse.y map_scan.l \ - mouse.c util.c wsconsctl.c + mouse.c mousecfg.c util.c wsconsctl.c CPPFLAGS+= -I${.CURDIR} -I. CLEANFILES+= keysym.h diff --git a/sbin/wsconsctl/mouse.c b/sbin/wsconsctl/mouse.c index a7ec3ed16af..54333dd4658 100644 --- a/sbin/wsconsctl/mouse.c +++ b/sbin/wsconsctl/mouse.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mouse.c,v 1.13 2012/08/08 16:44:07 shadchin Exp $ */ +/* $OpenBSD: mouse.c,v 1.14 2017/07/21 20:38:20 bru Exp $ */ /* $NetBSD: mouse.c,v 1.3 1999/11/15 13:47:30 ad Exp $ */ /*- @@ -38,6 +38,7 @@ #include <fcntl.h> #include <stdio.h> #include "wsconsctl.h" +#include "mousecfg.h" static u_int mstype; static u_int resolution; @@ -52,12 +53,50 @@ struct field mouse_field_tab[] = { { "type", &mstype, FMT_MSTYPE, FLG_RDONLY }, { "rawmode", &rawmode, FMT_UINT, FLG_MODIFY|FLG_INIT}, { "scale", &wmcoords, FMT_SCALE, FLG_MODIFY|FLG_INIT}, + /* touchpad configuration (mousecfg): */ + { "tp.tapping", &cfg_tapping, 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.param", &cfg_param, FMT_CFG, FLG_WRONLY }, { NULL } }; +static int dev_index = -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; + } + if (errstr != NULL) + warnx("mousecfg error: %s (%d)", errstr, err); + } else if (dev_index > -1) { + for (f = mouse_field_tab; f->name != NULL; f++) { + if (f->format == FMT_CFG) + 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) < 0) warn("WSMOUSEIO_GTYPE"); @@ -81,11 +120,24 @@ mouse_get_values(int fd) else warn("WSMOUSEIO_GCALIBCOORDS"); } + + for (f = mouse_field_tab; f->name != NULL; f++) { + if (f->format != FMT_CFG || !(f->flags & FLG_GET)) + continue; + if (f->valp == &cfg_param) + 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) < 0) { warn("WSMOUSEIO_SRES"); @@ -130,6 +182,16 @@ mouse_put_values(int fd) } } + 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; } diff --git a/sbin/wsconsctl/mousecfg.c b/sbin/wsconsctl/mousecfg.c new file mode 100644 index 00000000000..78f4d99dabb --- /dev/null +++ b/sbin/wsconsctl/mousecfg.c @@ -0,0 +1,339 @@ +/* $OpenBSD: mousecfg.c,v 1.1 2017/07/21 20:38:20 bru Exp $ */ + +/* + * Copyright (c) 2017 Ulf Brosziewski + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Read/write wsmouse parameters for touchpad configuration. + */ + +#include <sys/ioctl.h> +#include <sys/param.h> +#include <dev/wscons/wsconsio.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <err.h> +#include <errno.h> +#include "mousecfg.h" + +#define BASE_FIRST WSMOUSECFG_DX_SCALE +#define BASE_LAST WSMOUSECFG_Y_INV +#define TP_FILTER_FIRST WSMOUSECFG_DX_MAX +#define TP_FILTER_LAST WSMOUSECFG_SMOOTHING +#define TP_FEATURES_FIRST WSMOUSECFG_SOFTBUTTONS +#define TP_FEATURES_LAST WSMOUSECFG_TAPPING +#define TP_SETUP_FIRST WSMOUSECFG_LEFT_EDGE +#define TP_SETUP_LAST WSMOUSECFG_TAP_LOCKTIME + +#define BASESIZE (BASE_LAST - BASE_FIRST + 1) + +#define BUFSIZE (BASESIZE \ + + (TP_FILTER_LAST - TP_FILTER_FIRST + 1) \ + + (TP_FEATURES_LAST - TP_FEATURES_FIRST + 1) \ + + (TP_SETUP_LAST - TP_SETUP_FIRST + 1)) + +static const int range[][2] = { + { BASE_FIRST, BASE_LAST }, + { TP_FILTER_FIRST, TP_FILTER_LAST }, + { TP_FEATURES_FIRST, TP_FEATURES_LAST }, + { TP_SETUP_FIRST, TP_SETUP_LAST }, +}; + +static const int touchpad_types[] = { + WSMOUSE_TYPE_SYNAPTICS, /* Synaptics touchpad */ + WSMOUSE_TYPE_ALPS, /* ALPS touchpad */ + WSMOUSE_TYPE_ELANTECH, /* Elantech touchpad */ + WSMOUSE_TYPE_SYNAP_SBTN, /* Synaptics soft buttons */ +}; + +struct wsmouse_parameters cfg_tapping = { + (struct wsmouse_param[]) { + { WSMOUSECFG_TAPPING, 0 }, }, + 1 +}; + +struct wsmouse_parameters cfg_scaling = { + (struct wsmouse_param[]) { + { WSMOUSECFG_DX_SCALE, 0 }, + { WSMOUSECFG_DY_SCALE, 0 } }, + 2 +}; + +struct wsmouse_parameters cfg_swapsides = { + (struct wsmouse_param[]) { + { WSMOUSECFG_SWAPSIDES, 0 }, }, + 1 +}; + +struct wsmouse_parameters cfg_disable = { + (struct wsmouse_param[]) { + { WSMOUSECFG_DISABLE, 0 }, }, + 1 +}; + +struct wsmouse_parameters cfg_param = { + (struct wsmouse_param[]) { + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 } }, + 4 +}; + +static int cfg_horiz_res; +static int cfg_vert_res; +static struct wsmouse_param cfg_buffer[BUFSIZE]; + + +int +mousecfg_init(int dev_fd, const char **errstr) +{ + struct wsmouse_calibcoords coords; + struct wsmouse_parameters parameters; + struct wsmouse_param *param; + enum wsmousecfg k; + int i, err, type; + + *errstr = NULL; + + if ((err = ioctl(dev_fd, WSMOUSEIO_GTYPE, &type))) { + *errstr = "WSMOUSEIO_GTYPE"; + return err; + } + for (i = 0; i < nitems(touchpad_types) + && type != touchpad_types[i]; i++) {} + + /* + * If the device is not a touchpad, return an error without + * setting the error string. The caller shouldn't print a + * warning in this case. + */ + if (i == nitems(touchpad_types)) + return (-1); + + if ((err = ioctl(dev_fd, WSMOUSEIO_GCALIBCOORDS, &coords))) { + *errstr = "WSMOUSEIO_GCALIBCOORDS"; + return err; + } + cfg_horiz_res = coords.resx; + cfg_vert_res = coords.resy; + + param = cfg_buffer; + for (i = 0; i < nitems(range); i++) + for (k = range[i][0]; k <= range[i][1]; k++, param++) { + param->key = k; + param->value = 0; + } + + /* + * Not all touchpad drivers configure wsmouse for compat mode yet. + * In those cases the first ioctl call may be successful but the + * second one will fail because it includes wstpad parameters: + */ + parameters.params = cfg_buffer; + parameters.nparams = BASESIZE; + if ((err = ioctl(dev_fd, WSMOUSEIO_GETPARAMS, ¶meters))) { + *errstr = "WSMOUSEIO_GETPARAMS"; + return (err); + } + parameters.params = cfg_buffer + BASESIZE; + parameters.nparams = BUFSIZE - BASESIZE; + if ((err = ioctl(dev_fd, WSMOUSEIO_GETPARAMS, ¶meters))) { + if (err != EINVAL) + *errstr = "WSMOUSEIO_GETPARAMS"; + return (err); + } + + return (0); +} + +/* Map a key to its buffer index. */ +static int +index_of(enum wsmousecfg key) +{ + int i, n; + + for (i = 0, n = 0; i < nitems(range); i++) + if (key <= range[i][1] && key >= range[i][0]) + return (key - range[i][0] + n); + else + n += range[i][1] - range[i][0] + 1; + + return (-1); +} + +int +mousecfg_get_field(struct wsmouse_parameters *field) +{ + int i, n; + + for (i = 0; i < field->nparams; i++) { + if ((n = index_of(field->params[i].key)) >= 0) + field->params[i].value = cfg_buffer[n].value; + else + return (-1); + } + return (0); +} + +int +mousecfg_put_field(int fd, struct wsmouse_parameters *field) +{ + int i, n, d, err; + + d = 0; + for (i = 0; i < field->nparams; i++) + if ((n = index_of(field->params[i].key)) < 0) + return (-1); + else + d |= (cfg_buffer[n].value != field->params[i].value); + + if (!d) + return (0); + + /* Write and read back immediately, wsmouse may normalize values. */ + if ((err = ioctl(fd, WSMOUSEIO_SETPARAMS, field)) + || (err = ioctl(fd, WSMOUSEIO_GETPARAMS, field))) + return err; + + for (i = 0; i < field->nparams; i++) + cfg_buffer[n].value = field->params[i].value; + + return (0); +} + +static int +get_value(struct wsmouse_parameters *field, enum wsmousecfg key) +{ + int i; + + for (i = 0; i < field->nparams && key != field->params[i].key; i++) {} + + return (i < field->nparams ? field->params[i].value : 0); +} + +static void +set_value(struct wsmouse_parameters *field, enum wsmousecfg key, int value) +{ + int i; + + for (i = 0; i < field->nparams && key != field->params[i].key; i++) {} + + field->params[i].value = (i < field->nparams ? value : 0); +} + +/* + * Read or write up to four raw parameter values. In this case + * reading is a 'put' operation that writes back a value from the + * buffer. + */ +static int +read_param(struct wsmouse_parameters *field, char *val) +{ + int i, j, n; + + n = sscanf(val, "%d:%d,%d:%d,%d:%d,%d:%d", + &field->params[0].key, &field->params[0].value, + &field->params[1].key, &field->params[1].value, + &field->params[2].key, &field->params[2].value, + &field->params[3].key, &field->params[3].value); + if (n > 0 && (n & 1) == 0) { + n /= 2; + for (i = 0; i < n; i++) { + if (index_of(field->params[i].key) < 0) + return (-1); + } + field->nparams = n; + return (0); + } + n = sscanf(val, "%d,%d,%d,%d", + &field->params[0].key, &field->params[1].key, + &field->params[2].key, &field->params[3].key); + if (n > 0) { + for (i = 0; i < n; i++) { + if ((j = index_of(field->params[i].key)) < 0) + return (-1); + field->params[i].value = cfg_buffer[j].value; + } + field->nparams = n; + return (0); + } + return (-1); +} + +void +mousecfg_pr_field(struct wsmouse_parameters *field) +{ + int i, value; + float f; + + if (field == &cfg_param) { + for (i = 0; i < field->nparams; i++) + printf(i > 0 ? ",%d:%d" : "%d:%d", + field->params[i].key, + field->params[i].value); + return; + } + + if (field == &cfg_scaling) { + value = get_value(field, WSMOUSECFG_DX_SCALE); + f = (float) value / 4096; + printf("%.3f", f); + return; + } + + for (i = 0; i < field->nparams; i++) + printf(i > 0 ? ",%d" : "%d", field->params[i].value); +} + +void +mousecfg_rd_field(struct wsmouse_parameters *field, char *val) +{ + enum wsmousecfg first = field->params[0].key; + int i, n; + const char *s; + float f; + + if (field == &cfg_param) { + if (read_param(field, val)) + errx(1, "invalid input (param)"); + return; + } + + if (field == &cfg_scaling) { + if (sscanf(val, "%f", &f) == 1) { + n = (int) (f * 4096); + set_value(field, WSMOUSECFG_DX_SCALE, n); + if (cfg_horiz_res && cfg_vert_res) + n = n * cfg_horiz_res / cfg_vert_res; + set_value(field, WSMOUSECFG_DY_SCALE, n); + } else { + errx(1, "invalid input (scaling)"); + } + return; + } + + s = val; + for (i = 0; i < field->nparams; i++) { + if (sscanf(s, (i > 0 ? ",%d" : "%d"), &n) != 1) + break; + field->params[i].value = abs(n); + for (s++; *s != '\0' && *s != ','; s++) {} + } + if (i < field->nparams || *s != '\0') + errx(1, "invalid input '%s'", val); +} diff --git a/sbin/wsconsctl/mousecfg.h b/sbin/wsconsctl/mousecfg.h new file mode 100644 index 00000000000..4d63c4d7147 --- /dev/null +++ b/sbin/wsconsctl/mousecfg.h @@ -0,0 +1,29 @@ +/* $OpenBSD: mousecfg.h,v 1.1 2017/07/21 20:38:20 bru Exp $ */ + +/* + * Copyright (c) 2017 Ulf Brosziewski + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +extern struct wsmouse_parameters cfg_tapping; +extern struct wsmouse_parameters cfg_scaling; +extern struct wsmouse_parameters cfg_swapsides; +extern struct wsmouse_parameters cfg_disable; +extern struct wsmouse_parameters cfg_param; + +int mousecfg_init(int, const char **); +int mousecfg_get_field(struct wsmouse_parameters *); +int mousecfg_put_field(int, struct wsmouse_parameters *); +void mousecfg_pr_field(struct wsmouse_parameters *); +void mousecfg_rd_field(struct wsmouse_parameters *, char *); diff --git a/sbin/wsconsctl/util.c b/sbin/wsconsctl/util.c index 0e505f2f656..8d697c85088 100644 --- a/sbin/wsconsctl/util.c +++ b/sbin/wsconsctl/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.63 2016/02/10 05:49:50 guenther Exp $ */ +/* $OpenBSD: util.c,v 1.64 2017/07/21 20:38:20 bru Exp $ */ /* $NetBSD: util.c,v 1.8 2000/03/14 08:11:53 sato Exp $ */ /*- @@ -40,6 +40,7 @@ #include <stdio.h> #include <unistd.h> #include "wsconsctl.h" +#include "mousecfg.h" #define TABLEN(t) (sizeof(t)/sizeof(t[0])) @@ -309,6 +310,9 @@ pr_field(const char *pre, struct field *f, const char *sep) case FMT_STRING: printf("%s", (const char *)f->valp); break; + case FMT_CFG: + mousecfg_pr_field((struct wsmouse_parameters *) f->valp); + break; default: errx(1, "internal error: pr_field: no format %d", f->format); break; @@ -462,6 +466,9 @@ rd_field(struct field *f, char *val, int merge) case FMT_STRING: strlcpy(f->valp, val, WSFONT_NAME_SIZE); break; + case FMT_CFG: + mousecfg_rd_field((struct wsmouse_parameters *) f->valp, val); + break; default: errx(1, "internal error: rd_field: no format %d", f->format); break; diff --git a/sbin/wsconsctl/wsconsctl.c b/sbin/wsconsctl/wsconsctl.c index d821f19df44..1c62df8fe5d 100644 --- a/sbin/wsconsctl/wsconsctl.c +++ b/sbin/wsconsctl/wsconsctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wsconsctl.c,v 1.30 2017/04/06 17:33:39 jmc Exp $ */ +/* $OpenBSD: wsconsctl.c,v 1.31 2017/07/21 20:38:20 bru Exp $ */ /* $NetBSD: wsconsctl.c,v 1.2 1998/12/29 22:40:20 hannken Exp $ */ /*- @@ -50,15 +50,16 @@ void usage(void); struct vartypesw { const char *name; struct field *field_tab; + void (*init)(int,int); void (*getval)(int); int (*putval)(int); char * (*nextdev)(int); } typesw[] = { - { "keyboard", keyboard_field_tab, + { "keyboard", keyboard_field_tab, NULL, keyboard_get_values, keyboard_put_values, keyboard_next_device }, - { "mouse", mouse_field_tab, + { "mouse", mouse_field_tab, mouse_init, mouse_get_values, mouse_put_values, mouse_next_device }, - { "display", display_field_tab, + { "display", display_field_tab, NULL, display_get_values, display_put_values, display_next_device }, { NULL } }; @@ -138,6 +139,9 @@ main(int argc, char *argv[]) snprintf(devname, sizeof(devname), "%s%d", sw->name, devidx); + if (sw->init != NULL) + (*sw->init)(devfd, devidx); + for (f = sw->field_tab; f->name; f++) if (!(f->flags & (FLG_NOAUTO|FLG_WRONLY))) @@ -189,6 +193,9 @@ main(int argc, char *argv[]) snprintf(devname, sizeof(devname), "%s%d", sw->name, devidx); + if (sw->init != NULL) + (*sw->init)(devfd, devidx); + p = strchr(argv[i], '='); if (p == NULL) { if (!strchr(argv[i], '.')) { diff --git a/sbin/wsconsctl/wsconsctl.h b/sbin/wsconsctl/wsconsctl.h index 7ee37706d95..3a6e38d67e2 100644 --- a/sbin/wsconsctl/wsconsctl.h +++ b/sbin/wsconsctl/wsconsctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wsconsctl.h,v 1.15 2015/05/08 19:12:51 miod Exp $ */ +/* $OpenBSD: wsconsctl.h,v 1.16 2017/07/21 20:38:20 bru Exp $ */ /* $NetBSD: wsconsctl.h 1.1 1998/12/28 14:01:17 hannken Exp $ */ /*- @@ -48,6 +48,7 @@ struct field { #define FMT_EMUL 107 /* wsdisplay emulations */ #define FMT_SCREEN 108 /* wsdisplay screen types */ #define FMT_STRING 109 /* free string */ +#define FMT_CFG 201 /* wsmouse parameters */ int format; #define FLG_RDONLY 0x0001 /* variable cannot be modified */ #define FLG_WRONLY 0x0002 /* variable cannot be displayed */ @@ -78,6 +79,7 @@ keysym_t ksym_upcase(keysym_t); void keyboard_get_values(int); int keyboard_put_values(int); char * keyboard_next_device(int); +void mouse_init(int,int); void mouse_get_values(int); int mouse_put_values(int); char * mouse_next_device(int); |