Пример #1
0
int
kbdintr(void *arg)
{
	u_char c, st;
	struct kbd_softc *sc = arg;
	struct firm_event *fe;
	int put;

	/* clear receiver error if any */
	st = mfp_get_rsr();

	c = mfp_get_udr();

	if ((st & MFP_RSR_BF) == 0)
		return 0;	/* intr caused by an err -- no char received */

	/* if not in event mode, deliver straight to ite to process key stroke */
	if (!sc->sc_event_mode) {
		kbdbuf[kbdputoff++ & KBDBUFMASK] = c;
		softint_schedule(sc->sc_softintr_cookie);
		return 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!). */

	put = sc->sc_events.ev_put;
	fe = &sc->sc_events.ev_q[put];
	put = (put + 1) % EV_QSIZE;
	if (put == sc->sc_events.ev_get) {
		log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */
		return 0;
	}
	fe->id = KEY_CODE(c);
	fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
	firm_gettime(fe);
	sc->sc_events.ev_put = put;
	softint_schedule(sc->sc_softintr_cookie);

	return 0;
}
Пример #2
0
/* 
 * Note that we are called from the keyboard software interrupt!
 */
void
mouse_soft(REL_MOUSE *rel_ms, int size, int type)
{
	struct ms_softc		*ms = &ms_softc[0];
	struct firm_event	*fe, *fe2;
	REL_MOUSE		fake_mouse;
	int			get, put;
	int			sps;
	u_char			mbut, bmask;
	int			flush_buttons;

	if (ms->ms_events.ev_io == NULL)
		return;

	switch (type) {
	    case KBD_JOY1_PKG:
		/*
		 * Ignore if in emulation mode
		 */
		if (ms->ms_emul3b)
			return;

		/*
		 * There are some mice that have their middle button
		 * wired to the 'up' bit of joystick 1....
		 * Simulate a mouse packet with dx = dy = 0, the middle
		 * button state set by UP and the other buttons unchanged.
		 * Flush all button changes.
		 */
		flush_buttons = 1;
		fake_mouse.id = (rel_ms->dx & 1 ? 4 : 0) | (ms->ms_buttons & 3);
		fake_mouse.dx = fake_mouse.dy = 0;
		rel_ms = &fake_mouse;
		break;
	    case KBD_TIMEO_PKG:
		/*
		 * Timeout package. No button changes and no movement.
		 * Flush all button changes.
		 */
		flush_buttons = 1;
		fake_mouse.id = ms->ms_buttons;
		fake_mouse.dx = fake_mouse.dy = 0;
		rel_ms = &fake_mouse;
		break;
	    case KBD_RMS_PKG:
		/*
		 * Normal mouse package. Always copy the middle button
		 * status. The emulation code decides if button changes
		 * must be flushed.
		 */
		rel_ms->id = (ms->ms_buttons & 4) | (rel_ms->id & 3);
		flush_buttons = (ms->ms_emul3b) ? 0 : 1;
		break;
	    default:
		return;
	}

	sps = splev();
	get = ms->ms_events.ev_get;
	put = ms->ms_events.ev_put;
	fe  = &ms->ms_events.ev_q[put];

	if ((type != KBD_TIMEO_PKG) && ms->ms_emul3b && ms->ms_bq_idx)
		callout_stop(&ms->ms_delay_ch);

	/*
	 * Button states are encoded in the lower 3 bits of 'id'
	 */
	if (!(mbut = (rel_ms->id ^ ms->ms_buttons)) && (put != get)) {
		/*
		 * Compact dx/dy messages. Always generate an event when
		 * a button is pressed or the event queue is empty.
		 */
		ms->ms_dx += rel_ms->dx;
		ms->ms_dy += rel_ms->dy;
		goto out;
	}
	rel_ms->dx += ms->ms_dx;
	rel_ms->dy += ms->ms_dy;
	ms->ms_dx = ms->ms_dy = 0;

	/*
	 * Output location events _before_ button events ie. make sure
	 * the button is pressed at the correct location.
	 */
	if (rel_ms->dx) {
		if ((++put) % EV_QSIZE == get) {
			put--;
			goto out;
		}
		fe->id    = LOC_X_DELTA;
		fe->value = rel_ms->dx;
		firm_gettime(fe);
		if (put >= EV_QSIZE) {
			put = 0;
			fe  = &ms->ms_events.ev_q[0];
		}
		else fe++;
	}
	if (rel_ms->dy) {
		if ((++put) % EV_QSIZE == get) {
			put--;
			goto out;
		}
		fe->id    = LOC_Y_DELTA;
		fe->value = rel_ms->dy;
		firm_gettime(fe);
		if (put >= EV_QSIZE) {
			put = 0;
			fe  = &ms->ms_events.ev_q[0];
		}
		else fe++;
	}
	if (mbut && (type != KBD_TIMEO_PKG)) {
		for (bmask = 1; bmask < 0x08; bmask <<= 1) {
			if (!(mbut & bmask))
				continue;
			fe2 = &ms->ms_bq[ms->ms_bq_idx++];
			if (bmask == 1)
				fe2->id = MS_RIGHT;
			else if (bmask == 2)
				fe2->id = MS_LEFT;
			else fe2->id = MS_MIDDLE;
			fe2->value = rel_ms->id & bmask ? VKEY_DOWN : VKEY_UP;
			firm_gettime(fe2);
		}
	}

	/*
	 * Handle 3rd button emulation.
	 */
	if (ms->ms_emul3b && ms->ms_bq_idx && (type != KBD_TIMEO_PKG)) {
		/*
		 * If the middle button is pressed, any change to
		 * one of the other buttons releases all.
		 */
		if ((ms->ms_buttons & 4) && (mbut & 3)) {
			ms->ms_bq[0].id = MS_MIDDLE;
			ms->ms_bq_idx   = 1;
			rel_ms->id      = 0;
			flush_buttons   = 1;
			goto out;
		}
	    	if (ms->ms_bq_idx == 2) {
			if (ms->ms_bq[0].value == ms->ms_bq[1].value) {
				/* Must be 2 button presses! */
				ms->ms_bq[0].id = MS_MIDDLE;
				ms->ms_bq_idx   = 1;
				rel_ms->id      = 7;
			}
		}
		else if (ms->ms_bq[0].value == VKEY_DOWN) {
			callout_reset(&ms->ms_delay_ch, 10,
			    (FPV)ms_3b_delay, (void *)ms);
			goto out;
		}
		flush_buttons   = 1;
	}
out:
	if (flush_buttons) {
		int	i;

		for (i = 0; i < ms->ms_bq_idx; i++) {
			if ((++put) % EV_QSIZE == get) {
				ms->ms_bq_idx = 0;
				put--;
				goto out;
			}
			*fe = ms->ms_bq[i];
			if (put >= EV_QSIZE) {
				put = 0;
				fe  = &ms->ms_events.ev_q[0];
			}
			else fe++;
		}
		ms->ms_bq_idx = 0;
	}
	ms->ms_events.ev_put = put;
	ms->ms_buttons       = rel_ms->id;
	splx(sps);
	EV_WAKEUP(&ms->ms_events);
}