/* * Called by a uart interrupt for console input. * * turn '\r' into '\n' before putting it into the queue. */ int kbdcr2nl(Queue *q, int ch) { if(ch == '\r') ch = '\n'; return kbdputc(q, ch); }
static void pl011_clock(void) { char c; if (pl011_tstc()) { c = pl011_getc(); if (c == 13) { pl011_putc('\r'); pl011_putc('\n'); kbdputc(kbdq,'\r'); kbdputc(kbdq,'\n'); return; } pl011_putc(c); kbdputc(kbdq,c); } }
void kbdclock(void) { if(kbd.repeat == 0) return; if(kbd.repeat==1 && ++kbd.count>HZ){ kbd.repeat = 2; kbd.count = 0; return; } if(++kbd.count&1) kbdputc(kbdq, kbd.c); }
static long conswrite(Chan *c, void *va, long n, vlong offset) { vlong t; long l, bp; char *a = va; Cmdbuf *cb; Cmdtab *ct; char buf[256]; int x; switch((ulong)c->qid.path){ case Qcons: /* * Can't page fault in putstrn, so copy the data locally. */ l = n; while(l > 0){ bp = l; if(bp > sizeof buf) bp = sizeof buf; memmove(buf, a, bp); putstrn0(a, bp, 1); a += bp; l -= bp; } break; case Qconsctl: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, a, n); buf[n] = 0; for(a = buf; a;){ if(strncmp(a, "rawon", 5) == 0){ qlock(&kbd); flushkbdline(kbdq); kbd.raw = 1; qunlock(&kbd); } else if(strncmp(a, "rawoff", 6) == 0){ qlock(&kbd); kbd.raw = 0; kbd.x = 0; qunlock(&kbd); } if(a = strchr(a, ' ')) a++; } break; case Qkeyboard: for(x=0; x<n; ) { Rune r; x += chartorune(&r, &a[x]); kbdputc(kbdq, r); } break; case Qtime: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, a, n); buf[n] = 0; t = strtoll(buf, 0, 0)/1000000; boottime = t - TK2SEC(MACHP(0)->ticks); break; case Qhostowner: if(!iseve()) error(Eperm); if(offset != 0 || n >= sizeof(buf)) error(Ebadarg); memmove(buf, a, n); buf[n] = '\0'; if(n > 0 && buf[n-1] == '\n') buf[--n] = 0; if(n <= 0) error(Ebadarg); renameuser(eve, buf); renameproguser(eve, buf); kstrdup(&eve, buf); kstrdup(&up->env->user, buf); break; case Quser: if(!iseve()) error(Eperm); if(offset != 0) error(Ebadarg); if(n <= 0 || n >= sizeof(buf)) error(Ebadarg); strncpy(buf, a, n); buf[n] = 0; if(buf[n-1] == '\n') buf[n-1] = 0; kstrdup(&up->env->user, buf); break; case Qjit: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, va, n); buf[n] = '\0'; x = atoi(buf); if(x < 0 || x > 9) error(Ebadarg); cflag = x; return n; case Qnull: break; case Qsysname: if(offset != 0) error(Ebadarg); if(n <= 0 || n >= sizeof(buf)) error(Ebadarg); strncpy(buf, a, n); buf[n] = 0; if(buf[n-1] == '\n') buf[n-1] = 0; kstrdup(&sysname, buf); break; case Qsysctl: if(!iseve()) error(Eperm); cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, sysctlcmd, nelem(sysctlcmd)); switch(ct->index){ case CMreboot: reboot(); break; case CMhalt: halt(); break; case CMpanic: panic("sysctl"); case CMconsole: consoleprint = strcmp(cb->f[1], "off") != 0; break; case CMbroken: keepbroken = 1; break; case CMnobroken: keepbroken = 0; break; } poperror(); free(cb); break; default: print("conswrite: %llud\n", c->qid.path); error(Egreg); } return n; }
/* * keyboard interrupt */ static void i8042intr(Ureg*, void*) { int s, c, i; static int esc1, esc2; static int alt, caps, ctl, num, shift; static int collecting, nk; static Rune kc[5]; int keyup; /* * get status */ lock(&i8042lock); s = inb(Status); if(!(s&Inready)){ unlock(&i8042lock); return; } /* * get the character */ c = inb(Data); unlock(&i8042lock); /* * if it's the aux port... */ if(s & Minready){ if(auxputc != nil) auxputc(c, shift); return; } /* * e0's is the first of a 2 character sequence */ if(c == 0xe0){ esc1 = 1; return; } else if(c == 0xe1){ esc2 = 2; return; } keyup = c&0x80; c &= 0x7f; if(c > sizeof kbtab){ c |= keyup; if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */ print("unknown key %ux\n", c); return; } if(esc1){ c = kbtabesc1[c]; esc1 = 0; } else if(esc2){ esc2--; return; } else if(shift) c = kbtabshift[c]; else c = kbtab[c]; if(caps && c<='z' && c>='a') c += 'A' - 'a'; /* * keyup only important for shifts */ if(keyup){ switch(c){ case Latin: alt = 0; break; case Shift: shift = 0; break; case Ctrl: ctl = 0; break; } return; } /* * normal character */ if(!(c & (Spec|KF))){ if(ctl){ if(alt && c == Del) exit(0); c &= 0x1f; } if(!collecting){ kbdputc(kbdq, c); return; } kc[nk++] = c; c = latin1(kc, nk); if(c < -1) /* need more keystrokes */ return; if(c != -1) /* valid sequence */ kbdputc(kbdq, c); else /* dump characters */ for(i=0; i<nk; i++) kbdputc(kbdq, kc[i]); nk = 0; collecting = 0; return; } else { switch(c){ case Caps: caps ^= 1; return; case Num: num ^= 1; return; case Shift: shift = 1; return; case Latin: alt = 1; collecting = 1; nk = 0; return; case Ctrl: ctl = 1; return; } } kbdputc(kbdq, c); }
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { PAINTSTRUCT paint; HDC hdc; LONG x, y, b; int i; Rectangle r; b = 0; switch(msg) { case WM_CREATE: break; case WM_SETCURSOR: /* User set */ if(hcursor != NULL) { SetCursor(hcursor); return 1; } return DefWindowProc(hwnd, msg, wparam, lparam); case WM_MOUSEWHEEL: if ((int)(wparam & 0xFFFF0000)>0) b|=8; else b|=16; case WM_MOUSEMOVE: case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: x = LOWORD(lparam); y = HIWORD(lparam); if(wparam & MK_LBUTTON) b = 1; if(wparam & MK_MBUTTON) b |= 2; if(wparam & MK_RBUTTON) { if(wparam & MK_SHIFT) b |= 2; else b |= 4; } lock(&mouse.lk); i = mouse.wi; if(mousequeue) { if(i == mouse.ri || mouse.lastb != b || mouse.trans) { mouse.wi = (i+1)%Mousequeue; if(mouse.wi == mouse.ri) mouse.ri = (mouse.ri+1)%Mousequeue; mouse.trans = mouse.lastb != b; } else { i = (i-1+Mousequeue)%Mousequeue; } } else { mouse.wi = (i+1)%Mousequeue; mouse.ri = i; } mouse.queue[i].xy.x = x; mouse.queue[i].xy.y = y; mouse.queue[i].buttons = b; mouse.queue[i].msec = ticks(); mouse.lastb = b; unlock(&mouse.lk); wakeup(&mouse.r); break; case WM_CHAR: /* repeat count is lparam & 0xf */ switch(wparam){ case '\n': wparam = '\r'; break; case '\r': wparam = '\n'; break; } kbdputc(kbdq, wparam); break; case WM_SYSKEYUP: break; case WM_SYSKEYDOWN: case WM_KEYDOWN: switch(wparam) { case VK_MENU: kbdputc(kbdq, Kalt); break; case VK_INSERT: kbdputc(kbdq, Kins); break; case VK_DELETE: kbdputc(kbdq, Kdel); break; case VK_HOME: kbdputc(kbdq, Khome); break; case VK_END: kbdputc(kbdq, Kend); break; case VK_PRIOR: kbdputc(kbdq, Kpgup); break; case VK_NEXT: kbdputc(kbdq, Kpgdown); break; case VK_UP: kbdputc(kbdq, Kup); break; case VK_DOWN: kbdputc(kbdq, Kdown); break; case VK_LEFT: kbdputc(kbdq, Kleft); break; case VK_RIGHT: kbdputc(kbdq, Kright); break; } break; case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_PALETTECHANGED: if((HWND)wparam == hwnd) break; /* fall through */ case WM_QUERYNEWPALETTE: hdc = GetDC(hwnd); SelectPalette(hdc, palette, 0); if(RealizePalette(hdc) != 0) InvalidateRect(hwnd, nil, 0); ReleaseDC(hwnd, hdc); break; case WM_PAINT: hdc = BeginPaint(hwnd, &paint); r.min.x = paint.rcPaint.left; r.min.y = paint.rcPaint.top; r.max.x = paint.rcPaint.right; r.max.y = paint.rcPaint.bottom; flushmemscreen(r); EndPaint(hwnd, &paint); break; case WM_COMMAND: case WM_SETFOCUS: case WM_DEVMODECHANGE: case WM_WININICHANGE: case WM_INITMENU: default: return DefWindowProc(hwnd, msg, wparam, lparam); } return 0; }
/* * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard. * A 'standard' keyboard doesn't produce anything above 0x58. */ Rune kbtab[Nscan] = { [0x00] No, 0x1b, '1', '2', '3', '4', '5', '6', [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t', [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', [0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's', [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', [0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v', [0x30] 'b', 'n', 'm', ',', '.', '/', Shift, '*', [0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5, [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7', [0x48] '8', '9', '-', '4', '5', '6', '+', '1', [0x50] '2', '3', '0', '.', No, No, No, KF|11, [0x58] KF|12, No, No, No, No, No, No, No, [0x60] No, No, No, No, No, No, No, No, [0x68] No, No, No, No, No, No, No, No, [0x70] No, No, No, No, No, No, No, No, [0x78] No, View, No, Up, No, No, No, No, }; Rune kbtabshift[Nscan] = { [0x00] No, 0x1b, '!', '@', '#', '$', '%', '^', [0x08] '&', '*', '(', ')', '_', '+', '\b', '\t', [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', [0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S', [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', [0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V', [0x30] 'B', 'N', 'M', '<', '>', '?', Shift, '*', [0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5, [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7', [0x48] '8', '9', '-', '4', '5', '6', '+', '1', [0x50] '2', '3', '0', '.', No, No, No, KF|11, [0x58] KF|12, No, No, No, No, No, No, No, [0x60] No, No, No, No, No, No, No, No, [0x68] No, No, No, No, No, No, No, No, [0x70] No, No, No, No, No, No, No, No, [0x78] No, Up, No, Up, No, No, No, No, }; Rune kbtabesc1[Nscan] = { [0x00] No, No, No, No, No, No, No, No, [0x08] No, No, No, No, No, No, No, No, [0x10] No, No, No, No, No, No, No, No, [0x18] No, No, No, No, '\n', Ctrl, No, No, [0x20] No, No, No, No, No, No, No, No, [0x28] No, No, Shift, No, No, No, No, No, [0x30] No, No, No, No, No, '/', No, Print, [0x38] Altgr, No, No, No, No, No, No, No, [0x40] No, No, No, No, No, No, Break, Home, [0x48] Up, Pgup, No, Left, No, Right, No, End, [0x50] Down, Pgdown, Ins, Del, No, No, No, No, [0x58] No, No, No, No, No, No, No, No, [0x60] No, No, No, No, No, No, No, No, [0x68] No, No, No, No, No, No, No, No, [0x70] No, No, No, No, No, No, No, No, [0x78] No, Up, No, No, No, No, No, No, }; Rune kbtabshiftesc1[Nscan] = { [0x00] No, No, No, No, No, No, No, No, [0x08] No, No, No, No, No, No, No, No, [0x10] No, No, No, No, No, No, No, No, [0x18] No, No, No, No, No, No, No, No, [0x20] No, No, No, No, No, No, No, No, [0x28] No, No, No, No, No, No, No, No, [0x30] No, No, No, No, No, No, No, No, [0x38] No, No, No, No, No, No, No, No, [0x40] No, No, No, No, No, No, No, No, [0x48] Up, No, No, No, No, No, No, No, [0x50] No, No, No, No, No, No, No, No, [0x58] No, No, No, No, No, No, No, No, [0x60] No, No, No, No, No, No, No, No, [0x68] No, No, No, No, No, No, No, No, [0x70] No, No, No, No, No, No, No, No, [0x78] No, Up, No, No, No, No, No, No, }; Rune kbtabctrlesc1[Nscan] = { [0x00] No, No, No, No, No, No, No, No, [0x08] No, No, No, No, No, No, No, No, [0x10] No, No, No, No, No, No, No, No, [0x18] No, No, No, No, No, No, No, No, [0x20] No, No, No, No, No, No, No, No, [0x28] No, No, No, No, No, No, No, No, [0x30] No, No, No, No, No, No, No, No, [0x38] No, No, No, No, No, No, No, No, [0x40] No, No, No, No, No, No, No, No, [0x48] Up, No, No, No, No, No, No, No, [0x50] No, No, No, No, No, No, No, No, [0x58] No, No, No, No, No, No, No, No, [0x60] No, No, No, No, No, No, No, No, [0x68] No, No, No, No, No, No, No, No, [0x70] No, No, No, No, No, No, No, No, [0x78] No, Up, No, No, No, No, No, No, }; Rune kbtabaltgr[Nscan] = { [0x00] No, No, No, No, No, No, No, No, [0x08] No, No, No, No, No, No, No, No, [0x10] No, No, No, No, No, No, No, No, [0x18] No, No, No, No, '\n', Ctrl, No, No, [0x20] No, No, No, No, No, No, No, No, [0x28] No, No, Shift, No, No, No, No, No, [0x30] No, No, No, No, No, '/', No, Print, [0x38] Altgr, No, No, No, No, No, No, No, [0x40] No, No, No, No, No, No, Break, Home, [0x48] Up, Pgup, No, Left, No, Right, No, End, [0x50] Down, Pgdown, Ins, Del, No, No, No, No, [0x58] No, No, No, No, No, No, No, No, [0x60] No, No, No, No, No, No, No, No, [0x68] No, No, No, No, No, No, No, No, [0x70] No, No, No, No, No, No, No, No, [0x78] No, Up, No, No, No, No, No, No, }; Rune kbtabctrl[Nscan] = { [0x00] No, '', '', '', '', '', '', '', [0x08] '', '', '', '', ' ', '', '\b', '\t', [0x10] '', '', '', '', '', '', '', '\t', [0x18] '', '', '', '', '\n', Ctrl, '', '', [0x20] '', '', '', '\b', '\n', '', '', '', [0x28] '', No, Shift, '', '', '', '', '', [0x30] '', '', ' ', '', '', '', Shift, '\n', [0x38] Latin, No, Ctrl, '', '', '', '', '', [0x40] '', '', '', ' ', '', '', '', '', [0x48] '', '', ' ', '', '', '', '', '', [0x50] '', '', '', '', No, No, No, '', [0x58] '', No, No, No, No, No, No, No, [0x60] No, No, No, No, No, No, No, No, [0x68] No, No, No, No, No, No, No, No, [0x70] No, No, No, No, No, No, No, No, [0x78] No, '', No, '\b', No, No, No, No, }; int mouseshifted; void (*kbdmouse)(int); static int kdebug; typedef struct Kbscan Kbscan; struct Kbscan { int esc1; int esc2; int alt; int altgr; int caps; int ctl; int num; int shift; int collecting; int nk; Rune kc[5]; int buttons; }; Kbscan kbscans[Nscans]; /* kernel and external scan code state */ /* * Scan code processing */ void kbdputsc(int c, int external) { int i, keyup; Kbscan *kbscan; if(external) kbscan = &kbscans[Ext]; else kbscan = &kbscans[Int]; if(kdebug) print("sc %x ms %d\n", c, mouseshifted); /* * e0's is the first of a 2 character sequence, e1 the first * of a 3 character sequence (on the safari) */ if(c == 0xe0){ kbscan->esc1 = 1; return; } else if(c == 0xe1){ kbscan->esc2 = 2; return; } keyup = c & 0x80; c &= 0x7f; if(c > sizeof kbtab){ c |= keyup; if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */ print("unknown key %ux\n", c); return; } if(kbscan->esc1 && kbscan->shift){ c = kbtabshiftesc1[c]; kbscan->esc1 = 0; } else if(kbscan->esc1){ c = kbtabesc1[c]; kbscan->esc1 = 0; } else if(kbscan->esc2){ kbscan->esc2--; return; } else if(kbscan->shift) c = kbtabshift[c]; else if(kbscan->altgr) c = kbtabaltgr[c]; else if(kbscan->ctl) c = kbtabctrl[c]; else c = kbtab[c]; if(kbscan->caps && c<='z' && c>='a') c += 'A' - 'a'; /* * keyup only important for shifts */ if(keyup){ switch(c){ case Latin: kbscan->alt = 0; break; case Shift: kbscan->shift = 0; mouseshifted = 0; if(kdebug) print("shiftclr\n"); break; case Ctrl: kbscan->ctl = 0; break; case Altgr: kbscan->altgr = 0; break; case Kmouse|1: case Kmouse|2: case Kmouse|3: case Kmouse|4: case Kmouse|5: kbscan->buttons &= ~(1<<(c-Kmouse-1)); if(kbdmouse) kbdmouse(kbscan->buttons); break; } return; } /* * normal character */ if(!(c & (Spec|KF))){ if(kbscan->ctl) if(kbscan->alt && c == Del) exit(0); if(!kbscan->collecting){ kbdputc(kbdq, c); return; } kbscan->kc[kbscan->nk++] = c; c = latin1(kbscan->kc, kbscan->nk); if(c < -1) /* need more keystrokes */ return; if(c != -1) /* valid sequence */ kbdputc(kbdq, c); else /* dump characters */ for(i=0; i<kbscan->nk; i++) kbdputc(kbdq, kbscan->kc[i]); kbscan->nk = 0; kbscan->collecting = 0; return; } else { switch(c){ case Caps: kbscan->caps ^= 1; return; case Num: kbscan->num ^= 1; return; case Shift: kbscan->shift = 1; if(kdebug) print("shift\n"); mouseshifted = 1; return; case Latin: kbscan->alt = 1; /* * VMware and Qemu use Ctl-Alt as the key combination * to make the VM give up keyboard and mouse focus. * This has the unfortunate side effect that when you * come back into focus, Plan 9 thinks you want to type * a compose sequence (you just typed alt). * * As a clumsy hack around this, we look for ctl-alt and * don't treat it as the start of a compose sequence. */ if(!kbscan->ctl){ kbscan->collecting = 1; kbscan->nk = 0; } return; case Ctrl: kbscan->ctl = 1; return; case Altgr: kbscan->altgr = 1; return; case Kmouse|1: case Kmouse|2: case Kmouse|3: case Kmouse|4: case Kmouse|5: kbscan->buttons |= 1<<(c-Kmouse-1); if(kbdmouse) kbdmouse(kbscan->buttons); return; case KF|11: print("kbd debug on, F12 turns it off\n"); kdebug = 1; break; case KF|12: kdebug = 0; break;
/* * keyboard interrupt */ static void i8042intr(Ureg*, void*) { int s, c, i; static int esc1, esc2; static int alt, caps, ctl, num, shift; static int collecting, nk; static Rune kc[5]; int keyup; /* * get status */ lock(&i8042lock); s = inb(Status); if(!(s&Inready)){ unlock(&i8042lock); return; } /* * get the character */ c = inb(Data); unlock(&i8042lock); /* * if it's the aux port... */ if(s & Minready){ if(auxputc != nil) auxputc(c, shift); return; } /* * e0's is the first of a 2 character sequence */ if(c == 0xe0){ esc1 = 1; return; } else if(c == 0xe1){ esc2 = 2; return; } keyup = c&0x80; c &= 0x7f; if(c > sizeof kbtab){ c |= keyup; if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */ print("unknown key %ux\n", c); return; } if(esc1){ c = kbtabesc1[c]; esc1 = 0; } else if(esc2){ esc2--; return; } else if(shift) c = kbtabshift[c]; else c = kbtab[c]; if(caps && c<='z' && c>='a') c += 'A' - 'a'; /* * keyup only important for shifts */ if(keyup){ switch(c){ case Latin: alt = 0; break; case Shift: shift = 0; mouseshifted = 0; break; case Ctrl: ctl = 0; break; } return; } /* * normal character */ if(!(c & (Spec|KF))){ if(ctl){ if(alt && c == Del) exit(0); c &= 0x1f; } if(!collecting){ kbdputc(kbdq, c); return; } kc[nk++] = c; c = latin1(kc, nk); if(c < -1) /* need more keystrokes */ return; if(c != -1) /* valid sequence */ kbdputc(kbdq, c); else /* dump characters */ for(i=0; i<nk; i++) kbdputc(kbdq, kc[i]); nk = 0; collecting = 0; return; } else { switch(c){ case Caps: caps ^= 1; return; case Num: num ^= 1; return; case Shift: shift = 1; mouseshifted = 1; return; case Latin: alt = 1; /* * VMware uses Ctl-Alt as the key combination * to make the VM give up keyboard and mouse focus. * This has the unfortunate side effect that when you * come back into focus, Plan 9 thinks you want to type * a compose sequence (you just typed alt). * * As a clumsy hack around this, we look for ctl-alt * and don't treat it as the start of a compose sequence. */ if(!ctl){ collecting = 1; nk = 0; } return; case Ctrl: collecting = 0; nk = 0; ctl = 1; return; } } kbdputc(kbdq, c); }
static void xputc(int c) { kbdputc(kbdq, c); }