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