wok diff busybox/stuff/busybox-1.23-fbvnc.u @ rev 17543

Up busybox (1.23.1)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Tue Jan 27 16:55:03 2015 +0100 (2015-01-27)
parents
children dbf4eeed945f
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/busybox/stuff/busybox-1.23-fbvnc.u	Tue Jan 27 16:55:03 2015 +0100
     1.3 @@ -0,0 +1,681 @@
     1.4 +   text    data     bss     dec     hex filename
     1.5 +   3118       0       0    3118     c2e util-linux/fbvnc.o
     1.6 +--- /dev/null
     1.7 ++++ busybox/util-linux/fbvnc.c
     1.8 +@@ -0,0 +1,551 @@
     1.9 ++/* vi: set sw=4 ts=4: */
    1.10 ++/*
    1.11 ++ * A small linux framebuffer VNC viewer
    1.12 ++ *
    1.13 ++ * pascal.bellard@ads-lu.com
    1.14 ++ *
    1.15 ++ * Based on Ali Gholami Rudi's fbvnc.c
    1.16 ++ *   http://repo.or.cz/w/fbvnc.git
    1.17 ++ *
    1.18 ++ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1.19 ++ */
    1.20 ++
    1.21 ++//applet:IF_FBVNC(APPLET(fbvnc, BB_DIR_BIN, BB_SUID_DROP))
    1.22 ++
    1.23 ++//kbuild:lib-$(CONFIG_FBVNC) += fbvnc.o
    1.24 ++
    1.25 ++//config:config FBVNC
    1.26 ++//config:	bool "fbvnc"
    1.27 ++//config:	default n
    1.28 ++//config:	depends on PLATFORM_LINUX
    1.29 ++//config:	help
    1.30 ++//config:	  A linux framebuffer VNC viewer.
    1.31 ++
    1.32 ++//usage:#define fbvnc_trivial_usage
    1.33 ++//usage:	"[VNC_SERVER] [PORT]"
    1.34 ++//usage:#define fbvnc_full_usage "\n\n"
    1.35 ++//usage:     "A linux framebuffer VNC viewer."
    1.36 ++//usage:     "\nTo exit, move mouse to upper left corner and press ESC."
    1.37 ++
    1.38 ++#include "libbb.h"
    1.39 ++#include "vnc.h"
    1.40 ++
    1.41 ++/* Stuff stolen from the kernel's fb.h */
    1.42 ++#define FB_ACTIVATE_ALL 64
    1.43 ++enum {
    1.44 ++	FBIOGET_VSCREENINFO = 0x4600,
    1.45 ++	FBIOPUT_VSCREENINFO = 0x4601,
    1.46 ++	FBIOGET_FSCREENINFO = 0x4602,
    1.47 ++	FBIOGETCMAP = 0x4604,
    1.48 ++	FBIOPUTCMAP = 0x4605
    1.49 ++};
    1.50 ++
    1.51 ++struct fb_bitfield {
    1.52 ++	uint32_t offset;                /* beginning of bitfield */
    1.53 ++	uint32_t length;                /* length of bitfield */
    1.54 ++	uint32_t msb_right;             /* !=0: Most significant bit is right */
    1.55 ++};
    1.56 ++struct fb_var_screeninfo {
    1.57 ++	uint32_t xres;                  /* visible resolution */
    1.58 ++	uint32_t yres;
    1.59 ++	uint32_t xres_virtual;          /* virtual resolution */
    1.60 ++	uint32_t yres_virtual;
    1.61 ++	uint32_t xoffset;               /* offset from virtual to visible */
    1.62 ++	uint32_t yoffset;               /* resolution */
    1.63 ++
    1.64 ++	uint32_t bits_per_pixel;
    1.65 ++	uint32_t grayscale;             /* !=0 Graylevels instead of colors */
    1.66 ++
    1.67 ++	struct fb_bitfield red;         /* bitfield in fb mem if true color, */
    1.68 ++	struct fb_bitfield green;       /* else only length is significant */
    1.69 ++	struct fb_bitfield blue;
    1.70 ++	struct fb_bitfield transp;      /* transparency */
    1.71 ++
    1.72 ++	uint32_t nonstd;                /* !=0 Non standard pixel format */
    1.73 ++
    1.74 ++	uint32_t activate;              /* see FB_ACTIVATE_x */
    1.75 ++
    1.76 ++	uint32_t height;                /* height of picture in mm */
    1.77 ++	uint32_t width;                 /* width of picture in mm */
    1.78 ++
    1.79 ++	uint32_t accel_flags;           /* acceleration flags (hints) */
    1.80 ++
    1.81 ++	/* Timing: All values in pixclocks, except pixclock (of course) */
    1.82 ++	uint32_t pixclock;              /* pixel clock in ps (pico seconds) */
    1.83 ++	uint32_t left_margin;           /* time from sync to picture */
    1.84 ++	uint32_t right_margin;          /* time from picture to sync */
    1.85 ++	uint32_t upper_margin;          /* time from sync to picture */
    1.86 ++	uint32_t lower_margin;
    1.87 ++	uint32_t hsync_len;             /* length of horizontal sync */
    1.88 ++	uint32_t vsync_len;             /* length of vertical sync */
    1.89 ++	uint32_t sync;                  /* see FB_SYNC_x */
    1.90 ++	uint32_t vmode;                 /* see FB_VMODE_x */
    1.91 ++	uint32_t reserved[6];           /* Reserved for future compatibility */
    1.92 ++};
    1.93 ++
    1.94 ++#define DEFAULTFBDEV  FB_0
    1.95 ++
    1.96 ++struct fb_fix_screeninfo {
    1.97 ++	char id[16];			/* identification string eg "TT Builtin" */
    1.98 ++	unsigned long smem_start;	/* Start of frame buffer mem */
    1.99 ++					/* (physical address) */
   1.100 ++	uint32_t smem_len;		/* Length of frame buffer mem */
   1.101 ++	uint32_t type;			/* see FB_TYPE_*		*/
   1.102 ++	uint32_t type_aux;		/* Interleave for interleaved Planes */
   1.103 ++	uint32_t visual;		/* see FB_VISUAL_*		*/ 
   1.104 ++	uint16_t xpanstep;		/* zero if no hardware panning  */
   1.105 ++	uint16_t ypanstep;		/* zero if no hardware panning  */
   1.106 ++	uint16_t ywrapstep;		/* zero if no hardware ywrap    */
   1.107 ++	uint32_t line_length;		/* length of a line in bytes    */
   1.108 ++	unsigned long mmio_start;	/* Start of Memory Mapped I/O   */
   1.109 ++					/* (physical address) */
   1.110 ++	uint32_t mmio_len;		/* Length of Memory Mapped I/O  */
   1.111 ++	uint32_t accel;			/* Indicate to driver which	*/
   1.112 ++					/*  specific chip/card we have	*/
   1.113 ++	uint16_t reserved[3];		/* Reserved for future compatibility */
   1.114 ++};
   1.115 ++
   1.116 ++struct fb_cmap {
   1.117 ++	uint32_t start;			/* First entry	*/
   1.118 ++	uint32_t len;			/* Number of entries */
   1.119 ++	uint16_t *red;			/* Red values	*/
   1.120 ++	uint16_t *green;
   1.121 ++	uint16_t *blue;
   1.122 ++	uint16_t *transp;			/* transparency, can be NULL */
   1.123 ++};
   1.124 ++
   1.125 ++#define FB_VISUAL_TRUECOLOR		2	/* True color	*/
   1.126 ++
   1.127 ++#define COLORLEVELS   (1 << 8)
   1.128 ++
   1.129 ++struct scroll_data {
   1.130 ++	int size;
   1.131 ++	int srv_size;
   1.132 ++	int offset;
   1.133 ++	int pos;
   1.134 ++};
   1.135 ++
   1.136 ++struct globals {
   1.137 ++	struct termios term_orig;
   1.138 ++	struct pollfd ufds[3];
   1.139 ++#define kbd_fd		ufds[0].fd
   1.140 ++#define vnc_fd		ufds[1].fd
   1.141 ++#define rat_fd		ufds[2].fd
   1.142 ++	struct scroll_data scroll[2];
   1.143 ++#define cols		scroll[0].size
   1.144 ++#define srv_cols	scroll[0].srv_size
   1.145 ++#define oc		scroll[0].offset
   1.146 ++#define mc		scroll[0].pos
   1.147 ++#define rows		scroll[1].size
   1.148 ++#define srv_rows	scroll[1].srv_size
   1.149 ++#define or		scroll[1].offset
   1.150 ++#define mr		scroll[1].pos
   1.151 ++	int fb_fd;
   1.152 ++	void *fb_ptr;
   1.153 ++	int bpp;
   1.154 ++	int nr, ng, nb;
   1.155 ++	struct fb_var_screeninfo vinfo;
   1.156 ++	struct fb_fix_screeninfo finfo;
   1.157 ++	unsigned short red[COLORLEVELS], green[COLORLEVELS], blue[COLORLEVELS];
   1.158 ++};
   1.159 ++
   1.160 ++#define G (*ptr_to_globals)
   1.161 ++#define INIT_G() do { \
   1.162 ++	SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
   1.163 ++} while (0)
   1.164 ++
   1.165 ++static int fb_len(void)
   1.166 ++{
   1.167 ++	return G.finfo.line_length * G.vinfo.yres_virtual;
   1.168 ++}
   1.169 ++
   1.170 ++static void fb_ioctl_cmap(int fct, struct fb_cmap *cmap)
   1.171 ++{
   1.172 ++	if (G.finfo.visual == FB_VISUAL_TRUECOLOR)
   1.173 ++		return;
   1.174 ++	cmap->start = 0;
   1.175 ++	cmap->len = MAX(G.nr, MAX(G.ng, G.nb));
   1.176 ++	cmap->transp = NULL;
   1.177 ++	xioctl(G.fb_fd, fct, cmap);
   1.178 ++}
   1.179 ++
   1.180 ++static void fb_cmap_save(int save)
   1.181 ++{
   1.182 ++	struct fb_cmap cmap;
   1.183 ++	
   1.184 ++	cmap.red = G.red;
   1.185 ++	cmap.green = G.green;
   1.186 ++	cmap.blue = G.blue;
   1.187 ++	fb_ioctl_cmap(save ? FBIOGETCMAP : FBIOPUTCMAP, &cmap);
   1.188 ++}
   1.189 ++
   1.190 ++static void fb_build_cmap(unsigned short *color, int n)
   1.191 ++{
   1.192 ++	int i, inc = 65535 / (n - 1);
   1.193 ++	
   1.194 ++	for (i = 0; n--; i += inc)
   1.195 ++		*color++ = i;
   1.196 ++}
   1.197 ++
   1.198 ++static void fb_cmap(void)
   1.199 ++{
   1.200 ++	unsigned short red[COLORLEVELS], green[COLORLEVELS], blue[COLORLEVELS];
   1.201 ++	struct fb_cmap cmap;
   1.202 ++
   1.203 ++	fb_build_cmap(cmap.red = red,     G.nr);
   1.204 ++	fb_build_cmap(cmap.green = green, G.ng);
   1.205 ++	fb_build_cmap(cmap.blue = blue,   G.nb);
   1.206 ++	fb_ioctl_cmap(FBIOPUTCMAP, &cmap);
   1.207 ++}
   1.208 ++
   1.209 ++static void fb_init(void)
   1.210 ++{
   1.211 ++	G.fb_fd = xopen(DEFAULTFBDEV, O_RDWR);
   1.212 ++	xioctl(G.fb_fd, FBIOGET_VSCREENINFO, &G.vinfo);
   1.213 ++	xioctl(G.fb_fd, FBIOGET_FSCREENINFO, &G.finfo);
   1.214 ++	close_on_exec_on(G.fb_fd);
   1.215 ++	G.fb_ptr = mmap(NULL, fb_len(), PROT_READ | PROT_WRITE, MAP_SHARED, G.fb_fd, 0);
   1.216 ++	if (G.fb_ptr == MAP_FAILED)
   1.217 ++		bb_perror_msg_and_die("mmap");
   1.218 ++	G.bpp = (G.vinfo.bits_per_pixel + 7) >> 3;
   1.219 ++	G.nr = 1 << G.vinfo.red.length;
   1.220 ++	G.nb = 1 << G.vinfo.blue.length;
   1.221 ++	G.ng = 1 << G.vinfo.green.length;
   1.222 ++	fb_cmap_save(1);
   1.223 ++	fb_cmap();
   1.224 ++}
   1.225 ++
   1.226 ++static void fb_free(void)
   1.227 ++{
   1.228 ++	fb_cmap_save(0);
   1.229 ++	munmap(G.fb_ptr, fb_len());
   1.230 ++	close(G.fb_fd);
   1.231 ++}
   1.232 ++
   1.233 ++#define fb_rows vinfo.yres
   1.234 ++#define fb_cols vinfo.xres
   1.235 ++
   1.236 ++static void fb_set(int r, int c, void *mem, int len)
   1.237 ++{
   1.238 ++	memcpy(G.fb_ptr + (r + G.vinfo.yoffset) * G.finfo.line_length + 
   1.239 ++		(c + G.vinfo.xoffset) * G.bpp, mem, len * G.bpp);
   1.240 ++}
   1.241 ++
   1.242 ++#define line_buffer	bb_common_bufsiz1
   1.243 ++#define MAXPIX		(sizeof(line_buffer)/sizeof(uint32_t))
   1.244 ++
   1.245 ++static void skip(int len)
   1.246 ++{
   1.247 ++	int n;
   1.248 ++	while (len > 0 && (n = read(G.vnc_fd, line_buffer, 
   1.249 ++				    MIN(len, sizeof(line_buffer)))) > 0)
   1.250 ++		len -= n;
   1.251 ++}
   1.252 ++
   1.253 ++static void vnc_init(void)
   1.254 ++{
   1.255 ++	struct vnc_client_init clientinit;
   1.256 ++	struct vnc_server_init serverinit;
   1.257 ++	struct vnc_client_pixelfmt pixfmt_cmd;
   1.258 ++	int connstat = VNC_CONN_FAILED;
   1.259 ++
   1.260 ++	write(G.vnc_fd, "RFB 003.003\n", 12);
   1.261 ++	skip(12);
   1.262 ++
   1.263 ++	xread(G.vnc_fd, &connstat, sizeof(connstat));
   1.264 ++
   1.265 ++	if (ntohl(connstat) != VNC_CONN_NOAUTH)
   1.266 ++		bb_perror_msg_and_die("vnc auth");
   1.267 ++
   1.268 ++	clientinit.shared = 1;
   1.269 ++	write(G.vnc_fd, &clientinit, sizeof(clientinit));
   1.270 ++	read(G.vnc_fd, &serverinit, sizeof(serverinit));
   1.271 ++
   1.272 ++	fb_init();
   1.273 ++	G.srv_cols = ntohs(serverinit.w);
   1.274 ++	G.srv_rows = ntohs(serverinit.h);
   1.275 ++	G.cols = MIN(G.srv_cols, G.fb_cols);
   1.276 ++	G.rows = MIN(G.srv_rows, G.fb_rows);
   1.277 ++	G.mr = G.rows / 2;
   1.278 ++	G.mc = G.cols / 2;
   1.279 ++
   1.280 ++	skip(ntohl(serverinit.len));
   1.281 ++	pixfmt_cmd.type = VNC_CLIENT_PIXFMT;
   1.282 ++	pixfmt_cmd.format.bigendian = 0;
   1.283 ++	pixfmt_cmd.format.truecolor = 1;
   1.284 ++	pixfmt_cmd.format.bpp =
   1.285 ++	pixfmt_cmd.format.depth = G.bpp << 3;
   1.286 ++	pixfmt_cmd.format.rmax = htons(G.nr - 1);
   1.287 ++	pixfmt_cmd.format.gmax = htons(G.ng - 1);
   1.288 ++	pixfmt_cmd.format.bmax = htons(G.nb - 1);
   1.289 ++	pixfmt_cmd.format.rshl = G.vinfo.red.offset;
   1.290 ++	pixfmt_cmd.format.gshl = G.vinfo.green.offset;
   1.291 ++	pixfmt_cmd.format.bshl = G.vinfo.blue.offset;
   1.292 ++	write(G.vnc_fd, &pixfmt_cmd, sizeof(pixfmt_cmd));
   1.293 ++}
   1.294 ++
   1.295 ++static void vnc_refresh(int inc)
   1.296 ++{
   1.297 ++	struct vnc_client_fbup fbup_req;
   1.298 ++	fbup_req.type = VNC_CLIENT_FBUP;
   1.299 ++	fbup_req.inc = inc;
   1.300 ++	fbup_req.x = htons(G.oc);
   1.301 ++	fbup_req.y = htons(G.or);
   1.302 ++	fbup_req.w = htons(G.oc + G.cols);
   1.303 ++	fbup_req.h = htons(G.or + G.rows);
   1.304 ++	write(G.vnc_fd, &fbup_req, sizeof(fbup_req));
   1.305 ++}
   1.306 ++
   1.307 ++static void cleanup(void)
   1.308 ++{
   1.309 ++	const char *reset = "\x1b[?25h" "\x1b[2J\x1b[H";
   1.310 ++	fb_free();
   1.311 ++	tcsetattr_stdin_TCSANOW(&G.term_orig);
   1.312 ++	write(STDOUT_FILENO, reset, strlen(reset));
   1.313 ++	if (ENABLE_FEATURE_CLEAN_UP) {
   1.314 ++		close(G.vnc_fd);
   1.315 ++		close(G.rat_fd);
   1.316 ++	}
   1.317 ++}
   1.318 ++
   1.319 ++static void killed(int code) NORETURN;
   1.320 ++static void killed(int code)
   1.321 ++{
   1.322 ++	cleanup();
   1.323 ++	if (code > EXIT_FAILURE)
   1.324 ++		kill_myself_with_sig(code);
   1.325 ++	exit(code);
   1.326 ++}
   1.327 ++
   1.328 ++static void vnc_event(void)
   1.329 ++{
   1.330 ++	struct vnc_rect uprect;
   1.331 ++	union {
   1.332 ++		struct vnc_server_fbup fbup;
   1.333 ++		struct vnc_server_cuttext cuttext;
   1.334 ++		struct vnc_server_colormap colormap;
   1.335 ++	} msg;
   1.336 ++	int n;
   1.337 ++
   1.338 ++	switch (xread_char(G.vnc_fd)) {
   1.339 ++	case VNC_SERVER_FBUP:
   1.340 ++		xread(G.vnc_fd, &msg.fbup.pad, sizeof(msg.fbup) - 1);
   1.341 ++		n = ntohs(msg.fbup.n);
   1.342 ++		while (n--) {
   1.343 ++			int x, y, w, h, l, i;
   1.344 ++			xread(G.vnc_fd, &uprect, sizeof(uprect));
   1.345 ++			if (uprect.enc != 0)
   1.346 ++				killed(1);
   1.347 ++			i = 0;
   1.348 ++			x = ntohs(uprect.x) - G.oc;
   1.349 ++			y = ntohs(uprect.y) - G.or;
   1.350 ++			w = ntohs(uprect.w);
   1.351 ++			h = ntohs(uprect.h);
   1.352 ++			l = MIN(w, G.cols - x);
   1.353 ++			if (x < 0) {
   1.354 ++				l = MIN(w + x, G.cols);
   1.355 ++				i = -x;
   1.356 ++				x = 0;
   1.357 ++			}
   1.358 ++			for (; h--; y++) {
   1.359 ++				int a, b, c = i;
   1.360 ++				for (a = b = 0; w > b; b += a, c = 0) {
   1.361 ++					int len;
   1.362 ++					a = MIN(w - b, MAXPIX);
   1.363 ++					len = MIN(a, l - b) - c;
   1.364 ++					xread(G.vnc_fd, line_buffer, a * G.bpp);
   1.365 ++					if (y >= 0 && y < G.rows && len > 0)
   1.366 ++						fb_set(y, x + b, 
   1.367 ++						       line_buffer + (c * G.bpp),
   1.368 ++						       len);
   1.369 ++				}
   1.370 ++			}
   1.371 ++		}
   1.372 ++		break;
   1.373 ++	case VNC_SERVER_BELL:
   1.374 ++		break;
   1.375 ++	case VNC_SERVER_CUTTEXT:
   1.376 ++		xread(G.vnc_fd, &msg.cuttext.pad1, sizeof(msg.cuttext) - 1);
   1.377 ++		skip(ntohl(msg.cuttext.len));
   1.378 ++		break;
   1.379 ++	case VNC_SERVER_COLORMAP:
   1.380 ++		xread(G.vnc_fd, &msg.colormap.pad, sizeof(msg.colormap) - 1);
   1.381 ++		skip(ntohs(msg.colormap.n) * 3 * 2);
   1.382 ++		break;
   1.383 ++	default:
   1.384 ++		killed(1);
   1.385 ++	}
   1.386 ++}
   1.387 ++
   1.388 ++static int update_scroll(struct scroll_data *s)
   1.389 ++{
   1.390 ++	int shift = s->size / 5;
   1.391 ++	int max = s->srv_size - s->size;
   1.392 ++	int status = 0;
   1.393 ++	if (s->pos < s->offset) {
   1.394 ++		if ((s->offset -= shift) < 0)
   1.395 ++			s->offset = 0;
   1.396 ++	}
   1.397 ++	else if (s->pos >= s->offset + s->size && s->offset < max) {
   1.398 ++		if ((s->offset += shift) > max)
   1.399 ++			s->offset = max;
   1.400 ++	}
   1.401 ++	else status++;
   1.402 ++	s->pos = MAX(s->offset, MIN(s->offset + s->size - 1, s->pos));
   1.403 ++	return status;
   1.404 ++}
   1.405 ++
   1.406 ++static void rat_event(void)
   1.407 ++{
   1.408 ++	signed char ie[3];
   1.409 ++	struct vnc_client_ratevent me = {VNC_CLIENT_RATEVENT};
   1.410 ++	int mask = 0;
   1.411 ++	int refresh;
   1.412 ++
   1.413 ++	xread(G.rat_fd, &ie, sizeof(ie));
   1.414 ++	G.mc += ie[1];
   1.415 ++	G.mr -= ie[2];
   1.416 ++	refresh = 2 - update_scroll(&G.scroll[0]) - update_scroll(&G.scroll[1]);
   1.417 ++	if (ie[0] & 0x01)
   1.418 ++		mask |= VNC_BUTTON1_MASK;
   1.419 ++	if (ie[0] & 0x04)
   1.420 ++		mask |= VNC_BUTTON2_MASK;
   1.421 ++	if (ie[0] & 0x02)
   1.422 ++		mask |= VNC_BUTTON3_MASK;
   1.423 ++	me.y = htons(G.mr);
   1.424 ++	me.x = htons(G.mc);
   1.425 ++	me.mask = mask;
   1.426 ++	write(G.vnc_fd, &me, sizeof(me));
   1.427 ++	if (refresh)
   1.428 ++		vnc_refresh(0);
   1.429 ++}
   1.430 ++
   1.431 ++static int press(int key, int down)
   1.432 ++{
   1.433 ++	struct vnc_client_keyevent ke = {VNC_CLIENT_KEYEVENT};
   1.434 ++	ke.key = htonl(key);
   1.435 ++	ke.down = down;
   1.436 ++	return write(G.vnc_fd, &ke, sizeof(ke));
   1.437 ++}
   1.438 ++
   1.439 ++static void kbd_event(void)
   1.440 ++{
   1.441 ++	char key[1024];
   1.442 ++	int i, nr;
   1.443 ++
   1.444 ++	if ((nr = read(0, key, sizeof(key))) <= 0 )
   1.445 ++		killed(1);
   1.446 ++	for (i = 0; i < nr; i++) {
   1.447 ++		int k = -1;
   1.448 ++		int mod[4];
   1.449 ++		int nmod = 0;
   1.450 ++		switch (key[i]) {
   1.451 ++		case 0x08:
   1.452 ++		case 0x7f:
   1.453 ++			k = 0xff08;
   1.454 ++			break;
   1.455 ++		case 0x09:
   1.456 ++			k = 0xff09;
   1.457 ++			break;
   1.458 ++		case 0x1b:
   1.459 ++			if (G.oc + G.mc + G.or + G.mr == 0)
   1.460 ++				killed(0);
   1.461 ++			if (i + 2 < nr && key[i + 1] == '[') {
   1.462 ++				if (key[i + 2] == 'A')
   1.463 ++					k = 0xff52;
   1.464 ++				if (key[i + 2] == 'B')
   1.465 ++					k = 0xff54;
   1.466 ++				if (key[i + 2] == 'C')
   1.467 ++					k = 0xff53;
   1.468 ++				if (key[i + 2] == 'D')
   1.469 ++					k = 0xff51;
   1.470 ++				if (key[i + 2] == 'H')
   1.471 ++					k = 0xff50;
   1.472 ++				if (k > 0) {
   1.473 ++					i += 2;
   1.474 ++					break;
   1.475 ++				}
   1.476 ++			}
   1.477 ++			k = 0xff1b;
   1.478 ++			if (i + 1 < nr) {
   1.479 ++				mod[nmod++] = 0xffe9;
   1.480 ++				k = key[++i];
   1.481 ++			}
   1.482 ++			break;
   1.483 ++		case 0x0d:
   1.484 ++			k = 0xff0d;
   1.485 ++			break;
   1.486 ++		case 0x0c:	/* ^L: redraw */
   1.487 ++			vnc_refresh(0);
   1.488 ++		default:
   1.489 ++			k = (unsigned char) key[i];
   1.490 ++		}
   1.491 ++		if ((k >= 'A' && k <= 'Z') || strchr(":\"<>?{}|+_()*&^%$#@!~", k))
   1.492 ++			mod[nmod++] = 0xffe1;
   1.493 ++		if (k >= 1 && k <= 26) {
   1.494 ++			k += 'a' - 1;
   1.495 ++			mod[nmod++] = 0xffe3;
   1.496 ++		}
   1.497 ++		if (k > 0) {
   1.498 ++			int j;
   1.499 ++			mod[nmod] = k;
   1.500 ++			for (j = 0; j <= nmod; j++)
   1.501 ++				press(mod[j], 1);
   1.502 ++			press(k, 0);
   1.503 ++			for (j = 0; j < nmod; j++)
   1.504 ++				press(mod[j], 0);
   1.505 ++		}
   1.506 ++	}
   1.507 ++}
   1.508 ++
   1.509 ++static void term_setup(void)
   1.510 ++{
   1.511 ++	struct termios termios;
   1.512 ++	const char *init = "\x1b[?25l" "\x1b[2J\x1b[H" "** fbvnc **";
   1.513 ++
   1.514 ++	write(STDOUT_FILENO, init, strlen(init));
   1.515 ++	tcgetattr (STDIN_FILENO, &termios);
   1.516 ++	G.term_orig = termios;
   1.517 ++	cfmakeraw(&termios);
   1.518 ++	tcsetattr_stdin_TCSANOW(&termios);
   1.519 ++}
   1.520 ++
   1.521 ++int fbvnc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
   1.522 ++int fbvnc_main(int argc, char **argv)
   1.523 ++{
   1.524 ++	char *host = (char *) "127.0.0.1";
   1.525 ++	int port, pending = 0;
   1.526 ++	
   1.527 ++	INIT_G();
   1.528 ++	if (argc >= 2)
   1.529 ++		host = argv[1];
   1.530 ++	port = bb_lookup_port((argc >= 3) ?  argv[2] : "vnc", "tcp", 5900);
   1.531 ++	G.vnc_fd = create_and_connect_stream_or_die(host, port);
   1.532 ++	vnc_init();
   1.533 ++	G.rat_fd = open("/dev/input/mice", O_RDONLY);
   1.534 ++	term_setup();
   1.535 ++	atexit(cleanup);
   1.536 ++	bb_signals(BB_FATAL_SIGS, killed);
   1.537 ++
   1.538 ++	G.ufds[0].events =
   1.539 ++	G.ufds[1].events =
   1.540 ++	G.ufds[2].events = POLLIN;
   1.541 ++	vnc_refresh(0);
   1.542 ++	while (1) {
   1.543 ++		int status = poll(G.ufds, 3, 500);
   1.544 ++		if (status == -1 && errno != EINTR)
   1.545 ++			killed(1);
   1.546 ++		if (!status)
   1.547 ++			continue;
   1.548 ++		if (G.ufds[0].revents & POLLIN)
   1.549 ++			kbd_event();
   1.550 ++		if (G.ufds[1].revents & POLLIN) {
   1.551 ++			vnc_event();
   1.552 ++			pending = 0;
   1.553 ++		}
   1.554 ++		if (G.ufds[2].revents & POLLIN)
   1.555 ++			rat_event();
   1.556 ++		if (!pending++)
   1.557 ++			vnc_refresh(1);
   1.558 ++	}
   1.559 ++}
   1.560 +--- /dev/null
   1.561 ++++ busybox/util-linux/vnc.h
   1.562 +@@ -0,0 +1,122 @@
   1.563 ++#define VNC_CONN_FAILED		0
   1.564 ++#define VNC_CONN_NOAUTH		1
   1.565 ++#define VNC_CONN_AUTH		2
   1.566 ++
   1.567 ++#define VNC_AUTH_OK		0
   1.568 ++#define VNC_AUTH_FAILED		1
   1.569 ++#define VNC_AUTH_TOOMANY	2
   1.570 ++
   1.571 ++#define VNC_SERVER_FBUP		0
   1.572 ++#define VNC_SERVER_COLORMAP	1
   1.573 ++#define VNC_SERVER_BELL		2
   1.574 ++#define VNC_SERVER_CUTTEXT	3
   1.575 ++
   1.576 ++#define VNC_CLIENT_PIXFMT	0
   1.577 ++#define VNC_CLIENT_COLORMAP	1
   1.578 ++#define VNC_CLIENT_SETENC	2
   1.579 ++#define VNC_CLIENT_FBUP		3
   1.580 ++#define VNC_CLIENT_KEYEVENT	4
   1.581 ++#define VNC_CLIENT_RATEVENT	5
   1.582 ++#define VNC_CLIENT_CUTTEXT	6
   1.583 ++
   1.584 ++#define VNC_ENC_RAW		0
   1.585 ++#define VNC_ENC_COPYRECT	1
   1.586 ++#define VNC_ENC_RRE		2
   1.587 ++#define VNC_ENC_CORRE		4
   1.588 ++#define VNC_ENC_HEXTILE		5
   1.589 ++
   1.590 ++#define VNC_BUTTON1_MASK	0x1
   1.591 ++#define VNC_BUTTON2_MASK	0x2
   1.592 ++#define VNC_BUTTON3_MASK	0x4
   1.593 ++
   1.594 ++typedef unsigned char u8;
   1.595 ++typedef unsigned short u16;
   1.596 ++typedef unsigned int u32;
   1.597 ++
   1.598 ++struct vnc_pixelfmt {
   1.599 ++	u8 bpp;
   1.600 ++	u8 depth;
   1.601 ++	u8 bigendian;
   1.602 ++	u8 truecolor;
   1.603 ++	u16 rmax;
   1.604 ++	u16 gmax;
   1.605 ++	u16 bmax;
   1.606 ++	u8 rshl;
   1.607 ++	u8 gshl;
   1.608 ++	u8 bshl;
   1.609 ++
   1.610 ++	u8 pad1;
   1.611 ++	u16 pad2;
   1.612 ++};
   1.613 ++
   1.614 ++struct vnc_client_init {
   1.615 ++	u8 shared;
   1.616 ++};
   1.617 ++
   1.618 ++struct vnc_server_init {
   1.619 ++    u16 w;
   1.620 ++    u16 h;
   1.621 ++    struct vnc_pixelfmt fmt;
   1.622 ++    u32 len;
   1.623 ++    /* char name[len]; */
   1.624 ++};
   1.625 ++
   1.626 ++struct vnc_rect {
   1.627 ++	u16 x, y;
   1.628 ++	u16 w, h;
   1.629 ++	u32 enc;
   1.630 ++	/* rect bytes */
   1.631 ++};
   1.632 ++
   1.633 ++struct vnc_server_fbup {
   1.634 ++    u8 type;
   1.635 ++    u8 pad;
   1.636 ++    u16 n;
   1.637 ++    /* struct vnc_rect rects[n]; */
   1.638 ++};
   1.639 ++
   1.640 ++struct vnc_server_cuttext {
   1.641 ++	u8 type;
   1.642 ++	u8 pad1;
   1.643 ++	u16 pad2;
   1.644 ++	u32 len;
   1.645 ++	/* char text[length] */
   1.646 ++};
   1.647 ++
   1.648 ++struct vnc_server_colormap {
   1.649 ++	u8 type;
   1.650 ++	u8 pad;
   1.651 ++	u16 first;
   1.652 ++	u16 n;
   1.653 ++	/* u8 colors[n * 3 * 2]; */
   1.654 ++};
   1.655 ++
   1.656 ++struct vnc_client_pixelfmt {
   1.657 ++	u8 type;
   1.658 ++	u8 pad1;
   1.659 ++	u16 pad2;
   1.660 ++	struct vnc_pixelfmt format;
   1.661 ++};
   1.662 ++
   1.663 ++struct vnc_client_fbup {
   1.664 ++	u8 type;
   1.665 ++	u8 inc;
   1.666 ++	u16 x;
   1.667 ++	u16 y;
   1.668 ++	u16 w;
   1.669 ++	u16 h;
   1.670 ++};
   1.671 ++
   1.672 ++struct vnc_client_keyevent {
   1.673 ++	u8 type;
   1.674 ++	u8 down;
   1.675 ++	u16 pad;
   1.676 ++	u32 key;
   1.677 ++};
   1.678 ++
   1.679 ++struct vnc_client_ratevent {
   1.680 ++	u8 type;
   1.681 ++	u8 mask;
   1.682 ++	u16 x;
   1.683 ++	u16 y;
   1.684 ++};