ref: 5dc9cad6a69e06717ebe294735579a189bb010e0
parent: b103246745d12e985699a04877cbfa2d6138d9fb
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Feb 26 23:26:51 EST 2016
/dev/kbd support for rcpu (requires updated kbdfs on remote side) we provide minimal /dev/kbd just serving rune up/down messages which kbdfs will translate to full /dev/cons and /dev/kbd. this has the advantage that kbdfs can generate notes (interrupt key) for us and post hangup note when the connection breaks. drawterms task is relatively simple, just trnalsate keysyms to runes. this is essentially what vncs does.
--- a/cpu.c
+++ b/cpu.c
@@ -38,26 +38,9 @@
/* authentication mechanisms */
static int p9auth(int);
-static int srvp9auth(int, char*);
char *authserver;
-typedef struct AuthMethod AuthMethod;
-struct AuthMethod {
- char *name; /* name of method */
- int (*cf)(int); /* client side authentication */
- int (*sf)(int, char*); /* server side authentication */
-} authmethod[] =
-{
- { "p9", p9auth, srvp9auth,},
- { 0 }
-};
-AuthMethod *am = authmethod; /* default is p9 */
-
-char *p9authproto = "p9any";
-
-int setam(char*);
-
void
exits(char *s)
{
@@ -96,11 +79,11 @@
rcpu(char *host)
{
static char script[] =
-"mount -nc /fd/0 /mnt/term || exit \n"
-"bind -q /mnt/term/dev/cons /dev/cons \n"
-"</dev/cons >/dev/cons >[2=1] { \n"
-" service=cpu exec rc -li \n"
-"} \n";
+"mount -nc /fd/0 /mnt/term || exit\n"
+"bind -q /mnt/term/dev/cons /dev/cons\n"
+"</dev/cons >/dev/cons >[2=1] aux/kbdfs -dq -m /mnt/term/dev\n"
+"bind -q /mnt/term/dev/cons /dev/cons\n"
+"</dev/cons >/dev/cons >[2=1] service=cpu exec rc -li\n";
AuthInfo *ai;
TLSconn *conn;
char *na;
@@ -110,6 +93,10 @@
if((fd = dial(na, 0, 0, 0)) < 0)
return;
+ /* provide /dev/kbd for kbdfs */
+ if(bind("#b", "/dev", MAFTER) < 0)
+ panic("bind #b: %r");
+
ai = p9any(fd);
if(ai == nil)
fatal(1, "can't authenticate");
@@ -282,8 +269,6 @@
char *negstr = "negotiating authentication method";
-char bug[256];
-
char*
rexcall(int *fd, char *host, char *service)
{
@@ -298,10 +283,11 @@
return "can't dial";
/* negotiate authentication mechanism */
- if(ealgs != nil)
- snprint(msg, sizeof(msg), "%s %s", am->name, ealgs);
- else
- snprint(msg, sizeof(msg), "%s", am->name);
+ strcpy(msg, "p9any");
+ if(ealgs != nil){
+ strcat(msg, " ");
+ strcat(msg, ealgs);
+ }
writestr(*fd, msg, negstr, 0);
n = readstr(*fd, err, sizeof err);
if(n < 0)
@@ -312,7 +298,7 @@
}
/* authenticate */
- *fd = (*am->cf)(*fd);
+ *fd = p9auth(*fd);
if(*fd < 0)
return "can't authenticate";
return 0;
@@ -740,23 +726,4 @@
free(proto);
return ai;
-}
-
-static int
-srvp9auth(int fd, char *user)
-{
- return -1;
-}
-
-/*
- * set authentication mechanism
- */
-int
-setam(char *name)
-{
- for(am = authmethod; am->name != nil; am++)
- if(strcmp(am->name, name) == 0)
- return 0;
- am = authmethod;
- return -1;
}
--- a/gui-win32/screen.c
+++ b/gui-win32/screen.c
@@ -321,14 +321,41 @@
p[i] = i;
}
+
+Rune vk2rune[256] = {
+[VK_CANCEL] Kbreak,
+[VK_CAPITAL] Kcaps,
+[VK_CONTROL] Kctl,
+[VK_DELETE] Kdel,
+[VK_DOWN] Kdown,
+[VK_END] Kend,
+[VK_F1] KF|1,KF|2,KF|3,KF|4,KF|5,KF|6,KF|7,KF|8,KF|9,KF|10,KF|11,KF|12,
+[VK_HOME] Khome,
+[VK_INSERT] Kins,
+[VK_LEFT] Kleft,
+[VK_MENU] Kalt,
+[VK_NEXT] Kpgdown,
+[VK_NUMLOCK] Knum,
+[VK_PRINT] Kprint,
+[VK_PRIOR] Kpgup,
+[VK_RIGHT] Kright,
+[VK_RMENU] Kaltgr,
+[VK_SCROLL] Kscroll,
+[VK_SHIFT] Kshift,
+[VK_UP] Kup,
+};
+
+
LRESULT CALLBACK
WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
+ static Rune scdown[256];
PAINTSTRUCT paint;
HDC hdc;
LONG x, y, b;
int i;
Rectangle r;
+ Rune k;
b = 0;
@@ -392,56 +419,29 @@
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;
+ k = wparam;
+ if(k == '\n')
+ k = '\r';
+ else if(k == '\r')
+ k = '\n';
+ if(0){
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
- switch(wparam) {
- case VK_MENU:
- kbdputc(kbdq, Kalt);
+ k = vk2rune[wparam&0xFF];
+ }
+ if(k == 0)
break;
- case VK_INSERT:
- kbdputc(kbdq, Kins);
- break;
- case VK_DELETE:
- kbdputc(kbdq, Kdel);
- 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;
- 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;
+ i = (lparam>>16)&0xFF;
+ scdown[i] = k;
+ kbdkey(k, 1);
+ break;
+ case WM_SYSKEYUP:
+ case WM_KEYUP:
+ i = (lparam>>16)&0xFF;
+ k = scdown[i];
+ if(k != 0){
+ scdown[i] = 0;
+ kbdkey(k, 0);
}
break;
--- a/gui-x11/x11.c
+++ b/gui-x11/x11.c
@@ -660,6 +660,7 @@
XEvent event;
mask = KeyPressMask|
+ KeyReleaseMask|
ButtonPressMask|
ButtonReleaseMask|
PointerMotionMask|
@@ -1123,10 +1124,9 @@
* do case conversion properly
* (at least, with Xterminal servers and R4 intrinsics)
*/
- if(e->xany.type != KeyPress)
+ if(e->xany.type != KeyPress && e->xany.type != KeyRelease)
return;
-
XLookupString((XKeyEvent*)e, NULL, 0, &k, NULL);
if(k == XK_Multi_key || k == NoSymbol)
@@ -1252,7 +1252,7 @@
return;
}
- kbdputc(kbdq, k);
+ kbdkey(k, e->xany.type == KeyPress);
}
static void
--- a/kern/Makefile
+++ b/kern/Makefile
@@ -15,6 +15,7 @@
devfs-$(OS).$O\
devip.$O\
devip-$(OS).$O\
+ devkbd.$O\
devlfd.$O\
devmnt.$O\
devmouse.$O\
--- /dev/null
+++ b/kern/devkbd.c
@@ -1,0 +1,141 @@
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+
+static Queue* keyq;
+static int kbdinuse;
+
+void
+kbdkey(Rune r, int down)
+{
+ char buf[2+UTFmax];
+
+ if(r == 0)
+ return;
+
+ if(!kbdinuse || keyq == nil){
+ if(down)
+ kbdputc(kbdq, r); /* /dev/cons */
+ return;
+ }
+
+ memset(buf, 0, sizeof buf);
+ buf[0] = down ? 'r' : 'R';
+ qproduce(keyq, buf, 2+runetochar(buf+1, &r));
+}
+
+enum{
+ Qdir,
+ Qkbd,
+};
+
+static Dirtab kbddir[]={
+ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
+ "kbd", {Qkbd}, 0, 0444,
+};
+
+static void
+kbdinit(void)
+{
+ keyq = qopen(4*1024, 0, 0, 0);
+ if(keyq == nil)
+ panic("kbdinit");
+ qnoblock(keyq, 1);
+}
+
+static Chan*
+kbdattach(char *spec)
+{
+ return devattach('b', spec);
+}
+
+static Walkqid*
+kbdwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name,nname, kbddir, nelem(kbddir), devgen);
+}
+
+static int
+kbdstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, kbddir, nelem(kbddir), devgen);
+}
+
+static Chan*
+kbdopen(Chan *c, int omode)
+{
+ c = devopen(c, omode, kbddir, nelem(kbddir), devgen);
+ switch((ulong)c->qid.path){
+ case Qkbd:
+ if(kbdinuse){
+ c->flag &= ~COPEN;
+ error(Einuse);
+ }
+ kbdinuse = 1;
+ break;
+ }
+ return c;
+}
+
+static void
+kbdclose(Chan *c)
+{
+ switch((ulong)c->qid.path){
+ case Qkbd:
+ if(c->flag&COPEN)
+ kbdinuse = 0;
+ break;
+ }
+}
+
+static long
+kbdread(Chan *c, void *buf, long n, vlong off)
+{
+ USED(off);
+
+ if(n <= 0)
+ return n;
+ switch((ulong)c->qid.path){
+ case Qdir:
+ return devdirread(c, buf, n, kbddir, nelem(kbddir), devgen);
+ case Qkbd:
+ return qread(keyq, buf, n);
+ default:
+ print("kbdread 0x%llux\n", c->qid.path);
+ error(Egreg);
+ }
+ return -1; /* never reached */
+}
+
+static long
+kbdwrite(Chan *c, void *va, long n, vlong off)
+{
+ USED(c);
+ USED(va);
+ USED(n);
+ USED(off);
+ error(Eperm);
+}
+
+Dev kbddevtab = {
+ 'b',
+ "kbd",
+
+ devreset,
+ kbdinit,
+ devshutdown,
+ kbdattach,
+ kbdwalk,
+ kbdstat,
+ kbdopen,
+ devcreate,
+ kbdclose,
+ kbdread,
+ devbread,
+ kbdwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
--- a/kern/devtab.c
+++ b/kern/devtab.c
@@ -16,6 +16,7 @@
extern Dev mntdevtab;
extern Dev lfddevtab;
extern Dev audiodevtab;
+extern Dev kbddevtab;
Dev *devtab[] = {
&rootdevtab,
@@ -30,6 +31,7 @@
&mntdevtab,
&lfddevtab,
&audiodevtab,
+ &kbddevtab,
0
};
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -140,6 +140,7 @@
void kbdclock(void);
int kbdcr2nl(Queue*, int);
int kbdputc(Queue*, int);
+void kbdkey(Rune, int);
void kbdrepeat(int);
long keyread(char*, int, long);
void kickpager(void);