kbd.c revision 1.34 1 /* $NetBSD: kbd.c,v 1.34 2002/10/23 09:13:56 jdolecek 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.34 2002/10/23 09:13:56 jdolecek 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/sun/kbd_reg.h>
73 #include <dev/sun/kbio.h>
74 #include <dev/sun/vuid_event.h>
75 #include <dev/sun/event_var.h>
76 #include <dev/sun/kbd_xlate.h>
77 #include <dev/sun/kbdvar.h>
78
79 #include "locators.h"
80
81 extern struct cfdriver kbd_cd;
82
83 dev_type_open(kbdopen);
84 dev_type_close(kbdclose);
85 dev_type_read(kbdread);
86 dev_type_ioctl(kbdioctl);
87 dev_type_poll(kbdpoll);
88 dev_type_kqfilter(kbdkqfilter);
89
90 const struct cdevsw kbd_cdevsw = {
91 kbdopen, kbdclose, kbdread, nowrite, kbdioctl,
92 nostop, notty, kbdpoll, nommap, kbdkqfilter
93 };
94
95
96 /* ioctl helpers */
97 static int kbd_iockeymap(struct kbd_state *ks,
98 u_long cmd, struct kiockeymap *kio);
99 #ifdef KIOCGETKEY
100 static int kbd_oldkeymap(struct kbd_state *ks,
101 u_long cmd, struct okiockey *okio);
102 #endif
103
104
105 /* callbacks for console driver */
106 static int kbd_cc_open(struct cons_channel *);
107 static int kbd_cc_close(struct cons_channel *);
108
109 /* console input */
110 static void kbd_input_console(struct kbd_softc *, int);
111 static void kbd_repeat(void *);
112 static int kbd_input_keysym(struct kbd_softc *, int);
113 static void kbd_input_string(struct kbd_softc *, char *);
114 static void kbd_input_funckey(struct kbd_softc *, int);
115 static void kbd_update_leds(struct kbd_softc *);
116
117 /* firm events input */
118 static void kbd_input_event(struct kbd_softc *, int);
119
120
121
122 /****************************************************************
123 * Entry points for /dev/kbd
124 * (open,close,read,write,...)
125 ****************************************************************/
126
127 /*
128 * Open:
129 * Check exclusion, open actual device (_iopen),
130 * setup event channel, clear ASCII repeat stuff.
131 */
132 int
133 kbdopen(dev, flags, mode, p)
134 dev_t dev;
135 int flags, mode;
136 struct proc *p;
137 {
138 struct kbd_softc *k;
139 int error, unit;
140
141 /* locate device */
142 unit = minor(dev);
143 if (unit >= kbd_cd.cd_ndevs)
144 return (ENXIO);
145 k = kbd_cd.cd_devs[unit];
146 if (k == NULL)
147 return (ENXIO);
148
149 /*
150 * NB: wscons support: while we can track if wskbd has called
151 * enable(), we can't tell if that's for console input or for
152 * events input, so we should probably just let the open to
153 * always succeed regardless (e.g. Xsun opening /dev/kbd).
154 */
155
156 /* exclusive open required for /dev/kbd */
157 if (k->k_events.ev_io)
158 return (EBUSY);
159 k->k_events.ev_io = p;
160
161 /* stop pending autorepeat of console input */
162 if (k->k_repeating) {
163 k->k_repeating = 0;
164 callout_stop(&k->k_repeat_ch);
165 }
166
167 /* open actual underlying device */
168 if (k->k_ops != NULL && k->k_ops->open != NULL)
169 if ((error = (*k->k_ops->open)(k)) != 0) {
170 k->k_events.ev_io = NULL;
171 return (error);
172 }
173
174 ev_init(&k->k_events);
175 k->k_evmode = 0; /* XXX: OK? */
176
177 return (0);
178 }
179
180
181 /*
182 * Close:
183 * Turn off event mode, dump the queue, and close the keyboard
184 * unless it is supplying console input.
185 */
186 int
187 kbdclose(dev, flags, mode, p)
188 dev_t dev;
189 int flags, mode;
190 struct proc *p;
191 {
192 struct kbd_softc *k;
193
194 k = kbd_cd.cd_devs[minor(dev)];
195 k->k_evmode = 0;
196 ev_fini(&k->k_events);
197 k->k_events.ev_io = NULL;
198
199 if (k->k_ops != NULL && k->k_ops->close != NULL) {
200 int error;
201 if ((error = (*k->k_ops->close)(k)) != 0)
202 return (error);
203 }
204 return (0);
205 }
206
207
208 int
209 kbdread(dev, uio, flags)
210 dev_t dev;
211 struct uio *uio;
212 int flags;
213 {
214 struct kbd_softc *k;
215
216 k = kbd_cd.cd_devs[minor(dev)];
217 return (ev_read(&k->k_events, uio, flags));
218 }
219
220
221 int
222 kbdpoll(dev, events, p)
223 dev_t dev;
224 int events;
225 struct proc *p;
226 {
227 struct kbd_softc *k;
228
229 k = kbd_cd.cd_devs[minor(dev)];
230 return (ev_poll(&k->k_events, events, p));
231 }
232
233 int
234 kbdkqfilter(dev, kn)
235 dev_t dev;
236 struct knote *kn;
237 {
238 struct kbd_softc *k;
239
240 k = kbd_cd.cd_devs[minor(dev)];
241 return (ev_kqfilter(&k->k_events, kn));
242 }
243
244 int
245 kbdioctl(dev, cmd, data, flag, p)
246 dev_t dev;
247 u_long cmd;
248 caddr_t data;
249 int flag;
250 struct proc *p;
251 {
252 struct kbd_softc *k;
253 struct kbd_state *ks;
254 int error = 0;
255
256 k = kbd_cd.cd_devs[minor(dev)];
257 ks = &k->k_state;
258
259 switch (cmd) {
260
261 case KIOCTRANS: /* Set translation mode */
262 /* We only support "raw" mode on /dev/kbd */
263 if (*(int *)data != TR_UNTRANS_EVENT)
264 error = EINVAL;
265 break;
266
267 case KIOCGTRANS: /* Get translation mode */
268 /* We only support "raw" mode on /dev/kbd */
269 *(int *)data = TR_UNTRANS_EVENT;
270 break;
271
272 #ifdef KIOCGETKEY
273 case KIOCGETKEY: /* Get keymap entry (old format) */
274 error = kbd_oldkeymap(ks, cmd, (struct okiockey *)data);
275 break;
276 #endif /* KIOCGETKEY */
277
278 case KIOCSKEY: /* Set keymap entry */
279 /* FALLTHROUGH */
280 case KIOCGKEY: /* Get keymap entry */
281 error = kbd_iockeymap(ks, cmd, (struct kiockeymap *)data);
282 break;
283
284 case KIOCCMD: /* Send a command to the keyboard */
285 /* pass it to the middle layer */
286 if (k->k_ops != NULL && k->k_ops->docmd != NULL)
287 error = (*k->k_ops->docmd)(k, *(int *)data, 1);
288 break;
289
290 case KIOCTYPE: /* Get keyboard type */
291 *(int *)data = ks->kbd_id;
292 break;
293
294 case KIOCSDIRECT: /* Where to send input */
295 k->k_evmode = *(int *)data;
296 break;
297
298 case KIOCLAYOUT: /* Get keyboard layout */
299 *(int *)data = ks->kbd_layout;
300 break;
301
302 case KIOCSLED: /* Set keyboard LEDs */
303 /* pass the request to the middle layer */
304 if (k->k_ops != NULL && k->k_ops->setleds != NULL)
305 error = (*k->k_ops->setleds)(k, *(char *)data, 1);
306 break;
307
308 case KIOCGLED: /* Get keyboard LEDs */
309 *(char *)data = ks->kbd_leds;
310 break;
311
312 case FIONBIO: /* we will remove this someday (soon???) */
313 break;
314
315 case FIOASYNC:
316 k->k_events.ev_async = (*(int *)data != 0);
317 break;
318
319 case TIOCSPGRP:
320 if (*(int *)data != k->k_events.ev_io->p_pgid)
321 error = EPERM;
322 break;
323
324 default:
325 error = ENOTTY;
326 break;
327 }
328
329 return (error);
330 }
331
332
333 /****************************************************************
334 * ioctl helpers
335 ****************************************************************/
336
337 /*
338 * Get/Set keymap entry
339 */
340 static int
341 kbd_iockeymap(ks, cmd, kio)
342 struct kbd_state *ks;
343 u_long cmd;
344 struct kiockeymap *kio;
345 {
346 u_short *km;
347 u_int station;
348
349 switch (kio->kio_tablemask) {
350 case KIOC_NOMASK:
351 km = ks->kbd_k.k_normal;
352 break;
353 case KIOC_SHIFTMASK:
354 km = ks->kbd_k.k_shifted;
355 break;
356 case KIOC_CTRLMASK:
357 km = ks->kbd_k.k_control;
358 break;
359 case KIOC_UPMASK:
360 km = ks->kbd_k.k_release;
361 break;
362 default:
363 /* Silently ignore unsupported masks */
364 return (0);
365 }
366
367 /* Range-check the table position. */
368 station = kio->kio_station;
369 if (station >= KEYMAP_SIZE)
370 return (EINVAL);
371
372 switch (cmd) {
373
374 case KIOCGKEY: /* Get keymap entry */
375 kio->kio_entry = km[station];
376 break;
377
378 case KIOCSKEY: /* Set keymap entry */
379 km[station] = kio->kio_entry;
380 break;
381
382 default:
383 return(ENOTTY);
384 }
385 return (0);
386 }
387
388
389 #ifdef KIOCGETKEY
390 /*
391 * Get/Set keymap entry,
392 * old format (compatibility)
393 */
394 int
395 kbd_oldkeymap(ks, cmd, kio)
396 struct kbd_state *ks;
397 u_long cmd;
398 struct okiockey *kio;
399 {
400 int error = 0;
401
402 switch (cmd) {
403
404 case KIOCGETKEY:
405 if (kio->kio_station == 118) {
406 /*
407 * This is X11 asking if a type 3 keyboard is
408 * really a type 3 keyboard. Say yes, it is,
409 * by reporting key station 118 as a "hole".
410 * Note old (SunOS 3.5) definition of HOLE!
411 */
412 kio->kio_entry = 0xA2;
413 break;
414 }
415 /* fall through */
416
417 default:
418 error = ENOTTY;
419 break;
420 }
421
422 return (error);
423 }
424 #endif /* KIOCGETKEY */
425
426
427
428 /****************************************************************
429 * Keyboard input - called by middle layer at spltty().
430 ****************************************************************/
431
432 void
433 kbd_input(k, code)
434 struct kbd_softc *k;
435 int code;
436 {
437 /*
438 * TODO: wscons support: check if attached wskbd has called
439 * enable() and pass input to wskbd_input() if it has. But
440 * check for k_evmode first(!) - see the comment in kbdopen().
441 */
442
443 /*
444 * If /dev/kbd is not connected in event mode,
445 * translate and send upstream (to console).
446 */
447 if (!k->k_evmode) {
448 kbd_input_console(k, code);
449 return;
450 }
451
452 /*
453 * XXX: is this still true?
454 * IDLEs confuse the MIT X11R4 server badly, so we must drop them.
455 * This is bad as it means the server will not automatically resync
456 * on all-up IDLEs, but I did not drop them before, and the server
457 * goes crazy when it comes time to blank the screen....
458 */
459 if (code == KBD_IDLE)
460 return;
461
462 /*
463 * Keyboard is generating firm events. Turn this keystroke
464 * into an event and put it in the queue.
465 */
466 kbd_input_event(k, code);
467 }
468
469
470
471 /****************************************************************
472 * Open/close routines called upon opening /dev/console
473 * if we serve console input.
474 ****************************************************************/
475
476 struct cons_channel *
477 kbd_cc_alloc(k)
478 struct kbd_softc *k;
479 {
480 struct cons_channel *cc;
481
482 if ((cc = malloc(sizeof *cc, M_DEVBUF, M_NOWAIT)) == NULL)
483 return (NULL);
484
485 /* our callbacks for the console driver */
486 cc->cc_dev = k;
487 cc->cc_iopen = kbd_cc_open;
488 cc->cc_iclose = kbd_cc_close;
489
490 /* will be provided by the console driver so that we can feed input */
491 cc->cc_upstream = NULL;
492
493 /*
494 * TODO: clean up cons_attach_input() vs kd_attach_input() in
495 * lower layers and move that code here.
496 */
497
498 k->k_cc = cc;
499 return (cc);
500 }
501
502
503 static int
504 kbd_cc_open(cc)
505 struct cons_channel *cc;
506 {
507 struct kbd_softc *k;
508 int ret;
509
510 if (cc == NULL)
511 return (0);
512
513 k = (struct kbd_softc *)cc->cc_dev;
514 if (k == NULL)
515 return (0);
516
517 if (k->k_ops != NULL && k->k_ops->open != NULL)
518 ret = (*k->k_ops->open)(k);
519 else
520 ret = 0;
521
522 /* XXX: verify that callout is not active? */
523 k->k_repeat_start = hz/2;
524 k->k_repeat_step = hz/20;
525 callout_init(&k->k_repeat_ch);
526
527 return (ret);
528 }
529
530
531 static int
532 kbd_cc_close(cc)
533 struct cons_channel *cc;
534 {
535 struct kbd_softc *k;
536 int ret;
537
538 if (cc == NULL)
539 return (0);
540
541 k = (struct kbd_softc *)cc->cc_dev;
542 if (k == NULL)
543 return (0);
544
545 if (k->k_ops != NULL && k->k_ops->close != NULL)
546 ret = (*k->k_ops->close)(k);
547 else
548 ret = 0;
549
550 /* stop any pending auto-repeat */
551 if (k->k_repeating) {
552 k->k_repeating = 0;
553 callout_stop(&k->k_repeat_ch);
554 }
555
556 return (ret);
557 }
558
559
560
561 /****************************************************************
562 * Console input - called by middle layer at spltty().
563 ****************************************************************/
564
565 static void
566 kbd_input_console(k, code)
567 struct kbd_softc *k;
568 int code;
569 {
570 struct kbd_state *ks= &k->k_state;
571 int keysym;
572
573 /* any input stops auto-repeat (i.e. key release) */
574 if (k->k_repeating) {
575 k->k_repeating = 0;
576 callout_stop(&k->k_repeat_ch);
577 }
578
579 keysym = kbd_code_to_keysym(ks, code);
580
581 /* pass to console */
582 if (kbd_input_keysym(k, keysym)) {
583 log(LOG_WARNING, "%s: code=0x%x with mod=0x%x"
584 " produced unexpected keysym 0x%x\n",
585 k->k_dev.dv_xname,
586 code, ks->kbd_modbits, keysym);
587 return; /* no point in auto-repeat here */
588 }
589
590 if (KEYSYM_NOREPEAT(keysym))
591 return;
592
593 /* setup for auto-repeat after initial delay */
594 k->k_repeating = 1;
595 k->k_repeatsym = keysym;
596 callout_reset(&k->k_repeat_ch, k->k_repeat_start,
597 kbd_repeat, k);
598 }
599
600
601 /*
602 * This is the autorepeat callout function scheduled by kbd_input() above.
603 * Called at splsoftclock().
604 */
605 static void
606 kbd_repeat(arg)
607 void *arg;
608 {
609 struct kbd_softc *k = (struct kbd_softc *)arg;
610 int s;
611
612 s = spltty();
613 if (k->k_repeating && k->k_repeatsym >= 0) {
614 /* feed typematic keysym to the console */
615 (void)kbd_input_keysym(k, k->k_repeatsym);
616
617 /* reschedule next repeat */
618 callout_reset(&k->k_repeat_ch, k->k_repeat_step,
619 kbd_repeat, k);
620 }
621 splx(s);
622 }
623
624
625
626 /*
627 * Supply keysym as console input. Convert keysym to character(s) and
628 * pass them up to cons_channel's upstream hook.
629 *
630 * Return zero on success, else the keysym that we could not handle
631 * (so that the caller may complain).
632 */
633 static int
634 kbd_input_keysym(k, keysym)
635 struct kbd_softc *k;
636 int keysym;
637 {
638 struct kbd_state *ks = &k->k_state;
639 int data;
640
641 /* Check if a recipient has been configured */
642 if (k->k_cc == NULL || k->k_cc->cc_upstream == NULL)
643 return (0);
644
645 switch (KEYSYM_CLASS(keysym)) {
646
647 case KEYSYM_ASCII:
648 data = KEYSYM_DATA(keysym);
649 if (ks->kbd_modbits & KBMOD_META_MASK)
650 data |= 0x80;
651 (*k->k_cc->cc_upstream)(data);
652 break;
653
654 case KEYSYM_STRING:
655 data = keysym & 0xF;
656 kbd_input_string(k, kbd_stringtab[data]);
657 break;
658
659 case KEYSYM_FUNC:
660 kbd_input_funckey(k, keysym);
661 break;
662
663 case KEYSYM_CLRMOD:
664 data = 1 << (keysym & 0x1F);
665 ks->kbd_modbits &= ~data;
666 break;
667
668 case KEYSYM_SETMOD:
669 data = 1 << (keysym & 0x1F);
670 ks->kbd_modbits |= data;
671 break;
672
673 case KEYSYM_INVMOD:
674 data = 1 << (keysym & 0x1F);
675 ks->kbd_modbits ^= data;
676 kbd_update_leds(k);
677 break;
678
679 case KEYSYM_ALL_UP:
680 ks->kbd_modbits &= ~0xFFFF;
681 break;
682
683 case KEYSYM_SPECIAL:
684 if (keysym == KEYSYM_NOP)
685 break;
686 /* FALLTHROUGH */
687 default:
688 /* We could not handle it. */
689 return (keysym);
690 }
691
692 return (0);
693 }
694
695
696 /*
697 * Send string upstream.
698 */
699 static void
700 kbd_input_string(k, str)
701 struct kbd_softc *k;
702 char *str;
703 {
704
705 while (*str) {
706 (*k->k_cc->cc_upstream)(*str);
707 ++str;
708 }
709 }
710
711
712 /*
713 * Format the F-key sequence and send as a string.
714 * XXX: Ugly compatibility mappings.
715 */
716 static void
717 kbd_input_funckey(k, keysym)
718 struct kbd_softc *k;
719 int keysym;
720 {
721 int n;
722 char str[12];
723
724 n = 0xC0 + (keysym & 0x3F);
725 sprintf(str, "\033[%dz", n);
726 kbd_input_string(k, str);
727 }
728
729
730 /*
731 * Update LEDs to reflect console input state.
732 */
733 static void
734 kbd_update_leds(k)
735 struct kbd_softc *k;
736 {
737 struct kbd_state *ks = &k->k_state;
738 char leds;
739
740 leds = ks->kbd_leds;
741 leds &= ~(LED_CAPS_LOCK|LED_NUM_LOCK);
742
743 if (ks->kbd_modbits & (1 << KBMOD_CAPSLOCK))
744 leds |= LED_CAPS_LOCK;
745 if (ks->kbd_modbits & (1 << KBMOD_NUMLOCK))
746 leds |= LED_NUM_LOCK;
747
748 if (k->k_ops != NULL && k->k_ops->setleds != NULL)
749 (void)(*k->k_ops->setleds)(k, leds, 0);
750 }
751
752
753
754 /****************************************************************
755 * Events input - called by middle layer at spltty().
756 ****************************************************************/
757
758 /*
759 * Supply raw keystrokes when keyboard is open in firm event mode.
760 *
761 * Turn the keystroke into an event and put it in the queue.
762 * If the queue is full, the keystroke is lost (sorry!).
763 */
764 static void
765 kbd_input_event(k, code)
766 struct kbd_softc *k;
767 int code;
768 {
769 struct firm_event *fe;
770 int put;
771
772 #ifdef DIAGNOSTIC
773 if (!k->k_evmode) {
774 printf("%s: kbd_input_event called when not in event mode\n",
775 k->k_dev.dv_xname);
776 return;
777 }
778 #endif
779 put = k->k_events.ev_put;
780 fe = &k->k_events.ev_q[put];
781 put = (put + 1) % EV_QSIZE;
782 if (put == k->k_events.ev_get) {
783 log(LOG_WARNING, "%s: event queue overflow\n",
784 k->k_dev.dv_xname);
785 return;
786 }
787
788 fe->id = KEY_CODE(code);
789 fe->value = KEY_UP(code) ? VKEY_UP : VKEY_DOWN;
790 fe->time = time;
791 k->k_events.ev_put = put;
792 EV_WAKEUP(&k->k_events);
793 }
794
795
796
797 /****************************************************************
798 * Translation stuff declared in kbd_xlate.h
799 ****************************************************************/
800
801 /*
802 * Initialization - called by either lower layer attach or by kdcninit.
803 */
804 void
805 kbd_xlate_init(ks)
806 struct kbd_state *ks;
807 {
808 struct keyboard *ktbls;
809 int id;
810
811 id = ks->kbd_id;
812 if (id < KBD_MIN_TYPE)
813 id = KBD_MIN_TYPE;
814 if (id > kbd_max_type)
815 id = kbd_max_type;
816 ktbls = keyboards[id];
817
818 ks->kbd_k = *ktbls; /* struct assignment */
819 ks->kbd_modbits = 0;
820 }
821
822 /*
823 * Turn keyboard up/down codes into a KEYSYM.
824 * Note that the "kd" driver (on sun3 and sparc64) uses this too!
825 */
826 int
827 kbd_code_to_keysym(ks, c)
828 struct kbd_state *ks;
829 int c;
830 {
831 u_short *km;
832 int keysym;
833
834 /*
835 * Get keymap pointer. One of these:
836 * release, control, shifted, normal, ...
837 */
838 if (KEY_UP(c))
839 km = ks->kbd_k.k_release;
840 else if (ks->kbd_modbits & KBMOD_CTRL_MASK)
841 km = ks->kbd_k.k_control;
842 else if (ks->kbd_modbits & KBMOD_SHIFT_MASK)
843 km = ks->kbd_k.k_shifted;
844 else
845 km = ks->kbd_k.k_normal;
846
847 if (km == NULL) {
848 /*
849 * Do not know how to translate yet.
850 * We will find out when a RESET comes along.
851 */
852 return (KEYSYM_NOP);
853 }
854 keysym = km[KEY_CODE(c)];
855
856 /*
857 * Post-processing for Caps-lock
858 */
859 if ((ks->kbd_modbits & (1 << KBMOD_CAPSLOCK)) &&
860 (KEYSYM_CLASS(keysym) == KEYSYM_ASCII) )
861 {
862 if (('a' <= keysym) && (keysym <= 'z'))
863 keysym -= ('a' - 'A');
864 }
865
866 /*
867 * Post-processing for Num-lock. All "function"
868 * keysyms get indirected through another table.
869 * (XXX: Only if numlock on. Want off also!)
870 */
871 if ((ks->kbd_modbits & (1 << KBMOD_NUMLOCK)) &&
872 (KEYSYM_CLASS(keysym) == KEYSYM_FUNC) )
873 {
874 keysym = kbd_numlock_map[keysym & 0x3F];
875 }
876
877 return (keysym);
878 }
879
880
881 /*
882 * Back door for rcons (fb.c)
883 */
884 void
885 kbd_bell(on)
886 int on;
887 {
888 struct kbd_softc *k = kbd_cd.cd_devs[0]; /* XXX: hardcoded minor */
889
890 if (k == NULL || k->k_ops == NULL || k->k_ops->docmd == NULL)
891 return;
892
893 (void)(*k->k_ops->docmd)(k, on ? KBD_CMD_BELL : KBD_CMD_NOBELL, 0);
894 }
895