static int console_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, uint32_t *eax, void *arg) { static int opened; if (bytes == 2 && in) { *eax = BVM_CONS_SIG; return (0); } /* * Guests might probe this port to look for old ISA devices * using single-byte reads. Return 0xff for those. */ if (bytes == 1 && in) { *eax = 0xff; return (0); } if (bytes != 4) return (-1); if (!opened) { ttyopen(); opened = 1; } if (in) *eax = ttyread(); else ttywrite(*eax); return (0); }
void bpress(XEvent *e) { struct timespec now; MouseShortcut *ms; int snap; if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { mousereport(e); return; } for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { if (e->xbutton.button == ms->b && match(ms->mask, e->xbutton.state)) { ttywrite(ms->s, strlen(ms->s), 1); return; } } if (e->xbutton.button == Button1) { /* * If the user clicks below predefined timeouts specific * snapping behaviour is exposed. */ clock_gettime(CLOCK_MONOTONIC, &now); if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { snap = SNAP_LINE; } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { snap = SNAP_WORD; } else { snap = 0; } xsel.tclick2 = xsel.tclick1; xsel.tclick1 = now; selstart(evcol(e), evrow(e), snap); } }
static void pci_uart_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, uint64_t offset, int size, uint64_t value) { struct pci_uart_softc *sc; int fifosz; uint8_t msr; sc = pi->pi_arg; assert(baridx == 0); assert(size == 1); /* Open terminal */ if (!sc->opened && sc->stdio) { pci_uart_opentty(sc); sc->opened = 1; } pthread_mutex_lock(&sc->mtx); /* * Take care of the special case DLAB accesses first */ if ((sc->lcr & LCR_DLAB) != 0) { if (offset == REG_DLL) { sc->dll = value; goto done; } if (offset == REG_DLH) { sc->dlh = value; goto done; } } switch (offset) { case REG_DATA: if (sc->mcr & MCR_LOOPBACK) { if (fifo_putchar(&sc->rxfifo, value) != 0) sc->lsr |= LSR_OE; } else if (sc->stdio) { ttywrite(value); } /* else drop on floor */ sc->thre_int_pending = true; break; case REG_IER: /* * Apply mask so that bits 4-7 are 0 * Also enables bits 0-3 only if they're 1 */ sc->ier = value & 0x0F; break; case REG_FCR: /* * When moving from FIFO and 16450 mode and vice versa, * the FIFO contents are reset. */ if ((sc->fcr & FCR_ENABLE) ^ (value & FCR_ENABLE)) { fifosz = (value & FCR_ENABLE) ? FIFOSZ : 1; fifo_reset(&sc->rxfifo, fifosz); } /* * The FCR_ENABLE bit must be '1' for the programming * of other FCR bits to be effective. */ if ((value & FCR_ENABLE) == 0) { sc->fcr = 0; } else { if ((value & FCR_RCV_RST) != 0) fifo_reset(&sc->rxfifo, FIFOSZ); sc->fcr = value & (FCR_ENABLE | FCR_DMA | FCR_RX_MASK); } break; case REG_LCR: sc->lcr = value; break; case REG_MCR: /* Apply mask so that bits 5-7 are 0 */ sc->mcr = value & 0x1F; msr = 0; if (sc->mcr & MCR_LOOPBACK) { /* * In the loopback mode certain bits from the * MCR are reflected back into MSR */ if (sc->mcr & MCR_RTS) msr |= MSR_CTS; if (sc->mcr & MCR_DTR) msr |= MSR_DSR; if (sc->mcr & MCR_OUT1) msr |= MSR_RI; if (sc->mcr & MCR_OUT2) msr |= MSR_DCD; } /* * Detect if there has been any change between the * previous and the new value of MSR. If there is * then assert the appropriate MSR delta bit. */ if ((msr & MSR_CTS) ^ (sc->msr & MSR_CTS)) sc->msr |= MSR_DCTS; if ((msr & MSR_DSR) ^ (sc->msr & MSR_DSR)) sc->msr |= MSR_DDSR; if ((msr & MSR_DCD) ^ (sc->msr & MSR_DCD)) sc->msr |= MSR_DDCD; if ((sc->msr & MSR_RI) != 0 && (msr & MSR_RI) == 0) sc->msr |= MSR_TERI; /* * Update the value of MSR while retaining the delta * bits. */ sc->msr &= MSR_DELTA_MASK; sc->msr |= msr; break; case REG_LSR: /* * Line status register is not meant to be written to * during normal operation. */ break; case REG_MSR: /* * As far as I can tell MSR is a read-only register. */ break; case REG_SCR: sc->scr = value; break; default: break; } done: pci_uart_toggle_intr(sc); pthread_mutex_unlock(&sc->mtx); }
void selnotify(XEvent *e) { ulong nitems, ofs, rem; int format; uchar *data, *last, *repl; Atom type, incratom, property; incratom = XInternAtom(xw.dpy, "INCR", 0); ofs = 0; if (e->type == SelectionNotify) { property = e->xselection.property; } else if(e->type == PropertyNotify) { property = e->xproperty.atom; } else { return; } if (property == None) return; do { if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, BUFSIZ/4, False, AnyPropertyType, &type, &format, &nitems, &rem, &data)) { fprintf(stderr, "Clipboard allocation failed\n"); return; } if (e->type == PropertyNotify && nitems == 0 && rem == 0) { /* * If there is some PropertyNotify with no data, then * this is the signal of the selection owner that all * data has been transferred. We won't need to receive * PropertyNotify events anymore. */ MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); } if (type == incratom) { /* * Activate the PropertyNotify events so we receive * when the selection owner does send us the next * chunk of data. */ MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); /* * Deleting the property is the transfer start signal. */ XDeleteProperty(xw.dpy, xw.win, (int)property); continue; } /* * As seen in getsel: * Line endings are inconsistent in the terminal and GUI world * copy and pasting. When receiving some selection data, * replace all '\n' with '\r'. * FIXME: Fix the computer world. */ repl = data; last = data + nitems * format / 8; while ((repl = memchr(repl, '\n', last - repl))) { *repl++ = '\r'; } if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) ttywrite("\033[200~", 6); ttysend((char *)data, nitems * format / 8); if (IS_SET(MODE_BRCKTPASTE) && rem == 0) ttywrite("\033[201~", 6); XFree(data); /* number of 32-bit chunks returned */ ofs += nitems * format / 32; } while (rem > 0); /* * Deleting the property again tells the selection owner to send the * next data chunk in the property. */ XDeleteProperty(xw.dpy, xw.win, (int)property); }
void mousereport(XEvent *e) { int x = x2col(e->xbutton.x), y = y2row(e->xbutton.y), button = e->xbutton.button, state = e->xbutton.state, len; char buf[40]; static int ox, oy; /* from urxvt */ if (e->xbutton.type == MotionNotify) { if (x == ox && y == oy) return; if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) return; /* MOUSE_MOTION: no reporting if no button is pressed */ if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) return; button = oldbutton + 32; ox = x; oy = y; } else { if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { button = 3; } else { button -= Button1; if (button >= 3) button += 64 - 3; } if (e->xbutton.type == ButtonPress) { oldbutton = button; ox = x; oy = y; } else if (e->xbutton.type == ButtonRelease) { oldbutton = 3; /* MODE_MOUSEX10: no button release reporting */ if (IS_SET(MODE_MOUSEX10)) return; if (button == 64 || button == 65) return; } } if (!IS_SET(MODE_MOUSEX10)) { button += ((state & ShiftMask ) ? 4 : 0) + ((state & Mod4Mask ) ? 8 : 0) + ((state & ControlMask) ? 16 : 0); } if (IS_SET(MODE_MOUSESGR)) { len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", button, x+1, y+1, e->xbutton.type == ButtonRelease ? 'm' : 'M'); } else if (x < 223 && y < 223) { len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", 32+button, 32+x+1, 32+y+1); } else { return; } ttywrite(buf, len); }
void * serverSubThread(void *id) { struct sockinfo *sptr; char c, crlf, gotcrlf, msg[80]; sptr = &SockTbl[(int)id]; /* Option setup... * LINEMODE tells the client to send each character as it is typed. * ECHO tells the client that the server will echo the characters. */ msg[0] = (char)TELNET_IAC; msg[1] = (char)TELNET_DO; msg[2] = (char)TELNET_OPTION_LINEMODE; /* See RFC 1116 */ msg[3] = (char)TELNET_IAC; msg[4] = (char)TELNET_WILL; msg[5] = (char)TELNET_OPTION_ECHO; /* See RFC 857 */ send(sptr->socket,msg,6,0); if (telnetPassword[0]) { int pidx; char password[32]; socprintf(sptr->socket,"\n\n%s",PASSWORDPROMPT); for(pidx=0;pidx<sizeof(password);pidx++) { if (recv(sptr->socket,&c,1,0) <= 0) goto done; if (c == 0) { pidx--; continue; } if (c == TELNET_IAC) { processIAC(sptr->socket); pidx--; continue; } send(sptr->socket," ",1,0); password[pidx] = c; if ((c == '\n') || (c == '\r')) { password[pidx] = 0; if (strcmp(password,telnetPassword)) goto done; send(sptr->socket,"\r\n",2,0); break; } } if (pidx == sizeof(password)) goto done; } if (telnetWelcome[0]) socprintf(sptr->socket,"\n\n%s\n\n",telnetWelcome); else socprintf(sptr->socket,"\n\nTNT connected\n\n"); gotcrlf = crlf = 0; while(1) { if (recv(sptr->socket,&c,1,0) <= 0) break; if (c == 0) continue; if (c == TELNET_IAC) { processIAC(sptr->socket); continue; } /* As a Network Virtual Terminal (NVT) the client is supposed to * map the ENTER (or RETURN) key of the user to CR-LF (see Comer * pg411). If CCP->telnetCRLFProc is set, then we strip the * carriage return and only pass the line feed. */ if ((c == '\n') || (c == '\r')) { gotcrlf = 1; if ((crlf) && (crlf != c)) { crlf = 0; continue; } crlf = c; } else { gotcrlf = 0; crlf = 0; } if (telnetReadOnly == 0) ttywrite(&c,1); } done: close(sptr->socket); sptr->socket = INVALID_SOCKET; sptr->warning = 0; return(0); }
void uart_write(struct uart_softc *sc, int offset, uint8_t value) { int fifosz; uint8_t msr; pthread_mutex_lock(&sc->mtx); /* * Take care of the special case DLAB accesses first */ if ((sc->lcr & LCR_DLAB) != 0) { if (offset == REG_DLL) { sc->dll = value; goto done; } if (offset == REG_DLH) { sc->dlh = value; goto done; } } switch (offset) { case REG_DATA: if (sc->mcr & MCR_LOOPBACK) { if (rxfifo_putchar(sc, value) != 0) sc->lsr |= LSR_OE; } else if (sc->tty.opened) { ttywrite(&sc->tty, value); } /* else drop on floor */ sc->thre_int_pending = true; break; case REG_IER: /* * Apply mask so that bits 4-7 are 0 * Also enables bits 0-3 only if they're 1 */ sc->ier = value & 0x0F; break; case REG_FCR: /* * When moving from FIFO and 16450 mode and vice versa, * the FIFO contents are reset. */ if ((sc->fcr & FCR_ENABLE) ^ (value & FCR_ENABLE)) { fifosz = (value & FCR_ENABLE) ? FIFOSZ : 1; rxfifo_reset(sc, fifosz); } /* * The FCR_ENABLE bit must be '1' for the programming * of other FCR bits to be effective. */ if ((value & FCR_ENABLE) == 0) { sc->fcr = 0; } else { if ((value & FCR_RCV_RST) != 0) rxfifo_reset(sc, FIFOSZ); sc->fcr = value & (FCR_ENABLE | FCR_DMA | FCR_RX_MASK); } break; case REG_LCR: sc->lcr = value; break; case REG_MCR: /* Apply mask so that bits 5-7 are 0 */ sc->mcr = value & 0x1F; msr = modem_status(sc->mcr); /* * Detect if there has been any change between the * previous and the new value of MSR. If there is * then assert the appropriate MSR delta bit. */ if ((msr & MSR_CTS) ^ (sc->msr & MSR_CTS)) sc->msr |= MSR_DCTS; if ((msr & MSR_DSR) ^ (sc->msr & MSR_DSR)) sc->msr |= MSR_DDSR; if ((msr & MSR_DCD) ^ (sc->msr & MSR_DCD)) sc->msr |= MSR_DDCD; if ((sc->msr & MSR_RI) != 0 && (msr & MSR_RI) == 0) sc->msr |= MSR_TERI; /* * Update the value of MSR while retaining the delta * bits. */ sc->msr &= MSR_DELTA_MASK; sc->msr |= msr; break; case REG_LSR: /* * Line status register is not meant to be written to * during normal operation. */ break; case REG_MSR: /* * As far as I can tell MSR is a read-only register. */ break; case REG_SCR: sc->scr = value; break; default: break; } done: uart_toggle_intr(sc); pthread_mutex_unlock(&sc->mtx); }