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 <jmcne...@invisible.ca>
@@ -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 <jmcne...@invisible.ca>
@@ -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 <jmcne...@invisible.ca>
@@ -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 <rein...@netbsd.org>
@@ -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 <jmcne...@invisible.ca>
@@ -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 <jmcne...@invisible.ca>
+ * 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 (lenn...@augustsson.net) 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

Reply via email to