Add the wsmux pseudo device.

This commit is contained in:
augustss 1999-07-29 18:20:02 +00:00
parent d7f9efdafc
commit 3d3f77c49e
15 changed files with 1337 additions and 153 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.94 1999/07/17 07:09:40 itojun Exp $
# $NetBSD: Makefile,v 1.95 1999/07/29 18:22:03 augustss Exp $
# @(#)Makefile 8.1 (Berkeley) 6/18/93
MAN= ahb.4 ahc.4 aria.4 atalk.4 audio.4 bha.4 bpf.4 ccd.4 cd.4 ch.4 \
@ -10,8 +10,8 @@ MAN= ahb.4 ahc.4 aria.4 atalk.4 audio.4 bha.4 bpf.4 ccd.4 cd.4 ch.4 \
pcscp.4 pms.4 ppp.4 pty.4 puc.4 qsphy.4 raid.4 rnd.4 route.4 rtpphy.4 \
scsi.4 sd.4 sl.4 sm.4 spp.4 sqphy.4 ss.4 st.4 sv.4 strip.4 tb.4 tcp.4 \
termios.4 tl.4 tlphy.4 tp.4 tr.4 tty.4 tun.4 udp.4 uha.4 uk.4 unix.4 \
vga.4 vnd.4 wd.4 wdc.4 wscons.4 wsdisplay.4 wskbd.4 wsmouse.4 ym.4 \
zstty.4
vga.4 vnd.4 wd.4 wdc.4 wscons.4 wsdisplay.4 wskbd.4 wsmouse.4 wsmux.4 \
ym.4 zstty.4
# USB devices
MAN+= uaudio.4 ugen.4 uhid.4 ukbd.4 ulpt.4 ums.4 usb.4

View File

@ -1,4 +1,4 @@
.\" $NetBSD: wscons.4,v 1.8 1999/04/13 20:25:29 augustss Exp $
.\" $NetBSD: wscons.4,v 1.9 1999/07/29 18:22:04 augustss Exp $
.\"
.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -49,9 +49,11 @@
.Cd options WSDISPLAY_COMPAT_USL
.Cd options WSDISPLAY_COMPAT_RAWKBD
.Cd wsdisplay* at ...
.Cd wskbd* at ...
.Cd wsmouse* at ...
.Cd "wsdisplay* at ..."
.Cd "wskbd* at ... mux N"
.Cd "wsmouse* at ... mux N"
.Cd pseudo-device wsmux N
.Pp
.Sh DESCRIPTION
The
@ -67,6 +69,9 @@ hardware support for display adapters, keyboards and mice, see
.Xr wskbd 4 , and
.Xr wsmouse 4
.It
input event multiplexor, see
.Xr wsmux 4
.It
terminal emulation modules (see below), and
.It
compatibility options to support control operations and other low-level
@ -161,12 +166,12 @@ emulator.
.El
.Pp
The
.Cd WSEMUL_DEFAULT
.Va WSEMUL_DEFAULT
kernel option allows to select one of the described terminal options
as default choice. The default gets into effect in kernel startup, i.e.
for the operating system console or additional screens allocated
through the
.Cd WSDISPLAY_DEFAULTSCREENS
.Va WSDISPLAY_DEFAULTSCREENS
option (see
.Xr wsdisplay 4
), or if no emulation type was passed to the
@ -254,6 +259,7 @@ This man page is still extremely incomplete.
.Xr wsdisplay 4 ,
.Xr wskbd 4 ,
.Xr wsmouse 4 ,
.Xr wsmux 4 ,
.Xr wsconscfg 8 ,
.Xr wsconsctl 8 ,
.Xr wsfontload 8

View File

@ -1,4 +1,4 @@
.\" $NetBSD: wskbd.4,v 1.2 1999/04/08 16:29:56 drochner Exp $
.\" $NetBSD: wskbd.4,v 1.3 1999/07/29 18:22:04 augustss Exp $
.Dd March 20, 1999
.Os
@ -8,13 +8,13 @@
.Nd generic keyboard support in wscons
.Sh SYNOPSIS
.Cd "wskbd* at pckbd? console ?"
.Cd "wskbd* at pckbd? console ? mux 1"
(standard PC keyboard)
.Cd "wskbd* at ukbd? console ?"
.Cd "wskbd* at ukbd? console ? mux 1"
(USB keyboard)
.Cd "wskbd0 at akbd? console ?"
.Cd "wskbd0 at akbd? console ? mux 1"
(Apple ADB keyboard)
.Cd "wskbd0 at nextkbd? console ?"
.Cd "wskbd0 at nextkbd? console ? mux 1"
(NeXT keyboard)
.Sh DESCRIPTION
@ -85,19 +85,9 @@ wskbd device instance.
.Pa /usr/include/dev/wscons/wsconsio.h .
.El
.Sh BUGS
.Dq wskbd
devices are connected logically to
.Dq wsdisplay
devices at boot time. There is little support for hot insertion and
removal. It is not possible to feed a
.Dq wsdisplay
from multiple
.Dq wskbd
devices.
.Sh SEE ALSO
.Xr wscons 4 ,
.Xr wsconsctl 8 ,
.Xr wsmux 4 ,
.Xr pckbd 4 ,
.Xr ukbd 4

View File

@ -1,4 +1,4 @@
.\" $NetBSD: wsmouse.4,v 1.1 1999/03/22 19:15:03 drochner Exp $
.\" $NetBSD: wsmouse.4,v 1.2 1999/07/29 18:22:04 augustss Exp $
.Dd March 20, 1999
.Os
@ -8,19 +8,19 @@
.Nd generic mouse support in wscons
.Sh SYNOPSIS
.Cd "wsmouse* at pms?"
.Cd "wsmouse* at pms? mux 0"
(PS/2 mouse)
.Cd "wsmouse* at pmsi?"
.Cd "wsmouse* at pmsi? mux 0"
(
.Dq Intellimouse
-compatible wheel mouse with PS/2 interface)
.Cd "wsmouse* at ums?"
.Cd "wsmouse* at ums? mux 0"
(USB mouse)
.Cd "wsmouse* at lms?"
.Cd "wsmouse* at lms? mux 0"
(Logitech bus mouse, i386 only)
.Cd "wsmouse* at mms?"
.Cd "wsmouse* at mms? mux 0"
(Microsoft InPort mouse, i386 only)
.Cd "wsmouse0 at ams?"
.Cd "wsmouse0 at ams? mux 0"
(Apple ADB mouse)
.Sh DESCRIPTION
@ -57,6 +57,7 @@ removal.
.Sh SEE ALSO
.Xr wscons 4 ,
.Xr wsconsctl 8 ,
.Xr wsmux 4 ,
.Xr pms 4 ,
.Xr lms 4 ,
.Xr mms 4 ,

95
share/man/man4/wsmux.4 Normal file
View File

@ -0,0 +1,95 @@
.\" $NetBSD: wsmux.4,v 1.1 1999/07/29 18:22:04 augustss Exp $
.\"
.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" 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 NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
.\"
.Dd July 26, 1999
.Dt WSMUX 4
.Os
.Sh NAME
.Nm wsmux
.Nd console keyboard/mouse multiplexor
.Sh SYNOPSIS
.Cd "wskbd* at ... mux N"
.Cd "wsmouse* at ... mux N"
.Cd pseudo-device wsmux N
.Pp
.Sh DESCRIPTION
The
.Nm
is a pseudo-device driver that allows several
.Xr wscons 4
input devices to have their events multiplexed into one stream.
.Pp
The typical usage for this device is to have two multiplexors, one
for mouse events and one for keyboard events. All
.Xr wsmouse 4
devices should direct their events to the mouse mux (normally 0)
and all keyboard devices, except the console, should direct their
events to the keyboard mux (normally 1). A device will
send its events to the mux indicated my the
.Va mux
locator. If none is given the device will not use a multiplexor.
The keyboard multiplexor should be connected to the display, using
the
.Xr wsconscfg 8
command. It will then recieve all keystrokes from all keyboards
and, furthermore, keyboards can be dynamically attached and detached without
further user interaction.
In a similar way, the window system will open the mouse multiplexor
and recieve all mouse events; mice can also be dynamically attached
and detached.
.Pp
It is also possible to inject events into a multiplexor from a
user program. This is used by the
.Xr moused 8
deamon to take data from a mouse connected to a serial port and
make it appear on the standard mouse mux.
.Pp
.Sh FILES
.Bl -item
.It
.Pa /dev/wsmouse
.It
.Pa /dev/wskbd
.It
.Pa /usr/include/dev/wscons/wsconsio.h .
.El
.Sh SEE ALSO
.Xr moused 8 ,
.Xr wscons 4 ,
.Xr wsdisplay 4 ,
.Xr wskbd 4 ,
.Xr wsmouse 4 ,
.Xr wsconscfg 8 ,
.Xr wsconsctl 8 ,
.Xr wsfontload 8

View File

@ -1,4 +1,4 @@
# $NetBSD: files.wscons,v 1.15 1999/05/15 14:22:46 drochner Exp $
# $NetBSD: files.wscons,v 1.16 1999/07/29 18:20:02 augustss Exp $
#
# "Workstation Console" glue; attaches frame buffer to emulator & keyboard,
@ -52,3 +52,6 @@ file dev/rcons/raster_op.c wsrasteremulops
file dev/rcons/raster_text.c wsrasteremulops
file dev/wscons/wscons_rinit.c wsrasteremulops
file dev/wscons/wscons_rops.c wsrasteremulops
defpseudo wsmux
file dev/wscons/wsmux.c wsmux | wsdisplay needs-count

View File

@ -1,4 +1,4 @@
/* $NetBSD: wscons_callbacks.h,v 1.9 1999/05/15 14:22:46 drochner Exp $ */
/* $NetBSD: wscons_callbacks.h,v 1.10 1999/07/29 18:20:02 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -53,12 +53,7 @@ void wsdisplay_set_cons_kbd __P((int (*get)(dev_t),
/*
* Calls to the keyboard interface from the glue code.
*/
int wskbd_set_display __P((int, struct device *, struct device **));
struct device *wskbd_set_console_display __P((struct device *));
struct wsmux_softc;
struct device *wskbd_set_console_display
__P((struct device *, struct wsmux_softc *));
int wskbd_pickfree __P((void));
/*
* Calls to the keyboard interface from the display interface.
*/
int wskbd_displayioctl __P((struct device *dev, u_long cmd,
caddr_t data, int flag, struct proc *p));

View File

@ -1,4 +1,4 @@
/* $NetBSD: wsconsio.h,v 1.18 1999/05/15 14:22:46 drochner Exp $ */
/* $NetBSD: wsconsio.h,v 1.19 1999/07/29 18:20:02 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -295,15 +295,36 @@ struct wsdisplay_usefontdata {
};
#define WSDISPLAYIO_USEFONT _IOW('W', 80, struct wsdisplay_usefontdata)
/* Replaced by WSMUX_{ADD,REMOVE}_DEVICE */
struct wsdisplay_kbddata {
int op;
#define WSDISPLAY_KBD_ADD 0
#define WSDISPLAY_KBD_DEL 1
#define _O_WSDISPLAY_KBD_ADD 0
#define _O_WSDISPLAY_KBD_DEL 1
int idx;
};
#define WSDISPLAYIO_SETKEYBOARD _IOWR('W', 81, struct wsdisplay_kbddata)
#define _O_WSDISPLAYIO_SETKEYBOARD _IOWR('W', 81, struct wsdisplay_kbddata)
/* XXX NOT YET DEFINED */
/* Mapping information retrieval. */
/* Mux ioctls (96 - 127) */
#define WSMUX_INJECTEVENT _IOW('W', 96, struct wscons_event)
struct wsmux_device {
int type;
#define WSMUX_MOUSE 1
#define WSMUX_KBD 2
#define WSMUX_MUX 3
int idx;
};
#define WSMUX_ADD_DEVICE _IOW('W', 97, struct wsmux_device)
#define WSMUX_REMOVE_DEVICE _IOW('W', 98, struct wsmux_device)
#define WSMUX_MAXDEV 32
struct wsmux_device_list {
int ndevices;
struct wsmux_device devices[WSMUX_MAXDEV];
};
#define WSMUX_LIST_DEVICES _IOWR('W', 99, struct wsmux_device_list)
#endif /* _DEV_WSCONS_WSCONSIO_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: wsdisplay.c,v 1.25 1999/05/17 16:53:43 drochner Exp $ */
/* $NetBSD: wsdisplay.c,v 1.26 1999/07/29 18:20:02 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -33,7 +33,7 @@
static const char _copyright[] __attribute__ ((unused)) =
"Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.";
static const char _rcsid[] __attribute__ ((unused)) =
"$NetBSD: wsdisplay.c,v 1.25 1999/05/17 16:53:43 drochner Exp $";
"$NetBSD: wsdisplay.c,v 1.26 1999/07/29 18:20:02 augustss Exp $";
#include <sys/param.h>
#include <sys/conf.h>
@ -60,6 +60,12 @@ static const char _rcsid[] __attribute__ ((unused)) =
#include "opt_wsdisplay_compat.h"
#include "wskbd.h"
#include "wsmux.h"
#if NWSKBD > 0
#include <dev/wscons/wseventvar.h>
#include <dev/wscons/wsmuxvar.h>
#endif
struct wsscreen_internal {
const struct wsdisplay_emulops *emulops;
@ -124,7 +130,7 @@ struct wsdisplay_softc {
int sc_screenwanted, sc_oldscreen; /* valid with SC_SWITCHPENDING */
#if NWSKBD > 0
struct device *sc_kbddv;
struct wsmux_softc *sc_muxdv;
#ifdef WSDISPLAY_COMPAT_RAWKBD
int sc_rawkbd;
#endif
@ -566,6 +572,14 @@ wsdisplay_common_attach(sc, console, scrdata, accessops, accesscookie)
void *accesscookie;
{
int i = 0;
#if NWSKBD > 0
struct device *dv;
sc->sc_muxdv = wsmux_create("dmux", sc->sc_dv.dv_unit);
if (!sc->sc_muxdv)
panic("wsdisplay_common_attach: no memory\n");
sc->sc_muxdv->sc_displaydv = &sc->sc_dv;
#endif
sc->sc_isconsole = console;
@ -581,8 +595,8 @@ wsdisplay_common_attach(sc, console, scrdata, accessops, accesscookie)
wsdisplay_console_conf.wsemul->name);
#if NWSKBD > 0
if ((sc->sc_kbddv = wskbd_set_console_display(&sc->sc_dv)))
printf(", using %s", sc->sc_kbddv->dv_xname);
if ((dv = wskbd_set_console_display(&sc->sc_dv, sc->sc_muxdv)))
printf(", using %s", dv->dv_xname);
#endif
sc->sc_focusidx = 0;
@ -861,13 +875,13 @@ wsdisplayioctl(dev, cmd, data, flag, p)
/* do the line discipline ioctls first */
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
if (error >= 0)
return error;
return (error);
/* printf("tty\n"); */
/* then the tty ioctls */
error = ttioctl(tp, cmd, data, flag, p);
if (error >= 0)
return error;
return (error);
}
#ifdef WSDISPLAY_COMPAT_USL
@ -894,23 +908,20 @@ wsdisplay_internal_ioctl(sc, scr, cmd, data, flag, p)
struct wsdisplay_font fd;
#if NWSKBD > 0
if (sc->sc_kbddv != NULL) {
/* check ioctls for keyboard */
#ifdef WSDISPLAY_COMPAT_RAWKBD
switch (cmd) {
case WSKBDIO_SETMODE:
scr->scr_rawkbd = (*(int *)data == WSKBD_RAW);
return (wsdisplay_update_rawkbd(sc, scr));
case WSKBDIO_GETMODE:
*(int *)data = (scr->scr_rawkbd ?
WSKBD_RAW : WSKBD_TRANSLATED);
return (0);
}
#endif
error = wskbd_displayioctl(sc->sc_kbddv, cmd, data, flag, p);
if (error >= 0)
return error;
switch (cmd) {
case WSKBDIO_SETMODE:
scr->scr_rawkbd = (*(int *)data == WSKBD_RAW);
return (wsdisplay_update_rawkbd(sc, scr));
case WSKBDIO_GETMODE:
*(int *)data = (scr->scr_rawkbd ?
WSKBD_RAW : WSKBD_TRANSLATED);
return (0);
}
#endif
error = wsmux_displayioctl(&sc->sc_muxdv->sc_dv, cmd, data, flag, p);
if (error >= 0)
return (error);
#endif /* NWSKBD > 0 */
switch (cmd) {
@ -972,8 +983,8 @@ wsdisplay_cfg_ioctl(sc, cmd, data, flag, p)
int error;
char *type, typebuf[16], *emul, emulbuf[16];
void *buf;
#if NWSKBD > 0
struct device *kbddv;
#if defined(COMPAT_14) && NWSKBD > 0
struct wsmux_device wsmuxdata;
#endif
switch (cmd) {
@ -988,7 +999,7 @@ wsdisplay_cfg_ioctl(sc, cmd, data, flag, p)
} else
type = 0;
if (d->emul) {
error = copyinstr(d->emul, emulbuf, sizeof(emulbuf), 0);
error = copyinstr(d->emul, emulbuf, sizeof(emulbuf),0);
if (error)
return (error);
emul = emulbuf;
@ -1028,37 +1039,43 @@ wsdisplay_cfg_ioctl(sc, cmd, data, flag, p)
return (error);
#if NWSKBD > 0
case WSDISPLAYIO_SETKEYBOARD:
#ifdef COMPAT_14
case _O_WSDISPLAYIO_SETKEYBOARD:
#define d ((struct wsdisplay_kbddata *)data)
switch (d->op) {
case WSDISPLAY_KBD_ADD:
if (sc->sc_kbddv)
return (EBUSY);
case _O_WSDISPLAY_KBD_ADD:
if (d->idx == -1) {
d->idx = wskbd_pickfree();
if (d->idx == -1)
return (ENXIO);
}
error = wskbd_set_display(d->idx, &sc->sc_dv, &kbddv);
if (error)
return (error);
sc->sc_kbddv = kbddv;
return (0);
case WSDISPLAY_KBD_DEL:
if (sc->sc_kbddv == NULL)
return (ENXIO);
if (d->idx == -1)
d->idx = sc->sc_kbddv->dv_unit;
error = wskbd_set_display(d->idx, 0, 0);
if (error)
return (error);
sc->sc_kbddv = NULL;
return (0);
wsmuxdata.type = WSMUX_KBD;
wsmuxdata.idx = d->idx;
return (wsmuxdoioctl(&sc->sc_muxdv->sc_dv,
WSMUX_ADD_DEVICE,
(caddr_t)&wsmuxdata, flag, p));
case _O_WSDISPLAY_KBD_DEL:
wsmuxdata.type = WSMUX_KBD;
wsmuxdata.idx = d->idx;
return (wsmuxdoioctl(&sc->sc_muxdv->sc_dv,
WSMUX_REMOVE_DEVICE,
(caddr_t)&wsmuxdata, flag, p));
default:
return (EINVAL);
}
#undef d
return (0);
#endif
case WSMUX_ADD_DEVICE:
#define d ((struct wsmux_device *)data)
if (d->idx == -1 && d->type == WSMUX_KBD)
d->idx = wskbd_pickfree();
#undef d
/* fall into */
case WSMUX_INJECTEVENT:
case WSMUX_REMOVE_DEVICE:
case WSMUX_LIST_DEVICES:
return (wsmuxdoioctl(&sc->sc_muxdv->sc_dv, cmd, data, flag,p));
#endif /* NWSKBD > 0 */
}
@ -1289,15 +1306,14 @@ wsdisplay_update_rawkbd(sc, scr)
raw = (scr ? scr->scr_rawkbd : 0);
if (!sc->sc_kbddv ||
scr != sc->sc_focus ||
if (scr != sc->sc_focus ||
sc->sc_rawkbd == raw) {
splx(s);
return (0);
}
data = (raw ? WSKBD_RAW : WSKBD_TRANSLATED);
error = wskbd_displayioctl(sc->sc_kbddv, WSKBDIO_SETMODE,
data = raw ? WSKBD_RAW : WSKBD_TRANSLATED;
error = wsmux_displayioctl(&sc->sc_muxdv->sc_dv, WSKBDIO_SETMODE,
(caddr_t)&data, 0, 0);
if (!error)
sc->sc_rawkbd = raw;
@ -1609,7 +1625,8 @@ wsdisplay_set_console_kbd(kbddv)
{
if (!wsdisplay_console_device)
return (0);
wsdisplay_console_device->sc_kbddv = kbddv;
if (wskbd_add_mux(kbddv->dv_unit, wsdisplay_console_device->sc_muxdv))
return (0);
return (&wsdisplay_console_device->sc_dv);
}
#endif /* NWSKBD > 0 */

View File

@ -1,4 +1,4 @@
/* $NetBSD: wskbd.c,v 1.26 1999/07/06 07:42:23 augustss Exp $ */
/* $NetBSD: wskbd.c,v 1.27 1999/07/29 18:20:03 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -36,7 +36,7 @@
static const char _copyright[] __attribute__ ((unused)) =
"Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.";
static const char _rcsid[] __attribute__ ((unused)) =
"$NetBSD: wskbd.c,v 1.26 1999/07/06 07:42:23 augustss Exp $";
"$NetBSD: wskbd.c,v 1.27 1999/07/29 18:20:03 augustss Exp $";
/*
* Copyright (c) 1992, 1993
@ -114,6 +114,18 @@ static const char _rcsid[] __attribute__ ((unused)) =
#include "opt_wsdisplay_compat.h"
#include "wsdisplay.h"
#include "wsmux.h"
#ifdef WSKBD_DEBUG
#define DPRINTF(x) if (wskbddebug) printf x
int wskbddebug = 0;
#else
#define DPRINTF(x)
#endif
#if NWSMUX > 0 || NWSDISPLAY > 0
#include <dev/wscons/wsmuxvar.h>
#endif
struct wskbd_internal {
const struct wskbd_mapdata *t_keymap;
@ -161,6 +173,9 @@ struct wskbd_softc {
int sc_refcnt;
u_char sc_dying; /* device is being detached */
#if NWSMUX > 0 || NWSDISPLAY > 0
struct wsmux_softc *sc_mux;
#endif
};
#define MOD_SHIFT_L (1 << 0)
@ -191,6 +206,10 @@ void wskbd_attach __P((struct device *, struct device *, void *));
int wskbd_detach __P((struct device *, int));
int wskbd_activate __P((struct device *, enum devact));
static int wskbd_displayioctl
__P((struct device *, u_long, caddr_t, int, struct proc *p));
int wskbd_set_display __P((struct device *, struct wsmux_softc *));
static inline void update_leds __P((struct wskbd_internal *));
static inline void update_modifier __P((struct wskbd_internal *, u_int, int, int));
static int internal_command __P((struct wskbd_softc *, u_int *, keysym_t));
@ -203,6 +222,10 @@ static void wskbd_holdscreen __P((struct wskbd_softc *, int));
int wskbd_do_ioctl __P((struct wskbd_softc *, u_long, caddr_t,
int, struct proc *));
int wskbddoclose __P((struct device *, int, int, struct proc *));
int wskbddoioctl __P((struct device *, u_long, caddr_t, int,
struct proc *));
struct cfattach wskbd_ca = {
sizeof (struct wskbd_softc), wskbd_match, wskbd_attach,
wskbd_detach, wskbd_activate
@ -242,6 +265,11 @@ struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data = {
cdev_decl(wskbd);
struct wsmuxops wskbd_muxops = {
wskbdopen, wskbddoclose, wskbddoioctl, wskbd_displayioctl,
wskbd_set_display
};
#if NWSDISPLAY > 0
static void wskbd_repeat __P((void *v));
#endif
@ -301,26 +329,24 @@ wskbd_attach(parent, self, aux)
{
struct wskbd_softc *sc = (struct wskbd_softc *)self;
struct wskbddev_attach_args *ap = aux;
#if NWSMUX > 0 || NWSDISPLAY > 0
int mux;
#endif
#if NWSDISPLAY > 0
sc->sc_displaydv = NULL;
#endif
sc->sc_isconsole = ap->console;
if (ap->console) {
KASSERT(wskbd_console_initted);
KASSERT(wskbd_console_device == NULL);
wskbd_console_device = sc;
printf(": console keyboard");
#if NWSDISPLAY > 0
if ((sc->sc_displaydv = wsdisplay_set_console_kbd(self)))
printf(", using %s", sc->sc_displaydv->dv_xname);
#endif
#if NWSMUX > 0 || NWSDISPLAY > 0
mux = sc->sc_dv.dv_cfdata->wskbddevcf_mux;
if (sc->sc_isconsole && mux != WSKBDDEVCF_MUX_DEFAULT) {
printf(" (mux ignored for console)");
mux = WSKBDDEVCF_MUX_DEFAULT;
}
printf("\n");
if (mux != WSKBDDEVCF_MUX_DEFAULT)
printf(" mux %d", mux);
#endif
if (ap->console) {
sc->id = &wskbd_console_data;
@ -349,6 +375,28 @@ wskbd_attach(parent, self, aux)
/* set default bell and key repeat data */
sc->sc_bell_data = wskbd_default_bell_data;
sc->sc_keyrepeat_data = wskbd_default_keyrepeat_data;
if (ap->console) {
KASSERT(wskbd_console_initted);
KASSERT(wskbd_console_device == NULL);
wskbd_console_device = sc;
printf(": console keyboard");
#if NWSDISPLAY > 0
if ((sc->sc_displaydv = wsdisplay_set_console_kbd(self)))
printf(", using %s", sc->sc_displaydv->dv_xname);
#endif
}
printf("\n");
#if NWSMUX > 0 || NWSDISPLAY > 0
if (mux != WSKBDDEVCF_MUX_DEFAULT)
wsmux_attach(mux, WSMUX_KBD, &sc->sc_dv, &sc->sc_events,
&sc->sc_mux, &wskbd_muxops);
#endif
}
void
@ -408,11 +456,10 @@ wskbd_activate(self, act)
/*
* Detach a keyboard. To keep track of users of the softc we keep
* a reference count that's incremented while inside, e.g., read.
* If the mouse is active and the reference count is > 0 (0 is the
* If the keyboard is active and the reference count is > 0 (0 is the
* normal state) we post an event and then wait for the process
* that had the reference to wake us up again. Then we blow away the
* vnode and return (which will deallocate the softc).
* XXX what should we do if we are connected to a display?
*/
int
wskbd_detach(self, flags)
@ -423,6 +470,13 @@ wskbd_detach(self, flags)
struct wseventvar *evar;
int maj, mn;
int s;
#if NWSMUX > 0 || NWSDISPLAY > 0
int mux;
mux = sc->sc_dv.dv_cfdata->wskbddevcf_mux;
if (mux != WSMOUSEDEVCF_MUX_DEFAULT)
wsmux_detach(mux, &sc->sc_dv);
#endif
evar = &sc->sc_events;
if (evar->io) {
@ -503,7 +557,12 @@ wskbd_input(dev, type, value)
if (!sc->sc_ready)
return;
evar = &sc->sc_events;
#if NWSMUX > 0 || NWSDISPLAY > 0
if (sc->sc_mux)
evar = &sc->sc_mux->sc_events;
else
#endif
evar = &sc->sc_events;
put = evar->put;
ev = &evar->q[put];
@ -599,6 +658,11 @@ wskbdopen(dev, flags, mode, p)
if (sc->sc_dying)
return (EIO);
#if NWSMUX > 0 || NWSDISPLAY > 0
if (sc->sc_mux)
return (EBUSY);
#endif
if (sc->sc_events.io) /* and that it's not in use */
return (EBUSY);
@ -618,7 +682,16 @@ wskbdclose(dev, flags, mode, p)
int flags, mode;
struct proc *p;
{
struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
return (wskbddoclose(wskbd_cd.cd_devs[minor(dev)], flags, mode, p));
}
int
wskbddoclose(dv, flags, mode, p)
struct device *dv;
int flags, mode;
struct proc *p;
{
struct wskbd_softc *sc = (struct wskbd_softc *)dv;
sc->sc_ready = 0; /* stop accepting events */
sc->sc_translating = 1;
@ -659,7 +732,19 @@ wskbdioctl(dev, cmd, data, flag, p)
int flag;
struct proc *p;
{
struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
return (wskbddoioctl(wskbd_cd.cd_devs[minor(dev)], cmd, data, flag,p));
}
/* A wrapper around the ioctl() workhorse to make reference counting easy. */
int
wskbddoioctl(dv, cmd, data, flag, p)
struct device *dv;
u_long cmd;
caddr_t data;
int flag;
struct proc *p;
{
struct wskbd_softc *sc = (struct wskbd_softc *)dv;
int error;
sc->sc_refcnt++;
@ -708,7 +793,7 @@ wskbd_do_ioctl(sc, cmd, data, flag, p)
* WSKBDIO ioctls, handled in both emulation mode and in ``raw'' mode.
* Some of these have no real effect in raw mode, however.
*/
int
static int
wskbd_displayioctl(dev, cmd, data, flag, p)
struct device *dev;
u_long cmd;
@ -912,45 +997,98 @@ wskbd_pickfree()
return (-1);
}
int
wskbd_set_display(idx, displaydv, kbddv)
int idx;
struct device *displaydv, **kbddv;
struct device *
wskbd_set_console_display(displaydv, muxsc)
struct device *displaydv;
struct wsmux_softc *muxsc;
{
struct wskbd_softc *sc;
struct wskbd_softc *sc = wskbd_console_device;
if (idx >= wskbd_cd.cd_ndevs || /* make sure it was attached */
(sc = wskbd_cd.cd_devs[idx]) == NULL)
return (ENXIO);
if (!sc)
return (0);
sc->sc_displaydv = displaydv;
(void)wsmux_attach_sc(muxsc, WSMUX_KBD, &sc->sc_dv, &sc->sc_events,
&sc->sc_mux, &wskbd_muxops);
return (&sc->sc_dv);
}
int
wskbd_set_display(dv, muxsc)
struct device *dv;
struct wsmux_softc *muxsc;
{
struct wskbd_softc *sc = (struct wskbd_softc *)dv;
struct device *displaydv = muxsc ? muxsc->sc_displaydv : 0;
struct device *odisplaydv;
int error;
DPRINTF(("wskbd_set_display: %s mux=%p disp=%p odisp=%p cons=%d\n",
dv->dv_xname, muxsc, sc->sc_displaydv, displaydv,
sc->sc_isconsole));
if (sc->sc_isconsole)
return (EBUSY);
if (displaydv) {
if (sc->sc_displaydv)
return (EBUSY);
printf("%s: connecting to %s\n",
sc->sc_dv.dv_xname, displaydv->dv_xname);
} else {
if (sc->sc_displaydv == NULL)
return (ENXIO);
printf("%s: disconnecting\n", sc->sc_dv.dv_xname);
}
odisplaydv = sc->sc_displaydv;
sc->sc_displaydv = displaydv;
wskbd_enable(sc, displaydv != NULL);
if (kbddv)
*kbddv = &sc->sc_dv;
error = wskbd_enable(sc, displaydv != NULL);
if (error) {
sc->sc_displaydv = odisplaydv;
return (error);
}
if (displaydv)
printf("%s: connecting to %s\n",
sc->sc_dv.dv_xname, displaydv->dv_xname);
else
printf("%s: disconnecting from %s\n",
sc->sc_dv.dv_xname, odisplaydv->dv_xname);
return (0);
}
struct device *
wskbd_set_console_display(displaydv)
struct device *displaydv;
int
wskbd_add_mux(unit, muxsc)
int unit;
struct wsmux_softc *muxsc;
{
if (!wskbd_console_device)
return (0);
wskbd_console_device->sc_displaydv = displaydv;
return (&wskbd_console_device->sc_dv);
struct wskbd_softc *sc;
DPRINTF(("wskbd_add_mux: %d %s %p\n", unit, muxsc->sc_dv.dv_xname,
muxsc->sc_displaydv));
if (unit < 0 || unit >= wskbd_cd.cd_ndevs ||
(sc = wskbd_cd.cd_devs[unit]) == NULL)
return (ENXIO);
if (sc->sc_mux || sc->sc_events.io)
return (EBUSY);
return (wsmux_attach_sc(muxsc, WSMUX_KBD, &sc->sc_dv, &sc->sc_events,
&sc->sc_mux, &wskbd_muxops));
}
int
wskbd_rem_mux(unit, muxsc)
int unit;
struct wsmux_softc *muxsc;
{
struct wskbd_softc *sc;
DPRINTF(("wskbd_rem_mux: %d %s\n", unit, muxsc->sc_dv.dv_xname));
if (unit < 0 || unit >= wskbd_cd.cd_ndevs ||
(sc = wskbd_cd.cd_devs[unit]) == NULL)
return (ENXIO);
return (wsmux_detach_sc(muxsc, &sc->sc_dv));
}
#endif /* NWSDISPLAY > 0 */

View File

@ -1,4 +1,4 @@
/* $NetBSD: wskbdvar.h,v 1.6 1998/08/02 14:18:07 drochner Exp $ */
/* $NetBSD: wskbdvar.h,v 1.7 1999/07/29 18:20:03 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -75,6 +75,8 @@ struct wskbddev_attach_args {
#define wskbddevcf_console cf_loc[WSKBDDEVCF_CONSOLE] /* spec'd as console? */
#define WSKBDDEVCF_CONSOLE_UNK (WSKBDDEVCF_CONSOLE_DEFAULT)
#define wskbddevcf_mux cf_loc[WSKBDDEVCF_MUX]
/*
* Autoconfiguration helper functions.
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: wsmouse.c,v 1.7 1999/06/30 06:21:21 augustss Exp $ */
/* $NetBSD: wsmouse.c,v 1.8 1999/07/29 18:20:03 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -33,7 +33,7 @@
static const char _copyright[] __attribute__ ((unused)) =
"Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.";
static const char _rcsid[] __attribute__ ((unused)) =
"$NetBSD: wsmouse.c,v 1.7 1999/06/30 06:21:21 augustss Exp $";
"$NetBSD: wsmouse.c,v 1.8 1999/07/29 18:20:03 augustss Exp $";
/*
* Copyright (c) 1992, 1993
@ -101,6 +101,13 @@ static const char _rcsid[] __attribute__ ((unused)) =
#include <dev/wscons/wseventvar.h>
#include "wsmouse.h"
#include "wsmux.h"
#include "wsdisplay.h"
#include "wskbd.h"
#if NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0)
#include <dev/wscons/wsmuxvar.h>
#endif
struct wsmouse_softc {
struct device sc_dv;
@ -120,6 +127,9 @@ struct wsmouse_softc {
int sc_refcnt;
u_char sc_dying; /* device is being detached */
#if NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0)
struct wsmux_softc *sc_mux;
#endif
};
int wsmouse_match __P((struct device *, struct cfdata *, void *));
@ -130,6 +140,10 @@ int wsmouse_activate __P((struct device *, enum devact));
int wsmouse_do_ioctl __P((struct wsmouse_softc *, u_long, caddr_t,
int, struct proc *));
int wsmousedoclose __P((struct device *, int, int, struct proc *));
int wsmousedoioctl __P((struct device *, u_long, caddr_t, int,
struct proc *));
struct cfattach wsmouse_ca = {
sizeof (struct wsmouse_softc), wsmouse_match, wsmouse_attach,
wsmouse_detach, wsmouse_activate
@ -141,6 +155,10 @@ extern struct cfdriver wsmouse_cd;
cdev_decl(wsmouse);
struct wsmuxops wsmouse_muxops = {
wsmouseopen, wsmousedoclose, wsmousedoioctl, 0, 0
};
/*
* Print function (for parent devices).
*/
@ -171,11 +189,23 @@ wsmouse_attach(parent, self, aux)
{
struct wsmouse_softc *sc = (struct wsmouse_softc *)self;
struct wsmousedev_attach_args *ap = aux;
#if NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0)
int mux;
#endif
sc->sc_accessops = ap->accessops;
sc->sc_accesscookie = ap->accesscookie;
sc->sc_ready = 0; /* sanity */
#if NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0)
mux = sc->sc_dv.dv_cfdata->wsmousedevcf_mux;
if (mux != WSMOUSEDEVCF_MUX_DEFAULT) {
wsmux_attach(mux, WSMUX_MOUSE, &sc->sc_dv, &sc->sc_events,
&sc->sc_mux, &wsmouse_muxops);
printf(" mux %d", mux);
}
#endif
printf("\n");
}
@ -205,9 +235,18 @@ wsmouse_detach(self, flags)
struct wseventvar *evar;
int maj, mn;
int s;
#if NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0)
int mux;
#endif
sc->sc_dying = 1;
#if NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0)
mux = sc->sc_dv.dv_cfdata->wsmousedevcf_mux;
if (mux != WSMOUSEDEVCF_MUX_DEFAULT)
wsmux_detach(mux, &sc->sc_dv);
#endif
evar = &sc->sc_events;
if (evar->io) {
s = spltty();
@ -253,7 +292,12 @@ wsmouse_input(wsmousedev, btns, dx, dy, dz)
if (sc->sc_ready == 0)
return;
evar = &sc->sc_events;
#if NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0)
if (sc->sc_mux)
evar = &sc->sc_mux->sc_events;
else
#endif
evar = &sc->sc_events;
sc->sc_mb = btns;
sc->sc_dx += dx;
@ -368,6 +412,11 @@ wsmouseopen(dev, flags, mode, p)
return (0); /* always allow open for write
so ioctl() is possible. */
#if NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0)
if (sc->sc_mux)
return (EBUSY);
#endif
if (sc->sc_events.io) /* and that it's not in use */
return (EBUSY);
@ -398,7 +447,21 @@ wsmouseclose(dev, flags, mode, p)
struct proc *p;
{
#if NWSMOUSE > 0
struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)];
return (wsmousedoclose(wsmouse_cd.cd_devs[minor(dev)],
flags, mode, p));
#else
return (ENXIO);
#endif /* NWSMOUSE > 0 */
}
#if NWSMOUSE > 0
int
wsmousedoclose(dv, flags, mode, p)
struct device *dv;
int flags, mode;
struct proc *p;
{
struct wsmouse_softc *sc = (struct wsmouse_softc *)dv;
if ((flags & (FREAD | FWRITE)) == FWRITE)
return (0); /* see wsmouseopen() */
@ -409,10 +472,8 @@ wsmouseclose(dev, flags, mode, p)
wsevent_fini(&sc->sc_events);
sc->sc_events.io = NULL;
return (0);
#else
return (ENXIO);
#endif /* NWSMOUSE > 0 */
}
#endif /* NWSMOUSE > 0 */
int
wsmouseread(dev, uio, flags)
@ -448,7 +509,24 @@ wsmouseioctl(dev, cmd, data, flag, p)
struct proc *p;
{
#if NWSMOUSE > 0
struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)];
return (wsmousedoioctl(wsmouse_cd.cd_devs[minor(dev)],
cmd, data, flag, p));
#else
return (ENXIO);
#endif /* NWSMOUSE > 0 */
}
#if NWSMOUSE > 0
/* A wrapper around the ioctl() workhorse to make reference counting easy. */
int
wsmousedoioctl(dv, cmd, data, flag, p)
struct device *dv;
u_long cmd;
caddr_t data;
int flag;
struct proc *p;
{
struct wsmouse_softc *sc = (struct wsmouse_softc *)dv;
int error;
sc->sc_refcnt++;
@ -456,12 +534,8 @@ wsmouseioctl(dev, cmd, data, flag, p)
if (--sc->sc_refcnt < 0)
wakeup(sc);
return (error);
#else
return (ENXIO);
#endif /* NWSMOUSE > 0 */
}
#if NWSMOUSE > 0
int
wsmouse_do_ioctl(sc, cmd, data, flag, p)
struct wsmouse_softc *sc;
@ -517,3 +591,37 @@ wsmousepoll(dev, events, p)
#endif /* NWSMOUSE > 0 */
}
#if NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0)
int
wsmouse_add_mux(unit, muxsc)
int unit;
struct wsmux_softc *muxsc;
{
struct wsmouse_softc *sc;
if (unit < 0 || unit >= wsmouse_cd.cd_ndevs ||
(sc = wsmouse_cd.cd_devs[unit]) == NULL)
return (ENXIO);
if (sc->sc_mux || sc->sc_events.io)
return (EBUSY);
return (wsmux_attach_sc(muxsc, WSMUX_KBD, &sc->sc_dv, &sc->sc_events,
&sc->sc_mux, &wsmouse_muxops));
}
int
wsmouse_rem_mux(unit, muxsc)
int unit;
struct wsmux_softc *muxsc;
{
struct wsmouse_softc *sc;
if (unit < 0 || unit >= wsmouse_cd.cd_ndevs ||
(sc = wsmouse_cd.cd_devs[unit]) == NULL)
return (ENXIO);
return (wsmux_detach_sc(muxsc, &sc->sc_dv));
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: wsmousevar.h,v 1.2 1998/07/27 22:33:22 drochner Exp $ */
/* $NetBSD: wsmousevar.h,v 1.3 1999/07/29 18:20:03 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -56,8 +56,12 @@ struct wsmousedev_attach_args {
void *accesscookie; /* access cookie */
};
#include "locators.h"
#define wsmousedevcf_mux cf_loc[WSMOUSEDEVCF_MUX]
/*
* Autoconfiugration helper functions.
* Autoconfiguration helper functions.
*/
int wsmousedevprint __P((void *, const char *));

716
sys/dev/wscons/wsmux.c Normal file
View File

@ -0,0 +1,716 @@
/* $NetBSD: wsmux.c,v 1.1 1999/07/29 18:20:03 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Author: Lennart Augustsson <augustss@carlstedt.se>
* Carlstedt Research & Technology
*
* 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 NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
#include "wsmux.h"
#include "wsdisplay.h"
#include "wskbd.h"
#if NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0)
/*
* wscons mux device.
*
* The mux device is a collection of real mice and keyboards and acts as
* a merge point for all the events from the different real devices.
*/
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/syslog.h>
#include <sys/systm.h>
#include <sys/tty.h>
#include <sys/signalvar.h>
#include <sys/device.h>
#include "opt_wsdisplay_compat.h"
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wseventvar.h>
#include <dev/wscons/wscons_callbacks.h>
#include <dev/wscons/wsmuxvar.h>
#ifdef WSMUX_DEBUG
#define DPRINTF(x) if (wsmuxdebug) printf x
int wsmuxdebug = 0;
#else
#define DPRINTF(x)
#endif
struct wsplink {
LIST_ENTRY(wsplink) next;
int type;
struct wsmux_softc *mux; /* our mux device */
/* The rest of the fields reflect a value in the multiplexee. */
struct device *sc; /* softc */
struct wseventvar *sc_mevents; /* event var */
struct wsmux_softc **sc_muxp; /* pointer to us */
struct wsmuxops *sc_ops;
};
cdev_decl(wsmux);
int wsmuxdoclose __P((struct device *, int, int, struct proc *));
int wsmux_set_display __P((struct device *, struct wsmux_softc *));
int nwsmux = NWSMUX;
struct wsmux_softc *wsmuxdevs[NWSMUX];
void wsmuxattach __P((int));
struct wsmuxops wsmux_muxops = {
wsmuxopen, wsmuxdoclose, wsmuxdoioctl, wsmux_displayioctl,
wsmux_set_display
};
/* From upper level */
void
wsmuxattach(n)
int n;
{
int i;
#if 0
/* Called too late. We use static allocation instead. */
nwsmux = n;
wsmuxdevs = malloc(n * sizeof (struct wsmux_softc *),
M_DEVBUF, M_NOWAIT);
if (wsmuxdevs == 0)
panic("wsmuxattach: out of memory\n");
#endif
/* Make sure all muxes are there. */
for (i = 0; i < nwsmux; i++)
if (!wsmuxdevs[i])
wsmuxdevs[i] = wsmux_create("wsmux", i);
}
struct wsmux_softc *
wsmux_create(name, unit)
const char *name;
int unit;
{
struct wsmux_softc *sc;
DPRINTF(("wsmux_create: allocating\n"));
sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT);
if (!sc)
return (0);
memset(sc, 0, sizeof *sc);
LIST_INIT(&sc->sc_reals);
snprintf(sc->sc_dv.dv_xname, sizeof sc->sc_dv.dv_xname,
"%s%d", name, unit);
sc->sc_dv.dv_unit = unit;
return (sc);
}
/* From mouse or keyboard. */
void
wsmux_attach(n, type, dsc, ev, psp, ops)
int n;
int type;
struct device *dsc;
struct wseventvar *ev;
struct wsmux_softc **psp;
struct wsmuxops *ops;
{
struct wsmux_softc *sc;
int error;
DPRINTF(("wsmux_attach\n"));
if (n >= nwsmux || n < 0) {
printf("wsmux: attach device %d is out of range (%d..%d)\n",
n, 0, nwsmux-1);
return;
}
sc = wsmuxdevs[n];
if (sc == 0) {
sc = wsmux_create("wsmux", n);
if (sc == 0) {
printf("wsmux: attach out of memory\n");
return;
}
wsmuxdevs[n] = sc;
}
error = wsmux_attach_sc(sc, type, dsc, ev, psp, ops);
if (error)
printf("wsmux_attach: error=%d\n", error);
}
int
wsmux_attach_sc(sc, type, dsc, ev, psp, ops)
struct wsmux_softc *sc;
int type;
struct device *dsc;
struct wseventvar *ev;
struct wsmux_softc **psp;
struct wsmuxops *ops;
{
struct wsplink *m;
int error;
DPRINTF(("wsmux_attach_sc: %s: type=%d dsc=%p, *psp=%p\n",
sc->sc_dv.dv_xname, type, dsc, *psp));
m = malloc(sizeof *m, M_DEVBUF, M_NOWAIT);
if (m == 0)
return (ENOMEM);
m->type = type;
m->mux = sc;
m->sc = dsc;
m->sc_mevents = ev;
m->sc_muxp = psp;
m->sc_ops = ops;
LIST_INSERT_HEAD(&sc->sc_reals, m, next);
if (sc->sc_displaydv) {
/* This is a display mux, so attach the new device to it. */
DPRINTF(("wsmux_attach_sc: %s: set display %p\n",
sc->sc_dv.dv_xname, sc->sc_displaydv));
error = 0;
if (m->sc_ops->dsetdisplay) {
error = m->sc_ops->dsetdisplay(m->sc, sc);
/* Ignore that the console already has a display. */
if (error == EBUSY)
error = 0;
if (!error) {
*m->sc_muxp = sc;
#ifdef WSDISPLAY_COMPAT_RAWKBD
DPRINTF(("wsmux_attach_sc: on %s set rawkbd=%d\n",
m->sc->dv_xname, sc->sc_rawkbd));
(void)m->sc_ops->dioctl(m->sc,
WSKBDIO_SETMODE,
(caddr_t)&sc->sc_rawkbd,
0, 0);
#endif
}
}
} else if (sc->sc_events.io) {
/* Mux is open, so open the new subdevice */
DPRINTF(("wsmux_attach_sc: %s: calling open of %s\n",
sc->sc_dv.dv_xname, m->sc->dv_xname));
/* mux already open, join in */
error = m->sc_ops->dopen(makedev(0, m->sc->dv_unit),
sc->sc_flags, sc->sc_mode, sc->sc_p);
if (!error)
*m->sc_muxp = sc;
} else {
DPRINTF(("wsmux_attach_sc: %s not open\n",
sc->sc_dv.dv_xname));
error = 0;
}
DPRINTF(("wsmux_attach_sc: done sc=%p psp=%p *psp=%p\n",
sc, psp, *psp));
return (error);
}
/* From mouse or keyboard. */
void
wsmux_detach(n, dsc)
int n;
struct device *dsc;
{
#ifdef DIAGNOSTIC
int error;
if (n >= nwsmux || n < 0) {
printf("wsmux_detach: detach is out of range\n");
return;
}
if ((error = wsmux_detach_sc(wsmuxdevs[n], dsc)))
printf("wsmux_detach: error=%d\n", error);
#else
(void)wsmux_detach_sc(wsmuxdevs[n], dsc);
#endif
}
int
wsmux_detach_sc(sc, dsc)
struct wsmux_softc *sc;
struct device *dsc;
{
struct wsplink *m;
int error;
DPRINTF(("wsmux_detach_sc: %s: dsc=%p\n", sc->sc_dv.dv_xname, dsc));
#ifdef DIAGNOSTIC
if (sc == 0) {
printf("wsmux_detach_sc: not allocated\n");
return (ENXIO);
}
#endif
for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) {
if (m->sc == dsc)
break;
}
#ifdef DIAGNOSTIC
if (!m) {
printf("wsmux_detach_sc: not found\n");
return (ENXIO);
}
#endif
if (sc->sc_displaydv) {
if (m->sc_ops->dsetdisplay)
error = m->sc_ops->dsetdisplay(m->sc, 0);
if (error)
return (error);
*m->sc_muxp = 0;
} else if (*m->sc_muxp) {
DPRINTF(("wsmux_detach_sc: close\n"));
/* mux device is open, so close multiplexee */
m->sc_ops->dclose(m->sc, FREAD, 0, 0);
*m->sc_muxp = 0;
}
LIST_REMOVE(m, next);
free(m, M_DEVBUF);
DPRINTF(("wsmux_detach_sc: done sc=%p\n", sc));
return (0);
}
int
wsmuxopen(dev, flags, mode, p)
dev_t dev;
int flags, mode;
struct proc *p;
{
struct wsmux_softc *sc;
struct wsplink *m;
int unit, error, nopen, lasterror;
unit = minor(dev);
if (unit >= nwsmux || /* make sure it was attached */
(sc = wsmuxdevs[unit]) == NULL)
return (ENXIO);
DPRINTF(("wsmuxopen: %s: sc=%p\n", sc->sc_dv.dv_xname, sc));
if (!(flags & FREAD)) {
/* Not opening for read, only ioctl is available. */
return (0);
}
if (sc->sc_events.io)
return (EBUSY);
sc->sc_events.io = p;
sc->sc_flags = flags;
sc->sc_mode = mode;
sc->sc_p = p;
wsevent_init(&sc->sc_events); /* may cause sleep */
nopen = 0;
lasterror = 0;
for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) {
if (!m->sc_mevents->io && !*m->sc_muxp) {
DPRINTF(("wsmuxopen: %s: m=%p dev=%s\n",
sc->sc_dv.dv_xname, m, m->sc->dv_xname));
error = m->sc_ops->dopen(makedev(0, m->sc->dv_unit),
flags, mode, p);
if (error) {
/* Ignore opens that fail */
lasterror = error;
DPRINTF(("wsmuxopen: open failed %d\n",
error));
} else {
nopen++;
*m->sc_muxp = sc;
}
}
}
if (nopen == 0 && lasterror != 0) {
wsevent_fini(&sc->sc_events);
sc->sc_events.io = NULL;
return (lasterror);
}
return (0);
}
int
wsmuxclose(dev, flags, mode, p)
dev_t dev;
int flags, mode;
struct proc *p;
{
return wsmuxdoclose(&wsmuxdevs[minor(dev)]->sc_dv, flags, mode, p);
}
int wsmuxdoclose(dv, flags, mode, p)
struct device *dv;
int flags, mode;
struct proc *p;
{
struct wsmux_softc *sc = (struct wsmux_softc *)dv;
struct wsplink *m;
DPRINTF(("wsmuxclose: %s: sc=%p\n", sc->sc_dv.dv_xname, sc));
if (!(flags & FREAD)) {
/* Not closing read, so read still allowed. */
return 0;
}
for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) {
if (*m->sc_muxp == sc) {
DPRINTF(("wsmuxclose %s: m=%p dev=%s\n",
sc->sc_dv.dv_xname, m, m->sc->dv_xname));
m->sc_ops->dclose(m->sc, flags, mode, p);
*m->sc_muxp = 0;
}
}
wsevent_fini(&sc->sc_events);
sc->sc_events.io = NULL;
return (0);
}
int
wsmuxread(dev, uio, flags)
dev_t dev;
struct uio *uio;
int flags;
{
struct wsmux_softc *sc = wsmuxdevs[minor(dev)];
if (!sc->sc_events.io)
return (EACCES);
return (wsevent_read(&sc->sc_events, uio, flags));
}
int
wsmuxioctl(dev, cmd, data, flag, p)
dev_t dev;
u_long cmd;
caddr_t data;
int flag;
struct proc *p;
{
return wsmuxdoioctl(&wsmuxdevs[minor(dev)]->sc_dv, cmd, data, flag, p);
}
int
wsmuxdoioctl(dv, cmd, data, flag, p)
struct device *dv;
u_long cmd;
caddr_t data;
int flag;
struct proc *p;
{
struct wsmux_softc *sc = (struct wsmux_softc *)dv;
struct wsplink *m;
int error, ok;
int s, put, get, n;
struct wseventvar *evar;
struct wscons_event *ev;
struct timeval xxxtime;
struct wsmux_device_list *l;
DPRINTF(("wsmuxdoioctl: %s: sc=%p, cmd=%08lx\n",
sc->sc_dv.dv_xname, sc, cmd));
switch (cmd) {
case WSMUX_INJECTEVENT:
/* Inject an event, e.g., from moused. */
if (!sc->sc_events.io)
return (EACCES);
evar = &sc->sc_events;
s = spltty();
get = evar->get;
put = evar->put;
if (++put % WSEVENT_QSIZE == get) {
put--;
splx(s);
return (ENOSPC);
}
if (put >= WSEVENT_QSIZE)
put = 0;
ev = &evar->q[put];
*ev = *(struct wscons_event *)data;
microtime(&xxxtime);
TIMEVAL_TO_TIMESPEC(&xxxtime, &ev->time);
evar->put = put;
WSEVENT_WAKEUP(evar);
splx(s);
return (0);
case WSMUX_ADD_DEVICE:
#define d ((struct wsmux_device *)data)
switch (d->type) {
#if NWSMOUSE > 0
case WSMUX_MOUSE:
return (wsmouse_add_mux(d->idx, sc));
#endif
#if NWSKBD > 0
case WSMUX_KBD:
return (wskbd_add_mux(d->idx, sc));
#endif
case WSMUX_MUX:
return (wsmux_add_mux(d->idx, sc));
default:
return (EINVAL);
}
case WSMUX_REMOVE_DEVICE:
switch (d->type) {
#if NWSMOUSE > 0
case WSMUX_MOUSE:
return (wsmouse_rem_mux(d->idx, sc));
#endif
#if NWSKBD > 0
case WSMUX_KBD:
return (wskbd_rem_mux(d->idx, sc));
#endif
case WSMUX_MUX:
return (wsmux_rem_mux(d->idx, sc));
default:
return (EINVAL);
}
#undef d
case WSMUX_LIST_DEVICES:
l = (struct wsmux_device_list *)data;
for (n = 0, m = LIST_FIRST(&sc->sc_reals);
n < WSMUX_MAXDEV && m != NULL;
m = LIST_NEXT(m, next)) {
l->devices[n].type = m->type;
l->devices[n].idx = m->sc->dv_unit;
n++;
}
l->ndevices = n;
return (0);
#ifdef WSDISPLAY_COMPAT_RAWKBD
case WSKBDIO_SETMODE:
sc->sc_rawkbd = *(int *)data;
DPRINTF(("wsmuxdoioctl: save rawkbd = %d\n", sc->sc_rawkbd));
break;
#endif
default:
break;
}
if (sc->sc_events.io == NULL && sc->sc_displaydv == NULL)
return (EACCES);
/* Return 0 if any of the ioctl() succeeds, otherwise the last error */
error = 0;
ok = 0;
for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) {
DPRINTF(("wsmuxdoioctl: m=%p *m->sc_muxp=%p sc=%p\n",
m, *m->sc_muxp, sc));
if (*m->sc_muxp == sc) {
DPRINTF(("wsmuxdoioctl: %s: m=%p dev=%s\n",
sc->sc_dv.dv_xname, m, m->sc->dv_xname));
error = m->sc_ops->dioctl(m->sc, cmd, data, flag, p);
if (!error)
ok = 1;
}
}
if (ok)
error = 0;
return (error);
}
int
wsmux_displayioctl(dv, cmd, data, flag, p)
struct device *dv;
u_long cmd;
caddr_t data;
int flag;
struct proc *p;
{
struct wsmux_softc *sc = (struct wsmux_softc *)dv;
struct wsplink *m;
int error, ok;
DPRINTF(("wsmux_displayioctl: %s: sc=%p, cmd=%08lx\n",
sc->sc_dv.dv_xname, sc, cmd));
#ifdef WSDISPLAY_COMPAT_RAWKBD
if (cmd == WSKBDIO_SETMODE) {
sc->sc_rawkbd = *(int *)data;
DPRINTF(("wsmux_displayioctl: rawkbd = %d\n", sc->sc_rawkbd));
}
#endif
/* Return 0 if any of the ioctl() succeeds, otherwise the last error */
error = 0;
ok = 0;
for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) {
DPRINTF(("wsmux_displayioctl: m=%p sc=%p sc_muxp=%p\n",
m, sc, *m->sc_muxp));
if (m->sc_ops->ddispioctl && *m->sc_muxp == sc) {
error = m->sc_ops->ddispioctl(m->sc, cmd, data,
flag, p);
DPRINTF(("wsmux_displayioctl: m=%p dev=%s ==> %d\n",
m, m->sc->dv_xname, error));
if (!error)
ok = 1;
}
}
if (ok)
error = 0;
return (error);
}
int
wsmuxpoll(dev, events, p)
dev_t dev;
int events;
struct proc *p;
{
struct wsmux_softc *sc = wsmuxdevs[minor(dev)];
if (!sc->sc_events.io)
return (EACCES);
return (wsevent_poll(&sc->sc_events, events, p));
}
int
wsmux_set_display(dv, muxsc)
struct device *dv;
struct wsmux_softc *muxsc;
{
struct wsmux_softc *sc = (struct wsmux_softc *)dv;
struct wsmux_softc *nsc = muxsc ? sc : 0;
struct device *displaydv = muxsc ? muxsc->sc_displaydv : 0;
struct device *odisplaydv;
struct wsplink *m;
int error, ok;
DPRINTF(("wsmux_set_display: %s: displaydv=%p\n",
sc->sc_dv.dv_xname, displaydv));
if (displaydv) {
if (sc->sc_displaydv)
return (EBUSY);
} else {
if (sc->sc_displaydv == NULL)
return (ENXIO);
}
odisplaydv = sc->sc_displaydv;
sc->sc_displaydv = displaydv;
if (displaydv)
printf("%s: connecting to %s\n",
sc->sc_dv.dv_xname, displaydv->dv_xname);
ok = 0;
error = 0;
for (m = LIST_FIRST(&sc->sc_reals); m; m = LIST_NEXT(m, next)) {
if (m->sc_ops->dsetdisplay &&
(nsc ? m->sc_mevents->io == 0 && *m->sc_muxp == 0 :
*m->sc_muxp == sc)) {
error = m->sc_ops->dsetdisplay(m->sc, nsc);
DPRINTF(("wsmux_set_display: m=%p dev=%s error=%d\n",
m, m->sc->dv_xname, error));
if (!error) {
ok = 1;
*m->sc_muxp = nsc;
#ifdef WSDISPLAY_COMPAT_RAWKBD
DPRINTF(("wsmux_set_display: on %s set rawkbd=%d\n",
m->sc->dv_xname, sc->sc_rawkbd));
(void)m->sc_ops->dioctl(m->sc,
WSKBDIO_SETMODE,
(caddr_t)&sc->sc_rawkbd,
0, 0);
#endif
}
}
}
if (ok)
error = 0;
if (displaydv == NULL)
printf("%s: disconnecting from %s\n",
sc->sc_dv.dv_xname, odisplaydv->dv_xname);
return (error);
}
int
wsmux_add_mux(unit, muxsc)
int unit;
struct wsmux_softc *muxsc;
{
struct wsmux_softc *sc, *m;
if (unit < 0 || unit >= nwsmux || (sc = wsmuxdevs[unit]) == NULL)
return (ENXIO);
DPRINTF(("wsmux_add_mux: %s to %s\n", sc->sc_dv.dv_xname,
muxsc->sc_dv.dv_xname));
if (sc->sc_mux || sc->sc_events.io)
return (EBUSY);
/* The mux we are adding must not be an ancestor of it. */
for (m = muxsc->sc_mux; m; m = m->sc_mux)
if (m == sc)
return (EINVAL);
return (wsmux_attach_sc(muxsc, WSMUX_MUX, &sc->sc_dv, &sc->sc_events,
&sc->sc_mux, &wsmux_muxops));
}
int
wsmux_rem_mux(unit, muxsc)
int unit;
struct wsmux_softc *muxsc;
{
struct wsmux_softc *sc;
if (unit < 0 || unit >= nwsmux || (sc = wsmuxdevs[unit]) == NULL)
return (ENXIO);
DPRINTF(("wsmux_rem_mux: %s from %s\n", sc->sc_dv.dv_xname,
muxsc->sc_dv.dv_xname));
return (wsmux_detach_sc(muxsc, &sc->sc_dv));
}
#endif /* NWSMUX > 0 || (NWSDISPLAY > 0 && NWSKBD > 0) */

88
sys/dev/wscons/wsmuxvar.h Normal file
View File

@ -0,0 +1,88 @@
/* $NetBSD: wsmuxvar.h,v 1.1 1999/07/29 18:20:43 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Author: Lennart Augustsson <augustss@carlstedt.se>
* Carlstedt Research & Technology
*
* 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 NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
struct wsdisplay_softc;
struct wsplink;
struct wsmux_softc {
struct device sc_dv;
struct wseventvar sc_events; /* event queue state */
int sc_flags, sc_mode; /* open flags */
struct proc *sc_p; /* open proc */
LIST_HEAD(, wsplink) sc_reals; /* list of real devices */
struct wsmux_softc *sc_mux; /* if part of another mux */
struct device *sc_displaydv; /* our display if part of one */
#ifdef WSDISPLAY_COMPAT_RAWKBD
int sc_rawkbd; /* A hack to remember the kbd mode */
#endif
};
struct wsmuxops {
int (*dopen) __P((dev_t, int, int, struct proc *));
int (*dclose) __P((struct device *, int, int, struct proc *));
int (*dioctl) __P((struct device *, u_long, caddr_t, int,
struct proc *));
int (*ddispioctl) __P((struct device *, u_long, caddr_t, int,
struct proc *));
int (*dsetdisplay) __P((struct device *, struct wsmux_softc *));
};
struct wsmux_softc *wsmux_create __P((const char *name, int no));
int wsmux_attach_sc __P((
struct wsmux_softc *,
int, struct device *, struct wseventvar *,
struct wsmux_softc **,
struct wsmuxops *));
int wsmux_detach_sc __P((struct wsmux_softc *, struct device *));
void wsmux_attach __P((
int, int, struct device *, struct wseventvar *,
struct wsmux_softc **,
struct wsmuxops *));
void wsmux_detach __P((int, struct device *));
int wsmux_displayioctl __P((struct device *dev, u_long cmd,
caddr_t data, int flag, struct proc *p));
int wsmuxdoioctl __P((struct device *, u_long, caddr_t,int,struct proc *));
int wsmux_add_mux __P((int, struct wsmux_softc *));
int wsmux_rem_mux __P((int, struct wsmux_softc *));
int wskbd_add_mux __P((int, struct wsmux_softc *));
int wskbd_rem_mux __P((int, struct wsmux_softc *));
int wsmouse_add_mux __P((int, struct wsmux_softc *));
int wsmouse_rem_mux __P((int, struct wsmux_softc *));