Module Name: src Committed By: nia Date: Tue Sep 28 06:14:28 UTC 2021
Modified Files: src/sys/dev/wscons: wsconsio.h wsmouse.c wsmousevar.h Log Message: wsmouse: add support for "precision scrolling" events and (GET|SET)PARAMS WSCONS_EVENT_HSCROLL and WSCONS_EVENT_VSCROLL are two new wscons event types that allow scrolling with a higher precision ("smoothness") than an emulated scroll wheel, and are useful for touch input drivers. WSMOUSEIO_GETPARAMS and WSMOUSEIO_SETPARAMS are two new ioctls that allow the speed and direction of precision scrolling to be configured. both features were originally implemented in OpenBSD. To generate a diff of this commit: cvs rdiff -u -r1.125 -r1.126 src/sys/dev/wscons/wsconsio.h cvs rdiff -u -r1.69 -r1.70 src/sys/dev/wscons/wsmouse.c cvs rdiff -u -r1.11 -r1.12 src/sys/dev/wscons/wsmousevar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/wscons/wsconsio.h diff -u src/sys/dev/wscons/wsconsio.h:1.125 src/sys/dev/wscons/wsconsio.h:1.126 --- src/sys/dev/wscons/wsconsio.h:1.125 Sat Apr 24 00:15:37 2021 +++ src/sys/dev/wscons/wsconsio.h Tue Sep 28 06:14:27 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: wsconsio.h,v 1.125 2021/04/24 00:15:37 macallan Exp $ */ +/* $NetBSD: wsconsio.h,v 1.126 2021/09/28 06:14:27 nia Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -76,7 +76,8 @@ struct wscons_event { #define WSCONS_EVENT_ASCII 13 /* key code is already ascii */ #define WSCONS_EVENT_MOUSE_DELTA_W 14 /* W delta amount */ #define WSCONS_EVENT_MOUSE_ABSOLUTE_W 15 /* W location */ - +#define WSCONS_EVENT_HSCROLL 16 /* X axis precision scrolling */ +#define WSCONS_EVENT_VSCROLL 17 /* Y axis precision scrolling */ /* * Keyboard ioctls (0 - 31) @@ -270,6 +271,28 @@ struct wsmouse_repeat { #define WSMOUSEIO_SETVERSION _IOW('W', 41, int) #define WSMOUSE_EVENT_VERSION WSEVENT_VERSION +enum wsmousecfg { + WSMOUSECFG_REVERSE_SCROLLING = 0, + /* Touchpad parameters */ + WSMOUSECFG_HORIZSCROLLDIST, + WSMOUSECFG_VERTSCROLLDIST +}; + +struct wsmouse_param { + enum wsmousecfg key; + int value; +}; + +struct wsmouse_parameters { + struct wsmouse_param *params; + unsigned int nparams; +}; + +#define WSMOUSECFG_MAX (128) /* maximum number of wsmouse_params */ + +#define WSMOUSEIO_GETPARAMS _IOW('W', 42, struct wsmouse_parameters) +#define WSMOUSEIO_SETPARAMS _IOW('W', 43, struct wsmouse_parameters) + /* * Display ioctls (64 - 95) */ Index: src/sys/dev/wscons/wsmouse.c diff -u src/sys/dev/wscons/wsmouse.c:1.69 src/sys/dev/wscons/wsmouse.c:1.70 --- src/sys/dev/wscons/wsmouse.c:1.69 Sun Dec 27 16:09:33 2020 +++ src/sys/dev/wscons/wsmouse.c Tue Sep 28 06:14:27 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: wsmouse.c,v 1.69 2020/12/27 16:09:33 tsutsui Exp $ */ +/* $NetBSD: wsmouse.c,v 1.70 2021/09/28 06:14:27 nia Exp $ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. @@ -104,7 +104,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.69 2020/12/27 16:09:33 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.70 2021/09/28 06:14:27 nia Exp $"); #include "wsmouse.h" #include "wsdisplay.h" @@ -170,6 +170,10 @@ struct wsmouse_softc { int sc_repeat_button; callout_t sc_repeat_callout; unsigned int sc_repeat_delay; + + int sc_reverse_scroll; + int sc_horiz_scroll_dist; + int sc_vert_scroll_dist; }; static int wsmouse_match(device_t, cfdata_t, void *); @@ -177,6 +181,13 @@ static void wsmouse_attach(device_t, dev static int wsmouse_detach(device_t, int); static int wsmouse_activate(device_t, enum devact); +static int wsmouse_set_params(struct wsmouse_softc *, + struct wsmouse_param *, size_t); +static int wsmouse_get_params(struct wsmouse_softc *, + struct wsmouse_param *, size_t); +static int wsmouse_handle_params(struct wsmouse_softc *, + struct wsmouse_parameters *, bool); + static int wsmouse_do_ioctl(struct wsmouse_softc *, u_long, void *, int, struct lwp *); @@ -258,6 +269,9 @@ wsmouse_attach(device_t parent, device_t memset(&sc->sc_repeat, 0, sizeof(sc->sc_repeat)); sc->sc_repeat_button = -1; sc->sc_repeat_delay = 0; + sc->sc_reverse_scroll = 0; + sc->sc_horiz_scroll_dist = WSMOUSE_DEFAULT_SCROLL_DIST; + sc->sc_vert_scroll_dist = WSMOUSE_DEFAULT_SCROLL_DIST; callout_init(&sc->sc_repeat_callout, 0); callout_setfunc(&sc->sc_repeat_callout, wsmouse_repeat, sc); @@ -516,6 +530,41 @@ wsmouse_input(device_t wsmousedev, u_int } } +void +wsmouse_precision_scroll(device_t wsmousedev, int x, int y) +{ + struct wsmouse_softc *sc = device_private(wsmousedev); + struct wseventvar *evar; + struct wscons_event events[2]; + int nevents = 0; + + evar = sc->sc_base.me_evp; + if (evar == NULL) + return; + + if (sc->sc_reverse_scroll) { + x = -x; + y = -y; + } + + x = (x * 4096) / sc->sc_horiz_scroll_dist; + y = (y * 4096) / sc->sc_vert_scroll_dist; + + if (x != 0) { + events[nevents].type = WSCONS_EVENT_HSCROLL; + events[nevents].value = x; + nevents++; + } + + if (y != 0) { + events[nevents].type = WSCONS_EVENT_VSCROLL; + events[nevents].value = y; + nevents++; + } + + (void)wsevent_inject(evar, events, nevents); +} + static void wsmouse_repeat(void *v) { @@ -566,6 +615,88 @@ wsmouse_repeat(void *v) splx(oldspl); } +static int +wsmouse_set_params(struct wsmouse_softc *sc, + struct wsmouse_param *buf, size_t nparams) +{ + size_t i = 0; + + for (i = 0; i < nparams; ++i) { + switch (buf[i].key) { + case WSMOUSECFG_REVERSE_SCROLLING: + sc->sc_reverse_scroll = (buf[i].value != 0); + break; + case WSMOUSECFG_HORIZSCROLLDIST: + sc->sc_horiz_scroll_dist = buf[i].value; + break; + case WSMOUSECFG_VERTSCROLLDIST: + sc->sc_vert_scroll_dist = buf[i].value; + break; + } + } + return 0; +} + +static int +wsmouse_get_params(struct wsmouse_softc *sc, + struct wsmouse_param *buf, size_t nparams) +{ + size_t i = 0; + + for (i = 0; i < nparams; ++i) { + switch (buf[i].key) { + case WSMOUSECFG_REVERSE_SCROLLING: + buf[i].value = sc->sc_reverse_scroll; + break; + case WSMOUSECFG_HORIZSCROLLDIST: + buf[i].value = sc->sc_horiz_scroll_dist; + break; + case WSMOUSECFG_VERTSCROLLDIST: + buf[i].value = sc->sc_vert_scroll_dist; + break; + } + } + return 0; +} + +static int +wsmouse_handle_params(struct wsmouse_softc *sc, struct wsmouse_parameters *upl, + bool set) +{ + size_t len; + struct wsmouse_param *buf; + int error = 0; + + if (upl->params == NULL || upl->nparams > WSMOUSECFG_MAX) + return EINVAL; + if (upl->nparams == 0) + return 0; + + len = upl->nparams * sizeof(struct wsmouse_param); + + buf = kmem_alloc(len, KM_SLEEP); + if (buf == NULL) + return ENOMEM; + if ((error = copyin(upl->params, buf, len)) != 0) + goto error; + + if (set) { + error = wsmouse_set_params(sc, buf, upl->nparams); + if (error != 0) + goto error; + } else { + error = wsmouse_get_params(sc, buf, upl->nparams); + if (error != 0) + goto error; + if ((error = copyout(buf, upl->params, len)) != 0) + goto error; + } + +error: + kmem_free(buf, len); + return error; +} + int wsmouseopen(dev_t dev, int flags, int mode, struct lwp *l) { @@ -762,6 +893,16 @@ wsmouse_do_ioctl(struct wsmouse_softc *s case WSMOUSEIO_SETVERSION: return wsevent_setversion(sc->sc_base.me_evp, *(int *)data); + + case WSMOUSEIO_GETPARAMS: + return wsmouse_handle_params(sc, + (struct wsmouse_parameters *)data, false); + + case WSMOUSEIO_SETPARAMS: + if ((flag & FWRITE) == 0) + return EACCES; + return wsmouse_handle_params(sc, + (struct wsmouse_parameters *)data, true); } /* Index: src/sys/dev/wscons/wsmousevar.h diff -u src/sys/dev/wscons/wsmousevar.h:1.11 src/sys/dev/wscons/wsmousevar.h:1.12 --- src/sys/dev/wscons/wsmousevar.h:1.11 Tue May 12 14:47:55 2009 +++ src/sys/dev/wscons/wsmousevar.h Tue Sep 28 06:14:27 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: wsmousevar.h,v 1.11 2009/05/12 14:47:55 cegger Exp $ */ +/* $NetBSD: wsmousevar.h,v 1.12 2021/09/28 06:14:27 nia Exp $ */ /* * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. @@ -73,3 +73,5 @@ int wsmousedevprint(void *, const char * #define WSMOUSE_INPUT_ABSOLUTE_Z (1<<2) #define WSMOUSE_INPUT_ABSOLUTE_W (1<<3) void wsmouse_input(device_t, u_int, int, int, int, int, u_int); +#define WSMOUSE_DEFAULT_SCROLL_DIST (12) +void wsmouse_precision_scroll(device_t, int, int);