Module Name: src
Committed By: jmcneill
Date: Thu Dec 29 21:22:49 UTC 2011
Modified Files:
src/sys/arch/usermode/conf: GENERIC.common Makefile.usermode
files.usermode
src/sys/arch/usermode/dev: mainbus.c
src/sys/arch/usermode/include: mainbus.h thunk.h
src/sys/arch/usermode/usermode: machdep.c thunk.c
Added Files:
src/sys/arch/usermode/dev: vncfb.c vnckbdmap.c
Removed Files:
src/sys/arch/usermode/dev: genfb_thunkbus.c
Log Message:
Replace the SDL based genfb driver with a wsdisplay and wskbd driver that
implements the VNC (RFB) protocol.
To enable the VNC server, add 'vnc=640x480,5900' to the kernel command line
(where 640x480 is the desired fb resolution and 5900 is the TCP port).
Screenshot of it here: http://www.netbsd.org/~jmcneill/usermode.tiff
To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/usermode/conf/GENERIC.common
cvs rdiff -u -r1.25 -r1.26 src/sys/arch/usermode/conf/Makefile.usermode
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/usermode/conf/files.usermode
cvs rdiff -u -r1.1 -r0 src/sys/arch/usermode/dev/genfb_thunkbus.c
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/usermode/dev/mainbus.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/usermode/dev/vncfb.c \
src/sys/arch/usermode/dev/vnckbdmap.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/usermode/include/mainbus.h
cvs rdiff -u -r1.46 -r1.47 src/sys/arch/usermode/include/thunk.h
cvs rdiff -u -r1.46 -r1.47 src/sys/arch/usermode/usermode/machdep.c
cvs rdiff -u -r1.55 -r1.56 src/sys/arch/usermode/usermode/thunk.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/usermode/conf/GENERIC.common
diff -u src/sys/arch/usermode/conf/GENERIC.common:1.6 src/sys/arch/usermode/conf/GENERIC.common:1.7
--- src/sys/arch/usermode/conf/GENERIC.common:1.6 Tue Dec 27 18:24:41 2011
+++ src/sys/arch/usermode/conf/GENERIC.common Thu Dec 29 21:22:49 2011
@@ -1,14 +1,14 @@
-# $NetBSD: GENERIC.common,v 1.6 2011/12/27 18:24:41 jmcneill Exp $
+# $NetBSD: GENERIC.common,v 1.7 2011/12/29 21:22:49 jmcneill Exp $
include "arch/usermode/conf/std.usermode"
options INCLUDE_CONFIG_FILE
-#ident "GENERIC-$Revision: 1.6 $"
+#ident "GENERIC-$Revision: 1.7 $"
maxusers 32
makeoptions DEBUG="-O1 -g3"
-options SYMTAB_SPACE=300000
+options SYMTAB_SPACE=310000
options RTC_OFFSET=0
options KTRACE
@@ -56,9 +56,13 @@ veth0 at mainbus?
vaudio0 at mainbus?
audio0 at vaudio0
-#options SDL
-#genfb0 at thunkbus?
-#wsdisplay0 at genfb?
+vncfb0 at thunkbus?
+wsdisplay0 at vncfb?
+wskbd0 at vncfb?
+options WSEMUL_VT100
+options WS_KERNEL_FG=WSCOL_GREEN
+options WSKBD_DEFAULT_KEYREPEAT_DEL1=1000
+options WSKBD_DEFAULT_KEYREPEAT_DELN=200
pseudo-device loop
pseudo-device pty
Index: src/sys/arch/usermode/conf/Makefile.usermode
diff -u src/sys/arch/usermode/conf/Makefile.usermode:1.25 src/sys/arch/usermode/conf/Makefile.usermode:1.26
--- src/sys/arch/usermode/conf/Makefile.usermode:1.25 Tue Dec 20 21:01:39 2011
+++ src/sys/arch/usermode/conf/Makefile.usermode Thu Dec 29 21:22:49 2011
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.usermode,v 1.25 2011/12/20 21:01:39 jmcneill Exp $
+# $NetBSD: Makefile.usermode,v 1.26 2011/12/29 21:22:49 jmcneill Exp $
OPT_CPU_HOST= %CPU_HOST%
.if !empty(OPT_CPU_HOST)
@@ -37,16 +37,7 @@ DEFCOPTS= -fno-omit-frame-pointer
CPPFLAGS+= -Dusermode
CPPFLAGS.init_main.c+= -Dmain=kernmain
-OPT_SDL= %SDL%
-
-.if !empty(OPT_SDL)
-SDL_CFLAGS!= sdl-config --cflags
-SDL_LIBS!= sdl-config --libs
-USERMODE_LIBS+= -Wl,-Bdynamic ${SDL_LIBS}
-.endif
-
CPPFLAGS.thunk.c+= ${USERMODE_CPPFLAGS}
-CPPFLAGS.thunk_sdl.c+= ${SDL_CFLAGS} ${USERMODE_CPPFLAGS}
##
## (3) libkern and compat
@@ -61,11 +52,6 @@ MD_OBJS= thunk.o
MD_CFILES= ${USERMODE}/usermode/thunk.c
MD_SFILES=
-.if !empty(OPT_SDL)
-MD_OBJS+= thunk_sdl.o
-MD_CFILES+= ${USERMODE}/usermode/thunk_sdl.c
-.endif
-
##
## (5) link settings
##
@@ -98,13 +84,6 @@ thunk.d: ${USERMODE}/usermode/thunk.c
thunk.o: ${USERMODE}/usermode/thunk.c
${CC} ${CPPFLAGS.thunk.c} -c -o $@ ${USERMODE}/usermode/thunk.c
-thunk_sdl.d: ${USERMODE}/usermode/thunk.c
- ${MKDEP} -f ${.TARGET} -- ${MKDEP_CFLAGS} \
- ${CPPFLAGS.thunk_sdl.c} ${USERMODE}/usermode/thunk_sdl.c
-
-thunk_sdl.o: ${USERMODE}/usermode/thunk_sdl.c
- ${CC} ${CPPFLAGS.thunk_sdl.c} -c -o $@ ${USERMODE}/usermode/thunk_sdl.c
-
##
## (7) misc settings
##
Index: src/sys/arch/usermode/conf/files.usermode
diff -u src/sys/arch/usermode/conf/files.usermode:1.14 src/sys/arch/usermode/conf/files.usermode:1.15
--- src/sys/arch/usermode/conf/files.usermode:1.14 Mon Dec 26 21:06:42 2011
+++ src/sys/arch/usermode/conf/files.usermode Thu Dec 29 21:22:49 2011
@@ -1,10 +1,9 @@
-# $NetBSD: files.usermode,v 1.14 2011/12/26 21:06:42 jmcneill Exp $
+# $NetBSD: files.usermode,v 1.15 2011/12/29 21:22:49 jmcneill Exp $
maxpartitions 8
maxusers 8 16 64
defparam opt_memsize.h MEMSIZE
-defflag opt_sdl.h SDL
defflag opt_cpu.h CPU_DEBUG
defparam opt_cpu.h CPU_HOST
defparam opt_misc.h TEXTADDR
@@ -38,8 +37,10 @@ file arch/usermode/dev/vaudio.c vaudio
attach ld at thunkbus with ld_thunkbus
file arch/usermode/dev/ld_thunkbus.c ld_thunkbus
-attach genfb at thunkbus with genfb_thunkbus
-file arch/usermode/dev/genfb_thunkbus.c genfb_thunkbus
+device vncfb { } : wsemuldisplaydev, rasops32, vcons, wskbddev
+attach vncfb at thunkbus
+file arch/usermode/dev/vncfb.c vncfb
+file arch/usermode/dev/vnckbdmap.c vncfb
file arch/usermode/usermode/copy.c
file arch/usermode/usermode/intr.c
Index: src/sys/arch/usermode/dev/mainbus.c
diff -u src/sys/arch/usermode/dev/mainbus.c:1.7 src/sys/arch/usermode/dev/mainbus.c:1.8
--- src/sys/arch/usermode/dev/mainbus.c:1.7 Mon Dec 26 21:06:42 2011
+++ src/sys/arch/usermode/dev/mainbus.c Thu Dec 29 21:22:49 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: mainbus.c,v 1.7 2011/12/26 21:06:42 jmcneill Exp $ */
+/* $NetBSD: mainbus.c,v 1.8 2011/12/29 21:22:49 jmcneill Exp $ */
/*-
* Copyright (c) 2007 Jared D. McNeill <[email protected]>
@@ -26,12 +26,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef _KERNEL_OPT
-#include "opt_sdl.h"
-#endif
-
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.7 2011/12/26 21:06:42 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.8 2011/12/29 21:22:49 jmcneill Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@@ -58,6 +54,7 @@ extern char *usermode_root_image_path;
extern char *usermode_tap_device;
extern char *usermode_tap_eaddr;
extern char *usermode_audio_device;
+extern int usermode_vnc_width, usermode_vnc_height, usermode_vnc_port;
static int
mainbus_match(device_t parent, cfdata_t match, void *opaque)
@@ -80,15 +77,18 @@ mainbus_attach(device_t parent, device_t
taa.taa_type = THUNKBUS_TYPE_CPU;
config_found_ia(self, "thunkbus", &taa, mainbus_print);
-#if defined(SDL)
- taa.taa_type = THUNKBUS_TYPE_GENFB;
+ taa.taa_type = THUNKBUS_TYPE_TTYCONS;
config_found_ia(self, "thunkbus", &taa, mainbus_print);
-#endif
- taa.taa_type = THUNKBUS_TYPE_CLOCK;
- config_found_ia(self, "thunkbus", &taa, mainbus_print);
+ if (usermode_vnc_port > 0 && usermode_vnc_port < 65536) {
+ taa.taa_type = THUNKBUS_TYPE_VNCFB;
+ taa.u.vnc.width = usermode_vnc_width;
+ taa.u.vnc.height = usermode_vnc_height;
+ taa.u.vnc.port = usermode_vnc_port;
+ config_found_ia(self, "thunkbus", &taa, mainbus_print);
+ }
- taa.taa_type = THUNKBUS_TYPE_TTYCONS;
+ taa.taa_type = THUNKBUS_TYPE_CLOCK;
config_found_ia(self, "thunkbus", &taa, mainbus_print);
if (usermode_tap_device) {
Index: src/sys/arch/usermode/include/mainbus.h
diff -u src/sys/arch/usermode/include/mainbus.h:1.6 src/sys/arch/usermode/include/mainbus.h:1.7
--- src/sys/arch/usermode/include/mainbus.h:1.6 Mon Dec 26 21:06:42 2011
+++ src/sys/arch/usermode/include/mainbus.h Thu Dec 29 21:22:49 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: mainbus.h,v 1.6 2011/12/26 21:06:42 jmcneill Exp $ */
+/* $NetBSD: mainbus.h,v 1.7 2011/12/29 21:22:49 jmcneill Exp $ */
/*-
* Copyright (c) 2007 Jared D. McNeill <[email protected]>
@@ -35,7 +35,7 @@ struct thunkbus_attach_args {
#define THUNKBUS_TYPE_CLOCK 1
#define THUNKBUS_TYPE_TTYCONS 2
#define THUNKBUS_TYPE_DISKIMAGE 3
-#define THUNKBUS_TYPE_GENFB 4
+#define THUNKBUS_TYPE_VNCFB 4
#define THUNKBUS_TYPE_VETH 5
#define THUNKBUS_TYPE_VAUDIO 6
@@ -50,6 +50,11 @@ struct thunkbus_attach_args {
struct {
const char *device;
} vaudio;
+ struct {
+ unsigned int width;
+ unsigned int height;
+ uint16_t port;
+ } vnc;
} u;
};
Index: src/sys/arch/usermode/include/thunk.h
diff -u src/sys/arch/usermode/include/thunk.h:1.46 src/sys/arch/usermode/include/thunk.h:1.47
--- src/sys/arch/usermode/include/thunk.h:1.46 Mon Dec 26 21:06:42 2011
+++ src/sys/arch/usermode/include/thunk.h Thu Dec 29 21:22:49 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: thunk.h,v 1.46 2011/12/26 21:06:42 jmcneill Exp $ */
+/* $NetBSD: thunk.h,v 1.47 2011/12/29 21:22:49 jmcneill Exp $ */
/*-
* Copyright (c) 2011 Jared D. McNeill <[email protected]>
@@ -113,6 +113,7 @@ ssize_t thunk_write(int, const void *, s
int thunk_fsync(int);
int thunk_mkstemp(char *);
int thunk_unlink(const char *);
+pid_t thunk_getpid(void);
int thunk_sigaction(int, const struct sigaction *, struct sigaction *);
int thunk_sigaltstack(const stack_t *, stack_t *);
@@ -169,8 +170,48 @@ int thunk_audio_pollin(int);
int thunk_audio_write(int, const void *, size_t);
int thunk_audio_read(int, void *, size_t);
-int thunk_sdl_init(unsigned int, unsigned int, unsigned short);
-void * thunk_sdl_getfb(size_t);
-int thunk_sdl_getchar(void);
+typedef enum {
+ /* client -> server */
+ THUNK_RFB_SET_PIXEL_FORMAT = 0,
+ THUNK_RFB_SET_ENCODINGS = 2,
+ THUNK_RFB_FRAMEBUFFER_UPDATE_REQUEST = 3,
+ THUNK_RFB_KEY_EVENT = 4,
+ THUNK_RFB_POINTER_EVENT = 5,
+ THUNK_RFB_CLIENT_CUT_TEXT = 6,
+} thunk_rfb_message_t;
+
+typedef struct {
+ thunk_rfb_message_t message_type;
+ union {
+ struct {
+ uint8_t down_flag;
+ uint32_t keysym;
+ } key_event;
+ } data;
+} thunk_rfb_event_t;
+
+typedef struct {
+ bool pending;
+ uint16_t x, y, w, h;
+} thunk_rfb_update_t;
+
+typedef struct {
+ int sockfd;
+ int clientfd;
+ thunk_rfb_event_t event;
+
+ bool connected;
+
+ uint16_t width;
+ uint16_t height;
+ uint8_t depth;
+ char name[64];
+ uint8_t *framebuf;
+ thunk_rfb_update_t update;
+} thunk_rfb_t;
+
+int thunk_rfb_open(thunk_rfb_t *, uint16_t);
+int thunk_rfb_poll(thunk_rfb_t *, thunk_rfb_event_t *);
+void thunk_rfb_update(thunk_rfb_t *, int, int, int, int);
#endif /* !_ARCH_USERMODE_INCLUDE_THUNK_H */
Index: src/sys/arch/usermode/usermode/machdep.c
diff -u src/sys/arch/usermode/usermode/machdep.c:1.46 src/sys/arch/usermode/usermode/machdep.c:1.47
--- src/sys/arch/usermode/usermode/machdep.c:1.46 Tue Dec 27 14:55:31 2011
+++ src/sys/arch/usermode/usermode/machdep.c Thu Dec 29 21:22:49 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.46 2011/12/27 14:55:31 reinoud Exp $ */
+/* $NetBSD: machdep.c,v 1.47 2011/12/29 21:22:49 jmcneill Exp $ */
/*-
* Copyright (c) 2011 Reinoud Zandijk <[email protected]>
@@ -35,12 +35,12 @@
#include "opt_memsize.h"
-#include "opt_sdl.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.46 2011/12/27 14:55:31 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.47 2011/12/29 21:22:49 jmcneill Exp $");
#include <sys/types.h>
+#include <sys/systm.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/exec.h>
@@ -71,6 +71,9 @@ char *usermode_tap_device = NULL;
char *usermode_tap_eaddr = NULL;
static char usermode_audio_devicebuf[PATH_MAX] = "";
char *usermode_audio_device = NULL;
+int usermode_vnc_width = 0;
+int usermode_vnc_height = 0;
+int usermode_vnc_port = -1;
void main(int argc, char *argv[]);
void usermode_reboot(void);
@@ -81,20 +84,19 @@ usage(const char *pn)
printf("usage: %s [-acdqsvxz]"
" [tap=<dev>,<eaddr>]"
" [audio=<dev>]"
+ " [vnc=<width>x<height>,<port>]"
" [<fsimg>]\n",
pn);
printf(" (ex. \"%s"
" tap=tap0,00:00:be:ef:ca:fe"
" audio=audio0"
+ " vnc=640x480,5900"
" root.fs\")\n", pn);
}
void
main(int argc, char *argv[])
{
-#if defined(SDL)
- extern int genfb_thunkbus_cnattach(void);
-#endif
extern void ttycons_consinit(void);
extern void pmap_bootstrap(void);
extern void kernmain(void);
@@ -109,10 +111,7 @@ main(int argc, char *argv[])
snprintf(module_machine_usermode, sizeof(module_machine_usermode),
"%susermode", machine);
-#if defined(SDL)
- if (genfb_thunkbus_cnattach() == 0)
-#endif
- ttycons_consinit();
+ ttycons_consinit();
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-') {
@@ -147,6 +146,26 @@ main(int argc, char *argv[])
"%s", audio);
usermode_audio_device =
usermode_audio_devicebuf;
+ } else if (strncmp(argv[i], "vnc=",
+ strlen("vnc=")) == 0) {
+ char *vnc = argv[i] + strlen("vnc=");
+ char *w, *h, *p;
+ w = vnc;
+ h = strchr(w, 'x');
+ if (h == NULL) {
+ printf("bad vnc= format\n");
+ return;
+ }
+ *h++ = '\0';
+ p = strchr(h, ',');
+ if (p == NULL) {
+ printf("bad vnc= format\n");
+ return;
+ }
+ *p++ = '\0';
+ usermode_vnc_width = strtoul(w, NULL, 10);
+ usermode_vnc_height = strtoul(h, NULL, 10);
+ usermode_vnc_port = strtoul(p, NULL, 10);
} else {
usermode_root_image_path = argv[i];
}
Index: src/sys/arch/usermode/usermode/thunk.c
diff -u src/sys/arch/usermode/usermode/thunk.c:1.55 src/sys/arch/usermode/usermode/thunk.c:1.56
--- src/sys/arch/usermode/usermode/thunk.c:1.55 Tue Dec 27 20:59:24 2011
+++ src/sys/arch/usermode/usermode/thunk.c Thu Dec 29 21:22:49 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: thunk.c,v 1.55 2011/12/27 20:59:24 jmcneill Exp $ */
+/* $NetBSD: thunk.c,v 1.56 2011/12/29 21:22:49 jmcneill Exp $ */
/*-
* Copyright (c) 2011 Jared D. McNeill <[email protected]>
@@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifdef __NetBSD__
-__RCSID("$NetBSD: thunk.c,v 1.55 2011/12/27 20:59:24 jmcneill Exp $");
+__RCSID("$NetBSD: thunk.c,v 1.56 2011/12/29 21:22:49 jmcneill Exp $");
#endif
#include <sys/types.h>
@@ -38,15 +38,19 @@ __RCSID("$NetBSD: thunk.c,v 1.55 2011/12
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <sys/audioio.h>
+#include <sys/shm.h>
#include <machine/vmparam.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_ether.h>
#include <net/if_tap.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <aio.h>
#include <assert.h>
+#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <ifaddrs.h>
@@ -492,6 +496,12 @@ thunk_unlink(const char *path)
return unlink(path);
}
+pid_t
+thunk_getpid(void)
+{
+ return getpid();
+}
+
int
thunk_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
{
@@ -849,3 +859,283 @@ thunk_audio_read(int fd, void *buf, size
{
return read(fd, buf, buflen);
}
+
+int
+thunk_rfb_open(thunk_rfb_t *rfb, uint16_t port)
+{
+ struct sockaddr_in sin;
+
+ rfb->clientfd = -1;
+ rfb->connected = false;
+
+ /* create socket */
+ rfb->sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (rfb->sockfd == -1) {
+ printf("rfb: couldn't create socket: %s\n", strerror(errno));
+ return errno;
+ }
+ /* bind to requested port */
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ sin.sin_port = htons(port);
+ if (bind(rfb->sockfd, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
+ printf("rfb: couldn't bind port %d: %s\n", port,
+ strerror(errno));
+ close(rfb->sockfd);
+ return errno;
+ }
+ /* listen for connections */
+ if (listen(rfb->sockfd, 1) != 0) {
+ printf("rfb: couldn't listen on socket: %s\n", strerror(errno));
+ close(rfb->sockfd);
+ return errno;
+ }
+
+ return 0;
+}
+
+static int
+thunk_rfb_server_init(thunk_rfb_t *rfb)
+{
+ char msgbuf[80];
+ char *p = msgbuf;
+ uint32_t namelen = strlen(rfb->name);
+
+ *(uint16_t *)p = htons(rfb->width); p += 2;
+ *(uint16_t *)p = htons(rfb->height); p += 2;
+ *(uint8_t *)p = rfb->depth; p += 1;
+ *(uint8_t *)p = rfb->depth; p += 1;
+ *(uint8_t *)p = 0; p += 1; /* endian */
+ *(uint8_t *)p = 1; p += 1; /* true color */
+ *(uint16_t *)p = htons(0xff); p += 2; /* red max */
+ *(uint16_t *)p = htons(0xff); p += 2; /* green max */
+ *(uint16_t *)p = htons(0xff); p += 2; /* blue max */
+ *(uint8_t *)p = 0; p += 1; /* red shift */
+ *(uint8_t *)p = 8; p += 1; /* green shift */
+ *(uint8_t *)p = 16; p += 1; /* blue shift */
+ *(uint8_t *)p = 0; p += 1; /* padding x3 */
+ *(uint8_t *)p = 0; p += 1;
+ *(uint8_t *)p = 0; p += 1;
+ *(uint32_t *)p = htonl(namelen); p += 4; /* name length */
+ memcpy(p, rfb->name, namelen); p += namelen;
+
+ return send(rfb->clientfd, msgbuf, p - msgbuf, MSG_NOSIGNAL);
+}
+
+static int
+thunk_rfb_handshake(thunk_rfb_t *rfb)
+{
+ ssize_t len;
+ const char *protover = "RFB 003.003\n";
+ uint32_t security_type;
+ uint8_t shared_flag;
+ char dummy;
+
+ /* send server protocol version */
+ len = send(rfb->clientfd, protover, strlen(protover), MSG_NOSIGNAL);
+ if (len == -1)
+ return errno;
+
+ /* receive client protocol version */
+ do {
+ len = recv(rfb->clientfd, &dummy, sizeof(dummy), MSG_NOSIGNAL);
+ if (len == -1)
+ return errno;
+ if (len == 0)
+ return EIO;
+ } while (dummy != '\n');
+
+ /* send security capabilities */
+ security_type = htonl(1); /* no security */
+ len = send(rfb->clientfd, &security_type, sizeof(security_type),
+ MSG_NOSIGNAL);
+ if (len == -1)
+ return errno;
+
+ /* receive client init message */
+ len = recv(rfb->clientfd, &shared_flag, sizeof(shared_flag),
+ MSG_NOSIGNAL);
+ if (len == -1)
+ return errno;
+
+ /* send server init message */
+ len = thunk_rfb_server_init(rfb);
+ if (len == -1)
+ return errno;
+
+ return 0;
+}
+
+static void
+thunk_rfb_send_pending(thunk_rfb_t *rfb)
+{
+ uint8_t rfb_update[16];
+ uint8_t *p = rfb_update;
+ uint16_t x, y, w, h;
+ ssize_t len;
+
+ if (rfb->connected == false || rfb->update.pending == false)
+ return;
+
+ x = rfb->update.x;
+ y = rfb->update.y;
+ w = rfb->update.w;
+ h = rfb->update.h;
+ rfb->update.pending = false;
+
+ *(uint8_t *)p = 0; p += 1; /* FramebufferUpdate */
+ *(uint8_t *)p = 0; p += 1; /* padding */
+ *(uint16_t *)p = htons(1); p += 2; /* # rects */
+ *(uint16_t *)p = htons(x); p += 2;
+ *(uint16_t *)p = htons(y); p += 2;
+ *(uint16_t *)p = htons(w); p += 2;
+ *(uint16_t *)p = htons(h); p += 2;
+ *(uint32_t *)p = htonl(0); p += 4; /* Raw encoding */
+
+ len = send(rfb->clientfd, rfb_update, sizeof(rfb_update),
+ MSG_NOSIGNAL);
+ if (len <= 0)
+ goto disco;
+
+ p = rfb->framebuf + (y * rfb->width * (rfb->depth / 8)) +
+ (x * (rfb->depth / 8));
+ while (h-- > 0) {
+ len = send(rfb->clientfd, p, w * (rfb->depth / 8),
+ MSG_NOSIGNAL);
+ if (len <= 0)
+ goto disco;
+ p += rfb->width * (rfb->depth / 8);
+ }
+
+ return;
+
+disco:
+ fprintf(stdout, "rfb: client disconnected: %s\n", strerror(errno));
+ close(rfb->clientfd);
+ rfb->clientfd = -1;
+ rfb->connected = false;
+}
+
+int
+thunk_rfb_poll(thunk_rfb_t *rfb, thunk_rfb_event_t *event)
+{
+ int error, len, msg_len;
+ uint8_t set_pixel_format[19];
+ uint8_t set_encodings[3];
+ uint8_t framebuffer_update_request[9];
+ uint8_t key_event[7];
+ uint8_t pointer_event[5];
+ uint8_t client_cut_text[7];
+ uint8_t ch;
+
+ if (rfb->clientfd == -1) {
+ struct sockaddr_in sin;
+ struct pollfd fds[1];
+ socklen_t sinlen;
+
+ /* poll for connections */
+ fds[0].fd = rfb->sockfd;
+ fds[0].events = POLLIN;
+ fds[0].revents = 0;
+ if (poll(fds, __arraycount(fds), 0) != 1)
+ return -1;
+
+ sinlen = sizeof(sin);
+ rfb->clientfd = accept(rfb->sockfd, (struct sockaddr *)&sin,
+ &sinlen);
+ if (rfb->clientfd == -1)
+ return -1;
+
+ fprintf(stdout, "rfb: connection from %s:%d\n",
+ inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+
+ /* rfb handshake */
+ if (thunk_rfb_handshake(rfb) != 0) {
+ fprintf(stdout, "rfb: handshake failed\n");
+ close(rfb->clientfd);
+ rfb->clientfd = -1;
+ return -1;
+ }
+
+ rfb->connected = true;
+ thunk_rfb_update(rfb, 0, 0, rfb->width, rfb->height);
+ }
+
+ thunk_rfb_send_pending(rfb);
+ if (rfb->clientfd == -1)
+ return -1;
+
+ error = ioctl(rfb->clientfd, FIONREAD, &len);
+ if (error) {
+ //printf("rfb: FIONREAD failed: %s\n", strerror(errno));
+ close(rfb->clientfd);
+ rfb->clientfd = -1;
+ return -1;
+ }
+ if (len == 0)
+ return 0;
+
+ recv(rfb->clientfd, &ch, sizeof(ch), MSG_NOSIGNAL);
+
+ event->message_type = ch;
+ switch (ch) {
+ case THUNK_RFB_SET_PIXEL_FORMAT:
+ msg_len = sizeof(set_pixel_format);
+ break;
+ case THUNK_RFB_SET_ENCODINGS:
+ recv(rfb->clientfd, set_encodings, sizeof(set_encodings),
+ MSG_NOSIGNAL);
+ msg_len = 4 * ntohs(*(uint16_t *)&set_encodings[1]);
+ break;
+ case THUNK_RFB_FRAMEBUFFER_UPDATE_REQUEST:
+ msg_len = sizeof(framebuffer_update_request);
+ break;
+ case THUNK_RFB_KEY_EVENT:
+ recv(rfb->clientfd, key_event, sizeof(key_event), MSG_NOSIGNAL);
+ event->data.key_event.down_flag = key_event[0];
+ event->data.key_event.keysym =
+ ntohl(*(uint32_t *)&key_event[3]);
+ msg_len = 0;
+ break;
+ case THUNK_RFB_POINTER_EVENT:
+ msg_len = sizeof(pointer_event);
+ break;
+ case THUNK_RFB_CLIENT_CUT_TEXT:
+ recv(rfb->clientfd, client_cut_text, sizeof(client_cut_text),
+ MSG_NOSIGNAL);
+ msg_len = ntohl(*(uint32_t *)&client_cut_text[3]);
+ break;
+ default:
+ fprintf(stdout, "rfb: unknown message type %d\n", ch);
+ close(rfb->clientfd);
+ rfb->clientfd = -1;
+ return -1;
+ }
+
+ /* discard any remaining bytes */
+ while (msg_len-- > 0) {
+ recv(rfb->clientfd, &ch, sizeof(ch), MSG_NOSIGNAL);
+ }
+
+ return 1;
+}
+
+void
+thunk_rfb_update(thunk_rfb_t *rfb, int x, int y, int w, int h)
+{
+ if (rfb->update.pending) {
+ /* pending update, just redraw the whole screen */
+ rfb->update.x = 0;
+ rfb->update.y = 0;
+ rfb->update.w = rfb->width;
+ rfb->update.h = rfb->height;
+ } else {
+ /* try to only update the requested rectangle */
+ rfb->update.x = x;
+ rfb->update.y = y;
+ rfb->update.w = w;
+ rfb->update.h = h;
+ }
+ rfb->update.pending = true;
+}
Added files:
Index: src/sys/arch/usermode/dev/vncfb.c
diff -u /dev/null src/sys/arch/usermode/dev/vncfb.c:1.1
--- /dev/null Thu Dec 29 21:22:50 2011
+++ src/sys/arch/usermode/dev/vncfb.c Thu Dec 29 21:22:49 2011
@@ -0,0 +1,500 @@
+/* $NetBSD: vncfb.c,v 1.1 2011/12/29 21:22:49 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2011 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Jared D. McNeill.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_wsemul.h"
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: vncfb.c,v 1.1 2011/12/29 21:22:49 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/kmem.h>
+
+#include <dev/wscons/wsconsio.h>
+
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/wsfont/wsfont.h>
+#include <dev/rasops/rasops.h>
+#include <dev/wscons/wsdisplay_vconsvar.h>
+
+#include <dev/wscons/wskbdvar.h>
+#include <dev/wscons/wsksymdef.h>
+#include <dev/wscons/wsksymvar.h>
+
+#include <machine/mainbus.h>
+#include <machine/thunk.h>
+
+struct vncfb_fbops {
+ void (*copycols)(void *, int, int, int, int);
+ void (*erasecols)(void *, int, int, int, long);
+ void (*copyrows)(void *, int, int, int);
+ void (*eraserows)(void *, int, int, long);
+ void (*putchar)(void *, int, int, u_int, long);
+};
+
+struct vncfb_softc {
+ device_t sc_dev;
+ device_t sc_wskbddev;
+ thunk_rfb_t sc_rfb;
+ unsigned int sc_width;
+ unsigned int sc_height;
+ unsigned int sc_depth;
+ int sc_mode;
+ uint8_t * sc_framebuf;
+ struct vcons_data sc_vd;
+ struct vncfb_fbops sc_ops;
+
+ int sc_kbd_enable;
+
+ callout_t sc_callout;
+ void *sc_sih;
+};
+
+static int vncfb_match(device_t, cfdata_t, void *);
+static void vncfb_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(vncfb, sizeof(struct vncfb_softc),
+ vncfb_match, vncfb_attach, NULL, NULL);
+
+static void vncfb_putchar(void *, int, int, u_int, long);
+static void vncfb_copycols(void *, int, int, int, int);
+static void vncfb_erasecols(void *, int, int, int, long);
+static void vncfb_copyrows(void *, int, int, int);
+static void vncfb_eraserows(void *, int, int, long);
+
+static int vncfb_ioctl(void *, void *, u_long, void *, int, lwp_t *);
+static paddr_t vncfb_mmap(void *, void *, off_t, int);
+
+static void vncfb_init_screen(void *, struct vcons_screen *, int, long *);
+
+static void vncfb_update(struct vncfb_softc *, int, int, int, int);
+static void vncfb_poll(void *);
+static void vncfb_softintr(void *);
+
+static int vncfb_kbd_enable(void *, int);
+static void vncfb_kbd_set_leds(void *, int);
+static int vncfb_kbd_ioctl(void *, u_long, void *, int, lwp_t *);
+
+static void vncfb_kbd_cngetc(void *, u_int *, int *);
+static void vncfb_kbd_cnpollc(void *, int);
+
+static struct vcons_screen vncfb_console_screen;
+
+static struct wsscreen_descr vncfb_defaultscreen = {
+ .name = "default",
+ .fontwidth = 8,
+ .fontheight = 16,
+ .capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
+};
+
+static const struct wsscreen_descr *vncfb_screens[] = {
+ &vncfb_defaultscreen,
+};
+
+static struct wsscreen_list vncfb_screenlist = {
+ .screens = vncfb_screens,
+ .nscreens = __arraycount(vncfb_screens),
+};
+
+static struct wsdisplay_accessops vncfb_accessops = {
+ .ioctl = vncfb_ioctl,
+ .mmap = vncfb_mmap,
+};
+
+extern const struct wscons_keydesc vnckbd_keydesctab[];
+
+static const struct wskbd_mapdata vncfb_keymapdata = {
+ vnckbd_keydesctab,
+ KB_US,
+};
+
+static struct wskbd_accessops vncfb_kbd_accessops = {
+ vncfb_kbd_enable,
+ vncfb_kbd_set_leds,
+ vncfb_kbd_ioctl,
+};
+
+static const struct wskbd_consops vncfb_kbd_consops = {
+ vncfb_kbd_cngetc,
+ vncfb_kbd_cnpollc,
+ NULL, /* bell */
+};
+
+static int
+vncfb_match(device_t parent, cfdata_t match, void *priv)
+{
+ struct thunkbus_attach_args *taa = priv;
+
+ return taa->taa_type == THUNKBUS_TYPE_VNCFB;
+}
+
+static void
+vncfb_attach(device_t parent, device_t self, void *priv)
+{
+ struct vncfb_softc *sc = device_private(self);
+ struct thunkbus_attach_args *taa = priv;
+ struct wsemuldisplaydev_attach_args waa;
+ struct wskbddev_attach_args kaa;
+ struct rasops_info *ri;
+ unsigned long defattr;
+
+ sc->sc_dev = self;
+ sc->sc_width = taa->u.vnc.width;
+ sc->sc_height = taa->u.vnc.height;
+ sc->sc_depth = 32;
+ sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
+#if notyet
+ sc->sc_sockfd = thunk_vnc_open_socket(taa->u.vnc.port);
+ if (sc->sc_sockfd == -1)
+ panic("couldn't open VNC socket");
+#endif
+
+ sc->sc_framebuf = kmem_zalloc(sc->sc_width * sc->sc_height *
+ (sc->sc_depth / 8), KM_SLEEP);
+ KASSERT(sc->sc_framebuf != NULL);
+
+ callout_init(&sc->sc_callout, 0);
+ callout_setfunc(&sc->sc_callout, vncfb_poll, sc);
+
+ aprint_naive("\n");
+ aprint_normal(": %ux%u %ubpp (port %u)\n",
+ sc->sc_width, sc->sc_height, sc->sc_depth, taa->u.vnc.port);
+
+ sc->sc_rfb.width = sc->sc_width;
+ sc->sc_rfb.height = sc->sc_height;
+ sc->sc_rfb.depth = sc->sc_depth;
+ sc->sc_rfb.framebuf = sc->sc_framebuf;
+ snprintf(sc->sc_rfb.name, sizeof(sc->sc_rfb.name),
+ "NetBSD/usermode %d.%d.%d",
+ __NetBSD_Version__ / 100000000,
+ (__NetBSD_Version__ / 1000000) % 100,
+ (__NetBSD_Version__ / 100) % 100);
+ if (thunk_rfb_open(&sc->sc_rfb, taa->u.vnc.port) != 0)
+ panic("couldn't open rfb server");
+
+ sc->sc_sih = softint_establish(SOFTINT_SERIAL, vncfb_softintr, sc);
+ callout_schedule(&sc->sc_callout, 1);
+
+ vcons_init(&sc->sc_vd, sc, &vncfb_defaultscreen, &vncfb_accessops);
+ sc->sc_vd.init_screen = vncfb_init_screen;
+
+ ri = &vncfb_console_screen.scr_ri;
+ vcons_init_screen(&sc->sc_vd, &vncfb_console_screen, 1, &defattr);
+ vncfb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
+ vncfb_defaultscreen.textops = &ri->ri_ops;
+ vncfb_defaultscreen.capabilities = ri->ri_caps;
+ vncfb_defaultscreen.nrows = ri->ri_rows;
+ vncfb_defaultscreen.ncols = ri->ri_cols;
+ wsdisplay_cnattach(&vncfb_defaultscreen, ri, 0, 0, defattr);
+
+ vcons_replay_msgbuf(&vncfb_console_screen);
+
+ waa.console = true;
+ waa.scrdata = &vncfb_screenlist;
+ waa.accessops = &vncfb_accessops;
+ waa.accesscookie = &sc->sc_vd;
+
+ config_found(self, &waa, wsemuldisplaydevprint);
+
+ wskbd_cnattach(&vncfb_kbd_consops, sc, &vncfb_keymapdata);
+
+ kaa.console = true;
+ kaa.keymap = &vncfb_keymapdata;
+ kaa.accessops = &vncfb_kbd_accessops;
+ kaa.accesscookie = sc;
+
+ sc->sc_wskbddev = config_found_ia(self, "wskbddev", &kaa,
+ wskbddevprint);
+}
+
+static void
+vncfb_init_screen(void *priv, struct vcons_screen *scr, int existing,
+ long *defattr)
+{
+ struct vncfb_softc *sc = priv;
+ struct vncfb_fbops *ops = &sc->sc_ops;
+ struct rasops_info *ri = &scr->scr_ri;
+
+ ri->ri_width = sc->sc_width;
+ ri->ri_height = sc->sc_height;
+ ri->ri_depth = sc->sc_depth;
+ ri->ri_stride = sc->sc_width * ri->ri_depth / 8;
+ ri->ri_bits = sc->sc_framebuf;
+ ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
+ if (existing)
+ ri->ri_flg |= RI_CLEAR;
+
+ rasops_init(ri, sc->sc_height / 8, sc->sc_width / 8);
+ ri->ri_caps = WSSCREEN_WSCOLORS;
+ rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
+ sc->sc_width / ri->ri_font->fontwidth);
+
+ ri->ri_hw = scr;
+
+ ops->putchar = ri->ri_ops.putchar;
+ ops->copyrows = ri->ri_ops.copyrows;
+ ops->eraserows = ri->ri_ops.eraserows;
+ ops->copycols = ri->ri_ops.copycols;
+ ops->erasecols = ri->ri_ops.erasecols;
+
+ ri->ri_ops.copyrows = vncfb_copyrows;
+ ri->ri_ops.copycols = vncfb_copycols;
+ ri->ri_ops.eraserows = vncfb_eraserows;
+ ri->ri_ops.erasecols = vncfb_erasecols;
+ ri->ri_ops.putchar = vncfb_putchar;
+}
+
+static void
+vncfb_putchar(void *priv, int row, int col, u_int c, long attr)
+{
+ struct rasops_info *ri = priv;
+ struct vcons_screen *scr = ri->ri_hw;
+ struct vncfb_softc *sc = scr->scr_cookie;
+ struct vncfb_fbops *ops = &sc->sc_ops;
+ int x, y, w, h;
+
+ ops->putchar(ri, row, col, c, attr);
+
+ x = ri->ri_xorigin + (col * ri->ri_font->fontwidth);
+ y = ri->ri_yorigin + (row * ri->ri_font->fontheight);
+ w = ri->ri_font->fontwidth;
+ h = ri->ri_font->fontheight;
+
+ vncfb_update(sc, x, y, w, h);
+}
+
+static void
+vncfb_copycols(void *priv, int row, int srccol, int dstcol, int ncols)
+{
+ struct rasops_info *ri = priv;
+ struct vcons_screen *scr = ri->ri_hw;
+ struct vncfb_softc *sc = scr->scr_cookie;
+ struct vncfb_fbops *ops = &sc->sc_ops;
+ int x, y, w, h;
+
+ ops->copycols(ri, row, srccol, dstcol, ncols);
+
+ y = ri->ri_yorigin + (row * ri->ri_font->fontheight);
+ h = ri->ri_font->fontheight;
+ if (srccol < dstcol) {
+ x = ri->ri_xorigin + (srccol * ri->ri_font->fontwidth);
+ w = (dstcol - srccol) * ri->ri_font->fontwidth;
+
+ } else {
+ x = ri->ri_xorigin + (dstcol * ri->ri_font->fontwidth);
+ w = (srccol - dstcol) * ri->ri_font->fontwidth;
+ }
+
+ vncfb_update(sc, x, y, w, h);
+}
+
+static void
+vncfb_erasecols(void *priv, int row, int startcol, int ncols, long fillattr)
+{
+ struct rasops_info *ri = priv;
+ struct vcons_screen *scr = ri->ri_hw;
+ struct vncfb_softc *sc = scr->scr_cookie;
+ struct vncfb_fbops *ops = &sc->sc_ops;
+ int x, y, w, h;
+
+ ops->erasecols(ri, row, startcol, ncols, fillattr);
+
+ y = ri->ri_yorigin + (row * ri->ri_font->fontheight);
+ h = ri->ri_font->fontheight;
+ x = ri->ri_xorigin + (startcol * ri->ri_font->fontwidth);
+ w = ncols * ri->ri_font->fontwidth;
+
+ vncfb_update(sc, x, y, w, h);
+}
+
+static void
+vncfb_copyrows(void *priv, int srcrow, int dstrow, int nrows)
+{
+ struct rasops_info *ri = priv;
+ struct vcons_screen *scr = ri->ri_hw;
+ struct vncfb_softc *sc = scr->scr_cookie;
+ struct vncfb_fbops *ops = &sc->sc_ops;
+ int x, y, w, h;
+
+ ops->copyrows(ri, srcrow, dstrow, nrows);
+
+ x = ri->ri_xorigin;
+ w = ri->ri_width;
+ if (srcrow < dstrow) {
+ y = ri->ri_yorigin + (srcrow * ri->ri_font->fontheight);
+ h = (dstrow - srcrow) * ri->ri_font->fontheight;
+ } else {
+ y = ri->ri_yorigin + (dstrow * ri->ri_font->fontheight);
+ h = (srcrow - dstrow) * ri->ri_font->fontheight;
+ }
+
+ vncfb_update(sc, x, y, w, h);
+}
+
+static void
+vncfb_eraserows(void *priv, int row, int nrows, long fillattr)
+{
+ struct rasops_info *ri = priv;
+ struct vcons_screen *scr = ri->ri_hw;
+ struct vncfb_softc *sc = scr->scr_cookie;
+ struct vncfb_fbops *ops = &sc->sc_ops;
+ int x, y, w, h;
+
+ ops->eraserows(ri, row, nrows, fillattr);
+
+ y = ri->ri_yorigin + (row * ri->ri_font->fontheight);
+ h = nrows * ri->ri_font->fontheight;
+ x = ri->ri_xorigin;
+ w = ri->ri_width;
+
+ vncfb_update(sc, x, y, w, h);
+}
+
+static int
+vncfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l)
+{
+ struct vcons_data *vd = v;
+ struct vncfb_softc *sc = vd->cookie;
+ struct wsdisplay_fbinfo *wdf;
+ struct vcons_screen *ms = vd->active;
+ int new_mode;
+
+ switch (cmd) {
+ case WSDISPLAYIO_GTYPE:
+ *(u_int *)data = WSDISPLAY_TYPE_VNC;
+ return 0;
+ case WSDISPLAYIO_GINFO:
+ wdf = data;
+ wdf->height = ms->scr_ri.ri_height;
+ wdf->width = ms->scr_ri.ri_width;
+ wdf->depth = ms->scr_ri.ri_depth;
+ wdf->cmsize = 256;
+ return 0;
+ case WSDISPLAYIO_SMODE:
+ new_mode = *(int *)data;
+ if (sc->sc_mode != new_mode) {
+ sc->sc_mode = new_mode;
+ if (new_mode == WSDISPLAYIO_MODE_EMUL)
+ vcons_redraw_screen(ms);
+ }
+ return 0;
+ default:
+ return EPASSTHROUGH;
+ }
+}
+
+static paddr_t
+vncfb_mmap(void *v, void *vs, off_t offset, int prot)
+{
+ /* TODO */
+ return -1;
+}
+
+static void
+vncfb_update(struct vncfb_softc *sc, int x, int y, int w, int h)
+{
+ thunk_rfb_update(&sc->sc_rfb, x, y, w, h);
+}
+
+static void
+vncfb_poll(void *priv)
+{
+ struct vncfb_softc *sc = priv;
+
+ softint_schedule(sc->sc_sih);
+}
+
+static void
+vncfb_softintr(void *priv)
+{
+ struct vncfb_softc *sc = priv;
+ thunk_rfb_event_t event;
+ int s;
+
+ while (thunk_rfb_poll(&sc->sc_rfb, &event) > 0) {
+ switch (event.message_type) {
+ case THUNK_RFB_KEY_EVENT:
+ s = spltty();
+ wskbd_input(sc->sc_wskbddev,
+ event.data.key_event.down_flag ?
+ WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP,
+ event.data.key_event.keysym & 0xfff);
+ splx(s);
+ break;
+ default:
+ break;
+ }
+ }
+
+ callout_schedule(&sc->sc_callout, 1);
+}
+
+static int
+vncfb_kbd_enable(void *priv, int on)
+{
+ struct vncfb_softc *sc = priv;
+
+ sc->sc_kbd_enable = on;
+
+ return 0;
+}
+
+static void
+vncfb_kbd_set_leds(void *priv, int leds)
+{
+}
+
+static int
+vncfb_kbd_ioctl(void *priv, u_long cmd, void *data, int flag, lwp_t *l)
+{
+ switch (cmd) {
+ case WSKBDIO_GTYPE:
+ *(int *)data = WSKBD_TYPE_RFB;
+ return 0;
+ default:
+ return EPASSTHROUGH;
+ }
+}
+
+static void
+vncfb_kbd_cngetc(void *priv, u_int *type, int *data)
+{
+}
+
+static void
+vncfb_kbd_cnpollc(void *priv, int on)
+{
+}
Index: src/sys/arch/usermode/dev/vnckbdmap.c
diff -u /dev/null src/sys/arch/usermode/dev/vnckbdmap.c:1.1
--- /dev/null Thu Dec 29 21:22:50 2011
+++ src/sys/arch/usermode/dev/vnckbdmap.c Thu Dec 29 21:22:49 2011
@@ -0,0 +1,221 @@
+/* $NetBSD: vnckbdmap.c,v 1.1 2011/12/29 21:22:49 jmcneill Exp $ */
+
+/*
+ * Copyright (c) 1999,2001,2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson ([email protected]) at
+ * Carlstedt Research & Technology.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: vnckbdmap.c,v 1.1 2011/12/29 21:22:49 jmcneill Exp $");
+
+#include <sys/types.h>
+#include <dev/wscons/wsksymdef.h>
+#include <dev/wscons/wsksymvar.h>
+
+#define KC(n) KS_KEYCODE(n)
+
+static const keysym_t vnckbd_keydesc_us[] = {
+/* pos command normal shifted */
+
+ /* X11 TTY function keys */
+ KC(0xf08), KS_BackSpace,
+ KC(0xf09), KS_Tab,
+ KC(0xf0a), KS_Linefeed,
+ KC(0xf0b), KS_Clear,
+ KC(0xf0d), KS_Return,
+ KC(0xf13), KS_Pause,
+ KC(0xf14), KS_Hold_Screen,
+// KC(0xf15), KS_SysReq,
+ KC(0xf1b), KS_Escape,
+ KC(0xfff), KS_Delete,
+
+ /* X11 cursor control & motion */
+ KC(0xf50), KS_Home,
+ KC(0xf51), KS_Left,
+ KC(0xf52), KS_Up,
+ KC(0xf53), KS_Right,
+ KC(0xf54), KS_Down,
+ KC(0xf55), KS_Prior,
+ KC(0xf56), KS_Next,
+ KC(0xf57), KS_End,
+// KC(0xf58), KS_Begin,
+
+ /* X11 misc functions */
+ KC(0xf60), KS_Select,
+ KC(0xf61), KS_Print_Screen,
+ KC(0xf62), KS_Execute,
+ KC(0xf63), KS_Insert,
+ KC(0xf65), KS_Undo,
+ KC(0xf66), KS_Again,
+ KC(0xf67), KS_Menu,
+ KC(0xf68), KS_Find,
+// KC(0xf69), KS_Cancel,
+ KC(0xf6a), KS_Help,
+// KC(0xf6b), KS_Break,
+ KC(0xf7e), KS_Mode_switch,
+ KC(0xf7f), KS_Num_Lock,
+
+ /* X11 keypad functions */
+ /* ... */
+
+ /* X11 auxiliary functions */
+ /* ... */
+
+ /* X11 modifiers */
+ KC(0xfe1), KS_Shift_L,
+ KC(0xfe2), KS_Shift_R,
+ KC(0xfe3), KS_Control_L,
+ KC(0xfe4), KS_Control_R,
+ KC(0xfe5), KS_Caps_Lock,
+ KC(0xfe6), KS_Shift_Lock,
+ KC(0xfe7), KS_Meta_L,
+ KC(0xfe8), KS_Meta_R,
+ KC(0xfe9), KS_Alt_L,
+ KC(0xfea), KS_Alt_R,
+// KC(0xfeb), KS_Super_L,
+// KC(0xfec), KS_Super_R,
+// KC(0xfed), KS_Hyper_L,
+// KC(0xfee), KS_Hyper_R,
+
+ /* Latin 1 */
+ KC(0x20), KS_space,
+ KC(0x21), KS_exclam,
+ KC(0x22), KS_quotedbl,
+ KC(0x23), KS_numbersign,
+ KC(0x24), KS_dollar,
+ KC(0x25), KS_percent,
+ KC(0x26), KS_ampersand,
+ KC(0x27), KS_apostrophe,
+ KC(0x28), KS_parenleft,
+ KC(0x29), KS_parenright,
+ KC(0x2a), KS_asterisk,
+ KC(0x2b), KS_plus,
+ KC(0x2c), KS_comma,
+ KC(0x2d), KS_minus,
+ KC(0x2e), KS_period,
+ KC(0x2f), KS_slash,
+ KC(0x30), KS_0,
+ KC(0x31), KS_1,
+ KC(0x32), KS_2,
+ KC(0x33), KS_3,
+ KC(0x34), KS_4,
+ KC(0x35), KS_5,
+ KC(0x36), KS_6,
+ KC(0x37), KS_7,
+ KC(0x38), KS_8,
+ KC(0x39), KS_9,
+ KC(0x3a), KS_colon,
+ KC(0x3b), KS_semicolon,
+ KC(0x3c), KS_less,
+ KC(0x3d), KS_equal,
+ KC(0x3e), KS_greater,
+ KC(0x3f), KS_question,
+ KC(0x40), KS_at,
+ KC(0x41), KS_A,
+ KC(0x42), KS_B,
+ KC(0x43), KS_C,
+ KC(0x44), KS_D,
+ KC(0x45), KS_E,
+ KC(0x46), KS_F,
+ KC(0x47), KS_G,
+ KC(0x48), KS_H,
+ KC(0x49), KS_I,
+ KC(0x4a), KS_J,
+ KC(0x4b), KS_K,
+ KC(0x4c), KS_L,
+ KC(0x4d), KS_M,
+ KC(0x4e), KS_N,
+ KC(0x4f), KS_O,
+ KC(0x50), KS_P,
+ KC(0x51), KS_Q,
+ KC(0x52), KS_R,
+ KC(0x53), KS_S,
+ KC(0x54), KS_T,
+ KC(0x55), KS_U,
+ KC(0x56), KS_V,
+ KC(0x57), KS_W,
+ KC(0x58), KS_X,
+ KC(0x59), KS_Y,
+ KC(0x5a), KS_Z,
+ KC(0x5b), KS_bracketleft,
+ KC(0x5c), KS_backslash,
+ KC(0x5d), KS_bracketright,
+ KC(0x5e), KS_asciicircum,
+ KC(0x5f), KS_underscore,
+ KC(0x60), KS_grave,
+ KC(0x61), KS_a,
+ KC(0x62), KS_b,
+ KC(0x63), KS_c,
+ KC(0x64), KS_d,
+ KC(0x65), KS_e,
+ KC(0x66), KS_f,
+ KC(0x67), KS_g,
+ KC(0x68), KS_h,
+ KC(0x69), KS_i,
+ KC(0x6a), KS_j,
+ KC(0x6b), KS_k,
+ KC(0x6c), KS_l,
+ KC(0x6d), KS_m,
+ KC(0x6e), KS_n,
+ KC(0x6f), KS_o,
+ KC(0x70), KS_p,
+ KC(0x71), KS_q,
+ KC(0x72), KS_r,
+ KC(0x73), KS_s,
+ KC(0x74), KS_t,
+ KC(0x75), KS_u,
+ KC(0x76), KS_v,
+ KC(0x77), KS_w,
+ KC(0x78), KS_x,
+ KC(0x79), KS_y,
+ KC(0x7a), KS_z,
+ KC(0x7b), KS_braceleft,
+ KC(0x7c), KS_bar,
+ KC(0x7d), KS_braceright,
+ KC(0x7e), KS_asciitilde,
+ KC(0x7f), KS_Delete,
+/* TODO:
+ KC(0xa0), KS_nobreakspace,
+ KC(0xa1), KS_exclamdown,
+ KC(0xa2), KS_cent,
+ KC(0xa3), KS_sterling,
+ ...
+ */
+
+};
+
+#define KBD_MAP(name, base, map) \
+ { name, base, sizeof(map)/sizeof(keysym_t), map }
+
+const struct wscons_keydesc vnckbd_keydesctab[] = {
+ KBD_MAP(KB_US, 0, vnckbd_keydesc_us),
+ {0, 0, 0, 0}
+};
+
+#undef KBD_MAP
+#undef KC