Major rototilling of the wsmux code. No user visible changes (except that

many bugs have been fixed).
Changes:
The wskbd, wsmouse, and wsmux are now "sub-classes" of wsevsrc, which is
a source of ws events.  This make the structure of those drivers a little
more uniform.
Many bug fixes involving adding and removing devices from muxes.
When a kernel is configured without wsmux there will now be none (unlike
before where you got a console mux anyway).
The kernel now compiles with all combinations of ws devices present.
This commit is contained in:
augustss 2001-10-24 14:07:31 +00:00
parent ad870d54a0
commit 2f1f0a1702
10 changed files with 1041 additions and 844 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: files.wscons,v 1.22 2001/10/05 22:08:29 eeh Exp $
# $NetBSD: files.wscons,v 1.23 2001/10/24 14:07:31 augustss Exp $
#
# "Workstation Console" glue; attaches frame buffer to emulator & keyboard,
@ -40,7 +40,7 @@ file dev/wscons/wsemul_vt100.c wsdisplay & wsemul_vt100
file dev/wscons/wsemul_vt100_subr.c wsdisplay & wsemul_vt100
file dev/wscons/wsemul_vt100_chars.c wsdisplay & wsemul_vt100
file dev/wscons/wsemul_vt100_keys.c wsdisplay & wsemul_vt100
file dev/wscons/wsevent.c wskbd | wsmouse
file dev/wscons/wsevent.c wskbd | wsmouse | wsmux
file dev/wscons/wskbd.c wskbd needs-flag
file dev/wscons/wskbdutil.c wskbd needs-flag
file dev/wscons/wsmouse.c wsmouse needs-flag
@ -52,4 +52,4 @@ file dev/wscons/wscons_rinit.c wsrasteremulops
file dev/wscons/wscons_rops.c wsrasteremulops
defpseudo wsmux
file dev/wscons/wsmux.c wsmux | wsdisplay needs-flag
file dev/wscons/wsmux.c wsmux needs-flag

View File

@ -1,4 +1,4 @@
/* $NetBSD: wscons_callbacks.h,v 1.14 2001/10/13 15:56:15 augustss Exp $ */
/* $NetBSD: wscons_callbacks.h,v 1.15 2001/10/24 14:07:32 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -30,10 +30,12 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
struct wsevsrc;
/*
* Calls to the display interface from the glue code.
*/
struct device *wsdisplay_set_console_kbd(struct device *);
struct device *wsdisplay_set_console_kbd(struct wsevsrc *);
/*
* Calls to the display interface from the keyboard interface.
@ -57,6 +59,5 @@ int wsdisplay_param(struct device*, u_long, struct wsdisplay_param*);
/*
* Calls to the keyboard interface from the glue code.
*/
struct wsmux_softc;
struct device *wskbd_set_console_display(struct device *, struct wsmux_softc *);
struct wsevsrc *wskbd_set_console_display(struct device *, struct wsevsrc *);
int wskbd_pickfree(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: wsconsio.h,v 1.43 2001/10/02 21:03:05 mycroft Exp $ */
/* $NetBSD: wsconsio.h,v 1.44 2001/10/24 14:07:32 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -40,7 +40,8 @@
* 0-31 keyboard ioctls (WSKBDIO)
* 32-63 mouse ioctls (WSMOUSEIO)
* 64-95 display ioctls (WSDISPLAYIO)
* 96-255 reserved for future use
* 96-f127 mux ioctls (WSMUXIO)
* 128-255 reserved for future use
*/
#include <sys/types.h>
@ -340,7 +341,7 @@ struct wsdisplay_usefontdata {
};
#define WSDISPLAYIO_USEFONT _IOW('W', 80, struct wsdisplay_usefontdata)
/* Replaced by WSMUX_{ADD,REMOVE}_DEVICE */
/* Obsolete, replaced by WSMUXIO_{ADD,REMOVE}_DEVICE */
struct wsdisplay_kbddata {
int op;
#define _O_WSDISPLAY_KBD_ADD 0
@ -365,7 +366,8 @@ struct wsdisplay_param {
/* Mapping information retrieval. */
/* Mux ioctls (96 - 127) */
#define WSMUX_INJECTEVENT _IOW('W', 96, struct wscons_event)
#define WSMUXIO_INJECTEVENT _IOW('W', 96, struct wscons_event)
#define WSMUX_INJECTEVENT WSMUXIO_INJECTEVENT /* XXX compat */
struct wsmux_device {
int type;
@ -374,14 +376,17 @@ struct wsmux_device {
#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 WSMUXIO_ADD_DEVICE _IOW('W', 97, struct wsmux_device)
#define WSMUX_ADD_DEVICE WSMUXIO_ADD_DEVICE /* XXX compat */
#define WSMUXIO_REMOVE_DEVICE _IOW('W', 98, struct wsmux_device)
#define WSMUX_REMOVE_DEVICE WSMUXIO_REMOVE_DEVICE /* XXX compat */
#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)
#define WSMUXIO_LIST_DEVICES _IOWR('W', 99, struct wsmux_device_list)
#define WSMUX_LIST_DEVICES WSMUXIO_LIST_DEVICES /* XXX compat */
#endif /* _DEV_WSCONS_WSCONSIO_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: wsdisplay.c,v 1.55 2001/10/15 21:51:33 augustss Exp $ */
/* $NetBSD: wsdisplay.c,v 1.56 2001/10/24 14:07:32 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -30,8 +30,14 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "opt_wsdisplay_compat.h"
#include "opt_compat_netbsd.h"
#include "wskbd.h"
#include "wsmux.h"
#include "wsdisplay.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.55 2001/10/15 21:51:33 augustss Exp $");
__KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.56 2001/10/24 14:07:32 augustss Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@ -48,6 +54,8 @@ __KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.55 2001/10/15 21:51:33 augustss Exp
#include <sys/fcntl.h>
#include <sys/vnode.h>
#include <dev/wscons/wseventvar.h>
#include <dev/wscons/wsmuxvar.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/wscons/wsksymvar.h>
@ -56,16 +64,6 @@ __KERNEL_RCSID(0, "$NetBSD: wsdisplay.c,v 1.55 2001/10/15 21:51:33 augustss Exp
#include <dev/wscons/wscons_callbacks.h>
#include <dev/cons.h>
#include "opt_wsdisplay_compat.h"
#include "opt_compat_netbsd.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;
void *emulcookie;
@ -128,7 +126,7 @@ struct wsdisplay_softc {
int sc_screenwanted, sc_oldscreen; /* valid with SC_SWITCHPENDING */
#if NWSKBD > 0
struct wsmux_softc *sc_muxdv;
struct wsevsrc *sc_input;
#ifdef WSDISPLAY_COMPAT_RAWKBD
int sc_rawkbd;
#endif
@ -562,23 +560,28 @@ wsdisplay_common_attach(struct wsdisplay_softc *sc, int console, int kbdmux,
static int hookset;
int i, start=0;
#if NWSKBD > 0
struct device *dv;
struct wsevsrc *kme;
#if NWSMUX > 0
struct wsevsrc *inp;
if (kbdmux >= 0)
sc->sc_muxdv = wsmux_getmux(kbdmux);
inp = &wsmux_getmux(kbdmux)->sc_base;
else
#endif
sc->sc_muxdv = wsmux_create("dmux", sc->sc_dv.dv_unit);
inp = &wsmux_create("dmux", sc->sc_dv.dv_unit)->sc_base;
/* XXX panic()ing isn't nice, but attach cannot fail */
if (!sc->sc_muxdv)
if (inp == NULL)
panic("wsdisplay_common_attach: no memory\n");
sc->sc_muxdv->sc_displaydv = &sc->sc_dv;
sc->sc_input = inp;
inp->me_dispdv = &sc->sc_dv;
printf(" kbdmux %d", kbdmux);
#else
if (kbdmux >= 0)
printf(" (kbdmux ignored)");
#endif
#endif
sc->sc_isconsole = console;
printf(" kbdmux %d", kbdmux);
if (console) {
KASSERT(wsdisplay_console_initted);
KASSERT(wsdisplay_console_device == NULL);
@ -591,8 +594,12 @@ wsdisplay_common_attach(struct wsdisplay_softc *sc, int console, int kbdmux,
wsdisplay_console_conf.wsemul->name);
#if NWSKBD > 0
if ((dv = wskbd_set_console_display(&sc->sc_dv, sc->sc_muxdv)))
printf(", using %s", dv->dv_xname);
kme = wskbd_set_console_display(&sc->sc_dv, sc->sc_input);
if (kme != NULL)
printf(", using %s", kme->me_dv.dv_xname);
#if NWSMUX == 0
sc->sc_input = kme;
#endif
#endif
sc->sc_focusidx = 0;
@ -755,8 +762,8 @@ wsdisplayclose(dev_t dev, int flag, int mode, struct proc *p)
#ifdef WSDISPLAY_COMPAT_RAWKBD
if (scr->scr_rawkbd) {
int kbmode = WSKBD_TRANSLATED;
(void) wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE,
(caddr_t)&kbmode, 0, p);
(void)wsdisplay_internal_ioctl(sc, scr, WSKBDIO_SETMODE,
(caddr_t)&kbmode, 0, p);
}
#endif
@ -908,6 +915,8 @@ wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr,
struct wsdisplay_font fd;
#if NWSKBD > 0
struct wsevsrc *inp;
#ifdef WSDISPLAY_COMPAT_RAWKBD
switch (cmd) {
case WSKBDIO_SETMODE:
@ -919,7 +928,8 @@ wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr,
return (0);
}
#endif
error = wsmux_displayioctl(&sc->sc_muxdv->sc_dv, cmd, data, flag, p);
inp = sc->sc_input;
error = wsevsrc_display_ioctl(inp, cmd, data, flag, p);
if (error >= 0)
return (error);
#endif /* NWSKBD > 0 */
@ -987,6 +997,9 @@ wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data,
#if defined(COMPAT_14) && NWSKBD > 0
struct wsmux_device wsmuxdata;
#endif
#if NWSKBD > 0
struct wsevsrc *inp;
#endif
switch (cmd) {
case WSDISPLAYIO_ADDSCREEN:
@ -1056,31 +1069,30 @@ wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, u_long cmd, caddr_t data,
}
wsmuxdata.type = WSMUX_KBD;
wsmuxdata.idx = d->idx;
return (wsmuxdoioctl(&sc->sc_muxdv->sc_dv,
WSMUX_ADD_DEVICE,
(caddr_t)&wsmuxdata, flag, p));
return (wsevsrc_ioctl(sc->sc_input, WSMUX_ADD_DEVICE,
&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));
return (wsevsrc_ioctl(sc->sc_input,WSMUX_REMOVE_DEVICE,
&wsmuxdata, flag, p));
default:
return (EINVAL);
}
#undef d
#endif
case WSMUX_ADD_DEVICE:
case WSMUXIO_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));
case WSMUXIO_INJECTEVENT:
case WSMUXIO_REMOVE_DEVICE:
case WSMUXIO_LIST_DEVICES:
inp = sc->sc_input;
return (wsevsrc_ioctl(inp, cmd, data, flag, p));
#endif /* NWSKBD > 0 */
}
@ -1170,7 +1182,7 @@ wsdisplaystart(struct tty *tp)
if (tp->t_outq.c_cc <= tp->t_lowat) {
if (tp->t_state&TS_ASLEEP) {
tp->t_state &= ~TS_ASLEEP;
wakeup((caddr_t)&tp->t_outq);
wakeup(&tp->t_outq);
}
selwakeup(&tp->t_wsel);
}
@ -1268,11 +1280,14 @@ wsdisplay_kbdinput(struct device *dev, keysym_t ks)
}
}
#ifdef WSDISPLAY_COMPAT_RAWKBD
#if defined(WSDISPLAY_COMPAT_RAWKBD)
int
wsdisplay_update_rawkbd(struct wsdisplay_softc *sc, struct wsscreen *scr)
{
#if NWSKBD > 0
int s, raw, data, error;
struct wsevsrc *inp;
s = spltty();
raw = (scr ? scr->scr_rawkbd : 0);
@ -1284,12 +1299,15 @@ wsdisplay_update_rawkbd(struct wsdisplay_softc *sc, struct wsscreen *scr)
}
data = raw ? WSKBD_RAW : WSKBD_TRANSLATED;
error = wsmux_displayioctl(&sc->sc_muxdv->sc_dv, WSKBDIO_SETMODE,
(caddr_t)&data, 0, 0);
inp = sc->sc_input;
error = wsevsrc_display_ioctl(inp, WSKBDIO_SETMODE, &data, 0, 0);
if (!error)
sc->sc_rawkbd = raw;
splx(s);
return (error);
#else
return (0);
#endif
}
#endif
@ -1638,12 +1656,17 @@ wsdisplay_kbdholdscreen(struct device *dev, int hold)
#if NWSKBD > 0
struct device *
wsdisplay_set_console_kbd(struct device *kbddv)
wsdisplay_set_console_kbd(struct wsevsrc *kbd)
{
if (!wsdisplay_console_device)
return (0);
if (wskbd_add_mux(kbddv->dv_unit, wsdisplay_console_device->sc_muxdv))
return (0);
if (wsdisplay_console_device == NULL)
return (NULL);
#if NWSMUX > 0
if (wskbd_add_mux(kbd->me_dv.dv_unit,
(struct wsmux_softc *)wsdisplay_console_device->sc_input))
return (NULL);
#else
wsdisplay_console_device->sc_input = kbd;
#endif
return (&wsdisplay_console_device->sc_dv);
}
#endif /* NWSKBD > 0 */

View File

@ -1,4 +1,4 @@
/* $NetBSD: wsevent.c,v 1.6 2001/10/13 15:56:16 augustss Exp $ */
/* $NetBSD: wsevent.c,v 1.7 2001/10/24 14:07:32 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: wsevent.c,v 1.6 2001/10/13 15:56:16 augustss Exp $");
__KERNEL_RCSID(0, "$NetBSD: wsevent.c,v 1.7 2001/10/24 14:07:32 augustss Exp $");
/*
* Copyright (c) 1992, 1993
@ -100,10 +100,16 @@ void
wsevent_init(struct wseventvar *ev)
{
#ifdef DIAGNOSTIC
if (ev->q != NULL) {
printf("wsevent_init: already init\n");
return;
}
#endif
ev->get = ev->put = 0;
ev->q = malloc((u_long)WSEVENT_QSIZE * sizeof(struct wscons_event),
M_DEVBUF, M_WAITOK);
memset((caddr_t)ev->q, 0, WSEVENT_QSIZE * sizeof(struct wscons_event));
M_DEVBUF, M_WAITOK);
memset(ev->q, 0, WSEVENT_QSIZE * sizeof(struct wscons_event));
}
/*
@ -114,6 +120,31 @@ wsevent_fini(struct wseventvar *ev)
{
free(ev->q, M_DEVBUF);
ev->q = NULL;
}
/*
* Allocate a wseventvar.
*/
struct wseventvar *
wsevent_alloc(void)
{
struct wseventvar *ev;
ev = malloc(sizeof(*ev), M_DEVBUF, M_WAITOK);
memset(ev, 0, sizeof *ev);
wsevent_init(ev);
return (ev);
}
/*
* Deallocate a wseventvar.
*/
void
wsevent_free(struct wseventvar *ev)
{
wsevent_fini(ev);
free(ev, M_DEVBUF);
}
/*
@ -137,7 +168,7 @@ wsevent_read(struct wseventvar *ev, struct uio *uio, int flags)
return (EWOULDBLOCK);
}
ev->wanted = 1;
error = tsleep((caddr_t)ev, PWSEVENT | PCATCH,
error = tsleep(ev, PWSEVENT | PCATCH,
"wsevent_read", 0);
if (error) {
splx(s);
@ -156,7 +187,7 @@ wsevent_read(struct wseventvar *ev, struct uio *uio, int flags)
n = howmany(uio->uio_resid, sizeof(struct wscons_event));
if (cnt > n)
cnt = n;
error = uiomove((caddr_t)&ev->q[ev->get],
error = uiomove(&ev->q[ev->get],
cnt * sizeof(struct wscons_event), uio);
n -= cnt;
/*
@ -169,7 +200,7 @@ wsevent_read(struct wseventvar *ev, struct uio *uio, int flags)
return (error);
if (cnt > n)
cnt = n;
error = uiomove((caddr_t)&ev->q[0],
error = uiomove(&ev->q[0],
cnt * sizeof(struct wscons_event), uio);
ev->get = cnt;
return (error);

View File

@ -1,4 +1,4 @@
/* $NetBSD: wseventvar.h,v 1.2 2001/10/13 15:56:16 augustss Exp $ */
/* $NetBSD: wseventvar.h,v 1.3 2001/10/24 14:07:33 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -99,14 +99,16 @@ struct wseventvar {
selwakeup(&(ev)->sel); \
if ((ev)->wanted) { \
(ev)->wanted = 0; \
wakeup((caddr_t)(ev)); \
wakeup((ev)); \
} \
if ((ev)->async) \
psignal((ev)->io, SIGIO); \
}
void wsevent_init(struct wseventvar *);
struct wseventvar *wsevent_alloc(void);
void wsevent_fini(struct wseventvar *);
void wsevent_free(struct wseventvar *);
int wsevent_read(struct wseventvar *, struct uio *, int);
int wsevent_poll(struct wseventvar *, int, struct proc *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: wskbd.c,v 1.47 2001/10/13 19:58:35 augustss Exp $ */
/* $NetBSD: wskbd.c,v 1.48 2001/10/24 14:07:33 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: wskbd.c,v 1.47 2001/10/13 19:58:35 augustss Exp $");
__KERNEL_RCSID(0, "$NetBSD: wskbd.c,v 1.48 2001/10/24 14:07:33 augustss Exp $");
/*
* Copyright (c) 1992, 1993
@ -87,6 +87,11 @@ __KERNEL_RCSID(0, "$NetBSD: wskbd.c,v 1.47 2001/10/13 19:58:35 augustss Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
#include "opt_wsdisplay_compat.h"
#include "wsdisplay.h"
#include "wskbd.h"
#include "wsmux.h"
#include <sys/param.h>
#include <sys/conf.h>
@ -111,11 +116,6 @@ __KERNEL_RCSID(0, "$NetBSD: wskbd.c,v 1.47 2001/10/13 19:58:35 augustss Exp $");
#include <dev/wscons/wseventvar.h>
#include <dev/wscons/wscons_callbacks.h>
#include "opt_wsdisplay_compat.h"
#include "wsdisplay.h"
#include "wsmux.h"
#ifdef KGDB
#include <sys/kgdb.h>
#endif
@ -127,9 +127,7 @@ int wskbddebug = 0;
#define DPRINTF(x)
#endif
#if NWSMUX > 0 || NWSDISPLAY > 0
#include <dev/wscons/wsmuxvar.h>
#endif
struct wskbd_internal {
const struct wskbd_mapdata *t_keymap;
@ -151,7 +149,7 @@ struct wskbd_internal {
};
struct wskbd_softc {
struct device sc_dv;
struct wsevsrc sc_base;
struct wskbd_internal *id;
@ -160,13 +158,7 @@ struct wskbd_softc {
int sc_ledstate;
int sc_ready; /* accepting events */
struct wseventvar sc_events; /* event queue state */
int sc_isconsole;
#if NWSDISPLAY > 0
struct device *sc_displaydv;
#endif
struct wskbd_bell_data sc_bell_data;
struct wskbd_keyrepeat_data sc_keyrepeat_data;
@ -182,10 +174,6 @@ 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)
@ -211,14 +199,18 @@ struct wskbd_softc {
#define MOD_ONESET(id, mask) (((id)->t_modifiers & (mask)) != 0)
#define MOD_ALLSET(id, mask) (((id)->t_modifiers & (mask)) == (mask))
int wskbd_match(struct device *, struct cfdata *, void *);
void wskbd_attach(struct device *, struct device *, void *);
int wskbd_detach(struct device *, int);
int wskbd_activate(struct device *, enum devact);
static int wskbd_match(struct device *, struct cfdata *, void *);
static void wskbd_attach(struct device *, struct device *, void *);
static int wskbd_detach(struct device *, int);
static int wskbd_activate(struct device *, enum devact);
static int wskbd_displayioctl
(struct device *, u_long, caddr_t, int, struct proc *p);
int wskbd_set_display(struct device *, struct wsmux_softc *);
static int wskbd_displayioctl(struct device *, u_long, caddr_t, int,
struct proc *);
#if NWSDISPLAY > 0
static int wskbd_set_display(struct device *, struct wsevsrc *);
#else
#define wskbd_set_display NULL
#endif
static inline void update_leds(struct wskbd_internal *);
static inline void update_modifier(struct wskbd_internal *, u_int, int, int);
@ -230,10 +222,19 @@ static void change_displayparam(struct wskbd_softc *, int, int, int);
static void wskbd_holdscreen(struct wskbd_softc *, int);
#endif
int wskbd_do_ioctl(struct wskbd_softc *, u_long, caddr_t, int,struct proc*);
static int wskbd_do_ioctl_sc(struct wskbd_softc *, u_long, caddr_t, int,
struct proc *);
int wskbddoclose(struct device *, int, int, struct proc *);
int wskbddoioctl(struct device *, u_long, caddr_t, int, struct proc *);
#if NWSMUX > 0
static int wskbd_mux_open(struct wsevsrc *, struct wseventvar *);
static int wskbd_mux_close(struct wsevsrc *);
#else
#define wskbd_mux_open NULL
#define wskbd_mux_close NULL
#endif
static int wskbd_do_open(struct wskbd_softc *, struct wseventvar *);
static int wskbd_do_ioctl(struct device *, u_long, caddr_t, int, struct proc *);
struct cfattach wskbd_ca = {
sizeof (struct wskbd_softc), wskbd_match, wskbd_attach,
@ -274,10 +275,11 @@ struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data = {
cdev_decl(wskbd);
#if NWSMUX > 0 || NWSDISPLAY > 0
struct wsmuxops wskbd_muxops = {
wskbdopen, wskbddoclose, wskbddoioctl, wskbd_displayioctl,
wskbd_set_display
#if NWSDISPLAY > 0 || NWSMUX > 0
struct wssrcops wskbd_srcops = {
WSMUX_KBD,
wskbd_mux_open, wskbd_mux_close, wskbd_do_ioctl,
wskbd_displayioctl, wskbd_set_display
};
#endif
@ -345,23 +347,26 @@ wskbd_attach(struct device *parent, struct device *self, void *aux)
{
struct wskbd_softc *sc = (struct wskbd_softc *)self;
struct wskbddev_attach_args *ap = aux;
#if NWSMUX > 0 || NWSDISPLAY > 0
int mux;
#if NWSMUX > 0
int mux, error;
#endif
#if NWSDISPLAY > 0
sc->sc_displaydv = NULL;
#endif
sc->sc_isconsole = ap->console;
#if NWSMUX > 0 || NWSDISPLAY > 0
mux = sc->sc_dv.dv_cfdata->wskbddevcf_mux;
if (sc->sc_isconsole && mux != WSKBDDEVCF_MUX_DEFAULT) {
printf(" (mux %d ignored for console)", mux);
mux = WSKBDDEVCF_MUX_DEFAULT;
sc->sc_base.me_ops = &wskbd_srcops;
#endif
#if NWSMUX > 0
mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux;
if (sc->sc_isconsole && mux >= 0) {
/* printf(" (mux %d ignored for console)", mux); */
mux = -1;
}
if (mux != WSKBDDEVCF_MUX_DEFAULT)
if (mux >= 0)
printf(" mux %d", mux);
#else
if (sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux >= 0)
printf(" (mux ignored)");
#endif
if (ap->console) {
@ -380,7 +385,6 @@ wskbd_attach(struct device *parent, struct device *self, void *aux)
sc->sc_accessops = ap->accessops;
sc->sc_accesscookie = ap->accesscookie;
sc->sc_ready = 0; /* sanity */
sc->sc_repeating = 0;
sc->sc_translating = 1;
sc->sc_ledstate = -1; /* force update */
@ -404,18 +408,21 @@ wskbd_attach(struct device *parent, struct device *self, void *aux)
printf(": console keyboard");
#if NWSDISPLAY > 0
if ((sc->sc_displaydv = wsdisplay_set_console_kbd(self)))
printf(", using %s", sc->sc_displaydv->dv_xname);
sc->sc_base.me_dispdv = wsdisplay_set_console_kbd(&sc->sc_base);
if (sc->sc_base.me_dispdv != NULL)
printf(", using %s", sc->sc_base.me_dispdv->dv_xname);
#endif
}
printf("\n");
#if NWSMUX > 0
if (mux != WSKBDDEVCF_MUX_DEFAULT)
wsmux_attach(mux, WSMUX_KBD, &sc->sc_dv, &sc->sc_events,
&sc->sc_mux, &wskbd_muxops);
if (mux != WSKBDDEVCF_MUX_DEFAULT) {
error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base);
if (error)
printf("%s: attach error=%d\n",
sc->sc_base.me_dv.dv_xname, error);
}
#endif
}
void
@ -469,10 +476,10 @@ wskbd_repeat(void *v)
splx(s);
return;
}
if (sc->sc_displaydv != NULL) {
if (sc->sc_base.me_dispdv != NULL) {
int i;
for (i = 0; i < sc->sc_repeating; i++)
wsdisplay_kbdinput(sc->sc_displaydv,
wsdisplay_kbdinput(sc->sc_base.me_dispdv,
sc->id->t_symbols[i]);
}
callout_reset(&sc->sc_repeat_ch,
@ -484,7 +491,10 @@ wskbd_repeat(void *v)
int
wskbd_activate(struct device *self, enum devact act)
{
/* XXX should we do something more? */
struct wskbd_softc *sc = (struct wskbd_softc *)self;
if (act == DVACT_DEACTIVATE)
sc->sc_dying = 1;
return (0);
}
@ -503,16 +513,15 @@ wskbd_detach(struct device *self, int flags)
struct wseventvar *evar;
int maj, mn;
int s;
#if NWSMUX > 0
int mux;
mux = sc->sc_dv.dv_cfdata->wskbddevcf_mux;
if (mux != WSMOUSEDEVCF_MUX_DEFAULT)
wsmux_detach(mux, &sc->sc_dv);
#if NWSMUX > 0
/* Tell parent mux we're leaving. */
if (sc->sc_base.me_parent != NULL)
wsmux_detach_sc(&sc->sc_base);
#endif
evar = &sc->sc_events;
if (evar->io) {
evar = sc->sc_base.me_evp;
if (evar != NULL && evar->io != NULL) {
s = spltty();
if (--sc->sc_refcnt >= 0) {
/* Wake everyone by generating a dummy event. */
@ -522,7 +531,7 @@ wskbd_detach(struct device *self, int flags)
/* Wait for processes to go away. */
if (tsleep(sc, PZERO, "wskdet", hz * 60))
printf("wskbd_detach: %s didn't detach\n",
sc->sc_dv.dv_xname);
sc->sc_base.me_dv.dv_xname);
}
splx(s);
}
@ -545,7 +554,7 @@ wskbd_input(struct device *dev, u_int type, int value)
struct wskbd_softc *sc = (struct wskbd_softc *)dev;
struct wscons_event *ev;
struct wseventvar *evar;
struct timeval xxxtime;
struct timeval thistime;
#if NWSDISPLAY > 0
int num, i;
#endif
@ -564,9 +573,10 @@ wskbd_input(struct device *dev, u_int type, int value)
if (sc->sc_translating) {
num = wskbd_translate(sc->id, type, value);
if (num > 0) {
if (sc->sc_displaydv != NULL) {
if (sc->sc_base.me_dispdv != NULL) {
for (i = 0; i < num; i++)
wsdisplay_kbdinput(sc->sc_displaydv,
wsdisplay_kbdinput(
sc->sc_base.me_dispdv,
sc->id->t_symbols[i]);
}
@ -585,29 +595,24 @@ wskbd_input(struct device *dev, u_int type, int value)
* keystroke is lost (sorry!).
*/
/* no one to receive; punt!*/
if (!sc->sc_ready)
evar = sc->sc_base.me_evp;
if (evar == NULL) {
DPRINTF(("wskbd_input: not open\n"));
return;
#if NWSMUX > 0
if (sc->sc_mux)
evar = &sc->sc_mux->sc_events;
else
#endif
evar = &sc->sc_events;
}
put = evar->put;
ev = &evar->q[put];
put = (put + 1) % WSEVENT_QSIZE;
if (put == evar->get) {
log(LOG_WARNING, "%s: event queue overflow\n",
sc->sc_dv.dv_xname);
sc->sc_base.me_dv.dv_xname);
return;
}
ev->type = type;
ev->value = value;
microtime(&xxxtime);
TIMEVAL_TO_TIMESPEC(&xxxtime, &ev->time);
microtime(&thistime);
TIMEVAL_TO_TIMESPEC(&thistime, &ev->time);
evar->put = put;
WSEVENT_WAKEUP(evar);
}
@ -620,9 +625,9 @@ wskbd_rawinput(struct device *dev, u_char *buf, int len)
struct wskbd_softc *sc = (struct wskbd_softc *)dev;
int i;
if (sc->sc_displaydv != NULL)
if (sc->sc_base.me_dispdv != NULL)
for (i = 0; i < len; i++)
wsdisplay_kbdinput(sc->sc_displaydv, buf[i]);
wsdisplay_kbdinput(sc->sc_base.me_dispdv, buf[i]);
/* this is KS_GROUP_Ascii */
#endif
}
@ -634,8 +639,8 @@ wskbd_holdscreen(struct wskbd_softc *sc, int hold)
{
int new_state;
if (sc->sc_displaydv != NULL) {
wsdisplay_kbdholdscreen(sc->sc_displaydv, hold);
if (sc->sc_base.me_dispdv != NULL) {
wsdisplay_kbdholdscreen(sc->sc_base.me_dispdv, hold);
new_state = sc->sc_ledstate;
if (hold)
new_state |= WSKBD_LED_SCROLL;
@ -653,56 +658,90 @@ wskbd_holdscreen(struct wskbd_softc *sc, int hold)
static int
wskbd_enable(struct wskbd_softc *sc, int on)
{
int res;
int error;
/* XXX reference count? */
#if 0
/* I don't understand the purpose of this code. And it seems to
* break things, so it's out. -- Lennart
*/
if (!on && (!sc->sc_translating
#if NWSDISPLAY > 0
|| sc->sc_displaydv
|| sc->sc_base.me_dispdv
#endif
))
return (EBUSY);
#endif
res = (*sc->sc_accessops->enable)(sc->sc_accesscookie, on);
return (res);
error = (*sc->sc_accessops->enable)(sc->sc_accesscookie, on);
DPRINTF(("wskbd_enable: sc=%p on=%d res=%d\n", sc, on, error));
return (error);
}
#if NWSMUX > 0
int
wskbd_mux_open(struct wsevsrc *me, struct wseventvar *evp)
{
struct wskbd_softc *sc = (struct wskbd_softc *)me;
if (sc->sc_base.me_evp != NULL)
return (EBUSY);
return wskbd_do_open(sc, evp);
}
#endif
int
wskbdopen(dev_t dev, int flags, int mode, struct proc *p)
{
struct wskbd_softc *sc;
int unit;
struct wseventvar *evar;
int unit, error;
unit = minor(dev);
if (unit >= wskbd_cd.cd_ndevs || /* make sure it was attached */
(sc = wskbd_cd.cd_devs[unit]) == NULL)
return (ENXIO);
#if NWSMUX > 0
DPRINTF(("wskbdopen: %s mux=%p p=%p\n", sc->sc_base.me_dv.dv_xname,
sc->sc_base.me_parent, p));
#endif
if (sc->sc_dying)
return (EIO);
if (!(flags & FREAD)) {
if ((flags & (FREAD | FWRITE)) == FWRITE)
/* Not opening for read, only ioctl is available. */
return (0);
}
#if NWSMUX > 0
if (sc->sc_mux) {
if (sc->sc_base.me_parent != NULL)
/* Grab the keyboard out of the greedy hands of the mux. */
int error = wskbd_rem_mux(unit, sc->sc_mux);
if (error)
return (error);
}
wsmux_detach_sc(&sc->sc_base);
#endif
if (sc->sc_events.io) /* and that it's not in use */
if (sc->sc_base.me_evp != NULL)
return (EBUSY);
sc->sc_events.io = p;
wsevent_init(&sc->sc_events); /* may cause sleep */
evar = wsevent_alloc();
sc->sc_base.me_evp = evar;
evar->io = p;
error = wskbd_do_open(sc, evar);
if (error) {
DPRINTF(("wskbdopen: %s open failed\n",
sc->sc_base.me_dv.dv_xname));
sc->sc_base.me_evp = NULL;
wsevent_free(evar);
}
return (error);
}
int
wskbd_do_open(struct wskbd_softc *sc, struct wseventvar *evp)
{
sc->sc_base.me_evp = evp;
sc->sc_translating = 0;
sc->sc_ready = 1; /* start accepting events */
wskbd_enable(sc, 1);
return (0);
@ -711,29 +750,36 @@ wskbdopen(dev_t dev, int flags, int mode, struct proc *p)
int
wskbdclose(dev_t dev, int flags, int mode, struct proc *p)
{
return (wskbddoclose(wskbd_cd.cd_devs[minor(dev)], flags, mode, p));
}
struct wskbd_softc *sc =
(struct wskbd_softc *)wskbd_cd.cd_devs[minor(dev)];
struct wseventvar *evar = sc->sc_base.me_evp;
int
wskbddoclose(struct device *dv, int flags, int mode, struct proc *p)
{
struct wskbd_softc *sc = (struct wskbd_softc *)dv;
if (!(flags & FREAD)) {
/* Nothing to do, because open didn't do anything. */
if (evar == NULL)
/* not open for read */
return (0);
}
sc->sc_ready = 0; /* stop accepting events */
sc->sc_base.me_evp = NULL;
sc->sc_translating = 1;
wsevent_fini(&sc->sc_events);
sc->sc_events.io = NULL;
wskbd_enable(sc, 0);
wsevent_free(evar);
return (0);
}
#if NWSMUX > 0
int
wskbd_mux_close(struct wsevsrc *me)
{
struct wskbd_softc *sc = (struct wskbd_softc *)me;
sc->sc_base.me_evp = NULL;
sc->sc_translating = 1;
wskbd_enable(sc, 0);
return (0);
}
#endif
int
wskbdread(dev_t dev, struct uio *uio, int flags)
{
@ -743,8 +789,15 @@ wskbdread(dev_t dev, struct uio *uio, int flags)
if (sc->sc_dying)
return (EIO);
#ifdef DIAGNOSTIC
if (sc->sc_base.me_evp == NULL) {
printf("wskbdread: evp == NULL\n");
return (EINVAL);
}
#endif
sc->sc_refcnt++;
error = wsevent_read(&sc->sc_events, uio, flags);
error = wsevent_read(sc->sc_base.me_evp, uio, flags);
if (--sc->sc_refcnt < 0) {
wakeup(sc);
error = EIO;
@ -755,27 +808,27 @@ wskbdread(dev_t dev, struct uio *uio, int flags)
int
wskbdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
return (wskbddoioctl(wskbd_cd.cd_devs[minor(dev)], cmd, data, flag,p));
return (wskbd_do_ioctl(wskbd_cd.cd_devs[minor(dev)], cmd, data, flag,p));
}
/* A wrapper around the ioctl() workhorse to make reference counting easy. */
int
wskbddoioctl(struct device *dv, u_long cmd, caddr_t data, int flag,
wskbd_do_ioctl(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++;
error = wskbd_do_ioctl(sc, cmd, data, flag, p);
error = wskbd_do_ioctl_sc(sc, cmd, data, flag, p);
if (--sc->sc_refcnt < 0)
wakeup(sc);
return (error);
}
int
wskbd_do_ioctl(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag,
struct proc *p)
wskbd_do_ioctl_sc(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag,
struct proc *p)
{
int error;
@ -787,11 +840,15 @@ wskbd_do_ioctl(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag,
return (0);
case FIOASYNC:
sc->sc_events.async = *(int *)data != 0;
if (sc->sc_base.me_evp == NULL)
return (EINVAL);
sc->sc_base.me_evp->async = *(int *)data != 0;
return (0);
case TIOCSPGRP:
if (*(int *)data != sc->sc_events.io->p_pgid)
if (sc->sc_base.me_evp == NULL)
return (EINVAL);
if (*(int *)data != sc->sc_base.me_evp->io->p_pgid)
return (EPERM);
return (0);
}
@ -800,7 +857,7 @@ wskbd_do_ioctl(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag,
* Try the keyboard driver for WSKBDIO ioctls. It returns -1
* if it didn't recognize the request.
*/
error = wskbd_displayioctl((struct device *)sc, cmd, data, flag, p);
error = wskbd_displayioctl(&sc->sc_base.me_dv, cmd, data, flag, p);
return (error != -1 ? error : ENOTTY);
}
@ -1005,7 +1062,9 @@ wskbdpoll(dev_t dev, int events, struct proc *p)
{
struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
return (wsevent_poll(&sc->sc_events, events, p));
if (sc->sc_base.me_evp == NULL)
return (EINVAL);
return (wsevent_poll(sc->sc_base.me_evp, events, p));
}
#if NWSDISPLAY > 0
@ -1019,99 +1078,86 @@ wskbd_pickfree(void)
for (i = 0; i < wskbd_cd.cd_ndevs; i++) {
if ((sc = wskbd_cd.cd_devs[i]) == NULL)
continue;
if (sc->sc_displaydv == NULL)
if (sc->sc_base.me_dispdv == NULL)
return (i);
}
return (-1);
}
struct device *
wskbd_set_console_display(struct device *displaydv, struct wsmux_softc *muxsc)
struct wsevsrc *
wskbd_set_console_display(struct device *displaydv, struct wsevsrc *me)
{
struct wskbd_softc *sc = wskbd_console_device;
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);
if (sc == NULL)
return (NULL);
sc->sc_base.me_dispdv = displaydv;
#if NWSMUX > 0
(void)wsmux_attach_sc((struct wsmux_softc *)me, &sc->sc_base);
#endif
return (&sc->sc_base);
}
int
wskbd_set_display(struct device *dv, struct wsmux_softc *muxsc)
wskbd_set_display(struct device *dv, struct wsevsrc *me)
{
struct wskbd_softc *sc = (struct wskbd_softc *)dv;
struct device *displaydv = muxsc ? muxsc->sc_displaydv : 0;
struct device *displaydv = me != NULL ? me->me_dispdv : NULL;
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,
DPRINTF(("wskbd_set_display: %s me=%p disp=%p odisp=%p cons=%d\n",
dv->dv_xname, me, sc->sc_base.me_dispdv, displaydv,
sc->sc_isconsole));
if (sc->sc_isconsole)
return (EBUSY);
if (displaydv) {
if (sc->sc_displaydv)
if (displaydv != NULL) {
if (sc->sc_base.me_dispdv != NULL)
return (EBUSY);
} else {
if (sc->sc_displaydv == NULL)
if (sc->sc_base.me_dispdv == NULL)
return (ENXIO);
}
odisplaydv = sc->sc_displaydv;
sc->sc_displaydv = displaydv;
odisplaydv = sc->sc_base.me_dispdv;
sc->sc_base.me_dispdv = displaydv;
error = wskbd_enable(sc, displaydv != NULL);
if (error) {
sc->sc_displaydv = odisplaydv;
sc->sc_base.me_dispdv = odisplaydv;
return (error);
}
if (displaydv)
printf("%s: connecting to %s\n",
sc->sc_dv.dv_xname, displaydv->dv_xname);
sc->sc_base.me_dv.dv_xname, displaydv->dv_xname);
else
printf("%s: disconnecting from %s\n",
sc->sc_dv.dv_xname, odisplaydv->dv_xname);
sc->sc_base.me_dv.dv_xname, odisplaydv->dv_xname);
return (0);
}
#endif /* NWSDISPLAY > 0 */
#if NWSMUX > 0
int
wskbd_add_mux(int unit, struct wsmux_softc *muxsc)
{
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)
if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL)
return (EBUSY);
return (wsmux_attach_sc(muxsc, WSMUX_KBD, &sc->sc_dv, &sc->sc_events,
&sc->sc_mux, &wskbd_muxops));
return (wsmux_attach_sc(muxsc, &sc->sc_base));
}
int
wskbd_rem_mux(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 */
#endif
/*
* Console interface.
@ -1219,11 +1265,11 @@ change_displayparam(struct wskbd_softc *sc, int param, int updown,
int res;
struct wsdisplay_param dp;
if (sc->sc_displaydv == NULL)
if (sc->sc_base.me_dispdv == NULL)
return;
dp.param = param;
res = wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_GETPARAM, &dp);
res = wsdisplay_param(sc->sc_base.me_dispdv, WSDISPLAYIO_GETPARAM, &dp);
if (res == EINVAL)
return; /* no such parameter */
@ -1234,7 +1280,7 @@ change_displayparam(struct wskbd_softc *sc, int param, int updown,
else
if (dp.curval < dp.min)
dp.curval = wraparound ? dp.max : dp.min;
wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_SETPARAM, &dp);
wsdisplay_param(sc->sc_base.me_dispdv, WSDISPLAYIO_SETPARAM, &dp);
}
#endif
@ -1289,13 +1335,13 @@ internal_command(struct wskbd_softc *sc, u_int *type, keysym_t ksym,
case KS_Cmd_Screen7:
case KS_Cmd_Screen8:
case KS_Cmd_Screen9:
wsdisplay_switch(sc->sc_displaydv, ksym - KS_Cmd_Screen0, 0);
wsdisplay_switch(sc->sc_base.me_dispdv, ksym - KS_Cmd_Screen0, 0);
return (1);
case KS_Cmd_ResetEmul:
wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETEMUL);
wsdisplay_reset(sc->sc_base.me_dispdv, WSDISPLAY_RESETEMUL);
return (1);
case KS_Cmd_ResetClose:
wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETCLOSE);
wsdisplay_reset(sc->sc_base.me_dispdv, WSDISPLAY_RESETCLOSE);
return (1);
case KS_Cmd_BacklightOn:
case KS_Cmd_BacklightOff:

View File

@ -1,4 +1,4 @@
/* $NetBSD: wsmouse.c,v 1.16 2001/10/13 19:56:09 augustss Exp $ */
/* $NetBSD: wsmouse.c,v 1.17 2001/10/24 14:07:33 augustss Exp $ */
/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.16 2001/10/13 19:56:09 augustss Exp $");
__KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.17 2001/10/24 14:07:33 augustss Exp $");
/*
* Copyright (c) 1992, 1993
@ -81,6 +81,10 @@ __KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.16 2001/10/13 19:56:09 augustss Exp $"
* Mouse driver.
*/
#include "wsmouse.h"
#include "wsdisplay.h"
#include "wsmux.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/ioctl.h>
@ -97,14 +101,15 @@ __KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.16 2001/10/13 19:56:09 augustss Exp $"
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>
#include <dev/wscons/wseventvar.h>
#include "wsmouse.h"
#include "wsmux.h"
#include "wsdisplay.h"
#include "wskbd.h"
#if NWSMUX > 0
#include <dev/wscons/wsmuxvar.h>
#if defined(WSMUX_DEBUG) && NWSMUX > 0
#define DPRINTF(x) if (wsmuxdebug) printf x
#define DPRINTFN(n,x) if (wsmuxdebug > (n)) printf x
extern int wsmuxdebug;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
#endif
#define INVALID_X INT_MAX
@ -112,14 +117,11 @@ __KERNEL_RCSID(0, "$NetBSD: wsmouse.c,v 1.16 2001/10/13 19:56:09 augustss Exp $"
#define INVALID_Z INT_MAX
struct wsmouse_softc {
struct device sc_dv;
struct wsevsrc sc_base;
const struct wsmouse_accessops *sc_accessops;
void *sc_accesscookie;
int sc_ready; /* accepting events */
struct wseventvar sc_events; /* event queue state */
u_int sc_mb; /* mouse button state */
u_int sc_ub; /* user button state */
int sc_dx; /* delta-x */
@ -131,22 +133,24 @@ struct wsmouse_softc {
int sc_refcnt;
u_char sc_dying; /* device is being detached */
#if NWSMUX > 0
struct wsmux_softc *sc_mux;
#endif
};
int wsmouse_match(struct device *, struct cfdata *, void *);
void wsmouse_attach(struct device *, struct device *, void *);
int wsmouse_detach(struct device *, int);
int wsmouse_activate(struct device *, enum devact);
static int wsmouse_match(struct device *, struct cfdata *, void *);
static void wsmouse_attach(struct device *, struct device *, void *);
static int wsmouse_detach(struct device *, int);
static int wsmouse_activate(struct device *, enum devact);
int wsmouse_do_ioctl(struct wsmouse_softc *, u_long, caddr_t,
int, struct proc *);
static int wsmouse_do_ioctl(struct wsmouse_softc *, u_long, caddr_t,
int, struct proc *);
int wsmousedoclose(struct device *, int, int, struct proc *);
int wsmousedoioctl(struct device *, u_long, caddr_t, int, struct proc *);
#if NWSMUX > 0
static int wsmouse_mux_open(struct wsevsrc *, struct wseventvar *);
static int wsmouse_mux_close(struct wsevsrc *);
#endif
static int wsmousedoioctl(struct device *, u_long, caddr_t, int, struct proc *);
static int wsmousedoopen(struct wsmouse_softc *, struct wseventvar *);
struct cfattach wsmouse_ca = {
sizeof (struct wsmouse_softc), wsmouse_match, wsmouse_attach,
@ -160,8 +164,9 @@ extern struct cfdriver wsmouse_cd;
cdev_decl(wsmouse);
#if NWSMUX > 0
struct wsmuxops wsmouse_muxops = {
wsmouseopen, wsmousedoclose, wsmousedoioctl, 0, 0
struct wssrcops wsmouse_srcops = {
WSMUX_MOUSE,
wsmouse_mux_open, wsmouse_mux_close, wsmousedoioctl, NULL, NULL
};
#endif
@ -189,20 +194,25 @@ wsmouse_attach(struct device *parent, struct device *self, void *aux)
struct wsmouse_softc *sc = (struct wsmouse_softc *)self;
struct wsmousedev_attach_args *ap = aux;
#if NWSMUX > 0
int mux;
int mux, error;
#endif
sc->sc_accessops = ap->accessops;
sc->sc_accesscookie = ap->accesscookie;
sc->sc_ready = 0; /* sanity */
#if NWSMUX > 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);
sc->sc_base.me_ops = &wsmouse_srcops;
mux = sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_mux;
if (mux >= 0) {
error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base);
if (error)
printf(" attach error=%d", error);
else
printf(" mux %d", mux);
}
#else
if (sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_mux >= 0)
printf(" (mux ignored)");
#endif
printf("\n");
@ -211,7 +221,10 @@ wsmouse_attach(struct device *parent, struct device *self, void *aux)
int
wsmouse_activate(struct device *self, enum devact act)
{
/* XXX should we do something more? */
struct wsmouse_softc *sc = (struct wsmouse_softc *)self;
if (act == DVACT_DEACTIVATE)
sc->sc_dying = 1;
return (0);
}
@ -230,20 +243,16 @@ wsmouse_detach(struct device *self, int flags)
struct wseventvar *evar;
int maj, mn;
int s;
#if NWSMUX > 0
int mux;
#endif
sc->sc_dying = 1;
#if NWSMUX > 0
mux = sc->sc_dv.dv_cfdata->wsmousedevcf_mux;
if (mux != WSMOUSEDEVCF_MUX_DEFAULT)
wsmux_detach(mux, &sc->sc_dv);
/* Tell parent mux we're leaving. */
if (sc->sc_base.me_parent != NULL)
wsmux_detach_sc(&sc->sc_base);
#endif
evar = &sc->sc_events;
if (evar->io) {
/* If we're open ... */
evar = sc->sc_base.me_evp;
if (evar != NULL && evar->io != NULL) {
s = spltty();
if (--sc->sc_refcnt >= 0) {
/* Wake everyone by generating a dummy event. */
@ -253,7 +262,7 @@ wsmouse_detach(struct device *self, int flags)
/* Wait for processes to go away. */
if (tsleep(sc, PZERO, "wsmdet", hz * 60))
printf("wsmouse_detach: %s didn't detach\n",
sc->sc_dv.dv_xname);
sc->sc_base.me_dv.dv_xname);
}
splx(s);
}
@ -280,17 +289,16 @@ wsmouse_input(struct device *wsmousedev, u_int btns /* 0 is up */,
int mb, ub, d, get, put, any;
/*
* Discard input if not ready.
* Discard input if not open.
*/
if (sc->sc_ready == 0)
evar = sc->sc_base.me_evp;
if (evar == NULL)
return;
#if NWSMUX > 0
if (sc->sc_mux)
evar = &sc->sc_mux->sc_events;
else
DPRINTFN(5,("wsmouse_input: %s mux=%p, evar=%p\n",
sc->sc_base.me_dv.dv_xname, sc->sc_base.me_parent, evar));
#endif
evar = &sc->sc_events;
sc->sc_mb = btns;
if (!(flags & WSMOUSE_INPUT_ABSOLUTE_X))
@ -423,8 +431,8 @@ out:
int
wsmouseopen(dev_t dev, int flags, int mode, struct proc *p)
{
#if NWSMOUSE > 0
struct wsmouse_softc *sc;
struct wseventvar *evar;
int error, unit;
unit = minor(dev);
@ -432,6 +440,11 @@ wsmouseopen(dev_t dev, int flags, int mode, struct proc *p)
(sc = wsmouse_cd.cd_devs[unit]) == NULL)
return (ENXIO);
#if NWSMUX > 0
DPRINTF(("wsmouseopen: %s mux=%p p=%p\n", sc->sc_base.me_dv.dv_xname,
sc->sc_base.me_parent, p));
#endif
if (sc->sc_dying)
return (EIO);
@ -440,103 +453,89 @@ wsmouseopen(dev_t dev, int flags, int mode, struct proc *p)
so ioctl() is possible. */
#if NWSMUX > 0
if (sc->sc_mux != NULL) {
if (sc->sc_base.me_parent != NULL)
/* Grab the mouse out of the greedy hands of the mux. */
error = wsmouse_rem_mux(unit, sc->sc_mux);
if (error)
return (error);
}
wsmux_detach_sc(&sc->sc_base);
#endif
if (sc->sc_events.io) /* and that it's not in use */
if (sc->sc_base.me_evp != NULL)
return (EBUSY);
sc->sc_events.io = p;
wsevent_init(&sc->sc_events); /* may cause sleep */
evar = wsevent_alloc();
sc->sc_base.me_evp = evar;
evar->io = p;
sc->sc_ready = 1; /* start accepting events */
sc->sc_x = INVALID_X;
sc->sc_y = INVALID_Y;
sc->sc_z = INVALID_Z;
/* enable the device, and punt if that's not possible */
error = (*sc->sc_accessops->enable)(sc->sc_accesscookie);
error = wsmousedoopen(sc, evar);
if (error) {
sc->sc_ready = 0; /* stop accepting events */
wsevent_fini(&sc->sc_events);
sc->sc_events.io = NULL;
return (error);
DPRINTF(("wsmouseopen: %s open failed\n",
sc->sc_base.me_dv.dv_xname));
sc->sc_base.me_evp = NULL;
wsevent_free(evar);
}
return (0);
#else
return (ENXIO);
#endif /* NWSMOUSE > 0 */
return (error);
}
int
wsmouseclose(dev_t dev, int flags, int mode, struct proc *p)
{
#if NWSMOUSE > 0
return (wsmousedoclose(wsmouse_cd.cd_devs[minor(dev)],
flags, mode, p));
#else
return (ENXIO);
#endif /* NWSMOUSE > 0 */
}
#if NWSMOUSE > 0
int
wsmousedoclose(struct device *dv, int flags, int mode, struct proc *p)
{
struct wsmouse_softc *sc = (struct wsmouse_softc *)dv;
if ((flags & (FREAD | FWRITE)) == FWRITE)
return (0); /* see wsmouseopen() */
struct wsmouse_softc *sc =
(struct wsmouse_softc *)wsmouse_cd.cd_devs[minor(dev)];
struct wseventvar *evar = sc->sc_base.me_evp;
if (evar == NULL)
/* not open for read */
return (0);
sc->sc_base.me_evp = NULL;
(*sc->sc_accessops->disable)(sc->sc_accesscookie);
wsevent_free(evar);
sc->sc_ready = 0; /* stop accepting events */
wsevent_fini(&sc->sc_events);
sc->sc_events.io = NULL;
return (0);
}
#endif /* NWSMOUSE > 0 */
int
wsmousedoopen(struct wsmouse_softc *sc, struct wseventvar *evp)
{
sc->sc_base.me_evp = evp;
sc->sc_x = INVALID_X;
sc->sc_y = INVALID_Y;
sc->sc_z = INVALID_Z;
/* enable the device, and punt if that's not possible */
return (*sc->sc_accessops->enable)(sc->sc_accesscookie);
}
int
wsmouseread(dev_t dev, struct uio *uio, int flags)
{
#if NWSMOUSE > 0
struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)];
int error;
if (sc->sc_dying)
return (EIO);
#ifdef DIAGNOSTIC
if (sc->sc_base.me_evp == NULL) {
printf("wsmouseread: evp == NULL\n");
return (EINVAL);
}
#endif
sc->sc_refcnt++;
error = wsevent_read(&sc->sc_events, uio, flags);
error = wsevent_read(sc->sc_base.me_evp, uio, flags);
if (--sc->sc_refcnt < 0) {
wakeup(sc);
error = EIO;
}
return (error);
#else
return (ENXIO);
#endif /* NWSMOUSE > 0 */
}
int
wsmouseioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
#if NWSMOUSE > 0
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(struct device *dv, u_long cmd, caddr_t data, int flag,
@ -569,11 +568,15 @@ wsmouse_do_ioctl(struct wsmouse_softc *sc, u_long cmd, caddr_t data,
return (0);
case FIOASYNC:
sc->sc_events.async = *(int *)data != 0;
if (sc->sc_base.me_evp == NULL)
return (EINVAL);
sc->sc_base.me_evp->async = *(int *)data != 0;
return (0);
case TIOCSPGRP:
if (*(int *)data != sc->sc_events.io->p_pgid)
if (sc->sc_base.me_evp == NULL)
return (EINVAL);
if (*(int *)data != sc->sc_base.me_evp->io->p_pgid)
return (EPERM);
return (0);
}
@ -586,21 +589,40 @@ wsmouse_do_ioctl(struct wsmouse_softc *sc, u_long cmd, caddr_t data,
data, flag, p);
return (error != -1 ? error : ENOTTY);
}
#endif /* NWSMOUSE > 0 */
int
wsmousepoll(dev_t dev, int events, struct proc *p)
{
#if NWSMOUSE > 0
struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)];
return (wsevent_poll(&sc->sc_events, events, p));
#else
return (0);
#endif /* NWSMOUSE > 0 */
if (sc->sc_base.me_evp == NULL)
return (EINVAL);
return (wsevent_poll(sc->sc_base.me_evp, events, p));
}
#if NWSMUX > 0
int
wsmouse_mux_open(struct wsevsrc *me, struct wseventvar *evp)
{
struct wsmouse_softc *sc = (struct wsmouse_softc *)me;
if (sc->sc_base.me_evp != NULL)
return (EBUSY);
return wsmousedoopen(sc, evp);
}
int
wsmouse_mux_close(struct wsevsrc *me)
{
struct wsmouse_softc *sc = (struct wsmouse_softc *)me;
sc->sc_base.me_evp = NULL;
(*sc->sc_accessops->disable)(sc->sc_accesscookie);
return (0);
}
int
wsmouse_add_mux(int unit, struct wsmux_softc *muxsc)
{
@ -610,23 +632,9 @@ wsmouse_add_mux(int unit, struct wsmux_softc *muxsc)
(sc = wsmouse_cd.cd_devs[unit]) == NULL)
return (ENXIO);
if (sc->sc_mux || sc->sc_events.io)
if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL)
return (EBUSY);
return (wsmux_attach_sc(muxsc, WSMUX_MOUSE, &sc->sc_dv, &sc->sc_events,
&sc->sc_mux, &wsmouse_muxops));
return (wsmux_attach_sc(muxsc, &sc->sc_base));
}
int
wsmouse_rem_mux(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
#endif /* NWSMUX > 0 */

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: wsmuxvar.h,v 1.3 2001/10/13 15:56:16 augustss Exp $ */
/* $NetBSD: wsmuxvar.h,v 1.4 2001/10/24 14:07:33 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -36,52 +36,58 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
struct wsdisplay_softc;
struct wsplink;
/*
* A ws event source, i.e., wskbd, wsmouse, or wsmux.
*/
struct wsevsrc {
struct device me_dv;
const struct wssrcops *me_ops; /* method pointers */
struct wseventvar *me_evp; /* our wseventvar when open */
#if NWSDISPLAY > 0
struct device *me_dispdv; /* our display if part of one */
#endif
#if NWSMUX > 0
struct wsmux_softc *me_parent; /* parent mux device */
CIRCLEQ_ENTRY(wsevsrc) me_next; /* sibling pointers */
#endif
};
/*
* Methods that can be performed on an events source. Usually called
* from a wsmux.
*/
struct wssrcops {
int type; /* device type: WSMUX_{MOUSE,KBD,MUX} */
int (*dopen)(struct wsevsrc *, struct wseventvar *);
int (*dclose)(struct wsevsrc *);
int (*dioctl)(struct device *, u_long, caddr_t, int, struct proc *);
int (*ddispioctl)(struct device *, u_long, caddr_t, int, struct proc *);
int (*dsetdisplay)(struct device *, struct wsevsrc *);
};
#define wsevsrc_ioctl(me, cmd, data, flag, p) \
((me)->me_ops->dioctl(&(me)->me_dv, cmd, (caddr_t)data, flag, p))
#define wsevsrc_display_ioctl(me, cmd, data, flag, p) \
((me)->me_ops->ddispioctl(&(me)->me_dv, cmd, (caddr_t)data, flag, p))
#define wsevsrc_set_display(me, arg) \
((me)->me_ops->dsetdisplay(&(me)->me_dv, arg))
#if NWSMUX > 0
struct wsmux_softc {
struct device sc_dv;
struct wseventvar sc_events; /* event queue state */
int sc_flags, sc_mode; /* open flags */
struct wsevsrc sc_base;
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 */
CIRCLEQ_HEAD(, wsevsrc) sc_cld; /* list of children */
#ifdef WSDISPLAY_COMPAT_RAWKBD
int sc_rawkbd; /* A hack to remember the kbd mode */
#endif
};
struct wsmuxops {
int (*dopen)(dev_t, int, int, struct proc *);
int (*dclose)(struct device *, int, int, struct proc *);
int (*dioctl)(struct device *, u_long, caddr_t, int, struct proc *);
int (*ddispioctl)(struct device *, u_long, caddr_t, int, struct proc *);
int (*dsetdisplay)(struct device *, struct wsmux_softc *);
};
struct wsmux_softc *wsmux_getmux(int);
struct wsmux_softc *wsmux_create(const char *, int);
int wsmux_attach_sc(struct wsmux_softc *, struct wsevsrc *);
void wsmux_detach_sc(struct wsevsrc *);
struct wsmux_softc *wsmux_getmux(int);
struct wsmux_softc *wsmux_create(const char *, int);
int wsmux_attach_sc(
struct wsmux_softc *,
int, struct device *, struct wseventvar *,
struct wsmux_softc **,
struct wsmuxops *);
int wsmux_detach_sc(struct wsmux_softc *, struct device *);
void wsmux_attach(
int, int, struct device *, struct wseventvar *,
struct wsmux_softc **,
struct wsmuxops *);
void wsmux_detach(int, struct device *);
int wsmux_displayioctl(struct device *dev, u_long cmd,
caddr_t data, int flag, struct proc *p);
int wsmuxdoioctl(struct device *, u_long, caddr_t,int,struct proc *);
int wsmux_add_mux(int, struct wsmux_softc *);
int wsmux_rem_mux(int, struct wsmux_softc *);
int wskbd_add_mux(int, struct wsmux_softc *);
int wskbd_rem_mux(int, struct wsmux_softc *);
int wsmouse_add_mux(int, struct wsmux_softc *);
int wsmouse_rem_mux(int, struct wsmux_softc *);
#endif /* NWSMUX > 0 */