xref: /netbsd-src/sys/dev/sun/kbd.c (revision d710132b4b8ce7f7cccaaf660cb16aa16b4077a0)
1 /*	$NetBSD: kbd.c,v 1.35 2002/10/26 19:11:13 martin Exp $	*/
2 
3 /*
4  * Copyright (c) 1992, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This software was developed by the Computer Systems Engineering group
8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9  * contributed to Berkeley.
10  *
11  * All advertising materials mentioning features or use of this software
12  * must display the following acknowledgement:
13  *	This product includes software developed by the University of
14  *	California, Lawrence Berkeley Laboratory.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  * 3. All advertising materials mentioning features or use of this software
25  *    must display the following acknowledgement:
26  *	This product includes software developed by the University of
27  *	California, Berkeley and its contributors.
28  * 4. Neither the name of the University nor the names of its contributors
29  *    may be used to endorse or promote products derived from this software
30  *    without specific prior written permission.
31  *
32  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42  * SUCH DAMAGE.
43  *
44  *	@(#)kbd.c	8.2 (Berkeley) 10/30/93
45  */
46 
47 /*
48  * Keyboard driver (/dev/kbd -- note that we do not have minor numbers
49  * [yet?]).  Translates incoming bytes to ASCII or to `firm_events' and
50  * passes them up to the appropriate reader.
51  */
52 
53 #include <sys/cdefs.h>
54 __KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.35 2002/10/26 19:11:13 martin Exp $");
55 
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/conf.h>
59 #include <sys/device.h>
60 #include <sys/ioctl.h>
61 #include <sys/kernel.h>
62 #include <sys/proc.h>
63 #include <sys/malloc.h>
64 #include <sys/signal.h>
65 #include <sys/signalvar.h>
66 #include <sys/time.h>
67 #include <sys/syslog.h>
68 #include <sys/select.h>
69 #include <sys/poll.h>
70 #include <sys/file.h>
71 
72 #include <dev/wscons/wsksymdef.h>
73 
74 #include <dev/sun/kbd_reg.h>
75 #include <dev/sun/kbio.h>
76 #include <dev/sun/vuid_event.h>
77 #include <dev/sun/event_var.h>
78 #include <dev/sun/kbd_xlate.h>
79 #include <dev/sun/kbdvar.h>
80 
81 #include "locators.h"
82 
83 extern struct cfdriver kbd_cd;
84 
85 dev_type_open(kbdopen);
86 dev_type_close(kbdclose);
87 dev_type_read(kbdread);
88 dev_type_ioctl(kbdioctl);
89 dev_type_poll(kbdpoll);
90 dev_type_kqfilter(kbdkqfilter);
91 
92 const struct cdevsw kbd_cdevsw = {
93 	kbdopen, kbdclose, kbdread, nowrite, kbdioctl,
94 	nostop, notty, kbdpoll, nommap, kbdkqfilter
95 };
96 
97 #if NWSKBD > 0
98 int	wssunkbd_enable __P((void *, int));
99 void	wssunkbd_set_leds __P((void *, int));
100 int	wssunkbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
101 
102 void    sunkbd_wskbd_cngetc __P((void *, u_int *, int *));
103 void    sunkbd_wskbd_cnpollc __P((void *, int));
104 void    sunkbd_wskbd_cnbell __P((void *, u_int, u_int, u_int));
105 static void sunkbd_bell_off(void *v);
106 
107 const struct wskbd_accessops sunkbd_wskbd_accessops = {
108 	wssunkbd_enable,
109 	wssunkbd_set_leds,
110 	wssunkbd_ioctl,
111 };
112 
113 extern const struct wscons_keydesc wssun_keydesctab[];
114 const struct wskbd_mapdata sunkbd_wskbd_keymapdata = {
115 	wssun_keydesctab,
116 #ifdef SUNKBD_LAYOUT
117 	SUNKBD_LAYOUT,
118 #else
119 	KB_US,
120 #endif
121 };
122 
123 const struct wskbd_consops sunkbd_wskbd_consops = {
124         sunkbd_wskbd_cngetc,
125         sunkbd_wskbd_cnpollc,
126         sunkbd_wskbd_cnbell,
127 };
128 
129 void kbd_wskbd_attach(struct kbd_softc *k, int isconsole);
130 #endif
131 
132 /* ioctl helpers */
133 static int kbd_iockeymap(struct kbd_state *ks,
134 			 u_long cmd, struct kiockeymap *kio);
135 #ifdef KIOCGETKEY
136 static int kbd_oldkeymap(struct kbd_state *ks,
137 			 u_long cmd, struct okiockey *okio);
138 #endif
139 
140 
141 /* callbacks for console driver */
142 static int kbd_cc_open(struct cons_channel *);
143 static int kbd_cc_close(struct cons_channel *);
144 
145 /* console input */
146 static void	kbd_input_console(struct kbd_softc *, int);
147 static void	kbd_repeat(void *);
148 static int	kbd_input_keysym(struct kbd_softc *, int);
149 static void	kbd_input_string(struct kbd_softc *, char *);
150 static void	kbd_input_funckey(struct kbd_softc *, int);
151 static void	kbd_update_leds(struct kbd_softc *);
152 
153 #if NWSKBD > 0
154 static void	kbd_input_wskbd(struct kbd_softc *, int);
155 #endif
156 
157 /* firm events input */
158 static void	kbd_input_event(struct kbd_softc *, int);
159 
160 
161 
162 /****************************************************************
163  *  Entry points for /dev/kbd
164  *  (open,close,read,write,...)
165  ****************************************************************/
166 
167 /*
168  * Open:
169  * Check exclusion, open actual device (_iopen),
170  * setup event channel, clear ASCII repeat stuff.
171  */
172 int
173 kbdopen(dev, flags, mode, p)
174 	dev_t dev;
175 	int flags, mode;
176 	struct proc *p;
177 {
178 	struct kbd_softc *k;
179 	int error, unit;
180 
181 	/* locate device */
182 	unit = minor(dev);
183 	if (unit >= kbd_cd.cd_ndevs)
184 		return (ENXIO);
185 	k = kbd_cd.cd_devs[unit];
186 	if (k == NULL)
187 		return (ENXIO);
188 
189 	/*
190 	 * NB: wscons support: while we can track if wskbd has called
191 	 * enable(), we can't tell if that's for console input or for
192 	 * events input, so we should probably just let the open to
193 	 * always succeed regardless (e.g. Xsun opening /dev/kbd).
194 	 */
195 
196 	/* exclusive open required for /dev/kbd */
197 	if (k->k_events.ev_io)
198 		return (EBUSY);
199 	k->k_events.ev_io = p;
200 
201 	/* stop pending autorepeat of console input */
202 	if (k->k_repeating) {
203 		k->k_repeating = 0;
204 		callout_stop(&k->k_repeat_ch);
205 	}
206 
207 	/* open actual underlying device */
208 	if (k->k_ops != NULL && k->k_ops->open != NULL)
209 		if ((error = (*k->k_ops->open)(k)) != 0) {
210 			k->k_events.ev_io = NULL;
211 			return (error);
212 		}
213 
214 	ev_init(&k->k_events);
215 	k->k_evmode = 0;	/* XXX: OK? */
216 
217 	return (0);
218 }
219 
220 
221 /*
222  * Close:
223  * Turn off event mode, dump the queue, and close the keyboard
224  * unless it is supplying console input.
225  */
226 int
227 kbdclose(dev, flags, mode, p)
228 	dev_t dev;
229 	int flags, mode;
230 	struct proc *p;
231 {
232 	struct kbd_softc *k;
233 
234 	k = kbd_cd.cd_devs[minor(dev)];
235 	k->k_evmode = 0;
236 	ev_fini(&k->k_events);
237 	k->k_events.ev_io = NULL;
238 
239 	if (k->k_ops != NULL && k->k_ops->close != NULL) {
240 		int error;
241 		if ((error = (*k->k_ops->close)(k)) != 0)
242 			return (error);
243 	}
244 	return (0);
245 }
246 
247 
248 int
249 kbdread(dev, uio, flags)
250 	dev_t dev;
251 	struct uio *uio;
252 	int flags;
253 {
254 	struct kbd_softc *k;
255 
256 	k = kbd_cd.cd_devs[minor(dev)];
257 	return (ev_read(&k->k_events, uio, flags));
258 }
259 
260 
261 int
262 kbdpoll(dev, events, p)
263 	dev_t dev;
264 	int events;
265 	struct proc *p;
266 {
267 	struct kbd_softc *k;
268 
269 	k = kbd_cd.cd_devs[minor(dev)];
270 	return (ev_poll(&k->k_events, events, p));
271 }
272 
273 int
274 kbdkqfilter(dev, kn)
275 	dev_t dev;
276 	struct knote *kn;
277 {
278 	struct kbd_softc *k;
279 
280 	k = kbd_cd.cd_devs[minor(dev)];
281 	return (ev_kqfilter(&k->k_events, kn));
282 }
283 
284 int
285 kbdioctl(dev, cmd, data, flag, p)
286 	dev_t dev;
287 	u_long cmd;
288 	caddr_t data;
289 	int flag;
290 	struct proc *p;
291 {
292 	struct kbd_softc *k;
293 	struct kbd_state *ks;
294 	int error = 0;
295 
296 	k = kbd_cd.cd_devs[minor(dev)];
297 	ks = &k->k_state;
298 
299 	switch (cmd) {
300 
301 	case KIOCTRANS: 	/* Set translation mode */
302 		/* We only support "raw" mode on /dev/kbd */
303 		if (*(int *)data != TR_UNTRANS_EVENT)
304 			error = EINVAL;
305 		break;
306 
307 	case KIOCGTRANS:	/* Get translation mode */
308 		/* We only support "raw" mode on /dev/kbd */
309 		*(int *)data = TR_UNTRANS_EVENT;
310 		break;
311 
312 #ifdef KIOCGETKEY
313 	case KIOCGETKEY:	/* Get keymap entry (old format) */
314 		error = kbd_oldkeymap(ks, cmd, (struct okiockey *)data);
315 		break;
316 #endif /* KIOCGETKEY */
317 
318 	case KIOCSKEY:  	/* Set keymap entry */
319 		/* FALLTHROUGH */
320 	case KIOCGKEY:  	/* Get keymap entry */
321 		error = kbd_iockeymap(ks, cmd, (struct kiockeymap *)data);
322 		break;
323 
324 	case KIOCCMD:		/* Send a command to the keyboard */
325 		/* pass it to the middle layer */
326 		if (k->k_ops != NULL && k->k_ops->docmd != NULL)
327 			error = (*k->k_ops->docmd)(k, *(int *)data, 1);
328 		break;
329 
330 	case KIOCTYPE:		/* Get keyboard type */
331 		*(int *)data = ks->kbd_id;
332 		break;
333 
334 	case KIOCSDIRECT:	/* Where to send input */
335 		k->k_evmode = *(int *)data;
336 		break;
337 
338 	case KIOCLAYOUT:	/* Get keyboard layout */
339 		*(int *)data = ks->kbd_layout;
340 		break;
341 
342 	case KIOCSLED:		/* Set keyboard LEDs */
343 		/* pass the request to the middle layer */
344 		if (k->k_ops != NULL && k->k_ops->setleds != NULL)
345 			error = (*k->k_ops->setleds)(k, *(char *)data, 1);
346 		break;
347 
348 	case KIOCGLED:		/* Get keyboard LEDs */
349 		*(char *)data = ks->kbd_leds;
350 		break;
351 
352 	case FIONBIO:		/* we will remove this someday (soon???) */
353 		break;
354 
355 	case FIOASYNC:
356 		k->k_events.ev_async = (*(int *)data != 0);
357 		break;
358 
359 	case TIOCSPGRP:
360 		if (*(int *)data != k->k_events.ev_io->p_pgid)
361 			error = EPERM;
362 		break;
363 
364 	default:
365 		error = ENOTTY;
366 		break;
367 	}
368 
369 	return (error);
370 }
371 
372 
373 /****************************************************************
374  * ioctl helpers
375  ****************************************************************/
376 
377 /*
378  * Get/Set keymap entry
379  */
380 static int
381 kbd_iockeymap(ks, cmd, kio)
382 	struct kbd_state *ks;
383 	u_long cmd;
384 	struct kiockeymap *kio;
385 {
386 	u_short *km;
387 	u_int station;
388 
389 	switch (kio->kio_tablemask) {
390 	case KIOC_NOMASK:
391 		km = ks->kbd_k.k_normal;
392 		break;
393 	case KIOC_SHIFTMASK:
394 		km = ks->kbd_k.k_shifted;
395 		break;
396 	case KIOC_CTRLMASK:
397 		km = ks->kbd_k.k_control;
398 		break;
399 	case KIOC_UPMASK:
400 		km = ks->kbd_k.k_release;
401 		break;
402 	default:
403 		/* Silently ignore unsupported masks */
404 		return (0);
405 	}
406 
407 	/* Range-check the table position. */
408 	station = kio->kio_station;
409 	if (station >= KEYMAP_SIZE)
410 		return (EINVAL);
411 
412 	switch (cmd) {
413 
414 	case KIOCGKEY:	/* Get keymap entry */
415 		kio->kio_entry = km[station];
416 		break;
417 
418 	case KIOCSKEY:	/* Set keymap entry */
419 		km[station] = kio->kio_entry;
420 		break;
421 
422 	default:
423 		return(ENOTTY);
424 	}
425 	return (0);
426 }
427 
428 
429 #ifdef KIOCGETKEY
430 /*
431  * Get/Set keymap entry,
432  * old format (compatibility)
433  */
434 int
435 kbd_oldkeymap(ks, cmd, kio)
436 	struct kbd_state *ks;
437 	u_long cmd;
438 	struct okiockey *kio;
439 {
440 	int error = 0;
441 
442 	switch (cmd) {
443 
444 	case KIOCGETKEY:
445 		if (kio->kio_station == 118) {
446 			/*
447 			 * This is X11 asking if a type 3 keyboard is
448 			 * really a type 3 keyboard.  Say yes, it is,
449 			 * by reporting key station 118 as a "hole".
450 			 * Note old (SunOS 3.5) definition of HOLE!
451 			 */
452 			kio->kio_entry = 0xA2;
453 			break;
454 		}
455 		/* fall through */
456 
457 	default:
458 		error = ENOTTY;
459 		break;
460 	}
461 
462 	return (error);
463 }
464 #endif /* KIOCGETKEY */
465 
466 
467 
468 /****************************************************************
469  *  Keyboard input - called by middle layer at spltty().
470  ****************************************************************/
471 
472 void
473 kbd_input(k, code)
474 	struct kbd_softc *k;
475 	int code;
476 {
477 	if (k->k_evmode) {
478 
479 #ifdef KBD_IDLE_EVENTS
480 		/*
481 		 * XXX: is this still true?
482 		 * IDLEs confuse the MIT X11R4 server badly, so we must drop them.
483 		 * This is bad as it means the server will not automatically resync
484 		 * on all-up IDLEs, but I did not drop them before, and the server
485 		 * goes crazy when it comes time to blank the screen....
486 		 */
487 		if (code == KBD_IDLE)
488 			return;
489 #endif
490 
491 		/*
492 		 * Keyboard is generating firm events.  Turn this keystroke
493 		 * into an event and put it in the queue.
494 		 */
495 		kbd_input_event(k, code);
496 		return;
497 	}
498 
499 #if NWSKBD > 0
500 	if (k->k_wskbd != NULL && k->k_wsenabled) {
501 		/*
502 		 * We are using wskbd input mode, pass the event up.
503 		 */
504 		kbd_input_wskbd(k, code);
505 		return;
506 	}
507 #endif
508 
509 	/*
510 	 * If /dev/kbd is not connected in event mode, or wskbd mode,
511 	 * translate and send upstream (to console).
512 	 */
513 	kbd_input_console(k, code);
514 }
515 
516 
517 
518 /****************************************************************
519  *  Open/close routines called upon opening /dev/console
520  *  if we serve console input.
521  ****************************************************************/
522 
523 struct cons_channel *
524 kbd_cc_alloc(k)
525 	struct kbd_softc *k;
526 {
527 	struct cons_channel *cc;
528 
529 	if ((cc = malloc(sizeof *cc, M_DEVBUF, M_NOWAIT)) == NULL)
530 		return (NULL);
531 
532 	/* our callbacks for the console driver */
533 	cc->cc_dev = k;
534 	cc->cc_iopen = kbd_cc_open;
535 	cc->cc_iclose = kbd_cc_close;
536 
537 	/* will be provided by the console driver so that we can feed input */
538 	cc->cc_upstream = NULL;
539 
540 	/*
541 	 * TODO: clean up cons_attach_input() vs kd_attach_input() in
542 	 * lower layers and move that code here.
543 	 */
544 
545 	k->k_cc = cc;
546 	return (cc);
547 }
548 
549 
550 static int
551 kbd_cc_open(cc)
552 	struct cons_channel *cc;
553 {
554 	struct kbd_softc *k;
555 	int ret;
556 
557 	if (cc == NULL)
558 		return (0);
559 
560 	k = (struct kbd_softc *)cc->cc_dev;
561 	if (k == NULL)
562 		return (0);
563 
564 	if (k->k_ops != NULL && k->k_ops->open != NULL)
565 		ret = (*k->k_ops->open)(k);
566 	else
567 		ret = 0;
568 
569 	/* XXX: verify that callout is not active? */
570 	k->k_repeat_start = hz/2;
571 	k->k_repeat_step = hz/20;
572 	callout_init(&k->k_repeat_ch);
573 
574 	return (ret);
575 }
576 
577 
578 static int
579 kbd_cc_close(cc)
580 	struct cons_channel *cc;
581 {
582 	struct kbd_softc *k;
583 	int ret;
584 
585 	if (cc == NULL)
586 		return (0);
587 
588 	k = (struct kbd_softc *)cc->cc_dev;
589 	if (k == NULL)
590 		return (0);
591 
592 	if (k->k_ops != NULL && k->k_ops->close != NULL)
593 		ret = (*k->k_ops->close)(k);
594 	else
595 		ret = 0;
596 
597 	/* stop any pending auto-repeat */
598 	if (k->k_repeating) {
599 		k->k_repeating = 0;
600 		callout_stop(&k->k_repeat_ch);
601 	}
602 
603 	return (ret);
604 }
605 
606 
607 
608 /****************************************************************
609  *  Console input - called by middle layer at spltty().
610  ****************************************************************/
611 
612 static void
613 kbd_input_console(k, code)
614 	struct kbd_softc *k;
615 	int code;
616 {
617 	struct kbd_state *ks= &k->k_state;
618 	int keysym;
619 
620 	/* any input stops auto-repeat (i.e. key release) */
621 	if (k->k_repeating) {
622 		k->k_repeating = 0;
623 		callout_stop(&k->k_repeat_ch);
624 	}
625 
626 	keysym = kbd_code_to_keysym(ks, code);
627 
628 	/* pass to console */
629 	if (kbd_input_keysym(k, keysym)) {
630 		log(LOG_WARNING, "%s: code=0x%x with mod=0x%x"
631 		    " produced unexpected keysym 0x%x\n",
632 		    k->k_dev.dv_xname,
633 		    code, ks->kbd_modbits, keysym);
634 		return;		/* no point in auto-repeat here */
635 	}
636 
637 	if (KEYSYM_NOREPEAT(keysym))
638 		return;
639 
640 	/* setup for auto-repeat after initial delay */
641 	k->k_repeating = 1;
642 	k->k_repeatsym = keysym;
643 	callout_reset(&k->k_repeat_ch, k->k_repeat_start,
644 		      kbd_repeat, k);
645 }
646 
647 
648 /*
649  * This is the autorepeat callout function scheduled by kbd_input() above.
650  * Called at splsoftclock().
651  */
652 static void
653 kbd_repeat(arg)
654 	void *arg;
655 {
656 	struct kbd_softc *k = (struct kbd_softc *)arg;
657 	int s;
658 
659 	s = spltty();
660 	if (k->k_repeating && k->k_repeatsym >= 0) {
661 		/* feed typematic keysym to the console */
662 		(void)kbd_input_keysym(k, k->k_repeatsym);
663 
664 		/* reschedule next repeat */
665 		callout_reset(&k->k_repeat_ch, k->k_repeat_step,
666 			      kbd_repeat, k);
667 	}
668 	splx(s);
669 }
670 
671 
672 
673 /*
674  * Supply keysym as console input.  Convert keysym to character(s) and
675  * pass them up to cons_channel's upstream hook.
676  *
677  * Return zero on success, else the keysym that we could not handle
678  * (so that the caller may complain).
679  */
680 static int
681 kbd_input_keysym(k, keysym)
682 	struct kbd_softc *k;
683 	int keysym;
684 {
685 	struct kbd_state *ks = &k->k_state;
686 	int data;
687 
688 	/* Check if a recipient has been configured */
689 	if (k->k_cc == NULL || k->k_cc->cc_upstream == NULL)
690 		return (0);
691 
692 	switch (KEYSYM_CLASS(keysym)) {
693 
694 	case KEYSYM_ASCII:
695 		data = KEYSYM_DATA(keysym);
696 		if (ks->kbd_modbits & KBMOD_META_MASK)
697 			data |= 0x80;
698 		(*k->k_cc->cc_upstream)(data);
699 		break;
700 
701 	case KEYSYM_STRING:
702 		data = keysym & 0xF;
703 		kbd_input_string(k, kbd_stringtab[data]);
704 		break;
705 
706 	case KEYSYM_FUNC:
707 		kbd_input_funckey(k, keysym);
708 		break;
709 
710 	case KEYSYM_CLRMOD:
711 		data = 1 << (keysym & 0x1F);
712 		ks->kbd_modbits &= ~data;
713 		break;
714 
715 	case KEYSYM_SETMOD:
716 		data = 1 << (keysym & 0x1F);
717 		ks->kbd_modbits |= data;
718 		break;
719 
720 	case KEYSYM_INVMOD:
721 		data = 1 << (keysym & 0x1F);
722 		ks->kbd_modbits ^= data;
723 		kbd_update_leds(k);
724 		break;
725 
726 	case KEYSYM_ALL_UP:
727 		ks->kbd_modbits &= ~0xFFFF;
728 		break;
729 
730 	case KEYSYM_SPECIAL:
731 		if (keysym == KEYSYM_NOP)
732 			break;
733 		/* FALLTHROUGH */
734 	default:
735 		/* We could not handle it. */
736 		return (keysym);
737 	}
738 
739 	return (0);
740 }
741 
742 
743 /*
744  * Send string upstream.
745  */
746 static void
747 kbd_input_string(k, str)
748 	struct kbd_softc *k;
749 	char *str;
750 {
751 
752 	while (*str) {
753 		(*k->k_cc->cc_upstream)(*str);
754 		++str;
755 	}
756 }
757 
758 
759 /*
760  * Format the F-key sequence and send as a string.
761  * XXX: Ugly compatibility mappings.
762  */
763 static void
764 kbd_input_funckey(k, keysym)
765 	struct kbd_softc *k;
766 	int keysym;
767 {
768 	int n;
769 	char str[12];
770 
771 	n = 0xC0 + (keysym & 0x3F);
772 	sprintf(str, "\033[%dz", n);
773 	kbd_input_string(k, str);
774 }
775 
776 
777 /*
778  * Update LEDs to reflect console input state.
779  */
780 static void
781 kbd_update_leds(k)
782 	struct kbd_softc *k;
783 {
784 	struct kbd_state *ks = &k->k_state;
785 	char leds;
786 
787 	leds = ks->kbd_leds;
788 	leds &= ~(LED_CAPS_LOCK|LED_NUM_LOCK);
789 
790 	if (ks->kbd_modbits & (1 << KBMOD_CAPSLOCK))
791 		leds |= LED_CAPS_LOCK;
792 	if (ks->kbd_modbits & (1 << KBMOD_NUMLOCK))
793 		leds |= LED_NUM_LOCK;
794 
795 	if (k->k_ops != NULL && k->k_ops->setleds != NULL)
796 		(void)(*k->k_ops->setleds)(k, leds, 0);
797 }
798 
799 
800 
801 /****************************************************************
802  *  Events input - called by middle layer at spltty().
803  ****************************************************************/
804 
805 /*
806  * Supply raw keystrokes when keyboard is open in firm event mode.
807  *
808  * Turn the keystroke into an event and put it in the queue.
809  * If the queue is full, the keystroke is lost (sorry!).
810  */
811 static void
812 kbd_input_event(k, code)
813 	struct kbd_softc *k;
814 	int code;
815 {
816 	struct firm_event *fe;
817 	int put;
818 
819 #ifdef DIAGNOSTIC
820 	if (!k->k_evmode) {
821 		printf("%s: kbd_input_event called when not in event mode\n",
822 		       k->k_dev.dv_xname);
823 		return;
824 	}
825 #endif
826 	put = k->k_events.ev_put;
827 	fe = &k->k_events.ev_q[put];
828 	put = (put + 1) % EV_QSIZE;
829 	if (put == k->k_events.ev_get) {
830 		log(LOG_WARNING, "%s: event queue overflow\n",
831 		    k->k_dev.dv_xname);
832 		return;
833 	}
834 
835 	fe->id = KEY_CODE(code);
836 	fe->value = KEY_UP(code) ? VKEY_UP : VKEY_DOWN;
837 	fe->time = time;
838 	k->k_events.ev_put = put;
839 	EV_WAKEUP(&k->k_events);
840 }
841 
842 
843 
844 /****************************************************************
845  *  Translation stuff declared in kbd_xlate.h
846  ****************************************************************/
847 
848 /*
849  * Initialization - called by either lower layer attach or by kdcninit.
850  */
851 void
852 kbd_xlate_init(ks)
853 	struct kbd_state *ks;
854 {
855 	struct keyboard *ktbls;
856 	int id;
857 
858 	id = ks->kbd_id;
859 	if (id < KBD_MIN_TYPE)
860 		id = KBD_MIN_TYPE;
861 	if (id > kbd_max_type)
862 		id = kbd_max_type;
863 	ktbls = keyboards[id];
864 
865 	ks->kbd_k = *ktbls; 	/* struct assignment */
866 	ks->kbd_modbits = 0;
867 }
868 
869 /*
870  * Turn keyboard up/down codes into a KEYSYM.
871  * Note that the "kd" driver (on sun3 and sparc64) uses this too!
872  */
873 int
874 kbd_code_to_keysym(ks, c)
875 	struct kbd_state *ks;
876 	int c;
877 {
878 	u_short *km;
879 	int keysym;
880 
881 	/*
882 	 * Get keymap pointer.  One of these:
883 	 * release, control, shifted, normal, ...
884 	 */
885 	if (KEY_UP(c))
886 		km = ks->kbd_k.k_release;
887 	else if (ks->kbd_modbits & KBMOD_CTRL_MASK)
888 		km = ks->kbd_k.k_control;
889 	else if (ks->kbd_modbits & KBMOD_SHIFT_MASK)
890 		km = ks->kbd_k.k_shifted;
891 	else
892 		km = ks->kbd_k.k_normal;
893 
894 	if (km == NULL) {
895 		/*
896 		 * Do not know how to translate yet.
897 		 * We will find out when a RESET comes along.
898 		 */
899 		return (KEYSYM_NOP);
900 	}
901 	keysym = km[KEY_CODE(c)];
902 
903 	/*
904 	 * Post-processing for Caps-lock
905 	 */
906 	if ((ks->kbd_modbits & (1 << KBMOD_CAPSLOCK)) &&
907 		(KEYSYM_CLASS(keysym) == KEYSYM_ASCII) )
908 	{
909 		if (('a' <= keysym) && (keysym <= 'z'))
910 			keysym -= ('a' - 'A');
911 	}
912 
913 	/*
914 	 * Post-processing for Num-lock.  All "function"
915 	 * keysyms get indirected through another table.
916 	 * (XXX: Only if numlock on.  Want off also!)
917 	 */
918 	if ((ks->kbd_modbits & (1 << KBMOD_NUMLOCK)) &&
919 		(KEYSYM_CLASS(keysym) == KEYSYM_FUNC) )
920 	{
921 		keysym = kbd_numlock_map[keysym & 0x3F];
922 	}
923 
924 	return (keysym);
925 }
926 
927 
928 /*
929  * Back door for rcons (fb.c)
930  */
931 void
932 kbd_bell(on)
933 	int on;
934 {
935 	struct kbd_softc *k = kbd_cd.cd_devs[0]; /* XXX: hardcoded minor */
936 
937 	if (k == NULL || k->k_ops == NULL || k->k_ops->docmd == NULL)
938 		return;
939 
940 	(void)(*k->k_ops->docmd)(k, on ? KBD_CMD_BELL : KBD_CMD_NOBELL, 0);
941 }
942 
943 #if NWSKBD > 0
944 static void
945 kbd_input_wskbd(struct kbd_softc *k, int code)
946 {
947 	int type, key;
948 
949 	type = KEY_UP(code) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
950 	key = KEY_CODE(code);
951 	wskbd_input(k->k_wskbd, type, key);
952 }
953 
954 int
955 wssunkbd_enable(v, on)
956 	void *v;
957 	int on;
958 {
959 	struct kbd_softc *k = v;
960 
961 	k->k_wsenabled = on;
962 	if (on) {
963 		/* open actual underlying device */
964 		if (k->k_ops != NULL && k->k_ops->open != NULL)
965 			(*k->k_ops->open)(k);
966 		ev_init(&k->k_events);
967 		k->k_evmode = 0;	/* XXX: OK? */
968 	} else {
969 		/* close underlying device */
970 		if (k->k_ops != NULL && k->k_ops->close != NULL)
971 			(*k->k_ops->close)(k);
972 	}
973 
974 	return 0;
975 }
976 
977 void
978 wssunkbd_set_leds(v, leds)
979 	void *v;
980 	int leds;
981 {
982 	struct kbd_softc *k = v;
983 	int l = 0;
984 
985 	if (leds & WSKBD_LED_CAPS)
986 		l |= LED_CAPS_LOCK;
987 	if (leds & WSKBD_LED_NUM)
988 		l |= LED_NUM_LOCK;
989 	if (leds & WSKBD_LED_SCROLL)
990 		l |= LED_SCROLL_LOCK;
991 	if (leds & WSKBD_LED_COMPOSE)
992 		l |= LED_COMPOSE;
993 	if (k->k_ops != NULL && k->k_ops->setleds != NULL)
994 		(*k->k_ops->setleds)(k, l, 0);
995 }
996 
997 int
998 wssunkbd_ioctl(v, cmd, data, flag, p)
999 	void *v;
1000 	u_long cmd;
1001 	caddr_t data;
1002 	int flag;
1003 	struct proc *p;
1004 {
1005 	return EPASSTHROUGH;
1006 }
1007 
1008 void
1009 sunkbd_wskbd_cngetc(v, type, data)
1010 	void *v;
1011 	u_int *type;
1012 	int *data;
1013 {
1014 	/* struct kbd_sun_softc *k = v; */
1015 }
1016 
1017 void
1018 sunkbd_wskbd_cnpollc(v, on)
1019 	void *v;
1020 	int on;
1021 {
1022 }
1023 
1024 static void
1025 sunkbd_bell_off(v)
1026 	void *v;
1027 {
1028 	struct kbd_softc *k = v;
1029 	k->k_ops->docmd(k, KBD_CMD_NOBELL, 0);
1030 }
1031 
1032 void
1033 sunkbd_wskbd_cnbell(v, pitch, period, volume)
1034 	void *v;
1035 	u_int pitch, period, volume;
1036 {
1037 	struct kbd_softc *k = v;
1038 
1039 	callout_reset(&k->k_wsbell, period*1000/hz, sunkbd_bell_off, v);
1040 	k->k_ops->docmd(k, KBD_CMD_BELL, 0);
1041 }
1042 
1043 void
1044 kbd_wskbd_attach(k, isconsole)
1045 	struct kbd_softc *k;
1046 	int isconsole;
1047 {
1048 	struct wskbddev_attach_args a;
1049 
1050 	a.console = isconsole;
1051 
1052 	if (a.console)
1053 		wskbd_cnattach(&sunkbd_wskbd_consops, k, &sunkbd_wskbd_keymapdata);
1054 
1055 	a.keymap = &sunkbd_wskbd_keymapdata;
1056 
1057 	a.accessops = &sunkbd_wskbd_accessops;
1058 	a.accesscookie = k;
1059 
1060 	/* Attach the wskbd */
1061 	k->k_wskbd = config_found(&k->k_dev, &a, wskbddevprint);
1062 	k->k_wsenabled = 0;
1063 	callout_init(&k->k_wsbell);
1064 }
1065 #endif
1066