155105Storek /* 255105Storek * Copyright (c) 1992 The Regents of the University of California. 355105Storek * All rights reserved. 455105Storek * 555105Storek * This software was developed by the Computer Systems Engineering group 655105Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 755105Storek * contributed to Berkeley. 855105Storek * 9*55499Sbostic * All advertising materials mentioning features or use of this software 10*55499Sbostic * must display the following acknowledgement: 11*55499Sbostic * This product includes software developed by the University of 12*55499Sbostic * California, Lawrence Berkeley Laboratories. 13*55499Sbostic * 1455105Storek * %sccs.include.redist.c% 1555105Storek * 16*55499Sbostic * @(#)kbd.c 7.2 (Berkeley) 07/21/92 1755105Storek * 1855105Storek * from: $Header: kbd.c,v 1.15 92/07/09 07:59:27 torek Exp $ (LBL) 1955105Storek */ 2055105Storek 2155105Storek /* 2255105Storek * Keyboard driver (/dev/kbd -- note that we do not have minor numbers 2355105Storek * [yet?]). Translates incoming bytes to ASCII or to `firm_events' and 2455105Storek * passes them up to the appropriate reader. 2555105Storek */ 2655105Storek 2755105Storek #include "sys/param.h" 2855105Storek #include "sys/conf.h" 2955105Storek #include "sys/device.h" 3055105Storek #include "sys/ioctl.h" 3155105Storek #include "sys/kernel.h" 3255105Storek #include "sys/proc.h" 3355105Storek #include "sys/syslog.h" 3455105Storek #include "sys/systm.h" 3555105Storek #include "sys/tty.h" 3655105Storek 3755105Storek #include "machine/autoconf.h" 3855105Storek 3955105Storek #include "vuid_event.h" 4055105Storek #include "event_var.h" 4155105Storek #include "kbd.h" 4255105Storek #include "kbio.h" 4355105Storek 4455105Storek /* 4555105Storek * Sun keyboard definitions (from Sprite). 4655105Storek * These apply to type 2, 3 and 4 keyboards. 4755105Storek */ 4855105Storek #define KEY_CODE(c) ((c) & KBD_KEYMASK) /* keyboard code index */ 4955105Storek #define KEY_UP(c) ((c) & KBD_UP) /* true => key went up */ 5055105Storek 5155105Storek /* 5255105Storek * Each KEY_CODE(x) can be translated via the tables below. 5355105Storek * The result is either a valid ASCII value in [0..0x7f] or is one 5455105Storek * of the following `magic' values saying something interesting 5555105Storek * happened. If LSHIFT or RSHIFT has changed state the next 5655105Storek * lookup should come from the appropriate table; if ALLUP is 5755105Storek * sent all keys (including both shifts and the control key) are 5855105Storek * now up, and the next byte is the keyboard ID code. 5955105Storek * 6055105Storek * These tables ignore all function keys (on the theory that if you 6155105Storek * want these keys, you should use a window system). Note that 6255105Storek * `caps lock' is just mapped as `ignore' (so there!). (Only the 6355105Storek * type 3 and 4 keyboards have a caps lock key anyway.) 6455105Storek */ 6555105Storek #define KEY_MAGIC 0x80 /* flag => magic value */ 6655105Storek #define KEY_IGNORE 0x80 6755105Storek #define KEY_L1 KEY_IGNORE 6855105Storek #define KEY_CAPSLOCK KEY_IGNORE 6955105Storek #define KEY_LSHIFT 0x81 7055105Storek #define KEY_RSHIFT 0x82 7155105Storek #define KEY_CONTROL 0x83 7255105Storek #define KEY_ALLUP 0x84 /* all keys are now up; also reset */ 7355105Storek 7455105Storek /* 7555105Storek * Decode tables for type 2, 3, and 4 keyboards 7655105Storek * (stolen from Sprite; see also kbd.h). 7755105Storek */ 7855105Storek static const u_char kbd_unshifted[] = { 7955105Storek /* 0 */ KEY_IGNORE, KEY_L1, KEY_IGNORE, KEY_IGNORE, 8055105Storek /* 4 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 8155105Storek /* 8 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 8255105Storek /* 12 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 8355105Storek /* 16 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 8455105Storek /* 20 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 8555105Storek /* 24 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 8655105Storek /* 28 */ KEY_IGNORE, '\033', '1', '2', 8755105Storek /* 32 */ '3', '4', '5', '6', 8855105Storek /* 36 */ '7', '8', '9', '0', 8955105Storek /* 40 */ '-', '=', '`', '\b', 9055105Storek /* 44 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 9155105Storek /* 48 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 9255105Storek /* 52 */ KEY_IGNORE, '\t', 'q', 'w', 9355105Storek /* 56 */ 'e', 'r', 't', 'y', 9455105Storek /* 60 */ 'u', 'i', 'o', 'p', 9555105Storek /* 64 */ '[', ']', '\177', KEY_IGNORE, 9655105Storek /* 68 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 9755105Storek /* 72 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 9855105Storek /* 76 */ KEY_CONTROL, 'a', 's', 'd', 9955105Storek /* 80 */ 'f', 'g', 'h', 'j', 10055105Storek /* 84 */ 'k', 'l', ';', '\'', 10155105Storek /* 88 */ '\\', '\r', KEY_IGNORE, KEY_IGNORE, 10255105Storek /* 92 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 10355105Storek /* 96 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_LSHIFT, 10455105Storek /* 100 */ 'z', 'x', 'c', 'v', 10555105Storek /* 104 */ 'b', 'n', 'm', ',', 10655105Storek /* 108 */ '.', '/', KEY_RSHIFT, '\n', 10755105Storek /* 112 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 10855105Storek /* 116 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_CAPSLOCK, 10955105Storek /* 120 */ KEY_IGNORE, ' ', KEY_IGNORE, KEY_IGNORE, 11055105Storek /* 124 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_ALLUP, 11155105Storek }; 11255105Storek 11355105Storek static const u_char kbd_shifted[] = { 11455105Storek /* 0 */ KEY_IGNORE, KEY_L1, KEY_IGNORE, KEY_IGNORE, 11555105Storek /* 4 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 11655105Storek /* 8 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 11755105Storek /* 12 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 11855105Storek /* 16 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 11955105Storek /* 20 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 12055105Storek /* 24 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 12155105Storek /* 28 */ KEY_IGNORE, '\033', '!', '@', 12255105Storek /* 32 */ '#', '$', '%', '^', 12355105Storek /* 36 */ '&', '*', '(', ')', 12455105Storek /* 40 */ '_', '+', '~', '\b', 12555105Storek /* 44 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 12655105Storek /* 48 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 12755105Storek /* 52 */ KEY_IGNORE, '\t', 'Q', 'W', 12855105Storek /* 56 */ 'E', 'R', 'T', 'Y', 12955105Storek /* 60 */ 'U', 'I', 'O', 'P', 13055105Storek /* 64 */ '{', '}', '\177', KEY_IGNORE, 13155105Storek /* 68 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 13255105Storek /* 72 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 13355105Storek /* 76 */ KEY_CONTROL, 'A', 'S', 'D', 13455105Storek /* 80 */ 'F', 'G', 'H', 'J', 13555105Storek /* 84 */ 'K', 'L', ':', '"', 13655105Storek /* 88 */ '|', '\r', KEY_IGNORE, KEY_IGNORE, 13755105Storek /* 92 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 13855105Storek /* 96 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_LSHIFT, 13955105Storek /* 100 */ 'Z', 'X', 'C', 'V', 14055105Storek /* 104 */ 'B', 'N', 'M', '<', 14155105Storek /* 108 */ '>', '?', KEY_RSHIFT, '\n', 14255105Storek /* 112 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, 14355105Storek /* 116 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_CAPSLOCK, 14455105Storek /* 120 */ KEY_IGNORE, ' ', KEY_IGNORE, KEY_IGNORE, 14555105Storek /* 124 */ KEY_IGNORE, KEY_IGNORE, KEY_IGNORE, KEY_ALLUP, 14655105Storek }; 14755105Storek 14855105Storek /* 14955105Storek * We need to remember the state of the keyboard's shift and control 15055105Storek * keys, and we need a per-type translation table. 15155105Storek */ 15255105Storek struct kbd_state { 15355105Storek const u_char *kbd_unshifted; /* unshifted keys */ 15455105Storek const u_char *kbd_shifted; /* shifted keys */ 15555105Storek const u_char *kbd_cur; /* current keys (either of the preceding) */ 15655105Storek union { 15755105Storek char c[2]; /* left and right shift keys */ 15855105Storek short s; /* true => either shift key */ 15955105Storek } kbd_shift; 16055105Storek #define kbd_lshift kbd_shift.c[0] 16155105Storek #define kbd_rshift kbd_shift.c[1] 16255105Storek #define kbd_anyshift kbd_shift.s 16355105Storek char kbd_control; /* true => ctrl down */ 16455105Storek char kbd_click; /* true => keyclick enabled */ 16555105Storek char kbd_takeid; /* take next byte as ID */ 16655105Storek u_char kbd_id; /* a place to store the ID */ 16755105Storek }; 16855105Storek 16955105Storek /* 17055105Storek * Keyboard driver state. The ascii and kbd links go up and down and 17155105Storek * we just sit in the middle doing translation. Note that it is possible 17255105Storek * to get just one of the two links, in which case /dev/kbd is unavailable. 17355105Storek * The downlink supplies us with `internal' open and close routines which 17455105Storek * will enable dataflow across the downlink. We promise to call open when 17555105Storek * we are willing to take keystrokes, and to call close when we are not. 17655105Storek * If /dev/kbd is not the console tty input source, we do this whenever 17755105Storek * /dev/kbd is in use; otherwise we just leave it open forever. 17855105Storek */ 17955105Storek struct kbd_softc { 18055105Storek struct tty *k_cons; /* uplink for ASCII data to console */ 18155105Storek struct tty *k_kbd; /* downlink for output to keyboard */ 18255105Storek void (*k_open) __P((struct tty *)); /* enable dataflow */ 18355105Storek void (*k_close) __P((struct tty *)); /* disable dataflow */ 18455105Storek int k_evmode; /* set if we should produce events */ 18555105Storek struct kbd_state k_state; /* ASCII decode state */ 18655105Storek struct evvar k_events; /* event queue state */ 18755105Storek } kbd_softc; 18855105Storek 18955105Storek /* Prototypes */ 19055105Storek void kbd_ascii(struct tty *); 19155105Storek void kbd_serial(struct tty *, void (*)(), void (*)()); 19255105Storek static void kbd_getid(void *); 19355105Storek void kbd_reset(struct kbd_state *); 19455105Storek static int kbd_translate(int, struct kbd_state *); 19555105Storek void kbd_rint(int); 19655105Storek int kbdopen(dev_t, int, int, struct proc *); 19755105Storek int kbdclose(dev_t, int, int, struct proc *); 19855105Storek int kbdread(dev_t, struct uio *, int); 19955105Storek int kbdwrite(dev_t, struct uio *, int); 20055105Storek int kbdioctl(dev_t, int, caddr_t, int, struct proc *); 20155105Storek int kbdselect(dev_t, int, struct proc *); 20255105Storek int kbd_docmd(int, int); 20355105Storek 20455105Storek /* 20555105Storek * Attach the console keyboard ASCII (up-link) interface. 20655105Storek * This happens before kbd_serial. 20755105Storek */ 20855105Storek void 20955105Storek kbd_ascii(struct tty *tp) 21055105Storek { 21155105Storek 21255105Storek kbd_softc.k_cons = tp; 21355105Storek } 21455105Storek 21555105Storek /* 21655105Storek * Attach the console keyboard serial (down-link) interface. 21755105Storek * We pick up the initial keyboard clock state here as well. 21855105Storek */ 21955105Storek void 22055105Storek kbd_serial(struct tty *tp, void (*iopen)(), void (*iclose)()) 22155105Storek { 22255105Storek register struct kbd_softc *k; 22355105Storek register char *cp; 22455105Storek 22555105Storek k = &kbd_softc; 22655105Storek k->k_kbd = tp; 22755105Storek k->k_open = iopen; 22855105Storek k->k_close = iclose; 22955105Storek 23055105Storek cp = getpropstring(optionsnode, "keyboard-click?"); 23155105Storek if (cp && strcmp(cp, "true") == 0) 23255105Storek k->k_state.kbd_click = 1; 23355105Storek 23455105Storek if (k->k_cons) { 23555105Storek /* 23655105Storek * We supply keys for /dev/console. Before we can 23755105Storek * do so, we have to ``open'' the line. We also need 23855105Storek * the type, got by sending a RESET down the line ... 23955105Storek * but clists are not yet set up, so we use a timeout 24055105Storek * to try constantly until we can get the ID. (gag) 24155105Storek */ 24255105Storek (*iopen)(tp); /* never to be closed */ 24355105Storek kbd_getid(NULL); 24455105Storek } 24555105Storek } 24655105Storek 24755105Storek /* 24855105Storek * Initial keyboard reset, to obtain ID and thus a translation table. 24955105Storek * We have to try again and again until the tty subsystem works. 25055105Storek */ 25155105Storek static void 25255105Storek kbd_getid(void *arg) 25355105Storek { 25455105Storek register struct kbd_softc *k; 25555105Storek register struct tty *tp; 25655105Storek register int retry; 25755105Storek extern int cold; /* XXX */ 25855105Storek 25955105Storek k = &kbd_softc; 26055105Storek if (k->k_state.kbd_cur != NULL) 26155105Storek return; 26255105Storek tp = k->k_kbd; 26355105Storek if (cold || ttyoutput(KBD_CMD_RESET, tp) >= 0) 26455105Storek retry = 1; 26555105Storek else { 26655105Storek (*tp->t_oproc)(tp); 26755105Storek retry = 2 * hz; 26855105Storek } 26955105Storek timeout(kbd_getid, NULL, retry); 27055105Storek } 27155105Storek 27255105Storek void 27355105Storek kbd_reset(register struct kbd_state *ks) 27455105Storek { 27555105Storek /* 27655105Storek * On first identification, wake up anyone waiting for type 27755105Storek * and set up the table pointers. 27855105Storek */ 27955105Storek if (ks->kbd_unshifted == NULL) { 28055105Storek wakeup((caddr_t)ks); 28155105Storek ks->kbd_unshifted = kbd_unshifted; 28255105Storek ks->kbd_shifted = kbd_shifted; 28355105Storek ks->kbd_cur = ks->kbd_unshifted; 28455105Storek } 28555105Storek 28655105Storek /* Restore keyclick, if necessary */ 28755105Storek switch (ks->kbd_id) { 28855105Storek 28955105Storek case KB_SUN2: 29055105Storek /* Type 2 keyboards don't support keyclick */ 29155105Storek break; 29255105Storek 29355105Storek case KB_SUN3: 29455105Storek /* Type 3 keyboards come up with keyclick on */ 29555105Storek if (!ks->kbd_click) 29655105Storek (void) kbd_docmd(KBD_CMD_NOCLICK, 0); 29755105Storek break; 29855105Storek 29955105Storek case KB_SUN4: 30055105Storek /* Type 4 keyboards come up with keyclick off */ 30155105Storek if (ks->kbd_click) 30255105Storek (void) kbd_docmd(KBD_CMD_CLICK, 0); 30355105Storek break; 30455105Storek } 30555105Storek } 30655105Storek 30755105Storek /* 30855105Storek * Turn keyboard up/down codes into ASCII. 30955105Storek */ 31055105Storek static int 31155105Storek kbd_translate(register int c, register struct kbd_state *ks) 31255105Storek { 31355105Storek register int down; 31455105Storek 31555105Storek if (ks->kbd_cur == NULL) { 31655105Storek /* 31755105Storek * Do not know how to translate yet. 31855105Storek * We will find out when a RESET comes along. 31955105Storek */ 32055105Storek return (-1); 32155105Storek } 32255105Storek down = !KEY_UP(c); 32355105Storek c = ks->kbd_cur[KEY_CODE(c)]; 32455105Storek if (c & KEY_MAGIC) { 32555105Storek switch (c) { 32655105Storek 32755105Storek case KEY_LSHIFT: 32855105Storek ks->kbd_lshift = down; 32955105Storek break; 33055105Storek 33155105Storek case KEY_RSHIFT: 33255105Storek ks->kbd_rshift = down; 33355105Storek break; 33455105Storek 33555105Storek case KEY_ALLUP: 33655105Storek ks->kbd_anyshift = 0; 33755105Storek ks->kbd_control = 0; 33855105Storek break; 33955105Storek 34055105Storek case KEY_CONTROL: 34155105Storek ks->kbd_control = down; 34255105Storek /* FALLTHROUGH */ 34355105Storek 34455105Storek case KEY_IGNORE: 34555105Storek return (-1); 34655105Storek 34755105Storek default: 34855105Storek panic("kbd_translate"); 34955105Storek } 35055105Storek if (ks->kbd_anyshift) 35155105Storek ks->kbd_cur = ks->kbd_shifted; 35255105Storek else 35355105Storek ks->kbd_cur = ks->kbd_unshifted; 35455105Storek return (-1); 35555105Storek } 35655105Storek if (!down) 35755105Storek return (-1); 35855105Storek if (ks->kbd_control) { 35955105Storek /* control space and unshifted control atsign return null */ 36055105Storek if (c == ' ' || c == '2') 36155105Storek return (0); 36255105Storek /* unshifted control hat */ 36355105Storek if (c == '6') 36455105Storek return ('^' & 0x1f); 36555105Storek /* standard controls */ 36655105Storek if (c >= '@' && c < 0x7f) 36755105Storek return (c & 0x1f); 36855105Storek } 36955105Storek return (c); 37055105Storek } 37155105Storek 37255105Storek void 37355105Storek kbd_rint(register int c) 37455105Storek { 37555105Storek register struct kbd_softc *k = &kbd_softc; 37655105Storek register struct firm_event *fe; 37755105Storek register int put; 37855105Storek 37955105Storek /* 38055105Storek * Reset keyboard after serial port overrun, so we can resynch. 38155105Storek * The printf below should be shortened and/or replaced with a 38255105Storek * call to log() after this is tested (and how will we test it?!). 38355105Storek */ 38455105Storek if (c & (TTY_FE|TTY_PE)) { 38555105Storek printf("keyboard input parity or framing error (0x%x)\n", c); 38655105Storek (void) ttyoutput(KBD_CMD_RESET, k->k_kbd); 38755105Storek (*k->k_kbd->t_oproc)(k->k_kbd); 38855105Storek return; 38955105Storek } 39055105Storek 39155105Storek /* Read the keyboard id if we read a KBD_RESET last time */ 39255105Storek if (k->k_state.kbd_takeid) { 39355105Storek k->k_state.kbd_takeid = 0; 39455105Storek k->k_state.kbd_id = c; 39555105Storek kbd_reset(&k->k_state); 39655105Storek return; 39755105Storek } 39855105Storek 39955105Storek /* If we have been reset, setup to grab the keyboard id next time */ 40055105Storek if (c == KBD_RESET) { 40155105Storek k->k_state.kbd_takeid = 1; 40255105Storek return; 40355105Storek } 40455105Storek 40555105Storek /* 40655105Storek * If /dev/kbd is not connected in event mode, but we are sending 40755105Storek * data to /dev/console, translate and send upstream. Note that 40855105Storek * we will get this while opening /dev/kbd if it is not already 40955105Storek * open and we do not know its type. 41055105Storek */ 41155105Storek if (!k->k_evmode) { 41255105Storek c = kbd_translate(c, &k->k_state); 41355105Storek if (c >= 0 && k->k_cons != NULL) 41455105Storek ttyinput(c, k->k_cons); 41555105Storek return; 41655105Storek } 41755105Storek 41855105Storek /* 41955105Storek * IDLEs confuse the MIT X11R4 server badly, so we must drop them. 42055105Storek * This is bad as it means the server will not automatically resync 42155105Storek * on all-up IDLEs, but I did not drop them before, and the server 42255105Storek * goes crazy when it comes time to blank the screen.... 42355105Storek */ 42455105Storek if (c == KBD_IDLE) 42555105Storek return; 42655105Storek 42755105Storek /* 42855105Storek * Keyboard is generating events. Turn this keystroke into an 42955105Storek * event and put it in the queue. If the queue is full, the 43055105Storek * keystroke is lost (sorry!). 43155105Storek */ 43255105Storek put = k->k_events.ev_put; 43355105Storek fe = &k->k_events.ev_q[put]; 43455105Storek put = (put + 1) % EV_QSIZE; 43555105Storek if (put == k->k_events.ev_get) { 43655105Storek log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */ 43755105Storek return; 43855105Storek } 43955105Storek fe->id = KEY_CODE(c); 44055105Storek fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN; 44155105Storek fe->time = time; 44255105Storek k->k_events.ev_put = put; 44355105Storek EV_WAKEUP(&k->k_events); 44455105Storek } 44555105Storek 44655105Storek int 44755105Storek kbdopen(dev_t dev, int flags, int mode, struct proc *p) 44855105Storek { 44955105Storek int s, error; 45055105Storek 45155105Storek if (kbd_softc.k_events.ev_io) 45255105Storek return (EBUSY); 45355105Storek kbd_softc.k_events.ev_io = p; 45455105Storek /* 45555105Storek * If no console keyboard, tell the device to open up, maybe for 45655105Storek * the first time. Then make sure we know what kind of keyboard 45755105Storek * it is. 45855105Storek */ 45955105Storek if (kbd_softc.k_cons == NULL) 46055105Storek (*kbd_softc.k_open)(kbd_softc.k_kbd); 46155105Storek error = 0; 46255105Storek s = spltty(); 46355105Storek if (kbd_softc.k_state.kbd_cur == NULL) { 46455105Storek (void) ttyoutput(KBD_CMD_RESET, kbd_softc.k_kbd); 46555105Storek error = tsleep((caddr_t)&kbd_softc.k_state, PZERO | PCATCH, 46655105Storek devopn, hz); 46755105Storek if (error == EWOULDBLOCK) /* no response */ 46855105Storek error = ENXIO; 46955105Storek } 47055105Storek splx(s); 47155105Storek if (error) { 47255105Storek kbd_softc.k_events.ev_io = NULL; 47355105Storek return (error); 47455105Storek } 47555105Storek ev_init(&kbd_softc.k_events); 47655105Storek return (0); 47755105Storek } 47855105Storek 47955105Storek int 48055105Storek kbdclose(dev_t dev, int flags, int mode, struct proc *p) 48155105Storek { 48255105Storek 48355105Storek /* 48455105Storek * Turn off event mode, dump the queue, and close the keyboard 48555105Storek * unless it is supplying console input. 48655105Storek */ 48755105Storek kbd_softc.k_evmode = 0; 48855105Storek ev_fini(&kbd_softc.k_events); 48955105Storek if (kbd_softc.k_cons == NULL) 49055105Storek (*kbd_softc.k_close)(kbd_softc.k_kbd); 49155105Storek kbd_softc.k_events.ev_io = NULL; 49255105Storek return (0); 49355105Storek } 49455105Storek 49555105Storek int 49655105Storek kbdread(dev_t dev, struct uio *uio, int flags) 49755105Storek { 49855105Storek 49955105Storek return (ev_read(&kbd_softc.k_events, uio, flags)); 50055105Storek } 50155105Storek 50255105Storek /* this routine should not exist, but is convenient to write here for now */ 50355105Storek int 50455105Storek kbdwrite(dev_t dev, struct uio *uio, int flags) 50555105Storek { 50655105Storek 50755105Storek return (EOPNOTSUPP); 50855105Storek } 50955105Storek 51055105Storek int 51155105Storek kbdioctl(dev_t dev, int cmd, register caddr_t data, int flag, struct proc *p) 51255105Storek { 51355105Storek register struct kbd_softc *k = &kbd_softc; 51455105Storek 51555105Storek switch (cmd) { 51655105Storek 51755105Storek case KIOCTRANS: 51855105Storek if (*(int *)data == TR_UNTRANS_EVENT) 51955105Storek return (0); 52055105Storek break; 52155105Storek 52255105Storek case KIOCGTRANS: 52355105Storek /* 52455105Storek * Get translation mode 52555105Storek */ 52655105Storek *(int *)data = TR_UNTRANS_EVENT; 52755105Storek return (0); 52855105Storek 52955105Storek case KIOCGETKEY: 53055105Storek if (((struct kiockey *)data)->kio_station == 118) { 53155105Storek /* 53255105Storek * This is X11 asking if a type 3 keyboard is 53355105Storek * really a type 3 keyboard. Say yes. 53455105Storek */ 53555105Storek ((struct kiockey *)data)->kio_entry = HOLE; 53655105Storek return (0); 53755105Storek } 53855105Storek break; 53955105Storek 54055105Storek case KIOCCMD: 54155105Storek /* 54255105Storek * ``unimplemented commands are ignored'' (blech) 54355105Storek * so cannot check return value from kbd_docmd 54455105Storek */ 54555105Storek #ifdef notyet 54655105Storek while (kbd_docmd(*(int *)data, 1) == ENOSPC) /*ERESTART?*/ 54755105Storek (void) sleep((caddr_t)&lbolt, TTOPRI); 54855105Storek #else 54955105Storek (void) kbd_docmd(*(int *)data, 1); 55055105Storek #endif 55155105Storek return (0); 55255105Storek 55355105Storek case KIOCTYPE: 55455105Storek *(int *)data = k->k_state.kbd_id; 55555105Storek return (0); 55655105Storek 55755105Storek case KIOCSDIRECT: 55855105Storek k->k_evmode = *(int *)data; 55955105Storek return (0); 56055105Storek 56155105Storek case FIONBIO: /* we will remove this someday (soon???) */ 56255105Storek return (0); 56355105Storek 56455105Storek case FIOASYNC: 56555105Storek k->k_events.ev_async = *(int *)data != 0; 56655105Storek return (0); 56755105Storek 56855105Storek case TIOCSPGRP: 56955105Storek if (*(int *)data != k->k_events.ev_io->p_pgid) 57055105Storek return (EPERM); 57155105Storek return (0); 57255105Storek 57355105Storek default: 57455105Storek return (ENOTTY); 57555105Storek } 57655105Storek 57755105Storek /* 57855105Storek * We identified the ioctl, but we do not handle it. 57955105Storek */ 58055105Storek return (EOPNOTSUPP); /* misuse, but what the heck */ 58155105Storek } 58255105Storek 58355105Storek int 58455105Storek kbdselect(dev_t dev, int rw, struct proc *p) 58555105Storek { 58655105Storek 58755105Storek return (ev_select(&kbd_softc.k_events, rw, p)); 58855105Storek } 58955105Storek 59055105Storek /* 59155105Storek * Execute a keyboard command; return 0 on success. 59255105Storek * If `isuser', force a small delay before output if output queue 59355105Storek * is flooding. (The keyboard runs at 1200 baud, or 120 cps.) 59455105Storek */ 59555105Storek int 59655105Storek kbd_docmd(int cmd, int isuser) 59755105Storek { 59855105Storek register struct tty *tp = kbd_softc.k_kbd; 59955105Storek register struct kbd_softc *k = &kbd_softc; 60055105Storek int s; 60155105Storek 60255105Storek if (tp == NULL) 60355105Storek return (ENXIO); /* ??? */ 60455105Storek switch (cmd) { 60555105Storek 60655105Storek case KBD_CMD_BELL: 60755105Storek case KBD_CMD_NOBELL: 60855105Storek /* Supported by type 2, 3, and 4 keyboards */ 60955105Storek break; 61055105Storek 61155105Storek case KBD_CMD_CLICK: 61255105Storek /* Unsupported by type 2 keyboards */ 61355105Storek if (k->k_state.kbd_id != KB_SUN2) { 61455105Storek k->k_state.kbd_click = 1; 61555105Storek break; 61655105Storek } 61755105Storek return (EINVAL); 61855105Storek 61955105Storek case KBD_CMD_NOCLICK: 62055105Storek /* Unsupported by type 2 keyboards */ 62155105Storek if (k->k_state.kbd_id != KB_SUN2) { 62255105Storek k->k_state.kbd_click = 0; 62355105Storek break; 62455105Storek } 62555105Storek return (EINVAL); 62655105Storek 62755105Storek default: 62855105Storek return (EINVAL); /* ENOTTY? EOPNOTSUPP? */ 62955105Storek } 63055105Storek 63155105Storek if (isuser) { 63255105Storek s = spltty(); 63355105Storek if (tp->t_outq.c_cc > 120) 63455105Storek (void) tsleep((caddr_t)&lbolt, TTIPRI, 63555105Storek ttyout, 0); 63655105Storek splx(s); 63755105Storek } 63855105Storek if (ttyoutput(cmd, tp) >= 0) 63955105Storek return (ENOSPC); /* ERESTART? */ 64055105Storek (*tp->t_oproc)(tp); 64155105Storek return (0); 64255105Storek } 643