/* * Keyboard is generating events. Turn this keystroke into an * event and put it in the queue. If the queue is full, the * keystroke is lost (sorry!). */ void wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value) { struct wseventvar *evar; struct wscons_event *ev; int put; evar = sc->sc_base.me_evp; if (evar == NULL) { DPRINTF(("wskbd_input: not open\n")); return; } #ifdef DIAGNOSTIC if (evar->q == NULL) { printf("wskbd_input: evar->q=NULL\n"); return; } #endif 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_base.me_dv.dv_xname); return; } ev->type = type; ev->value = value; nanotime(&ev->time); evar->put = put; WSEVENT_WAKEUP(evar); }
/* * 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 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). */ int wskbd_detach(struct device *self, int flags) { struct wskbd_softc *sc = (struct wskbd_softc *)self; struct wseventvar *evar; int maj, mn; int s; #if NWSMUX > 0 /* Tell parent mux we're leaving. */ if (sc->sc_base.me_parent != NULL) wsmux_detach_sc(&sc->sc_base); #endif #if NWSDISPLAY > 0 if (sc->sc_repeating) { sc->sc_repeating = 0; timeout_del(&sc->sc_repeat_ch); } #endif if (sc->sc_isconsole) { KASSERT(wskbd_console_device == sc); wskbd_console_device = NULL; } 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. */ 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_base.me_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); }
/* * 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(struct device *self, int flags) { struct wsmouse_softc *sc = (struct wsmouse_softc *)self; struct wseventvar *evar; int maj, mn; int s; #if NWSMUX > 0 /* Tell parent mux we're leaving. */ if (sc->sc_base.me_parent != NULL) { DPRINTF(("wsmouse_detach:\n")); wsmux_detach_sc(&sc->sc_base); } #endif /* 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. */ 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_base.me_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 wsmouse_input(struct device *wsmousedev, u_int btns, /* 0 is up */ int x, int y, int z, int w, u_int flags) { struct wsmouse_softc *sc = (struct wsmouse_softc *)wsmousedev; struct wscons_event *ev; struct wseventvar *evar; int mb, ub, d, get, put, any; add_mouse_randomness(x ^ y ^ z ^ w ^ btns); /* * Discard input if not ready. */ evar = sc->sc_base.me_evp; if (evar == NULL) return; #ifdef DIAGNOSTIC if (evar->q == NULL) { printf("wsmouse_input: evar->q=NULL\n"); return; } #endif #if NWSMUX > 0 DPRINTFN(5,("wsmouse_input: %s mux=%p, evar=%p\n", sc->sc_base.me_dv.dv_xname, sc->sc_base.me_parent, evar)); #endif sc->sc_mb = btns; if (!(flags & WSMOUSE_INPUT_ABSOLUTE_X)) sc->sc_dx += x; if (!(flags & WSMOUSE_INPUT_ABSOLUTE_Y)) sc->sc_dy += y; if (!(flags & WSMOUSE_INPUT_ABSOLUTE_Z)) sc->sc_dz += z; if (!(flags & WSMOUSE_INPUT_ABSOLUTE_W)) sc->sc_dw += w; /* * We have at least one event (mouse button, delta-X, or * delta-Y; possibly all three, and possibly three separate * button events). Deliver these events until we are out * of changes or out of room. As events get delivered, * mark them `unchanged'. */ ub = sc->sc_ub; any = 0; get = evar->get; put = evar->put; ev = &evar->q[put]; /* NEXT prepares to put the next event, backing off if necessary */ #define NEXT \ if ((++put) % WSEVENT_QSIZE == get) { \ put--; \ goto out; \ } /* ADVANCE completes the `put' of the event */ #define ADVANCE \ ev++; \ if (put >= WSEVENT_QSIZE) { \ put = 0; \ ev = &evar->q[0]; \ } \ any = 1 /* TIMESTAMP sets `time' field of the event to the current time */ #define TIMESTAMP \ do { \ getnanotime(&ev->time); \ } while (0) if (flags & WSMOUSE_INPUT_ABSOLUTE_X) { if (sc->sc_x != x) { NEXT; ev->type = WSCONS_EVENT_MOUSE_ABSOLUTE_X; ev->value = x; TIMESTAMP; ADVANCE; sc->sc_x = x; } } else { if (sc->sc_dx) { NEXT; ev->type = WSCONS_EVENT_MOUSE_DELTA_X; ev->value = sc->sc_dx; TIMESTAMP; ADVANCE; sc->sc_dx = 0; } } if (flags & WSMOUSE_INPUT_ABSOLUTE_Y) { if (sc->sc_y != y) { NEXT; ev->type = WSCONS_EVENT_MOUSE_ABSOLUTE_Y; ev->value = y; TIMESTAMP; ADVANCE; sc->sc_y = y; } } else { if (sc->sc_dy) { NEXT; ev->type = WSCONS_EVENT_MOUSE_DELTA_Y; ev->value = sc->sc_dy; TIMESTAMP; ADVANCE; sc->sc_dy = 0; } } if (flags & WSMOUSE_INPUT_ABSOLUTE_Z) { if (sc->sc_z != z) { NEXT; ev->type = WSCONS_EVENT_MOUSE_ABSOLUTE_Z; ev->value = z; TIMESTAMP; ADVANCE; sc->sc_z = z; } } else { if (sc->sc_dz) { NEXT; ev->type = WSCONS_EVENT_MOUSE_DELTA_Z; ev->value = sc->sc_dz; TIMESTAMP; ADVANCE; sc->sc_dz = 0; } } if (flags & WSMOUSE_INPUT_ABSOLUTE_W) { if (sc->sc_w != w) { NEXT; ev->type = WSCONS_EVENT_MOUSE_ABSOLUTE_W; ev->value = w; TIMESTAMP; ADVANCE; sc->sc_w = w; } } else { if (sc->sc_dw) { NEXT; ev->type = WSCONS_EVENT_MOUSE_DELTA_W; ev->value = sc->sc_dw; TIMESTAMP; ADVANCE; sc->sc_dw = 0; } } mb = sc->sc_mb; while ((d = mb ^ ub) != 0) { /* * Mouse button change. Find the first change and drop * it into the event queue. */ NEXT; ev->value = ffs(d) - 1; KASSERT(ev->value >= 0); d = 1 << ev->value; ev->type = (mb & d) ? WSCONS_EVENT_MOUSE_DOWN : WSCONS_EVENT_MOUSE_UP; TIMESTAMP; ADVANCE; ub ^= d; } /* XXX fake wscons_event notifying wsmoused(8) to close mouse device */ if (flags & WSMOUSE_INPUT_WSMOUSED_CLOSE) { NEXT; ev->type = WSCONS_EVENT_WSMOUSED_CLOSE; ev->value = 0; TIMESTAMP; ADVANCE; } #undef TIMESTAMP #undef ADVANCE #undef NEXT out: if (any) { sc->sc_ub = ub; evar->put = put; WSEVENT_WAKEUP(evar); #ifdef BURNER_SUPPORT /* wsdisplay_burn(sc->sc_displaydv, WSDISPLAY_BURN_MOUSE); */ #endif #if NWSMUX > 0 DPRINTFN(5,("wsmouse_input: %s wakeup evar=%p\n", sc->sc_base.me_dv.dv_xname, evar)); #endif } }