コード例 #1
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(device_t self, int flags)
{
	struct wskbd_softc *sc = device_private(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

	callout_halt(&sc->sc_repeat_ch, NULL);
	callout_destroy(&sc->sc_repeat_ch);

	if (sc->sc_isconsole) {
		KASSERT(wskbd_console_device == sc);
		wskbd_console_device = NULL;
	}

	pmf_device_deregister(self);

	evar = sc->sc_base.me_evp;
	if (evar != NULL && evar->io != NULL) {
		s = spltty();
		if (--sc->sc_refcnt >= 0) {
			struct wscons_event event;

			/* Wake everyone by generating a dummy event. */
			event.type = 0;
			event.value = 0;
			if (wsevent_inject(evar, &event, 1) != 0)
				wsevent_wakeup(evar);

			/* Wait for processes to go away. */
			if (tsleep(sc, PZERO, "wskdet", hz * 60))
				aprint_error("wskbd_detach: %s didn't detach\n",
				       device_xname(self));
		}
		splx(s);
	}

	/* locate the major number */
	maj = cdevsw_lookup_major(&wskbd_cdevsw);

	/* Nuke the vnodes for any open instances. */
	mn = device_unit(self);
	vdevgone(maj, mn, mn, VCHR);

	return (0);
}
コード例 #2
0
static void
wsmouse_repeat(void *v)
{
	int oldspl;
	unsigned int newdelay;
	struct wsmouse_softc *sc;
	struct wscons_event events[2];

	oldspl = spltty();
	sc = (struct wsmouse_softc *)v;

	if (sc->sc_repeat_button == -1) {
		/* Race condition: a "button up" event came in when
		 * this function was already called but did not do
		 * spltty() yet. */
		splx(oldspl);
		return;
	}
	KASSERT(sc->sc_repeat_button >= 0);

	KASSERT(sc->sc_repeat.wr_buttons & (1 << sc->sc_repeat_button));

	newdelay = sc->sc_repeat_delay;

	events[0].type = WSCONS_EVENT_MOUSE_UP;
	events[0].value = sc->sc_repeat_button;
	events[1].type = WSCONS_EVENT_MOUSE_DOWN;
	events[1].value = sc->sc_repeat_button;

	if (wsevent_inject(sc->sc_base.me_evp, events, 2) == 0) {
		sc->sc_ub = 1 << sc->sc_repeat_button;

		if (newdelay - sc->sc_repeat.wr_delay_decrement <
		    sc->sc_repeat.wr_delay_minimum)
			newdelay = sc->sc_repeat.wr_delay_minimum;
		else if (newdelay > sc->sc_repeat.wr_delay_minimum)
			newdelay -= sc->sc_repeat.wr_delay_decrement;
		KASSERT(newdelay >= sc->sc_repeat.wr_delay_minimum &&
		    newdelay <= sc->sc_repeat.wr_delay_first);
	}

	/*
	 * Reprogram the repeating event.
	 */
	sc->sc_repeat_delay = newdelay;
	callout_schedule(&sc->sc_repeat_callout, mstohz(newdelay));

	splx(oldspl);
}
コード例 #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(device_t self, int flags)
{
	struct wsmouse_softc *sc = device_private(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) {
			struct wscons_event event;

			/* Wake everyone by generating a dummy event. */
			event.type = 0;
			event.value = 0;
			if (wsevent_inject(evar, &event, 1) != 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",
				       device_xname(self));
		}
		splx(s);
	}

	/* locate the major number */
	maj = cdevsw_lookup_major(&wsmouse_cdevsw);

	/* Nuke the vnodes for any open instances (calls close). */
	mn = device_unit(self);
	vdevgone(maj, mn, mn, VCHR);

	return (0);
}
コード例 #4
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!).
 */
static void
wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value)
{
	struct wseventvar *evar;
	struct wscons_event event;

	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

	event.type = type;
	event.value = 0;
	DPRINTF(("%d ->", value));
	if (sc->sc_evtrans_len > 0) {
		if (sc->sc_evtrans_len > value) {
			DPRINTF(("%d", sc->sc_evtrans[value]));
			event.value = sc->sc_evtrans[value];
		}
	} else {
		event.value = value;
	}
	DPRINTF(("\n"));
	if (wsevent_inject(evar, &event, 1) != 0)
		log(LOG_WARNING, "%s: event queue overflow\n",
		    device_xname(sc->sc_base.me_dv));
}
コード例 #5
0
void
wsmouse_input(device_t wsmousedev, u_int btns /* 0 is up */,
	int x, int y, int z, int w, u_int flags)
{
	struct wsmouse_softc *sc = device_private(wsmousedev);
	struct wseventvar *evar;
	int mb, ub, d, nevents;
	/* one for each dimension (4) + a bit for each button */
	struct wscons_event events[4 + sizeof(d) * 8];

        /*
         * Discard input if not open.
         */
	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",
		    device_xname(sc->sc_base.me_dv),
		    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;
	nevents = 0;

	if (flags & WSMOUSE_INPUT_ABSOLUTE_X) {
		if (sc->sc_x != x) {
			events[nevents].type = WSCONS_EVENT_MOUSE_ABSOLUTE_X;
			events[nevents].value = x;
			nevents++;
		}
	} else {
		if (sc->sc_dx) {
			events[nevents].type = WSCONS_EVENT_MOUSE_DELTA_X;
			events[nevents].value = sc->sc_dx;
			nevents++;
		}
	}
	if (flags & WSMOUSE_INPUT_ABSOLUTE_Y) {
		if (sc->sc_y != y) {
			events[nevents].type = WSCONS_EVENT_MOUSE_ABSOLUTE_Y;
			events[nevents].value = y;
			nevents++;
		}
	} else {
		if (sc->sc_dy) {
			events[nevents].type = WSCONS_EVENT_MOUSE_DELTA_Y;
			events[nevents].value = sc->sc_dy;
			nevents++;
		}
	}
	if (flags & WSMOUSE_INPUT_ABSOLUTE_Z) {
		if (sc->sc_z != z) {
			events[nevents].type = WSCONS_EVENT_MOUSE_ABSOLUTE_Z;
			events[nevents].value = z;
			nevents++;
		}
	} else {
		if (sc->sc_dz) {
			events[nevents].type = WSCONS_EVENT_MOUSE_DELTA_Z;
			events[nevents].value = sc->sc_dz;
			nevents++;
		}
	}
	if (flags & WSMOUSE_INPUT_ABSOLUTE_W) {
		if (sc->sc_w != w) {
			events[nevents].type = WSCONS_EVENT_MOUSE_ABSOLUTE_W;
			events[nevents].value = w;
			nevents++;
		}
	} else {
		if (sc->sc_dw) {
			events[nevents].type = WSCONS_EVENT_MOUSE_DELTA_W;
			events[nevents].value = sc->sc_dw;
			nevents++;
		}
	}

	mb = sc->sc_mb;
	while ((d = mb ^ ub) != 0) {
		int btnno;

		/*
		 * Cancel button repeating if button status changed.
		 */
		if (sc->sc_repeat_button != -1) {
			KASSERT(sc->sc_repeat_button >= 0);
			KASSERT(sc->sc_repeat.wr_buttons &
                            (1 << sc->sc_repeat_button));
			ub &= ~(1 << sc->sc_repeat_button);
			sc->sc_repeat_button = -1;
			callout_stop(&sc->sc_repeat_callout);
		}

		/*
		 * Mouse button change.  Find the first change and drop
		 * it into the event queue.
		 */
		btnno = ffs(d) - 1;
		KASSERT(btnno >= 0);

		if (nevents >= sizeof(events) / sizeof(events[0])) {
			aprint_error_dev(sc->sc_base.me_dv,
			    "Event queue full (button status mb=0x%x"
			    " ub=0x%x)\n", mb, ub);
			break;
		}

		events[nevents].type =
		    (mb & d) ? WSCONS_EVENT_MOUSE_DOWN : WSCONS_EVENT_MOUSE_UP;
		events[nevents].value = btnno;
		nevents++;

		ub ^= (1 << btnno);

		/*
		 * Program button repeating if configured for this button.
		 */
		if ((mb & d) && (sc->sc_repeat.wr_buttons & (1 << btnno)) &&
		    sc->sc_repeat.wr_delay_first > 0) {
			sc->sc_repeat_button = btnno;
			sc->sc_repeat_delay = sc->sc_repeat.wr_delay_first;
			callout_schedule(&sc->sc_repeat_callout,
			    mstohz(sc->sc_repeat_delay));
		}
	}

	if (nevents == 0 || wsevent_inject(evar, events, nevents) == 0) {
		/* All events were correctly injected into the queue.
		 * Synchronize the mouse's status with what the user
		 * has received. */
		sc->sc_x = x; sc->sc_dx = 0;
		sc->sc_y = y; sc->sc_dy = 0;
		sc->sc_z = z; sc->sc_dz = 0;
		sc->sc_w = w; sc->sc_dw = 0;
		sc->sc_ub = ub;
#if NWSMUX > 0
		DPRINTFN(5,("wsmouse_input: %s wakeup evar=%p\n",
			    device_xname(sc->sc_base.me_dv), evar));
#endif
	}
}