1 /* $OpenBSD: mouse.c,v 1.22 2024/10/05 13:27:16 chrisz Exp $ */ 2 /* $NetBSD: mouse.c,v 1.3 1999/11/15 13:47:30 ad Exp $ */ 3 4 /*- 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Juergen Hannken-Illjes. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/ioctl.h> 34 #include <sys/time.h> 35 #include <dev/wscons/wsconsio.h> 36 #include <err.h> 37 #include <errno.h> 38 #include <fcntl.h> 39 #include <stdio.h> 40 #include "wsconsctl.h" 41 #include "mousecfg.h" 42 43 static u_int mstype; 44 static u_int resolution; 45 static u_int samplerate; 46 static int rawmode; 47 48 struct wsmouse_calibcoords wmcoords, wmcoords_save; 49 50 struct field mouse_field_tab[] = { 51 { "resolution", &resolution, FMT_UINT, FLG_WRONLY }, 52 { "samplerate", &samplerate, FMT_UINT, FLG_WRONLY }, 53 { "type", &mstype, FMT_MSTYPE, FLG_RDONLY }, 54 { "rawmode", &rawmode, FMT_UINT, FLG_MODIFY|FLG_INIT}, 55 { "scale", &wmcoords, FMT_SCALE, FLG_MODIFY|FLG_INIT}, 56 /* mouse and touchpad configuration (mousecfg): */ 57 { "reverse_scrolling", &cfg_revscroll, FMT_CFG, FLG_NORDBACK }, 58 /* touchpad-specific options: */ 59 { "tp.tapping", &cfg_tapping, FMT_CFG, FLG_NORDBACK }, 60 { "tp.mtbuttons", &cfg_mtbuttons, FMT_CFG, FLG_NORDBACK }, 61 { "tp.scaling", &cfg_scaling, FMT_CFG, FLG_NORDBACK | FLG_WRONLY }, 62 { "tp.swapsides", &cfg_swapsides, FMT_CFG, FLG_NORDBACK }, 63 { "tp.disable", &cfg_disable, FMT_CFG, FLG_NORDBACK }, 64 { "tp.edges", &cfg_edges, FMT_CFG, FLG_NORDBACK }, 65 { "tp.param", &cfg_param, FMT_CFG, FLG_WRONLY }, 66 /* Add aliases. These fields are valid for all wsmouse devices. */ 67 { "param", &cfg_param, FMT_CFG, FLG_WRONLY }, 68 { "scaling", &cfg_scaling, FMT_CFG, FLG_NORDBACK }, 69 { NULL } 70 }; 71 72 static int dev_index = -1; 73 74 static struct wsmouse_parameters mtbtn_maxdist = { 75 (struct wsmouse_param[]) { { WSMOUSECFG_MTBTN_MAXDIST, 0 } }, 1 76 }; 77 78 79 void 80 mouse_init(int devfd, int devidx) { 81 struct field *f; 82 const char *errstr; 83 int err; 84 85 if (dev_index == devidx) 86 return; 87 88 if ((err = mousecfg_init(devfd, &errstr))) { 89 devidx = -1; 90 for (f = mouse_field_tab; f->name != NULL; f++) { 91 if (f->format == FMT_CFG) 92 f->flags |= FLG_DEAD; 93 } 94 warnx("mousecfg error: %s (%d)", errstr, err); 95 } else if (cfg_touchpad) { 96 for (f = mouse_field_tab; f->name != NULL; f++) 97 if (f->format == FMT_CFG) { 98 f->flags &= ~FLG_DEAD; 99 } 100 /* Hide the 'mtbuttons' field if the feature is unavailable. */ 101 if (mousecfg_get_field(&mtbtn_maxdist) || 102 mtbtn_maxdist.params[0].value < 0) { 103 f = field_by_value(mouse_field_tab, &cfg_mtbuttons); 104 f->flags |= FLG_DEAD; 105 } 106 } else { 107 for (f = mouse_field_tab; f->name != NULL; f++) 108 if (f->format == FMT_CFG) { 109 if (f->valp != &cfg_param 110 && f->valp != &cfg_scaling 111 && f->valp != &cfg_revscroll) 112 f->flags |= FLG_DEAD; 113 else 114 f->flags &= ~FLG_DEAD; 115 } 116 } 117 118 dev_index = devidx; 119 } 120 121 void 122 mouse_get_values(int fd) 123 { 124 struct field *f; 125 126 if (field_by_value(mouse_field_tab, &mstype)->flags & FLG_GET) 127 if (ioctl(fd, WSMOUSEIO_GTYPE, &mstype) == -1) 128 warn("WSMOUSEIO_GTYPE"); 129 130 if (field_by_value(mouse_field_tab, &rawmode)->flags & FLG_GET) { 131 if (ioctl(fd, WSMOUSEIO_GCALIBCOORDS, &wmcoords) == -1) { 132 if (errno == ENOTTY) 133 field_by_value(mouse_field_tab, 134 &rawmode)->flags |= FLG_DEAD; 135 else 136 warn("WSMOUSEIO_GCALIBCOORDS"); 137 } 138 rawmode = wmcoords.samplelen; 139 } 140 141 if (field_by_value(mouse_field_tab, &wmcoords)->flags & FLG_GET) 142 if (ioctl(fd, WSMOUSEIO_GCALIBCOORDS, &wmcoords) == -1) { 143 if (errno == ENOTTY) 144 field_by_value(mouse_field_tab, 145 &wmcoords)->flags |= FLG_DEAD; 146 else 147 warn("WSMOUSEIO_GCALIBCOORDS"); 148 } 149 150 for (f = mouse_field_tab; f->name != NULL; f++) { 151 if (f->format != FMT_CFG || !(f->flags & FLG_GET) 152 || f->valp == &cfg_param || (f->flags & FLG_DEAD)) 153 continue; 154 if (mousecfg_get_field((struct wsmouse_parameters *) f->valp)) { 155 f->flags |= FLG_DEAD; 156 warnx("mousecfg: invalid key in '%s'", f->name); 157 } 158 } 159 } 160 161 int 162 mouse_put_values(int fd) 163 { 164 struct field *f; 165 166 if (field_by_value(mouse_field_tab, &resolution)->flags & FLG_SET) { 167 if (ioctl(fd, WSMOUSEIO_SRES, &resolution) == -1) { 168 warn("WSMOUSEIO_SRES"); 169 return 1; 170 } 171 } 172 if (field_by_value(mouse_field_tab, &rawmode)->flags & FLG_SET) { 173 wmcoords.samplelen = rawmode; 174 if (ioctl(fd, WSMOUSEIO_SCALIBCOORDS, &wmcoords) == -1) { 175 if (errno == ENOTTY) { 176 field_by_value(mouse_field_tab, 177 &rawmode)->flags |= FLG_DEAD; 178 } else { 179 warn("WSMOUSEIO_SCALIBCOORDS"); 180 return 1; 181 } 182 } 183 } 184 if (field_by_value(mouse_field_tab, &wmcoords)->flags & FLG_SET) { 185 if (ioctl(fd, WSMOUSEIO_GCALIBCOORDS, &wmcoords_save) == -1) { 186 if (errno == ENOTTY) 187 field_by_value(mouse_field_tab, 188 &wmcoords)->flags |= FLG_DEAD; 189 else 190 warn("WSMOUSEIO_GCALIBCOORDS"); 191 } 192 wmcoords.samplelen = wmcoords_save.samplelen; 193 if (ioctl(fd, WSMOUSEIO_SCALIBCOORDS, &wmcoords) == -1) { 194 if (errno == ENOTTY) { 195 field_by_value(mouse_field_tab, 196 &wmcoords)->flags |= FLG_DEAD; 197 } else { 198 warn("WSMOUSEIO_SCALIBCOORDS"); 199 return 1; 200 } 201 } 202 } 203 204 for (f = mouse_field_tab; f->name != NULL; f++) { 205 if (f->format != FMT_CFG || !(f->flags & FLG_SET)) 206 continue; 207 if (mousecfg_put_field(fd, 208 (struct wsmouse_parameters *) f->valp)) { 209 warn("mousecfg error (%s)", f->name); 210 return 1; 211 } 212 } 213 214 return 0; 215 } 216 217 char * 218 mouse_next_device(int index) 219 { 220 static char devname[20]; 221 222 snprintf(devname, sizeof(devname), "/dev/wsmouse%d", index); 223 return (devname); 224 } 225