xref: /csrg-svn/sys/sparc/dev/kbd.c (revision 55105)
1*55105Storek /*
2*55105Storek  * Copyright (c) 1992 The Regents of the University of California.
3*55105Storek  * All rights reserved.
4*55105Storek  *
5*55105Storek  * This software was developed by the Computer Systems Engineering group
6*55105Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7*55105Storek  * contributed to Berkeley.
8*55105Storek  *
9*55105Storek  * %sccs.include.redist.c%
10*55105Storek  *
11*55105Storek  *	@(#)kbd.c	7.1 (Berkeley) 07/13/92
12*55105Storek  *
13*55105Storek  * from: $Header: kbd.c,v 1.15 92/07/09 07:59:27 torek Exp $ (LBL)
14*55105Storek  */
15*55105Storek 
16*55105Storek /*
17*55105Storek  * Keyboard driver (/dev/kbd -- note that we do not have minor numbers
18*55105Storek  * [yet?]).  Translates incoming bytes to ASCII or to `firm_events' and
19*55105Storek  * passes them up to the appropriate reader.
20*55105Storek  */
21*55105Storek 
22*55105Storek #include "sys/param.h"
23*55105Storek #include "sys/conf.h"
24*55105Storek #include "sys/device.h"
25*55105Storek #include "sys/ioctl.h"
26*55105Storek #include "sys/kernel.h"
27*55105Storek #include "sys/proc.h"
28*55105Storek #include "sys/syslog.h"
29*55105Storek #include "sys/systm.h"
30*55105Storek #include "sys/tty.h"
31*55105Storek 
32*55105Storek #include "machine/autoconf.h"
33*55105Storek 
34*55105Storek #include "vuid_event.h"
35*55105Storek #include "event_var.h"
36*55105Storek #include "kbd.h"
37*55105Storek #include "kbio.h"
38*55105Storek 
39*55105Storek /*
40*55105Storek  * Sun keyboard definitions (from Sprite).
41*55105Storek  * These apply to type 2, 3 and 4 keyboards.
42*55105Storek  */
43*55105Storek #define	KEY_CODE(c)	((c) & KBD_KEYMASK)	/* keyboard code index */
44*55105Storek #define	KEY_UP(c)	((c) & KBD_UP)		/* true => key went up */
45*55105Storek 
46*55105Storek /*
47*55105Storek  * Each KEY_CODE(x) can be translated via the tables below.
48*55105Storek  * The result is either a valid ASCII value in [0..0x7f] or is one
49*55105Storek  * of the following `magic' values saying something interesting
50*55105Storek  * happened.  If LSHIFT or RSHIFT has changed state the next
51*55105Storek  * lookup should come from the appropriate table; if ALLUP is
52*55105Storek  * sent all keys (including both shifts and the control key) are
53*55105Storek  * now up, and the next byte is the keyboard ID code.
54*55105Storek  *
55*55105Storek  * These tables ignore all function keys (on the theory that if you
56*55105Storek  * want these keys, you should use a window system).  Note that
57*55105Storek  * `caps lock' is just mapped as `ignore' (so there!). (Only the
58*55105Storek  * type 3 and 4 keyboards have a caps lock key anyway.)
59*55105Storek  */
60*55105Storek #define	KEY_MAGIC	0x80		/* flag => magic value */
61*55105Storek #define	KEY_IGNORE	0x80
62*55105Storek #define	KEY_L1		KEY_IGNORE
63*55105Storek #define	KEY_CAPSLOCK	KEY_IGNORE
64*55105Storek #define	KEY_LSHIFT	0x81
65*55105Storek #define	KEY_RSHIFT	0x82
66*55105Storek #define	KEY_CONTROL	0x83
67*55105Storek #define	KEY_ALLUP	0x84		/* all keys are now up; also reset */
68*55105Storek 
69*55105Storek /*
70*55105Storek  * Decode tables for type 2, 3, and 4 keyboards
71*55105Storek  * (stolen from Sprite; see also kbd.h).
72*55105Storek  */
73*55105Storek static const u_char kbd_unshifted[] = {
74*55105Storek /*   0 */	KEY_IGNORE,	KEY_L1,		KEY_IGNORE,	KEY_IGNORE,
75*55105Storek /*   4 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
76*55105Storek /*   8 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
77*55105Storek /*  12 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
78*55105Storek /*  16 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
79*55105Storek /*  20 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
80*55105Storek /*  24 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
81*55105Storek /*  28 */	KEY_IGNORE,	'\033',		'1',		'2',
82*55105Storek /*  32 */	'3',		'4',		'5',		'6',
83*55105Storek /*  36 */	'7',		'8',		'9',		'0',
84*55105Storek /*  40 */	'-',		'=',		'`',		'\b',
85*55105Storek /*  44 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
86*55105Storek /*  48 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
87*55105Storek /*  52 */	KEY_IGNORE,	'\t',		'q',		'w',
88*55105Storek /*  56 */	'e',		'r',		't',		'y',
89*55105Storek /*  60 */	'u',		'i',		'o',		'p',
90*55105Storek /*  64 */	'[',		']',		'\177',		KEY_IGNORE,
91*55105Storek /*  68 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
92*55105Storek /*  72 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
93*55105Storek /*  76 */	KEY_CONTROL,	'a',		's',		'd',
94*55105Storek /*  80 */	'f',		'g',		'h',		'j',
95*55105Storek /*  84 */	'k',		'l',		';',		'\'',
96*55105Storek /*  88 */	'\\',		'\r',		KEY_IGNORE,	KEY_IGNORE,
97*55105Storek /*  92 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
98*55105Storek /*  96 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_LSHIFT,
99*55105Storek /* 100 */	'z',		'x',		'c',		'v',
100*55105Storek /* 104 */	'b',		'n',		'm',		',',
101*55105Storek /* 108 */	'.',		'/',		KEY_RSHIFT,	'\n',
102*55105Storek /* 112 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
103*55105Storek /* 116 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_CAPSLOCK,
104*55105Storek /* 120 */	KEY_IGNORE,	' ',		KEY_IGNORE,	KEY_IGNORE,
105*55105Storek /* 124 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_ALLUP,
106*55105Storek };
107*55105Storek 
108*55105Storek static const u_char kbd_shifted[] = {
109*55105Storek /*   0 */	KEY_IGNORE,	KEY_L1,		KEY_IGNORE,	KEY_IGNORE,
110*55105Storek /*   4 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
111*55105Storek /*   8 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
112*55105Storek /*  12 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
113*55105Storek /*  16 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
114*55105Storek /*  20 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
115*55105Storek /*  24 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
116*55105Storek /*  28 */	KEY_IGNORE,	'\033',		'!',		'@',
117*55105Storek /*  32 */	'#',		'$',		'%',		'^',
118*55105Storek /*  36 */	'&',		'*',		'(',		')',
119*55105Storek /*  40 */	'_',		'+',		'~',		'\b',
120*55105Storek /*  44 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
121*55105Storek /*  48 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
122*55105Storek /*  52 */	KEY_IGNORE,	'\t',		'Q',		'W',
123*55105Storek /*  56 */	'E',		'R',		'T',		'Y',
124*55105Storek /*  60 */	'U',		'I',		'O',		'P',
125*55105Storek /*  64 */	'{',		'}',		'\177',		KEY_IGNORE,
126*55105Storek /*  68 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
127*55105Storek /*  72 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
128*55105Storek /*  76 */	KEY_CONTROL,	'A',		'S',		'D',
129*55105Storek /*  80 */	'F',		'G',		'H',		'J',
130*55105Storek /*  84 */	'K',		'L',		':',		'"',
131*55105Storek /*  88 */	'|',		'\r',		KEY_IGNORE,	KEY_IGNORE,
132*55105Storek /*  92 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
133*55105Storek /*  96 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_LSHIFT,
134*55105Storek /* 100 */	'Z',		'X',		'C',		'V',
135*55105Storek /* 104 */	'B',		'N',		'M',		'<',
136*55105Storek /* 108 */	'>',		'?',		KEY_RSHIFT,	'\n',
137*55105Storek /* 112 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,
138*55105Storek /* 116 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_CAPSLOCK,
139*55105Storek /* 120 */	KEY_IGNORE,	' ',		KEY_IGNORE,	KEY_IGNORE,
140*55105Storek /* 124 */	KEY_IGNORE,	KEY_IGNORE,	KEY_IGNORE,	KEY_ALLUP,
141*55105Storek };
142*55105Storek 
143*55105Storek /*
144*55105Storek  * We need to remember the state of the keyboard's shift and control
145*55105Storek  * keys, and we need a per-type translation table.
146*55105Storek  */
147*55105Storek struct kbd_state {
148*55105Storek 	const u_char *kbd_unshifted;	/* unshifted keys */
149*55105Storek 	const u_char *kbd_shifted;	/* shifted keys */
150*55105Storek 	const u_char *kbd_cur;	/* current keys (either of the preceding) */
151*55105Storek 	union {
152*55105Storek 		char	c[2];	/* left and right shift keys */
153*55105Storek 		short	s;	/* true => either shift key */
154*55105Storek 	} kbd_shift;
155*55105Storek #define	kbd_lshift	kbd_shift.c[0]
156*55105Storek #define	kbd_rshift	kbd_shift.c[1]
157*55105Storek #define	kbd_anyshift	kbd_shift.s
158*55105Storek 	char	kbd_control;	/* true => ctrl down */
159*55105Storek 	char	kbd_click;	/* true => keyclick enabled */
160*55105Storek 	char	kbd_takeid;	/* take next byte as ID */
161*55105Storek 	u_char	kbd_id;		/* a place to store the ID */
162*55105Storek };
163*55105Storek 
164*55105Storek /*
165*55105Storek  * Keyboard driver state.  The ascii and kbd links go up and down and
166*55105Storek  * we just sit in the middle doing translation.  Note that it is possible
167*55105Storek  * to get just one of the two links, in which case /dev/kbd is unavailable.
168*55105Storek  * The downlink supplies us with `internal' open and close routines which
169*55105Storek  * will enable dataflow across the downlink.  We promise to call open when
170*55105Storek  * we are willing to take keystrokes, and to call close when we are not.
171*55105Storek  * If /dev/kbd is not the console tty input source, we do this whenever
172*55105Storek  * /dev/kbd is in use; otherwise we just leave it open forever.
173*55105Storek  */
174*55105Storek struct kbd_softc {
175*55105Storek 	struct	tty *k_cons;		/* uplink for ASCII data to console */
176*55105Storek 	struct	tty *k_kbd;		/* downlink for output to keyboard */
177*55105Storek 	void	(*k_open) __P((struct tty *));	/* enable dataflow */
178*55105Storek 	void	(*k_close) __P((struct tty *));	/* disable dataflow */
179*55105Storek 	int	k_evmode;		/* set if we should produce events */
180*55105Storek 	struct	kbd_state k_state;	/* ASCII decode state */
181*55105Storek 	struct	evvar k_events;		/* event queue state */
182*55105Storek } kbd_softc;
183*55105Storek 
184*55105Storek /* Prototypes */
185*55105Storek void	kbd_ascii(struct tty *);
186*55105Storek void	kbd_serial(struct tty *, void (*)(), void (*)());
187*55105Storek static	void kbd_getid(void *);
188*55105Storek void	kbd_reset(struct kbd_state *);
189*55105Storek static	int kbd_translate(int, struct kbd_state *);
190*55105Storek void	kbd_rint(int);
191*55105Storek int	kbdopen(dev_t, int, int, struct proc *);
192*55105Storek int	kbdclose(dev_t, int, int, struct proc *);
193*55105Storek int	kbdread(dev_t, struct uio *, int);
194*55105Storek int	kbdwrite(dev_t, struct uio *, int);
195*55105Storek int	kbdioctl(dev_t, int, caddr_t, int, struct proc *);
196*55105Storek int	kbdselect(dev_t, int, struct proc *);
197*55105Storek int	kbd_docmd(int, int);
198*55105Storek 
199*55105Storek /*
200*55105Storek  * Attach the console keyboard ASCII (up-link) interface.
201*55105Storek  * This happens before kbd_serial.
202*55105Storek  */
203*55105Storek void
204*55105Storek kbd_ascii(struct tty *tp)
205*55105Storek {
206*55105Storek 
207*55105Storek 	kbd_softc.k_cons = tp;
208*55105Storek }
209*55105Storek 
210*55105Storek /*
211*55105Storek  * Attach the console keyboard serial (down-link) interface.
212*55105Storek  * We pick up the initial keyboard clock state here as well.
213*55105Storek  */
214*55105Storek void
215*55105Storek kbd_serial(struct tty *tp, void (*iopen)(), void (*iclose)())
216*55105Storek {
217*55105Storek 	register struct kbd_softc *k;
218*55105Storek 	register char *cp;
219*55105Storek 
220*55105Storek 	k = &kbd_softc;
221*55105Storek 	k->k_kbd = tp;
222*55105Storek 	k->k_open = iopen;
223*55105Storek 	k->k_close = iclose;
224*55105Storek 
225*55105Storek 	cp = getpropstring(optionsnode, "keyboard-click?");
226*55105Storek 	if (cp && strcmp(cp, "true") == 0)
227*55105Storek 		k->k_state.kbd_click = 1;
228*55105Storek 
229*55105Storek 	if (k->k_cons) {
230*55105Storek 		/*
231*55105Storek 		 * We supply keys for /dev/console.  Before we can
232*55105Storek 		 * do so, we have to ``open'' the line.  We also need
233*55105Storek 		 * the type, got by sending a RESET down the line ...
234*55105Storek 		 * but clists are not yet set up, so we use a timeout
235*55105Storek 		 * to try constantly until we can get the ID.  (gag)
236*55105Storek 		 */
237*55105Storek 		(*iopen)(tp);		/* never to be closed */
238*55105Storek 		kbd_getid(NULL);
239*55105Storek 	}
240*55105Storek }
241*55105Storek 
242*55105Storek /*
243*55105Storek  * Initial keyboard reset, to obtain ID and thus a translation table.
244*55105Storek  * We have to try again and again until the tty subsystem works.
245*55105Storek  */
246*55105Storek static void
247*55105Storek kbd_getid(void *arg)
248*55105Storek {
249*55105Storek 	register struct kbd_softc *k;
250*55105Storek 	register struct tty *tp;
251*55105Storek 	register int retry;
252*55105Storek 	extern int cold;		/* XXX */
253*55105Storek 
254*55105Storek 	k = &kbd_softc;
255*55105Storek 	if (k->k_state.kbd_cur != NULL)
256*55105Storek 		return;
257*55105Storek 	tp = k->k_kbd;
258*55105Storek 	if (cold || ttyoutput(KBD_CMD_RESET, tp) >= 0)
259*55105Storek 		retry = 1;
260*55105Storek 	else {
261*55105Storek 		(*tp->t_oproc)(tp);
262*55105Storek 		retry = 2 * hz;
263*55105Storek 	}
264*55105Storek 	timeout(kbd_getid, NULL, retry);
265*55105Storek }
266*55105Storek 
267*55105Storek void
268*55105Storek kbd_reset(register struct kbd_state *ks)
269*55105Storek {
270*55105Storek 	/*
271*55105Storek 	 * On first identification, wake up anyone waiting for type
272*55105Storek 	 * and set up the table pointers.
273*55105Storek 	 */
274*55105Storek 	if (ks->kbd_unshifted == NULL) {
275*55105Storek 		wakeup((caddr_t)ks);
276*55105Storek 		ks->kbd_unshifted = kbd_unshifted;
277*55105Storek 		ks->kbd_shifted = kbd_shifted;
278*55105Storek 		ks->kbd_cur = ks->kbd_unshifted;
279*55105Storek 	}
280*55105Storek 
281*55105Storek 	/* Restore keyclick, if necessary */
282*55105Storek 	switch (ks->kbd_id) {
283*55105Storek 
284*55105Storek 	case KB_SUN2:
285*55105Storek 		/* Type 2 keyboards don't support keyclick */
286*55105Storek 		break;
287*55105Storek 
288*55105Storek 	case KB_SUN3:
289*55105Storek 		/* Type 3 keyboards come up with keyclick on */
290*55105Storek 		if (!ks->kbd_click)
291*55105Storek 			(void) kbd_docmd(KBD_CMD_NOCLICK, 0);
292*55105Storek 		break;
293*55105Storek 
294*55105Storek 	case KB_SUN4:
295*55105Storek 		/* Type 4 keyboards come up with keyclick off */
296*55105Storek 		if (ks->kbd_click)
297*55105Storek 			(void) kbd_docmd(KBD_CMD_CLICK, 0);
298*55105Storek 		break;
299*55105Storek 	}
300*55105Storek }
301*55105Storek 
302*55105Storek /*
303*55105Storek  * Turn keyboard up/down codes into ASCII.
304*55105Storek  */
305*55105Storek static int
306*55105Storek kbd_translate(register int c, register struct kbd_state *ks)
307*55105Storek {
308*55105Storek 	register int down;
309*55105Storek 
310*55105Storek 	if (ks->kbd_cur == NULL) {
311*55105Storek 		/*
312*55105Storek 		 * Do not know how to translate yet.
313*55105Storek 		 * We will find out when a RESET comes along.
314*55105Storek 		 */
315*55105Storek 		return (-1);
316*55105Storek 	}
317*55105Storek 	down = !KEY_UP(c);
318*55105Storek 	c = ks->kbd_cur[KEY_CODE(c)];
319*55105Storek 	if (c & KEY_MAGIC) {
320*55105Storek 		switch (c) {
321*55105Storek 
322*55105Storek 		case KEY_LSHIFT:
323*55105Storek 			ks->kbd_lshift = down;
324*55105Storek 			break;
325*55105Storek 
326*55105Storek 		case KEY_RSHIFT:
327*55105Storek 			ks->kbd_rshift = down;
328*55105Storek 			break;
329*55105Storek 
330*55105Storek 		case KEY_ALLUP:
331*55105Storek 			ks->kbd_anyshift = 0;
332*55105Storek 			ks->kbd_control = 0;
333*55105Storek 			break;
334*55105Storek 
335*55105Storek 		case KEY_CONTROL:
336*55105Storek 			ks->kbd_control = down;
337*55105Storek 			/* FALLTHROUGH */
338*55105Storek 
339*55105Storek 		case KEY_IGNORE:
340*55105Storek 			return (-1);
341*55105Storek 
342*55105Storek 		default:
343*55105Storek 			panic("kbd_translate");
344*55105Storek 		}
345*55105Storek 		if (ks->kbd_anyshift)
346*55105Storek 			ks->kbd_cur = ks->kbd_shifted;
347*55105Storek 		else
348*55105Storek 			ks->kbd_cur = ks->kbd_unshifted;
349*55105Storek 		return (-1);
350*55105Storek 	}
351*55105Storek 	if (!down)
352*55105Storek 		return (-1);
353*55105Storek 	if (ks->kbd_control) {
354*55105Storek 		/* control space and unshifted control atsign return null */
355*55105Storek 		if (c == ' ' || c == '2')
356*55105Storek 			return (0);
357*55105Storek 		/* unshifted control hat */
358*55105Storek 		if (c == '6')
359*55105Storek 			return ('^' & 0x1f);
360*55105Storek 		/* standard controls */
361*55105Storek 		if (c >= '@' && c < 0x7f)
362*55105Storek 			return (c & 0x1f);
363*55105Storek 	}
364*55105Storek 	return (c);
365*55105Storek }
366*55105Storek 
367*55105Storek void
368*55105Storek kbd_rint(register int c)
369*55105Storek {
370*55105Storek 	register struct kbd_softc *k = &kbd_softc;
371*55105Storek 	register struct firm_event *fe;
372*55105Storek 	register int put;
373*55105Storek 
374*55105Storek 	/*
375*55105Storek 	 * Reset keyboard after serial port overrun, so we can resynch.
376*55105Storek 	 * The printf below should be shortened and/or replaced with a
377*55105Storek 	 * call to log() after this is tested (and how will we test it?!).
378*55105Storek 	 */
379*55105Storek 	if (c & (TTY_FE|TTY_PE)) {
380*55105Storek 		printf("keyboard input parity or framing error (0x%x)\n", c);
381*55105Storek 		(void) ttyoutput(KBD_CMD_RESET, k->k_kbd);
382*55105Storek 		(*k->k_kbd->t_oproc)(k->k_kbd);
383*55105Storek 		return;
384*55105Storek 	}
385*55105Storek 
386*55105Storek 	/* Read the keyboard id if we read a KBD_RESET last time */
387*55105Storek 	if (k->k_state.kbd_takeid) {
388*55105Storek 		k->k_state.kbd_takeid = 0;
389*55105Storek 		k->k_state.kbd_id = c;
390*55105Storek 		kbd_reset(&k->k_state);
391*55105Storek 		return;
392*55105Storek 	}
393*55105Storek 
394*55105Storek 	/* If we have been reset, setup to grab the keyboard id next time */
395*55105Storek 	if (c == KBD_RESET) {
396*55105Storek 		k->k_state.kbd_takeid = 1;
397*55105Storek 		return;
398*55105Storek 	}
399*55105Storek 
400*55105Storek 	/*
401*55105Storek 	 * If /dev/kbd is not connected in event mode, but we are sending
402*55105Storek 	 * data to /dev/console, translate and send upstream.  Note that
403*55105Storek 	 * we will get this while opening /dev/kbd if it is not already
404*55105Storek 	 * open and we do not know its type.
405*55105Storek 	 */
406*55105Storek 	if (!k->k_evmode) {
407*55105Storek 		c = kbd_translate(c, &k->k_state);
408*55105Storek 		if (c >= 0 && k->k_cons != NULL)
409*55105Storek 			ttyinput(c, k->k_cons);
410*55105Storek 		return;
411*55105Storek 	}
412*55105Storek 
413*55105Storek 	/*
414*55105Storek 	 * IDLEs confuse the MIT X11R4 server badly, so we must drop them.
415*55105Storek 	 * This is bad as it means the server will not automatically resync
416*55105Storek 	 * on all-up IDLEs, but I did not drop them before, and the server
417*55105Storek 	 * goes crazy when it comes time to blank the screen....
418*55105Storek 	 */
419*55105Storek 	if (c == KBD_IDLE)
420*55105Storek 		return;
421*55105Storek 
422*55105Storek 	/*
423*55105Storek 	 * Keyboard is generating events.  Turn this keystroke into an
424*55105Storek 	 * event and put it in the queue.  If the queue is full, the
425*55105Storek 	 * keystroke is lost (sorry!).
426*55105Storek 	 */
427*55105Storek 	put = k->k_events.ev_put;
428*55105Storek 	fe = &k->k_events.ev_q[put];
429*55105Storek 	put = (put + 1) % EV_QSIZE;
430*55105Storek 	if (put == k->k_events.ev_get) {
431*55105Storek 		log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */
432*55105Storek 		return;
433*55105Storek 	}
434*55105Storek 	fe->id = KEY_CODE(c);
435*55105Storek 	fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
436*55105Storek 	fe->time = time;
437*55105Storek 	k->k_events.ev_put = put;
438*55105Storek 	EV_WAKEUP(&k->k_events);
439*55105Storek }
440*55105Storek 
441*55105Storek int
442*55105Storek kbdopen(dev_t dev, int flags, int mode, struct proc *p)
443*55105Storek {
444*55105Storek 	int s, error;
445*55105Storek 
446*55105Storek 	if (kbd_softc.k_events.ev_io)
447*55105Storek 		return (EBUSY);
448*55105Storek 	kbd_softc.k_events.ev_io = p;
449*55105Storek 	/*
450*55105Storek 	 * If no console keyboard, tell the device to open up, maybe for
451*55105Storek 	 * the first time.  Then make sure we know what kind of keyboard
452*55105Storek 	 * it is.
453*55105Storek 	 */
454*55105Storek 	if (kbd_softc.k_cons == NULL)
455*55105Storek 		(*kbd_softc.k_open)(kbd_softc.k_kbd);
456*55105Storek 	error = 0;
457*55105Storek 	s = spltty();
458*55105Storek 	if (kbd_softc.k_state.kbd_cur == NULL) {
459*55105Storek 		(void) ttyoutput(KBD_CMD_RESET, kbd_softc.k_kbd);
460*55105Storek 		error = tsleep((caddr_t)&kbd_softc.k_state, PZERO | PCATCH,
461*55105Storek 		    devopn, hz);
462*55105Storek 		if (error == EWOULDBLOCK)	/* no response */
463*55105Storek 			error = ENXIO;
464*55105Storek 	}
465*55105Storek 	splx(s);
466*55105Storek 	if (error) {
467*55105Storek 		kbd_softc.k_events.ev_io = NULL;
468*55105Storek 		return (error);
469*55105Storek 	}
470*55105Storek 	ev_init(&kbd_softc.k_events);
471*55105Storek 	return (0);
472*55105Storek }
473*55105Storek 
474*55105Storek int
475*55105Storek kbdclose(dev_t dev, int flags, int mode, struct proc *p)
476*55105Storek {
477*55105Storek 
478*55105Storek 	/*
479*55105Storek 	 * Turn off event mode, dump the queue, and close the keyboard
480*55105Storek 	 * unless it is supplying console input.
481*55105Storek 	 */
482*55105Storek 	kbd_softc.k_evmode = 0;
483*55105Storek 	ev_fini(&kbd_softc.k_events);
484*55105Storek 	if (kbd_softc.k_cons == NULL)
485*55105Storek 		(*kbd_softc.k_close)(kbd_softc.k_kbd);
486*55105Storek 	kbd_softc.k_events.ev_io = NULL;
487*55105Storek 	return (0);
488*55105Storek }
489*55105Storek 
490*55105Storek int
491*55105Storek kbdread(dev_t dev, struct uio *uio, int flags)
492*55105Storek {
493*55105Storek 
494*55105Storek 	return (ev_read(&kbd_softc.k_events, uio, flags));
495*55105Storek }
496*55105Storek 
497*55105Storek /* this routine should not exist, but is convenient to write here for now */
498*55105Storek int
499*55105Storek kbdwrite(dev_t dev, struct uio *uio, int flags)
500*55105Storek {
501*55105Storek 
502*55105Storek 	return (EOPNOTSUPP);
503*55105Storek }
504*55105Storek 
505*55105Storek int
506*55105Storek kbdioctl(dev_t dev, int cmd, register caddr_t data, int flag, struct proc *p)
507*55105Storek {
508*55105Storek 	register struct kbd_softc *k = &kbd_softc;
509*55105Storek 
510*55105Storek 	switch (cmd) {
511*55105Storek 
512*55105Storek 	case KIOCTRANS:
513*55105Storek 		if (*(int *)data == TR_UNTRANS_EVENT)
514*55105Storek 			return (0);
515*55105Storek 		break;
516*55105Storek 
517*55105Storek 	case KIOCGTRANS:
518*55105Storek 		/*
519*55105Storek 		 * Get translation mode
520*55105Storek 		 */
521*55105Storek 		*(int *)data = TR_UNTRANS_EVENT;
522*55105Storek 		return (0);
523*55105Storek 
524*55105Storek 	case KIOCGETKEY:
525*55105Storek 		if (((struct kiockey *)data)->kio_station == 118) {
526*55105Storek 			/*
527*55105Storek 			 * This is X11 asking if a type 3 keyboard is
528*55105Storek 			 * really a type 3 keyboard.  Say yes.
529*55105Storek 			 */
530*55105Storek 			((struct kiockey *)data)->kio_entry = HOLE;
531*55105Storek 			return (0);
532*55105Storek 		}
533*55105Storek 		break;
534*55105Storek 
535*55105Storek 	case KIOCCMD:
536*55105Storek 		/*
537*55105Storek 		 * ``unimplemented commands are ignored'' (blech)
538*55105Storek 		 * so cannot check return value from kbd_docmd
539*55105Storek 		 */
540*55105Storek #ifdef notyet
541*55105Storek 		while (kbd_docmd(*(int *)data, 1) == ENOSPC) /*ERESTART?*/
542*55105Storek 			(void) sleep((caddr_t)&lbolt, TTOPRI);
543*55105Storek #else
544*55105Storek 		(void) kbd_docmd(*(int *)data, 1);
545*55105Storek #endif
546*55105Storek 		return (0);
547*55105Storek 
548*55105Storek 	case KIOCTYPE:
549*55105Storek 		*(int *)data = k->k_state.kbd_id;
550*55105Storek 		return (0);
551*55105Storek 
552*55105Storek 	case KIOCSDIRECT:
553*55105Storek 		k->k_evmode = *(int *)data;
554*55105Storek 		return (0);
555*55105Storek 
556*55105Storek 	case FIONBIO:		/* we will remove this someday (soon???) */
557*55105Storek 		return (0);
558*55105Storek 
559*55105Storek 	case FIOASYNC:
560*55105Storek 		k->k_events.ev_async = *(int *)data != 0;
561*55105Storek 		return (0);
562*55105Storek 
563*55105Storek 	case TIOCSPGRP:
564*55105Storek 		if (*(int *)data != k->k_events.ev_io->p_pgid)
565*55105Storek 			return (EPERM);
566*55105Storek 		return (0);
567*55105Storek 
568*55105Storek 	default:
569*55105Storek 		return (ENOTTY);
570*55105Storek 	}
571*55105Storek 
572*55105Storek 	/*
573*55105Storek 	 * We identified the ioctl, but we do not handle it.
574*55105Storek 	 */
575*55105Storek 	return (EOPNOTSUPP);		/* misuse, but what the heck */
576*55105Storek }
577*55105Storek 
578*55105Storek int
579*55105Storek kbdselect(dev_t dev, int rw, struct proc *p)
580*55105Storek {
581*55105Storek 
582*55105Storek 	return (ev_select(&kbd_softc.k_events, rw, p));
583*55105Storek }
584*55105Storek 
585*55105Storek /*
586*55105Storek  * Execute a keyboard command; return 0 on success.
587*55105Storek  * If `isuser', force a small delay before output if output queue
588*55105Storek  * is flooding.  (The keyboard runs at 1200 baud, or 120 cps.)
589*55105Storek  */
590*55105Storek int
591*55105Storek kbd_docmd(int cmd, int isuser)
592*55105Storek {
593*55105Storek 	register struct tty *tp = kbd_softc.k_kbd;
594*55105Storek 	register struct kbd_softc *k = &kbd_softc;
595*55105Storek 	int s;
596*55105Storek 
597*55105Storek 	if (tp == NULL)
598*55105Storek 		return (ENXIO);		/* ??? */
599*55105Storek 	switch (cmd) {
600*55105Storek 
601*55105Storek 	case KBD_CMD_BELL:
602*55105Storek 	case KBD_CMD_NOBELL:
603*55105Storek 		/* Supported by type 2, 3, and 4 keyboards */
604*55105Storek 		break;
605*55105Storek 
606*55105Storek 	case KBD_CMD_CLICK:
607*55105Storek 		/* Unsupported by type 2 keyboards */
608*55105Storek 		if (k->k_state.kbd_id != KB_SUN2) {
609*55105Storek 			k->k_state.kbd_click = 1;
610*55105Storek 			break;
611*55105Storek 		}
612*55105Storek 		return (EINVAL);
613*55105Storek 
614*55105Storek 	case KBD_CMD_NOCLICK:
615*55105Storek 		/* Unsupported by type 2 keyboards */
616*55105Storek 		if (k->k_state.kbd_id != KB_SUN2) {
617*55105Storek 			k->k_state.kbd_click = 0;
618*55105Storek 			break;
619*55105Storek 		}
620*55105Storek 		return (EINVAL);
621*55105Storek 
622*55105Storek 	default:
623*55105Storek 		return (EINVAL);	/* ENOTTY? EOPNOTSUPP? */
624*55105Storek 	}
625*55105Storek 
626*55105Storek 	if (isuser) {
627*55105Storek 		s = spltty();
628*55105Storek 		if (tp->t_outq.c_cc > 120)
629*55105Storek 			(void) tsleep((caddr_t)&lbolt, TTIPRI,
630*55105Storek 			    ttyout, 0);
631*55105Storek 		splx(s);
632*55105Storek 	}
633*55105Storek 	if (ttyoutput(cmd, tp) >= 0)
634*55105Storek 		return (ENOSPC);	/* ERESTART? */
635*55105Storek 	(*tp->t_oproc)(tp);
636*55105Storek 	return (0);
637*55105Storek }
638