Example #1
0
/*
 * 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);
}
Example #2
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 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);
}
Example #3
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);
}
Example #4
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
	}
}