📄 kbd.c
字号:
/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Lawrence Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kbd.c 8.2 (Berkeley) 10/30/93 * * from: $Header: kbd.c,v 1.18 93/10/31 05:44:01 torek Exp $ (LBL) *//* * Keyboard driver (/dev/kbd -- note that we do not have minor numbers * [yet?]). Translates incoming bytes to ASCII or to `firm_events' and * passes them up to the appropriate reader. */#include <sys/param.h>#include <sys/conf.h>#include <sys/device.h>#include <sys/ioctl.h>#include <sys/kernel.h>#include <sys/proc.h>#include <sys/syslog.h>#include <sys/systm.h>#include <sys/tty.h>#include <machine/autoconf.h>#include <sparc/dev/vuid_event.h>#include <sparc/dev/event_var.h>#include <sparc/dev/kbd.h>#include <sparc/dev/kbio.h>/* * Sun keyboard definitions (from Sprite). * These apply to type 2, 3 and 4 keyboards. */#define KEY_CODE(c) ((c) & KBD_KEYMASK) /* keyboard code index */#define KEY_UP(c) ((c) & KBD_UP) /* true => key went up *//* * Each KEY_CODE(x) can be translated via the tables below. * The result is either a valid ASCII value in [0..0x7f] or is one * of the following `magic' values saying something interesting * happened. If LSHIFT or RSHIFT has changed state the next * lookup should come from the appropriate table; if ALLUP is * sent all keys (including both shifts and the control key) are * now up, and the next byte is the keyboard ID code. * * These tables ignore all function keys (on the theory that if you * want these keys, you should use a window system). Note that * `caps lock' is just mapped as `ignore' (so there!). (Only the * type 3 and 4 keyboards have a caps lock key anyway.) */#define KEY_MAGIC 0x80 /* flag => magic value */#define KEY_IGNORE 0x80#define KEY_L1 KEY_IGNORE#define KEY_CAPSLOCK KEY_IGNORE#define KEY_LSHIFT 0x81#define KEY_RSHIFT 0x82#define KEY_CONTROL 0x83#define KEY_ALLUP 0x84 /* all keys are now up; also reset *//* * Decode tables for type 2, 3, and 4 keyboards * (stolen from Sprite; see also kbd.h). */static const u_char kbd_unshifted[] = {/* 0 */ KEY_IGNORE, KEY_L1, KEY_IGNORE, KEY_IGNORE,/* 4 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 8 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 12 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 16 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 20 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 24 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 28 */ KEY_IGNORE, '\033', '1', '2',/* 32 */ '3', '4', '5', '6',/* 36 */ '7', '8', '9', '0',/* 40 */ '-', '=', '`', '\b',/* 44 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 48 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 52 */ KEY_IGNORE, '\t', 'q', 'w',/* 56 */ 'e', 'r', 't', 'y',/* 60 */ 'u', 'i', 'o', 'p',/* 64 */ '[', ']', '\177', KEY_IGNORE,/* 68 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 72 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 76 */ KEY_CONTROL, 'a', 's', 'd',/* 80 */ 'f', 'g', 'h', 'j',/* 84 */ 'k', 'l', ';', '\'',/* 88 */ '\\', '\r', KEY_IGNORE, KEY_IGNORE,/* 92 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 96 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_LSHIFT,/* 100 */ 'z', 'x', 'c', 'v',/* 104 */ 'b', 'n', 'm', ',',/* 108 */ '.', '/', KEY_RSHIFT, '\n',/* 112 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 116 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_CAPSLOCK,/* 120 */ KEY_IGNORE, ' ', KEY_IGNORE, KEY_IGNORE,/* 124 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_ALLUP,};static const u_char kbd_shifted[] = {/* 0 */ KEY_IGNORE, KEY_L1, KEY_IGNORE, KEY_IGNORE,/* 4 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 8 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 12 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 16 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 20 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 24 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 28 */ KEY_IGNORE, '\033', '!', '@',/* 32 */ '#', '$', '%', '^',/* 36 */ '&', '*', '(', ')',/* 40 */ '_', '+', '~', '\b',/* 44 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 48 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 52 */ KEY_IGNORE, '\t', 'Q', 'W',/* 56 */ 'E', 'R', 'T', 'Y',/* 60 */ 'U', 'I', 'O', 'P',/* 64 */ '{', '}', '\177', KEY_IGNORE,/* 68 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 72 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 76 */ KEY_CONTROL, 'A', 'S', 'D',/* 80 */ 'F', 'G', 'H', 'J',/* 84 */ 'K', 'L', ':', '"',/* 88 */ '|', '\r', KEY_IGNORE, KEY_IGNORE,/* 92 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 96 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_LSHIFT,/* 100 */ 'Z', 'X', 'C', 'V',/* 104 */ 'B', 'N', 'M', '<',/* 108 */ '>', '?', KEY_RSHIFT, '\n',/* 112 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE,/* 116 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_CAPSLOCK,/* 120 */ KEY_IGNORE, ' ', KEY_IGNORE, KEY_IGNORE,/* 124 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_ALLUP,};/* * We need to remember the state of the keyboard's shift and control * keys, and we need a per-type translation table. */struct kbd_state { const u_char *kbd_unshifted; /* unshifted keys */ const u_char *kbd_shifted; /* shifted keys */ const u_char *kbd_cur; /* current keys (either of the preceding) */ union { char c[2]; /* left and right shift keys */ short s; /* true => either shift key */ } kbd_shift;#define kbd_lshift kbd_shift.c[0]#define kbd_rshift kbd_shift.c[1]#define kbd_anyshift kbd_shift.s char kbd_control; /* true => ctrl down */ char kbd_click; /* true => keyclick enabled */ char kbd_takeid; /* take next byte as ID */ u_char kbd_id; /* a place to store the ID */};/* * Keyboard driver state. The ascii and kbd links go up and down and * we just sit in the middle doing translation. Note that it is possible * to get just one of the two links, in which case /dev/kbd is unavailable. * The downlink supplies us with `internal' open and close routines which * will enable dataflow across the downlink. We promise to call open when * we are willing to take keystrokes, and to call close when we are not. * If /dev/kbd is not the console tty input source, we do this whenever * /dev/kbd is in use; otherwise we just leave it open forever. */struct kbd_softc { struct tty *k_cons; /* uplink for ASCII data to console */ struct tty *k_kbd; /* downlink for output to keyboard */ void (*k_open) __P((struct tty *)); /* enable dataflow */ void (*k_close) __P((struct tty *)); /* disable dataflow */ int k_evmode; /* set if we should produce events */ struct kbd_state k_state; /* ASCII decode state */ struct evvar k_events; /* event queue state */} kbd_softc;/* Prototypes */void kbd_ascii(struct tty *);void kbd_serial(struct tty *, void (*)(), void (*)());static void kbd_getid(void *);void kbd_reset(struct kbd_state *);static int kbd_translate(int, struct kbd_state *);void kbd_rint(int);int kbdopen(dev_t, int, int, struct proc *);int kbdclose(dev_t, int, int, struct proc *);int kbdread(dev_t, struct uio *, int);int kbdwrite(dev_t, struct uio *, int);int kbdioctl(dev_t, int, caddr_t, int, struct proc *);int kbdselect(dev_t, int, struct proc *);int kbd_docmd(int, int);/* * Attach the console keyboard ASCII (up-link) interface. * This happens before kbd_serial. */voidkbd_ascii(struct tty *tp){ kbd_softc.k_cons = tp;}/* * Attach the console keyboard serial (down-link) interface. * We pick up the initial keyboard click state here as well. */voidkbd_serial(struct tty *tp, void (*iopen)(), void (*iclose)()){ register struct kbd_softc *k; register char *cp; k = &kbd_softc; k->k_kbd = tp; k->k_open = iopen; k->k_close = iclose; cp = getpropstring(optionsnode, "keyboard-click?"); if (cp && strcmp(cp, "true") == 0) k->k_state.kbd_click = 1;}/* * Called from main() during pseudo-device setup. If this keyboard is * the console, this is our chance to open the underlying serial port and * send a RESET, so that we can find out what kind of keyboard it is. */voidkbdattach(int nkbd){ register struct kbd_softc *k; register struct tty *tp; if (kbd_softc.k_cons != NULL) { k = &kbd_softc; tp = k->k_kbd; (*k->k_open)(tp); /* never to be closed */ if (ttyoutput(KBD_CMD_RESET, tp) >= 0) panic("kbdattach"); (*tp->t_oproc)(tp); /* get it going */ }}voidkbd_reset(register struct kbd_state *ks){ /* * On first identification, wake up anyone waiting for type * and set up the table pointers. */ if (ks->kbd_unshifted == NULL) { wakeup((caddr_t)ks); ks->kbd_unshifted = kbd_unshifted; ks->kbd_shifted = kbd_shifted; ks->kbd_cur = ks->kbd_unshifted; } /* Restore keyclick, if necessary */ switch (ks->kbd_id) { case KB_SUN2: /* Type 2 keyboards don't support keyclick */ break; case KB_SUN3: /* Type 3 keyboards come up with keyclick on */ if (!ks->kbd_click) (void) kbd_docmd(KBD_CMD_NOCLICK, 0); break; case KB_SUN4: /* Type 4 keyboards come up with keyclick off */ if (ks->kbd_click) (void) kbd_docmd(KBD_CMD_CLICK, 0); break; }}/* * Turn keyboard up/down codes into ASCII. */static intkbd_translate(register int c, register struct kbd_state *ks){ register int down; if (ks->kbd_cur == NULL) { /* * Do not know how to translate yet.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -