1 /* $OpenBSD: sunms.c,v 1.3 2022/01/09 05:43:00 jsg Exp $ */
2
3 /*
4 * Copyright (c) 2002, 2009, Miodrag Vallat
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /*
29 * Common Sun mouse handling code.
30 *
31 * This code supports 3- and 5- byte Mouse Systems protocols, and speeds of
32 * 1200, 4800 and 9600 bps.
33 */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/conf.h>
38 #include <sys/device.h>
39 #include <sys/ioctl.h>
40 #include <sys/kernel.h>
41 #include <sys/proc.h>
42 #include <sys/time.h>
43 #include <sys/timeout.h>
44
45 #include <dev/wscons/wsconsio.h>
46 #include <dev/wscons/wsmousevar.h>
47
48 #include <dev/sun/sunmsvar.h>
49
50 void
sunms_attach(struct sunms_softc * sc,const struct wsmouse_accessops * ao)51 sunms_attach(struct sunms_softc *sc, const struct wsmouse_accessops *ao)
52 {
53 struct wsmousedev_attach_args a;
54
55 printf("\n");
56
57 /* Initialize state machine. */
58 sc->sc_state = STATE_PROBING;
59 sc->sc_bps = INIT_SPEED;
60 timeout_set(&sc->sc_abort_tmo, sunms_abort_input, sc);
61
62 /*
63 * Note that it doesn't matter if a long time elapses between this
64 * and the moment interrupts are enabled, as we either have the
65 * right speed, and will switch to decode state, or get a break
66 * or a framing error, causing an immediate speed change.
67 */
68 getmicrotime(&sc->sc_lastbpschange);
69
70 a.accessops = ao;
71 a.accesscookie = sc;
72 sc->sc_wsmousedev = config_found(&sc->sc_dev, &a, wsmousedevprint);
73 }
74
75 int
sunms_ioctl(void * v,u_long cmd,caddr_t data,int flag,struct proc * p)76 sunms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
77 {
78 #if 0
79 struct sunms_softc *sc = v;
80 #endif
81
82 switch (cmd) {
83 case WSMOUSEIO_GTYPE:
84 *(u_int *)data = WSMOUSE_TYPE_SUN;
85 break;
86
87 default:
88 return -1;
89 }
90
91 return 0;
92 }
93
94 /*
95 * Reinitialize the line to a different speed. Invoked at spltty().
96 */
97 void
sunms_speed_change(struct sunms_softc * sc)98 sunms_speed_change(struct sunms_softc *sc)
99 {
100 uint bps;
101
102 switch (sc->sc_bps) {
103 default:
104 case 9600:
105 bps = 4800;
106 break;
107 case 4800:
108 bps = 1200;
109 break;
110 case 1200:
111 bps = 9600;
112 break;
113 }
114
115 #ifdef DEBUG
116 printf("%s: %d bps\n", sc->sc_dev.dv_xname, bps);
117 #endif
118 microtime(&sc->sc_lastbpschange);
119
120 (*sc->sc_speed_change)(sc, bps);
121 sc->sc_state = STATE_PROBING;
122 sc->sc_bps = bps;
123 sc->sc_brk = 0;
124 timeout_del(&sc->sc_abort_tmo);
125 }
126
127 /*
128 * Process actual mouse data. Invoked at spltty().
129 */
130 void
sunms_input(struct sunms_softc * sc,int c)131 sunms_input(struct sunms_softc *sc, int c)
132 {
133 struct timeval curtime;
134
135 if (sc->sc_wsmousedev == NULL)
136 return; /* why bother */
137
138 if (sc->sc_state == STATE_RATE_CHANGE)
139 return; /* not ready yet */
140
141 /*
142 * If we have changed speed recently, ignore data for a few
143 * milliseconds to make sure that either we'll detect the speed
144 * is still not correct, or discard potential noise resulting
145 * from the speed change.
146 */
147 if (sc->sc_state == STATE_PROBING) {
148 microtime(&curtime);
149 timersub(&curtime, &sc->sc_lastbpschange, &curtime);
150 if (curtime.tv_sec != 0 ||
151 curtime.tv_usec >= 200 * 1000) {
152 sc->sc_state = STATE_DECODING;
153 sc->sc_byteno = -1;
154 } else
155 return;
156 }
157
158 /*
159 * The Sun mice use either 3 byte or 5 byte packets. The
160 * first byte of each packet has the topmost bit set;
161 * however motion parts of the packet may have the topmost
162 * bit set too; so we only check for a first byte pattern
163 * when we are not currently processing a packet.
164 */
165 if (sc->sc_byteno < 0) {
166 if (ISSET(c, 0x80) && !ISSET(c, 0x30))
167 sc->sc_byteno = 0;
168 else
169 return;
170 }
171
172 switch (sc->sc_byteno) {
173 case 0:
174 /*
175 * First packet has bit 7 set; bits 0-2 are button states,
176 * and bit 3 is set if it is a short (3 byte) packet.
177 * On the Tadpole SPARCbook, mice connected to the external
178 * connector will also have bit 6 set to allow it to be
179 * differentiated from the onboard pointer.
180 */
181 sc->sc_pktlen = ISSET(c, 0x08) ? 3 : 5;
182 sc->sc_mb = 0;
183 if (!ISSET(c, 1 << 2)) /* left button */
184 sc->sc_mb |= 1 << 0;
185 if (!ISSET(c, 1 << 1)) /* middle button */
186 sc->sc_mb |= 1 << 1;
187 if (!ISSET(c, 1 << 0)) /* right button */
188 sc->sc_mb |= 1 << 2;
189 sc->sc_byteno++;
190
191 /*
192 * In case we do not receive the whole packet, we need
193 * to be able to reset sc_byteno.
194 *
195 * At 1200bps 8N2, a five byte packet will span 50 bits
196 * and thus will transmit in 1/24 second, or about 42ms.
197 *
198 * A reset timeout of 100ms will be more than enough.
199 */
200 timeout_add_msec(&sc->sc_abort_tmo, 100);
201
202 break;
203 case 1:
204 case 3:
205 /*
206 * Following bytes contain signed 7 bit X, then Y deltas.
207 * Short packets only have one set of deltas (and are
208 * thus usually used on 4800 baud mice).
209 */
210 sc->sc_dx += (int8_t)c;
211 sc->sc_byteno++;
212 break;
213 case 2:
214 case 4:
215 sc->sc_dy += (int8_t)c;
216 sc->sc_byteno++;
217 break;
218 }
219
220 if (sc->sc_byteno == sc->sc_pktlen) {
221 timeout_del(&sc->sc_abort_tmo);
222 sc->sc_byteno = -1;
223 WSMOUSE_INPUT(sc->sc_wsmousedev,
224 sc->sc_mb, sc->sc_dx, sc->sc_dy, 0, 0);
225 sc->sc_dx = sc->sc_dy = 0;
226 }
227 }
228
229 void
sunms_abort_input(void * v)230 sunms_abort_input(void *v)
231 {
232 struct sunms_softc *sc = v;
233 int s;
234
235 #ifdef DEBUG
236 printf("aborting incomplete packet\n");
237 #endif
238 s = spltty();
239 sc->sc_byteno = -1;
240 splx(s);
241 }
242