diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-06-18 09:45:47 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-06-18 09:45:47 +0000 |
commit | 41ae123ec2d77615cd0b0476ff62564bd7a4865f (patch) | |
tree | ba6a57d3a8d7d725a5e0ae64e8401ed3bea0efb9 /sys/dev/wscons/kbd.c | |
parent | 7a0b7f798c45842a34a4c6413f45e1b3824154a5 (diff) |
sync to 0616, retaining local diffs
Diffstat (limited to 'sys/dev/wscons/kbd.c')
-rw-r--r-- | sys/dev/wscons/kbd.c | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/sys/dev/wscons/kbd.c b/sys/dev/wscons/kbd.c new file mode 100644 index 00000000000..67cd26fcee5 --- /dev/null +++ b/sys/dev/wscons/kbd.c @@ -0,0 +1,334 @@ +/* $NetBSD: kbd.c,v 1.1 1996/04/12 02:00:46 cgd Exp $ */ + +/* + * 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 + */ + +/* + * 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 <machine/vuid_event.h> +#include <machine/kbio.h> /* XXX FOR KIOCSDIRECT */ +#include <machine/wsconsio.h> /* XXX for bell ioctls */ +#include <alpha/wscons/event_var.h> +#include <alpha/wscons/wsconsvar.h> + +struct kbd_softc { + struct device *k_idev; /* the input device */ + struct wscons_idev_spec k_ispec; /* the input device information */ + + int k_evmode; /* set if we should produce events */ + struct evvar k_events; /* event queue state */ + char *k_repeatcp; /* repeated character (string) */ + int k_repeating; /* we've called timeout() */ + int k_repeat_start; /* how long (ms) until repeat */ + int k_repeat_step; /* how long (ms) until more repeats */ + + struct wsconsio_bell_data k_belldata; +} kbd_softc; + +void +kbdattach(idev, ispec) + struct device *idev; + struct wscons_idev_spec *ispec; +{ + register struct kbd_softc *k = &kbd_softc; + + /* + * It would be nice if the repeat rates were in ticks. + * However, if they were, we couldn't set them here, as + * hz might not be set up yet! + */ + k->k_repeat_start = 200; + k->k_repeat_step = 50; + + k->k_belldata.wbd_pitch = 1500; /* 1500 Hz */ + k->k_belldata.wbd_period = 100; /* 100 ms */ + k->k_belldata.wbd_volume = 50; /* 50% volume */ + + k->k_idev = idev; + k->k_ispec = *ispec; +} + +void +kbd_repeat(void *arg) +{ + struct kbd_softc *k = (struct kbd_softc *)arg; + int s = spltty(); + + if (k->k_repeating && k->k_repeatcp != NULL) { + wscons_input(k->k_repeatcp); + timeout(kbd_repeat, k, (hz * k->k_repeat_step) / 1000); + } + splx(s); +} + +void +kbd_input(register int c) +{ + register struct kbd_softc *k = &kbd_softc; + register struct firm_event *fe; + register int put; + char *cp; + + if (k->k_repeating) { + k->k_repeating = 0; + untimeout(kbd_repeat, k); + } + + /* + * If /dev/kbd is not connected in event mode translate and + * send upstream. + */ + if (!k->k_evmode) { + cp = (*k->k_ispec.wi_translate)(k->k_idev, c); + if (cp != NULL) { + wscons_input(cp); + k->k_repeating = 1; + k->k_repeatcp = cp; + timeout(kbd_repeat, k, (hz * k->k_repeat_start) / 1000); + } + return; + } + + /* + * Keyboard is generating events. Turn this keystroke into an + * event and put it in the queue. If the queue is full, the + * keystroke is lost (sorry!). + */ + put = k->k_events.ev_put; + fe = &k->k_events.ev_q[put]; + put = (put + 1) % EV_QSIZE; + if (put == k->k_events.ev_get) { + log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */ + return; + } + fe->id = c & k->k_ispec.wi_keymask; + fe->value = (c & k->k_ispec.wi_keyupmask) != 0 ? VKEY_UP : VKEY_DOWN; + microtime(&fe->time); + k->k_events.ev_put = put; + EV_WAKEUP(&k->k_events); +} + +int +kbdopen(dev_t dev, int flags, int mode, struct proc *p) +{ + int s; + struct tty *tp; + + if (kbd_softc.k_events.ev_io) + return (EBUSY); + kbd_softc.k_events.ev_io = p; + ev_init(&kbd_softc.k_events); + kbd_softc.k_evmode = 1; + return (0); +} + +int +kbdclose(dev_t dev, int flags, int mode, struct proc *p) +{ + + /* + * Turn off event mode, dump the queue, and close the keyboard + * unless it is supplying console input. + */ + kbd_softc.k_evmode = 0; + ev_fini(&kbd_softc.k_events); + kbd_softc.k_events.ev_io = NULL; + return (0); +} + +int +kbdread(dev_t dev, struct uio *uio, int flags) +{ + + return (ev_read(&kbd_softc.k_events, uio, flags)); +} + +/* this routine should not exist, but is convenient to write here for now */ +int +kbdwrite(dev_t dev, struct uio *uio, int flags) +{ + + return (EOPNOTSUPP); +} + +int +kbdioctl(dev_t dev, u_long cmd, register caddr_t data, int flag, struct proc *p) +{ + struct kbd_softc *k = &kbd_softc; + struct wsconsio_bell_data *wbd; + int rv; + + rv = ENOTTY; + switch (cmd) { +#if 0 + case KIOCSDIRECT: + k->k_evmode = *(int *)data; + return (0); +#endif + + case FIONBIO: /* we will remove this someday (soon???) */ + return (0); + + case FIOASYNC: + k->k_events.ev_async = *(int *)data != 0; + return (0); + + case TIOCSPGRP: + if (*(int *)data != k->k_events.ev_io->p_pgid) + return (EPERM); + return (0); + + case WSCONSIO_BELL: + if (k->k_ispec.wi_bell != NULL) + (*k->k_ispec.wi_bell)(k->k_idev, &k->k_belldata); + return (0); + + case WSCONSIO_COMPLEXBELL: + if (k->k_ispec.wi_bell != NULL) { + wbd = (struct wsconsio_bell_data *)data; + if ((wbd->wbd_flags & WSCONSIO_BELLDATA_PITCH) == 0) + wbd->wbd_pitch = k->k_belldata.wbd_pitch; + if ((wbd->wbd_flags & WSCONSIO_BELLDATA_PERIOD) == 0) + wbd->wbd_period = k->k_belldata.wbd_period; + if ((wbd->wbd_flags & WSCONSIO_BELLDATA_VOLUME) == 0) + wbd->wbd_volume = k->k_belldata.wbd_volume; + + (*k->k_ispec.wi_bell)(k->k_idev, wbd); + } + return (0); + + case WSCONSIO_SETBELL: + wbd = (struct wsconsio_bell_data *)data; + if ((wbd->wbd_flags & WSCONSIO_BELLDATA_PITCH) != 0) + k->k_belldata.wbd_pitch = wbd->wbd_pitch; + if ((wbd->wbd_flags & WSCONSIO_BELLDATA_PERIOD) != 0) + k->k_belldata.wbd_period = wbd->wbd_period; + if ((wbd->wbd_flags & WSCONSIO_BELLDATA_VOLUME) != 0) + k->k_belldata.wbd_volume = wbd->wbd_volume; + return (0); + + case WSCONSIO_GETBELL: + wbd = (struct wsconsio_bell_data *)data; + wbd->wbd_flags = WSCONSIO_BELLDATA_PITCH | + WSCONSIO_BELLDATA_PERIOD | WSCONSIO_BELLDATA_VOLUME; + wbd->wbd_pitch = k->k_belldata.wbd_pitch; + wbd->wbd_period = k->k_belldata.wbd_period; + wbd->wbd_volume = k->k_belldata.wbd_volume ; + return (0); + +#if 0 /* XXX */ + /* XXX KEY-REPEAT RATE SETTING */ +#endif /* XXX */ + + default: + if (k->k_ispec.wi_ioctl != NULL) + rv = (*k->k_ispec.wi_ioctl)(k->k_idev, cmd, data, + flag, p); + } + return (rv); +} + +int +kbdselect(dev_t dev, int rw, struct proc *p) +{ + + return (ev_select(&kbd_softc.k_events, rw, p)); +} + +/* Ring the console bell. (For wscons terminal emulator and other code) */ +void +wscons_kbd_bell() +{ + struct kbd_softc *k = &kbd_softc; + + if (k->k_ispec.wi_bell != NULL) + (*k->k_ispec.wi_bell)(k->k_idev, &k->k_belldata); +} + +/* + * Console handling functions. + */ + +int +kbd_cngetc(dev) + dev_t dev; +{ + struct kbd_softc *k = &kbd_softc; + + if (kbd_softc.k_evmode) /* XXX? */ + return 0; + if (k->k_ispec.wi_getc != NULL) + return (*k->k_ispec.wi_getc)(k->k_idev); + else + return 0; +} + +void +kbd_cnpollc(dev, on) + dev_t dev; + int on; +{ + struct kbd_softc *k = &kbd_softc; + + if (kbd_softc.k_evmode) /* XXX? */ + return; + if (k->k_ispec.wi_pollc != NULL) + (*k->k_ispec.wi_pollc)(k->k_idev, on); +} |