diff options
| author | augustss <augustss@NetBSD.org> | 1999-06-30 06:21:21 +0000 |
|---|---|---|
| committer | augustss <augustss@NetBSD.org> | 1999-06-30 06:21:21 +0000 |
| commit | dd048d428b1ea9f2e04762af75b62784b1b8a2e1 (patch) | |
| tree | 4f8b8d7c019c449131dfe0a60d7097f6625ef270 /sys/dev | |
| parent | b57c6ad0bc7766973b13197fc8ff3bc60270b159 (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.c | 118 | ||||
| -rw-r--r-- | sys/dev/wscons/wsmouse.c | 136 |
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 */ } + |
