summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authoraugustss <augustss@NetBSD.org>1999-06-30 06:21:21 +0000
committeraugustss <augustss@NetBSD.org>1999-06-30 06:21:21 +0000
commitdd048d428b1ea9f2e04762af75b62784b1b8a2e1 (patch)
tree4f8b8d7c019c449131dfe0a60d7097f6625ef270 /sys/dev
parentb57c6ad0bc7766973b13197fc8ff3bc60270b159 (diff)
Make it possible to detach wsmouse and wskbd.
XXX wskbd probably needs some more work.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/wscons/wskbd.c118
-rw-r--r--sys/dev/wscons/wsmouse.c136
2 files changed, 230 insertions, 24 deletions
diff --git a/sys/dev/wscons/wskbd.c b/sys/dev/wscons/wskbd.c
index c982d8b214f..a8121bf99c0 100644
--- a/sys/dev/wscons/wskbd.c
+++ b/sys/dev/wscons/wskbd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wskbd.c,v 1.23 1999/05/16 19:21:31 thorpej Exp $ */
+/* $NetBSD: wskbd.c,v 1.24 1999/06/30 06:21:21 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.23 1999/05/16 19:21:31 thorpej Exp $";
+ "$NetBSD: wskbd.c,v 1.24 1999/06/30 06:21:21 augustss Exp $";
/*
* Copyright (c) 1992, 1993
@@ -102,6 +102,7 @@ static const char _rcsid[] __attribute__ ((unused)) =
#include <sys/signalvar.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
+#include <sys/vnode.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wskbdvar.h>
@@ -156,6 +157,10 @@ struct wskbd_softc {
int sc_maplen; /* number of entries in sc_map */
struct wscons_keymap *sc_map; /* current translation map */
kbd_t sc_layout; /* current layout */
+
+ int sc_refcnt;
+ u_char sc_dying; /* device is being detached */
+
};
#define MOD_SHIFT_L (1 << 0)
@@ -183,6 +188,9 @@ struct wskbd_softc {
int wskbd_match __P((struct device *, struct cfdata *, void *));
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 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));
@@ -192,6 +200,9 @@ static int wskbd_enable __P((struct wskbd_softc *, int));
static void wskbd_holdscreen __P((struct wskbd_softc *, int));
#endif
+int wskbd_do_ioctl __P((struct wskbd_softc *, u_long, caddr_t,
+ int, struct proc *));
+
struct cfattach wskbd_ca = {
sizeof (struct wskbd_softc), wskbd_match, wskbd_attach,
};
@@ -384,6 +395,62 @@ wskbd_repeat(v)
}
#endif
+int
+wskbd_activate(self, act)
+ struct device *self;
+ enum devact act;
+{
+ /* XXX should we do something more? */
+ return (0);
+}
+
+/*
+ * 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
+ * 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)
+ struct device *self;
+ int flags;
+{
+ struct wskbd_softc *sc = (struct wskbd_softc *)self;
+ struct wseventvar *evar;
+ int maj, mn;
+ int s;
+
+ evar = &sc->sc_events;
+ if (evar->io) {
+ s = spltty();
+ if (--sc->sc_refcnt >= 0) {
+ /* Wake everyone by generating a dummy event. */
+ if (++evar->put >= WSEVENT_QSIZE)
+ evar->put = 0;
+ WSEVENT_WAKEUP(evar);
+ /* 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);
+ }
+ splx(s);
+ }
+
+ /* locate the major number */
+ for (maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == wskbdopen)
+ break;
+
+ /* Nuke the vnodes for any open instances. */
+ mn = self->dv_unit;
+ vdevgone(maj, mn, mn, VCHR);
+
+ return (0);
+}
+
void
wskbd_input(dev, type, value)
struct device *dev;
@@ -392,6 +459,7 @@ wskbd_input(dev, type, value)
{
struct wskbd_softc *sc = (struct wskbd_softc *)dev;
struct wscons_event *ev;
+ struct wseventvar *evar;
struct timeval xxxtime;
#if NWSDISPLAY > 0
keysym_t ks;
@@ -405,7 +473,7 @@ wskbd_input(dev, type, value)
}
/*
- * If /dev/kbd is not connected in event mode translate and
+ * If /dev/wskbd is not connected in event mode translate and
* send upstream.
*/
if (sc->sc_translating) {
@@ -434,10 +502,12 @@ wskbd_input(dev, type, value)
if (!sc->sc_ready)
return;
- put = sc->sc_events.put;
- ev = &sc->sc_events.q[put];
+ evar = &sc->sc_events;
+
+ put = evar->put;
+ ev = &evar->q[put];
put = (put + 1) % WSEVENT_QSIZE;
- if (put == sc->sc_events.get) {
+ if (put == evar->get) {
log(LOG_WARNING, "%s: event queue overflow\n",
sc->sc_dv.dv_xname);
return;
@@ -446,8 +516,8 @@ wskbd_input(dev, type, value)
ev->value = value;
microtime(&xxxtime);
TIMEVAL_TO_TIMESPEC(&xxxtime, &ev->time);
- sc->sc_events.put = put;
- WSEVENT_WAKEUP(&sc->sc_events);
+ evar->put = put;
+ WSEVENT_WAKEUP(evar);
}
#ifdef WSDISPLAY_COMPAT_RAWKBD
@@ -525,6 +595,9 @@ wskbdopen(dev, flags, mode, p)
(sc = wskbd_cd.cd_devs[unit]) == NULL)
return (ENXIO);
+ if (sc->sc_dying)
+ return (EIO);
+
if (sc->sc_events.io) /* and that it's not in use */
return (EBUSY);
@@ -563,8 +636,18 @@ wskbdread(dev, uio, flags)
int flags;
{
struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
+ int error;
- return (wsevent_read(&sc->sc_events, uio, flags));
+ if (sc->sc_dying)
+ return (EIO);
+
+ sc->sc_refcnt++;
+ error = wsevent_read(&sc->sc_events, uio, flags);
+ if (--sc->sc_refcnt < 0) {
+ wakeup(sc);
+ error = EIO;
+ }
+ return (error);
}
int
@@ -578,6 +661,23 @@ wskbdioctl(dev, cmd, data, flag, p)
struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
int error;
+ sc->sc_refcnt++;
+ error = wskbd_do_ioctl(sc, cmd, data, flag, p);
+ if (--sc->sc_refcnt < 0)
+ wakeup(sc);
+ return (error);
+}
+
+int
+wskbd_do_ioctl(sc, cmd, data, flag, p)
+ struct wskbd_softc *sc;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ int error;
+
/*
* Try the generic ioctls that the wskbd interface supports.
*/
diff --git a/sys/dev/wscons/wsmouse.c b/sys/dev/wscons/wsmouse.c
index 0710edf9f9d..fbd8b3d29d8 100644
--- a/sys/dev/wscons/wsmouse.c
+++ b/sys/dev/wscons/wsmouse.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wsmouse.c,v 1.6 1999/01/10 18:22:14 augustss Exp $ */
+/* $NetBSD: wsmouse.c,v 1.7 1999/06/30 06:21:21 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.6 1999/01/10 18:22:14 augustss Exp $";
+ "$NetBSD: wsmouse.c,v 1.7 1999/06/30 06:21:21 augustss Exp $";
/*
* Copyright (c) 1992, 1993
@@ -94,6 +94,7 @@ static const char _rcsid[] __attribute__ ((unused)) =
#include <sys/tty.h>
#include <sys/signalvar.h>
#include <sys/device.h>
+#include <sys/vnode.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>
@@ -115,13 +116,23 @@ struct wsmouse_softc {
int sc_dx; /* delta-x */
int sc_dy; /* delta-y */
int sc_dz; /* delta-z */
+
+ int sc_refcnt;
+ u_char sc_dying; /* device is being detached */
+
};
int wsmouse_match __P((struct device *, struct cfdata *, void *));
void wsmouse_attach __P((struct device *, struct device *, void *));
+int wsmouse_detach __P((struct device *, int));
+int wsmouse_activate __P((struct device *, enum devact));
+
+int wsmouse_do_ioctl __P((struct wsmouse_softc *, u_long, caddr_t,
+ int, struct proc *));
struct cfattach wsmouse_ca = {
sizeof (struct wsmouse_softc), wsmouse_match, wsmouse_attach,
+ wsmouse_detach, wsmouse_activate
};
#if NWSMOUSE > 0
@@ -150,7 +161,6 @@ wsmouse_match(parent, match, aux)
struct cfdata *match;
void *aux;
{
-
return (1);
}
@@ -162,11 +172,68 @@ wsmouse_attach(parent, self, aux)
struct wsmouse_softc *sc = (struct wsmouse_softc *)self;
struct wsmousedev_attach_args *ap = aux;
- printf("\n");
-
sc->sc_accessops = ap->accessops;
sc->sc_accesscookie = ap->accesscookie;
sc->sc_ready = 0; /* sanity */
+
+ printf("\n");
+}
+
+int
+wsmouse_activate(self, act)
+ struct device *self;
+ enum devact act;
+{
+ /* XXX should we do something more? */
+ return (0);
+}
+
+/*
+ * Detach a mouse. 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
+ * 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).
+ */
+int
+wsmouse_detach(self, flags)
+ struct device *self;
+ int flags;
+{
+ struct wsmouse_softc *sc = (struct wsmouse_softc *)self;
+ struct wseventvar *evar;
+ int maj, mn;
+ int s;
+
+ sc->sc_dying = 1;
+
+ evar = &sc->sc_events;
+ if (evar->io) {
+ s = spltty();
+ if (--sc->sc_refcnt >= 0) {
+ /* Wake everyone by generating a dummy event. */
+ if (++evar->put >= WSEVENT_QSIZE)
+ evar->put = 0;
+ WSEVENT_WAKEUP(evar);
+ /* 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);
+ }
+ splx(s);
+ }
+
+ /* locate the major number */
+ for (maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == wsmouseopen)
+ break;
+
+ /* Nuke the vnodes for any open instances (calls close). */
+ mn = self->dv_unit;
+ vdevgone(maj, mn, mn, VCHR);
+
+ return (0);
}
void
@@ -177,6 +244,7 @@ wsmouse_input(wsmousedev, btns, dx, dy, dz)
{
struct wsmouse_softc *sc = (struct wsmouse_softc *)wsmousedev;
struct wscons_event *ev;
+ struct wseventvar *evar;
int mb, ub, d, get, put, any;
/*
@@ -185,6 +253,8 @@ wsmouse_input(wsmousedev, btns, dx, dy, dz)
if (sc->sc_ready == 0)
return;
+ evar = &sc->sc_events;
+
sc->sc_mb = btns;
sc->sc_dx += dx;
sc->sc_dy += dy;
@@ -198,9 +268,9 @@ wsmouse_input(wsmousedev, btns, dx, dy, dz)
* mark them `unchanged'.
*/
any = 0;
- get = sc->sc_events.get;
- put = sc->sc_events.put;
- ev = &sc->sc_events.q[put];
+ get = evar->get;
+ put = evar->put;
+ ev = &evar->q[put];
/* NEXT prepares to put the next event, backing off if necessary */
#define NEXT \
@@ -213,7 +283,7 @@ wsmouse_input(wsmousedev, btns, dx, dy, dz)
ev++; \
if (put >= WSEVENT_QSIZE) { \
put = 0; \
- ev = &sc->sc_events.q[0]; \
+ ev = &evar->q[0]; \
} \
any = 1
/* TIMESTAMP sets `time' field of the event to the current time */
@@ -271,8 +341,8 @@ wsmouse_input(wsmousedev, btns, dx, dy, dz)
out:
if (any) {
sc->sc_ub = ub;
- sc->sc_events.put = put;
- WSEVENT_WAKEUP(&sc->sc_events);
+ evar->put = put;
+ WSEVENT_WAKEUP(evar);
}
}
@@ -291,6 +361,9 @@ wsmouseopen(dev, flags, mode, p)
(sc = wsmouse_cd.cd_devs[unit]) == NULL)
return (ENXIO);
+ if (sc->sc_dying)
+ return (EIO);
+
if ((flags & (FREAD | FWRITE)) == FWRITE)
return (0); /* always allow open for write
so ioctl() is possible. */
@@ -349,8 +422,18 @@ wsmouseread(dev, uio, flags)
{
#if NWSMOUSE > 0
struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)];
+ int error;
- return (wsevent_read(&sc->sc_events, uio, flags));
+ if (sc->sc_dying)
+ return (EIO);
+
+ sc->sc_refcnt++;
+ error = wsevent_read(&sc->sc_events, uio, flags);
+ if (--sc->sc_refcnt < 0) {
+ wakeup(sc);
+ error = EIO;
+ }
+ return (error);
#else
return (ENXIO);
#endif /* NWSMOUSE > 0 */
@@ -368,6 +451,30 @@ wsmouseioctl(dev, cmd, data, flag, p)
struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)];
int error;
+ sc->sc_refcnt++;
+ error = wsmouse_do_ioctl(sc, 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;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ int error;
+
+ if (sc->sc_dying)
+ return (EIO);
+
/*
* Try the generic ioctls that the wsmouse interface supports.
*/
@@ -392,10 +499,8 @@ wsmouseioctl(dev, cmd, data, flag, p)
error = (*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd,
data, flag, p);
return (error != -1 ? error : ENOTTY);
-#else
- return (ENXIO);
-#endif /* NWSMOUSE > 0 */
}
+#endif /* NWSMOUSE > 0 */
int
wsmousepoll(dev, events, p)
@@ -411,3 +516,4 @@ wsmousepoll(dev, events, p)
return (0);
#endif /* NWSMOUSE > 0 */
}
+