void ukbd_intr(struct uhidev *addr, void *ibuf, u_int len) { struct ukbd_softc *sc = (struct ukbd_softc *)addr; struct ukbd_data *ud = &sc->sc_ndata; int i; #ifdef UKBD_DEBUG if (ukbddebug > 5) { printf("ukbd_intr: data"); for (i = 0; i < len; i++) printf(" 0x%02x", ((u_char *)ibuf)[i]); printf("\n"); } #endif ud->modifiers = 0; for (i = 0; i < sc->sc_nmod; i++) if (hid_get_data(ibuf, &sc->sc_modloc[i])) ud->modifiers |= sc->sc_mods[i].mask; memcpy(ud->keycode, (char *)ibuf + sc->sc_keycodeloc.pos / 8, sc->sc_nkeycode); if (sc->sc_debounce && !sc->sc_polling) { /* * Some keyboards have a peculiar quirk. They sometimes * generate a key up followed by a key down for the same * key after about 10 ms. * We avoid this bug by holding off decoding for 20 ms. */ sc->sc_data = *ud; usb_callout(sc->sc_delay, hz / 50, ukbd_delayed_decode, sc); #ifdef DDB } else if (sc->sc_console_keyboard && !sc->sc_polling) { /* * For the console keyboard we can't deliver CTL-ALT-ESC * from the interrupt routine. Doing so would start * polling from inside the interrupt routine and that * loses bigtime. */ sc->sc_data = *ud; usb_callout(sc->sc_delay, 1, ukbd_delayed_decode, sc); #endif } else { ukbd_decode(sc, ud); } }
void ukbd_rawrepeat(void *v) { struct ukbd_softc *sc = v; int s; s = spltty(); wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep); splx(s); usb_callout(sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000, ukbd_rawrepeat, sc); }
Static void url_tick_task(void *xsc) { struct url_softc *sc = xsc; struct ifnet *ifp; struct mii_data *mii; int s; if (sc == NULL) return; DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__)); if (sc->sc_dying) return; ifp = GET_IFP(sc); mii = GET_MII(sc); if (mii == NULL) return; s = splnet(); mii_tick(mii); if (!sc->sc_link) { mii_pollstat(mii); if (mii->mii_media_status & IFM_ACTIVE && IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { DPRINTF(("%s: %s: got link\n", USBDEVNAME(sc->sc_dev), __func__)); sc->sc_link++; if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) url_start(ifp); } } usb_callout(sc->sc_stat_ch, hz, url_tick, sc); splx(s); }
Static int url_init(struct ifnet *ifp) { struct url_softc *sc = ifp->if_softc; struct mii_data *mii = GET_MII(sc); u_char *eaddr; int i, s; DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__)); if (sc->sc_dying) return (EIO); s = splnet(); /* Cancel pending I/O and free all TX/RX buffers */ url_stop(ifp, 1); #if defined(__OpenBSD__) eaddr = sc->sc_ac.ac_enaddr; #elif defined(__NetBSD__) eaddr = LLADDR(ifp->if_sadl); #endif for (i = 0; i < ETHER_ADDR_LEN; i++) url_csr_write_1(sc, URL_IDR0 + i, eaddr[i]); /* Init transmission control register */ URL_CLRBIT(sc, URL_TCR, URL_TCR_TXRR1 | URL_TCR_TXRR0 | URL_TCR_IFG1 | URL_TCR_IFG0 | URL_TCR_NOCRC); /* Init receive control register */ URL_SETBIT2(sc, URL_RCR, URL_RCR_TAIL | URL_RCR_AD); if (ifp->if_flags & IFF_BROADCAST) URL_SETBIT2(sc, URL_RCR, URL_RCR_AB); else URL_CLRBIT2(sc, URL_RCR, URL_RCR_AB); /* If we want promiscuous mode, accept all physical frames. */ if (ifp->if_flags & IFF_PROMISC) URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); else URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); /* Initialize transmit ring */ if (url_tx_list_init(sc) == ENOBUFS) { printf("%s: tx list init failed\n", USBDEVNAME(sc->sc_dev)); splx(s); return (EIO); } /* Initialize receive ring */ if (url_rx_list_init(sc) == ENOBUFS) { printf("%s: rx list init failed\n", USBDEVNAME(sc->sc_dev)); splx(s); return (EIO); } /* Load the multicast filter */ url_setmulti(sc); /* Enable RX and TX */ URL_SETBIT(sc, URL_CR, URL_CR_TE | URL_CR_RE); mii_mediachg(mii); if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) { if (url_openpipes(sc)) { splx(s); return (EIO); } } ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; splx(s); usb_callout(sc->sc_stat_ch, hz, url_tick, sc); return (0); }
void ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud) { int mod, omod; u_int16_t ibuf[MAXKEYS]; /* chars events */ int s; int nkeys, i, j; int key; #define ADDKEY(c) ibuf[nkeys++] = (c) #ifdef UKBD_DEBUG /* * Keep a trace of the last events. Using printf changes the * timing, so this can be useful sometimes. */ if (ukbdtrace) { struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex]; p->unit = device_unit(sc->sc_hdev.sc_dev); microtime(&p->tv); p->ud = *ud; if (++ukbdtraceindex >= UKBDTRACESIZE) ukbdtraceindex = 0; } if (ukbddebug > 5) { struct timeval tv; microtime(&tv); DPRINTF((" at %"PRIu64".%06"PRIu64" mod=0x%02x key0=0x%02x key1=0x%02x " "key2=0x%02x key3=0x%02x\n", tv.tv_sec, (uint64_t)tv.tv_usec, ud->modifiers, ud->keycode[0], ud->keycode[1], ud->keycode[2], ud->keycode[3])); } #endif if (ud->keycode[0] == KEY_ERROR) { DPRINTF(("ukbd_intr: KEY_ERROR\n")); return; /* ignore */ } nkeys = 0; mod = ud->modifiers; omod = sc->sc_odata.modifiers; if (mod != omod) for (i = 0; i < sc->sc_nmod; i++) if (( mod & sc->sc_mods[i].mask) != (omod & sc->sc_mods[i].mask)) ADDKEY(sc->sc_mods[i].key | (mod & sc->sc_mods[i].mask ? PRESS : RELEASE)); if (memcmp(ud->keycode, sc->sc_odata.keycode, sc->sc_nkeycode) != 0) { /* Check for released keys. */ for (i = 0; i < sc->sc_nkeycode; i++) { key = sc->sc_odata.keycode[i]; if (key == 0) continue; for (j = 0; j < sc->sc_nkeycode; j++) if (key == ud->keycode[j]) goto rfound; DPRINTFN(3,("ukbd_intr: relse key=0x%02x\n", key)); ADDKEY(key | RELEASE); rfound: ; } /* Check for pressed keys. */ for (i = 0; i < sc->sc_nkeycode; i++) { key = ud->keycode[i]; if (key == 0) continue; for (j = 0; j < sc->sc_nkeycode; j++) if (key == sc->sc_odata.keycode[j]) goto pfound; DPRINTFN(2,("ukbd_intr: press key=0x%02x\n", key)); ADDKEY(key | PRESS); pfound: ; } } sc->sc_odata = *ud; if (nkeys == 0) return; if (sc->sc_polling) { DPRINTFN(1,("ukbd_intr: pollchar = 0x%03x\n", ibuf[0])); memcpy(sc->sc_pollchars, ibuf, nkeys * sizeof(u_int16_t)); sc->sc_npollchar = nkeys; return; } #ifdef WSDISPLAY_COMPAT_RAWKBD if (sc->sc_rawkbd) { u_char cbuf[MAXKEYS * 2]; int c; int npress; for (npress = i = j = 0; i < nkeys; i++) { key = ibuf[i]; c = ukbd_trtab[key & CODEMASK]; if (c == NN) continue; if (c == 0x7f) { /* pause key */ cbuf[j++] = 0xe1; cbuf[j++] = 0x1d; cbuf[j-1] |= (key & RELEASE) ? 0x80 : 0; cbuf[j] = 0x45; } else { if (c & 0x80) cbuf[j++] = 0xe0; cbuf[j] = c & 0x7f; } if (key & RELEASE) cbuf[j] |= 0x80; #if defined(UKBD_REPEAT) else { /* remember pressed keys for autorepeat */ if (c & 0x80) sc->sc_rep[npress++] = 0xe0; sc->sc_rep[npress++] = c & 0x7f; } #endif DPRINTFN(1,("ukbd_intr: raw = %s0x%02x\n", c & 0x80 ? "0xe0 " : "", cbuf[j])); j++; } s = spltty(); wskbd_rawinput(sc->sc_wskbddev, cbuf, j); splx(s); #ifdef UKBD_REPEAT usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc); if (npress != 0) { sc->sc_nrep = npress; usb_callout(sc->sc_rawrepeat_ch, hz * REP_DELAY1 / 1000, ukbd_rawrepeat, sc); } #endif return; } #endif s = spltty(); for (i = 0; i < nkeys; i++) { key = ibuf[i]; wskbd_input(sc->sc_wskbddev, key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN, key&CODEMASK); } splx(s); }