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; }
/* * 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); }