xref: /openbsd-src/sys/dev/sun/sunkbd.c (revision 850e275390052b330d93020bf619a739a3c277ac)
1 /*	$OpenBSD: sunkbd.c,v 1.21 2005/11/11 16:44:51 miod Exp $	*/
2 
3 /*
4  * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
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
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  *
28  * Effort sponsored in part by the Defense Advanced Research Projects
29  * Agency (DARPA) and Air Force Research Laboratory, Air Force
30  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
31  *
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
37 #include <sys/kernel.h>
38 #include <sys/timeout.h>
39 
40 #include <dev/wscons/wsconsio.h>
41 #include <dev/wscons/wskbdvar.h>
42 
43 #include <dev/sun/sunkbdreg.h>
44 #include <dev/sun/sunkbdvar.h>
45 
46 #ifdef __sparc64__
47 #define	NTCTRL 0
48 #else
49 #include "tctrl.h"
50 #endif
51 
52 #if NTCTRL > 0
53 #include <sparc/dev/tctrlvar.h>		/* XXX for tadpole_bell() */
54 #endif
55 
56 void	sunkbd_bell(struct sunkbd_softc *, u_int, u_int, u_int);
57 int	sunkbd_enable(void *, int);
58 int	sunkbd_getleds(struct sunkbd_softc *);
59 int	sunkbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
60 void	sunkbd_setleds(void *, int);
61 
62 struct wskbd_accessops sunkbd_accessops = {
63 	sunkbd_enable,
64 	sunkbd_setleds,
65 	sunkbd_ioctl
66 };
67 
68 void
69 sunkbd_bell(struct sunkbd_softc *sc, u_int period, u_int pitch, u_int volume)
70 {
71 	int ticks, s;
72 	u_int8_t c = SKBD_CMD_BELLON;
73 
74 #if NTCTRL > 0
75 	if (tadpole_bell(period / 10, pitch, volume) != 0)
76 		return;
77 #endif
78 
79 	s = spltty();
80 	if (sc->sc_bellactive) {
81 		if (sc->sc_belltimeout == 0)
82 			timeout_del(&sc->sc_bellto);
83 	}
84 	if (pitch == 0 || period == 0) {
85 		sunkbd_bellstop(sc);
86 		splx(s);
87 		return;
88 	}
89 	if (sc->sc_bellactive == 0) {
90 		ticks = (period * hz) / 1000;
91 		if (ticks <= 0)
92 			ticks = 1;
93 
94 		sc->sc_bellactive = 1;
95 		sc->sc_belltimeout = 1;
96 		(*sc->sc_sendcmd)(sc, &c, 1);
97 		timeout_add(&sc->sc_bellto, ticks);
98 	}
99 	splx(s);
100 }
101 
102 void
103 sunkbd_bellstop(void *v)
104 {
105 	struct sunkbd_softc *sc = v;
106 	int s;
107 	u_int8_t c;
108 
109 	s = spltty();
110 	sc->sc_belltimeout = 0;
111 	c = SKBD_CMD_BELLOFF;
112 	(*sc->sc_sendcmd)(v, &c, 1);
113 	sc->sc_bellactive = 0;
114 	splx(s);
115 }
116 
117 void
118 sunkbd_decode(u_int8_t c, u_int *type, int *value)
119 {
120 	switch (c) {
121 	case SKBD_RSP_IDLE:
122 		*type = WSCONS_EVENT_ALL_KEYS_UP;
123 		*value = 0;
124 		break;
125 	default:
126 		*type = (c & 0x80) ?
127 		    WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
128 		*value = c & 0x7f;
129 		break;
130 	}
131 }
132 
133 int
134 sunkbd_enable(void *v, int on)
135 {
136 	return (0);
137 }
138 
139 int
140 sunkbd_getleds(struct sunkbd_softc *sc)
141 {
142 	return (sc->sc_leds);
143 }
144 
145 int
146 sunkbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
147 {
148 	struct sunkbd_softc *sc = v;
149 	int *d_int = (int *)data;
150 	struct wskbd_bell_data *d_bell = (struct wskbd_bell_data *)data;
151 
152 	switch (cmd) {
153 	case WSKBDIO_GTYPE:
154 		if (ISTYPE5(sc->sc_layout)) {
155 			*d_int = WSKBD_TYPE_SUN5;
156 		} else {
157 			*d_int = WSKBD_TYPE_SUN;
158 		}
159 		return (0);
160 	case WSKBDIO_SETLEDS:
161 		sunkbd_setleds(sc, *d_int);
162 		return (0);
163 	case WSKBDIO_GETLEDS:
164 		*d_int = sunkbd_getleds(sc);
165 		return (0);
166 	case WSKBDIO_COMPLEXBELL:
167 		sunkbd_bell(sc, d_bell->period, d_bell->pitch, d_bell->volume);
168 		return (0);
169 	}
170 
171 	return (-1);
172 }
173 
174 void
175 sunkbd_raw(struct sunkbd_softc *sc, u_int8_t c)
176 {
177 	int claimed = 0;
178 
179 	if (sc->sc_kbdstate == SKBD_STATE_LAYOUT) {
180 		sc->sc_kbdstate = SKBD_STATE_GETKEY;
181 		sc->sc_layout = c;
182 		return;
183 	}
184 
185 	switch (c) {
186 	case SKBD_RSP_RESET:
187 		sc->sc_kbdstate = SKBD_STATE_RESET;
188 		claimed = 1;
189 		break;
190 	case SKBD_RSP_LAYOUT:
191 		sc->sc_kbdstate = SKBD_STATE_LAYOUT;
192 		claimed = 1;
193 		break;
194 	case SKBD_RSP_IDLE:
195 		sc->sc_kbdstate = SKBD_STATE_GETKEY;
196 		claimed = 1;
197 	}
198 
199 	if (claimed)
200 		return;
201 
202 	switch (sc->sc_kbdstate) {
203 	case SKBD_STATE_RESET:
204 		sc->sc_kbdstate = SKBD_STATE_GETKEY;
205 		if (c < KB_SUN2 || c > KB_SUN4)
206 			printf("%s: reset: invalid keyboard type 0x%02x\n",
207 			    sc->sc_dev.dv_xname, c);
208 		else
209 			sc->sc_id = c;
210 		break;
211 	case SKBD_STATE_GETKEY:
212 		break;
213 	}
214 }
215 
216 int
217 sunkbd_setclick(struct sunkbd_softc *sc, int click)
218 {
219 	u_int8_t c;
220 
221 	/* Type 2 keyboards do not support keyclick */
222 	if (sc->sc_id == KB_SUN2)
223 		return (ENXIO);
224 
225 	c = click ? SKBD_CMD_CLICKON : SKBD_CMD_CLICKOFF;
226 	(*sc->sc_sendcmd)(sc, &c, 1);
227 	return (0);
228 }
229 
230 void
231 sunkbd_setleds(void *v, int wled)
232 {
233 	struct sunkbd_softc *sc = v;
234 	u_int8_t sled = 0;
235 	u_int8_t cmd[2];
236 
237 	sc->sc_leds = wled;
238 
239 	if (wled & WSKBD_LED_CAPS)
240 		sled |= SKBD_LED_CAPSLOCK;
241 	if (wled & WSKBD_LED_NUM)
242 		sled |= SKBD_LED_NUMLOCK;
243 	if (wled & WSKBD_LED_SCROLL)
244 		sled |= SKBD_LED_SCROLLLOCK;
245 	if (wled & WSKBD_LED_COMPOSE)
246 		sled |= SKBD_LED_COMPOSE;
247 
248 	cmd[0] = SKBD_CMD_SETLED;
249 	cmd[1] = sled;
250 	(*sc->sc_sendcmd)(sc, cmd, sizeof(cmd));
251 }
252